## Automatically generated incremental diff ## From: linux-2.5.70-bk19 ## To: linux-2.5.71 ## Robot: $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $ diff -urN linux-2.5.70-bk19/Documentation/cpu-freq/user-guide.txt linux-2.5.71/Documentation/cpu-freq/user-guide.txt --- linux-2.5.70-bk19/Documentation/cpu-freq/user-guide.txt 2003-05-26 18:00:22.000000000 -0700 +++ linux-2.5.71/Documentation/cpu-freq/user-guide.txt 2003-06-14 13:53:22.000000000 -0700 @@ -53,9 +53,12 @@ AMD Elan - SC400, SC410 AMD mobile K6-2+ AMD mobile K6-3+ +AMD mobile Duron +AMD mobile Athlon Cyrix Media GXm Intel mobile PIII [*] and Intel mobile PIII-M on certain chipsets Intel Pentium 4, Intel Xeon +Intel Pentium M (Centrino) National Semiconductors Geode GX Transmeta Crusoe VIA Cyrix 3 / C3 @@ -117,7 +120,7 @@ The preferred interface is located in the sysfs filesystem. If you mounted it at /sys, the cpufreq interface is located in a subdirectory "cpufreq" within the cpu-device directory -(e.g. /sys/devices/sys/cpu0/cpufreq/ for the first CPU). +(e.g. /sys/class/cpu/cpu0/cpufreq/ for the first CPU). cpuinfo_min_freq : this file shows the minimum operating frequency the processor can run at(in kHz) diff -urN linux-2.5.70-bk19/Makefile linux-2.5.71/Makefile --- linux-2.5.70-bk19/Makefile 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/Makefile 2003-06-14 13:53:22.000000000 -0700 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 5 -SUBLEVEL = 70 -EXTRAVERSION = -bk19 +SUBLEVEL = 71 +EXTRAVERSION = # *DOCUMENTATION* # To see a list of typical targets execute "make help" @@ -90,25 +90,23 @@ KBUILD_BUILTIN := 1 # If we have only "make modules", don't compile built-in objects. +# When we're building modules with modversions, we need to consider +# the built-in objects during the descend as well, in order to +# make sure the checksums are uptodate before we record them. ifeq ($(MAKECMDGOALS),modules) - KBUILD_BUILTIN := + KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1) endif # If we have "make modules", compile modules # in addition to whatever we do anyway. - -ifneq ($(filter modules,$(MAKECMDGOALS)),) - KBUILD_MODULES := 1 -endif - # Just "make" or "make all" shall build modules as well -ifeq ($(MAKECMDGOALS),) +ifneq ($(filter all modules,$(MAKECMDGOALS)),) KBUILD_MODULES := 1 endif -ifneq ($(filter all,$(MAKECMDGOALS)),) +ifeq ($(MAKECMDGOALS),) KBUILD_MODULES := 1 endif @@ -310,18 +308,6 @@ CFLAGS += -fomit-frame-pointer endif -# When we're building modules with modversions, we need to consider -# the built-in objects during the descend as well, in order to -# make sure the checksums are uptodate before we record them. - -ifdef CONFIG_MODVERSIONS -ifeq ($(KBUILD_MODULES),1) -ifneq ($(KBUILD_BUILTIN),1) - KBUILD_BUILTIN := 1 -endif -endif -endif - # # INSTALL_PATH specifies where to place the updated kernel and system map # images. Uncomment if you want to place them anywhere other than root. @@ -380,7 +366,7 @@ endef define rule_vmlinux - $(rule_vmlinux__) + $(rule_vmlinux__); \ $(NM) $@ | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map endef @@ -446,9 +432,8 @@ @echo '*** Warning: Overriding SUBDIRS on the command line can cause' @echo '*** inconsistencies' endif - $(Q)mkdir -p $(MODVERDIR) endif - @echo ' Starting the build. KBUILD_BUILTIN=$(KBUILD_BUILTIN) KBUILD_MODULES=$(KBUILD_MODULES)' + $(if $(CONFIG_MODULES),$(Q)mkdir -p $(MODVERDIR)) # This can be used by arch/$ARCH/Makefile to preprocess # their vmlinux.lds.S file @@ -470,9 +455,7 @@ %.o: %.c scripts FORCE $(Q)$(MAKE) $(build)=$(@D) $@ %/: scripts prepare FORCE - $(Q)$(MAKE) $(build)=$(@D) -%.ko: scripts FORCE - $(Q)$(MAKE) $(build)=$(@D) $@ + $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) $(build)=$(@D) %.lst: %.c scripts FORCE $(Q)$(MAKE) $(build)=$(@D) $@ %.s: %.S scripts FORCE @@ -514,7 +497,7 @@ if expr length "$(KERNELRELEASE)" \> $(uts_len) >/dev/null ; then \ echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \ exit 1; \ - fi; + fi; \ (echo \#define UTS_RELEASE \"$(KERNELRELEASE)\"; \ echo \#define LINUX_VERSION_CODE `expr $(VERSION) \\* 65536 + $(PATCHLEVEL) \\* 256 + $(SUBLEVEL)`; \ echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))'; \ @@ -825,6 +808,7 @@ @echo '* vmlinux - Build the bare kernel' @echo '* modules - Build all modules' @echo ' modules_install - Install all modules' + @echo ' dir/ - Build all files in dir and below' @echo ' dir/file.[ois] - Build specified target only' @echo ' rpm - Build a kernel as an RPM package' @echo ' tags/TAGS - Generate tags file for editors' diff -urN linux-2.5.70-bk19/arch/i386/kernel/Makefile linux-2.5.71/arch/i386/kernel/Makefile --- linux-2.5.70-bk19/arch/i386/kernel/Makefile 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/i386/kernel/Makefile 2003-06-14 13:53:22.000000000 -0700 @@ -38,14 +38,22 @@ # vsyscall.o contains the vsyscall DSO images as __initdata. # We must build both images before we can assemble it. +# Note: kbuild does not track this dependency due to usage of .incbin $(obj)/vsyscall.o: $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so -extra-y += $(foreach F,int80 sysenter,vsyscall-$F.o vsyscall-$F.so) +targets += $(foreach F,int80 sysenter,vsyscall-$F.o vsyscall-$F.so) # The DSO images are built using a special linker script. +quiet_cmd_syscall = SYSCALL $@ + cmd_syscall = $(CC) -nostdlib $(SYSCFLAGS_$(@F)) \ + -Wl,-T,$(filter-out FORCE,$^) -o $@ + +vsyscall-flags = -shared -s -Wl,-soname=linux-vsyscall.so.1 +SYSCFLAGS_vsyscall-sysenter.so = $(vsyscall-flags) +SYSCFLAGS_vsyscall-int80.so = $(vsyscall-flags) + $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so: \ -$(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o - $(CC) -nostdlib -shared -s -Wl,-soname=linux-vsyscall.so.1 \ - -o $@ -Wl,-T,$^ +$(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE + $(call if_changed,syscall) # We also create a special relocatable object that should mirror the symbol # table and layout of the linked DSO. With ld -R we can then refer to @@ -53,5 +61,7 @@ extra-y += vsyscall-syms.o $(obj)/built-in.o: $(obj)/vsyscall-syms.o $(obj)/built-in.o: ld_flags += -R $(obj)/vsyscall-syms.o -$(obj)/vsyscall-syms.o: $(src)/vsyscall.lds $(obj)/vsyscall-sysenter.o - $(CC) -nostdlib -r -o $@ -Wl,-T,$^ + +SYSCFLAGS_vsyscall-syms.o = -r +$(obj)/vsyscall-syms.o: $(src)/vsyscall.lds $(obj)/vsyscall-sysenter.o FORCE + $(call if_changed,syscall) diff -urN linux-2.5.70-bk19/arch/i386/kernel/cpu/cpufreq/Kconfig linux-2.5.71/arch/i386/kernel/cpu/cpufreq/Kconfig --- linux-2.5.70-bk19/arch/i386/kernel/cpu/cpufreq/Kconfig 2003-05-26 18:00:25.000000000 -0700 +++ linux-2.5.71/arch/i386/kernel/cpu/cpufreq/Kconfig 2003-06-14 13:53:22.000000000 -0700 @@ -11,7 +11,7 @@ fly. This is a nice method to save battery power on notebooks, because the lower the clock speed, the less power the CPU consumes. - For more information, take a look at linux/Documentation/cpufreq or + For more information, take a look at linux/Documentation/cpu-freq or at If in doubt, say N. @@ -38,7 +38,7 @@ This driver adds a CPUFreq driver which utilizes the ACPI Processor Performance States. - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. @@ -63,7 +63,7 @@ parameter: elanfreq=maxspeed (in kHz) or as module parameter "max_freq". - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. @@ -74,7 +74,7 @@ This adds the CPUFreq driver for mobile AMD K6-2+ and mobile AMD K6-3+ processors. - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. @@ -84,7 +84,7 @@ help This adds the CPUFreq driver for mobile AMD K7 mobile processors. - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. @@ -95,22 +95,34 @@ This add the CPUFreq driver for NatSemi Geode processors which support suspend modulation. - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. -config X86_SPEEDSTEP +config X86_SPEEDSTEP_ICH tristate "Intel Speedstep" depends on CPU_FREQ_TABLE help This adds the CPUFreq driver for certain mobile Intel Pentium III - (Coppermine), all mobile Intel Pentium III-M (Tulatin) and all - mobile Intel Pentium 4 P4-Ms. + (Coppermine), all mobile Intel Pentium III-M (Tualatin) and all + mobile Intel Pentium 4 P4-Ms, with an Intel ICH2, ICH3, + or ICH4 southbridge. - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. +config X86_SPEEDSTEP_CENTRINO + tristate "Intel Enhanced SpeedStep" + depends on CPU_FREQ_TABLE + help + This adds the CPUFreq driver for Enhanced SpeedStep enabled + mobile CPUs. This means Intel Pentium M (Centrino) CPUs. + + For details, take a look at linux/Documentation/cpu-freq. + + If in doubt, say N. + config X86_P4_CLOCKMOD tristate "Intel Pentium 4 clock modulation" depends on CPU_FREQ_TABLE @@ -118,7 +130,7 @@ This adds the CPUFreq driver for Intel Pentium 4 / XEON processors. - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. @@ -129,7 +141,7 @@ This adds the CPUFreq driver for Transmeta Crusoe processors which support LongRun. - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. @@ -141,7 +153,7 @@ VIA Cyrix Samuel/C3, VIA Cyrix Ezra and VIA Cyrix Ezra-T processors. - For details, take a look at linux/Documentation/cpufreq. + For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. diff -urN linux-2.5.70-bk19/arch/i386/kernel/cpu/cpufreq/Makefile linux-2.5.71/arch/i386/kernel/cpu/cpufreq/Makefile --- linux-2.5.70-bk19/arch/i386/kernel/cpu/cpufreq/Makefile 2003-05-26 18:00:39.000000000 -0700 +++ linux-2.5.71/arch/i386/kernel/cpu/cpufreq/Makefile 2003-06-14 13:53:22.000000000 -0700 @@ -1,12 +1,13 @@ obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o obj-$(CONFIG_X86_LONGHAUL) += longhaul.o -obj-$(CONFIG_X86_SPEEDSTEP) += speedstep.o obj-$(CONFIG_X86_P4_CLOCKMOD) += p4-clockmod.o obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o obj-$(CONFIG_X86_LONGRUN) += longrun.o obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi.o +obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o +obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o ifdef CONFIG_X86_ACPI_CPUFREQ ifdef CONFIG_ACPI_DEBUG diff -urN linux-2.5.70-bk19/arch/i386/kernel/cpu/cpufreq/powernow-k7.c linux-2.5.71/arch/i386/kernel/cpu/cpufreq/powernow-k7.c --- linux-2.5.70-bk19/arch/i386/kernel/cpu/cpufreq/powernow-k7.c 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/i386/kernel/cpu/cpufreq/powernow-k7.c 2003-06-14 13:53:22.000000000 -0700 @@ -10,7 +10,6 @@ * * Errata 5: Processor may fail to execute a FID/VID change in presence of interrupt. * - We cli/sti on stepping A0 CPUs around the FID/VID transition. - * (ADDENDUM: This seems to be needed on more systems, so we do it unconditionally now). * Errata 15: Processors with half frequency multipliers may hang upon wakeup from disconnect. * - We disable half multipliers if ACPI is used on A0 stepping CPUs. */ @@ -260,7 +259,8 @@ /* Now do the magic poking into the MSRs. */ - __asm__("\tcli\n"); + if (have_a0 == 1) /* A0 errata 5 */ + __asm__("\tcli\n"); if (freqs.old > freqs.new) { /* Going down, so change FID first */ @@ -272,7 +272,9 @@ change_FID(vid); } - __asm__("\tsti\n"); + + if (have_a0 == 1) + __asm__("\tsti\n"); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); } diff -urN linux-2.5.70-bk19/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c linux-2.5.71/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c --- linux-2.5.70-bk19/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c 2003-06-14 13:53:22.000000000 -0700 @@ -0,0 +1,377 @@ +/* + * cpufreq driver for Enhanced SpeedStep, as found in Intel's Pentium + * M (part of the Centrino chipset). + * + * Despite the "SpeedStep" in the name, this is almost entirely unlike + * traditional SpeedStep. + * + * Modelled on speedstep.c + * + * Copyright (C) 2003 Jeremy Fitzhardinge + * + * WARNING WARNING WARNING + * + * This driver manipulates the PERF_CTL MSR, which is only somewhat + * documented. While it seems to work on my laptop, it has not been + * tested anywhere else, and it may not work for you, do strange + * things or simply crash. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#define PFX "speedstep-centrino: " +#define MAINTAINER "Jeremy Fitzhardinge " + +#define CENTRINO_DEBUG + +#ifdef CENTRINO_DEBUG +#define dprintk(msg...) printk(msg) +#else +#define dprintk(msg...) do { } while(0) +#endif + +struct cpu_model +{ + const char *model_name; + unsigned max_freq; /* max clock in kHz */ + + struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */ +}; + +/* Operating points for current CPU */ +static const struct cpu_model *centrino_model; + +/* Computes the correct form for IA32_PERF_CTL MSR for a particular + frequency/voltage operating point; frequency in MHz, volts in mV. + This is stored as "index" in the structure. */ +#define OP(mhz, mv) \ + { \ + .frequency = (mhz) * 1000, \ + .index = (((mhz)/100) << 8) | ((mv - 700) / 16) \ + } + +/* + * These voltage tables were derived from the Intel Pentium M + * datasheet, document 25261202.pdf, Table 5. I have verified they + * are consistent with my IBM ThinkPad X31, which has a 1.3GHz Pentium + * M. + */ + +/* Ultra Low Voltage Intel Pentium M processor 900MHz */ +static struct cpufreq_frequency_table op_900[] = +{ + OP(600, 844), + OP(800, 988), + OP(900, 1004), + { .frequency = CPUFREQ_TABLE_END } +}; + +/* Low Voltage Intel Pentium M processor 1.10GHz */ +static struct cpufreq_frequency_table op_1100[] = +{ + OP( 600, 956), + OP( 800, 1020), + OP( 900, 1100), + OP(1000, 1164), + OP(1100, 1180), + { .frequency = CPUFREQ_TABLE_END } +}; + + +/* Low Voltage Intel Pentium M processor 1.20GHz */ +static struct cpufreq_frequency_table op_1200[] = +{ + OP( 600, 956), + OP( 800, 1004), + OP( 900, 1020), + OP(1000, 1100), + OP(1100, 1164), + OP(1200, 1180), + { .frequency = CPUFREQ_TABLE_END } +}; + +/* Intel Pentium M processor 1.30GHz */ +static struct cpufreq_frequency_table op_1300[] = +{ + OP( 600, 956), + OP( 800, 1260), + OP(1000, 1292), + OP(1200, 1356), + OP(1300, 1388), + { .frequency = CPUFREQ_TABLE_END } +}; + +/* Intel Pentium M processor 1.40GHz */ +static struct cpufreq_frequency_table op_1400[] = +{ + OP( 600, 956), + OP( 800, 1180), + OP(1000, 1308), + OP(1200, 1436), + OP(1400, 1484), + { .frequency = CPUFREQ_TABLE_END } +}; + +/* Intel Pentium M processor 1.50GHz */ +static struct cpufreq_frequency_table op_1500[] = +{ + OP( 600, 956), + OP( 800, 1116), + OP(1000, 1228), + OP(1200, 1356), + OP(1400, 1452), + OP(1500, 1484), + { .frequency = CPUFREQ_TABLE_END } +}; + +/* Intel Pentium M processor 1.60GHz */ +static struct cpufreq_frequency_table op_1600[] = +{ + OP( 600, 956), + OP( 800, 1036), + OP(1000, 1164), + OP(1200, 1276), + OP(1400, 1420), + OP(1600, 1484), + { .frequency = CPUFREQ_TABLE_END } +}; + +/* Intel Pentium M processor 1.70GHz */ +static struct cpufreq_frequency_table op_1700[] = +{ + OP( 600, 956), + OP( 800, 1004), + OP(1000, 1116), + OP(1200, 1228), + OP(1400, 1308), + OP(1700, 1484), + { .frequency = CPUFREQ_TABLE_END } +}; +#undef OP + +#define CPU(max) \ + { "Intel(R) Pentium(R) M processor " #max "MHz", (max)*1000, op_##max } + +/* CPU models, their operating frequency range, and freq/voltage + operating points */ +static const struct cpu_model models[] = +{ + CPU( 900), + CPU(1100), + CPU(1200), + CPU(1300), + CPU(1400), + CPU(1500), + CPU(1600), + CPU(1700), + { 0, } +}; +#undef CPU + +/* Extract clock in kHz from PERF_CTL value */ +static unsigned extract_clock(unsigned msr) +{ + msr = (msr >> 8) & 0xff; + return msr * 100000; +} + +/* Return the current CPU frequency in kHz */ +static unsigned get_cur_freq(void) +{ + unsigned l, h; + + rdmsr(MSR_IA32_PERF_STATUS, l, h); + return extract_clock(l); +} + +static int centrino_cpu_init(struct cpufreq_policy *policy) +{ + unsigned freq; + + if (policy->cpu != 0 || centrino_model == NULL) + return -ENODEV; + + freq = get_cur_freq(); + + policy->policy = (freq == centrino_model->max_freq) ? + CPUFREQ_POLICY_PERFORMANCE : + CPUFREQ_POLICY_POWERSAVE; + policy->cpuinfo.transition_latency = 10; /* 10uS transition latency */ + policy->cur = freq; + + dprintk(KERN_INFO PFX "centrino_cpu_init: policy=%d cur=%dkHz\n", + policy->policy, policy->cur); + + return cpufreq_frequency_table_cpuinfo(policy, centrino_model->op_points); +} + +/** + * centrino_verify - verifies a new CPUFreq policy + * @freq: new policy + * + * Limit must be within this model's frequency range at least one + * border included. + */ +static int centrino_verify (struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, centrino_model->op_points); +} + +/** + * centrino_setpolicy - set a new CPUFreq policy + * @policy: new policy + * + * Sets a new CPUFreq policy. + */ +static int centrino_target (struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned int newstate = 0; + unsigned int msr, oldmsr, h; + struct cpufreq_freqs freqs; + + if (centrino_model == NULL) + return -ENODEV; + + if (cpufreq_frequency_table_target(policy, centrino_model->op_points, target_freq, + relation, &newstate)) + return -EINVAL; + + msr = centrino_model->op_points[newstate].index; + rdmsr(MSR_IA32_PERF_CTL, oldmsr, h); + + if (msr == (oldmsr & 0xffff)) + return 0; + + /* Hm, old frequency can either be the last value we put in + PERF_CTL, or whatever it is now. The trouble is that TM2 + can change it behind our back, which means we never get to + see the speed change. Reading back the current speed would + tell us something happened, but it may leave the things on + the notifier chain confused; we therefore stick to using + the last programmed speed rather than the current speed for + "old". + + TODO: work out how the TCC interrupts work, and try to + catch the CPU changing things under us. + */ + freqs.cpu = 0; + freqs.old = extract_clock(oldmsr); + freqs.new = extract_clock(msr); + + dprintk(KERN_INFO PFX "target=%dkHz old=%d new=%d msr=%04x\n", + target_freq, freqs.old, freqs.new, msr); + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + /* all but 16 LSB are "reserved", so treat them with + care */ + oldmsr &= ~0xffff; + msr &= 0xffff; + oldmsr |= msr; + + wrmsr(MSR_IA32_PERF_CTL, oldmsr, h); + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return 0; +} + +static struct cpufreq_driver centrino_driver = { + .name = "centrino", /* should be speedstep-centrino, + but there's a 16 char limit */ + .init = centrino_cpu_init, + .verify = centrino_verify, + .target = centrino_target, + .owner = THIS_MODULE, +}; + + +/** + * centrino_init - initializes the Enhanced SpeedStep CPUFreq driver + * + * Initializes the Enhanced SpeedStep support. Returns -ENODEV on + * unsupported devices, -ENOENT if there's no voltage table for this + * particular CPU model, -EINVAL on problems during initiatization, + * and zero on success. + * + * This is quite picky. Not only does the CPU have to advertise the + * "est" flag in the cpuid capability flags, we look for a specific + * CPU model and stepping, and we need to have the exact model name in + * our voltage tables. That is, be paranoid about not releasing + * someone's valuable magic smoke. + */ +static int __init centrino_init(void) +{ + struct cpuinfo_x86 *cpu = cpu_data; + const struct cpu_model *model; + unsigned l, h; + + if (!cpu_has(cpu, X86_FEATURE_EST)) + return -ENODEV; + + /* Only Intel Pentium M stepping 5 for now - add new CPUs as + they appear after making sure they use PERF_CTL in the same + way. */ + if (cpu->x86_vendor != X86_VENDOR_INTEL || + cpu->x86 != 6 || + cpu->x86_model != 9 || + cpu->x86_mask != 5) { + printk(KERN_INFO PFX "found unsupported CPU with Enhanced SpeedStep: " + "send /proc/cpuinfo to " MAINTAINER "\n"); + return -ENODEV; + } + + /* Check to see if Enhanced SpeedStep is enabled, and try to + enable it if not. */ + rdmsr(MSR_IA32_MISC_ENABLE, l, h); + + if (!(l & (1<<16))) { + l |= (1<<16); + wrmsr(MSR_IA32_MISC_ENABLE, l, h); + + /* check to see if it stuck */ + rdmsr(MSR_IA32_MISC_ENABLE, l, h); + if (!(l & (1<<16))) { + printk(KERN_INFO PFX "couldn't enable Enhanced SpeedStep\n"); + return -ENODEV; + } + } + + for(model = models; model->model_name != NULL; model++) + if (strcmp(cpu->x86_model_id, model->model_name) == 0) + break; + if (model->model_name == NULL) { + printk(KERN_INFO PFX "no support for CPU model \"%s\": " + "send /proc/cpuinfo to " MAINTAINER "\n", + cpu->x86_model_id); + return -ENOENT; + } + + centrino_model = model; + + printk(KERN_INFO PFX "found \"%s\": max frequency: %dkHz\n", + model->model_name, model->max_freq); + + return cpufreq_register_driver(¢rino_driver); +} + +static void __exit centrino_exit(void) +{ + cpufreq_unregister_driver(¢rino_driver); +} + +MODULE_AUTHOR ("Jeremy Fitzhardinge "); +MODULE_DESCRIPTION ("Enhanced SpeedStep driver for Intel Pentium M processors."); +MODULE_LICENSE ("GPL"); + +module_init(centrino_init); +module_exit(centrino_exit); diff -urN linux-2.5.70-bk19/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c linux-2.5.71/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c --- linux-2.5.70-bk19/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c 2003-06-14 13:53:22.000000000 -0700 @@ -0,0 +1,737 @@ +/* + * $Id: speedstep.c,v 1.70 2003/02/22 10:23:46 db Exp $ + * + * (C) 2001 Dave Jones, Arjan van de ven. + * (C) 2002 - 2003 Dominik Brodowski + * + * Licensed under the terms of the GNU GPL License version 2. + * Based upon reverse engineered information, and on Intel documentation + * for chipsets ICH2-M and ICH3-M. + * + * Many thanks to Ducrot Bruno for finding and fixing the last + * "missing link" for ICH2-M/ICH3-M support, and to Thomas Winkler + * for extensive testing. + * + * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* + */ + + +/********************************************************************* + * SPEEDSTEP - DEFINITIONS * + *********************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include + +/* speedstep_chipset: + * It is necessary to know which chipset is used. As accesses to + * this device occur at various places in this module, we need a + * static struct pci_dev * pointing to that device. + */ +static unsigned int speedstep_chipset; +static struct pci_dev *speedstep_chipset_dev; + +#define SPEEDSTEP_CHIPSET_ICH2M 0x00000002 +#define SPEEDSTEP_CHIPSET_ICH3M 0x00000003 +#define SPEEDSTEP_CHIPSET_ICH4M 0x00000004 + +/* speedstep_processor + */ +static unsigned int speedstep_processor = 0; +static int speedstep_coppermine = 0; + +#define SPEEDSTEP_PROCESSOR_PIII_C 0x00000001 /* Coppermine core */ +#define SPEEDSTEP_PROCESSOR_PIII_T 0x00000002 /* Tualatin core */ +#define SPEEDSTEP_PROCESSOR_P4M 0x00000003 /* P4-M with 100 MHz FSB */ + + +/* speedstep_[low,high]_freq + * There are only two frequency states for each processor. Values + * are in kHz for the time being. + */ +#define SPEEDSTEP_HIGH 0x00000000 +#define SPEEDSTEP_LOW 0x00000001 + +static struct cpufreq_frequency_table speedstep_freqs[] = { + {SPEEDSTEP_HIGH, 0}, + {SPEEDSTEP_LOW, 0}, + {0, CPUFREQ_TABLE_END}, +}; + +#define speedstep_low_freq speedstep_freqs[SPEEDSTEP_LOW].frequency +#define speedstep_high_freq speedstep_freqs[SPEEDSTEP_HIGH].frequency + + +/* DEBUG + * Define it if you want verbose debug output, e.g. for bug reporting + */ +//#define SPEEDSTEP_DEBUG + +#ifdef SPEEDSTEP_DEBUG +#define dprintk(msg...) printk(msg) +#else +#define dprintk(msg...) do { } while(0) +#endif + + + +/********************************************************************* + * LOW LEVEL CHIPSET INTERFACE * + *********************************************************************/ + +/** + * speedstep_get_state - read the current SpeedStep state + * @state: Speedstep state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) + * + * Tries to read the SpeedStep state. Returns -EIO when there has been + * trouble to read the status or write to the control register, -EINVAL + * on an unsupported chipset, and zero on success. + */ +static int speedstep_get_state (unsigned int *state) +{ + unsigned long flags; + u32 pmbase; + u8 value; + + if (!speedstep_chipset_dev || !state) + return -EINVAL; + + switch (speedstep_chipset) { + case SPEEDSTEP_CHIPSET_ICH2M: + case SPEEDSTEP_CHIPSET_ICH3M: + case SPEEDSTEP_CHIPSET_ICH4M: + /* get PMBASE */ + pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); + if (!(pmbase & 0x01)) + return -EIO; + + pmbase &= 0xFFFFFFFE; + if (!pmbase) + return -EIO; + + /* read state */ + local_irq_save(flags); + value = inb(pmbase + 0x50); + local_irq_restore(flags); + + dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); + + *state = value & 0x01; + return 0; + + } + + printk (KERN_ERR "cpufreq: setting CPU frequency on this chipset unsupported.\n"); + return -EINVAL; +} + + +/** + * speedstep_set_state - set the SpeedStep state + * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) + * + * Tries to change the SpeedStep state. + */ +static void speedstep_set_state (unsigned int state, int notify) +{ + u32 pmbase; + u8 pm2_blk; + u8 value; + unsigned long flags; + unsigned int oldstate; + struct cpufreq_freqs freqs; + + if (!speedstep_chipset_dev || (state > 0x1)) + return; + + if (speedstep_get_state(&oldstate)) + return; + + if (oldstate == state) + return; + + freqs.old = (oldstate == SPEEDSTEP_HIGH) ? speedstep_high_freq : speedstep_low_freq; + freqs.new = (state == SPEEDSTEP_HIGH) ? speedstep_high_freq : speedstep_low_freq; + freqs.cpu = 0; /* speedstep.c is UP only driver */ + + if (notify) + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + switch (speedstep_chipset) { + case SPEEDSTEP_CHIPSET_ICH2M: + case SPEEDSTEP_CHIPSET_ICH3M: + case SPEEDSTEP_CHIPSET_ICH4M: + /* get PMBASE */ + pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); + if (!(pmbase & 0x01)) + { + printk(KERN_ERR "cpufreq: could not find speedstep register\n"); + return; + } + + pmbase &= 0xFFFFFFFE; + if (!pmbase) { + printk(KERN_ERR "cpufreq: could not find speedstep register\n"); + return; + } + + /* Disable IRQs */ + local_irq_save(flags); + + /* read state */ + value = inb(pmbase + 0x50); + + dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); + + /* write new state */ + value &= 0xFE; + value |= state; + + dprintk(KERN_DEBUG "cpufreq: writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase); + + /* Disable bus master arbitration */ + pm2_blk = inb(pmbase + 0x20); + pm2_blk |= 0x01; + outb(pm2_blk, (pmbase + 0x20)); + + /* Actual transition */ + outb(value, (pmbase + 0x50)); + + /* Restore bus master arbitration */ + pm2_blk &= 0xfe; + outb(pm2_blk, (pmbase + 0x20)); + + /* check if transition was successful */ + value = inb(pmbase + 0x50); + + /* Enable IRQs */ + local_irq_restore(flags); + + dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); + + if (state == (value & 0x1)) { + dprintk (KERN_INFO "cpufreq: change to %u MHz succeeded\n", (freqs.new / 1000)); + } else { + printk (KERN_ERR "cpufreq: change failed - I/O error\n"); + } + break; + default: + printk (KERN_ERR "cpufreq: setting CPU frequency on this chipset unsupported.\n"); + } + + if (notify) + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return; +} + + +/** + * speedstep_activate - activate SpeedStep control in the chipset + * + * Tries to activate the SpeedStep status and control registers. + * Returns -EINVAL on an unsupported chipset, and zero on success. + */ +static int speedstep_activate (void) +{ + if (!speedstep_chipset_dev) + return -EINVAL; + + switch (speedstep_chipset) { + case SPEEDSTEP_CHIPSET_ICH2M: + case SPEEDSTEP_CHIPSET_ICH3M: + case SPEEDSTEP_CHIPSET_ICH4M: + { + u16 value = 0; + + pci_read_config_word(speedstep_chipset_dev, + 0x00A0, &value); + if (!(value & 0x08)) { + value |= 0x08; + dprintk(KERN_DEBUG "cpufreq: activating SpeedStep (TM) registers\n"); + pci_write_config_word(speedstep_chipset_dev, + 0x00A0, value); + } + + return 0; + } + } + + printk (KERN_ERR "cpufreq: SpeedStep (TM) on this chipset unsupported.\n"); + return -EINVAL; +} + + +/** + * speedstep_detect_chipset - detect the Southbridge which contains SpeedStep logic + * + * Detects PIIX4, ICH2-M and ICH3-M so far. The pci_dev points to + * the LPC bridge / PM module which contains all power-management + * functions. Returns the SPEEDSTEP_CHIPSET_-number for the detected + * chipset, or zero on failure. + */ +static unsigned int speedstep_detect_chipset (void) +{ + speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801DB_12, + PCI_ANY_ID, + PCI_ANY_ID, + NULL); + if (speedstep_chipset_dev) + return SPEEDSTEP_CHIPSET_ICH4M; + + speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801CA_12, + PCI_ANY_ID, + PCI_ANY_ID, + NULL); + if (speedstep_chipset_dev) + return SPEEDSTEP_CHIPSET_ICH3M; + + + speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801BA_10, + PCI_ANY_ID, + PCI_ANY_ID, + NULL); + if (speedstep_chipset_dev) { + /* speedstep.c causes lockups on Dell Inspirons 8000 and + * 8100 which use a pretty old revision of the 82815 + * host brige. Abort on these systems. + */ + static struct pci_dev *hostbridge; + u8 rev = 0; + + hostbridge = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82815_MC, + PCI_ANY_ID, + PCI_ANY_ID, + NULL); + + if (!hostbridge) + return SPEEDSTEP_CHIPSET_ICH2M; + + pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev); + if (rev < 5) { + dprintk(KERN_INFO "cpufreq: hostbridge does not support speedstep\n"); + speedstep_chipset_dev = NULL; + return 0; + } + + return SPEEDSTEP_CHIPSET_ICH2M; + } + + return 0; +} + + + +/********************************************************************* + * LOW LEVEL PROCESSOR INTERFACE * + *********************************************************************/ + + +/** + * pentium3_get_frequency - get the core frequencies for PIIIs + * + * Returns the core frequency of a Pentium III processor (in kHz) + */ +static unsigned int pentium3_get_frequency (void) +{ + /* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */ + struct { + unsigned int ratio; /* Frequency Multiplier (x10) */ + u8 bitmap; /* power on configuration bits + [27, 25:22] (in MSR 0x2a) */ + } msr_decode_mult [] = { + { 30, 0x01 }, + { 35, 0x05 }, + { 40, 0x02 }, + { 45, 0x06 }, + { 50, 0x00 }, + { 55, 0x04 }, + { 60, 0x0b }, + { 65, 0x0f }, + { 70, 0x09 }, + { 75, 0x0d }, + { 80, 0x0a }, + { 85, 0x26 }, + { 90, 0x20 }, + { 100, 0x2b }, + { 0, 0xff } /* error or unknown value */ + }; + /* PIII(-M) FSB settings: see table b1-b of 24547206.pdf */ + struct { + unsigned int value; /* Front Side Bus speed in MHz */ + u8 bitmap; /* power on configuration bits [18: 19] + (in MSR 0x2a) */ + } msr_decode_fsb [] = { + { 66, 0x0 }, + { 100, 0x2 }, + { 133, 0x1 }, + { 0, 0xff} + }; + u32 msr_lo, msr_tmp; + int i = 0, j = 0; + struct cpuinfo_x86 *c = cpu_data; + + /* read MSR 0x2a - we only need the low 32 bits */ + rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp); + dprintk(KERN_DEBUG "cpufreq: P3 - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp); + msr_tmp = msr_lo; + + /* decode the FSB */ + msr_tmp &= 0x00c0000; + msr_tmp >>= 18; + while (msr_tmp != msr_decode_fsb[i].bitmap) { + if (msr_decode_fsb[i].bitmap == 0xff) + return -EINVAL; + i++; + } + + /* decode the multiplier */ + if ((c->x86_model == 0x08) && (c->x86_mask == 0x01)) + /* different on early Coppermine PIII */ + msr_lo &= 0x03c00000; + else + msr_lo &= 0x0bc00000; + msr_lo >>= 22; + while (msr_lo != msr_decode_mult[j].bitmap) { + if (msr_decode_mult[j].bitmap == 0xff) + return -EINVAL; + j++; + } + + return (msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100); +} + + +/** + * pentium4_get_frequency - get the core frequency for P4-Ms + * + * Should return the core frequency (in kHz) for P4-Ms. + */ +static unsigned int pentium4_get_frequency(void) +{ + u32 msr_lo, msr_hi; + + rdmsr(0x2c, msr_lo, msr_hi); + + dprintk(KERN_DEBUG "cpufreq: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); + + /* First 12 bits seem to change a lot (0x511, 0x410 and 0x30f seen + * yet). Next 12 bits always seem to be 0x300. If this is not true + * on this CPU, complain. Last 8 bits are frequency (in 100MHz). + */ + if (msr_hi || ((msr_lo & 0x00FFF000) != 0x300000)) { + printk(KERN_DEBUG "cpufreq: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); + printk(KERN_INFO "cpufreq: problem in initialization. Please contact Dominik Brodowski\n"); + printk(KERN_INFO "cpufreq: and attach this dmesg. Thanks in advance\n"); + return 0; + } + + msr_lo >>= 24; + return (msr_lo * 100000); +} + + +/** + * speedstep_detect_processor - detect Intel SpeedStep-capable processors. + * + * Returns the SPEEDSTEP_PROCESSOR_-number for the detected processor, + * or zero on failure. + */ +static unsigned int speedstep_detect_processor (void) +{ + struct cpuinfo_x86 *c = cpu_data; + u32 ebx; + + if ((c->x86_vendor != X86_VENDOR_INTEL) || + ((c->x86 != 6) && (c->x86 != 0xF))) + return 0; + + if (c->x86 == 0xF) { + /* Intel Pentium 4 Mobile P4-M */ + if (c->x86_model != 2) + return 0; + + if ((c->x86_mask != 4) && (c->x86_mask != 7)) + return 0; + + ebx = cpuid_ebx(0x00000001); + ebx &= 0x000000FF; + if ((ebx != 0x0e) && (ebx != 0x0f)) + return 0; + + return SPEEDSTEP_PROCESSOR_P4M; + } + + switch (c->x86_model) { + case 0x0B: /* Intel PIII [Tualatin] */ + /* cpuid_ebx(1) is 0x04 for desktop PIII, + 0x06 for mobile PIII-M */ + ebx = cpuid_ebx(0x00000001); + + ebx &= 0x000000FF; + if (ebx != 0x06) + return 0; + + /* So far all PIII-M processors support SpeedStep. See + * Intel's 24540633.pdf of August 2002 + */ + + return SPEEDSTEP_PROCESSOR_PIII_T; + + case 0x08: /* Intel PIII [Coppermine] */ + { + u32 msr_lo, msr_hi; + + /* all mobile PIII Coppermines have FSB 100 MHz + * ==> sort out a few desktop PIIIs. */ + rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_hi); + dprintk(KERN_DEBUG "cpufreq: Coppermine: MSR_IA32_EBL_Cr_POWERON is 0x%x, 0x%x\n", msr_lo, msr_hi); + msr_lo &= 0x00c0000; + if (msr_lo != 0x0080000) + return 0; + + if (speedstep_coppermine) + return SPEEDSTEP_PROCESSOR_PIII_C; + + /* + * If the processor is a mobile version, + * platform ID has bit 50 set + * it has SpeedStep technology if either + * bit 56 or 57 is set + */ + rdmsr(MSR_IA32_PLATFORM_ID, msr_lo, msr_hi); + dprintk(KERN_DEBUG "cpufreq: Coppermine: MSR_IA32_PLATFORM ID is 0x%x, 0x%x\n", msr_lo, msr_hi); + if ((msr_hi & (1<<18)) && (msr_hi & (3<<24))) + return SPEEDSTEP_PROCESSOR_PIII_C; + + printk(KERN_INFO "cpufreq: in case this is a SpeedStep-capable Intel Pentium III Coppermine\n"); + printk(KERN_INFO "cpufreq: processor, please pass the boot option or module parameter\n"); + printk(KERN_INFO "cpufreq: `speedstep_coppermine=1` to the kernel. Thanks!\n"); + return 0; + } + + default: + return 0; + } +} + + + +/********************************************************************* + * HIGH LEVEL FUNCTIONS * + *********************************************************************/ + +/** + * speedstep_detect_speeds - detects low and high CPU frequencies. + * + * Detects the low and high CPU frequencies in kHz. Returns 0 on + * success or -EINVAL / -EIO on problems. + */ +static int speedstep_detect_speeds (void) +{ + unsigned long flags; + unsigned int state; + int i, result; + + /* Disable irqs for entire detection process */ + local_irq_save(flags); + + for (i=0; i<2; i++) { + /* read the current state */ + result = speedstep_get_state(&state); + if (result) { + local_irq_restore(flags); + return result; + } + + /* save the correct value, and switch to other */ + if (state == SPEEDSTEP_LOW) { + switch (speedstep_processor) { + case SPEEDSTEP_PROCESSOR_PIII_C: + case SPEEDSTEP_PROCESSOR_PIII_T: + speedstep_low_freq = pentium3_get_frequency(); + break; + case SPEEDSTEP_PROCESSOR_P4M: + speedstep_low_freq = pentium4_get_frequency(); + } + speedstep_set_state(SPEEDSTEP_HIGH, 0); + } else { + switch (speedstep_processor) { + case SPEEDSTEP_PROCESSOR_PIII_C: + case SPEEDSTEP_PROCESSOR_PIII_T: + speedstep_high_freq = pentium3_get_frequency(); + break; + case SPEEDSTEP_PROCESSOR_P4M: + speedstep_high_freq = pentium4_get_frequency(); + } + speedstep_set_state(SPEEDSTEP_LOW, 0); + } + } + + local_irq_restore(flags); + + if (!speedstep_low_freq || !speedstep_high_freq || + (speedstep_low_freq == speedstep_high_freq)) + return -EIO; + + return 0; +} + + +/** + * speedstep_setpolicy - set a new CPUFreq policy + * @policy: new policy + * + * Sets a new CPUFreq policy. + */ +static int speedstep_target (struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned int newstate = 0; + + if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate)) + return -EINVAL; + + speedstep_set_state(newstate, 1); + + return 0; +} + + +/** + * speedstep_verify - verifies a new CPUFreq policy + * @freq: new policy + * + * Limit must be within speedstep_low_freq and speedstep_high_freq, with + * at least one border included. + */ +static int speedstep_verify (struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]); +} + + +static int speedstep_cpu_init(struct cpufreq_policy *policy) +{ + int result = 0; + unsigned int speed; + + /* capability check */ + if (policy->cpu != 0) + return -ENODEV; + + /* detect low and high frequency */ + result = speedstep_detect_speeds(); + if (result) + return result; + + /* get current speed setting */ + result = speedstep_get_state(&speed); + if (result) + return result; + + speed = (speed == SPEEDSTEP_LOW) ? speedstep_low_freq : speedstep_high_freq; + dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n", + (speed == speedstep_low_freq) ? "low" : "high", + (speed / 1000)); + + /* cpuinfo and default policy values */ + policy->policy = (speed == speedstep_low_freq) ? + CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cur = speed; + + return cpufreq_frequency_table_cpuinfo(policy, &speedstep_freqs[0]); +} + + +#ifndef MODULE +/** + * speedstep_setup speedstep command line parameter parsing + * + * speedstep command line parameter. Use: + * speedstep_coppermine=1 + * if the CPU in your notebook is a SpeedStep-capable Intel + * Pentium III Coppermine. These processors cannot be detected + * automatically, as Intel continues to consider the detection + * algorithm as proprietary material. + */ +static int __init speedstep_setup(char *str) +{ + speedstep_coppermine = simple_strtoul(str, &str, 0); + return 1; +} +__setup("speedstep_coppermine=", speedstep_setup); +#endif + + +static struct cpufreq_driver speedstep_driver = { + .name = "speedstep", + .verify = speedstep_verify, + .target = speedstep_target, + .init = speedstep_cpu_init, + .owner = THIS_MODULE, +}; + + +/** + * speedstep_init - initializes the SpeedStep CPUFreq driver + * + * Initializes the SpeedStep support. Returns -ENODEV on unsupported + * devices, -EINVAL on problems during initiatization, and zero on + * success. + */ +static int __init speedstep_init(void) +{ + /* detect chipset */ + speedstep_chipset = speedstep_detect_chipset(); + + /* detect chipset */ + if (speedstep_chipset) + speedstep_processor = speedstep_detect_processor(); + + if ((!speedstep_chipset) || (!speedstep_processor)) { + printk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this %s not (yet) available.\n", speedstep_chipset ? "processor" : "chipset"); + return -ENODEV; + } + + dprintk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) support $Revision: 1.70 $\n"); + + /* activate speedstep support */ + if (speedstep_activate()) + return -EINVAL; + + return cpufreq_register_driver(&speedstep_driver); +} + + +/** + * speedstep_exit - unregisters SpeedStep support + * + * Unregisters SpeedStep support. + */ +static void __exit speedstep_exit(void) +{ + cpufreq_unregister_driver(&speedstep_driver); +} + + +MODULE_PARM (speedstep_coppermine, "i"); + +MODULE_AUTHOR ("Dave Jones , Dominik Brodowski "); +MODULE_DESCRIPTION ("Speedstep driver for Intel mobile processors."); +MODULE_LICENSE ("GPL"); + +module_init(speedstep_init); +module_exit(speedstep_exit); diff -urN linux-2.5.70-bk19/arch/i386/kernel/cpu/cpufreq/speedstep.c linux-2.5.71/arch/i386/kernel/cpu/cpufreq/speedstep.c --- linux-2.5.70-bk19/arch/i386/kernel/cpu/cpufreq/speedstep.c 2003-05-26 18:00:20.000000000 -0700 +++ linux-2.5.71/arch/i386/kernel/cpu/cpufreq/speedstep.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,724 +0,0 @@ -/* - * $Id: speedstep.c,v 1.70 2003/02/22 10:23:46 db Exp $ - * - * (C) 2001 Dave Jones, Arjan van de ven. - * (C) 2002 - 2003 Dominik Brodowski - * - * Licensed under the terms of the GNU GPL License version 2. - * Based upon reverse engineered information, and on Intel documentation - * for chipsets ICH2-M and ICH3-M. - * - * Many thanks to Ducrot Bruno for finding and fixing the last - * "missing link" for ICH2-M/ICH3-M support, and to Thomas Winkler - * for extensive testing. - * - * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* - */ - - -/********************************************************************* - * SPEEDSTEP - DEFINITIONS * - *********************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include - -/* speedstep_chipset: - * It is necessary to know which chipset is used. As accesses to - * this device occur at various places in this module, we need a - * static struct pci_dev * pointing to that device. - */ -static unsigned int speedstep_chipset; -static struct pci_dev *speedstep_chipset_dev; - -#define SPEEDSTEP_CHIPSET_ICH2M 0x00000002 -#define SPEEDSTEP_CHIPSET_ICH3M 0x00000003 -#define SPEEDSTEP_CHIPSET_ICH4M 0x00000004 - -/* speedstep_processor - */ -static unsigned int speedstep_processor = 0; -static int speedstep_coppermine = 0; - -#define SPEEDSTEP_PROCESSOR_PIII_C 0x00000001 /* Coppermine core */ -#define SPEEDSTEP_PROCESSOR_PIII_T 0x00000002 /* Tualatin core */ -#define SPEEDSTEP_PROCESSOR_P4M 0x00000003 /* P4-M with 100 MHz FSB */ - - -/* speedstep_[low,high]_freq - * There are only two frequency states for each processor. Values - * are in kHz for the time being. - */ -#define SPEEDSTEP_HIGH 0x00000000 -#define SPEEDSTEP_LOW 0x00000001 - -static struct cpufreq_frequency_table speedstep_freqs[] = { - {SPEEDSTEP_HIGH, 0}, - {SPEEDSTEP_LOW, 0}, - {0, CPUFREQ_TABLE_END}, -}; - -#define speedstep_low_freq speedstep_freqs[SPEEDSTEP_LOW].frequency -#define speedstep_high_freq speedstep_freqs[SPEEDSTEP_HIGH].frequency - - -/* DEBUG - * Define it if you want verbose debug output, e.g. for bug reporting - */ -//#define SPEEDSTEP_DEBUG - -#ifdef SPEEDSTEP_DEBUG -#define dprintk(msg...) printk(msg) -#else -#define dprintk(msg...) do { } while(0) -#endif - - - -/********************************************************************* - * LOW LEVEL CHIPSET INTERFACE * - *********************************************************************/ - -/** - * speedstep_get_state - read the current SpeedStep state - * @state: Speedstep state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) - * - * Tries to read the SpeedStep state. Returns -EIO when there has been - * trouble to read the status or write to the control register, -EINVAL - * on an unsupported chipset, and zero on success. - */ -static int speedstep_get_state (unsigned int *state) -{ - unsigned long flags; - u32 pmbase; - u8 value; - - if (!speedstep_chipset_dev || !state) - return -EINVAL; - - switch (speedstep_chipset) { - case SPEEDSTEP_CHIPSET_ICH2M: - case SPEEDSTEP_CHIPSET_ICH3M: - case SPEEDSTEP_CHIPSET_ICH4M: - /* get PMBASE */ - pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); - if (!(pmbase & 0x01)) - return -EIO; - - pmbase &= 0xFFFFFFFE; - if (!pmbase) - return -EIO; - - /* read state */ - local_irq_save(flags); - value = inb(pmbase + 0x50); - local_irq_restore(flags); - - dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); - - *state = value & 0x01; - return 0; - - } - - printk (KERN_ERR "cpufreq: setting CPU frequency on this chipset unsupported.\n"); - return -EINVAL; -} - - -/** - * speedstep_set_state - set the SpeedStep state - * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) - * - * Tries to change the SpeedStep state. - */ -static void speedstep_set_state (unsigned int state, int notify) -{ - u32 pmbase; - u8 pm2_blk; - u8 value; - unsigned long flags; - unsigned int oldstate; - struct cpufreq_freqs freqs; - - if (!speedstep_chipset_dev || (state > 0x1)) - return; - - if (speedstep_get_state(&oldstate)) - return; - - if (oldstate == state) - return; - - freqs.old = (oldstate == SPEEDSTEP_HIGH) ? speedstep_high_freq : speedstep_low_freq; - freqs.new = (state == SPEEDSTEP_HIGH) ? speedstep_high_freq : speedstep_low_freq; - freqs.cpu = 0; /* speedstep.c is UP only driver */ - - if (notify) - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - - switch (speedstep_chipset) { - case SPEEDSTEP_CHIPSET_ICH2M: - case SPEEDSTEP_CHIPSET_ICH3M: - case SPEEDSTEP_CHIPSET_ICH4M: - /* get PMBASE */ - pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); - if (!(pmbase & 0x01)) - { - printk(KERN_ERR "cpufreq: could not find speedstep register\n"); - return; - } - - pmbase &= 0xFFFFFFFE; - if (!pmbase) { - printk(KERN_ERR "cpufreq: could not find speedstep register\n"); - return; - } - - /* Disable IRQs */ - local_irq_save(flags); - - /* read state */ - value = inb(pmbase + 0x50); - - dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); - - /* write new state */ - value &= 0xFE; - value |= state; - - dprintk(KERN_DEBUG "cpufreq: writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase); - - /* Disable bus master arbitration */ - pm2_blk = inb(pmbase + 0x20); - pm2_blk |= 0x01; - outb(pm2_blk, (pmbase + 0x20)); - - /* Actual transition */ - outb(value, (pmbase + 0x50)); - - /* Restore bus master arbitration */ - pm2_blk &= 0xfe; - outb(pm2_blk, (pmbase + 0x20)); - - /* check if transition was successful */ - value = inb(pmbase + 0x50); - - /* Enable IRQs */ - local_irq_restore(flags); - - dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); - - if (state == (value & 0x1)) { - dprintk (KERN_INFO "cpufreq: change to %u MHz succeeded\n", (freqs.new / 1000)); - } else { - printk (KERN_ERR "cpufreq: change failed - I/O error\n"); - } - break; - default: - printk (KERN_ERR "cpufreq: setting CPU frequency on this chipset unsupported.\n"); - } - - if (notify) - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - - return; -} - - -/** - * speedstep_activate - activate SpeedStep control in the chipset - * - * Tries to activate the SpeedStep status and control registers. - * Returns -EINVAL on an unsupported chipset, and zero on success. - */ -static int speedstep_activate (void) -{ - if (!speedstep_chipset_dev) - return -EINVAL; - - switch (speedstep_chipset) { - case SPEEDSTEP_CHIPSET_ICH2M: - case SPEEDSTEP_CHIPSET_ICH3M: - case SPEEDSTEP_CHIPSET_ICH4M: - { - u16 value = 0; - - pci_read_config_word(speedstep_chipset_dev, - 0x00A0, &value); - if (!(value & 0x08)) { - value |= 0x08; - dprintk(KERN_DEBUG "cpufreq: activating SpeedStep (TM) registers\n"); - pci_write_config_word(speedstep_chipset_dev, - 0x00A0, value); - } - - return 0; - } - } - - printk (KERN_ERR "cpufreq: SpeedStep (TM) on this chipset unsupported.\n"); - return -EINVAL; -} - - -/** - * speedstep_detect_chipset - detect the Southbridge which contains SpeedStep logic - * - * Detects PIIX4, ICH2-M and ICH3-M so far. The pci_dev points to - * the LPC bridge / PM module which contains all power-management - * functions. Returns the SPEEDSTEP_CHIPSET_-number for the detected - * chipset, or zero on failure. - */ -static unsigned int speedstep_detect_chipset (void) -{ - speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82801DB_12, - PCI_ANY_ID, - PCI_ANY_ID, - NULL); - if (speedstep_chipset_dev) - return SPEEDSTEP_CHIPSET_ICH4M; - - speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82801CA_12, - PCI_ANY_ID, - PCI_ANY_ID, - NULL); - if (speedstep_chipset_dev) - return SPEEDSTEP_CHIPSET_ICH3M; - - - speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82801BA_10, - PCI_ANY_ID, - PCI_ANY_ID, - NULL); - if (speedstep_chipset_dev) { - /* speedstep.c causes lockups on Dell Inspirons 8000 and - * 8100 which use a pretty old revision of the 82815 - * host brige. Abort on these systems. - */ - static struct pci_dev *hostbridge; - u8 rev = 0; - - hostbridge = pci_find_subsys(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82815_MC, - PCI_ANY_ID, - PCI_ANY_ID, - NULL); - - if (!hostbridge) - return SPEEDSTEP_CHIPSET_ICH2M; - - pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev); - if (rev < 5) { - dprintk(KERN_INFO "cpufreq: hostbridge does not support speedstep\n"); - speedstep_chipset_dev = NULL; - return 0; - } - - return SPEEDSTEP_CHIPSET_ICH2M; - } - - return 0; -} - - - -/********************************************************************* - * LOW LEVEL PROCESSOR INTERFACE * - *********************************************************************/ - - -/** - * pentium3_get_frequency - get the core frequencies for PIIIs - * - * Returns the core frequency of a Pentium III processor (in kHz) - */ -static unsigned int pentium3_get_frequency (void) -{ - /* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */ - struct { - unsigned int ratio; /* Frequency Multiplier (x10) */ - u8 bitmap; /* power on configuration bits - [27, 25:22] (in MSR 0x2a) */ - } msr_decode_mult [] = { - { 30, 0x01 }, - { 35, 0x05 }, - { 40, 0x02 }, - { 45, 0x06 }, - { 50, 0x00 }, - { 55, 0x04 }, - { 60, 0x0b }, - { 65, 0x0f }, - { 70, 0x09 }, - { 75, 0x0d }, - { 80, 0x0a }, - { 85, 0x26 }, - { 90, 0x20 }, - { 100, 0x2b }, - { 0, 0xff } /* error or unknown value */ - }; - /* PIII(-M) FSB settings: see table b1-b of 24547206.pdf */ - struct { - unsigned int value; /* Front Side Bus speed in MHz */ - u8 bitmap; /* power on configuration bits [18: 19] - (in MSR 0x2a) */ - } msr_decode_fsb [] = { - { 66, 0x0 }, - { 100, 0x2 }, - { 133, 0x1 }, - { 0, 0xff} - }; - u32 msr_lo, msr_tmp; - int i = 0, j = 0; - struct cpuinfo_x86 *c = cpu_data; - - /* read MSR 0x2a - we only need the low 32 bits */ - rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp); - dprintk(KERN_DEBUG "cpufreq: P3 - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp); - msr_tmp = msr_lo; - - /* decode the FSB */ - msr_tmp &= 0x00c0000; - msr_tmp >>= 18; - while (msr_tmp != msr_decode_fsb[i].bitmap) { - if (msr_decode_fsb[i].bitmap == 0xff) - return -EINVAL; - i++; - } - - /* decode the multiplier */ - if ((c->x86_model == 0x08) && (c->x86_mask == 0x01)) - /* different on early Coppermine PIII */ - msr_lo &= 0x03c00000; - else - msr_lo &= 0x0bc00000; - msr_lo >>= 22; - while (msr_lo != msr_decode_mult[j].bitmap) { - if (msr_decode_mult[j].bitmap == 0xff) - return -EINVAL; - j++; - } - - return (msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100); -} - - -/** - * pentium4_get_frequency - get the core frequency for P4-Ms - * - * Should return the core frequency (in kHz) for P4-Ms. - */ -static unsigned int pentium4_get_frequency(void) -{ - u32 msr_lo, msr_hi; - - rdmsr(0x2c, msr_lo, msr_hi); - - dprintk(KERN_DEBUG "cpufreq: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); - - /* First 12 bits seem to change a lot (0x511, 0x410 and 0x30f seen - * yet). Next 12 bits always seem to be 0x300. If this is not true - * on this CPU, complain. Last 8 bits are frequency (in 100MHz). - */ - if (msr_hi || ((msr_lo & 0x00FFF000) != 0x300000)) { - printk(KERN_DEBUG "cpufreq: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); - printk(KERN_INFO "cpufreq: problem in initialization. Please contact Dominik Brodowski\n"); - printk(KERN_INFO "cpufreq: and attach this dmesg. Thanks in advance\n"); - return 0; - } - - msr_lo >>= 24; - return (msr_lo * 100000); -} - - -/** - * speedstep_detect_processor - detect Intel SpeedStep-capable processors. - * - * Returns the SPEEDSTEP_PROCESSOR_-number for the detected processor, - * or zero on failure. - */ -static unsigned int speedstep_detect_processor (void) -{ - struct cpuinfo_x86 *c = cpu_data; - u32 ebx; - - if ((c->x86_vendor != X86_VENDOR_INTEL) || - ((c->x86 != 6) && (c->x86 != 0xF))) - return 0; - - if (c->x86 == 0xF) { - /* Intel Pentium 4 Mobile P4-M */ - if (c->x86_model != 2) - return 0; - - if ((c->x86_mask != 4) && (c->x86_mask != 7)) - return 0; - - ebx = cpuid_ebx(0x00000001); - ebx &= 0x000000FF; - if ((ebx != 0x0e) && (ebx != 0x0f)) - return 0; - - return SPEEDSTEP_PROCESSOR_P4M; - } - - switch (c->x86_model) { - case 0x0B: /* Intel PIII [Tualatin] */ - /* cpuid_ebx(1) is 0x04 for desktop PIII, - 0x06 for mobile PIII-M */ - ebx = cpuid_ebx(0x00000001); - - ebx &= 0x000000FF; - if (ebx != 0x06) - return 0; - - /* So far all PIII-M processors support SpeedStep. See - * Intel's 24540633.pdf of August 2002 - */ - - return SPEEDSTEP_PROCESSOR_PIII_T; - - case 0x08: /* Intel PIII [Coppermine] */ - { - u32 msr_lo, msr_hi; - - /* all mobile PIII Coppermines have FSB 100 MHz - * ==> sort out a few desktop PIIIs. */ - rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_hi); - dprintk(KERN_DEBUG "cpufreq: Coppermine: MSR_IA32_EBL_Cr_POWERON is 0x%x, 0x%x\n", msr_lo, msr_hi); - msr_lo &= 0x00c0000; - if (msr_lo != 0x0080000) - return 0; - - if (speedstep_coppermine) - return SPEEDSTEP_PROCESSOR_PIII_C; - - printk(KERN_INFO "cpufreq: in case this is a SpeedStep-capable Intel Pentium III Coppermine\n"); - printk(KERN_INFO "cpufreq: processor, please pass the boot option or module parameter\n"); - printk(KERN_INFO "cpufreq: `speedstep_coppermine=1` to the kernel. Thanks!\n"); - return 0; - } - - default: - return 0; - } -} - - - -/********************************************************************* - * HIGH LEVEL FUNCTIONS * - *********************************************************************/ - -/** - * speedstep_detect_speeds - detects low and high CPU frequencies. - * - * Detects the low and high CPU frequencies in kHz. Returns 0 on - * success or -EINVAL / -EIO on problems. - */ -static int speedstep_detect_speeds (void) -{ - unsigned long flags; - unsigned int state; - int i, result; - - /* Disable irqs for entire detection process */ - local_irq_save(flags); - - for (i=0; i<2; i++) { - /* read the current state */ - result = speedstep_get_state(&state); - if (result) - return result; - - /* save the correct value, and switch to other */ - if (state == SPEEDSTEP_LOW) { - switch (speedstep_processor) { - case SPEEDSTEP_PROCESSOR_PIII_C: - case SPEEDSTEP_PROCESSOR_PIII_T: - speedstep_low_freq = pentium3_get_frequency(); - break; - case SPEEDSTEP_PROCESSOR_P4M: - speedstep_low_freq = pentium4_get_frequency(); - } - speedstep_set_state(SPEEDSTEP_HIGH, 0); - } else { - switch (speedstep_processor) { - case SPEEDSTEP_PROCESSOR_PIII_C: - case SPEEDSTEP_PROCESSOR_PIII_T: - speedstep_high_freq = pentium3_get_frequency(); - break; - case SPEEDSTEP_PROCESSOR_P4M: - speedstep_high_freq = pentium4_get_frequency(); - } - speedstep_set_state(SPEEDSTEP_LOW, 0); - } - } - - local_irq_restore(flags); - - if (!speedstep_low_freq || !speedstep_high_freq || - (speedstep_low_freq == speedstep_high_freq)) - return -EIO; - - return 0; -} - - -/** - * speedstep_setpolicy - set a new CPUFreq policy - * @policy: new policy - * - * Sets a new CPUFreq policy. - */ -static int speedstep_target (struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) -{ - unsigned int newstate = 0; - - if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate)) - return -EINVAL; - - speedstep_set_state(newstate, 1); - - return 0; -} - - -/** - * speedstep_verify - verifies a new CPUFreq policy - * @freq: new policy - * - * Limit must be within speedstep_low_freq and speedstep_high_freq, with - * at least one border included. - */ -static int speedstep_verify (struct cpufreq_policy *policy) -{ - return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]); -} - - -static int speedstep_cpu_init(struct cpufreq_policy *policy) -{ - int result = 0; - unsigned int speed; - - /* capability check */ - if (policy->cpu != 0) - return -ENODEV; - - /* detect low and high frequency */ - result = speedstep_detect_speeds(); - if (result) - return result; - - /* get current speed setting */ - result = speedstep_get_state(&speed); - if (result) - return result; - - speed = (speed == SPEEDSTEP_LOW) ? speedstep_low_freq : speedstep_high_freq; - dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n", - (speed == speedstep_low_freq) ? "low" : "high", - (speed / 1000)); - - /* cpuinfo and default policy values */ - policy->policy = (speed == speedstep_low_freq) ? - CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE; - policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policy->cur = speed; - - return cpufreq_frequency_table_cpuinfo(policy, &speedstep_freqs[0]); -} - - -#ifndef MODULE -/** - * speedstep_setup speedstep command line parameter parsing - * - * speedstep command line parameter. Use: - * speedstep_coppermine=1 - * if the CPU in your notebook is a SpeedStep-capable Intel - * Pentium III Coppermine. These processors cannot be detected - * automatically, as Intel continues to consider the detection - * algorithm as proprietary material. - */ -static int __init speedstep_setup(char *str) -{ - speedstep_coppermine = simple_strtoul(str, &str, 0); - return 1; -} -__setup("speedstep_coppermine=", speedstep_setup); -#endif - - -static struct cpufreq_driver speedstep_driver = { - .name = "speedstep", - .verify = speedstep_verify, - .target = speedstep_target, - .init = speedstep_cpu_init, - .owner = THIS_MODULE, -}; - - -/** - * speedstep_init - initializes the SpeedStep CPUFreq driver - * - * Initializes the SpeedStep support. Returns -ENODEV on unsupported - * devices, -EINVAL on problems during initiatization, and zero on - * success. - */ -static int __init speedstep_init(void) -{ - /* detect chipset */ - speedstep_chipset = speedstep_detect_chipset(); - - /* detect chipset */ - if (speedstep_chipset) - speedstep_processor = speedstep_detect_processor(); - - if ((!speedstep_chipset) || (!speedstep_processor)) { - printk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this %s not (yet) available.\n", speedstep_chipset ? "processor" : "chipset"); - return -ENODEV; - } - - dprintk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) support $Revision: 1.70 $\n"); - - /* activate speedstep support */ - if (speedstep_activate()) - return -EINVAL; - - return cpufreq_register_driver(&speedstep_driver); -} - - -/** - * speedstep_exit - unregisters SpeedStep support - * - * Unregisters SpeedStep support. - */ -static void __exit speedstep_exit(void) -{ - cpufreq_unregister_driver(&speedstep_driver); -} - - -MODULE_PARM (speedstep_coppermine, "i"); - -MODULE_AUTHOR ("Dave Jones , Dominik Brodowski "); -MODULE_DESCRIPTION ("Speedstep driver for Intel mobile processors."); -MODULE_LICENSE ("GPL"); - -module_init(speedstep_init); -module_exit(speedstep_exit); diff -urN linux-2.5.70-bk19/arch/ppc64/boot/zlib.c linux-2.5.71/arch/ppc64/boot/zlib.c --- linux-2.5.70-bk19/arch/ppc64/boot/zlib.c 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/ppc64/boot/zlib.c 2003-06-14 13:53:23.000000000 -0700 @@ -1545,10 +1545,11 @@ local inflate_huft *fixed_td; -local voidpf falloc(q, n, s) -voidpf q; /* opaque pointer (not used) */ -uInt n; /* number of items */ -uInt s; /* size of item */ +local voidpf falloc( + voidpf q, /* opaque pointer (not used) */ + uInt n, /* number of items */ + uInt s /* size of item */ +) { Assert(s == sizeof(inflate_huft) && n <= fixed_left, "inflate_trees falloc overflow"); @@ -1558,10 +1559,11 @@ } -local void ffree(q, p, n) -voidpf q; -voidpf p; -uInt n; +local void ffree( + voidpf q, + voidpf p, + uInt n +) { Assert(0, "inflate_trees ffree called!"); if (q) q = p; /* to make some compilers happy */ @@ -2164,10 +2166,11 @@ #define DO16(buf) DO8(buf); DO8(buf); /* ========================================================================= */ -uLong adler32(adler, buf, len) - uLong adler; - Bytef *buf; - uInt len; +uLong adler32( + uLong adler, + Bytef *buf, + uInt len +) { unsigned long s1 = adler & 0xffff; unsigned long s2 = (adler >> 16) & 0xffff; diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/Makefile linux-2.5.71/arch/ppc64/kernel/Makefile --- linux-2.5.70-bk19/arch/ppc64/kernel/Makefile 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -9,7 +9,7 @@ align.o semaphore.o bitops.o stab.o htab.o pacaData.o \ udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \ ptrace32.o signal32.o pmc.o rtc.o init_task.o \ - lmb.o pci.o pci_dn.o pci_dma.o + lmb.o pci.o pci_dn.o pci_dma.o cputable.o obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_pci_reset.o \ iSeries_IoMmTable.o iSeries_irq.o \ @@ -19,11 +19,11 @@ mf.o HvLpEvent.o iSeries_proc.o obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \ - eeh.o rtasd.o nvram.o + eeh.o rtasd.o nvram.o ras.o # Change this to pSeries only once we've got iSeries up to date obj-y += open_pic.o xics.o pSeries_htab.o rtas.o \ - chrp_setup.o i8259.o ras.o prom.o + chrp_setup.o i8259.o prom.o obj-$(CONFIG_PROC_FS) += proc_ppc64.o obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o @@ -31,3 +31,5 @@ obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o obj-$(CONFIG_PPC_RTAS) += rtas-proc.o obj-$(CONFIG_SCANLOG) += scanlog.o + +CFLAGS_ioctl32.o += -Ifs/ diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/align.c linux-2.5.71/arch/ppc64/kernel/align.c --- linux-2.5.70-bk19/arch/ppc64/kernel/align.c 2003-05-26 18:01:00.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/align.c 2003-06-14 13:53:23.000000000 -0700 @@ -20,6 +20,7 @@ #include #include #include +#include void disable_kernel_fp(void); /* asm function from head.S */ @@ -238,12 +239,11 @@ dsisr = regs->dsisr; - /* Power4 doesn't set DSISR for an alignment interrupt */ - if (!cpu_alignexc_sets_dsisr()) { - unsigned int real_instr; - if (__get_user(real_instr, (unsigned int *)regs->nip)) - return 0; - dsisr = make_dsisr(real_instr); + if (cur_cpu_spec->cpu_features & CPU_FTR_NODSISRALIGN) { + unsigned int real_instr; + if (__get_user(real_instr, (unsigned int *)regs->nip)) + return 0; + dsisr = make_dsisr(*((unsigned *)regs->nip)); } /* extract the operation and registers from the dsisr */ diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/asm-offsets.c linux-2.5.71/arch/ppc64/kernel/asm-offsets.c --- linux-2.5.70-bk19/arch/ppc64/kernel/asm-offsets.c 2003-05-26 18:00:42.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/asm-offsets.c 2003-06-14 13:53:23.000000000 -0700 @@ -34,6 +34,7 @@ #include #include #include +#include #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) @@ -159,5 +160,12 @@ DEFINE(CLONE_VM, CLONE_VM); DEFINE(CLONE_UNTRACED, CLONE_UNTRACED); + /* About the CPU features table */ + DEFINE(CPU_SPEC_ENTRY_SIZE, sizeof(struct cpu_spec)); + DEFINE(CPU_SPEC_PVR_MASK, offsetof(struct cpu_spec, pvr_mask)); + DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value)); + DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features)); + DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); + return 0; } diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/chrp_setup.c linux-2.5.71/arch/ppc64/kernel/chrp_setup.c --- linux-2.5.70-bk19/arch/ppc64/kernel/chrp_setup.c 2003-05-26 18:00:24.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/chrp_setup.c 2003-06-14 13:53:23.000000000 -0700 @@ -62,13 +62,13 @@ #include "open_pic.h" #include #include +#include extern volatile unsigned char *chrp_int_ack_special; void chrp_progress(char *, unsigned short); extern void openpic_init_IRQ(void); -extern void init_ras_IRQ(void); extern void find_and_init_phbs(void); @@ -238,7 +238,6 @@ ppc_md.init_IRQ = xics_init_IRQ; ppc_md.get_irq = xics_get_irq; } - ppc_md.init_ras_IRQ = init_ras_IRQ; ppc_md.init = chrp_init2; @@ -253,6 +252,34 @@ ppc_md.progress = chrp_progress; + /* build up the firmware_features bitmask field + * using contents of device-tree/ibm,hypertas-functions. + * Ultimately this functionality may be moved into prom.c prom_init(). + */ + struct device_node * dn; + char * hypertas; + unsigned int len; + dn = find_path_device("/rtas"); + cur_cpu_spec->firmware_features = 0; + hypertas = get_property(dn, "ibm,hypertas-functions", &len); + if (hypertas) { + while (len > 0){ + int i; + /* check value against table of strings */ + for(i=0; i < FIRMWARE_MAX_FEATURES ;i++) { + if ((firmware_features_table[i].name) && (strcmp(firmware_features_table[i].name,hypertas))==0) { + /* we have a match */ + cur_cpu_spec->firmware_features |= (1UL << firmware_features_table[i].val); + break; + } + } + int hypertas_len = strlen(hypertas); + len -= hypertas_len +1; + hypertas+= hypertas_len +1; + } + } + udbg_printf("firmware_features bitmask: 0x%x \n", + cur_cpu_spec->firmware_features); } void diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/cputable.c linux-2.5.71/arch/ppc64/kernel/cputable.c --- linux-2.5.70-bk19/arch/ppc64/kernel/cputable.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/ppc64/kernel/cputable.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,127 @@ +/* + * arch/ppc64/kernel/cputable.c + * + * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org) + * + * Modifications for ppc64: + * Copyright (C) 2003 Dave Engebretsen + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +struct cpu_spec* cur_cpu_spec = NULL; + +extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec); +extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec); + + +/* We only set the altivec features if the kernel was compiled with altivec + * support + */ +#ifdef CONFIG_ALTIVEC +#define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC +#else +#define CPU_FTR_ALTIVEC_COMP 0 +#endif + +struct cpu_spec cpu_specs[] = { + { /* Power3 */ + 0xffff0000, 0x00400000, "Power3 (630)", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_USER_PPC64, + 128, 128, + __setup_cpu_power3, + COMMON_PPC64_FW + }, + { /* Power3+ */ + 0xffff0000, 0x00410000, "Power3 (630+)", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_USER_PPC64, + 128, 128, + __setup_cpu_power3, + COMMON_PPC64_FW + }, + { /* Northstar */ + 0xffff0000, 0x00330000, "Northstar", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_USER_PPC64, + 128, 128, + __setup_cpu_power3, + COMMON_PPC64_FW + }, + { /* Pulsar */ + 0xffff0000, 0x00340000, "Pulsar", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_USER_PPC64, + 128, 128, + __setup_cpu_power3, + COMMON_PPC64_FW + }, + { /* I-star */ + 0xffff0000, 0x00360000, "I-star", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_USER_PPC64, + 128, 128, + __setup_cpu_power3, + COMMON_PPC64_FW + }, + { /* S-star */ + 0xffff0000, 0x00370000, "S-star", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + COMMON_USER_PPC64, + 128, 128, + __setup_cpu_power3, + COMMON_PPC64_FW + }, + { /* Power4 */ + 0xffff0000, 0x00350000, "Power4", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | + CPU_FTR_PPCAS_ARCH_V2, + COMMON_USER_PPC64, + 128, 128, + __setup_cpu_power4, + COMMON_PPC64_FW + }, + { /* Power4+ */ + 0xffff0000, 0x00380000, "Power4+", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | + CPU_FTR_PPCAS_ARCH_V2, + COMMON_USER_PPC64, + 128, 128, + __setup_cpu_power4, + COMMON_PPC64_FW + }, + { /* default match */ + 0x00000000, 0x00000000, "(Power4-Compatible)", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | + CPU_FTR_PPCAS_ARCH_V2, + COMMON_USER_PPC64, + 128, 128, + __setup_cpu_power4, + COMMON_PPC64_FW + } +}; + +firmware_feature_t firmware_features_table[FIRMWARE_MAX_FEATURES] = { + {FW_FEATURE_PFT, "hcall-pft"}, + {FW_FEATURE_TCE, "hcall-tce"}, + {FW_FEATURE_SPRG0, "hcall-sprg0"}, + {FW_FEATURE_DABR, "hcall-dabr"}, + {FW_FEATURE_COPY, "hcall-copy"}, + {FW_FEATURE_ASR, "hcall-asr"}, + {FW_FEATURE_DEBUG, "hcall-debug"}, + {FW_FEATURE_PERF, "hcall-perf"}, + {FW_FEATURE_DUMP, "hcall-dump"}, + {FW_FEATURE_INTERRUPT, "hcall-interrupt"}, + {FW_FEATURE_MIGRATE, "hcall-migrate"}, +}; diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/head.S linux-2.5.71/arch/ppc64/kernel/head.S --- linux-2.5.70-bk19/arch/ppc64/kernel/head.S 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/head.S 2003-06-14 13:53:23.000000000 -0700 @@ -34,6 +34,7 @@ #include #include #include +#include #ifdef CONFIG_PPC_ISERIES #define DO_SOFT_DISABLE @@ -1267,6 +1268,11 @@ li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) + LOADADDR(r3,cpu_specs) + LOADADDR(r4,cur_cpu_spec) + li r5,0 + bl .identify_cpu + LOADADDR(r2,__toc_start) addi r2,r2,0x4000 addi r2,r2,0x4000 @@ -1730,6 +1736,13 @@ li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) + LOADADDR(r3,cpu_specs) + sub r3,r3,r26 + LOADADDR(r4,cur_cpu_spec) + sub r4,r4,r26 + mr r5,r26 + bl .identify_cpu + /* set up the TOC (physical address) */ LOADADDR(r2,__toc_start) addi r2,r2,0x4000 @@ -1888,6 +1901,11 @@ bl .start_kernel +_GLOBAL(__setup_cpu_power3) + blr +_GLOBAL(__setup_cpu_power4) + blr + _GLOBAL(hmt_init) #ifdef CONFIG_HMT LOADADDR(r5, hmt_thread_data) diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/htab.c linux-2.5.71/arch/ppc64/kernel/htab.c --- linux-2.5.70-bk19/arch/ppc64/kernel/htab.c 2003-05-26 18:00:41.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/htab.c 2003-06-14 13:53:23.000000000 -0700 @@ -46,6 +46,7 @@ #include #include #include +#include /* * Note: pte --> Linux PTE @@ -165,7 +166,8 @@ mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX; /* XXX we currently map kernel text rw, should fix this */ - if (cpu_has_largepage() && systemcfg->physicalMemorySize > 256*MB) { + if ((cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) + && systemcfg->physicalMemorySize > 256*MB) { create_pte_mapping((unsigned long)KERNELBASE, KERNELBASE + 256*MB, mode_rw, 0); create_pte_mapping((unsigned long)KERNELBASE + 256*MB, @@ -279,7 +281,8 @@ #define PPC64_HWNOEXEC (1 << 2) /* We do lazy icache flushing on cpus that support it */ - if (unlikely(cpu_has_noexecute() && pfn_valid(pte_pfn(new_pte)))) { + if (unlikely((cur_cpu_spec->cpu_features & CPU_FTR_NOEXECUTE) + && pfn_valid(pte_pfn(new_pte)))) { struct page *page = pte_page(new_pte); /* page is dirty */ diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/iSeries_setup.c linux-2.5.71/arch/ppc64/kernel/iSeries_setup.c --- linux-2.5.70-bk19/arch/ppc64/kernel/iSeries_setup.c 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/iSeries_setup.c 2003-06-14 13:53:23.000000000 -0700 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "iSeries_setup.h" @@ -254,7 +255,7 @@ { unsigned long i; unsigned long mem_blocks = 0; - if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) + if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) mem_blocks = iSeries_process_Regatta_mainstore_vpd( mb_array, max_entries ); else mem_blocks = iSeries_process_Condor_mainstore_vpd( mb_array, max_entries ); @@ -311,7 +312,6 @@ ppc_md.setup_residual = iSeries_setup_residual; ppc_md.get_cpuinfo = iSeries_get_cpuinfo; ppc_md.init_IRQ = iSeries_init_IRQ; - ppc_md.init_ras_IRQ = NULL; ppc_md.get_irq = iSeries_get_irq; ppc_md.init = NULL; diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/ioctl32.c linux-2.5.71/arch/ppc64/kernel/ioctl32.c --- linux-2.5.70-bk19/arch/ppc64/kernel/ioctl32.c 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/ioctl32.c 2003-06-14 13:53:23.000000000 -0700 @@ -20,3189 +20,340 @@ * 2 of the License, or (at your option) any later version. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#define INCLUDES +#include "compat_ioctl.c" #include -#include -#include -#include -#include -#include -#include - -#include -/* Ugly hack. */ -#undef __KERNEL__ -#include -#define __KERNEL__ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include #include -#include -/* Aiee. Someone does not find a difference between int and long */ -#define EXT2_IOC32_GETFLAGS _IOR('f', 1, int) -#define EXT2_IOC32_SETFLAGS _IOW('f', 2, int) -#define EXT2_IOC32_GETVERSION _IOR('v', 1, int) -#define EXT2_IOC32_SETVERSION _IOW('v', 2, int) +#define CODE +#include "compat_ioctl.c" -extern asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); - -static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - int err; - unsigned long val; - - set_fs (KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&val); - set_fs (old_fs); - if (!err && put_user(val, (u32 *)arg)) - return -EFAULT; - return err; -} - -static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg) +struct hd_big_geometry32 { + unsigned char heads; + unsigned char sectors; + unsigned int cylinders; + u32 start; +}; + +static int hdio_getgeo_big(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); + struct hd_big_geometry geo; int err; - unsigned long val; - if (get_user(val, (u32 *)arg)) - return -EFAULT; set_fs (KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&val); + err = sys_ioctl(fd, cmd, (unsigned long)&geo); set_fs (old_fs); - if (!err && put_user(val, (u32 *)arg)) - return -EFAULT; - return err; -} + if (!err) { + struct hd_big_geometry32 *up = (struct hd_big_geometry32 *) arg; -static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - /* These are just misnamed, they actually get/put from/to user an int */ - switch (cmd) { - case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break; - case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break; - case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break; - case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break; + if (put_user(geo.heads, &up->heads) || + __put_user(geo.sectors, &up->sectors) || + __put_user(geo.cylinders, &up->cylinders) || + __put_user(((u32) geo.start), &up->start)) + err = -EFAULT; } - return sys_ioctl(fd, cmd, arg); -} - -struct video_tuner32 { - s32 tuner; - u8 name[32]; - u32 rangelow, rangehigh; - u32 flags; - u16 mode, signal; -}; - -static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 *up) -{ - int i; - - if (get_user(kp->tuner, &up->tuner)) - return -EFAULT; - for(i = 0; i < 32; i++) - __get_user(kp->name[i], &up->name[i]); - __get_user(kp->rangelow, &up->rangelow); - __get_user(kp->rangehigh, &up->rangehigh); - __get_user(kp->flags, &up->flags); - __get_user(kp->mode, &up->mode); - __get_user(kp->signal, &up->signal); - return 0; -} - -static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 *up) -{ - int i; - - if (put_user(kp->tuner, &up->tuner)) - return -EFAULT; - for(i = 0; i < 32; i++) - __put_user(kp->name[i], &up->name[i]); - __put_user(kp->rangelow, &up->rangelow); - __put_user(kp->rangehigh, &up->rangehigh); - __put_user(kp->flags, &up->flags); - __put_user(kp->mode, &up->mode); - __put_user(kp->signal, &up->signal); - return 0; + return err; } -struct video_buffer32 { - /* void * */ u32 base; - s32 height, width, depth, bytesperline; +struct ncp_ioctl_request_32 { + unsigned int function; + unsigned int size; + compat_caddr_t data; }; -static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 *up) -{ - u32 tmp; - - if (get_user(tmp, &up->base)) - return -EFAULT; - kp->base = (void *) ((unsigned long)tmp); - __get_user(kp->height, &up->height); - __get_user(kp->width, &up->width); - __get_user(kp->depth, &up->depth); - __get_user(kp->bytesperline, &up->bytesperline); - return 0; -} - -static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 *up) -{ - u32 tmp = (u32)((unsigned long)kp->base); - - if (put_user(tmp, &up->base)) - return -EFAULT; - __put_user(kp->height, &up->height); - __put_user(kp->width, &up->width); - __put_user(kp->depth, &up->depth); - __put_user(kp->bytesperline, &up->bytesperline); - return 0; -} +struct ncp_fs_info_v2_32 { + int version; + unsigned int mounted_uid; + unsigned int connection; + unsigned int buffer_size; -struct video_clip32 { - s32 x, y, width, height; - /* struct video_clip32 * */ u32 next; -}; + unsigned int volume_number; + __u32 directory_id; -struct video_window32 { - u32 x, y, width, height, chromakey, flags; - /* struct video_clip32 * */ u32 clips; - s32 clipcount; + __u32 dummy1; + __u32 dummy2; + __u32 dummy3; }; -static void free_kvideo_clips(struct video_window *kp) -{ - struct video_clip *cp; - - cp = kp->clips; - if (cp != NULL) - kfree(cp); -} - -static int get_video_window32(struct video_window *kp, struct video_window32 *up) -{ - struct video_clip32 *ucp; - struct video_clip *kcp; - int nclips, err, i; - u32 tmp; - - if (get_user(kp->x, &up->x)) - return -EFAULT; - __get_user(kp->y, &up->y); - __get_user(kp->width, &up->width); - __get_user(kp->height, &up->height); - __get_user(kp->chromakey, &up->chromakey); - __get_user(kp->flags, &up->flags); - __get_user(kp->clipcount, &up->clipcount); - __get_user(tmp, &up->clips); - ucp = (struct video_clip32 *)A(tmp); - kp->clips = NULL; - - nclips = kp->clipcount; - if (nclips == 0) - return 0; - - if (ucp == 0) - return -EINVAL; - - /* Peculiar interface... */ - if (nclips < 0) - nclips = VIDEO_CLIPMAP_SIZE; - - kcp = kmalloc(nclips * sizeof(struct video_clip), GFP_KERNEL); - err = -ENOMEM; - if (kcp == NULL) - goto cleanup_and_err; - - kp->clips = kcp; - for(i = 0; i < nclips; i++) { - __get_user(kcp[i].x, &ucp[i].x); - __get_user(kcp[i].y, &ucp[i].y); - __get_user(kcp[i].width, &ucp[i].width); - __get_user(kcp[i].height, &ucp[i].height); - kcp[nclips].next = NULL; - } - - return 0; - -cleanup_and_err: - free_kvideo_clips(kp); - return err; -} - -/* You get back everything except the clips... */ -static int put_video_window32(struct video_window *kp, struct video_window32 *up) -{ - if (put_user(kp->x, &up->x)) - return -EFAULT; - __put_user(kp->y, &up->y); - __put_user(kp->width, &up->width); - __put_user(kp->height, &up->height); - __put_user(kp->chromakey, &up->chromakey); - __put_user(kp->flags, &up->flags); - __put_user(kp->clipcount, &up->clipcount); - return 0; -} - -#define VIDIOCGTUNER32 _IOWR('v',4, struct video_tuner32) -#define VIDIOCSTUNER32 _IOW('v',5, struct video_tuner32) -#define VIDIOCGWIN32 _IOR('v',9, struct video_window32) -#define VIDIOCSWIN32 _IOW('v',10, struct video_window32) -#define VIDIOCGFBUF32 _IOR('v',11, struct video_buffer32) -#define VIDIOCSFBUF32 _IOW('v',12, struct video_buffer32) -#define VIDIOCGFREQ32 _IOR('v',14, u32) -#define VIDIOCSFREQ32 _IOW('v',15, u32) - -static int do_video_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - union { - struct video_tuner vt; - struct video_buffer vb; - struct video_window vw; - unsigned long vx; - } karg; - mm_segment_t old_fs = get_fs(); - void *up = (void *)arg; - int err = 0; - - /* First, convert the command. */ - switch(cmd) { - case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break; - case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break; - case VIDIOCGWIN32: cmd = VIDIOCGWIN; break; - case VIDIOCSWIN32: cmd = VIDIOCSWIN; break; - case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break; - case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break; - case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break; - case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break; - }; - - switch(cmd) { - case VIDIOCSTUNER: - case VIDIOCGTUNER: - err = get_video_tuner32(&karg.vt, up); - break; - - case VIDIOCSWIN: - err = get_video_window32(&karg.vw, up); - break; - - case VIDIOCSFBUF: - err = get_video_buffer32(&karg.vb, up); - break; - - case VIDIOCSFREQ: - err = get_user(karg.vx, (u32 *)up); - break; - }; - if (err) - goto out; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&karg); - set_fs(old_fs); - - if (cmd == VIDIOCSWIN) - free_kvideo_clips(&karg.vw); - - if (err == 0) { - switch(cmd) { - case VIDIOCGTUNER: - err = put_video_tuner32(&karg.vt, up); - break; - - case VIDIOCGWIN: - err = put_video_window32(&karg.vw, up); - break; - - case VIDIOCGFBUF: - err = put_video_buffer32(&karg.vb, up); - break; - - case VIDIOCGFREQ: - err = put_user(((u32)karg.vx), (u32 *)up); - break; - }; - } -out: - return err; -} - -static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg) +struct ncp_objectname_ioctl_32 { - struct compat_timeval *up = (struct compat_timeval *)arg; - struct timeval ktv; - mm_segment_t old_fs = get_fs(); - int err; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&ktv); - set_fs(old_fs); - if (!err) { - err = put_user(ktv.tv_sec, &up->tv_sec); - err |= __put_user(ktv.tv_usec, &up->tv_usec); - } - return err; -} - -struct ifmap32 { - u32 mem_start; - u32 mem_end; - unsigned short base_addr; - unsigned char irq; - unsigned char dma; - unsigned char port; -}; - -struct ifreq32 { -#define IFHWADDRLEN 6 -#define IFNAMSIZ 16 - union { - char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ - } ifr_ifrn; - union { - struct sockaddr ifru_addr; - struct sockaddr ifru_dstaddr; - struct sockaddr ifru_broadaddr; - struct sockaddr ifru_netmask; - struct sockaddr ifru_hwaddr; - short ifru_flags; - int ifru_ivalue; - int ifru_mtu; - struct ifmap32 ifru_map; - char ifru_slave[IFNAMSIZ]; /* Just fits the size */ - char ifru_newname[IFNAMSIZ]; - compat_caddr_t ifru_data; - } ifr_ifru; -}; - -struct ifconf32 { - int ifc_len; /* size of buffer */ - compat_caddr_t ifcbuf; + int auth_type; + unsigned int object_name_len; + compat_caddr_t object_name; /* an userspace data, in most cases user name */ }; -#ifdef CONFIG_NET -static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg) +struct ncp_privatedata_ioctl_32 { - struct net_device *dev; - struct ifreq32 ifr32; - int err; + unsigned int len; + compat_caddr_t data; /* ~1000 for NDS */ +}; - if (copy_from_user(&ifr32, (struct ifreq32 *)arg, sizeof(struct ifreq32))) - return -EFAULT; +#define NCP_IOC_NCPREQUEST_32 _IOR('n', 1, struct ncp_ioctl_request_32) - dev = dev_get_by_index(ifr32.ifr_ifindex); - if (!dev) - return -ENODEV; +#define NCP_IOC_GETMOUNTUID2_32 _IOW('n', 2, unsigned int) - strcpy(ifr32.ifr_name, dev->name); - dev_put(dev); +#define NCP_IOC_GET_FS_INFO_V2_32 _IOWR('n', 4, struct ncp_fs_info_v2_32) - err = copy_to_user((struct ifreq32 *)arg, &ifr32, sizeof(struct ifreq32)); - return (err ? -EFAULT : 0); -} -#endif +#define NCP_IOC_GETOBJECTNAME_32 _IOWR('n', 9, struct ncp_objectname_ioctl_32) +#define NCP_IOC_SETOBJECTNAME_32 _IOR('n', 9, struct ncp_objectname_ioctl_32) +#define NCP_IOC_GETPRIVATEDATA_32 _IOWR('n', 10, struct ncp_privatedata_ioctl_32) +#define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct ncp_privatedata_ioctl_32) -static int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg) +static int do_ncp_ncprequest(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct ifconf32 ifc32; - struct ifconf ifc; - struct ifreq32 *ifr32; - struct ifreq *ifr; + struct ncp_ioctl_request_32 n32; + struct ncp_ioctl_request n; mm_segment_t old_fs; - unsigned int i, j; int err; - if (copy_from_user(&ifc32, (struct ifconf32 *)arg, sizeof(struct ifconf32))) - return -EFAULT; - - if (ifc32.ifcbuf == 0) { - ifc32.ifc_len = 0; - ifc.ifc_len = 0; - ifc.ifc_buf = NULL; - } else { - ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32)) + 1) * - sizeof (struct ifreq); - ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL); - if (!ifc.ifc_buf) - return -ENOMEM; - } - ifr = ifc.ifc_req; - ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf); - for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) { - if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) { - kfree (ifc.ifc_buf); - return -EFAULT; - } - } - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc); - set_fs (old_fs); - if (!err) { - ifr = ifc.ifc_req; - ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf); - for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len; - i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) { - if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) { - err = -EFAULT; - break; - } - } - if (!err) { - if (ifc32.ifcbuf == 0) { - /* Translate from 64-bit structure multiple to - * a 32-bit one. - */ - i = ifc.ifc_len; - i = ((i / sizeof(struct ifreq)) * sizeof(struct ifreq32)); - ifc32.ifc_len = i; - } else { - if (i <= ifc32.ifc_len) - ifc32.ifc_len = i; - else - ifc32.ifc_len = i - sizeof (struct ifreq32); - } - if (copy_to_user((struct ifconf32 *)arg, &ifc32, sizeof(struct ifconf32))) - err = -EFAULT; - } - } - if (ifc.ifc_buf != NULL) - kfree (ifc.ifc_buf); - return err; -} - -static int ethtool_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ifreq ifr; - mm_segment_t old_fs; - int err, len; - u32 data, ethcmd; - - if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) + if (copy_from_user(&n32, (struct ncp_ioctl_request_32*)arg, + sizeof(n32))) return -EFAULT; - ifr.ifr_data = (__kernel_caddr_t)get_zeroed_page(GFP_KERNEL); - if (!ifr.ifr_data) - return -EAGAIN; - __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); - - if (get_user(ethcmd, (u32 *)A(data))) { - err = -EFAULT; - goto out; - } - switch (ethcmd) { - case ETHTOOL_GDRVINFO: len = sizeof(struct ethtool_drvinfo); break; - case ETHTOOL_GMSGLVL: - case ETHTOOL_SMSGLVL: - case ETHTOOL_GLINK: - case ETHTOOL_NWAY_RST: len = sizeof(struct ethtool_value); break; - case ETHTOOL_GREGS: { - struct ethtool_regs *regaddr = (struct ethtool_regs *)A(data); - /* darned variable size arguments */ - if (get_user(len, (u32 *)®addr->len)) { - err = -EFAULT; - goto out; - } - len += sizeof(struct ethtool_regs); - break; - } - case ETHTOOL_GEEPROM: - case ETHTOOL_SEEPROM: { - struct ethtool_eeprom *promaddr = (struct ethtool_eeprom *)A(data); - /* darned variable size arguments */ - if (get_user(len, (u32 *)&promaddr->len)) { - err = -EFAULT; - goto out; - } - len += sizeof(struct ethtool_eeprom); - break; - } - case ETHTOOL_GSET: - case ETHTOOL_SSET: len = sizeof(struct ethtool_cmd); break; - default: - err = -EOPNOTSUPP; - goto out; - } - - if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) { - err = -EFAULT; + n.function = n32.function; + n.size = n32.size; + if (n.size > 65536) + return -EINVAL; + n.data = vmalloc(65536); /* 65536 must be same as NCP_PACKET_SIZE_INTERNAL in ncpfs */ + if (!n.data) + return -ENOMEM; + err = -EFAULT; + if (copy_from_user(n.data, (void *)A(n32.data), n.size)) goto out; - } - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&ifr); + old_fs = get_fs(); set_fs (KERNEL_DS); + err = sys_ioctl (fd, NCP_IOC_NCPREQUEST, (unsigned long)&n); set_fs (old_fs); - if (!err) { - u32 data; - - __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); - len = copy_to_user((char *)A(data), ifr.ifr_data, len); - if (len) - err = -EFAULT; - } - -out: - free_page((unsigned long)ifr.ifr_data); - return err; -} - -static int bond_ioctl(unsigned long fd, unsigned int cmd, unsigned long arg) -{ - struct ifreq ifr; - mm_segment_t old_fs; - int err, len; - u32 data; - - if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) - return -EFAULT; - ifr.ifr_data = (__kernel_caddr_t)get_zeroed_page(GFP_KERNEL); - if (!ifr.ifr_data) - return -EAGAIN; - - switch (cmd) { - case SIOCBONDENSLAVE: - case SIOCBONDRELEASE: - case SIOCBONDSETHWADDR: - case SIOCBONDCHANGEACTIVE: - len = IFNAMSIZ * sizeof(char); - break; - case SIOCBONDSLAVEINFOQUERY: - len = sizeof(struct ifslave); - break; - case SIOCBONDINFOQUERY: - len = sizeof(struct ifbond); - break; - default: + if(err <= 0) + goto out; + if (err > 65536) { err = -EINVAL; goto out; - }; - - __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); - if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) { + } + if (copy_to_user((void *)A(n32.data), n.data, err)) { err = -EFAULT; goto out; } - - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&ifr); - set_fs (old_fs); - if (!err) { - len = copy_to_user((char *)A(data), ifr.ifr_data, len); - if (len) - err = -EFAULT; - } - -out: - free_page((unsigned long)ifr.ifr_data); + out: + vfree(n.data); return err; } -int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ifreq *u_ifreq64; - struct ifreq32 *u_ifreq32 = (struct ifreq32 *) arg; - char tmp_buf[IFNAMSIZ]; - void __user *data64; - u32 data32; - - if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), - IFNAMSIZ)) - return -EFAULT; - if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) - return -EFAULT; - data64 = (void __user *)A(data32); - - u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64)); - - /* Don't check these user accesses, just let that get trapped - * in the ioctl handler instead. - */ - copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], IFNAMSIZ); - __put_user(data64, &u_ifreq64->ifr_ifru.ifru_data); - - return sys_ioctl(fd, cmd, (unsigned long) u_ifreq64); -} - -static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) +static int do_ncp_getmountuid2(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct ifreq ifr; - mm_segment_t old_fs; + mm_segment_t old_fs = get_fs(); + __kernel_uid_t kuid; int err; - - switch (cmd) { - case SIOCSIFMAP: - err = copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(ifr.ifr_name)); - err |= __get_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start)); - err |= __get_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end)); - err |= __get_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr)); - err |= __get_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq)); - err |= __get_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma)); - err |= __get_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port)); - if (err) - return -EFAULT; - break; - default: - if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) - return -EFAULT; - break; - } - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&ifr); - set_fs (old_fs); - if (!err) { - switch (cmd) { - case SIOCGIFFLAGS: - case SIOCGIFMETRIC: - case SIOCGIFMTU: - case SIOCGIFMEM: - case SIOCGIFHWADDR: - case SIOCGIFINDEX: - case SIOCGIFADDR: - case SIOCGIFBRDADDR: - case SIOCGIFDSTADDR: - case SIOCGIFNETMASK: - case SIOCGIFTXQLEN: - if (copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(struct ifreq32))) - return -EFAULT; - break; - case SIOCGIFMAP: - err = copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(ifr.ifr_name)); - err |= __put_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start)); - err |= __put_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end)); - err |= __put_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr)); - err |= __put_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq)); - err |= __put_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma)); - err |= __put_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port)); - if (err) - err = -EFAULT; - break; - } - } - return err; -} - -struct rtentry32 { - u32 rt_pad1; - struct sockaddr rt_dst; /* target address */ - struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ - struct sockaddr rt_genmask; /* target network mask (IP) */ - unsigned short rt_flags; - short rt_pad2; - u32 rt_pad3; - unsigned char rt_tos; - unsigned char rt_class; - short rt_pad4; - short rt_metric; /* +1 for binary compatibility! */ - /* char * */ u32 rt_dev; /* forcing the device at add */ - u32 rt_mtu; /* per route MTU/Window */ - u32 rt_window; /* Window clamping */ - unsigned short rt_irtt; /* Initial RTT */ - -}; - -struct in6_rtmsg32 { - struct in6_addr rtmsg_dst; - struct in6_addr rtmsg_src; - struct in6_addr rtmsg_gateway; - u32 rtmsg_type; - u16 rtmsg_dst_len; - u16 rtmsg_src_len; - u32 rtmsg_metric; - u32 rtmsg_info; - u32 rtmsg_flags; - s32 rtmsg_ifindex; -}; - -static int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - int ret; - void *r = NULL; - struct in6_rtmsg r6; - struct rtentry r4; - char devname[16]; - u32 rtdev; - mm_segment_t old_fs = get_fs(); - - struct socket *mysock = sockfd_lookup(fd, &ret); - - if (mysock && mysock->sk && mysock->sk->sk_family == AF_INET6) { /* ipv6 */ - ret = copy_from_user (&r6.rtmsg_dst, &(((struct in6_rtmsg32 *)arg)->rtmsg_dst), - 3 * sizeof(struct in6_addr)); - ret |= __get_user (r6.rtmsg_type, &(((struct in6_rtmsg32 *)arg)->rtmsg_type)); - ret |= __get_user (r6.rtmsg_dst_len, &(((struct in6_rtmsg32 *)arg)->rtmsg_dst_len)); - ret |= __get_user (r6.rtmsg_src_len, &(((struct in6_rtmsg32 *)arg)->rtmsg_src_len)); - ret |= __get_user (r6.rtmsg_metric, &(((struct in6_rtmsg32 *)arg)->rtmsg_metric)); - ret |= __get_user (r6.rtmsg_info, &(((struct in6_rtmsg32 *)arg)->rtmsg_info)); - ret |= __get_user (r6.rtmsg_flags, &(((struct in6_rtmsg32 *)arg)->rtmsg_flags)); - ret |= __get_user (r6.rtmsg_ifindex, &(((struct in6_rtmsg32 *)arg)->rtmsg_ifindex)); - - r = (void *) &r6; - } else { /* ipv4 */ - ret = copy_from_user (&r4.rt_dst, &(((struct rtentry32 *)arg)->rt_dst), 3 * sizeof(struct sockaddr)); - ret |= __get_user (r4.rt_flags, &(((struct rtentry32 *)arg)->rt_flags)); - ret |= __get_user (r4.rt_metric, &(((struct rtentry32 *)arg)->rt_metric)); - ret |= __get_user (r4.rt_mtu, &(((struct rtentry32 *)arg)->rt_mtu)); - ret |= __get_user (r4.rt_window, &(((struct rtentry32 *)arg)->rt_window)); - ret |= __get_user (r4.rt_irtt, &(((struct rtentry32 *)arg)->rt_irtt)); - ret |= __get_user (rtdev, &(((struct rtentry32 *)arg)->rt_dev)); - if (rtdev) { - ret |= copy_from_user (devname, (char *)A(rtdev), 15); - r4.rt_dev = devname; devname[15] = 0; - } else - r4.rt_dev = 0; - - r = (void *) &r4; - } - - if (ret) - return -EFAULT; - - set_fs (KERNEL_DS); - ret = sys_ioctl (fd, cmd, (long) r); - set_fs (old_fs); - - if (mysock) - sockfd_put(mysock); - - return ret; -} - -struct hd_geometry32 { - unsigned char heads; - unsigned char sectors; - unsigned short cylinders; - u32 start; -}; - -static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct hd_geometry geo; - int err; - - set_fs (KERNEL_DS); - err = sys_ioctl(fd, HDIO_GETGEO, (unsigned long)&geo); - set_fs (old_fs); - if (!err) { - if (copy_to_user ((struct hd_geometry32 *)arg, &geo, 4) || - __put_user (geo.start, &(((struct hd_geometry32 *)arg)->start))) - err = -EFAULT; - } - return err; -} - -struct hd_big_geometry32 { - unsigned char heads; - unsigned char sectors; - unsigned int cylinders; - u32 start; -}; - -static int hdio_getgeo_big(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct hd_big_geometry geo; - int err; - - set_fs (KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&geo); - set_fs (old_fs); - if (!err) { - struct hd_big_geometry32 *up = (struct hd_big_geometry32 *) arg; - - if (put_user(geo.heads, &up->heads) || - __put_user(geo.sectors, &up->sectors) || - __put_user(geo.cylinders, &up->cylinders) || - __put_user(((u32) geo.start), &up->start)) - err = -EFAULT; - } - return err; -} - -static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - unsigned long kval; - unsigned int *uvp; - int error; - - set_fs(KERNEL_DS); - error = sys_ioctl(fd, cmd, (long)&kval); - set_fs(old_fs); - - if (error == 0) { - uvp = (unsigned int *)arg; - if (put_user(kval, uvp)) - error = -EFAULT; - } - return error; -} - -struct floppy_struct32 { - unsigned int size; - unsigned int sect; - unsigned int head; - unsigned int track; - unsigned int stretch; - unsigned char gap; - unsigned char rate; - unsigned char spec1; - unsigned char fmt_gap; - const compat_caddr_t name; -}; - -struct floppy_drive_params32 { - char cmos; - u32 max_dtr; - u32 hlt; - u32 hut; - u32 srt; - u32 spinup; - u32 spindown; - unsigned char spindown_offset; - unsigned char select_delay; - unsigned char rps; - unsigned char tracks; - u32 timeout; - unsigned char interleave_sect; - struct floppy_max_errors max_errors; - char flags; - char read_track; - short autodetect[8]; - int checkfreq; - int native_format; -}; - -struct floppy_drive_struct32 { - signed char flags; - u32 spinup_date; - u32 select_date; - u32 first_read_date; - short probed_format; - short track; - short maxblock; - short maxtrack; - int generation; - int keep_data; - int fd_ref; - int fd_device; - int last_checked; - compat_caddr_t dmabuf; - int bufblocks; -}; - -struct floppy_fdc_state32 { - int spec1; - int spec2; - int dtr; - unsigned char version; - unsigned char dor; - u32 address; - unsigned int rawcmd:2; - unsigned int reset:1; - unsigned int need_configure:1; - unsigned int perp_mode:2; - unsigned int has_fifo:1; - unsigned int driver_version; - unsigned char track[4]; -}; - -struct floppy_write_errors32 { - unsigned int write_errors; - u32 first_error_sector; - int first_error_generation; - u32 last_error_sector; - int last_error_generation; - unsigned int badness; -}; - -#define FDSETPRM32 _IOW(2, 0x42, struct floppy_struct32) -#define FDDEFPRM32 _IOW(2, 0x43, struct floppy_struct32) -#define FDGETPRM32 _IOR(2, 0x04, struct floppy_struct32) -#define FDSETDRVPRM32 _IOW(2, 0x90, struct floppy_drive_params32) -#define FDGETDRVPRM32 _IOR(2, 0x11, struct floppy_drive_params32) -#define FDGETDRVSTAT32 _IOR(2, 0x12, struct floppy_drive_struct32) -#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct floppy_drive_struct32) -#define FDGETFDCSTAT32 _IOR(2, 0x15, struct floppy_fdc_state32) -#define FDWERRORGET32 _IOR(2, 0x17, struct floppy_write_errors32) - -static struct { - unsigned int cmd32; - unsigned int cmd; -} fd_ioctl_trans_table[] = { - { FDSETPRM32, FDSETPRM }, - { FDDEFPRM32, FDDEFPRM }, - { FDGETPRM32, FDGETPRM }, - { FDSETDRVPRM32, FDSETDRVPRM }, - { FDGETDRVPRM32, FDGETDRVPRM }, - { FDGETDRVSTAT32, FDGETDRVSTAT }, - { FDPOLLDRVSTAT32, FDPOLLDRVSTAT }, - { FDGETFDCSTAT32, FDGETFDCSTAT }, - { FDWERRORGET32, FDWERRORGET } -}; - -#define NR_FD_IOCTL_TRANS (sizeof(fd_ioctl_trans_table)/sizeof(fd_ioctl_trans_table[0])) - -static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - void *karg = NULL; - unsigned int kcmd = 0; - int i, err; - - for (i = 0; i < NR_FD_IOCTL_TRANS; i++) - if (cmd == fd_ioctl_trans_table[i].cmd32) { - kcmd = fd_ioctl_trans_table[i].cmd; - break; - } - if (!kcmd) - return -EINVAL; - - switch (cmd) { - case FDSETPRM32: - case FDDEFPRM32: - case FDGETPRM32: - { - struct floppy_struct *f; - - f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL); - if (!karg) - return -ENOMEM; - if (cmd == FDGETPRM32) - break; - err = __get_user(f->size, &((struct floppy_struct32 *)arg)->size); - err |= __get_user(f->sect, &((struct floppy_struct32 *)arg)->sect); - err |= __get_user(f->head, &((struct floppy_struct32 *)arg)->head); - err |= __get_user(f->track, &((struct floppy_struct32 *)arg)->track); - err |= __get_user(f->stretch, &((struct floppy_struct32 *)arg)->stretch); - err |= __get_user(f->gap, &((struct floppy_struct32 *)arg)->gap); - err |= __get_user(f->rate, &((struct floppy_struct32 *)arg)->rate); - err |= __get_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1); - err |= __get_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap); - err |= __get_user((u64)f->name, &((struct floppy_struct32 *)arg)->name); - if (err) { - err = -EFAULT; - goto out; - } - break; - } - case FDSETDRVPRM32: - case FDGETDRVPRM32: - { - struct floppy_drive_params *f; - - f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL); - if (!karg) - return -ENOMEM; - if (cmd == FDGETDRVPRM32) - break; - err = __get_user(f->cmos, &((struct floppy_drive_params32 *)arg)->cmos); - err |= __get_user(f->max_dtr, &((struct floppy_drive_params32 *)arg)->max_dtr); - err |= __get_user(f->hlt, &((struct floppy_drive_params32 *)arg)->hlt); - err |= __get_user(f->hut, &((struct floppy_drive_params32 *)arg)->hut); - err |= __get_user(f->srt, &((struct floppy_drive_params32 *)arg)->srt); - err |= __get_user(f->spinup, &((struct floppy_drive_params32 *)arg)->spinup); - err |= __get_user(f->spindown, &((struct floppy_drive_params32 *)arg)->spindown); - err |= __get_user(f->spindown_offset, &((struct floppy_drive_params32 *)arg)->spindown_offset); - err |= __get_user(f->select_delay, &((struct floppy_drive_params32 *)arg)->select_delay); - err |= __get_user(f->rps, &((struct floppy_drive_params32 *)arg)->rps); - err |= __get_user(f->tracks, &((struct floppy_drive_params32 *)arg)->tracks); - err |= __get_user(f->timeout, &((struct floppy_drive_params32 *)arg)->timeout); - err |= __get_user(f->interleave_sect, &((struct floppy_drive_params32 *)arg)->interleave_sect); - err |= __copy_from_user(&f->max_errors, &((struct floppy_drive_params32 *)arg)->max_errors, sizeof(f->max_errors)); - err |= __get_user(f->flags, &((struct floppy_drive_params32 *)arg)->flags); - err |= __get_user(f->read_track, &((struct floppy_drive_params32 *)arg)->read_track); - err |= __copy_from_user(f->autodetect, ((struct floppy_drive_params32 *)arg)->autodetect, sizeof(f->autodetect)); - err |= __get_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq); - err |= __get_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format); - if (err) { - err = -EFAULT; - goto out; - } - break; - } - case FDGETDRVSTAT32: - case FDPOLLDRVSTAT32: - karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL); - if (!karg) - return -ENOMEM; - break; - case FDGETFDCSTAT32: - karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL); - if (!karg) - return -ENOMEM; - break; - case FDWERRORGET32: - karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL); - if (!karg) - return -ENOMEM; - break; - default: - return -EINVAL; - } - set_fs (KERNEL_DS); - err = sys_ioctl (fd, kcmd, (unsigned long)karg); - set_fs (old_fs); - if (err) - goto out; - switch (cmd) { - case FDGETPRM32: - { - struct floppy_struct *f = karg; - - err = __put_user(f->size, &((struct floppy_struct32 *)arg)->size); - err |= __put_user(f->sect, &((struct floppy_struct32 *)arg)->sect); - err |= __put_user(f->head, &((struct floppy_struct32 *)arg)->head); - err |= __put_user(f->track, &((struct floppy_struct32 *)arg)->track); - err |= __put_user(f->stretch, &((struct floppy_struct32 *)arg)->stretch); - err |= __put_user(f->gap, &((struct floppy_struct32 *)arg)->gap); - err |= __put_user(f->rate, &((struct floppy_struct32 *)arg)->rate); - err |= __put_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1); - err |= __put_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap); - err |= __put_user((u64)f->name, &((struct floppy_struct32 *)arg)->name); - break; - } - case FDGETDRVPRM32: - { - struct floppy_drive_params *f = karg; - - err = __put_user(f->cmos, &((struct floppy_drive_params32 *)arg)->cmos); - err |= __put_user(f->max_dtr, &((struct floppy_drive_params32 *)arg)->max_dtr); - err |= __put_user(f->hlt, &((struct floppy_drive_params32 *)arg)->hlt); - err |= __put_user(f->hut, &((struct floppy_drive_params32 *)arg)->hut); - err |= __put_user(f->srt, &((struct floppy_drive_params32 *)arg)->srt); - err |= __put_user(f->spinup, &((struct floppy_drive_params32 *)arg)->spinup); - err |= __put_user(f->spindown, &((struct floppy_drive_params32 *)arg)->spindown); - err |= __put_user(f->spindown_offset, &((struct floppy_drive_params32 *)arg)->spindown_offset); - err |= __put_user(f->select_delay, &((struct floppy_drive_params32 *)arg)->select_delay); - err |= __put_user(f->rps, &((struct floppy_drive_params32 *)arg)->rps); - err |= __put_user(f->tracks, &((struct floppy_drive_params32 *)arg)->tracks); - err |= __put_user(f->timeout, &((struct floppy_drive_params32 *)arg)->timeout); - err |= __put_user(f->interleave_sect, &((struct floppy_drive_params32 *)arg)->interleave_sect); - err |= __copy_to_user(&((struct floppy_drive_params32 *)arg)->max_errors, &f->max_errors, sizeof(f->max_errors)); - err |= __put_user(f->flags, &((struct floppy_drive_params32 *)arg)->flags); - err |= __put_user(f->read_track, &((struct floppy_drive_params32 *)arg)->read_track); - err |= __copy_to_user(((struct floppy_drive_params32 *)arg)->autodetect, f->autodetect, sizeof(f->autodetect)); - err |= __put_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq); - err |= __put_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format); - break; - } - case FDGETDRVSTAT32: - case FDPOLLDRVSTAT32: - { - struct floppy_drive_struct *f = karg; - - err = __put_user(f->flags, &((struct floppy_drive_struct32 *)arg)->flags); - err |= __put_user(f->spinup_date, &((struct floppy_drive_struct32 *)arg)->spinup_date); - err |= __put_user(f->select_date, &((struct floppy_drive_struct32 *)arg)->select_date); - err |= __put_user(f->first_read_date, &((struct floppy_drive_struct32 *)arg)->first_read_date); - err |= __put_user(f->probed_format, &((struct floppy_drive_struct32 *)arg)->probed_format); - err |= __put_user(f->track, &((struct floppy_drive_struct32 *)arg)->track); - err |= __put_user(f->maxblock, &((struct floppy_drive_struct32 *)arg)->maxblock); - err |= __put_user(f->maxtrack, &((struct floppy_drive_struct32 *)arg)->maxtrack); - err |= __put_user(f->generation, &((struct floppy_drive_struct32 *)arg)->generation); - err |= __put_user(f->keep_data, &((struct floppy_drive_struct32 *)arg)->keep_data); - err |= __put_user(f->fd_ref, &((struct floppy_drive_struct32 *)arg)->fd_ref); - err |= __put_user(f->fd_device, &((struct floppy_drive_struct32 *)arg)->fd_device); - err |= __put_user(f->last_checked, &((struct floppy_drive_struct32 *)arg)->last_checked); - err |= __put_user((u64)f->dmabuf, &((struct floppy_drive_struct32 *)arg)->dmabuf); - err |= __put_user((u64)f->bufblocks, &((struct floppy_drive_struct32 *)arg)->bufblocks); - break; - } - case FDGETFDCSTAT32: - { - struct floppy_fdc_state *f = karg; - - err = __put_user(f->spec1, &((struct floppy_fdc_state32 *)arg)->spec1); - err |= __put_user(f->spec2, &((struct floppy_fdc_state32 *)arg)->spec2); - err |= __put_user(f->dtr, &((struct floppy_fdc_state32 *)arg)->dtr); - err |= __put_user(f->version, &((struct floppy_fdc_state32 *)arg)->version); - err |= __put_user(f->dor, &((struct floppy_fdc_state32 *)arg)->dor); - err |= __put_user(f->address, &((struct floppy_fdc_state32 *)arg)->address); - err |= __copy_to_user((char *)&((struct floppy_fdc_state32 *)arg)->address - + sizeof(((struct floppy_fdc_state32 *)arg)->address), - (char *)&f->address + sizeof(f->address), sizeof(int)); - err |= __put_user(f->driver_version, &((struct floppy_fdc_state32 *)arg)->driver_version); - err |= __copy_to_user(((struct floppy_fdc_state32 *)arg)->track, f->track, sizeof(f->track)); - break; - } - case FDWERRORGET32: - { - struct floppy_write_errors *f = karg; - - err = __put_user(f->write_errors, &((struct floppy_write_errors32 *)arg)->write_errors); - err |= __put_user(f->first_error_sector, &((struct floppy_write_errors32 *)arg)->first_error_sector); - err |= __put_user(f->first_error_generation, &((struct floppy_write_errors32 *)arg)->first_error_generation); - err |= __put_user(f->last_error_sector, &((struct floppy_write_errors32 *)arg)->last_error_sector); - err |= __put_user(f->last_error_generation, &((struct floppy_write_errors32 *)arg)->last_error_generation); - err |= __put_user(f->badness, &((struct floppy_write_errors32 *)arg)->badness); - break; - } - default: - break; - } - if (err) - err = -EFAULT; - -out: if (karg) kfree(karg); - return err; -} - -typedef struct sg_io_hdr32 { - s32 interface_id; /* [i] 'S' for SCSI generic (required) */ - s32 dxfer_direction; /* [i] data transfer direction */ - u8 cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ - u8 mx_sb_len; /* [i] max length to write to sbp */ - u16 iovec_count; /* [i] 0 implies no scatter gather */ - u32 dxfer_len; /* [i] byte count of data transfer */ - u32 dxferp; /* [i], [*io] points to data transfer memory - or scatter gather list */ - u32 cmdp; /* [i], [*i] points to command to perform */ - u32 sbp; /* [i], [*o] points to sense_buffer memory */ - u32 timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ - u32 flags; /* [i] 0 -> default, see SG_FLAG... */ - s32 pack_id; /* [i->o] unused internally (normally) */ - u32 usr_ptr; /* [i->o] unused internally */ - u8 status; /* [o] scsi status */ - u8 masked_status; /* [o] shifted, masked scsi status */ - u8 msg_status; /* [o] messaging level data (optional) */ - u8 sb_len_wr; /* [o] byte count actually written to sbp */ - u16 host_status; /* [o] errors from host adapter */ - u16 driver_status; /* [o] errors from software driver */ - s32 resid; /* [o] dxfer_len - actual_transferred */ - u32 duration; /* [o] time taken by cmd (unit: millisec) */ - u32 info; /* [o] auxiliary information */ -} sg_io_hdr32_t; /* 64 bytes long (on sparc32) */ - -typedef struct sg_iovec32 { - u32 iov_base; - u32 iov_len; -} sg_iovec32_t; - -static int alloc_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32) -{ - sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32); - sg_iovec_t *kiov; - int i; - - sgp->dxferp = kmalloc(sgp->iovec_count * - sizeof(sg_iovec_t), GFP_KERNEL); - if (!sgp->dxferp) - return -ENOMEM; - memset(sgp->dxferp, 0, - sgp->iovec_count * sizeof(sg_iovec_t)); - - kiov = (sg_iovec_t *) sgp->dxferp; - for (i = 0; i < sgp->iovec_count; i++) { - u32 iov_base32; - if (__get_user(iov_base32, &uiov->iov_base) || - __get_user(kiov->iov_len, &uiov->iov_len)) - return -EFAULT; - - kiov->iov_base = kmalloc(kiov->iov_len, GFP_KERNEL); - if (!kiov->iov_base) - return -ENOMEM; - if (copy_from_user(kiov->iov_base, - (void *) A(iov_base32), - kiov->iov_len)) - return -EFAULT; - - uiov++; - kiov++; - } - - return 0; -} - -static int copy_back_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32) -{ - sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32); - sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; - int i; - - for (i = 0; i < sgp->iovec_count; i++) { - u32 iov_base32; - - if (__get_user(iov_base32, &uiov->iov_base)) - return -EFAULT; - - if (copy_to_user((void *) A(iov_base32), - kiov->iov_base, - kiov->iov_len)) - return -EFAULT; - - uiov++; - kiov++; - } - - return 0; -} - -static void free_sg_iovec(sg_io_hdr_t *sgp) -{ - sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; - int i; - - for (i = 0; i < sgp->iovec_count; i++) { - if (kiov->iov_base) { - kfree(kiov->iov_base); - kiov->iov_base = NULL; - } - kiov++; - } - kfree(sgp->dxferp); - sgp->dxferp = NULL; -} - -static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - sg_io_hdr32_t *sg_io32; - sg_io_hdr_t sg_io64; - u32 dxferp32, cmdp32, sbp32; - mm_segment_t old_fs; - int err = 0; - - sg_io32 = (sg_io_hdr32_t *)arg; - err = __get_user(sg_io64.interface_id, &sg_io32->interface_id); - err |= __get_user(sg_io64.dxfer_direction, &sg_io32->dxfer_direction); - err |= __get_user(sg_io64.cmd_len, &sg_io32->cmd_len); - err |= __get_user(sg_io64.mx_sb_len, &sg_io32->mx_sb_len); - err |= __get_user(sg_io64.iovec_count, &sg_io32->iovec_count); - err |= __get_user(sg_io64.dxfer_len, &sg_io32->dxfer_len); - err |= __get_user(sg_io64.timeout, &sg_io32->timeout); - err |= __get_user(sg_io64.flags, &sg_io32->flags); - err |= __get_user(sg_io64.pack_id, &sg_io32->pack_id); - - sg_io64.dxferp = NULL; - sg_io64.cmdp = NULL; - sg_io64.sbp = NULL; - - err |= __get_user(cmdp32, &sg_io32->cmdp); - sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL); - if (!sg_io64.cmdp) { - err = -ENOMEM; - goto out; - } - if (copy_from_user(sg_io64.cmdp, - (void *) A(cmdp32), - sg_io64.cmd_len)) { - err = -EFAULT; - goto out; - } - - err |= __get_user(sbp32, &sg_io32->sbp); - sg_io64.sbp = kmalloc(sg_io64.mx_sb_len, GFP_KERNEL); - if (!sg_io64.sbp) { - err = -ENOMEM; - goto out; - } - if (copy_from_user(sg_io64.sbp, - (void *) A(sbp32), - sg_io64.mx_sb_len)) { - err = -EFAULT; - goto out; - } - - err |= __get_user(dxferp32, &sg_io32->dxferp); - if (sg_io64.iovec_count) { - int ret; - - if ((ret = alloc_sg_iovec(&sg_io64, dxferp32))) { - err = ret; - goto out; - } - } else { - sg_io64.dxferp = kmalloc(sg_io64.dxfer_len, GFP_KERNEL); - if (!sg_io64.dxferp) { - err = -ENOMEM; - goto out; - } - if (copy_from_user(sg_io64.dxferp, - (void *) A(dxferp32), - sg_io64.dxfer_len)) { - err = -EFAULT; - goto out; - } - } - - /* Unused internally, do not even bother to copy it over. */ - sg_io64.usr_ptr = NULL; - - if (err) - return -EFAULT; - - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long) &sg_io64); - set_fs (old_fs); - - if (err < 0) - goto out; - - err = __put_user(sg_io64.pack_id, &sg_io32->pack_id); - err |= __put_user(sg_io64.status, &sg_io32->status); - err |= __put_user(sg_io64.masked_status, &sg_io32->masked_status); - err |= __put_user(sg_io64.msg_status, &sg_io32->msg_status); - err |= __put_user(sg_io64.sb_len_wr, &sg_io32->sb_len_wr); - err |= __put_user(sg_io64.host_status, &sg_io32->host_status); - err |= __put_user(sg_io64.driver_status, &sg_io32->driver_status); - err |= __put_user(sg_io64.resid, &sg_io32->resid); - err |= __put_user(sg_io64.duration, &sg_io32->duration); - err |= __put_user(sg_io64.info, &sg_io32->info); - err |= copy_to_user((void *)A(sbp32), sg_io64.sbp, sg_io64.mx_sb_len); - if (sg_io64.dxferp) { - if (sg_io64.iovec_count) - err |= copy_back_sg_iovec(&sg_io64, dxferp32); - else - err |= copy_to_user((void *)A(dxferp32), - sg_io64.dxferp, - sg_io64.dxfer_len); - } - if (err) - err = -EFAULT; - -out: - if (sg_io64.cmdp) - kfree(sg_io64.cmdp); - if (sg_io64.sbp) - kfree(sg_io64.sbp); - if (sg_io64.dxferp) { - if (sg_io64.iovec_count) { - free_sg_iovec(&sg_io64); - } else { - kfree(sg_io64.dxferp); - } - } - return err; -} - -struct ppp_option_data32 { - compat_caddr_t ptr; - __u32 length; - int transmit; -}; -#define PPPIOCSCOMPRESS32 _IOW('t', 77, struct ppp_option_data32) - -struct ppp_idle32 { - compat_time_t xmit_idle; - compat_time_t recv_idle; -}; -#define PPPIOCGIDLE32 _IOR('t', 63, struct ppp_idle32) - -static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct ppp_option_data32 data32; - struct ppp_option_data data; - struct ppp_idle32 idle32; - struct ppp_idle idle; - unsigned int kcmd; - void *karg; - int err = 0; - - switch (cmd) { - case PPPIOCGIDLE32: - kcmd = PPPIOCGIDLE; - karg = &idle; - break; - case PPPIOCSCOMPRESS32: - if (copy_from_user(&data32, (struct ppp_option_data32 *)arg, sizeof(struct ppp_option_data32))) - return -EFAULT; - data.ptr = kmalloc (data32.length, GFP_KERNEL); - if (!data.ptr) - return -ENOMEM; - if (copy_from_user(data.ptr, (__u8 *)A(data32.ptr), data32.length)) { - kfree(data.ptr); - return -EFAULT; - } - data.length = data32.length; - data.transmit = data32.transmit; - kcmd = PPPIOCSCOMPRESS; - karg = &data; - break; - default: - do { - static int count = 0; - if (++count <= 20) - printk("ppp_ioctl: Unknown cmd fd(%d) " - "cmd(%08x) arg(%08x)\n", - (int)fd, (unsigned int)cmd, (unsigned int)arg); - } while (0); - return -EINVAL; - } - set_fs (KERNEL_DS); - err = sys_ioctl (fd, kcmd, (unsigned long)karg); - set_fs (old_fs); - switch (cmd) { - case PPPIOCGIDLE32: - if (err) - return err; - idle32.xmit_idle = idle.xmit_idle; - idle32.recv_idle = idle.recv_idle; - if (copy_to_user((struct ppp_idle32 *)arg, &idle32, sizeof(struct ppp_idle32))) - return -EFAULT; - break; - case PPPIOCSCOMPRESS32: - kfree(data.ptr); - break; - default: - break; - } - return err; -} - - -struct mtget32 { - __u32 mt_type; - __u32 mt_resid; - __u32 mt_dsreg; - __u32 mt_gstat; - __u32 mt_erreg; - compat_daddr_t mt_fileno; - compat_daddr_t mt_blkno; -}; -#define MTIOCGET32 _IOR('m', 2, struct mtget32) - -struct mtpos32 { - __u32 mt_blkno; -}; -#define MTIOCPOS32 _IOR('m', 3, struct mtpos32) - -struct mtconfiginfo32 { - __u32 mt_type; - __u32 ifc_type; - __u16 irqnr; - __u16 dmanr; - __u16 port; - __u32 debug; - __u32 have_dens:1; - __u32 have_bsf:1; - __u32 have_fsr:1; - __u32 have_bsr:1; - __u32 have_eod:1; - __u32 have_seek:1; - __u32 have_tell:1; - __u32 have_ras1:1; - __u32 have_ras2:1; - __u32 have_ras3:1; - __u32 have_qfa:1; - __u32 pad1:5; - char reserved[10]; -}; -#define MTIOCGETCONFIG32 _IOR('m', 4, struct mtconfiginfo32) -#define MTIOCSETCONFIG32 _IOW('m', 5, struct mtconfiginfo32) - -static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct mtconfiginfo info; - struct mtget get; - struct mtpos pos; - unsigned long kcmd; - void *karg; - int err = 0; - - switch(cmd) { - case MTIOCPOS32: - kcmd = MTIOCPOS; - karg = &pos; - break; - case MTIOCGET32: - kcmd = MTIOCGET; - karg = &get; - break; - case MTIOCGETCONFIG32: - kcmd = MTIOCGETCONFIG; - karg = &info; - break; - case MTIOCSETCONFIG32: - kcmd = MTIOCSETCONFIG; - karg = &info; - err = __get_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type); - err |= __get_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type); - err |= __get_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr); - err |= __get_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr); - err |= __get_user(info.port, &((struct mtconfiginfo32 *)arg)->port); - err |= __get_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug); - err |= __copy_from_user((char *)&info.debug + sizeof(info.debug), - (char *)&((struct mtconfiginfo32 *)arg)->debug - + sizeof(((struct mtconfiginfo32 *)arg)->debug), sizeof(__u32)); - if (err) - return -EFAULT; - break; - default: - do { - static int count = 0; - if (++count <= 20) - printk("mt_ioctl: Unknown cmd fd(%d) " - "cmd(%08x) arg(%08x)\n", - (int)fd, (unsigned int)cmd, (unsigned int)arg); - } while (0); - return -EINVAL; - } - set_fs (KERNEL_DS); - err = sys_ioctl (fd, kcmd, (unsigned long)karg); - set_fs (old_fs); - if (err) - return err; - switch (cmd) { - case MTIOCPOS32: - err = __put_user(pos.mt_blkno, &((struct mtpos32 *)arg)->mt_blkno); - break; - case MTIOCGET32: - err = __put_user(get.mt_type, &((struct mtget32 *)arg)->mt_type); - err |= __put_user(get.mt_resid, &((struct mtget32 *)arg)->mt_resid); - err |= __put_user(get.mt_dsreg, &((struct mtget32 *)arg)->mt_dsreg); - err |= __put_user(get.mt_gstat, &((struct mtget32 *)arg)->mt_gstat); - err |= __put_user(get.mt_erreg, &((struct mtget32 *)arg)->mt_erreg); - err |= __put_user(get.mt_fileno, &((struct mtget32 *)arg)->mt_fileno); - err |= __put_user(get.mt_blkno, &((struct mtget32 *)arg)->mt_blkno); - break; - case MTIOCGETCONFIG32: - err = __put_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type); - err |= __put_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type); - err |= __put_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr); - err |= __put_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr); - err |= __put_user(info.port, &((struct mtconfiginfo32 *)arg)->port); - err |= __put_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug); - err |= __copy_to_user((char *)&((struct mtconfiginfo32 *)arg)->debug - + sizeof(((struct mtconfiginfo32 *)arg)->debug), - (char *)&info.debug + sizeof(info.debug), sizeof(__u32)); - break; - case MTIOCSETCONFIG32: - break; - } - return err ? -EFAULT: 0; -} - -struct cdrom_read32 { - int cdread_lba; - compat_caddr_t cdread_bufaddr; - int cdread_buflen; -}; - -struct cdrom_read_audio32 { - union cdrom_addr addr; - u_char addr_format; - int nframes; - compat_caddr_t buf; -}; - -struct cdrom_generic_command32 { - unsigned char cmd[CDROM_PACKET_SIZE]; - compat_caddr_t buffer; - unsigned int buflen; - int stat; - compat_caddr_t sense; - compat_caddr_t reserved[3]; -}; - -static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct cdrom_read cdread; - struct cdrom_read_audio cdreadaudio; - struct cdrom_generic_command cgc; - compat_caddr_t addr; - char *data = 0; - void *karg; - int err = 0; - - switch(cmd) { - case CDROMREADMODE2: - case CDROMREADMODE1: - case CDROMREADRAW: - case CDROMREADCOOKED: - karg = &cdread; - err = __get_user(cdread.cdread_lba, &((struct cdrom_read32 *)arg)->cdread_lba); - err |= __get_user(addr, &((struct cdrom_read32 *)arg)->cdread_bufaddr); - err |= __get_user(cdread.cdread_buflen, &((struct cdrom_read32 *)arg)->cdread_buflen); - if (err) - return -EFAULT; - data = kmalloc(cdread.cdread_buflen, GFP_KERNEL); - if (!data) - return -ENOMEM; - cdread.cdread_bufaddr = data; - break; - case CDROMREADAUDIO: - karg = &cdreadaudio; - err = copy_from_user(&cdreadaudio.addr, &((struct cdrom_read_audio32 *)arg)->addr, sizeof(cdreadaudio.addr)); - err |= __get_user(cdreadaudio.addr_format, &((struct cdrom_read_audio32 *)arg)->addr_format); - err |= __get_user(cdreadaudio.nframes, &((struct cdrom_read_audio32 *)arg)->nframes); - err |= __get_user(addr, &((struct cdrom_read_audio32 *)arg)->buf); - if (err) - return -EFAULT; - data = kmalloc(cdreadaudio.nframes * 2352, GFP_KERNEL); - if (!data) - return -ENOMEM; - cdreadaudio.buf = data; - break; - case CDROM_SEND_PACKET: - karg = &cgc; - err = copy_from_user(cgc.cmd, &((struct cdrom_generic_command32 *)arg)->cmd, sizeof(cgc.cmd)); - err |= __get_user(addr, &((struct cdrom_generic_command32 *)arg)->buffer); - err |= __get_user(cgc.buflen, &((struct cdrom_generic_command32 *)arg)->buflen); - if (err) - return -EFAULT; - if ((data = kmalloc(cgc.buflen, GFP_KERNEL)) == NULL) - return -ENOMEM; - cgc.buffer = data; - break; - default: - do { - static int count = 0; - if (++count <= 20) - printk("cdrom_ioctl: Unknown cmd fd(%d) " - "cmd(%08x) arg(%08x)\n", - (int)fd, (unsigned int)cmd, (unsigned int)arg); - } while (0); - return -EINVAL; - } - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)karg); - set_fs (old_fs); - if (err) - goto out; - switch (cmd) { - case CDROMREADMODE2: - case CDROMREADMODE1: - case CDROMREADRAW: - case CDROMREADCOOKED: - err = copy_to_user((char *)A(addr), data, cdread.cdread_buflen); - break; - case CDROMREADAUDIO: - err = copy_to_user((char *)A(addr), data, cdreadaudio.nframes * 2352); - break; - case CDROM_SEND_PACKET: - err = copy_to_user((char *)A(addr), data, cgc.buflen); - break; - default: - break; - } -out: if (data) - kfree(data); - return err ? -EFAULT : 0; -} - -struct loop_info32 { - int lo_number; /* ioctl r/o */ - compat_dev_t lo_device; /* ioctl r/o */ - unsigned int lo_inode; /* ioctl r/o */ - compat_dev_t lo_rdevice; /* ioctl r/o */ - int lo_offset; - int lo_encrypt_type; - int lo_encrypt_key_size; /* ioctl w/o */ - int lo_flags; /* ioctl r/o */ - char lo_name[LO_NAME_SIZE]; - unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ - unsigned int lo_init[2]; - char reserved[4]; -}; - -static int loop_status(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct loop_info l; - int err = -EINVAL; - - switch(cmd) { - case LOOP_SET_STATUS: - err = get_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number); - err |= __get_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device); - err |= __get_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode); - err |= __get_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice); - err |= __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)arg)->lo_offset, - 8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset); - if (err) { - err = -EFAULT; - } else { - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&l); - set_fs (old_fs); - } - break; - case LOOP_GET_STATUS: - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&l); - set_fs (old_fs); - if (!err) { - err = put_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number); - err |= __put_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device); - err |= __put_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode); - err |= __put_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice); - err |= __copy_to_user((char *)&((struct loop_info32 *)arg)->lo_offset, - (char *)&l.lo_offset, (unsigned long)l.lo_init - (unsigned long)&l.lo_offset); - if (err) - err = -EFAULT; - } - break; - default: { - static int count = 0; - if (++count <= 20) - printk("%s: Unknown loop ioctl cmd, fd(%d) " - "cmd(%08x) arg(%08lx)\n", - __FUNCTION__, fd, cmd, arg); - } - } - return err; -} - -extern int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); - -#ifdef CONFIG_VT -static int vt_check(struct file *file) -{ - struct tty_struct *tty; - struct inode *inode = file->f_dentry->d_inode; - - if (file->f_op->ioctl != tty_ioctl) - return -EINVAL; - - tty = (struct tty_struct *)file->private_data; - if (tty_paranoia_check(tty, inode->i_rdev, "tty_ioctl")) - return -EINVAL; - - if (tty->driver->ioctl != vt_ioctl) - return -EINVAL; - - /* - * To have permissions to do most of the vt ioctls, we either have - * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. - */ - if (current->tty == tty || capable(CAP_SYS_TTY_CONFIG)) - return 1; - return 0; -} - -struct consolefontdesc32 { - unsigned short charcount; /* characters in font (256 or 512) */ - unsigned short charheight; /* scan lines per character (1-32) */ - u32 chardata; /* font data in expanded form */ -}; - -static int do_fontx_ioctl(unsigned int fd, int cmd, struct consolefontdesc32 *user_cfd, struct file *file) -{ - struct consolefontdesc cfdarg; - struct console_font_op op; - int i, perm; - - perm = vt_check(file); - if (perm < 0) return perm; - - if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc32))) - return -EFAULT; - - cfdarg.chardata = (unsigned char *)A(((struct consolefontdesc32 *)&cfdarg)->chardata); - - switch (cmd) { - case PIO_FONTX: - if (!perm) - return -EPERM; - op.op = KD_FONT_OP_SET; - op.flags = 0; - op.width = 8; - op.height = cfdarg.charheight; - op.charcount = cfdarg.charcount; - op.data = cfdarg.chardata; - return con_font_op(fg_console, &op); - case GIO_FONTX: - if (!cfdarg.chardata) - return 0; - op.op = KD_FONT_OP_GET; - op.flags = 0; - op.width = 8; - op.height = cfdarg.charheight; - op.charcount = cfdarg.charcount; - op.data = cfdarg.chardata; - i = con_font_op(fg_console, &op); - if (i) - return i; - cfdarg.charheight = op.height; - cfdarg.charcount = op.charcount; - ((struct consolefontdesc32 *)&cfdarg)->chardata = (unsigned long)cfdarg.chardata; - if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc32))) - return -EFAULT; - return 0; - } - return -EINVAL; -} - -struct console_font_op32 { - unsigned int op; /* operation code KD_FONT_OP_* */ - unsigned int flags; /* KD_FONT_FLAG_* */ - unsigned int width, height; /* font size */ - unsigned int charcount; - u32 data; /* font data with height fixed to 32 */ -}; - -static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, struct console_font_op32 *fontop, struct file *file) -{ - struct console_font_op op; - int perm = vt_check(file), i; - struct vt_struct *vt; - - if (perm < 0) return perm; - - if (copy_from_user(&op, (void *) fontop, sizeof(struct console_font_op32))) - return -EFAULT; - if (!perm && op.op != KD_FONT_OP_GET) - return -EPERM; - op.data = (unsigned char *)A(((struct console_font_op32 *)&op)->data); - op.flags |= KD_FONT_FLAG_OLD; - vt = (struct vt_struct *)((struct tty_struct *)file->private_data)->driver_data; - i = con_font_op(vt->vc_num, &op); - if (i) return i; - ((struct console_font_op32 *)&op)->data = (unsigned long)op.data; - if (copy_to_user((void *) fontop, &op, sizeof(struct console_font_op32))) - return -EFAULT; - return 0; -} - -struct fb_fix_screeninfo32 { - char id[16]; /* identification string eg "TT Builtin" */ - unsigned int smem_start; /* Start of frame buffer mem */ - /* (physical address) */ - __u32 smem_len; /* Length of frame buffer mem */ - __u32 type; /* see FB_TYPE_* */ - __u32 type_aux; /* Interleave for interleaved Planes */ - __u32 visual; /* see FB_VISUAL_* */ - __u16 xpanstep; /* zero if no hardware panning */ - __u16 ypanstep; /* zero if no hardware panning */ - __u16 ywrapstep; /* zero if no hardware ywrap */ - __u32 line_length; /* length of a line in bytes */ - unsigned int mmio_start; /* Start of Memory Mapped I/O */ - /* (physical address) */ - __u32 mmio_len; /* Length of Memory Mapped I/O */ - __u32 accel; /* Type of acceleration available */ - __u16 reserved[3]; /* Reserved for future compatibility */ -}; - -static int do_fbioget_fscreeninfo_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct fb_fix_screeninfo fix; - int err; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (long)&fix); - set_fs(old_fs); - - if (err == 0) { - unsigned int smem_start = fix.smem_start; /* lose top 32 bits */ - unsigned int mmio_start = fix.mmio_start; /* lose top 32 bits */ - int i; - - err = put_user(fix.id[0], &((struct fb_fix_screeninfo32 *)arg)->id[0]); - for (i=1; i<16; i++) { - err |= __put_user(fix.id[i], &((struct fb_fix_screeninfo32 *)arg)->id[i]); - } - err |= __put_user(smem_start, &((struct fb_fix_screeninfo32 *)arg)->smem_start); - err |= __put_user(fix.smem_len, &((struct fb_fix_screeninfo32 *)arg)->smem_len); - err |= __put_user(fix.type, &((struct fb_fix_screeninfo32 *)arg)->type); - err |= __put_user(fix.type_aux, &((struct fb_fix_screeninfo32 *)arg)->type_aux); - err |= __put_user(fix.visual, &((struct fb_fix_screeninfo32 *)arg)->visual); - err |= __put_user(fix.xpanstep, &((struct fb_fix_screeninfo32 *)arg)->xpanstep); - err |= __put_user(fix.ypanstep, &((struct fb_fix_screeninfo32 *)arg)->ypanstep); - err |= __put_user(fix.ywrapstep, &((struct fb_fix_screeninfo32 *)arg)->ywrapstep); - err |= __put_user(fix.line_length, &((struct fb_fix_screeninfo32 *)arg)->line_length); - err |= __put_user(mmio_start, &((struct fb_fix_screeninfo32 *)arg)->mmio_start); - err |= __put_user(fix.mmio_len, &((struct fb_fix_screeninfo32 *)arg)->mmio_len); - err |= __put_user(fix.accel, &((struct fb_fix_screeninfo32 *)arg)->accel); - err |= __put_user(fix.reserved[0], &((struct fb_fix_screeninfo32 *)arg)->reserved[0]); - err |= __put_user(fix.reserved[1], &((struct fb_fix_screeninfo32 *)arg)->reserved[1]); - err |= __put_user(fix.reserved[2], &((struct fb_fix_screeninfo32 *)arg)->reserved[2]); - if (err) - err = -EFAULT; - } - return err; -} - -struct fb_cmap32 { - __u32 start; /* First entry */ - __u32 len; /* Number of entries */ - __u32 redptr; /* Red values */ - __u32 greenptr; - __u32 blueptr; - __u32 transpptr; /* transparency, can be NULL */ -}; - -static int do_fbiogetcmap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct fb_cmap cmap; - int err; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (long)&cmap); - set_fs(old_fs); - - if (err == 0) { - __u32 redptr = (__u32)(__u64)cmap.red; - __u32 greenptr = (__u32)(__u64)cmap.green; - __u32 blueptr = (__u32)(__u64)cmap.blue; - __u32 transpptr = (__u32)(__u64)cmap.transp; - - err = put_user(cmap.start, &((struct fb_cmap32 *)arg)->start); - err |= __put_user(cmap.len, &((struct fb_cmap32 *)arg)->len); - err |= __put_user(redptr, &((struct fb_cmap32 *)arg)->redptr); - err |= __put_user(greenptr, &((struct fb_cmap32 *)arg)->greenptr); - err |= __put_user(blueptr, &((struct fb_cmap32 *)arg)->blueptr); - err |= __put_user(transpptr, &((struct fb_cmap32 *)arg)->transpptr); - if (err) - err = -EFAULT; - } - return err; -} - -static int do_fbioputcmap_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct fb_cmap cmap; - __u32 redptr, greenptr, blueptr, transpptr; - int err; - - err = get_user(cmap.start, &((struct fb_cmap32 *)arg)->start); - err |= __get_user(cmap.len, &((struct fb_cmap32 *)arg)->len); - err |= __get_user(redptr, &((struct fb_cmap32 *)arg)->redptr); - err |= __get_user(greenptr, &((struct fb_cmap32 *)arg)->greenptr); - err |= __get_user(blueptr, &((struct fb_cmap32 *)arg)->blueptr); - err |= __get_user(transpptr, &((struct fb_cmap32 *)arg)->transpptr); - - if (err) { - err = -EFAULT; - } else { - cmap.red = (__u16 *)(__u64)redptr; - cmap.green = (__u16 *)(__u64)greenptr; - cmap.blue = (__u16 *)(__u64)blueptr; - cmap.transp = (__u16 *)(__u64)transpptr; - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&cmap); - set_fs (old_fs); - } - return err; -} - -struct unimapdesc32 { - unsigned short entry_ct; - u32 entries; -}; - -static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, struct unimapdesc32 *user_ud, struct file *file) -{ - struct unimapdesc32 tmp; - int perm = vt_check(file); - - if (perm < 0) return perm; - if (copy_from_user(&tmp, user_ud, sizeof tmp)) - return -EFAULT; - switch (cmd) { - case PIO_UNIMAP: - if (!perm) return -EPERM; - return con_set_unimap(fg_console, tmp.entry_ct, (struct unipair *)A(tmp.entries)); - case GIO_UNIMAP: - return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), (struct unipair *)A(tmp.entries)); - } - return 0; -} -#endif /* CONFIG_VT */ -static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - __kernel_uid_t kuid; - int err; - - cmd = SMB_IOC_GETMOUNTUID; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&kuid); - set_fs(old_fs); - - if (err >= 0) - err = put_user(kuid, (compat_uid_t *)arg); - - return err; -} - -struct ncp_ioctl_request_32 { - unsigned int function; - unsigned int size; - compat_caddr_t data; -}; - -struct ncp_fs_info_v2_32 { - int version; - unsigned int mounted_uid; - unsigned int connection; - unsigned int buffer_size; - - unsigned int volume_number; - __u32 directory_id; - - __u32 dummy1; - __u32 dummy2; - __u32 dummy3; -}; - -struct ncp_objectname_ioctl_32 -{ - int auth_type; - unsigned int object_name_len; - compat_caddr_t object_name; /* an userspace data, in most cases user name */ -}; - -struct ncp_privatedata_ioctl_32 -{ - unsigned int len; - compat_caddr_t data; /* ~1000 for NDS */ -}; - -#define NCP_IOC_NCPREQUEST_32 _IOR('n', 1, struct ncp_ioctl_request_32) - -#define NCP_IOC_GETMOUNTUID2_32 _IOW('n', 2, unsigned int) - -#define NCP_IOC_GET_FS_INFO_V2_32 _IOWR('n', 4, struct ncp_fs_info_v2_32) - -#define NCP_IOC_GETOBJECTNAME_32 _IOWR('n', 9, struct ncp_objectname_ioctl_32) -#define NCP_IOC_SETOBJECTNAME_32 _IOR('n', 9, struct ncp_objectname_ioctl_32) -#define NCP_IOC_GETPRIVATEDATA_32 _IOWR('n', 10, struct ncp_privatedata_ioctl_32) -#define NCP_IOC_SETPRIVATEDATA_32 _IOR('n', 10, struct ncp_privatedata_ioctl_32) - -static int do_ncp_ncprequest(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ncp_ioctl_request_32 n32; - struct ncp_ioctl_request n; - mm_segment_t old_fs; - int err; - - if (copy_from_user(&n32, (struct ncp_ioctl_request_32*)arg, - sizeof(n32))) - return -EFAULT; - - n.function = n32.function; - n.size = n32.size; - if (n.size > 65536) - return -EINVAL; - n.data = vmalloc(65536); /* 65536 must be same as NCP_PACKET_SIZE_INTERNAL in ncpfs */ - if (!n.data) - return -ENOMEM; - err = -EFAULT; - if (copy_from_user(n.data, (void *)A(n32.data), n.size)) - goto out; - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, NCP_IOC_NCPREQUEST, (unsigned long)&n); - set_fs (old_fs); - if(err <= 0) - goto out; - if (err > 65536) { - err = -EINVAL; - goto out; - } - if (copy_to_user((void *)A(n32.data), n.data, err)) { - err = -EFAULT; - goto out; - } - out: - vfree(n.data); - return err; -} - -static int do_ncp_getmountuid2(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - __kernel_uid_t kuid; - int err; - - cmd = NCP_IOC_GETMOUNTUID2; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&kuid); - set_fs(old_fs); - - if (!err) - err = put_user(kuid, (unsigned int*)arg); - - return err; -} - -static int do_ncp_getfsinfo2(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct ncp_fs_info_v2_32 n32; - struct ncp_fs_info_v2 n; - int err; - - if (copy_from_user(&n32, (struct ncp_fs_info_v2_32*)arg, sizeof(n32))) - return -EFAULT; - if (n32.version != NCP_GET_FS_INFO_VERSION_V2) - return -EINVAL; - n.version = NCP_GET_FS_INFO_VERSION_V2; - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, NCP_IOC_GET_FS_INFO_V2, (unsigned long)&n); - set_fs(old_fs); - - if (!err) { - n32.version = n.version; - n32.mounted_uid = n.mounted_uid; - n32.connection = n.connection; - n32.buffer_size = n.buffer_size; - n32.volume_number = n.volume_number; - n32.directory_id = n.directory_id; - n32.dummy1 = n.dummy1; - n32.dummy2 = n.dummy2; - n32.dummy3 = n.dummy3; - err = copy_to_user((struct ncp_fs_info_v2_32*)arg, &n32, sizeof(n32)) ? -EFAULT : 0; - } - return err; -} - -static int do_ncp_getobjectname(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ncp_objectname_ioctl_32 n32; - struct ncp_objectname_ioctl n; - mm_segment_t old_fs; - int err; - size_t tl; - - if (copy_from_user(&n32, (struct ncp_objectname_ioctl_32*)arg, - sizeof(n32))) - return -EFAULT; - - n.object_name_len = tl = n32.object_name_len; - if (tl) { - n.object_name = kmalloc(tl, GFP_KERNEL); - if (!n.object_name) - return -ENOMEM; - } else { - n.object_name = NULL; - } - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, NCP_IOC_GETOBJECTNAME, (unsigned long)&n); - set_fs (old_fs); - if(err) - goto out; - - if (tl > n.object_name_len) - tl = n.object_name_len; - - err = -EFAULT; - if (tl && copy_to_user((void *)A(n32.object_name), n.object_name, tl)) - goto out; - - n32.auth_type = n.auth_type; - n32.object_name_len = n.object_name_len; - - if (copy_to_user((struct ncp_objectname_ioctl_32*)arg, &n32, sizeof(n32))) - goto out; - - err = 0; - out: - if (n.object_name) - kfree(n.object_name); - - return err; -} - -static int do_ncp_setobjectname(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ncp_objectname_ioctl_32 n32; - struct ncp_objectname_ioctl n; - mm_segment_t old_fs; - int err; - size_t tl; - - if (copy_from_user(&n32, (struct ncp_objectname_ioctl_32*)arg, - sizeof(n32))) - return -EFAULT; - - n.auth_type = n32.auth_type; - n.object_name_len = tl = n32.object_name_len; - if (tl) { - n.object_name = kmalloc(tl, GFP_KERNEL); - if (!n.object_name) - return -ENOMEM; - err = -EFAULT; - if (copy_from_user(n.object_name, (void *)A(n32.object_name), tl)) - goto out; - } else { - n.object_name = NULL; - } - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, NCP_IOC_SETOBJECTNAME, (unsigned long)&n); - set_fs (old_fs); - - out: - if (n.object_name) - kfree(n.object_name); - - return err; -} - -static int do_ncp_getprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ncp_privatedata_ioctl_32 n32; - struct ncp_privatedata_ioctl n; - mm_segment_t old_fs; - int err; - size_t tl; - - if (copy_from_user(&n32, (struct ncp_privatedata_ioctl_32*)arg, - sizeof(n32))) - return -EFAULT; - - n.len = tl = n32.len; - if (tl) { - n.data = kmalloc(tl, GFP_KERNEL); - if (!n.data) - return -ENOMEM; - } else { - n.data = NULL; - } - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, NCP_IOC_GETPRIVATEDATA, (unsigned long)&n); - set_fs (old_fs); - if(err) - goto out; - - if (tl > n.len) - tl = n.len; - - err = -EFAULT; - if (tl && copy_to_user((void *)A(n32.data), n.data, tl)) - goto out; - - n32.len = n.len; - - if (copy_to_user((struct ncp_privatedata_ioctl_32*)arg, &n32, sizeof(n32))) - goto out; - - err = 0; - out: - if (n.data) - kfree(n.data); - - return err; -} - -static int do_ncp_setprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct ncp_privatedata_ioctl_32 n32; - struct ncp_privatedata_ioctl n; - mm_segment_t old_fs; - int err; - size_t tl; - - if (copy_from_user(&n32, (struct ncp_privatedata_ioctl_32*)arg, - sizeof(n32))) - return -EFAULT; - - n.len = tl = n32.len; - if (tl) { - n.data = kmalloc(tl, GFP_KERNEL); - if (!n.data) - return -ENOMEM; - err = -EFAULT; - if (copy_from_user(n.data, (void *)A(n32.data), tl)) - goto out; - } else { - n.data = NULL; - } - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, NCP_IOC_SETPRIVATEDATA, (unsigned long)&n); - set_fs (old_fs); - - out: - if (n.data) - kfree(n.data); - - return err; -} - -struct atmif_sioc32 { - int number; - int length; - compat_caddr_t arg; -}; - -struct atm_iobuf32 { - int length; - compat_caddr_t buffer; -}; - -#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32) -#define ATM_GETNAMES32 _IOW('a', ATMIOC_ITF+3, struct atm_iobuf32) -#define ATM_GETTYPE32 _IOW('a', ATMIOC_ITF+4, struct atmif_sioc32) -#define ATM_GETESI32 _IOW('a', ATMIOC_ITF+5, struct atmif_sioc32) -#define ATM_GETADDR32 _IOW('a', ATMIOC_ITF+6, struct atmif_sioc32) -#define ATM_RSTADDR32 _IOW('a', ATMIOC_ITF+7, struct atmif_sioc32) -#define ATM_ADDADDR32 _IOW('a', ATMIOC_ITF+8, struct atmif_sioc32) -#define ATM_DELADDR32 _IOW('a', ATMIOC_ITF+9, struct atmif_sioc32) -#define ATM_GETCIRANGE32 _IOW('a', ATMIOC_ITF+10, struct atmif_sioc32) -#define ATM_SETCIRANGE32 _IOW('a', ATMIOC_ITF+11, struct atmif_sioc32) -#define ATM_SETESI32 _IOW('a', ATMIOC_ITF+12, struct atmif_sioc32) -#define ATM_SETESIF32 _IOW('a', ATMIOC_ITF+13, struct atmif_sioc32) -#define ATM_GETSTAT32 _IOW('a', ATMIOC_SARCOM+0, struct atmif_sioc32) -#define ATM_GETSTATZ32 _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32) -#define ATM_GETLOOP32 _IOW('a', ATMIOC_SARCOM+2, struct atmif_sioc32) -#define ATM_SETLOOP32 _IOW('a', ATMIOC_SARCOM+3, struct atmif_sioc32) -#define ATM_QUERYLOOP32 _IOW('a', ATMIOC_SARCOM+4, struct atmif_sioc32) - -static struct { - unsigned int cmd32; - unsigned int cmd; -} atm_ioctl_map[] = { - { ATM_GETLINKRATE32, ATM_GETLINKRATE }, - { ATM_GETNAMES32, ATM_GETNAMES }, - { ATM_GETTYPE32, ATM_GETTYPE }, - { ATM_GETESI32, ATM_GETESI }, - { ATM_GETADDR32, ATM_GETADDR }, - { ATM_RSTADDR32, ATM_RSTADDR }, - { ATM_ADDADDR32, ATM_ADDADDR }, - { ATM_DELADDR32, ATM_DELADDR }, - { ATM_GETCIRANGE32, ATM_GETCIRANGE }, - { ATM_SETCIRANGE32, ATM_SETCIRANGE }, - { ATM_SETESI32, ATM_SETESI }, - { ATM_SETESIF32, ATM_SETESIF }, - { ATM_GETSTAT32, ATM_GETSTAT }, - { ATM_GETSTATZ32, ATM_GETSTATZ }, - { ATM_GETLOOP32, ATM_GETLOOP }, - { ATM_SETLOOP32, ATM_SETLOOP }, - { ATM_QUERYLOOP32, ATM_QUERYLOOP } -}; - -#define NR_ATM_IOCTL (sizeof(atm_ioctl_map)/sizeof(atm_ioctl_map[0])) - - -static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct atm_iobuf32 iobuf32; - struct atm_iobuf iobuf = { 0, NULL }; - mm_segment_t old_fs; - int err; - - err = copy_from_user(&iobuf32, (struct atm_iobuf32*)arg, - sizeof(struct atm_iobuf32)); - if (err) - return -EFAULT; - - iobuf.length = iobuf32.length; - - if (iobuf32.buffer == (compat_caddr_t) NULL || iobuf32.length == 0) { - iobuf.buffer = (void*)(unsigned long)iobuf32.buffer; - } else { - iobuf.buffer = kmalloc(iobuf.length, GFP_KERNEL); - if (iobuf.buffer == NULL) { - err = -ENOMEM; - goto out; - } - - err = copy_from_user(iobuf.buffer, (void *)A(iobuf32.buffer), iobuf.length); - if (err) { - err = -EFAULT; - goto out; - } - } - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&iobuf); - set_fs (old_fs); - if (err) - goto out; - - if (iobuf.buffer && iobuf.length > 0) { - err = copy_to_user((void *)A(iobuf32.buffer), iobuf.buffer, iobuf.length); - if (err) { - err = -EFAULT; - goto out; - } - } - err = __put_user(iobuf.length, &(((struct atm_iobuf32*)arg)->length)); - - out: - if (iobuf32.buffer && iobuf32.length > 0) - kfree(iobuf.buffer); - - return err; -} - - -static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct atmif_sioc32 sioc32; - struct atmif_sioc sioc = { 0, 0, NULL }; - mm_segment_t old_fs; - int err; - - err = copy_from_user(&sioc32, (struct atmif_sioc32*)arg, - sizeof(struct atmif_sioc32)); - if (err) - return -EFAULT; - - sioc.number = sioc32.number; - sioc.length = sioc32.length; - - if (sioc32.arg == (compat_caddr_t) NULL || sioc32.length == 0) { - sioc.arg = (void*)(unsigned long)sioc32.arg; - } else { - sioc.arg = kmalloc(sioc.length, GFP_KERNEL); - if (sioc.arg == NULL) { - err = -ENOMEM; - goto out; - } - - err = copy_from_user(sioc.arg, (void *)A(sioc32.arg), sioc32.length); - if (err) { - err = -EFAULT; - goto out; - } - } - - old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&sioc); - set_fs (old_fs); - if (err) { - goto out; - } - - if (sioc.arg && sioc.length > 0) { - err = copy_to_user((void *)A(sioc32.arg), sioc.arg, sioc.length); - if (err) { - err = -EFAULT; - goto out; - } - } - err = __put_user(sioc.length, &(((struct atmif_sioc32*)arg)->length)); - - out: - if (sioc32.arg && sioc32.length > 0) - kfree(sioc.arg); - - return err; -} - - -static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg) -{ - int i; - unsigned int cmd = 0; - - switch (cmd32) { - case SONET_GETSTAT: - case SONET_GETSTATZ: - case SONET_GETDIAG: - case SONET_SETDIAG: - case SONET_CLRDIAG: - case SONET_SETFRAMING: - case SONET_GETFRAMING: - case SONET_GETFRSENSE: - return do_atmif_sioc(fd, cmd32, arg); - } - - for (i = 0; i < NR_ATM_IOCTL; i++) { - if (cmd32 == atm_ioctl_map[i].cmd32) { - cmd = atm_ioctl_map[i].cmd; - break; - } - } - if (i == NR_ATM_IOCTL) { - return -EINVAL; - } - - switch (cmd) { - case ATM_GETNAMES: - return do_atm_iobuf(fd, cmd, arg); - - case ATM_GETLINKRATE: - case ATM_GETTYPE: - case ATM_GETESI: - case ATM_GETADDR: - case ATM_RSTADDR: - case ATM_ADDADDR: - case ATM_DELADDR: - case ATM_GETCIRANGE: - case ATM_SETCIRANGE: - case ATM_SETESI: - case ATM_SETESIF: - case ATM_GETSTAT: - case ATM_GETSTATZ: - case ATM_GETLOOP: - case ATM_SETLOOP: - case ATM_QUERYLOOP: - return do_atmif_sioc(fd, cmd, arg); - } - - return -EINVAL; -} - -#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) -/* This really belongs in include/linux/drm.h -DaveM */ -#include "../../../drivers/char/drm/drm.h" - -typedef struct drm32_version { - int version_major; /* Major version */ - int version_minor; /* Minor version */ - int version_patchlevel;/* Patch level */ - int name_len; /* Length of name buffer */ - u32 name; /* Name of driver */ - int date_len; /* Length of date buffer */ - u32 date; /* User-space buffer to hold date */ - int desc_len; /* Length of desc buffer */ - u32 desc; /* User-space buffer to hold desc */ -} drm32_version_t; -#define DRM32_IOCTL_VERSION DRM_IOWR(0x00, drm32_version_t) -static int drm32_version(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_version_t *uversion = (drm32_version_t *)arg; - char *name_ptr, *date_ptr, *desc_ptr; - u32 tmp1, tmp2, tmp3; - drm_version_t kversion; - mm_segment_t old_fs; - int ret; - - memset(&kversion, 0, sizeof(kversion)); - if (get_user(kversion.name_len, &uversion->name_len) || - get_user(kversion.date_len, &uversion->date_len) || - get_user(kversion.desc_len, &uversion->desc_len) || - get_user(tmp1, &uversion->name) || - get_user(tmp2, &uversion->date) || - get_user(tmp3, &uversion->desc)) - return -EFAULT; - - name_ptr = (char *) A(tmp1); - date_ptr = (char *) A(tmp2); - desc_ptr = (char *) A(tmp3); - - ret = -ENOMEM; - if (kversion.name_len && name_ptr) { - kversion.name = kmalloc(kversion.name_len, GFP_KERNEL); - if (!kversion.name) - goto out; - } - if (kversion.date_len && date_ptr) { - kversion.date = kmalloc(kversion.date_len, GFP_KERNEL); - if (!kversion.date) - goto out; - } - if (kversion.desc_len && desc_ptr) { - kversion.desc = kmalloc(kversion.desc_len, GFP_KERNEL); - if (!kversion.desc) - goto out; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl (fd, DRM_IOCTL_VERSION, (unsigned long)&kversion); - set_fs(old_fs); - - if (!ret) { - if ((kversion.name && - copy_to_user(name_ptr, kversion.name, kversion.name_len)) || - (kversion.date && - copy_to_user(date_ptr, kversion.date, kversion.date_len)) || - (kversion.desc && - copy_to_user(desc_ptr, kversion.desc, kversion.desc_len))) - ret = -EFAULT; - if (put_user(kversion.version_major, &uversion->version_major) || - put_user(kversion.version_minor, &uversion->version_minor) || - put_user(kversion.version_patchlevel, &uversion->version_patchlevel) || - put_user(kversion.name_len, &uversion->name_len) || - put_user(kversion.date_len, &uversion->date_len) || - put_user(kversion.desc_len, &uversion->desc_len)) - ret = -EFAULT; - } - -out: - if (kversion.name) - kfree(kversion.name); - if (kversion.date) - kfree(kversion.date); - if (kversion.desc) - kfree(kversion.desc); - return ret; -} - -typedef struct drm32_unique { - int unique_len; /* Length of unique */ - u32 unique; /* Unique name for driver instantiation */ -} drm32_unique_t; -#define DRM32_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm32_unique_t) -#define DRM32_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm32_unique_t) - -static int drm32_getsetunique(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_unique_t *uarg = (drm32_unique_t *)arg; - drm_unique_t karg; - mm_segment_t old_fs; - char *uptr; - u32 tmp; - int ret; - - if (get_user(karg.unique_len, &uarg->unique_len)) - return -EFAULT; - karg.unique = NULL; - - if (get_user(tmp, &uarg->unique)) - return -EFAULT; - - uptr = (char *) A(tmp); - - if (uptr) { - karg.unique = kmalloc(karg.unique_len, GFP_KERNEL); - if (!karg.unique) - return -ENOMEM; - if (cmd == DRM32_IOCTL_SET_UNIQUE && - copy_from_user(karg.unique, uptr, karg.unique_len)) { - kfree(karg.unique); - return -EFAULT; - } - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - if (cmd == DRM32_IOCTL_GET_UNIQUE) - ret = sys_ioctl (fd, DRM_IOCTL_GET_UNIQUE, (unsigned long)&karg); - else - ret = sys_ioctl (fd, DRM_IOCTL_SET_UNIQUE, (unsigned long)&karg); - set_fs(old_fs); - - if (!ret) { - if (cmd == DRM32_IOCTL_GET_UNIQUE && - uptr != NULL && - copy_to_user(uptr, karg.unique, karg.unique_len)) - ret = -EFAULT; - if (put_user(karg.unique_len, &uarg->unique_len)) - ret = -EFAULT; - } - - if (karg.unique != NULL) - kfree(karg.unique); - - return ret; -} - -typedef struct drm32_map { - u32 offset; /* Requested physical address (0 for SAREA)*/ - u32 size; /* Requested physical size (bytes) */ - drm_map_type_t type; /* Type of memory to map */ - drm_map_flags_t flags; /* Flags */ - u32 handle; /* User-space: "Handle" to pass to mmap */ - /* Kernel-space: kernel-virtual address */ - int mtrr; /* MTRR slot used */ - /* Private data */ -} drm32_map_t; -#define DRM32_IOCTL_ADD_MAP DRM_IOWR(0x15, drm32_map_t) - -static int drm32_addmap(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_map_t *uarg = (drm32_map_t *) arg; - drm_map_t karg; - mm_segment_t old_fs; - u32 tmp; - int ret; - - ret = get_user(karg.offset, &uarg->offset); - ret |= get_user(karg.size, &uarg->size); - ret |= get_user(karg.type, &uarg->type); - ret |= get_user(karg.flags, &uarg->flags); - ret |= get_user(tmp, &uarg->handle); - ret |= get_user(karg.mtrr, &uarg->mtrr); - if (ret) - return -EFAULT; - - karg.handle = (void *) A(tmp); - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_ADD_MAP, (unsigned long) &karg); - set_fs(old_fs); - - if (!ret) { - ret = put_user(karg.offset, &uarg->offset); - ret |= put_user(karg.size, &uarg->size); - ret |= put_user(karg.type, &uarg->type); - ret |= put_user(karg.flags, &uarg->flags); - tmp = (u32) (long)karg.handle; - ret |= put_user(tmp, &uarg->handle); - ret |= put_user(karg.mtrr, &uarg->mtrr); - if (ret) - ret = -EFAULT; - } - - return ret; -} - -typedef struct drm32_buf_info { - int count; /* Entries in list */ - u32 list; /* (drm_buf_desc_t *) */ -} drm32_buf_info_t; -#define DRM32_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm32_buf_info_t) - -static int drm32_info_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - drm32_buf_info_t *uarg = (drm32_buf_info_t *)arg; - drm_buf_desc_t *ulist; - drm_buf_info_t karg; - mm_segment_t old_fs; - int orig_count, ret; - u32 tmp; - - if (get_user(karg.count, &uarg->count) || - get_user(tmp, &uarg->list)) - return -EFAULT; - - ulist = (drm_buf_desc_t *) A(tmp); - - orig_count = karg.count; - - karg.list = kmalloc(karg.count * sizeof(drm_buf_desc_t), GFP_KERNEL); - if (!karg.list) - return -EFAULT; + cmd = NCP_IOC_GETMOUNTUID2; - old_fs = get_fs(); set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_INFO_BUFS, (unsigned long) &karg); + err = sys_ioctl(fd, cmd, (unsigned long)&kuid); set_fs(old_fs); - if (!ret) { - if (karg.count <= orig_count && - (copy_to_user(ulist, karg.list, - karg.count * sizeof(drm_buf_desc_t)))) - ret = -EFAULT; - if (put_user(karg.count, &uarg->count)) - ret = -EFAULT; - } - - kfree(karg.list); + if (!err) + err = put_user(kuid, (unsigned int*)arg); - return ret; + return err; } -typedef struct drm32_buf_free { - int count; - u32 list; /* (int *) */ -} drm32_buf_free_t; -#define DRM32_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm32_buf_free_t) - -static int drm32_free_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) +static int do_ncp_getfsinfo2(unsigned int fd, unsigned int cmd, unsigned long arg) { - drm32_buf_free_t *uarg = (drm32_buf_free_t *)arg; - drm_buf_free_t karg; - mm_segment_t old_fs; - int *ulist; - int ret; - u32 tmp; + mm_segment_t old_fs = get_fs(); + struct ncp_fs_info_v2_32 n32; + struct ncp_fs_info_v2 n; + int err; - if (get_user(karg.count, &uarg->count) || - get_user(tmp, &uarg->list)) + if (copy_from_user(&n32, (struct ncp_fs_info_v2_32*)arg, sizeof(n32))) return -EFAULT; + if (n32.version != NCP_GET_FS_INFO_VERSION_V2) + return -EINVAL; + n.version = NCP_GET_FS_INFO_VERSION_V2; - ulist = (int *) A(tmp); - - karg.list = kmalloc(karg.count * sizeof(int), GFP_KERNEL); - if (!karg.list) - return -ENOMEM; - - ret = -EFAULT; - if (copy_from_user(karg.list, ulist, (karg.count * sizeof(int)))) - goto out; - - old_fs = get_fs(); set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_FREE_BUFS, (unsigned long) &karg); + err = sys_ioctl(fd, NCP_IOC_GET_FS_INFO_V2, (unsigned long)&n); set_fs(old_fs); -out: - kfree(karg.list); - - return ret; + if (!err) { + n32.version = n.version; + n32.mounted_uid = n.mounted_uid; + n32.connection = n.connection; + n32.buffer_size = n.buffer_size; + n32.volume_number = n.volume_number; + n32.directory_id = n.directory_id; + n32.dummy1 = n.dummy1; + n32.dummy2 = n.dummy2; + n32.dummy3 = n.dummy3; + err = copy_to_user((struct ncp_fs_info_v2_32*)arg, &n32, sizeof(n32)) ? -EFAULT : 0; + } + return err; } -typedef struct drm32_buf_pub { - int idx; /* Index into master buflist */ - int total; /* Buffer size */ - int used; /* Amount of buffer in use (for DMA) */ - u32 address; /* Address of buffer (void *) */ -} drm32_buf_pub_t; - -typedef struct drm32_buf_map { - int count; /* Length of buflist */ - u32 virtual; /* Mmaped area in user-virtual (void *) */ - u32 list; /* Buffer information (drm_buf_pub_t *) */ -} drm32_buf_map_t; -#define DRM32_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm32_buf_map_t) - -static int drm32_map_bufs(unsigned int fd, unsigned int cmd, unsigned long arg) +static int do_ncp_getobjectname(unsigned int fd, unsigned int cmd, unsigned long arg) { - drm32_buf_map_t *uarg = (drm32_buf_map_t *)arg; - drm32_buf_pub_t *ulist; - drm_buf_map_t karg; + struct ncp_objectname_ioctl_32 n32; + struct ncp_objectname_ioctl n; mm_segment_t old_fs; - int orig_count, ret, i; - u32 tmp1, tmp2; + int err; + size_t tl; - if (get_user(karg.count, &uarg->count) || - get_user(tmp1, &uarg->virtual) || - get_user(tmp2, &uarg->list)) + if (copy_from_user(&n32, (struct ncp_objectname_ioctl_32*)arg, + sizeof(n32))) return -EFAULT; - karg.virtual = (void *) A(tmp1); - ulist = (drm32_buf_pub_t *) A(tmp2); - - orig_count = karg.count; - - karg.list = kmalloc(karg.count * sizeof(drm_buf_pub_t), GFP_KERNEL); - if (!karg.list) - return -ENOMEM; - - ret = -EFAULT; - for (i = 0; i < karg.count; i++) { - if (get_user(karg.list[i].idx, &ulist[i].idx) || - get_user(karg.list[i].total, &ulist[i].total) || - get_user(karg.list[i].used, &ulist[i].used) || - get_user(tmp1, &ulist[i].address)) - goto out; - - karg.list[i].address = (void *) A(tmp1); + n.object_name_len = tl = n32.object_name_len; + if (tl) { + n.object_name = kmalloc(tl, GFP_KERNEL); + if (!n.object_name) + return -ENOMEM; + } else { + n.object_name = NULL; } - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_MAP_BUFS, (unsigned long) &karg); - set_fs(old_fs); + old_fs = get_fs(); set_fs (KERNEL_DS); + err = sys_ioctl (fd, NCP_IOC_GETOBJECTNAME, (unsigned long)&n); + set_fs (old_fs); + if(err) + goto out; + + if (tl > n.object_name_len) + tl = n.object_name_len; - if (!ret) { - for (i = 0; i < orig_count; i++) { - tmp1 = (u32) (long) karg.list[i].address; - if (put_user(karg.list[i].idx, &ulist[i].idx) || - put_user(karg.list[i].total, &ulist[i].total) || - put_user(karg.list[i].used, &ulist[i].used) || - put_user(tmp1, &ulist[i].address)) { - ret = -EFAULT; - goto out; - } - } - if (put_user(karg.count, &uarg->count)) - ret = -EFAULT; - } + err = -EFAULT; + if (tl && copy_to_user((void *)A(n32.object_name), n.object_name, tl)) + goto out; -out: - kfree(karg.list); - return ret; + n32.auth_type = n.auth_type; + n32.object_name_len = n.object_name_len; + + if (copy_to_user((struct ncp_objectname_ioctl_32*)arg, &n32, sizeof(n32))) + goto out; + + err = 0; + out: + if (n.object_name) + kfree(n.object_name); + + return err; } -typedef struct drm32_dma { - /* Indices here refer to the offset into - buflist in drm_buf_get_t. */ - int context; /* Context handle */ - int send_count; /* Number of buffers to send */ - u32 send_indices; /* List of handles to buffers (int *) */ - u32 send_sizes; /* Lengths of data to send (int *) */ - drm_dma_flags_t flags; /* Flags */ - int request_count; /* Number of buffers requested */ - int request_size; /* Desired size for buffers */ - u32 request_indices; /* Buffer information (int *) */ - u32 request_sizes; /* (int *) */ - int granted_count; /* Number of buffers granted */ -} drm32_dma_t; -#define DRM32_IOCTL_DMA DRM_IOWR(0x29, drm32_dma_t) - -/* RED PEN The DRM layer blindly dereferences the send/request - * indice/size arrays even though they are userland - * pointers. -DaveM - */ -static int drm32_dma(unsigned int fd, unsigned int cmd, unsigned long arg) +static int do_ncp_setobjectname(unsigned int fd, unsigned int cmd, unsigned long arg) { - drm32_dma_t *uarg = (drm32_dma_t *) arg; - int *u_si, *u_ss, *u_ri, *u_rs; - drm_dma_t karg; + struct ncp_objectname_ioctl_32 n32; + struct ncp_objectname_ioctl n; mm_segment_t old_fs; - int ret; - u32 tmp1, tmp2, tmp3, tmp4; - - karg.send_indices = karg.send_sizes = NULL; - karg.request_indices = karg.request_sizes = NULL; + int err; + size_t tl; - if (get_user(karg.context, &uarg->context) || - get_user(karg.send_count, &uarg->send_count) || - get_user(tmp1, &uarg->send_indices) || - get_user(tmp2, &uarg->send_sizes) || - get_user(karg.flags, &uarg->flags) || - get_user(karg.request_count, &uarg->request_count) || - get_user(karg.request_size, &uarg->request_size) || - get_user(tmp3, &uarg->request_indices) || - get_user(tmp4, &uarg->request_sizes) || - get_user(karg.granted_count, &uarg->granted_count)) + if (copy_from_user(&n32, (struct ncp_objectname_ioctl_32*)arg, + sizeof(n32))) return -EFAULT; - u_si = (int *) A(tmp1); - u_ss = (int *) A(tmp2); - u_ri = (int *) A(tmp3); - u_rs = (int *) A(tmp4); - - if (karg.send_count) { - karg.send_indices = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL); - karg.send_sizes = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL); - - ret = -ENOMEM; - if (!karg.send_indices || !karg.send_sizes) - goto out; - - ret = -EFAULT; - if (copy_from_user(karg.send_indices, u_si, - (karg.send_count * sizeof(int))) || - copy_from_user(karg.send_sizes, u_ss, - (karg.send_count * sizeof(int)))) - goto out; - } - - if (karg.request_count) { - karg.request_indices = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL); - karg.request_sizes = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL); - - ret = -ENOMEM; - if (!karg.request_indices || !karg.request_sizes) - goto out; - - ret = -EFAULT; - if (copy_from_user(karg.request_indices, u_ri, - (karg.request_count * sizeof(int))) || - copy_from_user(karg.request_sizes, u_rs, - (karg.request_count * sizeof(int)))) + n.auth_type = n32.auth_type; + n.object_name_len = tl = n32.object_name_len; + if (tl) { + n.object_name = kmalloc(tl, GFP_KERNEL); + if (!n.object_name) + return -ENOMEM; + err = -EFAULT; + if (copy_from_user(n.object_name, (void *)A(n32.object_name), tl)) goto out; + } else { + n.object_name = NULL; } + + old_fs = get_fs(); set_fs (KERNEL_DS); + err = sys_ioctl (fd, NCP_IOC_SETOBJECTNAME, (unsigned long)&n); + set_fs (old_fs); + + out: + if (n.object_name) + kfree(n.object_name); - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_DMA, (unsigned long) &karg); - set_fs(old_fs); - - if (!ret) { - if (put_user(karg.context, &uarg->context) || - put_user(karg.send_count, &uarg->send_count) || - put_user(karg.flags, &uarg->flags) || - put_user(karg.request_count, &uarg->request_count) || - put_user(karg.request_size, &uarg->request_size) || - put_user(karg.granted_count, &uarg->granted_count)) - ret = -EFAULT; - - if (karg.send_count) { - if (copy_to_user(u_si, karg.send_indices, - (karg.send_count * sizeof(int))) || - copy_to_user(u_ss, karg.send_sizes, - (karg.send_count * sizeof(int)))) - ret = -EFAULT; - } - if (karg.request_count) { - if (copy_to_user(u_ri, karg.request_indices, - (karg.request_count * sizeof(int))) || - copy_to_user(u_rs, karg.request_sizes, - (karg.request_count * sizeof(int)))) - ret = -EFAULT; - } - } - -out: - if (karg.send_indices) - kfree(karg.send_indices); - if (karg.send_sizes) - kfree(karg.send_sizes); - if (karg.request_indices) - kfree(karg.request_indices); - if (karg.request_sizes) - kfree(karg.request_sizes); - - return ret; + return err; } -typedef struct drm32_ctx_res { - int count; - u32 contexts; /* (drm_ctx_t *) */ -} drm32_ctx_res_t; -#define DRM32_IOCTL_RES_CTX DRM_IOWR(0x26, drm32_ctx_res_t) - -static int drm32_res_ctx(unsigned int fd, unsigned int cmd, unsigned long arg) +static int do_ncp_getprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg) { - drm32_ctx_res_t *uarg = (drm32_ctx_res_t *) arg; - drm_ctx_t *ulist; - drm_ctx_res_t karg; + struct ncp_privatedata_ioctl_32 n32; + struct ncp_privatedata_ioctl n; mm_segment_t old_fs; - int orig_count, ret; - u32 tmp; + int err; + size_t tl; - karg.contexts = NULL; - if (get_user(karg.count, &uarg->count) || - get_user(tmp, &uarg->contexts)) + if (copy_from_user(&n32, (struct ncp_privatedata_ioctl_32*)arg, + sizeof(n32))) return -EFAULT; - ulist = (drm_ctx_t *) A(tmp); - - orig_count = karg.count; - if (karg.count && ulist) { - karg.contexts = kmalloc((karg.count * sizeof(drm_ctx_t)), GFP_KERNEL); - if (!karg.contexts) + n.len = tl = n32.len; + if (tl) { + n.data = kmalloc(tl, GFP_KERNEL); + if (!n.data) return -ENOMEM; - if (copy_from_user(karg.contexts, ulist, - (karg.count * sizeof(drm_ctx_t)))) { - kfree(karg.contexts); - return -EFAULT; - } + } else { + n.data = NULL; } - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, DRM_IOCTL_RES_CTX, (unsigned long) &karg); - set_fs(old_fs); + old_fs = get_fs(); set_fs (KERNEL_DS); + err = sys_ioctl (fd, NCP_IOC_GETPRIVATEDATA, (unsigned long)&n); + set_fs (old_fs); + if(err) + goto out; + + if (tl > n.len) + tl = n.len; - if (!ret) { - if (orig_count) { - if (copy_to_user(ulist, karg.contexts, - (orig_count * sizeof(drm_ctx_t)))) - ret = -EFAULT; - } - if (put_user(karg.count, &uarg->count)) - ret = -EFAULT; - } + err = -EFAULT; + if (tl && copy_to_user((void *)A(n32.data), n.data, tl)) + goto out; - if (karg.contexts) - kfree(karg.contexts); + n32.len = n.len; + + if (copy_to_user((struct ncp_privatedata_ioctl_32*)arg, &n32, sizeof(n32))) + goto out; + + err = 0; + out: + if (n.data) + kfree(n.data); - return ret; + return err; } -#endif - -static int ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg) +static int do_ncp_setprivatedata(unsigned int fd, unsigned int cmd, unsigned long arg) { - return -EINVAL; -} + struct ncp_privatedata_ioctl_32 n32; + struct ncp_privatedata_ioctl n; + mm_segment_t old_fs; + int err; + size_t tl; -static int broken_blkgetsize(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - /* The mkswap binary hard codes it to Intel value :-((( */ - return w_long(fd, BLKGETSIZE, arg); -} + if (copy_from_user(&n32, (struct ncp_privatedata_ioctl_32*)arg, + sizeof(n32))) + return -EFAULT; -struct blkpg_ioctl_arg32 { - int op; - int flags; - int datalen; - u32 data; -}; - -static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, struct blkpg_ioctl_arg32 *arg) -{ - struct blkpg_ioctl_arg a; - struct blkpg_partition p; - int err; - mm_segment_t old_fs = get_fs(); + n.len = tl = n32.len; + if (tl) { + n.data = kmalloc(tl, GFP_KERNEL); + if (!n.data) + return -ENOMEM; + err = -EFAULT; + if (copy_from_user(n.data, (void *)A(n32.data), tl)) + goto out; + } else { + n.data = NULL; + } - err = get_user(a.op, &arg->op); - err |= __get_user(a.flags, &arg->flags); - err |= __get_user(a.datalen, &arg->datalen); - err |= __get_user((long)a.data, &arg->data); - if (err) return err; - switch (a.op) { - case BLKPG_ADD_PARTITION: - case BLKPG_DEL_PARTITION: - if (a.datalen < sizeof(struct blkpg_partition)) - return -EINVAL; - if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition))) - return -EFAULT; - a.data = &p; - set_fs (KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&a); - set_fs (old_fs); - default: - return -EINVAL; - } - return err; -} + old_fs = get_fs(); set_fs (KERNEL_DS); + err = sys_ioctl (fd, NCP_IOC_SETPRIVATEDATA, (unsigned long)&n); + set_fs (old_fs); + + out: + if (n.data) + kfree(n.data); -static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); + return err; } struct usbdevfs_ctrltransfer32 { @@ -3596,92 +747,6 @@ return err; } -struct mtd_oob_buf32 { - u32 start; - u32 length; - u32 ptr; /* unsigned char* */ -}; - -#define MEMWRITEOOB32 _IOWR('M',3,struct mtd_oob_buf32) -#define MEMREADOOB32 _IOWR('M',4,struct mtd_oob_buf32) - -static inline int -mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs = get_fs(); - struct mtd_oob_buf32 *uarg = (struct mtd_oob_buf32 *)arg; - struct mtd_oob_buf karg; - u32 tmp; - char *ptr; - int ret; - - if (get_user(karg.start, &uarg->start) || - get_user(karg.length, &uarg->length) || - get_user(tmp, &uarg->ptr)) - return -EFAULT; - - ptr = (char *)A(tmp); - if (0 >= karg.length) - return -EINVAL; - - karg.ptr = kmalloc(karg.length, GFP_KERNEL); - if (NULL == karg.ptr) - return -ENOMEM; - - if (copy_from_user(karg.ptr, ptr, karg.length)) { - kfree(karg.ptr); - return -EFAULT; - } - - set_fs(KERNEL_DS); - if (MEMREADOOB32 == cmd) - ret = sys_ioctl(fd, MEMREADOOB, (unsigned long)&karg); - else if (MEMWRITEOOB32 == cmd) - ret = sys_ioctl(fd, MEMWRITEOOB, (unsigned long)&karg); - else - ret = -EINVAL; - set_fs(old_fs); - - if (0 == ret && cmd == MEMREADOOB32) { - ret = copy_to_user(ptr, karg.ptr, karg.length); - ret |= put_user(karg.start, &uarg->start); - ret |= put_user(karg.length, &uarg->length); - } - - kfree(karg.ptr); - return ((0 == ret) ? 0 : -EFAULT); -} - -/* Fix sizeof(sizeof()) breakage */ -#define BLKBSZGET_32 _IOR(0x12,112,int) -#define BLKBSZSET_32 _IOW(0x12,113,int) -#define BLKGETSIZE64_32 _IOR(0x12,114,int) - -static int do_blkbszget(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - return sys_ioctl(fd, BLKBSZGET, arg); -} - -static int do_blkbszset(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - return sys_ioctl(fd, BLKBSZSET, arg); -} - -static int do_blkgetsize64(unsigned int fd, unsigned int cmd, - unsigned long arg) -{ - return sys_ioctl(fd, BLKGETSIZE64, arg); -} - -/* Bluetooth ioctls */ -#define HCIUARTSETPROTO _IOW('U', 200, int) -#define HCIUARTGETPROTO _IOR('U', 201, int) - -#define BNEPCONNADD _IOW('B', 200, int) -#define BNEPCONNDEL _IOW('B', 201, int) -#define BNEPGETCONNLIST _IOR('B', 210, int) -#define BNEPGETCONNINFO _IOR('B', 211, int) - #define HANDLE_IOCTL(cmd,handler) { cmd, (ioctl_trans_handler_t)handler, 0 }, #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl) @@ -3690,11 +755,10 @@ #define IOCTL_TABLE_END \ }; struct ioctl_trans ioctl_end[0]; -#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int) -#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t) - IOCTL_TABLE_START #include +#define DECLARES +#include "compat_ioctl.c" COMPATIBLE_IOCTL(TCSBRKP) COMPATIBLE_IOCTL(TIOCSTART) COMPATIBLE_IOCTL(TIOCSTOP) @@ -3709,116 +773,8 @@ COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ /* And these ioctls need translation */ -HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob) -HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob) -#ifdef CONFIG_NET -HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32) -#endif -HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf) -HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFFLAGS, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFMETRIC, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFMETRIC, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFMTU, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFMTU, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFMEM, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFMEM, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFHWADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFHWADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCADDMULTI, dev_ifsioc) -HANDLE_IOCTL(SIOCDELMULTI, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFINDEX, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFMAP, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFMAP, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFBRDADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFBRDADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFDSTADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFDSTADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFNETMASK, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFNETMASK, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFPFLAGS, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc) -HANDLE_IOCTL(SIOCETHTOOL, ethtool_ioctl) -HANDLE_IOCTL(SIOCBONDENSLAVE, bond_ioctl) -HANDLE_IOCTL(SIOCBONDRELEASE, bond_ioctl) -HANDLE_IOCTL(SIOCBONDSETHWADDR, bond_ioctl) -HANDLE_IOCTL(SIOCBONDSLAVEINFOQUERY, bond_ioctl) -HANDLE_IOCTL(SIOCBONDINFOQUERY, bond_ioctl) -HANDLE_IOCTL(SIOCBONDCHANGEACTIVE, bond_ioctl) -HANDLE_IOCTL(SIOCADDRT, routing_ioctl) -HANDLE_IOCTL(SIOCDELRT, routing_ioctl) -/* Note SIOCRTMSG is no longer, so this is safe and - * the user would have seen just an -EINVAL anyways. */ -HANDLE_IOCTL(SIOCRTMSG, ret_einval) -HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp) -HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo) HANDLE_IOCTL(HDIO_GETGEO_BIG_RAW, hdio_getgeo_big) -HANDLE_IOCTL(BLKGETSIZE, w_long) -HANDLE_IOCTL(BLKRAGET, w_long) -HANDLE_IOCTL(BLKFRAGET, w_long) -HANDLE_IOCTL(0x1260, broken_blkgetsize) -HANDLE_IOCTL(BLKSECTGET, w_long) -HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_32BIT, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_MULTCOUNT, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_NOWERR, hdio_ioctl_trans) -HANDLE_IOCTL(HDIO_GET_NICE, hdio_ioctl_trans) -HANDLE_IOCTL(FDSETPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDDEFPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDGETPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDSETDRVPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDGETDRVPRM32, fd_ioctl_trans) -HANDLE_IOCTL(FDGETDRVSTAT32, fd_ioctl_trans) -HANDLE_IOCTL(FDPOLLDRVSTAT32, fd_ioctl_trans) -HANDLE_IOCTL(FDGETFDCSTAT32, fd_ioctl_trans) -HANDLE_IOCTL(FDWERRORGET32, fd_ioctl_trans) -HANDLE_IOCTL(SG_IO,sg_ioctl_trans) -HANDLE_IOCTL(PPPIOCGIDLE32, ppp_ioctl_trans) -HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans) -HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans) -HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans) -HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans) -HANDLE_IOCTL(MTIOCSETCONFIG32, mt_ioctl_trans) -HANDLE_IOCTL(CDROMREADMODE2, cdrom_ioctl_trans) -HANDLE_IOCTL(CDROMREADMODE1, cdrom_ioctl_trans) -HANDLE_IOCTL(CDROMREADRAW, cdrom_ioctl_trans) -HANDLE_IOCTL(CDROMREADCOOKED, cdrom_ioctl_trans) -HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans) -HANDLE_IOCTL(CDROMREADALL, cdrom_ioctl_trans) -HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans) -HANDLE_IOCTL(LOOP_SET_STATUS, loop_status) -HANDLE_IOCTL(LOOP_GET_STATUS, loop_status) -HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout) -#ifdef CONFIG_VT -HANDLE_IOCTL(PIO_FONTX, do_fontx_ioctl) -HANDLE_IOCTL(GIO_FONTX, do_fontx_ioctl) -HANDLE_IOCTL(PIO_UNIMAP, do_unimap_ioctl) -HANDLE_IOCTL(GIO_UNIMAP, do_unimap_ioctl) -HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl) -HANDLE_IOCTL(FBIOGET_FSCREENINFO, do_fbioget_fscreeninfo_ioctl) -HANDLE_IOCTL(FBIOGETCMAP, do_fbiogetcmap_ioctl) -HANDLE_IOCTL(FBIOPUTCMAP, do_fbioputcmap_ioctl) -#endif -HANDLE_IOCTL(EXT2_IOC32_GETFLAGS, do_ext2_ioctl) -HANDLE_IOCTL(EXT2_IOC32_SETFLAGS, do_ext2_ioctl) -HANDLE_IOCTL(EXT2_IOC32_GETVERSION, do_ext2_ioctl) -HANDLE_IOCTL(EXT2_IOC32_SETVERSION, do_ext2_ioctl) -HANDLE_IOCTL(VIDIOCGTUNER32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCSTUNER32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCGWIN32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCSWIN32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCGFBUF32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCSFBUF32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCGFREQ32, do_video_ioctl) -HANDLE_IOCTL(VIDIOCSFREQ32, do_video_ioctl) -/* One SMB ioctl needs translations. */ -HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid) + /* NCPFS */ HANDLE_IOCTL(NCP_IOC_NCPREQUEST_32, do_ncp_ncprequest) HANDLE_IOCTL(NCP_IOC_GETMOUNTUID2_32, do_ncp_getmountuid2) @@ -3827,51 +783,12 @@ HANDLE_IOCTL(NCP_IOC_SETOBJECTNAME_32, do_ncp_setobjectname) HANDLE_IOCTL(NCP_IOC_GETPRIVATEDATA_32, do_ncp_getprivatedata) HANDLE_IOCTL(NCP_IOC_SETPRIVATEDATA_32, do_ncp_setprivatedata) -HANDLE_IOCTL(ATM_GETLINKRATE32, do_atm_ioctl) -HANDLE_IOCTL(ATM_GETNAMES32, do_atm_ioctl) -HANDLE_IOCTL(ATM_GETTYPE32, do_atm_ioctl) -HANDLE_IOCTL(ATM_GETESI32, do_atm_ioctl) -HANDLE_IOCTL(ATM_GETADDR32, do_atm_ioctl) -HANDLE_IOCTL(ATM_RSTADDR32, do_atm_ioctl) -HANDLE_IOCTL(ATM_ADDADDR32, do_atm_ioctl) -HANDLE_IOCTL(ATM_DELADDR32, do_atm_ioctl) -HANDLE_IOCTL(ATM_GETCIRANGE32, do_atm_ioctl) -HANDLE_IOCTL(ATM_SETCIRANGE32, do_atm_ioctl) -HANDLE_IOCTL(ATM_SETESI32, do_atm_ioctl) -HANDLE_IOCTL(ATM_SETESIF32, do_atm_ioctl) -HANDLE_IOCTL(ATM_GETSTAT32, do_atm_ioctl) -HANDLE_IOCTL(ATM_GETSTATZ32, do_atm_ioctl) -HANDLE_IOCTL(ATM_GETLOOP32, do_atm_ioctl) -HANDLE_IOCTL(ATM_SETLOOP32, do_atm_ioctl) -HANDLE_IOCTL(ATM_QUERYLOOP32, do_atm_ioctl) -HANDLE_IOCTL(SONET_GETSTAT, do_atm_ioctl) -HANDLE_IOCTL(SONET_GETSTATZ, do_atm_ioctl) -HANDLE_IOCTL(SONET_GETDIAG, do_atm_ioctl) -HANDLE_IOCTL(SONET_SETDIAG, do_atm_ioctl) -HANDLE_IOCTL(SONET_CLRDIAG, do_atm_ioctl) -HANDLE_IOCTL(SONET_SETFRAMING, do_atm_ioctl) -HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl) -HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl) -#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) -HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version) -HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique) -HANDLE_IOCTL(DRM32_IOCTL_SET_UNIQUE, drm32_getsetunique) -HANDLE_IOCTL(DRM32_IOCTL_ADD_MAP, drm32_addmap) -HANDLE_IOCTL(DRM32_IOCTL_INFO_BUFS, drm32_info_bufs) -HANDLE_IOCTL(DRM32_IOCTL_FREE_BUFS, drm32_free_bufs) -HANDLE_IOCTL(DRM32_IOCTL_MAP_BUFS, drm32_map_bufs) -HANDLE_IOCTL(DRM32_IOCTL_DMA, drm32_dma) -HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx) -#endif /* DRM */ + +/* USB devfs */ HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control) HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk) /*HANDLE_IOCTL(USBDEVFS_SUBMITURB32, do_usbdevfs_urb)*/ HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb) HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb) HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal) -/* take care of sizeof(sizeof()) breakage */ -/* block stuff */ -HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget) -HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset) -HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64) IOCTL_TABLE_END diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/irq.c linux-2.5.71/arch/ppc64/kernel/irq.c --- linux-2.5.70-bk19/arch/ppc64/kernel/irq.c 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/irq.c 2003-06-14 13:53:23.000000000 -0700 @@ -596,7 +596,6 @@ once++; ppc_md.init_IRQ(); - if(ppc_md.init_ras_IRQ) ppc_md.init_ras_IRQ(); } static struct proc_dir_entry * root_irq_dir; diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/misc.S linux-2.5.71/arch/ppc64/kernel/misc.S --- linux-2.5.70-bk19/arch/ppc64/kernel/misc.S 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/misc.S 2003-06-14 13:53:23.000000000 -0700 @@ -27,6 +27,7 @@ #include #include #include +#include .text @@ -445,6 +446,95 @@ blr /* + * identify_cpu, + * In: r3 = base of the cpu_specs array + * r4 = address of cur_cpu_spec + * r5 = relocation offset + */ +_GLOBAL(identify_cpu) + mfpvr r7 +1: + lwz r8,CPU_SPEC_PVR_MASK(r3) + and r8,r8,r7 + lwz r9,CPU_SPEC_PVR_VALUE(r3) + cmplw 0,r9,r8 + beq 1f + addi r3,r3,CPU_SPEC_ENTRY_SIZE + b 1b +1: + add r3,r3,r5 + std r3,0(r4) + blr + +/* + * do_cpu_ftr_fixups - goes through the list of CPU feature fixups + * and writes nop's over sections of code that don't apply for this cpu. + * r3 = data offset (not changed) + */ +_GLOBAL(do_cpu_ftr_fixups) + /* Get CPU 0 features */ + LOADADDR(r6,cur_cpu_spec) + sub r6,r6,r3 + ld r4,0(r6) + sub r4,r4,r3 + ld r4,CPU_SPEC_FEATURES(r4) + /* Get the fixup table */ + LOADADDR(r6,__start___ftr_fixup) + sub r6,r6,r3 + LOADADDR(r7,__stop___ftr_fixup) + sub r7,r7,r3 + /* Do the fixup */ +1: cmpld r6,r7 + bgelr + addi r6,r6,32 + ld r8,-32(r6) /* mask */ + and r8,r8,r4 + ld r9,-24(r6) /* value */ + cmpld r8,r9 + beq 1b + ld r8,-16(r6) /* section begin */ + ld r9,-8(r6) /* section end */ + subf. r9,r8,r9 + beq 1b + /* write nops over the section of code */ + /* todo: if large section, add a branch at the start of it */ + srwi r9,r9,2 + mtctr r9 + sub r8,r8,r3 + lis r0,0x60000000@h /* nop */ +3: stw r0,0(r8) + andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l + beq 2f + dcbst 0,r8 /* suboptimal, but simpler */ + sync + icbi 0,r8 +2: addi r8,r8,4 + bdnz 3b + sync /* additional sync needed on g4 */ + isync + b 1b + +/* + * call_setup_cpu - call the setup_cpu function for this cpu + * r3 = data offset + * + * Setup function is called with: + * r3 = data offset + * r4 = ptr to CPU spec (relocated) + */ +_GLOBAL(call_setup_cpu) + LOADADDR(r4, cur_cpu_spec) + sub r4,r4,r3 + lwz r4,0(r4) # load pointer to cpu_spec + sub r4,r4,r3 # relocate + lwz r6,CPU_SPEC_SETUP(r4) # load function pointer + sub r6,r6,r3 + mtctr r6 + bctr + + + +/* * Create a kernel thread * kernel_thread(fn, arg, flags) */ diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/module.c linux-2.5.71/arch/ppc64/kernel/module.c --- linux-2.5.70-bk19/arch/ppc64/kernel/module.c 2003-05-26 18:01:00.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/module.c 2003-06-14 13:53:23.000000000 -0700 @@ -376,15 +376,57 @@ return 0; } +LIST_HEAD(module_bug_list); + int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) { + char *secstrings; + unsigned int i; + + me->arch.bug_table = NULL; + me->arch.num_bugs = 0; + + /* Find the __bug_table section, if present */ + secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + for (i = 1; i < hdr->e_shnum; i++) { + if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) + continue; + me->arch.bug_table = (void *) sechdrs[i].sh_addr; + me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry); + break; + } + + /* + * Strictly speaking this should have a spinlock to protect against + * traversals, but since we only traverse on BUG()s, a spinlock + * could potentially lead to deadlock and thus be counter-productive. + */ + list_add(&me->arch.bug_list, &module_bug_list); + sort_ex_table((struct exception_table_entry *)me->extable, (struct exception_table_entry *)me->extable + me->num_exentries); + return 0; } void module_arch_cleanup(struct module *mod) { + list_del(&mod->arch.bug_list); +} + +struct bug_entry *module_find_bug(unsigned long bugaddr) +{ + struct mod_arch_specific *mod; + unsigned int i; + struct bug_entry *bug; + + list_for_each_entry(mod, &module_bug_list, bug_list) { + bug = mod->bug_table; + for (i = 0; i < mod->num_bugs; ++i, ++bug) + if (bugaddr == bug->bug_addr) + return bug; + } + return NULL; } diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/pSeries_htab.c linux-2.5.71/arch/ppc64/kernel/pSeries_htab.c --- linux-2.5.70-bk19/arch/ppc64/kernel/pSeries_htab.c 2003-05-26 18:00:37.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/pSeries_htab.c 2003-06-14 13:53:23.000000000 -0700 @@ -21,6 +21,7 @@ #include #include #include +#include #define HPTE_LOCK_BIT 3 @@ -217,7 +218,7 @@ } /* Ensure it is out of the tlb too */ - if (cpu_has_tlbiel() && !large && local) { + if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) { _tlbiel(va); } else { spin_lock_irqsave(&pSeries_tlbie_lock, flags); @@ -283,7 +284,7 @@ } /* Invalidate the tlb */ - if (cpu_has_tlbiel() && !large && local) { + if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) { _tlbiel(va); } else { spin_lock_irqsave(&pSeries_tlbie_lock, flags); @@ -346,7 +347,7 @@ j++; } - if (cpu_has_tlbiel() && !large && local) { + if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) { asm volatile("ptesync":::"memory"); for (i = 0; i < j; i++) { diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/process.c linux-2.5.71/arch/ppc64/kernel/process.c --- linux-2.5.70-bk19/arch/ppc64/kernel/process.c 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/process.c 2003-06-14 13:53:23.000000000 -0700 @@ -45,6 +45,7 @@ #include #include #include +#include struct task_struct *last_task_used_math = NULL; @@ -412,7 +413,7 @@ * __get_free_pages() might give us a page > KERNBASE+256M which * is mapped with large ptes so we can't set up the guard page. */ - if (cpu_has_largepage()) + if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) return; for (i=0; i < NR_CPUS; i++) { diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/ras.c linux-2.5.71/arch/ppc64/kernel/ras.c --- linux-2.5.70-bk19/arch/ppc64/kernel/ras.c 2003-05-26 18:00:27.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/ras.c 2003-06-14 13:53:23.000000000 -0700 @@ -58,7 +58,6 @@ struct pt_regs * regs); static irqreturn_t ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs); -void init_ras_IRQ(void); /* #define DEBUG */ @@ -66,7 +65,8 @@ * Initialize handlers for the set of interrupts caused by hardware errors * and power system events. */ -void init_ras_IRQ(void) { +static int __init init_ras_IRQ(void) +{ struct device_node *np; unsigned int *ireg, len, i; @@ -91,7 +91,10 @@ ireg++; } } + + return 1; } +__initcall(init_ras_IRQ); /* * Handle power subsystem events (EPOW). diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/smp.c linux-2.5.71/arch/ppc64/kernel/smp.c --- linux-2.5.70-bk19/arch/ppc64/kernel/smp.c 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/smp.c 2003-06-14 13:53:23.000000000 -0700 @@ -47,6 +47,7 @@ #include "open_pic.h" #include #include +#include int smp_threads_ready; unsigned long cache_decay_ticks; @@ -583,7 +584,7 @@ paca[cpu].prof_multiplier = 1; paca[cpu].default_decr = tb_ticks_per_jiffy / decr_overclock; - if (!cpu_has_slb()) { + if (!(cur_cpu_spec->cpu_features & CPU_FTR_SLB)) { void *tmp; /* maximum of 48 CPUs on machines with a segment table */ diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/stab.c linux-2.5.71/arch/ppc64/kernel/stab.c --- linux-2.5.70-bk19/arch/ppc64/kernel/stab.c 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/stab.c 2003-06-14 13:53:23.000000000 -0700 @@ -21,6 +21,7 @@ #include #include #include +#include int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid); void make_slbe(unsigned long esid, unsigned long vsid, int large, @@ -38,7 +39,7 @@ esid = GET_ESID(KERNELBASE); vsid = get_kernel_vsid(esid << SID_SHIFT); - if (cpu_has_slb()) { + if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) { /* Invalidate the entire SLB & all the ERATS */ #ifdef CONFIG_PPC_ISERIES asm volatile("isync; slbia; isync":::"memory"); @@ -222,7 +223,7 @@ static inline void __ste_allocate(unsigned long esid, unsigned long vsid, int kernel_segment) { - if (cpu_has_slb()) { + if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) { #ifndef CONFIG_PPC_ISERIES if (REGION_ID(esid << SID_SHIFT) == KERNEL_REGION_ID) make_slbe(esid, vsid, 1, kernel_segment); @@ -275,7 +276,7 @@ esid = GET_ESID(ea); __ste_allocate(esid, vsid, kernel_segment); - if (!cpu_has_slb()) { + if (!(cur_cpu_spec->cpu_features & CPU_FTR_SLB)) { /* Order update */ asm volatile("sync":::"memory"); } @@ -327,7 +328,7 @@ } } - if (!cpu_has_slb()) { + if (!(cur_cpu_spec->cpu_features & CPU_FTR_SLB)) { /* Order update */ asm volatile("sync" : : : "memory"); } @@ -336,7 +337,7 @@ /* Flush all user entries from the segment table of the current processor. */ void flush_stab(struct task_struct *tsk, struct mm_struct *mm) { - if (cpu_has_slb()) { + if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) { /* * XXX disable 32bit slb invalidate optimisation until we fix * the issue where a 32bit app execed out of a 64bit app can diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/sys_ppc32.c linux-2.5.71/arch/ppc64/kernel/sys_ppc32.c --- linux-2.5.70-bk19/arch/ppc64/kernel/sys_ppc32.c 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/sys_ppc32.c 2003-06-14 13:53:23.000000000 -0700 @@ -1136,7 +1136,11 @@ u32 totalswap; u32 freeswap; unsigned short procs; - char _f[22]; + unsigned short pad; + u32 totalhigh; + u32 freehigh; + u32 mem_unit; + char _f[20-2*sizeof(long)-sizeof(int)]; }; extern asmlinkage long sys_sysinfo(struct sysinfo *info); @@ -1145,11 +1149,30 @@ { struct sysinfo s; int ret, err; + int bitcount=0; mm_segment_t old_fs = get_fs (); set_fs (KERNEL_DS); ret = sys_sysinfo(&s); set_fs (old_fs); + /* Check to see if any memory value is too large for 32-bit and + * scale down if needed. + */ + if ((s.totalram >> 32) || (s.totalswap >> 32)) { + while (s.mem_unit < PAGE_SIZE) { + s.mem_unit <<= 1; + bitcount++; + } + s.totalram >>=bitcount; + s.freeram >>= bitcount; + s.sharedram >>= bitcount; + s.bufferram >>= bitcount; + s.totalswap >>= bitcount; + s.freeswap >>= bitcount; + s.totalhigh >>= bitcount; + s.freehigh >>= bitcount; + } + err = put_user (s.uptime, &info->uptime); err |= __put_user (s.loads[0], &info->loads[0]); err |= __put_user (s.loads[1], &info->loads[1]); @@ -1161,6 +1184,9 @@ err |= __put_user (s.totalswap, &info->totalswap); err |= __put_user (s.freeswap, &info->freeswap); err |= __put_user (s.procs, &info->procs); + err |= __put_user (s.totalhigh, &info->totalhigh); + err |= __put_user (s.freehigh, &info->freehigh); + err |= __put_user (s.mem_unit, &info->mem_unit); if (err) return -EFAULT; diff -urN linux-2.5.70-bk19/arch/ppc64/kernel/traps.c linux-2.5.71/arch/ppc64/kernel/traps.c --- linux-2.5.70-bk19/arch/ppc64/kernel/traps.c 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/ppc64/kernel/traps.c 2003-06-14 13:53:23.000000000 -0700 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -306,6 +307,56 @@ _exception(SIGFPE, &info, regs); } +/* + * Look through the list of trap instructions that are used for BUG(), + * BUG_ON() and WARN_ON() and see if we hit one. At this point we know + * that the exception was caused by a trap instruction of some kind. + * Returns 1 if we should continue (i.e. it was a WARN_ON) or 0 + * otherwise. + */ +extern struct bug_entry __start___bug_table[], __stop___bug_table[]; + +#ifndef CONFIG_MODULES +#define module_find_bug(x) NULL +#endif + +static struct bug_entry *find_bug(unsigned long bugaddr) +{ + struct bug_entry *bug; + + for (bug = __start___bug_table; bug < __stop___bug_table; ++bug) + if (bugaddr == bug->bug_addr) + return bug; + return module_find_bug(bugaddr); +} + +int +check_bug_trap(struct pt_regs *regs) +{ + struct bug_entry *bug; + unsigned long addr; + + if (regs->msr & MSR_PR) + return 0; /* not in kernel */ + addr = regs->nip; /* address of trap instruction */ + if (addr < PAGE_OFFSET) + return 0; + bug = find_bug(regs->nip); + if (bug == NULL) + return 0; + if (bug->line & BUG_WARNING_TRAP) { + /* this is a WARN_ON rather than BUG/BUG_ON */ + printk(KERN_ERR "Badness in %s at %s:%d\n", + bug->function, bug->file, + bug->line & ~BUG_WARNING_TRAP); + dump_stack(); + return 1; + } + printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n", + bug->function, bug->file, bug->line); + return 0; +} + void ProgramCheckException(struct pt_regs *regs) { @@ -330,6 +381,10 @@ if (debugger_bpt && debugger_bpt(regs)) return; #endif + if (check_bug_trap(regs)) { + regs->nip += 4; + return; + } info.si_signo = SIGTRAP; info.si_errno = 0; info.si_code = TRAP_BRKPT; diff -urN linux-2.5.70-bk19/arch/ppc64/lib/copyuser.S linux-2.5.71/arch/ppc64/lib/copyuser.S --- linux-2.5.70-bk19/arch/ppc64/lib/copyuser.S 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/ppc64/lib/copyuser.S 2003-06-14 13:53:23.000000000 -0700 @@ -130,7 +130,7 @@ 6: cmpwi cr1,r5,8 addi r3,r3,32 sld r9,r9,r10 - blt cr1,.Ldo_tail + ble cr1,.Ldo_tail 34: ld r0,8(r4) srd r7,r0,r11 or r9,r7,r9 diff -urN linux-2.5.70-bk19/arch/ppc64/lib/string.S linux-2.5.71/arch/ppc64/lib/string.S --- linux-2.5.70-bk19/arch/ppc64/lib/string.S 2003-05-26 18:00:24.000000000 -0700 +++ linux-2.5.71/arch/ppc64/lib/string.S 2003-06-14 13:53:23.000000000 -0700 @@ -200,6 +200,7 @@ .llong 8b,92b .text +/* r3 = dst, r4 = src, r5 = count */ _GLOBAL(__strncpy_from_user) addi r6,r3,-1 addi r4,r4,-1 @@ -222,14 +223,10 @@ .llong 1b,99b .text -/* r3 = str, r4 = len (> 0), r5 = top (highest addr) */ +/* r3 = str, r4 = len (> 0) */ _GLOBAL(__strnlen_user) addi r7,r3,-1 - subf r6,r7,r5 /* top+1 - str */ - cmplw 0,r4,r6 - bge 0f - mr r6,r4 -0: mtctr r6 /* ctr = min(len, top - str) */ + mtctr r4 /* ctr = len */ 1: lbzu r0,1(r7) /* get next byte */ cmpwi 0,r0,0 bdnzf 2,1b /* loop if --ctr != 0 && byte != 0 */ diff -urN linux-2.5.70-bk19/arch/ppc64/mm/init.c linux-2.5.71/arch/ppc64/mm/init.c --- linux-2.5.70-bk19/arch/ppc64/mm/init.c 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/ppc64/mm/init.c 2003-06-14 13:53:23.000000000 -0700 @@ -59,6 +59,7 @@ #include #include #include +#include #include @@ -512,7 +513,7 @@ static struct kcore_list kcore_vmem; -static void setup_kcore(void) +static int __init setup_kcore(void) { int i; @@ -536,7 +537,10 @@ } kclist_add(&kcore_vmem, (void *)VMALLOC_START, VMALLOC_END-VMALLOC_START); + + return 0; } +module_init(setup_kcore); void initialize_paca_hardware_interrupt_stack(void); @@ -606,8 +610,6 @@ #endif mem_init_done = 1; - setup_kcore(); - /* set the last page of each hardware interrupt stack to be protected */ initialize_paca_hardware_interrupt_stack(); @@ -698,7 +700,7 @@ int local = 0; /* handle i-cache coherency */ - if (!cpu_has_noexecute()) { + if (!(cur_cpu_spec->cpu_features & CPU_FTR_NOEXECUTE)) { unsigned long pfn = pte_pfn(pte); if (pfn_valid(pfn)) { struct page *page = pfn_to_page(pfn); diff -urN linux-2.5.70-bk19/arch/ppc64/mm/numa.c linux-2.5.71/arch/ppc64/mm/numa.c --- linux-2.5.70-bk19/arch/ppc64/mm/numa.c 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/ppc64/mm/numa.c 2003-06-14 13:53:23.000000000 -0700 @@ -154,8 +154,28 @@ if (max_domain < numa_domain) max_domain = numa_domain; - node_data[numa_domain].node_start_pfn = start / PAGE_SIZE; - node_data[numa_domain].node_size = size / PAGE_SIZE; + /* + * For backwards compatibility, OF splits the first node + * into two regions (the first being 0-4GB). Check for + * this simple case and complain if there is a gap in + * memory + */ + if (node_data[numa_domain].node_size) { + unsigned long shouldstart = + node_data[numa_domain].node_start_pfn + + node_data[numa_domain].node_size; + if (shouldstart != (start / PAGE_SIZE)) { + printk(KERN_ERR "Hole in node, disabling " + "region start %lx length %lx\n", + start, size); + continue; + } + node_data[numa_domain].node_size += size / PAGE_SIZE; + } else { + node_data[numa_domain].node_start_pfn = + start / PAGE_SIZE; + node_data[numa_domain].node_size = size / PAGE_SIZE; + } for (i = start ; i < (start+size); i += MEMORY_INCREMENT) numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = @@ -174,6 +194,20 @@ return 0; } +void setup_nonnuma(void) +{ + unsigned long i; + + for (i = 0; i < NR_CPUS; i++) + map_cpu_to_node(i, 0); + + node_data[0].node_start_pfn = 0; + node_data[0].node_size = lmb_end_of_DRAM() / PAGE_SIZE; + + for (i = 0 ; i < lmb_end_of_DRAM(); i += MEMORY_INCREMENT) + numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = 0; +} + void __init do_init_bootmem(void) { int nid; @@ -181,9 +215,8 @@ min_low_pfn = 0; max_low_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT; - /* XXX FIXME: support machines without associativity information */ if (parse_numa_properties()) - BUG(); + setup_nonnuma(); for (nid = 0; nid < numnodes; nid++) { unsigned long start_paddr, end_paddr; @@ -204,7 +237,7 @@ NODE_DATA(nid)->bdata = &plat_node_bdata[nid]; - bootmap_pages = bootmem_bootmap_pages(end_paddr - start_paddr); + bootmap_pages = bootmem_bootmap_pages((end_paddr - start_paddr) >> PAGE_SHIFT); dbg("bootmap_pages = %lx\n", bootmap_pages); bootmem_paddr = lmb_alloc_base(bootmap_pages << PAGE_SHIFT, diff -urN linux-2.5.70-bk19/arch/ppc64/vmlinux.lds.S linux-2.5.71/arch/ppc64/vmlinux.lds.S --- linux-2.5.70-bk19/arch/ppc64/vmlinux.lds.S 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/ppc64/vmlinux.lds.S 2003-06-14 13:53:23.000000000 -0700 @@ -65,6 +65,14 @@ __ex_table : { *(__ex_table) } __stop___ex_table = .; + __start___bug_table = .; + __bug_table : { *(__bug_table) } + __stop___bug_table = .; + + __start___ftr_fixup = .; + __ftr_fixup : { *(__ftr_fixup) } + __stop___ftr_fixup = .; + . = ALIGN(16384); /* init_task */ .data.init_task : { *(.data.init_task) } diff -urN linux-2.5.70-bk19/arch/sh/Kconfig linux-2.5.71/arch/sh/Kconfig --- linux-2.5.70-bk19/arch/sh/Kconfig 2003-05-26 18:01:00.000000000 -0700 +++ linux-2.5.71/arch/sh/Kconfig 2003-06-14 13:53:23.000000000 -0700 @@ -12,11 +12,7 @@ The SuperH is a RISC processor targeted for use in embedded systems and consumer electronics; it was also used in the Sega Dreamcast gaming console. The SuperH port has a home page at - . - -config MMU - bool - default y + . config UID16 bool @@ -33,60 +29,18 @@ bool default y +config VARIABLE_CLOCK_TICK_RATE + bool + default y + source "init/Kconfig" -menu "Processor type and features" +menu "System type" choice prompt "SuperH system type" - default SH_GENERIC - -config SH_GENERIC - bool "Generic" - ---help--- - Select Generic if configuring for a generic SuperH system. - The "generic" option compiles in *all* the possible hardware - support and relies on the sh_mv= kernel commandline option to choose - at runtime which routines to use. "MV" stands for "machine vector"; - each of the machines below is described by a machine vector. - - Select SolutionEngine if configuring for a Hitachi SH7709 - or SH7750/7750S evalutation board. - - Select Overdrive if configuring for a ST407750 Overdrive board. - More information at - . - - Select HP620 if configuring for a HP Jornada HP620. - More information (hardware only) at - . - - Select HP680 if configuring for a HP Jornada HP680. - More information (hardware only) at - . - - Select HP690 if configuring for a HP Jornada HP690. - More information (hardware only) at - . - - Select CqREEK if configuring for a CqREEK SH7708 or SH7750. - More information at - . - - Select DMIDA if configuring for a DataMyte 4000 Industrial - Digital Assistant. More information at . - - Select EC3104 if configuring for a system with an Eclipse - International EC3104 chip, e.g. the Harris AD2000 or Compaq Aero 8000. - - Select Dreamcast if configuring for a SEGA Dreamcast. - More information at - . There is a - Dreamcast project is at . - - Select BareCPU if you know what this means, and it applies - to your system. + default SH_UNKNOWN config SH_SOLUTION_ENGINE bool "SolutionEngine" @@ -146,6 +100,9 @@ Select EC3104 if configuring for a system with an Eclipse International EC3104 chip, e.g. the Harris AD2000. +config SH_SATURN + bool "Saturn" + config SH_DREAMCAST bool "Dreamcast" help @@ -162,10 +119,19 @@ config SH_SH2000 bool "SH2000" + help + SH-2000 is a single-board computer based around SH7709A chip + intended for embedded applications. + It has an Ethernet interface (CS8900A), direct connected + Compact Flash socket, three serial ports and PC-104 bus. + More information at . config SH_ADX bool "ADX" +config SH_MPC1211 + bool "MPC1211" + config SH_UNKNOWN bool "BareCPU" help @@ -180,6 +146,119 @@ endchoice +config MMU + bool "Support for memory management hardware" + depends on !CPU_SH2 + default y + help + Early SH processors (such as the SH7604) lack an MMU. In order to + boot on these systems, this option must not be set. + + On other systems (such as the SH-3 and 4) where an MMU exists, + turning this off will boot the kernel on these machines with the + MMU implicitly switched off. + +config CMDLINE_BOOL + bool "Default bootloader kernel arguments" + +config CMDLINE + string "Initial kernel command string" + depends on CMDLINE_BOOL + default "console=ttySC1,115200" + +# Platform-specific memory start and size definitions +config MEMORY_START + hex "Physical memory start address" if !MEMORY_SET || MEMORY_OVERRIDE + default "08000000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || SH_MPC1211 + default "0c000000" if !MEMORY_OVERRIDE && (SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE) + ---help--- + Computers built with Hitachi SuperH processors always + map the ROM starting at address zero. But the processor + does not specify the range that RAM takes. + + The physical memory (RAM) start address will be automatically + set to 08000000, unless you selected one of the following + processor types: SolutionEngine, Overdrive, HP620, HP680, HP690, + in which case the start address will be set to 0c000000. + + Tweak this only when porting to a new machine which is not already + known by the config system. Changing it from the known correct + value on any of the known systems will only lead to disaster. + +config MEMORY_SIZE + hex "Physical memory size" if !MEMORY_SET || MEMORY_OVERRIDE + default "00400000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || !MEMORY_OVERRIDE && (SH_HP600 || SH_BIGSUR || SH_SH2000) + default "01000000" if !MEMORY_OVERRIDE && SH_DREAMCAST + default "04000000" if !MEMORY_OVERRIDE && SH_7751_SOLUTION_ENGINE + default "02000000" if !MEMORY_OVERRIDE && SH_SOLUTION_ENGINE + default "08000000" if SH_MPC1211 + help + This sets the default memory size assumed by your SH kernel. It can + be overridden as normal by the 'mem=' argument on the kernel command + line. If unsure, consult your board specifications or just leave it + as 0x00400000 which was the default value before this became + configurable. + +config MEMORY_SET + bool + depends on !MEMORY_OVERRIDE && (SH_MPC1211 || SH_ADX || SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE) + default y + help + This is an option about which you will never be asked a question. + Therefore, I conclude that you do not exist - go away. + + There is a grue here. + +# If none of the above have set memory start/size, ask the user. +config MEMORY_OVERRIDE + bool "Override default load address and memory size" + +# XXX: break these out into the board-specific configs below +config CF_ENABLER + bool "Compact Flash Enabler support" + depends on SH_ADX || SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_CAT68701 + ---help--- + Compact Flash is a small, removable mass storage device introduced + in 1994 originally as a PCMCIA device. If you say `Y' here, you + compile in support for Compact Flash devices directly connected to + a SuperH processor. A Compact Flash FAQ is available at + . + + If your board has "Directly Connected" CompactFlash at area 5 or 6, + you may want to enable this option. Then, you can use CF as + primary IDE drive (only tested for SanDisk). + + If in doubt, select 'N'. + +choice + prompt "Compact Flash Connection Area" + depends on CF_ENABLER + default CF_AREA6 + +config CF_AREA5 + bool "Area5" + help + If your board has "Directly Connected" CompactFlash, You should + select the area where your CF is connected to. + + - "Area5" if CompactFlash is connected to Area 5 (0x14000000) + - "Area6" if it is connected to Area 6 (0x18000000) + + "Area6" will work for most boards. For ADX, select "Area5". + +config CF_AREA6 + bool "Area6" + +endchoice + +config CF_BASE_ADDR + hex + depends on CF_ENABLER + default "b8000000" if CF_AREA6 + default "b4000000" if CF_AREA5 + +endmenu + # The SH7750 RTC module is disabled in the Dreamcast config SH_RTC bool @@ -191,21 +270,50 @@ If unsure, say N. +# This is also board-specific +config PCI_AUTO + bool + config SH_HP600 bool depends on SH_HP620 || SH_HP680 || SH_HP690 default y +config DISCONTIGMEM + bool + depends on SH_HP690 + default y + help + Say Y to upport efficient handling of discontiguous physical memory, + for architectures which are either NUMA (Non-Uniform Memory Access) + or have huge holes in the physical address space for other reasons. + See for more. + + +menu "Processor type and features" + +# +# Ick, get rid of all this CPU_SUBTYPE nonsense. Just probe it, fill in +# cpu_data, and leave it alone. (Feasible for SH-4 at least, and some +# SH-3). ++paulm +# choice prompt "Processor type" default CPU_SUBTYPE_SH7708 +config CPU_SUBTYPE_SH7604 + bool "SH7604" + help + Select SH7604 if you have SH7604 + config CPU_SUBTYPE_SH7707 bool "SH7707" ---help--- Select the type of SuperH processor you have. This information is used for optimizing and configuration purposes. + Select SH7604 if you have a SH-2 CPU. + Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU. Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or @@ -237,174 +345,188 @@ config CPU_SUBTYPE_SH7751 bool "SH7751" + help + Select SH7750 if you have a 166 Mhz SH-4 HD6417751 CPU. config CPU_SUBTYPE_ST40STB1 bool "ST40STB1" + help + Select ST40STB1 if you have a ST40STB1 CPU. endchoice +config CPU_SH2 + bool + depends on CPU_SUBTYPE_SH7604 + default y + config CPU_SH3 bool - depends on CPU_SUBTYPE_SH7709 || CPU_SUBTYPE_SH7708 || CPU_SUBTYPE_SH7707 + depends on !CPU_SH2 && (CPU_SUBTYPE_SH7707 || CPU_SUBTYPE_SH7708 || CPU_SUBTYPE_SH7709) default y config CPU_SH4 bool - depends on CPU_SUBTYPE_ST40STB1 || CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7750 + depends on !CPU_SH3 && !CPU_SH2 && (CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_ST40STB1) default y -config CPU_LITTLE_ENDIAN - bool "Little Endian" +config ZERO_PAGE_OFFSET + hex "Zero page offset" + default "00001000" if !SH_MPC1211 + default "00004000" if SH_MPC1211 help - Some MIPS machines can be configured for either little or big endian - byte order. These modes require different kernels. Say Y if your - machine is little endian, N if it's a big endian machine. - -# Platform-specific memory start and size definitions -config MEMORY_START - hex "Physical memory start address" if !MEMORY_SET - default "08000000" if !MEMORY_SET || SH_ADX || CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY - default "0c000000" if SH_HP600 || SH_BIGSUR || SH_DREAMCAST || SH_SH2000 || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE - ---help--- - Computers built with Hitachi SuperH processors always - map the ROM starting at address zero. But the processor - does not specify the range that RAM takes. + This sets the default offset of zero page. - The physical memory (RAM) start address will be automatically - set to 08000000, unless you selected one of the following - processor types: SolutionEngine, Overdrive, HP620, HP680, HP690, - in which case the start address will be set to 0c000000. +# XXX: needs to lose subtype for system type +config ST40_LMI_MEMORY + bool "Memory on LMI" + depends on CPU_SUBTYPE_ST40STB1 - Tweak this only when porting to a new machine which is not already - known by the config system. Changing it from the known correct - value on any of the known systems will only lead to disaster. +config MEMORY_START + hex + depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY + default "08000000" config MEMORY_SIZE - hex "Physical memory size" if !MEMORY_SET - default "00400000" if !MEMORY_SET || SH_ADX || CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY || SH_HP600 || SH_BIGSUR || SH_DREAMCAST || SH_SH2000 - default "04000000" if SH_7751_SOLUTION_ENGINE - default "02000000" if SH_SOLUTION_ENGINE - help - This sets the default memory size assumed by your SH kernel. It can - be overridden as normal by the 'mem=' argument on the kernel command - line. If unsure, consult your board specifications or just leave it - as 0x00400000 which was the default value before this became - configurable. + hex + depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY + default "00400000" config MEMORY_SET bool - depends on SH_ADX || CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY || SH_HP600 || SH_BIGSUR || SH_DREAMCAST || SH_SH2000 || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE + depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY default y + +config CPU_LITTLE_ENDIAN + bool "Little Endian" help - This is an option about which you will never be asked a question. - Therefore, I conclude that you do not exist - go away. + Some SuperH machines can be configured for either little or big + endian byte order. These modes require different kernels. Say Y if + your machine is little endian, N if it's a big endian machine. + +config PREEMPT + bool "Preemptible Kernel (EXPERIMENTAL)" + depends on EXPERIMENTAL + +config UBC_WAKEUP + bool "Wakeup UBC on startup" + help + Selecting this option will wakeup the User Break Controller (UBC) on + startup. Although the UBC is left in an awake state when the processor + comes up, some boot loaders misbehave by putting the UBC to sleep in a + power saving state, which causes issues with things like ptrace(). - There is a grue here. + If unsure, say N. -config ST40_LMI_MEMORY - bool "Memory on LMI" - depends on CPU_SUBTYPE_ST40STB1 +config SH_WRITETHROUGH + bool "Use write-through caching" + default y if CPU_SH2 + help + Selecting this option will configure the caches in write-through + mode, as opposed to the default write-back configuration. + + Since there's sill some aliasing issues on SH-4, this option will + unfortunately still require the majority of flushing functions to + be implemented to deal with aliasing. -# If none of the above have set memory start/size, ask the user. -endmenu + If unsure, say N. -config DISCONTIGMEM - bool - depends on SH_HP690 - default y +config SH_OCRAM + bool "Operand Cache RAM (OCRAM) support" help - Say Y to upport efficient handling of discontiguous physical memory, - for architectures which are either NUMA (Non-Uniform Memory Access) - or have huge holes in the physical address space for other reasons. - See for more. + Selecting this option will automatically tear down the number of + sets in the dcache by half, which in turn exposes a memory range. + The addresses for the OC RAM base will vary according to the + processor version. Consult vendor documentation for specifics. -menu "General setup" - -# Even on SuperH devices which don't have an ISA bus, -# this variable helps the PCMCIA modules handle -# IRQ requesting properly -- Greg Banks. -config ISA - bool - default y - help - Find out whether you have ISA slots on your motherboard. ISA is the - name of a bus system, i.e. the way the CPU talks to the other stuff - inside your box. Other bus systems are PCI, EISA, MicroChannel - (MCA) or VESA. ISA is an older system, now being displaced by PCI; - newer boards don't support it. If you have ISA, say Y, otherwise N. + If unsure, say N. -config EISA - bool +config SMP + bool "Symmetric multi-processing support" ---help--- - The Extended Industry Standard Architecture (EISA) bus was - developed as an open alternative to the IBM MicroChannel bus. + This enables support for systems with more than one CPU. If you have + a system with only one CPU, like most personal computers, say N. If + you have a system with more than one CPU, say Y. + + If you say N here, the kernel will run on single and multiprocessor + machines, but will use only one CPU of a multiprocessor machine. If + you say Y here, the kernel will run on many, but not all, + singleprocessor machines. On a singleprocessor machine, the kernel + will run faster if you say N here. + + People using multiprocessor machines who say Y here should also say + Y to "Enhanced Real Time Clock Support", below. + + See also the , + , + and the SMP-HOWTO available at + . - The EISA bus provided some of the features of the IBM MicroChannel - bus while maintaining backward compatibility with cards made for - the older ISA bus. The EISA bus saw limited use between 1988 and - 1995 when it was made obsolete by the PCI bus. + If you don't know what to do here, say N. - Say Y here if you are building a kernel for an EISA-based machine. +config NR_CPUS + int "Maximum number of CPUs (2-32)" + depends on SMP + default "2" + help + This allows you to specify the maximum number of CPUs which this + kernel will support. The maximum supported value is 32 and the + minimum value which makes sense is 2. - Otherwise, say N. + This is purely to save memory - each supported CPU adds + approximately eight kilobytes to the kernel image. -config MCA - bool +config SH_DMA + bool "DMA controller (DMAC) support" help - MicroChannel Architecture is found in some IBM PS/2 machines and - laptops. It is a bus system similar to PCI or ISA. See - (and especially the web page given - there) before attempting to build an MCA bus kernel. - -config SBUS - bool + Selecting this option will provide same API as PC's Direct Memory + Access Controller(8237A) for SuperH DMAC. -config CF_ENABLER - bool "Compact Flash Enabler support" - depends on SH_GENERIC || SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_CAT68701 || SH_ADX - ---help--- - Compact Flash is a small, removable mass storage device introduced - in 1994 originally as a PCMCIA device. If you say `Y' here, you - compile in support for Compact Flash devices directly connected to - a SuperH processor. A Compact Flash FAQ is available at - . + If unsure, say N. - If your board has "Directly Connected" CompactFlash at area 5 or 6, - you may want to enable this option. Then, you can use CF as - primary IDE drive (only tested for SanDisk). +config CPU_FREQ + bool "CPU Frequency scaling" + help + CPU clock scaling allows you to change the clock speed of the + running CPU on the fly. - If in doubt, select 'N'. + For details, take a look at . -choice - prompt "Compact Flash Connection Area" - depends on CF_ENABLER - default CF_AREA6 + If unsure, say N. -config CF_AREA5 - bool "Area5" +config CPU_FREQ_TABLE + tristate "CPU frequency table helpers" + depends on CPU_FREQ + default y help - If your board has "Directly Connected" CompactFlash, You should - select the area where your CF is connected to. + Many cpufreq drivers use these helpers, so only say N here if + the cpufreq driver of your choice doesn't need these helpers. - - "Area5" if CompactFlash is connected to Area 5 (0x14000000) - - "Area6" if it is connected to Area 6 (0x18000000) + If unsure, say Y. - "Area6" will work for most boards. For ADX, select "Area5". +config SH_CPU_FREQ + tristate "SuperH CPU Frequency driver" + depends on CPU_FREQ + help + This adds the cpufreq driver for SuperH. At present, only + the SH-4 is supported. -config CF_AREA6 - bool "Area6" + For details, take a look at . -endchoice + If unsure, say N. -config CF_BASE_ADDR - hex - depends on CF_ENABLER - default "b8000000" if CF_AREA6 - default "b4000000" if CF_AREA5 +source "drivers/cpufreq/Kconfig" + +# A board must have defined HD6446X_SERIES in order to see these +choice + prompt "HD6446x options" + depends HD6446X_SERIES + default HD64461 config HD64461 bool "Hitachi HD64461 companion chip support" + depends on CPU_SUBTYPE_SH7709 ---help--- The Hitachi HD64461 provides an interface for the SH7709 CPU, supporting a LCD controller, @@ -417,6 +539,24 @@ Say Y if you want support for the HD64461. Otherwise, say N. +config HD64465 + bool "Hitachi HD64465 companion chip support" + depends on CPU_SUBTYPE_SH7750 + ---help--- + The Hitachi HD64465 provides an interface for + the SH7750 CPU, supporting a LCD controller, + CRT color controller, IrDA, USB, PCMCIA, + keyboard controller, and a printer interface. + + More information is available at + . + + Say Y if you want support for the HD64465. + Otherwise, say N. + +endchoice + +# These will also be split into the Kconfig's below config HD64461_IRQ int "HD64461 IRQ" depends on HD64461 @@ -434,19 +574,6 @@ via the HD64461 companion chip. Otherwise, say N. -config HD64465 - bool "Hitachi HD64465 companion chip support" - ---help--- - The Hitachi HD64465 provides an interface for - the SH7750 CPU, supporting a LCD controller, - CRT color controller, IrDA, USB, PCMCIA, - keyboard controller, and a printer interface. - - More information is available at - . - - Say Y if you want support for the HD64465. - Otherwise, say N. config HD64465_IOBASE hex "HD64465 start address" @@ -466,13 +593,49 @@ Do not change this unless you know what you are doing. -config SH_DMA - bool "DMA controller (DMAC) support" +endmenu + + +menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" + +# Even on SuperH devices which don't have an ISA bus, +# this variable helps the PCMCIA modules handle +# IRQ requesting properly -- Greg Banks. +config ISA + bool + default y help - Selecting this option will provide same API as PC's Direct Memory - Access Controller(8237A) for SuperH DMAC. + Find out whether you have ISA slots on your motherboard. ISA is the + name of a bus system, i.e. the way the CPU talks to the other stuff + inside your box. Other bus systems are PCI, EISA, MicroChannel + (MCA) or VESA. ISA is an older system, now being displaced by PCI; + newer boards don't support it. If you have ISA, say Y, otherwise N. - If unsure, say N. +config EISA + bool + ---help--- + The Extended Industry Standard Architecture (EISA) bus was + developed as an open alternative to the IBM MicroChannel bus. + + The EISA bus provided some of the features of the IBM MicroChannel + bus while maintaining backward compatibility with cards made for + the older ISA bus. The EISA bus saw limited use between 1988 and + 1995 when it was made obsolete by the PCI bus. + + Say Y here if you are building a kernel for an EISA-based machine. + + Otherwise, say N. + +config MCA + bool + help + MicroChannel Architecture is found in some IBM PS/2 machines and + laptops. It is a bus system similar to PCI or ISA. See + (and especially the web page given + there) before attempting to build an MCA bus kernel. + +config SBUS + bool config PCI bool "PCI support" @@ -559,6 +722,13 @@ source "drivers/pcmcia/Kconfig" +source "drivers/hotplug/Kconfig" + +endmenu + + +menu "Executable file formats" + choice prompt "Kernel core (/proc/kcore) format" depends on PROC_FS @@ -622,6 +792,9 @@ will be called binfmt_elf. Saying M or N here is dangerous because some crucial programs on your system might be in ELF format. +config BINFMT_FLAT + tristate "Kernel support for FLAT binaries" + config BINFMT_MISC tristate "Kernel support for MISC binaries" ---help--- @@ -647,15 +820,13 @@ you have use for it; the module is called binfmt_misc. If you don't know what to answer at this point, say Y. -source "drivers/parport/Kconfig" - endmenu source "drivers/mtd/Kconfig" -source "drivers/block/Kconfig" +source "drivers/parport/Kconfig" -source "drivers/md/Kconfig" +source "drivers/block/Kconfig" menu "ATA/ATAPI/MFM/RLL support" @@ -711,10 +882,10 @@ endmenu -menu "SCSI support" +menu "SCSI device support" config SCSI - tristate "SCSI support" + tristate "SCSI device support" ---help--- If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or any other SCSI device under Linux, say Y and make sure that you know @@ -737,9 +908,6 @@ endmenu -source "drivers/ieee1394/Kconfig" - -source "net/Kconfig" menu "Old CD-ROM drivers (not SCSI, not IDE)" @@ -776,8 +944,22 @@ endmenu +source "drivers/md/Kconfig" + +source "drivers/ieee1394/Kconfig" + +source "net/Kconfig" + +source "net/ax25/Kconfig" + +source "net/irda/Kconfig" + +source "drivers/isdn/Kconfig" + +source "drivers/telephony/Kconfig" + # -# input before char - char/joystick depends on it. As does USB. +# input - input/joystick depends on it. As does USB. # source "drivers/input/Kconfig" @@ -837,6 +1019,11 @@ If unsure, say Y. +config HW_CONSOLE + bool + depends on VT && !S390 && !UM + default y + config SERIAL tristate "Serial (8250, 16450, 16550 or compatible) support" ---help--- @@ -948,7 +1135,7 @@ config HEARTBEAT bool "Heartbeat LED" - depends on SH_GENERIC || SH_CAT68701 || SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE + depends on SH_MPC1211 || SH_CAT68701 || SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE help Use the power-on LED on your machine as a load meter. The exact behavior is platform-dependent, but normally the flash frequency is @@ -971,7 +1158,6 @@ endmenu -#source drivers/char/joystick/Config.in config PRINTER tristate "Parallel printer support" depends on PARPORT @@ -1095,12 +1281,18 @@ it has been started. config SH_WDT - tristate "SH 3/4 Watchdog" + tristate "SuperH Watchdog" depends on WATCHDOG help This driver adds watchdog support for the integrated watchdog in the - SuperH 3 and 4 processors. If you have one of these processors, say Y, - otherwise say N. + SuperH processors. If you have one of these processors and wish + to have watchdog support enabled, say Y, otherwise say N. + + As a side note, saying Y here will automatically boost HZ to 1000 + so that the timer has a chance to clear the overflow counter. On + slower systems (such as the SH-2 and SH-3) this will likely yield + some performance issues. As such, the WDT should be avoided here + unless it is absolutely necessary. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -1138,6 +1330,10 @@ source "drivers/char/pcmcia/Kconfig" +source "drivers/serial/Kconfig" + +source "drivers/i2c/Kconfig" + endmenu source "fs/Kconfig" @@ -1182,6 +1378,10 @@ endmenu +source "drivers/usb/Kconfig" + +source "net/bluetooth/Kconfig" + menu "Kernel hacking" @@ -1198,6 +1398,14 @@ keys are documented in . Don't say Y unless you really know what this hack does. +config DEBUG_SPINLOCK + bool "Spinlock debugging" + help + Say Y here and build SMP to catch missing spinlock initialization + and certain other kinds of spinlock errors commonly made. This is + best used in conjunction with the NMI watchdog so that spinlock + deadlocks are also debuggable. + config SH_STANDARD_BIOS bool "Use LinuxSH standard BIOS" help diff -urN linux-2.5.70-bk19/arch/sh/Makefile linux-2.5.71/arch/sh/Makefile --- linux-2.5.70-bk19/arch/sh/Makefile 2003-05-26 18:00:42.000000000 -0700 +++ linux-2.5.71/arch/sh/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -1,10 +1,12 @@ -# $Id: Makefile,v 1.6 2000/06/10 03:03:52 gniibe Exp $ +# $Id: Makefile,v 1.17 2003/05/20 03:12:54 lethal Exp $ # # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive # for more details. # # Copyright (C) 1999 Kaz Kojima +# Copyright (C) 2002, 2003 Paul Mundt +# Copyright (C) 2002 M. R. Brown # # This file is included by the global makefile so that you can add your own # architecture-specific flags and dependencies. Remember to do have actions @@ -12,72 +14,116 @@ # this architecture # -ifdef CONFIG_CPU_LITTLE_ENDIAN -CFLAGS += -ml -AFLAGS += -ml -# LDFLAGS_vmlinux += -EL -LDFLAGS := -EL -else -CFLAGS += -mb -AFLAGS += -mb -# LDFLAGS_vmlinux += -EB -LDFLAGS := -EB +# +# We don't necessarily agree with the top-level Makefile with regards to what +# does and does not qualify as a noconfig_targets rule. In this case, we're +# still dependant on .config settings in order for core-y (machdir-y in +# particular) to resolve the proper directory. So we just manually include it +# if it hasn't been already.. +# +ifndef include_config +-include .config endif -OBJCOPYFLAGS := -O binary -R .note -R .comment -R .stab -R .stabstr -S - -MODFLAGS += +cpu-y := -mb +cpu-$(CONFIG_CPU_LITTLE_ENDIAN) := -ml -# -# - -ifdef CONFIG_CPU_SH3 -CFLAGS += -m3 -AFLAGS += -m3 +cpu-$(CONFIG_CPU_SH2) += -m2 +cpu-$(CONFIG_CPU_SH3) += -m3 +cpu-$(CONFIG_CPU_SH4) += -m4 -mno-implicit-fp + +ifdef CONFIG_SH_KGDB +CFLAGS :=$(CFLAGS:-fomit-frame-pointer=) -g +AFLAGS += -g +ifdef CONFIG_KGDB_MORE +CFLAGS += $(shell echo $(CONFIG_KGDB_OPTIONS) | sed -e 's/"//g') endif -ifdef CONFIG_CPU_SH4 -CFLAGS += -m4 -mno-implicit-fp -AFLAGS += -m4 -mno-implicit-fp endif +OBJCOPYFLAGS := -O binary -R .note -R .comment -R .stab -R .stabstr -S + # # Choosing incompatible machines durings configuration will result in # error messages during linking. # LDFLAGS_vmlinux += -e _stext -ifdef LOADADDR -LDFLAGS_vmlinux += -Ttext $(word 1,$(LOADADDR)) +ifdef CONFIG_CPU_LITTLE_ENDIAN +LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64' -EL +LDFLAGS_BLOB :=--format binary --oformat elf32-sh-linux +else +LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64+4' -EB +LDFLAGS_BLOB :=--format binary --oformat elf32-shbig-linux endif -# -CFLAGS += -pipe +CFLAGS += -pipe $(cpu-y) +AFLAGS += $(cpu-y) head-y := arch/sh/kernel/head.o arch/sh/kernel/init_task.o LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) core-y += arch/sh/kernel/ arch/sh/mm/ -core-$(CONFIG_SH_GENERIC) += arch/sh/stboards/ -core-$(CONFIG_SH_STB1_HARP) += arch/sh/stboards/ -core-$(CONFIG_SH_STB1_OVERDRIVE)+= arch/sh/stboards/ + +# Boards +machdir-$(CONFIG_SH_SOLUTION_ENGINE) := se/770x +machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE) := se/7751 +machdir-$(CONFIG_SH_STB1_HARP) := harp +machdir-$(CONFIG_SH_STB1_OVERDRIVE) := overdrive +machdir-$(CONFIG_SH_HP620) := hp6xx/hp620 +machdir-$(CONFIG_SH_HP680) := hp6xx/hp680 +machdir-$(CONFIG_SH_HP690) := hp6xx/hp690 +machdir-$(CONFIG_SH_CQREEK) := cqreek +machdir-$(CONFIG_SH_DMIDA) := dmida +machdir-$(CONFIG_SH_EC3104) := ec3104 +machdir-$(CONFIG_SH_SATURN) := saturn +machdir-$(CONFIG_SH_DREAMCAST) := dreamcast +machdir-$(CONFIG_SH_CAT68701) := cat68701 +machdir-$(CONFIG_SH_BIGSUR) := bigsur +machdir-$(CONFIG_SH_SH2000) := sh2000 +machdir-$(CONFIG_SH_ADX) := adx +machdir-$(CONFIG_SH_MPC1211) := mpc1211 +machdir-$(CONFIG_SH_UNKNOWN) := unknown + +incdir-y := $(machdir-y) + +incdir-$(CONFIG_SH_SOLUTION_ENGINE) := se +incdir-$(CONFIG_SH_7751_SOLUTION_ENGINE) := se7751 +incdir-$(CONFIG_SH_HP600) := hp6xx + +core-y += arch/sh/boards/$(machdir-y)/ + +# Companion chips +core-$(CONFIG_HD64461) += arch/sh/cchips/hd6446x/hd64461/ +core-$(CONFIG_HD64465) += arch/sh/cchips/hd6446x/hd64465/ + +cpuincdir-$(CONFIG_CPU_SH2) := cpu-sh2 +cpuincdir-$(CONFIG_CPU_SH3) := cpu-sh3 +cpuincdir-$(CONFIG_CPU_SH4) := cpu-sh4 + libs-y += arch/sh/lib/ $(LIBGCC) -MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot +boot := arch/sh/boot AFLAGS_vmlinux.lds.o := -traditional +prepare: target_links + +.PHONY: target_links FORCE +target_links: + @echo ' Making asm-sh/cpu -> asm-sh/$(cpuincdir-y) link' + @ln -sf $(cpuincdir-y) include/asm-sh/cpu + + @echo ' Making asm-sh/mach -> asm-sh/$(incdir-y) link' + @ln -sf $(incdir-y) include/asm-sh/mach + + $(Q)$(MAKE) $(build)=arch/sh/tools include/asm-sh/machtypes.h + +BOOTIMAGE=arch/sh/boot/zImage zImage: vmlinux - @$(MAKEBOOT) zImage + $(Q)$(MAKE) $(build)=$(boot) $(BOOTIMAGE) compressed: zImage -zdisk: vmlinux - @$(MAKEBOOT) zdisk - archclean: - @$(MAKEBOOT) clean - $(MAKE) -C arch/$(ARCH)/kernel clean - $(MAKE) -C arch/$(ARCH)/stboards clean -# $(MAKE) -C arch/$(ARCH)/tools clean - + $(Q)$(MAKE) $(clean)=$(boot) diff -urN linux-2.5.70-bk19/arch/sh/boards/adx/Makefile linux-2.5.71/arch/sh/boards/adx/Makefile --- linux-2.5.70-bk19/arch/sh/boards/adx/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/adx/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,10 @@ +# +# Makefile for ADX boards +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := mach.o setup.o io.o irq.o irq_maskreq.o + diff -urN linux-2.5.70-bk19/arch/sh/boards/adx/io.c linux-2.5.71/arch/sh/boards/adx/io.c --- linux-2.5.70-bk19/arch/sh/boards/adx/io.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/adx/io.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,195 @@ +/* + * linux/arch/sh/kernel/io_adx.c + * + * Copyright (C) 2001 A&D Co., Ltd. + * + * I/O routine and setup routines for A&D ADX Board + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + */ + +#include +#include +#include + +#define PORT2ADDR(x) (adx_isa_port2addr(x)) + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); +} + +unsigned char adx_inb(unsigned long port) +{ + return *(volatile unsigned char*)PORT2ADDR(port); +} + +unsigned short adx_inw(unsigned long port) +{ + return *(volatile unsigned short*)PORT2ADDR(port); +} + +unsigned int adx_inl(unsigned long port) +{ + return *(volatile unsigned long*)PORT2ADDR(port); +} + +unsigned char adx_inb_p(unsigned long port) +{ + unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); + + delay(); + return v; +} + +unsigned short adx_inw_p(unsigned long port) +{ + unsigned long v = *(volatile unsigned short*)PORT2ADDR(port); + + delay(); + return v; +} + +unsigned int adx_inl_p(unsigned long port) +{ + unsigned long v = *(volatile unsigned long*)PORT2ADDR(port); + + delay(); + return v; +} + +void adx_insb(unsigned long port, void *buffer, unsigned long count) +{ + unsigned char *buf = buffer; + while(count--) *buf++ = inb(port); +} + +void adx_insw(unsigned long port, void *buffer, unsigned long count) +{ + unsigned short *buf = buffer; + while(count--) *buf++ = inw(port); +} + +void adx_insl(unsigned long port, void *buffer, unsigned long count) +{ + unsigned long *buf = buffer; + while(count--) *buf++ = inl(port); +} + +void adx_outb(unsigned char b, unsigned long port) +{ + *(volatile unsigned char*)PORT2ADDR(port) = b; +} + +void adx_outw(unsigned short b, unsigned long port) +{ + *(volatile unsigned short*)PORT2ADDR(port) = b; +} + +void adx_outl(unsigned int b, unsigned long port) +{ + *(volatile unsigned long*)PORT2ADDR(port) = b; +} + +void adx_outb_p(unsigned char b, unsigned long port) +{ + *(volatile unsigned char*)PORT2ADDR(port) = b; + delay(); +} + +void adx_outw_p(unsigned short b, unsigned long port) +{ + *(volatile unsigned short*)PORT2ADDR(port) = b; + delay(); +} + +void adx_outl_p(unsigned int b, unsigned long port) +{ + *(volatile unsigned long*)PORT2ADDR(port) = b; + delay(); +} + +void adx_outsb(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned char *buf = buffer; + while(count--) outb(*buf++, port); +} + +void adx_outsw(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned short *buf = buffer; + while(count--) outw(*buf++, port); +} + +void adx_outsl(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned long *buf = buffer; + while(count--) outl(*buf++, port); +} + +unsigned char adx_readb(unsigned long addr) +{ + return *(volatile unsigned char*)addr; +} + +unsigned short adx_readw(unsigned long addr) +{ + return *(volatile unsigned short*)addr; +} + +unsigned int adx_readl(unsigned long addr) +{ + return *(volatile unsigned long*)addr; +} + +void adx_writeb(unsigned char b, unsigned long addr) +{ + *(volatile unsigned char*)addr = b; +} + +void adx_writew(unsigned short b, unsigned long addr) +{ + *(volatile unsigned short*)addr = b; +} + +void adx_writel(unsigned int b, unsigned long addr) +{ + *(volatile unsigned long*)addr = b; +} + +void *adx_ioremap(unsigned long offset, unsigned long size) +{ + return (void *)P2SEGADDR(offset); +} + +EXPORT_SYMBOL (adx_ioremap); + +void adx_iounmap(void *addr) +{ +} + +EXPORT_SYMBOL(adx_iounmap); + +#ifdef CONFIG_IDE +#include +extern void *cf_io_base; + +unsigned long adx_isa_port2addr(unsigned long offset) +{ + /* CompactFlash (IDE) */ + if (((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset == 0x3f6)) { + return (unsigned long)cf_io_base + offset; + } + + /* eth0 */ + if ((offset >= 0x300) && (offset <= 0x30f)) { + return 0xa5000000 + offset; /* COMM BOARD (AREA1) */ + } + + return offset + 0xb0000000; /* IOBUS (AREA 4)*/ +} +#endif + diff -urN linux-2.5.70-bk19/arch/sh/boards/adx/irq.c linux-2.5.71/arch/sh/boards/adx/irq.c --- linux-2.5.70-bk19/arch/sh/boards/adx/irq.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/adx/irq.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,31 @@ +/* + * linux/arch/sh/boards/adx/irq.c + * + * Copyright (C) 2001 A&D Co., Ltd. + * + * I/O routine and setup routines for A&D ADX Board + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + */ + +#include + +void init_adx_IRQ(void) +{ + int i; + +/* printk("init_adx_IRQ()\n");*/ + /* setup irq_mask_register */ + irq_mask_register = (unsigned short *)0xa6000008; + + /* cover all external interrupt area by maskreg_irq_type + * (Actually, irq15 doesn't exist) + */ + for (i = 0; i < 16; i++) { + make_maskreg_irq(i); + disable_irq(i); + } +} diff -urN linux-2.5.70-bk19/arch/sh/boards/adx/irq_maskreg.c linux-2.5.71/arch/sh/boards/adx/irq_maskreg.c --- linux-2.5.70-bk19/arch/sh/boards/adx/irq_maskreg.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/adx/irq_maskreg.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,107 @@ +/* + * linux/arch/sh/kernel/irq_maskreg.c + * + * Copyright (C) 2001 A&D Co., Ltd. + * + * This file may be copied or modified under the terms of the GNU + * General Public License. See linux/COPYING for more information. + * + * Interrupt handling for Simple external interrupt mask register + * + * This is for the machine which have single 16 bit register + * for masking external IRQ individually. + * Each bit of the register is for masking each interrupt. + */ + +#include +#include +#include +#include + +#include +#include +#include + +/* address of external interrupt mask register + * address must be set prior to use these (maybe in init_XXX_irq()) + * XXX : is it better to use .config than specifying it in code? */ +unsigned short *irq_mask_register = 0; + +/* forward declaration */ +static unsigned int startup_maskreg_irq(unsigned int irq); +static void shutdown_maskreg_irq(unsigned int irq); +static void enable_maskreg_irq(unsigned int irq); +static void disable_maskreg_irq(unsigned int irq); +static void mask_and_ack_maskreg(unsigned int); +static void end_maskreg_irq(unsigned int irq); + +/* hw_interrupt_type */ +static struct hw_interrupt_type maskreg_irq_type = { + " Mask Register", + startup_maskreg_irq, + shutdown_maskreg_irq, + enable_maskreg_irq, + disable_maskreg_irq, + mask_and_ack_maskreg, + end_maskreg_irq +}; + +/* actual implementatin */ +static unsigned int startup_maskreg_irq(unsigned int irq) +{ + enable_maskreg_irq(irq); + return 0; /* never anything pending */ +} + +static void shutdown_maskreg_irq(unsigned int irq) +{ + disable_maskreg_irq(irq); +} + +static void disable_maskreg_irq(unsigned int irq) +{ + if (irq_mask_register) { + unsigned long flags; + unsigned short val, mask = 0x01 << irq; + + /* Set "irq"th bit */ + local_irq_save(flags); + val = ctrl_inw((unsigned long)irq_mask_register); + val |= mask; + ctrl_outw(val, (unsigned long)irq_mask_register); + local_irq_restore(flags); + } +} + +static void enable_maskreg_irq(unsigned int irq) +{ + if (irq_mask_register) { + unsigned long flags; + unsigned short val, mask = ~(0x01 << irq); + + /* Clear "irq"th bit */ + local_irq_save(flags); + val = ctrl_inw((unsigned long)irq_mask_register); + val &= mask; + ctrl_outw(val, (unsigned long)irq_mask_register); + local_irq_restore(flags); + } +} + +static void mask_and_ack_maskreg(unsigned int irq) +{ + disable_maskreg_irq(irq); +} + +static void end_maskreg_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_maskreg_irq(irq); +} + +void make_maskreg_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].handler = &maskreg_irq_type; + disable_maskreg_irq(irq); +} diff -urN linux-2.5.70-bk19/arch/sh/boards/adx/mach.c linux-2.5.71/arch/sh/boards/adx/mach.c --- linux-2.5.70-bk19/arch/sh/boards/adx/mach.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/adx/mach.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,66 @@ +/* + * linux/arch/sh/kernel/mach_adx.c + * + * Copyright (C) 2001 A&D Co., Ltd. + * + * This file may be copied or modified under the terms of the GNU + * General Public License. See linux/COPYING for more information. + * + * Machine vector for the A&D ADX Board + */ + +#include +#include + +#include +#include +#include +#include + +extern void init_adx_IRQ(void); + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_adx __initmv = { + mv_nr_irqs: 48, + + mv_inb: adx_inb, + mv_inw: adx_inw, + mv_inl: adx_inl, + mv_outb: adx_outb, + mv_outw: adx_outw, + mv_outl: adx_outl, + + mv_inb_p: adx_inb_p, + mv_inw_p: adx_inw, + mv_inl_p: adx_inl, + mv_outb_p: adx_outb_p, + mv_outw_p: adx_outw, + mv_outl_p: adx_outl, + + mv_insb: adx_insb, + mv_insw: adx_insw, + mv_insl: adx_insl, + mv_outsb: adx_outsb, + mv_outsw: adx_outsw, + mv_outsl: adx_outsl, + + mv_readb: adx_readb, + mv_readw: adx_readw, + mv_readl: adx_readl, + mv_writeb: adx_writeb, + mv_writew: adx_writew, + mv_writel: adx_writel, + + mv_ioremap: adx_ioremap, + mv_iounmap: adx_iounmap, + + mv_isa_port2addr: adx_isa_port2addr, + + mv_init_irq: init_adx_IRQ, + + mv_hw_adx: 1, +}; +ALIAS_MV(adx) diff -urN linux-2.5.70-bk19/arch/sh/boards/adx/setup.c linux-2.5.71/arch/sh/boards/adx/setup.c --- linux-2.5.70-bk19/arch/sh/boards/adx/setup.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/adx/setup.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,24 @@ +/* + * linux/arch/sh/board/adx/setup.c + * + * Copyright (C) 2001 A&D Co., Ltd. + * + * I/O routine and setup routines for A&D ADX Board + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + */ + +#include +#include + +const char *get_system_type(void) +{ + return "A&D ADX"; +} + +void platform_setup(void) +{ +} diff -urN linux-2.5.70-bk19/arch/sh/boards/bigsur/Makefile linux-2.5.71/arch/sh/boards/bigsur/Makefile --- linux-2.5.70-bk19/arch/sh/boards/bigsur/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/bigsur/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,12 @@ +# +# Makefile for the BigSur specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := mach.o setup.o io.o irq.o led.o + +obj-$(CONFIG_PCI) += pci.o + diff -urN linux-2.5.70-bk19/arch/sh/boards/bigsur/io.c linux-2.5.71/arch/sh/boards/bigsur/io.c --- linux-2.5.70-bk19/arch/sh/boards/bigsur/io.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/bigsur/io.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,249 @@ +/* + * include/asm-sh/io_bigsur.c + * + * By Dustin McIntire (dustin@sensoria.com) (c)2001 + * Derived from io_hd64465.h, which bore the message: + * By Greg Banks + * (c) 2000 PocketPenguins Inc. + * and from io_hd64461.h, which bore the message: + * Copyright 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * IO functions for a Hitachi Big Sur Evaluation Board. + */ + +#include +#include +#include +#include +#include +#include + +//#define BIGSUR_DEBUG 2 +#undef BIGSUR_DEBUG + +#ifdef BIGSUR_DEBUG +#define DPRINTK(args...) printk(args) +#define DIPRINTK(n, args...) if (BIGSUR_DEBUG>(n)) printk(args) +#else +#define DPRINTK(args...) +#define DIPRINTK(n, args...) +#endif + + +/* Low iomap maps port 0-1K to addresses in 8byte chunks */ +#define BIGSUR_IOMAP_LO_THRESH 0x400 +#define BIGSUR_IOMAP_LO_SHIFT 3 +#define BIGSUR_IOMAP_LO_MASK ((1<>BIGSUR_IOMAP_LO_SHIFT) +static u32 bigsur_iomap_lo[BIGSUR_IOMAP_LO_NMAP]; +static u8 bigsur_iomap_lo_shift[BIGSUR_IOMAP_LO_NMAP]; + +/* High iomap maps port 1K-64K to addresses in 1K chunks */ +#define BIGSUR_IOMAP_HI_THRESH 0x10000 +#define BIGSUR_IOMAP_HI_SHIFT 10 +#define BIGSUR_IOMAP_HI_MASK ((1<>BIGSUR_IOMAP_HI_SHIFT) +static u32 bigsur_iomap_hi[BIGSUR_IOMAP_HI_NMAP]; +static u8 bigsur_iomap_hi_shift[BIGSUR_IOMAP_HI_NMAP]; + +#ifndef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) +#endif + +#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x)) + +void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift) +{ + u32 port, endport = baseport + nports; + + DPRINTK("bigsur_port_map(base=0x%0x, n=0x%0x, addr=0x%08x)\n", + baseport, nports, addr); + + for (port = baseport ; + port < endport && port < BIGSUR_IOMAP_LO_THRESH ; + port += (1<>BIGSUR_IOMAP_LO_SHIFT] = addr; + bigsur_iomap_lo_shift[port>>BIGSUR_IOMAP_LO_SHIFT] = shift; + addr += (1<<(BIGSUR_IOMAP_LO_SHIFT)); + } + + for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ; + port < endport && port < BIGSUR_IOMAP_HI_THRESH ; + port += (1<>BIGSUR_IOMAP_HI_SHIFT] = addr; + bigsur_iomap_hi_shift[port>>BIGSUR_IOMAP_HI_SHIFT] = shift; + addr += (1<<(BIGSUR_IOMAP_HI_SHIFT)); + } +} +EXPORT_SYMBOL(bigsur_port_map); + +void bigsur_port_unmap(u32 baseport, u32 nports) +{ + u32 port, endport = baseport + nports; + + DPRINTK("bigsur_port_unmap(base=0x%0x, n=0x%0x)\n", baseport, nports); + + for (port = baseport ; + port < endport && port < BIGSUR_IOMAP_LO_THRESH ; + port += (1<>BIGSUR_IOMAP_LO_SHIFT] = 0; + } + + for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ; + port < endport && port < BIGSUR_IOMAP_HI_THRESH ; + port += (1<>BIGSUR_IOMAP_HI_SHIFT] = 0; + } +} +EXPORT_SYMBOL(bigsur_port_unmap); + +unsigned long bigsur_isa_port2addr(unsigned long port) +{ + unsigned long addr = 0; + unsigned char shift; + + /* Physical address not in P0, do nothing */ + if (PXSEG(port)) addr = port; + /* physical address in P0, map to P2 */ + else if (port >= 0x30000) + addr = P2SEGADDR(port); + /* Big Sur I/O + HD64465 registers 0x10000-0x30000 */ + else if (port >= BIGSUR_IOMAP_HI_THRESH) + addr = BIGSUR_INTERNAL_BASE + (port - BIGSUR_IOMAP_HI_THRESH); + /* Handle remapping of high IO/PCI IO ports */ + else if (port >= BIGSUR_IOMAP_LO_THRESH) { + addr = bigsur_iomap_hi[port >> BIGSUR_IOMAP_HI_SHIFT]; + shift = bigsur_iomap_hi_shift[port >> BIGSUR_IOMAP_HI_SHIFT]; + if (addr != 0) + addr += (port & BIGSUR_IOMAP_HI_MASK) << shift; + } + /* Handle remapping of low IO ports */ + else { + addr = bigsur_iomap_lo[port >> BIGSUR_IOMAP_LO_SHIFT]; + shift = bigsur_iomap_lo_shift[port >> BIGSUR_IOMAP_LO_SHIFT]; + if (addr != 0) + addr += (port & BIGSUR_IOMAP_LO_MASK) << shift; + } + + DIPRINTK(2, "PORT2ADDR(0x%08lx) = 0x%08lx\n", port, addr); + + return addr; +} + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); +} + +unsigned char bigsur_inb(unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + unsigned long b = (addr == 0 ? 0 : *(volatile unsigned char*)addr); + + DIPRINTK(0, "inb(%08lx) = %02x\n", addr, (unsigned)b); + return b; +} + +unsigned char bigsur_inb_p(unsigned long port) +{ + unsigned long v; + unsigned long addr = PORT2ADDR(port); + + v = (addr == 0 ? 0 : *(volatile unsigned char*)addr); + delay(); + DIPRINTK(0, "inb_p(%08lx) = %02x\n", addr, (unsigned)v); + return v; +} + +unsigned short bigsur_inw(unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + unsigned long b = (addr == 0 ? 0 : *(volatile unsigned short*)addr); + DIPRINTK(0, "inw(%08lx) = %04lx\n", addr, b); + return b; +} + +unsigned int bigsur_inl(unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + unsigned int b = (addr == 0 ? 0 : *(volatile unsigned long*)addr); + DIPRINTK(0, "inl(%08lx) = %08x\n", addr, b); + return b; +} + +void bigsur_insb(unsigned long port, void *buffer, unsigned long count) +{ + unsigned char *buf=buffer; + while(count--) *buf++=inb(port); +} + +void bigsur_insw(unsigned long port, void *buffer, unsigned long count) +{ + unsigned short *buf=buffer; + while(count--) *buf++=inw(port); +} + +void bigsur_insl(unsigned long port, void *buffer, unsigned long count) +{ + unsigned long *buf=buffer; + while(count--) *buf++=inl(port); +} + +void bigsur_outb(unsigned char b, unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + + DIPRINTK(0, "outb(%02x, %08lx)\n", (unsigned)b, addr); + if (addr != 0) + *(volatile unsigned char*)addr = b; +} + +void bigsur_outb_p(unsigned char b, unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + + DIPRINTK(0, "outb_p(%02x, %08lx)\n", (unsigned)b, addr); + if (addr != 0) + *(volatile unsigned char*)addr = b; + delay(); +} + +void bigsur_outw(unsigned short b, unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + DIPRINTK(0, "outw(%04x, %08lx)\n", (unsigned)b, addr); + if (addr != 0) + *(volatile unsigned short*)addr = b; +} + +void bigsur_outl(unsigned int b, unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + DIPRINTK(0, "outl(%08x, %08lx)\n", b, addr); + if (addr != 0) + *(volatile unsigned long*)addr = b; +} + +void bigsur_outsb(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned char *buf=buffer; + while(count--) outb(*buf++, port); +} + +void bigsur_outsw(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned short *buf=buffer; + while(count--) outw(*buf++, port); +} + +void bigsur_outsl(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned long *buf=buffer; + while(count--) outl(*buf++, port); +} + diff -urN linux-2.5.70-bk19/arch/sh/boards/bigsur/irq.c linux-2.5.71/arch/sh/boards/bigsur/irq.c --- linux-2.5.70-bk19/arch/sh/boards/bigsur/irq.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/bigsur/irq.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,348 @@ +/* + * + * By Dustin McIntire (dustin@sensoria.com) (c)2001 + * + * Setup and IRQ handling code for the HD64465 companion chip. + * by Greg Banks + * Copyright (c) 2000 PocketPenguins Inc + * + * Derived from setup_hd64465.c which bore the message: + * Greg Banks + * Copyright (c) 2000 PocketPenguins Inc and + * Copyright (C) 2000 YAEGASHI Takeshi + * and setup_cqreek.c which bore message: + * Copyright (C) 2000 Niibe Yutaka + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * IRQ functions for a Hitachi Big Sur Evaluation Board. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +//#define BIGSUR_DEBUG 3 +#undef BIGSUR_DEBUG + +#ifdef BIGSUR_DEBUG +#define DPRINTK(args...) printk(args) +#define DIPRINTK(n, args...) if (BIGSUR_DEBUG>(n)) printk(args) +#else +#define DPRINTK(args...) +#define DIPRINTK(n, args...) +#endif /* BIGSUR_DEBUG */ + +#ifdef CONFIG_HD64465 +extern int hd64465_irq_demux(int irq); +#endif /* CONFIG_HD64465 */ + + +/*===========================================================*/ +// Big Sur CPLD IRQ Routines +/*===========================================================*/ + +/* Level 1 IRQ routines */ +static void disable_bigsur_l1irq(unsigned int irq) +{ + unsigned long flags; + unsigned char mask; + unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0; + unsigned char bit = (1 << ((irq - MGATE_IRQ_LOW)%8) ); + + if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) { + DPRINTK("Disable L1 IRQ %d\n", irq); + DIPRINTK(2,"disable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n", + mask_port, bit); + local_irq_save(flags); + + /* Disable IRQ - set mask bit */ + mask = inb(mask_port) | bit; + outb(mask, mask_port); + local_irq_restore(flags); + return; + } + DPRINTK("disable_bigsur_l1irq: Invalid IRQ %d\n", irq); +} + +static void enable_bigsur_l1irq(unsigned int irq) +{ + unsigned long flags; + unsigned char mask; + unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0; + unsigned char bit = (1 << ((irq - MGATE_IRQ_LOW)%8) ); + + if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) { + DPRINTK("Enable L1 IRQ %d\n", irq); + DIPRINTK(2,"enable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n", + mask_port, bit); + local_irq_save(flags); + /* Enable L1 IRQ - clear mask bit */ + mask = inb(mask_port) & ~bit; + outb(mask, mask_port); + local_irq_restore(flags); + return; + } + DPRINTK("enable_bigsur_l1irq: Invalid IRQ %d\n", irq); +} + + +/* Level 2 irq masks and registers for L2 decoding */ +/* Level2 bitmasks for each level 1 IRQ */ +const u32 bigsur_l2irq_mask[] = + {0x40,0x80,0x08,0x01,0x01,0x3C,0x3E,0xFF,0x40,0x80,0x06,0x03}; +/* Level2 to ISR[n] map for each level 1 IRQ */ +const u32 bigsur_l2irq_reg[] = + { 2, 2, 3, 3, 1, 2, 1, 0, 1, 1, 3, 2}; +/* Level2 to Level 1 IRQ map */ +const u32 bigsur_l2_l1_map[] = + {7,7,7,7,7,7,7,7, 4,6,6,6,6,6,8,9, 11,11,5,5,5,5,0,1, 3,10,10,2,-1,-1,-1,-1}; +/* IRQ inactive level (high or low) */ +const u32 bigsur_l2_inactv_state[] = {0x00, 0xBE, 0xFC, 0xF7}; + +/* CPLD external status and mask registers base and offsets */ +static const u32 isr_base = BIGSUR_IRQ0; +static const u32 isr_offset = BIGSUR_IRQ0 - BIGSUR_IRQ1; +static const u32 imr_base = BIGSUR_IMR0; +static const u32 imr_offset = BIGSUR_IMR0 - BIGSUR_IMR1; + +#define REG_NUM(irq) ((irq-BIGSUR_2NDLVL_IRQ_LOW)/8 ) + +/* Level 2 IRQ routines */ +static void disable_bigsur_l2irq(unsigned int irq) +{ + unsigned long flags; + unsigned char mask; + unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8); + unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset; + + if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) { + DPRINTK("Disable L2 IRQ %d\n", irq); + DIPRINTK(2,"disable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n", + mask_port, bit); + local_irq_save(flags); + + /* Disable L2 IRQ - set mask bit */ + mask = inb(mask_port) | bit; + outb(mask, mask_port); + local_irq_restore(flags); + return; + } + DPRINTK("disable_bigsur_l2irq: Invalid IRQ %d\n", irq); +} + +static void enable_bigsur_l2irq(unsigned int irq) +{ + unsigned long flags; + unsigned char mask; + unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8); + unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset; + + if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) { + DPRINTK("Enable L2 IRQ %d\n", irq); + DIPRINTK(2,"enable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n", + mask_port, bit); + local_irq_save(flags); + + /* Enable L2 IRQ - clear mask bit */ + mask = inb(mask_port) & ~bit; + outb(mask, mask_port); + local_irq_restore(flags); + return; + } + DPRINTK("enable_bigsur_l2irq: Invalid IRQ %d\n", irq); +} + +static void mask_and_ack_bigsur(unsigned int irq) +{ + DPRINTK("mask_and_ack_bigsur IRQ %d\n", irq); + if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) + disable_bigsur_l1irq(irq); + else + disable_bigsur_l2irq(irq); +} + +static void end_bigsur_irq(unsigned int irq) +{ + DPRINTK("end_bigsur_irq IRQ %d\n", irq); + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { + if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) + enable_bigsur_l1irq(irq); + else + enable_bigsur_l2irq(irq); + } +} + +static unsigned int startup_bigsur_irq(unsigned int irq) +{ + u8 mask; + u32 reg; + + DPRINTK("startup_bigsur_irq IRQ %d\n", irq); + + if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) { + /* Enable the L1 IRQ */ + enable_bigsur_l1irq(irq); + /* Enable all L2 IRQs in this L1 IRQ */ + mask = ~(bigsur_l2irq_mask[irq-BIGSUR_IRQ_LOW]); + reg = imr_base - bigsur_l2irq_reg[irq-BIGSUR_IRQ_LOW] * imr_offset; + mask &= inb(reg); + outb(mask,reg); + DIPRINTK(2,"startup_bigsur_irq: IMR=0x%08x mask=0x%x\n",reg,inb(reg)); + } + else { + /* Enable the L2 IRQ - clear mask bit */ + enable_bigsur_l2irq(irq); + /* Enable the L1 bit masking this L2 IRQ */ + enable_bigsur_l1irq(bigsur_l2_l1_map[irq-BIGSUR_2NDLVL_IRQ_LOW]); + DIPRINTK(2,"startup_bigsur_irq: L1=%d L2=%d\n", + bigsur_l2_l1_map[irq-BIGSUR_2NDLVL_IRQ_LOW],irq); + } + return 0; +} + +static void shutdown_bigsur_irq(unsigned int irq) +{ + DPRINTK("shutdown_bigsur_irq IRQ %d\n", irq); + if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) + disable_bigsur_l1irq(irq); + else + disable_bigsur_l2irq(irq); +} + +/* Define the IRQ structures for the L1 and L2 IRQ types */ +static struct hw_interrupt_type bigsur_l1irq_type = { + "BigSur-CPLD-Level1-IRQ", + startup_bigsur_irq, + shutdown_bigsur_irq, + enable_bigsur_l1irq, + disable_bigsur_l1irq, + mask_and_ack_bigsur, + end_bigsur_irq +}; + +static struct hw_interrupt_type bigsur_l2irq_type = { + "BigSur-CPLD-Level2-IRQ", + startup_bigsur_irq, + shutdown_bigsur_irq, + enable_bigsur_l2irq, + disable_bigsur_l2irq, + mask_and_ack_bigsur, + end_bigsur_irq +}; + + +static void make_bigsur_l1isr(unsigned int irq) { + + /* sanity check first */ + if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) { + /* save the handler in the main description table */ + irq_desc[irq].handler = &bigsur_l1irq_type; + irq_desc[irq].status = IRQ_DISABLED; + irq_desc[irq].action = 0; + irq_desc[irq].depth = 1; + + disable_bigsur_l1irq(irq); + return; + } + DPRINTK("make_bigsur_l1isr: bad irq, %d\n", irq); + return; +} + +static void make_bigsur_l2isr(unsigned int irq) { + + /* sanity check first */ + if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) { + /* save the handler in the main description table */ + irq_desc[irq].handler = &bigsur_l2irq_type; + irq_desc[irq].status = IRQ_DISABLED; + irq_desc[irq].action = 0; + irq_desc[irq].depth = 1; + + disable_bigsur_l2irq(irq); + return; + } + DPRINTK("make_bigsur_l2isr: bad irq, %d\n", irq); + return; +} + +/* The IRQ's will be decoded as follows: + * If a level 2 handler exists and there is an unmasked active + * IRQ, the 2nd level handler will be called. + * If a level 2 handler does not exist for the active IRQ + * the 1st level handler will be called. + */ + +int bigsur_irq_demux(int irq) +{ + int dmux_irq = irq; + u8 mask, actv_irqs; + u32 reg_num; + + DIPRINTK(3,"bigsur_irq_demux, irq=%d\n", irq); + /* decode the 1st level IRQ */ + if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) { + /* Get corresponding L2 ISR bitmask and ISR number */ + mask = bigsur_l2irq_mask[irq-BIGSUR_IRQ_LOW]; + reg_num = bigsur_l2irq_reg[irq-BIGSUR_IRQ_LOW]; + /* find the active IRQ's (XOR with inactive level)*/ + actv_irqs = inb(isr_base-reg_num*isr_offset) ^ + bigsur_l2_inactv_state[reg_num]; + /* decode active IRQ's */ + actv_irqs = actv_irqs & mask & ~(inb(imr_base-reg_num*imr_offset)); + /* if NEZ then we have an active L2 IRQ */ + if(actv_irqs) dmux_irq = ffz(~actv_irqs) + reg_num*8+BIGSUR_2NDLVL_IRQ_LOW; + /* if no 2nd level IRQ action, but has 1st level, use 1st level handler */ + if(!irq_desc[dmux_irq].action && irq_desc[irq].action) + dmux_irq = irq; + DIPRINTK(1,"bigsur_irq_demux: irq=%d dmux_irq=%d mask=0x%04x reg=%d\n", + irq, dmux_irq, mask, reg_num); + } +#ifdef CONFIG_HD64465 + dmux_irq = hd64465_irq_demux(dmux_irq); +#endif /* CONFIG_HD64465 */ + DIPRINTK(3,"bigsur_irq_demux, demux_irq=%d\n", dmux_irq); + + return dmux_irq; +} + +/*===========================================================*/ +// Big Sur Init Routines +/*===========================================================*/ +void __init init_bigsur_IRQ(void) +{ + int i; + + if (!MACH_BIGSUR) return; + + /* Create ISR's for Big Sur CPLD IRQ's */ + /*==============================================================*/ + for(i=BIGSUR_IRQ_LOW;i + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file contains Big Sur specific LED code. + */ + +#include +#include +#include + +static void mach_led(int position, int value) +{ + int word; + + word = bigsur_inl(BIGSUR_CSLR); + if (value) { + bigsur_outl(word & ~BIGSUR_LED, BIGSUR_CSLR); + } else { + bigsur_outl(word | BIGSUR_LED, BIGSUR_CSLR); + } +} + +#ifdef CONFIG_HEARTBEAT + +#include + +/* Cycle the LED on/off */ +void heartbeat_bigsur(void) +{ + static unsigned cnt = 0, period = 0, dist = 0; + + if (cnt == 0 || cnt == dist) + mach_led( -1, 1); + else if (cnt == 7 || cnt == dist+7) + mach_led( -1, 0); + + if (++cnt > period) { + cnt = 0; + /* The hyperbolic function below modifies the heartbeat period + * length in dependency of the current (5min) load. It goes + * through the points f(0)=126, f(1)=86, f(5)=51, + * f(inf)->30. */ + period = ((672< +#include + +#include +#include +#include +#include +#include +#include + +/* + * The Machine Vector + */ +extern void heartbeat_bigsur(void); +extern void init_bigsur_IRQ(void); + +struct sh_machine_vector mv_bigsur __initmv = { + mv_nr_irqs: NR_IRQS, // Defined in + mv_inb: bigsur_inb, + mv_inw: bigsur_inw, + mv_inl: bigsur_inl, + mv_outb: bigsur_outb, + mv_outw: bigsur_outw, + mv_outl: bigsur_outl, + + mv_inb_p: bigsur_inb_p, + mv_inw_p: bigsur_inw, + mv_inl_p: bigsur_inl, + mv_outb_p: bigsur_outb_p, + mv_outw_p: bigsur_outw, + mv_outl_p: bigsur_outl, + + mv_insb: bigsur_insb, + mv_insw: bigsur_insw, + mv_insl: bigsur_insl, + mv_outsb: bigsur_outsb, + mv_outsw: bigsur_outsw, + mv_outsl: bigsur_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_ioremap: generic_ioremap, + mv_iounmap: generic_iounmap, + + mv_isa_port2addr: bigsur_isa_port2addr, + mv_irq_demux: bigsur_irq_demux, + + mv_init_irq: init_bigsur_IRQ, +#ifdef CONFIG_HEARTBEAT + mv_heartbeat: heartbeat_bigsur, +#endif + +}; +ALIAS_MV(bigsur) diff -urN linux-2.5.70-bk19/arch/sh/boards/bigsur/pci.c linux-2.5.71/arch/sh/boards/bigsur/pci.c --- linux-2.5.70-bk19/arch/sh/boards/bigsur/pci.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/bigsur/pci.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,163 @@ +/* + * linux/arch/sh/kernel/pci-bigsur.c + * + * By Dustin McIntire (dustin@sensoria.com) (c)2001 + + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * PCI initialization for the Hitachi Big Sur Evaluation Board + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define PCI_REG(reg) (SH7751_PCIREG_BASE+reg) + +/* + * Initialize the Big Sur PCI interface + * Setup hardware to be Central Funtion + * Copy the BSR regs to the PCI interface + * Setup PCI windows into local RAM + */ +int __init pcibios_init_platform(void) { + u32 reg; + u32 word; + + PCIDBG(1,"PCI: bigsur_pci_init called\n"); + /* Set the BCR's to enable PCI access */ + reg = inl(SH7751_BCR1); + reg |= 0x80000; + outl(reg, SH7751_BCR1); + + /* Setup the host hardware */ + if(inl(PCI_REG(SH7751_PCICONF0)) != + (u32)((SH7751_DEVICE_ID <<16) | (SH7751_VENDOR_ID))) { + printk("PCI: Unkown PCI host bridge.\n"); + return 0; + } + printk("PCI: SH7751 PCI host bridge found.\n"); + + /* Turn the clocks back on (not done in reset)*/ + outl(0, PCI_REG(SH7751_PCICLKR)); + /* Clear Powerdown IRQ's (not done in reset) */ + word = SH7751_PCIPINT_D3 | SH7751_PCIPINT_D0; + outl(word, PCI_REG(SH7751_PCICLKR)); + + /* toggle PCI reset pin */ + word = SH7751_PCICR_PREFIX | SH7751_PCICR_PRST; + outl(word,PCI_REG(SH7751_PCICR)); + /* Wait for a long time... not 1 sec. but long enough */ + mdelay(100); + word = SH7751_PCICR_PREFIX; + outl(word,PCI_REG(SH7751_PCICR)); + + /* set the command/status bits to: + * Wait Cycle Control + Parity Enable + Bus Master + + * Mem space enable + */ + word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER | + SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES; + outl(word, PCI_REG(SH7751_PCICONF1)); + + /* define this host as the host bridge */ + word = SH7751_PCI_HOST_BRIDGE << 24; + outl(word, PCI_REG(SH7751_PCICONF2)); + + /* Set IO and Mem windows to local address + * Make PCI and local address the same for easy 1 to 1 mapping + * Window0 = BIGSUR_LSR0_SIZE @ non-cached CS3 base = SDRAM + * Window1 = BIGSUR_LSR1_SIZE @ cached CS3 base = SDRAM + */ + word = BIGSUR_LSR0_SIZE - 1; + outl(word, PCI_REG(SH7751_PCILSR0)); + word = BIGSUR_LSR1_SIZE - 1; + outl(word, PCI_REG(SH7751_PCILSR1)); + /* Set the values on window 0 PCI config registers */ + word = P2SEGADDR(SH7751_CS3_BASE_ADDR); + outl(word, PCI_REG(SH7751_PCILAR0)); + outl(word, PCI_REG(SH7751_PCICONF5)); + /* Set the values on window 1 PCI config registers */ + word = PHYSADDR(SH7751_CS3_BASE_ADDR); + outl(word, PCI_REG(SH7751_PCILAR1)); + outl(word, PCI_REG(SH7751_PCICONF6)); + + /* Set the local 16MB PCI memory space window to + * the lowest PCI mapped address + */ + word = PCIBIOS_MIN_MEM & SH7751_PCIMBR_MASK; + PCIDBG(2,"PCI: Setting upper bits of Memory window to 0x%x\n", word); + outl(word , PCI_REG(SH7751_PCIMBR)); + + /* Map IO space into PCI IO window + * The IO window is 64K-PCIBIOS_MIN_IO in size + * IO addresses will be translated to the + * PCI IO window base address + */ + PCIDBG(3,"PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n", PCIBIOS_MIN_IO, + (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO); + bigsur_port_map(PCIBIOS_MIN_IO, (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO,0); + + /* Make sure the MSB's of IO window are set to access PCI space correctly */ + word = PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK; + PCIDBG(2,"PCI: Setting upper bits of IO window to 0x%x\n", word); + outl(word, PCI_REG(SH7751_PCIIOBR)); + + /* Set PCI WCRx, BCRx's, copy from BSC locations */ + word = inl(SH7751_BCR1); + /* check BCR for SDRAM in area 3 */ + if(((word >> 3) & 1) == 0) { + printk("PCI: Area 3 is not configured for SDRAM. BCR1=0x%x\n", word); + return 0; + } + outl(word, PCI_REG(SH7751_PCIBCR1)); + word = (u16)inw(SH7751_BCR2); + /* check BCR2 for 32bit SDRAM interface*/ + if(((word >> 6) & 0x3) != 0x3) { + printk("PCI: Area 3 is not 32 bit SDRAM. BCR2=0x%x\n", word); + return 0; + } + outl(word, PCI_REG(SH7751_PCIBCR2)); + /* configure the wait control registers */ + word = inl(SH7751_WCR1); + outl(word, PCI_REG(SH7751_PCIWCR1)); + word = inl(SH7751_WCR2); + outl(word, PCI_REG(SH7751_PCIWCR2)); + word = inl(SH7751_WCR3); + outl(word, PCI_REG(SH7751_PCIWCR3)); + word = inl(SH7751_MCR); + outl(word, PCI_REG(SH7751_PCIMCR)); + + /* NOTE: I'm ignoring the PCI error IRQs for now.. + * TODO: add support for the internal error interrupts and + * DMA interrupts... + */ + + /* SH7751 init done, set central function init complete */ + word = SH7751_PCICR_PREFIX | SH7751_PCICR_CFIN; + outl(word,PCI_REG(SH7751_PCICR)); + PCIDBG(2,"PCI: bigsur_pci_init finished\n"); + + return 1; +} + +int pcibios_map_platform_irq(u8 slot, u8 pin) +{ + /* The Big Sur can be used in a CPCI chassis, but the SH7751 PCI interface is on the + * wrong end of the board so that it can also support a V320 CPI interface chip... + * Therefor the IRQ mapping is somewhat use dependent... I'l assume a linear map for + * now, i.e. INTA=slot0,pin0... INTD=slot3,pin0... + */ + int irq = (slot + pin-1)%4 + BIGSUR_SH7751_PCI_IRQ_BASE; + PCIDBG(2,"PCI: Mapping Big Sur IRQ for slot %d, pin %c to irq %d\n", slot, pin-1+'A', irq); + return irq; + +} diff -urN linux-2.5.70-bk19/arch/sh/boards/bigsur/setup.c linux-2.5.71/arch/sh/boards/bigsur/setup.c --- linux-2.5.70-bk19/arch/sh/boards/bigsur/setup.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/bigsur/setup.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,94 @@ +/* + * + * By Dustin McIntire (dustin@sensoria.com) (c)2001 + * + * Setup and IRQ handling code for the HD64465 companion chip. + * by Greg Banks + * Copyright (c) 2000 PocketPenguins Inc + * + * Derived from setup_hd64465.c which bore the message: + * Greg Banks + * Copyright (c) 2000 PocketPenguins Inc and + * Copyright (C) 2000 YAEGASHI Takeshi + * and setup_cqreek.c which bore message: + * Copyright (C) 2000 Niibe Yutaka + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Setup functions for a Hitachi Big Sur Evaluation Board. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +//#define BIGSUR_DEBUG 3 +#undef BIGSUR_DEBUG + +#ifdef BIGSUR_DEBUG +#define DPRINTK(args...) printk(args) +#define DIPRINTK(n, args...) if (BIGSUR_DEBUG>(n)) printk(args) +#else +#define DPRINTK(args...) +#define DIPRINTK(n, args...) +#endif /* BIGSUR_DEBUG */ + +/*===========================================================*/ +// Big Sur Init Routines +/*===========================================================*/ + +const char *get_system_type(void) +{ + return "Big Sur"; +} + +int __init platform_setup(void) +{ + static int done = 0; /* run this only once */ + + if (!MACH_BIGSUR || done) return 0; + done = 1; + + /* Mask all 2nd level IRQ's */ + outb(-1,BIGSUR_IMR0); + outb(-1,BIGSUR_IMR1); + outb(-1,BIGSUR_IMR2); + outb(-1,BIGSUR_IMR3); + + /* Mask 1st level interrupts */ + outb(-1,BIGSUR_IRLMR0); + outb(-1,BIGSUR_IRLMR1); + +#if defined (CONFIG_HD64465) && defined (CONFIG_SERIAL) + /* remap IO ports for first ISA serial port to HD64465 UART */ + bigsur_port_map(0x3f8, 8, CONFIG_HD64465_IOBASE + 0x8000, 1); +#endif /* CONFIG_HD64465 && CONFIG_SERIAL */ + /* TODO: setup IDE registers */ + bigsur_port_map(BIGSUR_IDECTL_IOPORT, 2, BIGSUR_ICTL, 8); + /* Setup the Ethernet port to BIGSUR_ETHER_IOPORT */ + bigsur_port_map(BIGSUR_ETHER_IOPORT, 16, BIGSUR_ETHR+BIGSUR_ETHER_IOPORT, 0); + /* set page to 1 */ + outw(1, BIGSUR_ETHR+0xe); + /* set the IO port to BIGSUR_ETHER_IOPORT */ + outw(BIGSUR_ETHER_IOPORT<<3, BIGSUR_ETHR+0x2); + + return 0; +} + +module_init(setup_bigsur); diff -urN linux-2.5.70-bk19/arch/sh/boards/cat68701/Makefile linux-2.5.71/arch/sh/boards/cat68701/Makefile --- linux-2.5.70-bk19/arch/sh/boards/cat68701/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/cat68701/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,10 @@ +# +# Makefile for the CAT-68701 specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := mach.o setup.o io.o irq.o + diff -urN linux-2.5.70-bk19/arch/sh/boards/cat68701/io.c linux-2.5.71/arch/sh/boards/cat68701/io.c --- linux-2.5.70-bk19/arch/sh/boards/cat68701/io.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/cat68701/io.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,207 @@ +/* + * linux/arch/sh/boards/cat68701/io.c + * + * Copyright (C) 2000 Niibe Yutaka + * 2001 Yutaro Ebihara + * + * I/O routines for A-ONE Corp CAT-68701 SH7708 Board + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + */ + +#include +#include +#include +#include + +#define SH3_PCMCIA_BUG_WORKAROUND 1 +#define DUMMY_READ_AREA6 0xba000000 + +#define PORT2ADDR(x) (cat68701_isa_port2addr(x)) + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); +} + +unsigned char cat68701_inb(unsigned long port) +{ + return *(volatile unsigned char*)PORT2ADDR(port); +} + +unsigned short cat68701_inw(unsigned long port) +{ + return *(volatile unsigned short*)PORT2ADDR(port); +} + +unsigned int cat68701_inl(unsigned long port) +{ + return *(volatile unsigned long*)PORT2ADDR(port); +} + +unsigned char cat68701_inb_p(unsigned long port) +{ + unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); + + delay(); + return v; +} + +unsigned short cat68701_inw_p(unsigned long port) +{ + unsigned long v = *(volatile unsigned short*)PORT2ADDR(port); + + delay(); + return v; +} + +unsigned int cat68701_inl_p(unsigned long port) +{ + unsigned long v = *(volatile unsigned long*)PORT2ADDR(port); + + delay(); + return v; +} + +void cat68701_insb(unsigned long port, void *buffer, unsigned long count) +{ + unsigned char *buf=buffer; + while(count--) *buf++=inb(port); +} + +void cat68701_insw(unsigned long port, void *buffer, unsigned long count) +{ + unsigned short *buf=buffer; + while(count--) *buf++=inw(port); +#ifdef SH3_PCMCIA_BUG_WORKAROUND + ctrl_inb (DUMMY_READ_AREA6); +#endif +} + +void cat68701_insl(unsigned long port, void *buffer, unsigned long count) +{ + unsigned long *buf=buffer; + while(count--) *buf++=inl(port); +#ifdef SH3_PCMCIA_BUG_WORKAROUND + ctrl_inb (DUMMY_READ_AREA6); +#endif +} + +void cat68701_outb(unsigned char b, unsigned long port) +{ + *(volatile unsigned char*)PORT2ADDR(port) = b; +} + +void cat68701_outw(unsigned short b, unsigned long port) +{ + *(volatile unsigned short*)PORT2ADDR(port) = b; +} + +void cat68701_outl(unsigned int b, unsigned long port) +{ + *(volatile unsigned long*)PORT2ADDR(port) = b; +} + +void cat68701_outb_p(unsigned char b, unsigned long port) +{ + *(volatile unsigned char*)PORT2ADDR(port) = b; + delay(); +} + +void cat68701_outw_p(unsigned short b, unsigned long port) +{ + *(volatile unsigned short*)PORT2ADDR(port) = b; + delay(); +} + +void cat68701_outl_p(unsigned int b, unsigned long port) +{ + *(volatile unsigned long*)PORT2ADDR(port) = b; + delay(); +} + +void cat68701_outsb(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned char *buf=buffer; + while(count--) outb(*buf++, port); +} + +void cat68701_outsw(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned short *buf=buffer; + while(count--) outw(*buf++, port); +#ifdef SH3_PCMCIA_BUG_WORKAROUND + ctrl_inb (DUMMY_READ_AREA6); +#endif +} + +void cat68701_outsl(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned long *buf=buffer; + while(count--) outl(*buf++, port); +#ifdef SH3_PCMCIA_BUG_WORKAROUND + ctrl_inb (DUMMY_READ_AREA6); +#endif +} + +unsigned char cat68701_readb(unsigned long addr) +{ + return *(volatile unsigned char*)addr; +} + +unsigned short cat68701_readw(unsigned long addr) +{ + return *(volatile unsigned short*)addr; +} + +unsigned int cat68701_readl(unsigned long addr) +{ + return *(volatile unsigned long*)addr; +} + +void cat68701_writeb(unsigned char b, unsigned long addr) +{ + *(volatile unsigned char*)addr = b; +} + +void cat68701_writew(unsigned short b, unsigned long addr) +{ + *(volatile unsigned short*)addr = b; +} + +void cat68701_writel(unsigned int b, unsigned long addr) +{ + *(volatile unsigned long*)addr = b; +} + +void * cat68701_ioremap(unsigned long offset, unsigned long size) +{ + return (void *) P2SEGADDR(offset); +} +EXPORT_SYMBOL(cat68701_ioremap); + +void cat68701_iounmap(void *addr) +{ +} +EXPORT_SYMBOL(cat68701_iounmap); + +unsigned long cat68701_isa_port2addr(unsigned long offset) +{ + /* CompactFlash (IDE) */ + if(((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset==0x3f6)) + return 0xba000000 + offset; + + /* INPUT PORT */ + if((offset >= 0x3fc) && (offset <= 0x3fd)) + return 0xb4007000 + offset; + + /* OUTPUT PORT */ + if((offset >= 0x3fe) && (offset <= 0x3ff)) + return 0xb4007400 + offset; + + return offset + 0xb4000000; /* other I/O (EREA 5)*/ +} + diff -urN linux-2.5.70-bk19/arch/sh/boards/cat68701/irq.c linux-2.5.71/arch/sh/boards/cat68701/irq.c --- linux-2.5.70-bk19/arch/sh/boards/cat68701/irq.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/cat68701/irq.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,28 @@ +/* + * linux/arch/sh/boards/cat68701/irq.c + * + * Copyright (C) 2000 Niibe Yutaka + * 2001 Yutaro Ebihara + * + * Setup routines for A-ONE Corp CAT-68701 SH7708 Board + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + */ + +#include + +int cat68701_irq_demux(int irq) +{ + if(irq==13) return 14; + if(irq==7) return 10; + return irq; +} + +void init_cat68701_IRQ() +{ + make_imask_irq(10); + make_imask_irq(14); +} diff -urN linux-2.5.70-bk19/arch/sh/boards/cat68701/mach.c linux-2.5.71/arch/sh/boards/cat68701/mach.c --- linux-2.5.70-bk19/arch/sh/boards/cat68701/mach.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/cat68701/mach.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,66 @@ +/* + * linux/arch/sh/boards/cat68701/mach.c + * + * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) + * 2001 Yutaro Ebihara (ebihara@si-linux.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Machine vector for the A-ONE corp. CAT-68701 SH7708 board + */ + +#include +#include + +#include +#include +#include +#include + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_cat68701 __initmv = { + mv_nr_irqs: 32, + mv_inb: cat68701_inb, + mv_inw: cat68701_inw, + mv_inl: cat68701_inl, + mv_outb: cat68701_outb, + mv_outw: cat68701_outw, + mv_outl: cat68701_outl, + + mv_inb_p: cat68701_inb_p, + mv_inw_p: cat68701_inw, + mv_inl_p: cat68701_inl, + mv_outb_p: cat68701_outb_p, + mv_outw_p: cat68701_outw, + mv_outl_p: cat68701_outl, + + mv_insb: cat68701_insb, + mv_insw: cat68701_insw, + mv_insl: cat68701_insl, + mv_outsb: cat68701_outsb, + mv_outsw: cat68701_outsw, + mv_outsl: cat68701_outsl, + + mv_readb: cat68701_readb, + mv_readw: cat68701_readw, + mv_readl: cat68701_readl, + mv_writeb: cat68701_writeb, + mv_writew: cat68701_writew, + mv_writel: cat68701_writel, + + mv_ioremap: cat68701_ioremap, + mv_iounmap: cat68701_iounmap, + + mv_isa_port2addr: cat68701_isa_port2addr, + mv_irq_demux: cat68701_irq_demux, + + mv_init_irq: init_cat68701_IRQ, +#ifdef CONFIG_HEARTBEAT + mv_heartbeat: heartbeat_cat68701, +#endif +}; +ALIAS_MV(cat68701) diff -urN linux-2.5.70-bk19/arch/sh/boards/cat68701/setup.c linux-2.5.71/arch/sh/boards/cat68701/setup.c --- linux-2.5.70-bk19/arch/sh/boards/cat68701/setup.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/cat68701/setup.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,51 @@ +/* + * linux/arch/sh/boards/cat68701/setup.c + * + * Copyright (C) 2000 Niibe Yutaka + * 2001 Yutaro Ebihara + * + * Setup routines for A-ONE Corp CAT-68701 SH7708 Board + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + */ + +#include +#include +#include +#include + +const char *get_system_type(void) +{ + return "CAT-68701"; +} + +void platform_setup() +{ + /* dummy read erea5 (CS8900A) */ +} + +#ifdef CONFIG_HEARTBEAT +#include +void heartbeat_cat68701() +{ + static unsigned int cnt = 0, period = 0 , bit = 0; + cnt += 1; + if (cnt < period) { + return; + } + cnt = 0; + + /* Go through the points (roughly!): + * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110 + */ + period = 110 - ( (300< +#include + +#include +#include +#include +#include +#include +#include +#include + +struct cqreek_irq_data { + unsigned short mask_port; /* Port of Interrupt Mask Register */ + unsigned short stat_port; /* Port of Interrupt Status Register */ + unsigned short bit; /* Value of the bit */ +}; +static struct cqreek_irq_data cqreek_irq_data[NR_IRQS]; + +static void disable_cqreek_irq(unsigned int irq) +{ + unsigned long flags; + unsigned short mask; + unsigned short mask_port = cqreek_irq_data[irq].mask_port; + unsigned short bit = cqreek_irq_data[irq].bit; + + local_irq_save(flags); + /* Disable IRQ */ + mask = inw(mask_port) & ~bit; + outw_p(mask, mask_port); + local_irq_restore(flags); +} + +static void enable_cqreek_irq(unsigned int irq) +{ + unsigned long flags; + unsigned short mask; + unsigned short mask_port = cqreek_irq_data[irq].mask_port; + unsigned short bit = cqreek_irq_data[irq].bit; + + local_irq_save(flags); + /* Enable IRQ */ + mask = inw(mask_port) | bit; + outw_p(mask, mask_port); + local_irq_restore(flags); +} + +static void mask_and_ack_cqreek(unsigned int irq) +{ + unsigned short stat_port = cqreek_irq_data[irq].stat_port; + unsigned short bit = cqreek_irq_data[irq].bit; + + disable_cqreek_irq(irq); + /* Clear IRQ (it might be edge IRQ) */ + inw(stat_port); + outw_p(bit, stat_port); +} + +static void end_cqreek_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_cqreek_irq(irq); +} + +static unsigned int startup_cqreek_irq(unsigned int irq) +{ + enable_cqreek_irq(irq); + return 0; +} + +static void shutdown_cqreek_irq(unsigned int irq) +{ + disable_cqreek_irq(irq); +} + +static struct hw_interrupt_type cqreek_irq_type = { + "CqREEK-IRQ", + startup_cqreek_irq, + shutdown_cqreek_irq, + enable_cqreek_irq, + disable_cqreek_irq, + mask_and_ack_cqreek, + end_cqreek_irq +}; + +int cqreek_has_ide, cqreek_has_isa; + +/* XXX: This is just for test for my NE2000 ISA board + What we really need is virtualized IRQ and demultiplexer like HP600 port */ +void __init init_cqreek_IRQ(void) +{ + if (cqreek_has_ide) { + cqreek_irq_data[14].mask_port = BRIDGE_IDE_INTR_MASK; + cqreek_irq_data[14].stat_port = BRIDGE_IDE_INTR_STAT; + cqreek_irq_data[14].bit = 1; + + irq_desc[14].handler = &cqreek_irq_type; + irq_desc[14].status = IRQ_DISABLED; + irq_desc[14].action = 0; + irq_desc[14].depth = 1; + + disable_cqreek_irq(14); + } + + if (cqreek_has_isa) { + cqreek_irq_data[10].mask_port = BRIDGE_ISA_INTR_MASK; + cqreek_irq_data[10].stat_port = BRIDGE_ISA_INTR_STAT; + cqreek_irq_data[10].bit = (1 << 10); + + /* XXX: Err... we may need demultiplexer for ISA irq... */ + irq_desc[10].handler = &cqreek_irq_type; + irq_desc[10].status = IRQ_DISABLED; + irq_desc[10].action = 0; + irq_desc[10].depth = 1; + + disable_cqreek_irq(10); + } +} + diff -urN linux-2.5.70-bk19/arch/sh/boards/cqreek/mach.c linux-2.5.71/arch/sh/boards/cqreek/mach.c --- linux-2.5.70-bk19/arch/sh/boards/cqreek/mach.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/cqreek/mach.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,66 @@ +/* $Id: mach.c,v 1.1.2.4.2.1 2003/01/10 17:26:32 lethal Exp $ + * + * arch/sh/kernel/setup_cqreek.c + * + * Copyright (C) 2000 Niibe Yutaka + * + * CqREEK IDE/ISA Bridge Support. + * + */ + +#include +#include +#include +#include +#include +#include + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_cqreek __initmv = { +#if defined(CONFIG_CPU_SH4) + mv_nr_irqs: 48, +#elif defined(CONFIG_CPU_SUBTYPE_SH7708) + mv_nr_irqs: 32, +#elif defined(CONFIG_CPU_SUBTYPE_SH7709) + mv_nr_irqs: 61, +#endif + + mv_inb: generic_inb, + mv_inw: generic_inw, + mv_inl: generic_inl, + mv_outb: generic_outb, + mv_outw: generic_outw, + mv_outl: generic_outl, + + mv_inb_p: generic_inb_p, + mv_inw_p: generic_inw_p, + mv_inl_p: generic_inl_p, + mv_outb_p: generic_outb_p, + mv_outw_p: generic_outw_p, + mv_outl_p: generic_outl_p, + + mv_insb: generic_insb, + mv_insw: generic_insw, + mv_insl: generic_insl, + mv_outsb: generic_outsb, + mv_outsw: generic_outsw, + mv_outsl: generic_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_init_irq: init_cqreek_IRQ, + + mv_isa_port2addr: cqreek_port2addr, + + mv_ioremap: generic_ioremap, + mv_iounmap: generic_iounmap, +}; +ALIAS_MV(cqreek) diff -urN linux-2.5.70-bk19/arch/sh/boards/cqreek/setup.c linux-2.5.71/arch/sh/boards/cqreek/setup.c --- linux-2.5.70-bk19/arch/sh/boards/cqreek/setup.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/cqreek/setup.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,69 @@ +/* $Id: setup.c,v 1.1.2.5 2002/03/02 21:57:07 lethal Exp $ + * + * arch/sh/kernel/setup_cqreek.c + * + * Copyright (C) 2000 Niibe Yutaka + * + * CqREEK IDE/ISA Bridge Support. + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +const char *get_system_type(void) +{ + return "CqREEK"; +} + +/* + * Initialize the board + */ +void __init platform_setup(void) +{ + int i; +/* udelay is not available at setup time yet... */ +#define DELAY() do {for (i=0; i<10000; i++) ctrl_inw(0xa0000000);} while(0) + + if ((inw (BRIDGE_FEATURE) & 1)) { /* We have IDE interface */ + outw_p(0, BRIDGE_IDE_INTR_LVL); + outw_p(0, BRIDGE_IDE_INTR_MASK); + + outw_p(0, BRIDGE_IDE_CTRL); + DELAY(); + + outw_p(0x8000, BRIDGE_IDE_CTRL); + DELAY(); + + outw_p(0xffff, BRIDGE_IDE_INTR_STAT); /* Clear interrupt status */ + outw_p(0x0f-14, BRIDGE_IDE_INTR_LVL); /* Use 14 IPR */ + outw_p(1, BRIDGE_IDE_INTR_MASK); /* Enable interrupt */ + cqreek_has_ide=1; + } + + if ((inw (BRIDGE_FEATURE) & 2)) { /* We have ISA interface */ + outw_p(0, BRIDGE_ISA_INTR_LVL); + outw_p(0, BRIDGE_ISA_INTR_MASK); + + outw_p(0, BRIDGE_ISA_CTRL); + DELAY(); + outw_p(0x8000, BRIDGE_ISA_CTRL); + DELAY(); + + outw_p(0xffff, BRIDGE_ISA_INTR_STAT); /* Clear interrupt status */ + outw_p(0x0f-10, BRIDGE_ISA_INTR_LVL); /* Use 10 IPR */ + outw_p(0xfff8, BRIDGE_ISA_INTR_MASK); /* Enable interrupt */ + cqreek_has_isa=1; + } + + printk(KERN_INFO "CqREEK Setup (IDE=%d, ISA=%d)...done\n", cqreek_has_ide, cqreek_has_isa); +} + diff -urN linux-2.5.70-bk19/arch/sh/boards/dmida/Makefile linux-2.5.71/arch/sh/boards/dmida/Makefile --- linux-2.5.70-bk19/arch/sh/boards/dmida/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/dmida/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,11 @@ +# +# Makefile for the DataMyte Industrial Digital Assistant(tm) specific parts +# of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := mach.o + diff -urN linux-2.5.70-bk19/arch/sh/boards/dmida/mach.c linux-2.5.71/arch/sh/boards/dmida/mach.c --- linux-2.5.70-bk19/arch/sh/boards/dmida/mach.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/dmida/mach.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,73 @@ +/* + * linux/arch/sh/kernel/mach_dmida.c + * + * by Greg Banks + * (c) 2000 PocketPenguins Inc + * + * Derived from mach_hp600.c, which bore the message: + * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Machine vector for the DataMyte Industrial Digital Assistant(tm). + * See http://www.dmida.com + * + */ + +#include + +#include +#include +#include + +#include +#include +#include + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_dmida __initmv = { + mv_name: "DMIDA", + + mv_nr_irqs: HD64465_IRQ_BASE+HD64465_IRQ_NUM, + + mv_inb: hd64465_inb, + mv_inw: hd64465_inw, + mv_inl: hd64465_inl, + mv_outb: hd64465_outb, + mv_outw: hd64465_outw, + mv_outl: hd64465_outl, + + mv_inb_p: hd64465_inb_p, + mv_inw_p: hd64465_inw, + mv_inl_p: hd64465_inl, + mv_outb_p: hd64465_outb_p, + mv_outw_p: hd64465_outw, + mv_outl_p: hd64465_outl, + + mv_insb: hd64465_insb, + mv_insw: hd64465_insw, + mv_insl: hd64465_insl, + mv_outsb: hd64465_outsb, + mv_outsw: hd64465_outsw, + mv_outsl: hd64465_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_irq_demux: hd64465_irq_demux, + + mv_rtc_gettimeofday: sh_rtc_gettimeofday, + mv_rtc_settimeofday: sh_rtc_settimeofday, + + mv_hw_hd64465: 1, +}; +ALIAS_MV(dmida) + diff -urN linux-2.5.70-bk19/arch/sh/boards/dreamcast/Makefile linux-2.5.71/arch/sh/boards/dreamcast/Makefile --- linux-2.5.70-bk19/arch/sh/boards/dreamcast/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/dreamcast/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,12 @@ +# +# Makefile for the Sega Dreamcast specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := mach.o setup.o io.o irq.o rtc.o + +obj-$(CONFIG_PCI) += pci.o + diff -urN linux-2.5.70-bk19/arch/sh/boards/dreamcast/io.c linux-2.5.71/arch/sh/boards/dreamcast/io.c --- linux-2.5.70-bk19/arch/sh/boards/dreamcast/io.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/dreamcast/io.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,12 @@ +/* + * $Id: io.c,v 1.1.2.1 2002/01/19 23:54:19 mrbrown Exp $ + * I/O routines for SEGA Dreamcast + */ + +#include +#include + +unsigned long dreamcast_isa_port2addr(unsigned long offset) +{ + return offset + 0xa0000000; +} diff -urN linux-2.5.70-bk19/arch/sh/boards/dreamcast/irq.c linux-2.5.71/arch/sh/boards/dreamcast/irq.c --- linux-2.5.70-bk19/arch/sh/boards/dreamcast/irq.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/dreamcast/irq.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,160 @@ +/* + * arch/sh/boards/dreamcast/irq.c + * + * Holly IRQ support for the Sega Dreamcast. + * + * Copyright (c) 2001, 2002 M. R. Brown + * + * This file is part of the LinuxDC project (www.linuxdc.org) + * Released under the terms of the GNU GPL v2.0 + */ + +#include + +#include +#include +#include + +/* Dreamcast System ASIC Hardware Events - + + The Dreamcast's System ASIC (a.k.a. Holly) is responsible for receiving + hardware events from system peripherals and triggering an SH7750 IRQ. + Hardware events can trigger IRQs 13, 11, or 9 depending on which bits are + set in the Event Mask Registers (EMRs). When a hardware event is + triggered, it's corresponding bit in the Event Status Registers (ESRs) + is set, and that bit should be rewritten to the ESR to acknowledge that + event. + + There are three 32-bit ESRs located at 0xa05f8900 - 0xa05f6908. Event + types can be found in include/asm-sh/dc_sysasic.h. There are three groups + of EMRs that parallel the ESRs. Each EMR group corresponds to an IRQ, so + 0xa05f6910 - 0xa05f6918 triggers IRQ 13, 0xa05f6920 - 0xa05f6928 triggers + IRQ 11, and 0xa05f6930 - 0xa05f6938 triggers IRQ 9. + + In the kernel, these events are mapped to virtual IRQs so that drivers can + respond to them as they would a normal interrupt. In order to keep this + mapping simple, the events are mapped as: + + 6900/6910 - Events 0-31, IRQ 13 + 6904/6924 - Events 32-63, IRQ 11 + 6908/6938 - Events 64-95, IRQ 9 + +*/ + +#define ESR_BASE 0x005f6900 /* Base event status register */ +#define EMR_BASE 0x005f6910 /* Base event mask register */ + +/* Helps us determine the EMR group that this event belongs to: 0 = 0x6910, + 1 = 0x6920, 2 = 0x6930; also determine the event offset */ +#define LEVEL(event) (((event) - HW_EVENT_IRQ_BASE) / 32) + +/* Return the hardware event's bit positon within the EMR/ESR */ +#define EVENT_BIT(event) (((event) - HW_EVENT_IRQ_BASE) & 31) + +/* For each of these *_irq routines, the IRQ passed in is the virtual IRQ + (logically mapped to the corresponding bit for the hardware event). */ + +/* Disable the hardware event by masking its bit in its EMR */ +static inline void disable_systemasic_irq(unsigned int irq) +{ + unsigned long flags; + __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2); + __u32 mask; + + local_irq_save(flags); + mask = inl(emr); + mask &= ~(1 << EVENT_BIT(irq)); + outl(mask, emr); + local_irq_restore(flags); +} + +/* Enable the hardware event by setting its bit in its EMR */ +static inline void enable_systemasic_irq(unsigned int irq) +{ + unsigned long flags; + __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2); + __u32 mask; + + local_irq_save(flags); + mask = inl(emr); + mask |= (1 << EVENT_BIT(irq)); + outl(mask, emr); + local_irq_restore(flags); +} + +/* Acknowledge a hardware event by writing its bit back to its ESR */ +static void ack_systemasic_irq(unsigned int irq) +{ + __u32 esr = ESR_BASE + (LEVEL(irq) << 2); + disable_systemasic_irq(irq); + outl((1 << EVENT_BIT(irq)), esr); +} + +/* After a IRQ has been ack'd and responded to, it needs to be renabled */ +static void end_systemasic_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_systemasic_irq(irq); +} + +static unsigned int startup_systemasic_irq(unsigned int irq) +{ + enable_systemasic_irq(irq); + + return 0; +} + +static void shutdown_systemasic_irq(unsigned int irq) +{ + disable_systemasic_irq(irq); +} + +struct hw_interrupt_type systemasic_int = { + typename: "System ASIC", + startup: startup_systemasic_irq, + shutdown: shutdown_systemasic_irq, + enable: enable_systemasic_irq, + disable: disable_systemasic_irq, + ack: ack_systemasic_irq, + end: end_systemasic_irq, +}; + +/* + * Map the hardware event indicated by the processor IRQ to a virtual IRQ. + */ +int systemasic_irq_demux(int irq) +{ + __u32 emr, esr, status, level; + __u32 j, bit; + + switch (irq) { + case 13: + level = 0; + break; + case 11: + level = 1; + break; + case 9: + level = 2; + break; + default: + return irq; + } + emr = EMR_BASE + (level << 4) + (level << 2); + esr = ESR_BASE + (level << 2); + + /* Mask the ESR to filter any spurious, unwanted interrtupts */ + status = inl(esr); + status &= inl(emr); + + /* Now scan and find the first set bit as the event to map */ + for (bit = 1, j = 0; j < 32; bit <<= 1, j++) { + if (status & bit) { + irq = HW_EVENT_IRQ_BASE + j + (level << 5); + return irq; + } + } + + /* Not reached */ + return irq; +} diff -urN linux-2.5.70-bk19/arch/sh/boards/dreamcast/mach.c linux-2.5.71/arch/sh/boards/dreamcast/mach.c --- linux-2.5.70-bk19/arch/sh/boards/dreamcast/mach.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/dreamcast/mach.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,62 @@ +/* + * $Id: mach.c,v 1.1.2.5 2002/03/01 11:22:17 lethal Exp $ + * SEGA Dreamcast machine vector + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +void __init dreamcast_pcibios_init(void); + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_dreamcast __initmv = { + mv_nr_irqs: NR_IRQS, + + mv_inb: generic_inb, + mv_inw: generic_inw, + mv_inl: generic_inl, + mv_outb: generic_outb, + mv_outw: generic_outw, + mv_outl: generic_outl, + + mv_inb_p: generic_inb_p, + mv_inw_p: generic_inw, + mv_inl_p: generic_inl, + mv_outb_p: generic_outb_p, + mv_outw_p: generic_outw, + mv_outl_p: generic_outl, + + mv_insb: generic_insb, + mv_insw: generic_insw, + mv_insl: generic_insl, + mv_outsb: generic_outsb, + mv_outsw: generic_outsw, + mv_outsl: generic_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_ioremap: generic_ioremap, + mv_iounmap: generic_iounmap, + + mv_isa_port2addr: dreamcast_isa_port2addr, + mv_irq_demux: systemasic_irq_demux, + + mv_hw_dreamcast: 1, +}; +ALIAS_MV(dreamcast) diff -urN linux-2.5.70-bk19/arch/sh/boards/dreamcast/pci.c linux-2.5.71/arch/sh/boards/dreamcast/pci.c --- linux-2.5.70-bk19/arch/sh/boards/dreamcast/pci.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/dreamcast/pci.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,214 @@ +/* + $ $Id: pci.c,v 1.1.2.4.2.1 2003/03/31 14:33:18 lethal Exp $ + * Dreamcast PCI: Supports SEGA Broadband Adaptor only. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define GAPSPCI_REGS 0x01001400 +#define GAPSPCI_DMA_BASE 0x01840000 +#define GAPSPCI_DMA_SIZE 32768 +#define GAPSPCI_BBA_CONFIG 0x01001600 + +#define GAPSPCI_IRQ HW_EVENT_EXTERNAL + +static int gapspci_dma_used; + +/* XXX: Uh... */ +static struct resource gapspci_io_resource = { + "GAPSPCI IO", + 0x01001600, + 0x010016ff, + IORESOURCE_IO +}; + +static struct resource gapspci_mem_resource = { + "GAPSPCI mem", + 0x01840000, + 0x01847fff, + IORESOURCE_MEM +}; + +static struct pci_ops gapspci_pci_ops; +struct pci_channel board_pci_channels[] = { + {&gapspci_pci_ops, &gapspci_io_resource, &gapspci_mem_resource, 0, 1}, + {NULL, NULL, NULL, 0, 0}, +}; + +struct pci_fixup pcibios_fixups[] = { + {0, 0, 0, NULL} +}; + +#define BBA_SELECTED(bus,devfn) (bus->number==0 && devfn==0) + +static int gapspci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) +{ + switch (size) { + case 1: + if (BBA_SELECTED(bus, devfn)) + *val = (u8)inb(GAPSPCI_BBA_CONFIG+where); + else + *val = (u8)0xff; + break; + case 2: + if (BBA_SELECTED(bus, devfn)) + *val = (u16)inw(GAPSPCI_BBA_CONFIG+where); + else + *val = (u16)0xffff; + break; + case 4: + if (BBA_SELECTED(bus, devfn)) + *val = inl(GAPSPCI_BBA_CONFIG+where); + else + *val = 0xffffffff; + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int gapspci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) +{ + if (BBA_SELECTED(bus, devfn)) { + switch (size) { + case 1: + if (BBA_SELECTED(bus, devfn)) + outb((u8)val, GAPSPCI_BBA_CONFIG+where); + break; + case 2: + if (BBA_SELECTED(bus, devfn)) + outw((u16)val, GAPSPCI_BBA_CONFIG+where); + break; + case 4: + if (BBA_SELECTED(bus, devfn)) + outl(val, GAPSPCI_BBA_CONFIG+where); + break; + } + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops gapspci_pci_ops = { + .read = gapspci_read, + .write = gapspci_write, +}; + + +void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t * dma_handle) +{ + unsigned long buf; + + if (gapspci_dma_used+size > GAPSPCI_DMA_SIZE) + return NULL; + + buf = GAPSPCI_DMA_BASE+gapspci_dma_used; + + gapspci_dma_used = PAGE_ALIGN(gapspci_dma_used+size); + + printk("pci_alloc_consistent: %ld bytes at 0x%lx\n", (long)size, buf); + + *dma_handle = (dma_addr_t)buf; + + return (void *)P2SEGADDR(buf); +} + + +void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + /* XXX */ + gapspci_dma_used = 0; +} + + +void __init pcibios_fixup_bus(struct pci_bus *bus) +{ + struct list_head *ln; + struct pci_dev *dev; + + for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { + dev = pci_dev_b(ln); + if (!BBA_SELECTED(bus, dev->devfn)) continue; + + printk("PCI: MMIO fixup to %s\n", dev->dev.name); + dev->resource[1].start=0x01001700; + dev->resource[1].end=0x010017ff; + } +} + + +static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin) +{ + return PCI_SLOT(dev->devfn); +} + + +static int __init map_dc_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + return GAPSPCI_IRQ; +} + +void __init pcibios_fixup(void) { /* Do nothing. */ } + +void __init pcibios_fixup_irqs(void) +{ + pci_fixup_irqs(no_swizzle, map_dc_irq); +} + +int __init gapspci_init(void) +{ + int i; + char idbuf[16]; + + for(i=0; i<16; i++) + idbuf[i]=inb(GAPSPCI_REGS+i); + + if(strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16)) + return -1; + + outl(0x5a14a501, GAPSPCI_REGS+0x18); + + for(i=0; i<1000000; i++); + + if(inl(GAPSPCI_REGS+0x18)!=1) + return -1; + + outl(0x01000000, GAPSPCI_REGS+0x20); + outl(0x01000000, GAPSPCI_REGS+0x24); + + outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28); + outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c); + + outl(1, GAPSPCI_REGS+0x14); + outl(1, GAPSPCI_REGS+0x34); + + gapspci_dma_used=0; + + /* Setting Broadband Adapter */ + outw(0xf900, GAPSPCI_BBA_CONFIG+0x06); + outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30); + outb(0x00, GAPSPCI_BBA_CONFIG+0x3c); + outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d); + outw(0x0006, GAPSPCI_BBA_CONFIG+0x04); + outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10); + outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14); + + return 0; +} + +/* Haven't done anything here as yet */ +char * __devinit pcibios_setup(char *str) +{ + return str; +} diff -urN linux-2.5.70-bk19/arch/sh/boards/dreamcast/rtc.c linux-2.5.71/arch/sh/boards/dreamcast/rtc.c --- linux-2.5.70-bk19/arch/sh/boards/dreamcast/rtc.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/dreamcast/rtc.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,81 @@ +/* arch/sh/kernel/rtc-aica.c + * + * Dreamcast AICA RTC routines. + * + * Copyright (c) 2001, 2002 M. R. Brown + * Copyright (c) 2002 Paul Mundt + * + * Released under the terms of the GNU GPL v2.0. + * + */ + +#include + +#include + +extern void (*rtc_get_time)(struct timespec *); +extern int (*rtc_set_time)(const time_t); + +/* The AICA RTC has an Epoch of 1/1/1950, so we must subtract 20 years (in + seconds to get the standard Unix Epoch when getting the time, and add 20 + years when setting the time. */ +#define TWENTY_YEARS ((20 * 365LU + 5) * 86400) + +/* The AICA RTC is represented by a 32-bit seconds counter stored in 2 16-bit + registers.*/ +#define AICA_RTC_SECS_H 0xa0710000 +#define AICA_RTC_SECS_L 0xa0710004 + +/** + * aica_rtc_gettimeofday - Get the time from the AICA RTC + * @tv: pointer to resulting timeval + * + * Grabs the current RTC seconds counter and adjusts it to the Unix Epoch. + */ +void aica_rtc_gettimeofday(struct timespec *ts) { + unsigned long val1, val2; + + do { + val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | + (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); + + val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | + (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); + } while (val1 != val2); + + ts->tv_sec = val1 - TWENTY_YEARS; + + /* Can't get nanoseconds with just a seconds counter. */ + ts->tv_nsec = 0; +} + +/** + * aica_rtc_settimeofday - Set the AICA RTC to the current time + * @tv: contains the timeval to set + * + * Adjusts the given @tv to the AICA Epoch and sets the RTC seconds counter. + */ +int aica_rtc_settimeofday(const time_t secs) { + unsigned long val1, val2; + unsigned long adj = secs + TWENTY_YEARS; + + do { + ctrl_outl((adj & 0xffff0000) >> 16, AICA_RTC_SECS_H); + ctrl_outl((adj & 0xffff), AICA_RTC_SECS_L); + + val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | + (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); + + val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | + (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); + } while (val1 != val2); + + return 0; +} + +void aica_time_init(void) +{ + rtc_get_time = aica_rtc_gettimeofday; + rtc_set_time = aica_rtc_settimeofday; +} + diff -urN linux-2.5.70-bk19/arch/sh/boards/dreamcast/setup.c linux-2.5.71/arch/sh/boards/dreamcast/setup.c --- linux-2.5.70-bk19/arch/sh/boards/dreamcast/setup.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/dreamcast/setup.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,64 @@ +/* arch/sh/kernel/setup_dc.c + * + * Hardware support for the Sega Dreamcast. + * + * Copyright (c) 2001, 2002 M. R. Brown + * Copyright (c) 2002 Paul Mundt + * + * This file is part of the LinuxDC project (www.linuxdc.org) + * + * Released under the terms of the GNU GPL v2.0. + * + * This file originally bore the message (with enclosed-$): + * Id: setup_dc.c,v 1.5 2001/05/24 05:09:16 mrbrown Exp + * SEGA Dreamcast support + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +extern struct hw_interrupt_type systemasic_int; +/* XXX: Move this into it's proper header. */ +extern void (*board_time_init)(void); +extern void aica_time_init(void); + +const char *get_system_type(void) +{ + return "Sega Dreamcast"; +} + +#ifdef CONFIG_PCI +extern int gapspci_init(void); +#endif + +int __init platform_setup(void) +{ + int i; + + /* Mask all hardware events */ + /* XXX */ + + /* Acknowledge any previous events */ + /* XXX */ + + /* Assign all virtual IRQs to the System ASIC int. handler */ + for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++) + irq_desc[i].handler = &systemasic_int; + + board_time_init = aica_time_init; + +#ifdef CONFIG_PCI + if (gapspci_init() < 0) + printk(KERN_WARNING "GAPSPCI was not detected.\n"); +#endif + + return 0; +} diff -urN linux-2.5.70-bk19/arch/sh/boards/ec3104/Makefile linux-2.5.71/arch/sh/boards/ec3104/Makefile --- linux-2.5.70-bk19/arch/sh/boards/ec3104/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/ec3104/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,10 @@ +# +# Makefile for the EC3104 specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := mach.o setup.o io.o irq.o + diff -urN linux-2.5.70-bk19/arch/sh/boards/ec3104/io.c linux-2.5.71/arch/sh/boards/ec3104/io.c --- linux-2.5.70-bk19/arch/sh/boards/ec3104/io.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/ec3104/io.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,81 @@ +/* + * linux/arch/sh/kernel/io_ec3104.c + * EC3104 companion chip support + * + * Copyright (C) 2000 Philipp Rumpf + * + */ +/* EC3104 note: + * This code was written without any documentation about the EC3104 chip. While + * I hope I got most of the basic functionality right, the register names I use + * are most likely completely different from those in the chip documentation. + * + * If you have any further information about the EC3104, please tell me + * (prumpf@tux.org). + */ + +#include +#include +#include +#include +#include + +/* + * EC3104 has a real ISA bus which we redirect low port accesses to (the + * actual device on mine is a ESS 1868, and I don't want to hack the driver + * more than strictly necessary). I am not going to duplicate the + * hard coding of PC addresses (for the 16550s aso) here though; it's just + * too ugly. + */ + +#define low_port(port) ((port) < 0x10000) + +static inline unsigned long port2addr(unsigned long port) +{ + switch(port >> 16) { + case 0: + return EC3104_ISA_BASE + port * 2; + + /* XXX hack. it's unclear what to do about the serial ports */ + case 1: + return EC3104_BASE + (port&0xffff) * 4; + + default: + /* XXX PCMCIA */ + return 0; + } +} + +unsigned char ec3104_inb(unsigned long port) +{ + u8 ret; + + ret = *(volatile u8 *)port2addr(port); + + return ret; +} + +unsigned short ec3104_inw(unsigned long port) +{ + BUG(); +} + +unsigned long ec3104_inl(unsigned long port) +{ + BUG(); +} + +void ec3104_outb(unsigned char data, unsigned long port) +{ + *(volatile u8 *)port2addr(port) = data; +} + +void ec3104_outw(unsigned short data, unsigned long port) +{ + BUG(); +} + +void ec3104_outl(unsigned long data, unsigned long port) +{ + BUG(); +} diff -urN linux-2.5.70-bk19/arch/sh/boards/ec3104/irq.c linux-2.5.71/arch/sh/boards/ec3104/irq.c --- linux-2.5.70-bk19/arch/sh/boards/ec3104/irq.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/ec3104/irq.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,196 @@ +/* + * linux/arch/sh/boards/ec3104/irq.c + * EC3104 companion chip support + * + * Copyright (C) 2000 Philipp Rumpf + * + */ + +#include +#include +#include + +/* This is for debugging mostly; here's the table that I intend to keep + * in here: + * + * index function base addr power interrupt bit + * 0 power b0ec0000 --- 00000001 (unused) + * 1 irqs b0ec1000 --- 00000002 (unused) + * 2 ?? b0ec2000 b0ec0008 00000004 + * 3 PS2 (1) b0ec3000 b0ec000c 00000008 + * 4 PS2 (2) b0ec4000 b0ec0010 00000010 + * 5 ?? b0ec5000 b0ec0014 00000020 + * 6 I2C b0ec6000 b0ec0018 00000040 + * 7 serial (1) b0ec7000 b0ec001c 00000080 + * 8 serial (2) b0ec8000 b0ec0020 00000100 + * 9 serial (3) b0ec9000 b0ec0024 00000200 + * 10 serial (4) b0eca000 b0ec0028 00000400 + * 12 GPIO (1) b0ecc000 b0ec0030 + * 13 GPIO (2) b0ecc000 b0ec0030 + * 16 pcmcia (1) b0ed0000 b0ec0040 00010000 + * 17 pcmcia (2) b0ed1000 b0ec0044 00020000 + */ + +/* I used the register names from another interrupt controller I worked with, + * since it seems to be identical to the ec3104 except that all bits are + * inverted: + * + * IRR: Interrupt Request Register (pending and enabled interrupts) + * IMR: Interrupt Mask Register (which interrupts are enabled) + * IPR: Interrupt Pending Register (pending interrupts, even disabled ones) + * + * 0 bits mean pending or enabled, 1 bits mean not pending or disabled. all + * IRQs seem to be level-triggered. + */ + +#define EC3104_IRR (EC3104_BASE + 0x1000) +#define EC3104_IMR (EC3104_BASE + 0x1004) +#define EC3104_IPR (EC3104_BASE + 0x1008) + +#define ctrl_readl(addr) (*(volatile u32 *)(addr)) +#define ctrl_writel(data,addr) (*(volatile u32 *)(addr) = (data)) +#define ctrl_readb(addr) (*(volatile u8 *)(addr)) + +static char *ec3104_name(unsigned index) +{ + switch(index) { + case 0: + return "power management"; + case 1: + return "interrupts"; + case 3: + return "PS2 (1)"; + case 4: + return "PS2 (2)"; + case 5: + return "I2C (1)"; + case 6: + return "I2C (2)"; + case 7: + return "serial (1)"; + case 8: + return "serial (2)"; + case 9: + return "serial (3)"; + case 10: + return "serial (4)"; + case 16: + return "pcmcia (1)"; + case 17: + return "pcmcia (2)"; + default: { + static char buf[32]; + + sprintf(buf, "unknown (%d)", index); + + return buf; + } + } +} + +int get_pending_interrupts(char *buf) +{ + u32 ipr; + u32 bit; + char *p = buf; + + p += sprintf(p, "pending: ("); + + ipr = ctrl_inl(EC3104_IPR); + + for (bit = 1; bit < 32; bit++) + if (!(ipr & (1< + * + */ +/* EC3104 note: + * This code was written without any documentation about the EC3104 chip. While + * I hope I got most of the basic functionality right, the register names I use + * are most likely completely different from those in the chip documentation. + * + * If you have any further information about the EC3104, please tell me + * (prumpf@tux.org). + */ + +#include + +#include +#include +#include + +#include +#include + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_ec3104 __initmv = { + mv_name: "EC3104", + + mv_nr_irqs: 96, + + mv_inb: ec3104_inb, + mv_inw: ec3104_inw, + mv_inl: ec3104_inl, + mv_outb: ec3104_outb, + mv_outw: ec3104_outw, + mv_outl: ec3104_outl, + + mv_inb_p: generic_inb_p, + mv_inw_p: generic_inw, + mv_inl_p: generic_inl, + mv_outb_p: generic_outb_p, + mv_outw_p: generic_outw, + mv_outl_p: generic_outl, + + mv_insb: generic_insb, + mv_insw: generic_insw, + mv_insl: generic_insl, + mv_outsb: generic_outsb, + mv_outsw: generic_outsw, + mv_outsl: generic_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_irq_demux: ec3104_irq_demux, + + mv_rtc_gettimeofday: sh_rtc_gettimeofday, + mv_rtc_settimeofday: sh_rtc_settimeofday, +}; + +ALIAS_MV(ec3104) diff -urN linux-2.5.70-bk19/arch/sh/boards/ec3104/setup.c linux-2.5.71/arch/sh/boards/ec3104/setup.c --- linux-2.5.70-bk19/arch/sh/boards/ec3104/setup.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/ec3104/setup.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,57 @@ +/* + * linux/arch/sh/boards/ec3104/setup.c + * EC3104 companion chip support + * + * Copyright (C) 2000 Philipp Rumpf + * + */ +/* EC3104 note: + * This code was written without any documentation about the EC3104 chip. While + * I hope I got most of the basic functionality right, the register names I use + * are most likely completely different from those in the chip documentation. + * + * If you have any further information about the EC3104, please tell me + * (prumpf@tux.org). + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +int __init setup_ec3104(void) +{ + char str[8]; + int i; + + if (!MACH_EC3104) + printk("!MACH_EC3104\n"); + + if (0) + return 0; + + for (i=0; i<8; i++) + str[i] = ctrl_readb(EC3104_BASE + i); + + for (i = EC3104_IRQBASE; i < EC3104_IRQBASE + 32; i++) + irq_desc[i].handler = &ec3104_int; + + printk("initializing EC3104 \"%.8s\" at %08x, IRQ %d, IRQ base %d\n", + str, EC3104_BASE, EC3104_IRQ, EC3104_IRQBASE); + + + /* mask all interrupts. this should have been done by the boot + * loader for us but we want to be sure ... */ + ctrl_writel(0xffffffff, EC3104_IMR); + + return 0; +} + +module_init(setup_ec3104); diff -urN linux-2.5.70-bk19/arch/sh/boards/harp/Makefile linux-2.5.71/arch/sh/boards/harp/Makefile --- linux-2.5.70-bk19/arch/sh/boards/harp/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/harp/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,12 @@ +# +# Makefile for STMicroelectronics board specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := irq.o setup.o mach.o led.o + +obj-$(CONFIG_PCI) += pcidma.o + diff -urN linux-2.5.70-bk19/arch/sh/boards/harp/irq.c linux-2.5.71/arch/sh/boards/harp/irq.c --- linux-2.5.70-bk19/arch/sh/boards/harp/irq.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/harp/irq.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2000 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Looks after interrupts on the HARP board. + * + * Bases on the IPR irq system + */ + +#include +#include +#include + +#include +#include +#include + + +#define NUM_EXTERNAL_IRQS 16 + +// Early versions of the STB1 Overdrive required this nasty frig +//#define INVERT_INTMASK_WRITES + +static void enable_harp_irq(unsigned int irq); +static void disable_harp_irq(unsigned int irq); + +/* shutdown is same as "disable" */ +#define shutdown_harp_irq disable_harp_irq + +static void mask_and_ack_harp(unsigned int); +static void end_harp_irq(unsigned int irq); + +static unsigned int startup_harp_irq(unsigned int irq) +{ + enable_harp_irq(irq); + return 0; /* never anything pending */ +} + +static struct hw_interrupt_type harp_irq_type = { + "Harp-IRQ", + startup_harp_irq, + shutdown_harp_irq, + enable_harp_irq, + disable_harp_irq, + mask_and_ack_harp, + end_harp_irq +}; + +static void disable_harp_irq(unsigned int irq) +{ + unsigned val, flags; + unsigned maskReg; + unsigned mask; + int pri; + + if (irq < 0 || irq >= NUM_EXTERNAL_IRQS) + return; + + pri = 15 - irq; + + if (pri < 8) { + maskReg = EPLD_INTMASK0; + } else { + maskReg = EPLD_INTMASK1; + pri -= 8; + } + + local_irq_save(flags); + mask = ctrl_inl(maskReg); + mask &= (~(1 << pri)); +#if defined(INVERT_INTMASK_WRITES) + mask ^= 0xff; +#endif + ctrl_outl(mask, maskReg); + local_irq_restore(flags); +} + +static void enable_harp_irq(unsigned int irq) +{ + unsigned flags; + unsigned maskReg; + unsigned mask; + int pri; + + if (irq < 0 || irq >= NUM_EXTERNAL_IRQS) + return; + + pri = 15 - irq; + + if (pri < 8) { + maskReg = EPLD_INTMASK0; + } else { + maskReg = EPLD_INTMASK1; + pri -= 8; + } + + local_irq_save(flags); + mask = ctrl_inl(maskReg); + + + mask |= (1 << pri); + +#if defined(INVERT_INTMASK_WRITES) + mask ^= 0xff; +#endif + ctrl_outl(mask, maskReg); + + local_irq_restore(flags); +} + +/* This functions sets the desired irq handler to be an overdrive type */ +static void __init make_harp_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].handler = &harp_irq_type; + disable_harp_irq(irq); +} + +static void mask_and_ack_harp(unsigned int irq) +{ + disable_harp_irq(irq); +} + +static void end_harp_irq(unsigned int irq) +{ + enable_harp_irq(irq); +} + +void __init init_harp_irq(void) +{ + int i; + +#if !defined(INVERT_INTMASK_WRITES) + // On the harp these are set to enable an interrupt + ctrl_outl(0x00, EPLD_INTMASK0); + ctrl_outl(0x00, EPLD_INTMASK1); +#else + // On the Overdrive the data is inverted before being stored in the reg + ctrl_outl(0xff, EPLD_INTMASK0); + ctrl_outl(0xff, EPLD_INTMASK1); +#endif + + for (i = 0; i < NUM_EXTERNAL_IRQS; i++) { + make_harp_irq(i); + } +} diff -urN linux-2.5.70-bk19/arch/sh/boards/harp/led.c linux-2.5.71/arch/sh/boards/harp/led.c --- linux-2.5.70-bk19/arch/sh/boards/harp/led.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/harp/led.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,52 @@ +/* + * linux/arch/sh/stboards/led.c + * + * Copyright (C) 2000 Stuart Menefy + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file contains ST40STB1 HARP and compatible code. + */ + +#include +#include +#include + +/* Harp: Flash LD10 (front pannel) connected to EPLD (IC8) */ +/* Overdrive: Flash LD1 (front panel) connected to EPLD (IC4) */ +/* Works for HARP and overdrive */ +static void mach_led(int position, int value) +{ + if (value) { + ctrl_outl(EPLD_LED_ON, EPLD_LED); + } else { + ctrl_outl(EPLD_LED_OFF, EPLD_LED); + } +} + +#ifdef CONFIG_HEARTBEAT + +#include + +/* acts like an actual heart beat -- ie thump-thump-pause... */ +void heartbeat_harp(void) +{ + static unsigned cnt = 0, period = 0, dist = 0; + + if (cnt == 0 || cnt == dist) + mach_led( -1, 1); + else if (cnt == 7 || cnt == dist+7) + mach_led( -1, 0); + + if (++cnt > period) { + cnt = 0; + /* The hyperbolic function below modifies the heartbeat period + * length in dependency of the current (5min) load. It goes + * through the points f(0)=126, f(1)=86, f(5)=51, + * f(inf)->30. */ + period = ((672< + +#include +#include +#include +#include +#include + +void setup_harp(void); +void init_harp_irq(void); +void heartbeat_harp(void); + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_harp __initmv = { + mv_nr_irqs: 89 + HD64465_IRQ_NUM, + + mv_inb: hd64465_inb, + mv_inw: hd64465_inw, + mv_inl: hd64465_inl, + mv_outb: hd64465_outb, + mv_outw: hd64465_outw, + mv_outl: hd64465_outl, + + mv_inb_p: hd64465_inb_p, + mv_inw_p: hd64465_inw, + mv_inl_p: hd64465_inl, + mv_outb_p: hd64465_outb_p, + mv_outw_p: hd64465_outw, + mv_outl_p: hd64465_outl, + + mv_insb: hd64465_insb, + mv_insw: hd64465_insw, + mv_insl: hd64465_insl, + mv_outsb: hd64465_outsb, + mv_outsw: hd64465_outsw, + mv_outsl: hd64465_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_ioremap: generic_ioremap, + mv_iounmap: generic_iounmap, + + mv_isa_port2addr: hd64465_isa_port2addr, + +#ifdef CONFIG_PCI + mv_init_irq: init_harp_irq, +#endif +#ifdef CONFIG_HEARTBEAT + mv_heartbeat: heartbeat_harp, +#endif +}; + +ALIAS_MV(harp) diff -urN linux-2.5.70-bk19/arch/sh/boards/harp/pcidma.c linux-2.5.71/arch/sh/boards/harp/pcidma.c --- linux-2.5.70-bk19/arch/sh/boards/harp/pcidma.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/harp/pcidma.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Dynamic DMA mapping support. + */ + +#include +#include +#include +#include +#include +#include + + +void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t * dma_handle) +{ + void *ret; + int gfp = GFP_ATOMIC; + + ret = (void *) __get_free_pages(gfp, get_order(size)); + + if (ret != NULL) { + /* Is it neccessary to do the memset? */ + memset(ret, 0, size); + *dma_handle = virt_to_bus(ret); + } + /* We must flush the cache before we pass it on to the device */ + flush_cache_all(); + return P2SEGADDR(ret); +} + +void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + unsigned long p1addr=P1SEGADDR((unsigned long)vaddr); + + free_pages(p1addr, get_order(size)); +} diff -urN linux-2.5.70-bk19/arch/sh/boards/harp/setup.c linux-2.5.71/arch/sh/boards/harp/setup.c --- linux-2.5.70-bk19/arch/sh/boards/harp/setup.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/harp/setup.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,56 @@ +/* + * arch/sh/stboard/setup.c + * + * Copyright (C) 2001 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * STMicroelectronics ST40STB1 HARP and compatible support. + */ + +#include +#include +#include +#include +#include + +const char *get_system_type(void) +{ + return "STB1 Harp"; +} + +/* + * Initialize the board + */ +int __init platform_setup(void) +{ +#ifdef CONFIG_SH_STB1_HARP + unsigned long ic8_version, ic36_version; + + ic8_version = ctrl_inl(EPLD_REVID2); + ic36_version = ctrl_inl(EPLD_REVID1); + + printk("STMicroelectronics STB1 HARP initialisaton\n"); + printk("EPLD versions: IC8: %d.%02d, IC36: %d.%02d\n", + (ic8_version >> 4) & 0xf, ic8_version & 0xf, + (ic36_version >> 4) & 0xf, ic36_version & 0xf); +#elif defined(CONFIG_SH_STB1_OVERDRIVE) + unsigned long version; + + version = ctrl_inl(EPLD_REVID); + + printk("STMicroelectronics STB1 Overdrive initialisaton\n"); + printk("EPLD version: %d.%02d\n", + (version >> 4) & 0xf, version & 0xf); +#else +#error Undefined machine +#endif + + /* Currently all STB1 chips have problems with the sleep instruction, + * so disable it here. + */ + disable_hlt(); + + return 0; +} diff -urN linux-2.5.70-bk19/arch/sh/boards/hp6xx/hp620/Makefile linux-2.5.71/arch/sh/boards/hp6xx/hp620/Makefile --- linux-2.5.70-bk19/arch/sh/boards/hp6xx/hp620/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/hp6xx/hp620/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,10 @@ +# +# Makefile for the HP620 specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := mach.o + diff -urN linux-2.5.70-bk19/arch/sh/boards/hp6xx/hp620/mach.c linux-2.5.71/arch/sh/boards/hp6xx/hp620/mach.c --- linux-2.5.70-bk19/arch/sh/boards/hp6xx/hp620/mach.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/hp6xx/hp620/mach.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,68 @@ +/* + * linux/arch/sh/boards/hp6xx/hp620/mach.c + * + * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Machine vector for the HP620 + */ + +#include + +#include +#include +#include + +#include +#include +#include + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_hp620 __initmv = { + mv_name: "hp620", + + mv_nr_irqs: HD64461_IRQBASE+HD64461_IRQ_NUM, + + mv_inb: hd64461_inb, + mv_inw: hd64461_inw, + mv_inl: hd64461_inl, + mv_outb: hd64461_outb, + mv_outw: hd64461_outw, + mv_outl: hd64461_outl, + + mv_inb_p: hd64461_inb_p, + mv_inw_p: hd64461_inw, + mv_inl_p: hd64461_inl, + mv_outb_p: hd64461_outb_p, + mv_outw_p: hd64461_outw, + mv_outl_p: hd64461_outl, + + mv_insb: hd64461_insb, + mv_insw: hd64461_insw, + mv_insl: hd64461_insl, + mv_outsb: hd64461_outsb, + mv_outsw: hd64461_outsw, + mv_outsl: hd64461_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_irq_demux: hd64461_irq_demux, + + mv_rtc_gettimeofday: sh_rtc_gettimeofday, + mv_rtc_settimeofday: sh_rtc_settimeofday, + + mv_hw_hp600: 1, + mv_hw_hp620: 1, + mv_hw_hd64461: 1, +}; +ALIAS_MV(hp620) diff -urN linux-2.5.70-bk19/arch/sh/boards/hp6xx/hp680/Makefile linux-2.5.71/arch/sh/boards/hp6xx/hp680/Makefile --- linux-2.5.70-bk19/arch/sh/boards/hp6xx/hp680/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/hp6xx/hp680/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,10 @@ +# +# Makefile for the HP680 specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := mach.o + diff -urN linux-2.5.70-bk19/arch/sh/boards/hp6xx/hp680/mach.c linux-2.5.71/arch/sh/boards/hp6xx/hp680/mach.c --- linux-2.5.70-bk19/arch/sh/boards/hp6xx/hp680/mach.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/hp6xx/hp680/mach.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,64 @@ +/* + * linux/arch/sh/boards/hp6xx/hp680/mach.c + * + * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Machine vector for the HP680 + */ + +#include + +#include +#include +#include + +#include +#include +#include + +struct sh_machine_vector mv_hp680 __initmv = { + mv_name: "hp680", + + mv_nr_irqs: HD64461_IRQBASE+HD64461_IRQ_NUM, + + mv_inb: hd64461_inb, + mv_inw: hd64461_inw, + mv_inl: hd64461_inl, + mv_outb: hd64461_outb, + mv_outw: hd64461_outw, + mv_outl: hd64461_outl, + + mv_inb_p: hd64461_inb_p, + mv_inw_p: hd64461_inw, + mv_inl_p: hd64461_inl, + mv_outb_p: hd64461_outb_p, + mv_outw_p: hd64461_outw, + mv_outl_p: hd64461_outl, + + mv_insb: hd64461_insb, + mv_insw: hd64461_insw, + mv_insl: hd64461_insl, + mv_outsb: hd64461_outsb, + mv_outsw: hd64461_outsw, + mv_outsl: hd64461_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_irq_demux: hd64461_irq_demux, + + mv_rtc_gettimeofday: sh_rtc_gettimeofday, + mv_rtc_settimeofday: sh_rtc_settimeofday, + + mv_hw_hp600: 1, + mv_hw_hp680: 1, + mv_hw_hd64461: 1, +}; +ALIAS_MV(hp680) diff -urN linux-2.5.70-bk19/arch/sh/boards/hp6xx/hp690/Makefile linux-2.5.71/arch/sh/boards/hp6xx/hp690/Makefile --- linux-2.5.70-bk19/arch/sh/boards/hp6xx/hp690/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/hp6xx/hp690/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,10 @@ +# +# Makefile for the HP690 specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := mach.o + diff -urN linux-2.5.70-bk19/arch/sh/boards/hp6xx/hp690/mach.c linux-2.5.71/arch/sh/boards/hp6xx/hp690/mach.c --- linux-2.5.70-bk19/arch/sh/boards/hp6xx/hp690/mach.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/hp6xx/hp690/mach.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,64 @@ +/* + * linux/arch/sh/boards/hp6xx/hp690/mach.c + * + * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Machine vector for the HP690 + */ + +#include + +#include +#include +#include + +#include +#include +#include + +struct sh_machine_vector mv_hp690 __initmv = { + mv_name: "hp690", + + mv_nr_irqs: HD64461_IRQBASE+HD64461_IRQ_NUM, + + mv_inb: hd64461_inb, + mv_inw: hd64461_inw, + mv_inl: hd64461_inl, + mv_outb: hd64461_outb, + mv_outw: hd64461_outw, + mv_outl: hd64461_outl, + + mv_inb_p: hd64461_inb_p, + mv_inw_p: hd64461_inw, + mv_inl_p: hd64461_inl, + mv_outb_p: hd64461_outb_p, + mv_outw_p: hd64461_outw, + mv_outl_p: hd64461_outl, + + mv_insb: hd64461_insb, + mv_insw: hd64461_insw, + mv_insl: hd64461_insl, + mv_outsb: hd64461_outsb, + mv_outsw: hd64461_outsw, + mv_outsl: hd64461_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_irq_demux: hd64461_irq_demux, + + mv_rtc_gettimeofday: sh_rtc_gettimeofday, + mv_rtc_settimeofday: sh_rtc_settimeofday, + + mv_hw_hp600: 1, + mv_hw_hp690: 1, + mv_hw_hd64461: 1, +}; +ALIAS_MV(hp690) diff -urN linux-2.5.70-bk19/arch/sh/boards/overdrive/Makefile linux-2.5.71/arch/sh/boards/overdrive/Makefile --- linux-2.5.70-bk19/arch/sh/boards/overdrive/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/overdrive/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,12 @@ +# +# Makefile for the STMicroelectronics Overdrive specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := mach.o setup.o io.o irq.o led.o time.o + +obj-$(CONFIG_PCI) += fpga.o galileo.o pcidma.o + diff -urN linux-2.5.70-bk19/arch/sh/boards/overdrive/fpga.c linux-2.5.71/arch/sh/boards/overdrive/fpga.c --- linux-2.5.70-bk19/arch/sh/boards/overdrive/fpga.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/overdrive/fpga.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2000 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file handles programming up the Altera Flex10K that interfaces to + * the Galileo, and does the PS/2 keyboard and mouse + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include + +#define FPGA_NotConfigHigh() (*FPGA_ControlReg) = (*FPGA_ControlReg) | ENABLE_FPGA_BIT +#define FPGA_NotConfigLow() (*FPGA_ControlReg) = (*FPGA_ControlReg) & RESET_FPGA_MASK + +/* I need to find out what (if any) the real delay factor here is */ +/* The delay is definately not critical */ +#define long_delay() {int i;for(i=0;i<10000;i++);} +#define short_delay() {int i;for(i=0;i<100;i++);} + +static void __init program_overdrive_fpga(const unsigned char *fpgacode, + int size) +{ + int timeout = 0; + int i, j; + unsigned char b; + static volatile unsigned char *FPGA_ControlReg = + (volatile unsigned char *) (OVERDRIVE_CTRL); + static volatile unsigned char *FPGA_ProgramReg = + (volatile unsigned char *) (FPGA_DCLK_ADDRESS); + + printk("FPGA: Commencing FPGA Programming\n"); + + /* The PCI reset but MUST be low when programming the FPGA !!! */ + b = (*FPGA_ControlReg) & RESET_PCI_MASK; + + (*FPGA_ControlReg) = b; + + /* Prepare FPGA to program */ + + FPGA_NotConfigHigh(); + long_delay(); + + FPGA_NotConfigLow(); + short_delay(); + + while ((*FPGA_ProgramReg & FPGA_NOT_STATUS) != 0) { + printk("FPGA: Waiting for NotStatus to go Low ... \n"); + } + + FPGA_NotConfigHigh(); + + /* Wait for FPGA "ready to be programmed" signal */ + printk("FPGA: Waiting for NotStatus to go high (FPGA ready)... \n"); + + for (timeout = 0; + (((*FPGA_ProgramReg & FPGA_NOT_STATUS) == 0) + && (timeout < FPGA_TIMEOUT)); timeout++); + + /* Check if timeout condition occured - i.e. an error */ + + if (timeout == FPGA_TIMEOUT) { + printk + ("FPGA: Failed to program - Timeout waiting for notSTATUS to go high\n"); + return; + } + + printk("FPGA: Copying data to FPGA ... %d bytes\n", size); + + /* Copy array to FPGA - bit at a time */ + + for (i = 0; i < size; i++) { + volatile unsigned w = 0; + + for (j = 0; j < 8; j++) { + *FPGA_ProgramReg = (fpgacode[i] >> j) & 0x01; + short_delay(); + } + if ((i & 0x3ff) == 0) { + printk("."); + } + } + + /* Waiting for CONFDONE to go high - means the program is complete */ + + for (timeout = 0; + (((*FPGA_ProgramReg & FPGA_CONFDONE) == 0) + && (timeout < FPGA_TIMEOUT)); timeout++) { + + *FPGA_ProgramReg = 0x0; + long_delay(); + } + + if (timeout == FPGA_TIMEOUT) { + printk + ("FPGA: Failed to program - Timeout waiting for CONFDONE to go high\n"); + return; + } else { /* Clock another 10 times - gets the device into a working state */ + for (i = 0; i < 10; i++) { + *FPGA_ProgramReg = 0x0; + short_delay(); + } + } + + printk("FPGA: Programming complete\n"); +} + + +static const unsigned char __init fpgacode[] = { +#include "./overdrive.ttf" /* Code from maxplus2 compiler */ + , 0, 0 +}; + + +int __init init_overdrive_fpga(void) +{ + program_overdrive_fpga(fpgacode, sizeof(fpgacode)); + + return 0; +} diff -urN linux-2.5.70-bk19/arch/sh/boards/overdrive/galileo.c linux-2.5.71/arch/sh/boards/overdrive/galileo.c --- linux-2.5.70-bk19/arch/sh/boards/overdrive/galileo.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/overdrive/galileo.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,594 @@ +/* + * Copyright (C) 2000 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file contains the PCI routines required for the Galileo GT6411 + * PCI bridge as used on the Orion and Overdrive boards. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +/* After boot, we shift the Galileo registers so that they appear + * in BANK6, along with IO space. This means we can have one contingous + * lump of PCI address space without these registers appearing in the + * middle of them + */ + +#define GT64111_BASE_ADDRESS 0xbb000000 +#define GT64111_IO_BASE_ADDRESS 0x1000 +/* The GT64111 registers appear at this address to the SH4 after reset */ +#define RESET_GT64111_BASE_ADDRESS 0xb4000000 + +/* Macros used to access the Galileo registers */ +#define RESET_GT64111_REG(x) (RESET_GT64111_BASE_ADDRESS+x) +#define GT64111_REG(x) (GT64111_BASE_ADDRESS+x) + +#define RESET_GT_WRITE(x,v) writel((v),RESET_GT64111_REG(x)) + +#define RESET_GT_READ(x) readl(RESET_GT64111_REG(x)) + +#define GT_WRITE(x,v) writel((v),GT64111_REG(x)) +#define GT_WRITE_BYTE(x,v) writeb((v),GT64111_REG(x)) +#define GT_WRITE_SHORT(x,v) writew((v),GT64111_REG(x)) + +#define GT_READ(x) readl(GT64111_REG(x)) +#define GT_READ_BYTE(x) readb(GT64111_REG(x)) +#define GT_READ_SHORT(x) readw(GT64111_REG(x)) + + +/* Where the various SH banks start at */ +#define SH_BANK4_ADR 0xb0000000 +#define SH_BANK5_ADR 0xb4000000 +#define SH_BANK6_ADR 0xb8000000 + +/* Masks out everything but lines 28,27,26 */ +#define BANK_SELECT_MASK 0x1c000000 + +#define SH4_TO_BANK(x) ( (x) & BANK_SELECT_MASK) + +/* + * Masks used for address conversaion. Bank 6 is used for IO and + * has all the address bits zeroed by the FPGA. Special case this + */ +#define MEMORY_BANK_MASK 0x1fffffff +#define IO_BANK_MASK 0x03ffffff + +/* Mark bank 6 as the bank used for IO. You can change this in the FPGA code + * if you want + */ +#define IO_BANK_ADR PCI_GTIO_BASE + +/* Will select the correct mask to apply depending on the SH$ address */ +#define SELECT_BANK_MASK(x) \ + ( (SH4_TO_BANK(x)==SH4_TO_BANK(IO_BANK_ADR)) ? IO_BANK_MASK : MEMORY_BANK_MASK) + +/* Converts between PCI space and P2 region */ +#define SH4_TO_PCI(x) ((x)&SELECT_BANK_MASK(x)) + +/* Various macros for figuring out what to stick in the Galileo registers. + * You *really* don't want to figure this stuff out by hand, you always get + * it wrong + */ +#define GT_MEM_LO_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>21)&0x7ff) +#define GT_MEM_HI_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>21)&0x7f) +#define GT_MEM_SUB_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>20)&0xff) + +#define PROGRAM_HI_LO(block,a,s) \ + GT_WRITE(block##_LO_DEC_ADR,GT_MEM_LO_ADR(a));\ + GT_WRITE(block##_HI_DEC_ADR,GT_MEM_HI_ADR(a+s-1)) + +#define PROGRAM_SUB_HI_LO(block,a,s) \ + GT_WRITE(block##_LO_DEC_ADR,GT_MEM_SUB_ADR(a));\ + GT_WRITE(block##_HI_DEC_ADR,GT_MEM_SUB_ADR(a+s-1)) + +/* We need to set the size, and the offset register */ + +#define GT_BAR_MASK(x) ((x)&~0xfff) + +/* Macro to set up the BAR in the Galileo. Essentially used for the DRAM */ +#define PROGRAM_GT_BAR(block,a,s) \ + GT_WRITE(PCI_##block##_BANK_SIZE,GT_BAR_MASK((s-1)));\ + write_config_to_galileo(PCI_CONFIG_##block##_BASE_ADR,\ + GT_BAR_MASK(a)) + +#define DISABLE_GT_BAR(block) \ + GT_WRITE(PCI_##block##_BANK_SIZE,0),\ + GT_CONFIG_WRITE(PCI_CONFIG_##block##_BASE_ADR,\ + 0x80000000) + +/* Macros to disable things we are not going to use */ +#define DISABLE_DECODE(x) GT_WRITE(x##_LO_DEC_ADR,0x7ff);\ + GT_WRITE(x##_HI_DEC_ADR,0x00) + +#define DISABLE_SUB_DECODE(x) GT_WRITE(x##_LO_DEC_ADR,0xff);\ + GT_WRITE(x##_HI_DEC_ADR,0x00) + +static void __init reset_pci(void) +{ + /* Set RESET_PCI bit high */ + writeb(readb(OVERDRIVE_CTRL) | ENABLE_PCI_BIT, OVERDRIVE_CTRL); + udelay(250); + + /* Set RESET_PCI bit low */ + writeb(readb(OVERDRIVE_CTRL) & RESET_PCI_MASK, OVERDRIVE_CTRL); + udelay(250); + + writeb(readb(OVERDRIVE_CTRL) | ENABLE_PCI_BIT, OVERDRIVE_CTRL); + udelay(250); +} + +static int write_config_to_galileo(int where, u32 val); +#define GT_CONFIG_WRITE(where,val) write_config_to_galileo(where,val) + +#define ENABLE_PCI_DRAM + + +#ifdef TEST_DRAM +/* Test function to check out if the PCI DRAM is working OK */ +static int /* __init */ test_dram(unsigned *base, unsigned size) +{ + unsigned *p = base; + unsigned *end = (unsigned *) (((unsigned) base) + size); + unsigned w; + + for (p = base; p < end; p++) { + *p = 0xffffffff; + if (*p != 0xffffffff) { + printk("AAARGH -write failed!!! at %p is %x\n", p, + *p); + return 0; + } + *p = 0x0; + if (*p != 0x0) { + printk("AAARGH -write failed!!!\n"); + return 0; + } + } + + for (p = base; p < end; p++) { + *p = (unsigned) p; + if (*p != (unsigned) p) { + printk("Failed at 0x%p, actually is 0x%x\n", p, + *p); + return 0; + } + } + + for (p = base; p < end; p++) { + w = ((unsigned) p & 0xffff0000); + *p = w | (w >> 16); + } + + for (p = base; p < end; p++) { + w = ((unsigned) p & 0xffff0000); + w |= (w >> 16); + if (*p != w) { + printk + ("Failed at 0x%p, should be 0x%x actually is 0x%x\n", + p, w, *p); + return 0; + } + } + + return 1; +} +#endif + + +/* Function to set up and initialise the galileo. This sets up the BARS, + * maps the DRAM into the address space etc,etc + */ +int __init galileo_init(void) +{ + reset_pci(); + + /* Now shift the galileo regs into this block */ + RESET_GT_WRITE(INTERNAL_SPACE_DEC, + GT_MEM_LO_ADR(GT64111_BASE_ADDRESS)); + + /* Should have a sanity check here, that you can read back at the new + * address what you just wrote + */ + + /* Disable decode for all regions */ + DISABLE_DECODE(RAS10); + DISABLE_DECODE(RAS32); + DISABLE_DECODE(CS20); + DISABLE_DECODE(CS3); + DISABLE_DECODE(PCI_IO); + DISABLE_DECODE(PCI_MEM0); + DISABLE_DECODE(PCI_MEM1); + + /* Disable all BARS */ + GT_WRITE(BAR_ENABLE_ADR, 0x1ff); + DISABLE_GT_BAR(RAS10); + DISABLE_GT_BAR(RAS32); + DISABLE_GT_BAR(CS20); + DISABLE_GT_BAR(CS3); + + /* Tell the BAR where the IO registers now are */ + GT_CONFIG_WRITE(PCI_CONFIG_INT_REG_IO_ADR,GT_BAR_MASK( + (GT64111_IO_BASE_ADDRESS & + IO_BANK_MASK))); + /* set up a 112 Mb decode */ + PROGRAM_HI_LO(PCI_MEM0, SH_BANK4_ADR, 112 * 1024 * 1024); + + /* Set up a 32 MB io space decode */ + PROGRAM_HI_LO(PCI_IO, IO_BANK_ADR, 32 * 1024 * 1024); + +#ifdef ENABLE_PCI_DRAM + /* Program up the DRAM configuration - there is DRAM only in bank 0 */ + /* Now set up the DRAM decode */ + PROGRAM_HI_LO(RAS10, PCI_DRAM_BASE, PCI_DRAM_SIZE); + /* And the sub decode */ + PROGRAM_SUB_HI_LO(RAS0, PCI_DRAM_BASE, PCI_DRAM_SIZE); + + DISABLE_SUB_DECODE(RAS1); + + /* Set refresh rate */ + GT_WRITE(DRAM_BANK0_PARMS, 0x3f); + GT_WRITE(DRAM_CFG, 0x100); + + /* we have to lob off the top bits rememeber!! */ + PROGRAM_GT_BAR(RAS10, SH4_TO_PCI(PCI_DRAM_BASE), PCI_DRAM_SIZE); + +#endif + + /* We are only interested in decoding RAS10 and the Galileo's internal + * registers (as IO) on the PCI bus + */ +#ifdef ENABLE_PCI_DRAM + GT_WRITE(BAR_ENABLE_ADR, (~((1 << 8) | (1 << 3))) & 0x1ff); +#else + GT_WRITE(BAR_ENABLE_ADR, (~(1 << 3)) & 0x1ff); +#endif + + /* Change the class code to host bridge, it actually powers up + * as a memory controller + */ + GT_CONFIG_WRITE(8, 0x06000011); + + /* Allow the galileo to master the PCI bus */ + GT_CONFIG_WRITE(PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | + PCI_COMMAND_IO); + + +#if 0 + printk("Testing PCI DRAM - "); + if(test_dram(PCI_DRAM_BASE,PCI_DRAM_SIZE)) { + printk("Passed\n"); + }else { + printk("FAILED\n"); + } +#endif + return 0; + +} + + +#define SET_CONFIG_BITS(bus,devfn,where)\ + ((1<<31) | ((bus) << 16) | ((devfn) << 8) | ((where) & ~3)) + +#define CONFIG_CMD(dev, where) SET_CONFIG_BITS((dev)->bus->number,(dev)->devfn,where) + +/* This write to the galileo config registers, unlike the functions below, can + * be used before the PCI subsystem has started up + */ +static int __init write_config_to_galileo(int where, u32 val) +{ + GT_WRITE(PCI_CFG_ADR, SET_CONFIG_BITS(0, 0, where)); + + GT_WRITE(PCI_CFG_DATA, val); + return 0; +} + +/* We exclude the galileo and slot 31, the galileo because I don't know how to stop + * the setup code shagging up the setup I have done on it, and 31 because the whole + * thing locks up if you try to access that slot (which doesn't exist of course anyway + */ + +#define EXCLUDED_DEV(dev) ((dev->bus->number==0) && ((PCI_SLOT(dev->devfn)==0) || (PCI_SLOT(dev->devfn) == 31))) + +static int galileo_read_config_byte(struct pci_dev *dev, int where, + u8 * val) +{ + + + /* I suspect this doesn't work because this drives a special cycle ? */ + if (EXCLUDED_DEV(dev)) { + *val = 0xff; + return PCIBIOS_SUCCESSFUL; + } + /* Start the config cycle */ + GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where)); + /* Read back the result */ + *val = GT_READ_BYTE(PCI_CFG_DATA + (where & 3)); + + return PCIBIOS_SUCCESSFUL; +} + + +static int galileo_read_config_word(struct pci_dev *dev, int where, + u16 * val) +{ + + if (EXCLUDED_DEV(dev)) { + *val = 0xffff; + return PCIBIOS_SUCCESSFUL; + } + + GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where)); + *val = GT_READ_SHORT(PCI_CFG_DATA + (where & 2)); + + return PCIBIOS_SUCCESSFUL; +} + + +static int galileo_read_config_dword(struct pci_dev *dev, int where, + u32 * val) +{ + if (EXCLUDED_DEV(dev)) { + *val = 0xffffffff; + return PCIBIOS_SUCCESSFUL; + } + + GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where)); + *val = GT_READ(PCI_CFG_DATA); + + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_write_config_byte(struct pci_dev *dev, int where, + u8 val) +{ + GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where)); + + GT_WRITE_BYTE(PCI_CFG_DATA + (where & 3), val); + + return PCIBIOS_SUCCESSFUL; +} + + +static int galileo_write_config_word(struct pci_dev *dev, int where, + u16 val) +{ + GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where)); + + GT_WRITE_SHORT(PCI_CFG_DATA + (where & 2), val); + + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_write_config_dword(struct pci_dev *dev, int where, + u32 val) +{ + GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where)); + + GT_WRITE(PCI_CFG_DATA, val); + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops pci_config_ops = { + galileo_read_config_byte, + galileo_read_config_word, + galileo_read_config_dword, + galileo_write_config_byte, + galileo_write_config_word, + galileo_write_config_dword +}; + + +/* Everything hangs off this */ +static struct pci_bus *pci_root_bus; + + +static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin) +{ + return PCI_SLOT(dev->devfn); +} + +static int __init map_od_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + /* Slot 1: Galileo + * Slot 2: PCI Slot 1 + * Slot 3: PCI Slot 2 + * Slot 4: ESS + */ + switch (slot) { + case 2: + return OVERDRIVE_PCI_IRQ1; + case 3: + /* Note this assumes you have a hacked card in slot 2 */ + return OVERDRIVE_PCI_IRQ2; + case 4: + return OVERDRIVE_ESS_IRQ; + default: + /* printk("PCI: Unexpected IRQ mapping request for slot %d\n", slot); */ + return -1; + } +} + + + +void __init +pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges) +{ + ranges->io_start -= bus->resource[0]->start; + ranges->io_end -= bus->resource[0]->start; + ranges->mem_start -= bus->resource[1]->start; + ranges->mem_end -= bus->resource[1]->start; +} + +static void __init pci_fixup_ide_bases(struct pci_dev *d) +{ + int i; + + /* + * PCI IDE controllers use non-standard I/O port decoding, respect it. + */ + if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) + return; + printk("PCI: IDE base address fixup for %s\n", d->slot_name); + for(i=0; i<4; i++) { + struct resource *r = &d->resource[i]; + if ((r->start & ~0x80) == 0x374) { + r->start |= 2; + r->end = r->start; + } + } +} + + +/* Add future fixups here... */ +struct pci_fixup pcibios_fixups[] = { + { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, + { 0 } +}; + +void __init pcibios_init(void) +{ + static struct resource galio,galmem; + + /* Allocate the registers used by the Galileo */ + galio.flags = IORESOURCE_IO; + galio.name = "Galileo GT64011"; + galmem.flags = IORESOURCE_MEM|IORESOURCE_PREFETCH; + galmem.name = "Galileo GT64011 DRAM"; + + allocate_resource(&ioport_resource, &galio, 256, + GT64111_IO_BASE_ADDRESS,GT64111_IO_BASE_ADDRESS+256, 256, NULL, NULL); + allocate_resource(&iomem_resource, &galmem,PCI_DRAM_SIZE, + PHYSADDR(PCI_DRAM_BASE), PHYSADDR(PCI_DRAM_BASE)+PCI_DRAM_SIZE, + PCI_DRAM_SIZE, NULL, NULL); + + /* ok, do the scan man */ + pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL); + + pci_assign_unassigned_resources(); + pci_fixup_irqs(no_swizzle, map_od_irq); + +#ifdef TEST_DRAM + printk("Testing PCI DRAM - "); + if(test_dram(PCI_DRAM_BASE,PCI_DRAM_SIZE)) { + printk("Passed\n"); + }else { + printk("FAILED\n"); + } +#endif + +} + +char * __init pcibios_setup(char *str) +{ + return str; +} + + + +int pcibios_enable_device(struct pci_dev *dev) +{ + + u16 cmd, old_cmd; + int idx; + struct resource *r; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for (idx = 0; idx < 6; idx++) { + r = dev->resource + idx; + if (!r->start && r->end) { + printk(KERN_ERR + "PCI: Device %s not available because" + " of resource collisions\n", + dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (cmd != old_cmd) { + printk("PCI: enabling device %s (%04x -> %04x)\n", + dev->slot_name, old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; + +} + +/* We should do some optimisation work here I think. Ok for now though */ +void __init pcibios_fixup_bus(struct pci_bus *bus) +{ + +} + +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size) +{ +} + +void __init pcibios_update_resource(struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) +{ + + unsigned long where, size; + u32 reg; + + + printk("PCI: Assigning %3s %08lx to %s\n", + res->flags & IORESOURCE_IO ? "IO" : "MEM", + res->start, dev->name); + + where = PCI_BASE_ADDRESS_0 + resource * 4; + size = res->end - res->start; + + pci_read_config_dword(dev, where, ®); + reg = (reg & size) | (((u32) (res->start - root->start)) & ~size); + pci_write_config_dword(dev, where, reg); +} + + +void __init pcibios_update_irq(struct pci_dev *dev, int irq) +{ + printk("PCI: Assigning IRQ %02d to %s\n", irq, dev->name); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + +/* + * If we set up a device for bus mastering, we need to check the latency + * timer as certain crappy BIOSes forget to set it properly. + */ +unsigned int pcibios_max_latency = 255; + +void pcibios_set_master(struct pci_dev *dev) +{ + u8 lat; + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + if (lat < 16) + lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; + else if (lat > pcibios_max_latency) + lat = pcibios_max_latency; + else + return; + printk("PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); +} diff -urN linux-2.5.70-bk19/arch/sh/boards/overdrive/io.c linux-2.5.71/arch/sh/boards/overdrive/io.c --- linux-2.5.70-bk19/arch/sh/boards/overdrive/io.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/overdrive/io.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2000 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file contains the I/O routines for use on the overdrive board + * + */ + +#include +#include +#include +#include +#include +#include + +#include + +/* + * readX/writeX() are used to access memory mapped devices. On some + * architectures the memory mapped IO stuff needs to be accessed + * differently. On the SuperH architecture, we just read/write the + * memory location directly. + */ + +#define dprintk(x...) + +/* Translates an IO address to where it is mapped in memory */ + +#define io_addr(x) (((unsigned)(x))|PCI_GTIO_BASE) + +unsigned char od_inb(unsigned long port) +{ +dprintk("od_inb(%x)\n", port); + return readb(io_addr(port)) & 0xff; +} + + +unsigned short od_inw(unsigned long port) +{ +dprintk("od_inw(%x)\n", port); + return readw(io_addr(port)) & 0xffff; +} + +unsigned int od_inl(unsigned long port) +{ +dprintk("od_inl(%x)\n", port); + return readl(io_addr(port)); +} + +void od_outb(unsigned char value, unsigned long port) +{ +dprintk("od_outb(%x, %x)\n", value, port); + writeb(value, io_addr(port)); +} + +void od_outw(unsigned short value, unsigned long port) +{ +dprintk("od_outw(%x, %x)\n", value, port); + writew(value, io_addr(port)); +} + +void od_outl(unsigned int value, unsigned long port) +{ +dprintk("od_outl(%x, %x)\n", value, port); + writel(value, io_addr(port)); +} + +/* This is horrible at the moment - needs more work to do something sensible */ +#define IO_DELAY() udelay(10) + +#define OUT_DELAY(x,type) \ +void od_out##x##_p(unsigned type value,unsigned long port){out##x(value,port);IO_DELAY();} + +#define IN_DELAY(x,type) \ +unsigned type od_in##x##_p(unsigned long port) {unsigned type tmp=in##x(port);IO_DELAY();return tmp;} + + +OUT_DELAY(b,char) +OUT_DELAY(w,short) +OUT_DELAY(l,int) + +IN_DELAY(b,char) +IN_DELAY(w,short) +IN_DELAY(l,int) + + +/* Now for the string version of these functions */ +void od_outsb(unsigned long port, const void *addr, unsigned long count) +{ + int i; + unsigned char *p = (unsigned char *) addr; + + for (i = 0; i < count; i++, p++) { + outb(*p, port); + } +} + + +void od_insb(unsigned long port, void *addr, unsigned long count) +{ + int i; + unsigned char *p = (unsigned char *) addr; + + for (i = 0; i < count; i++, p++) { + *p = inb(port); + } +} + +/* For the 16 and 32 bit string functions, we have to worry about alignment. + * The SH does not do unaligned accesses, so we have to read as bytes and + * then write as a word or dword. + * This can be optimised a lot more, especially in the case where the data + * is aligned + */ + +void od_outsw(unsigned long port, const void *addr, unsigned long count) +{ + int i; + unsigned short tmp; + unsigned char *p = (unsigned char *) addr; + + for (i = 0; i < count; i++, p += 2) { + tmp = (*p) | ((*(p + 1)) << 8); + outw(tmp, port); + } +} + + +void od_insw(unsigned long port, void *addr, unsigned long count) +{ + int i; + unsigned short tmp; + unsigned char *p = (unsigned char *) addr; + + for (i = 0; i < count; i++, p += 2) { + tmp = inw(port); + p[0] = tmp & 0xff; + p[1] = (tmp >> 8) & 0xff; + } +} + + +void od_outsl(unsigned long port, const void *addr, unsigned long count) +{ + int i; + unsigned tmp; + unsigned char *p = (unsigned char *) addr; + + for (i = 0; i < count; i++, p += 4) { + tmp = (*p) | ((*(p + 1)) << 8) | ((*(p + 2)) << 16) | + ((*(p + 3)) << 24); + outl(tmp, port); + } +} + + +void od_insl(unsigned long port, void *addr, unsigned long count) +{ + int i; + unsigned tmp; + unsigned char *p = (unsigned char *) addr; + + for (i = 0; i < count; i++, p += 4) { + tmp = inl(port); + p[0] = tmp & 0xff; + p[1] = (tmp >> 8) & 0xff; + p[2] = (tmp >> 16) & 0xff; + p[3] = (tmp >> 24) & 0xff; + + } +} diff -urN linux-2.5.70-bk19/arch/sh/boards/overdrive/irq.c linux-2.5.71/arch/sh/boards/overdrive/irq.c --- linux-2.5.70-bk19/arch/sh/boards/overdrive/irq.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/overdrive/irq.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2000 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Looks after interrupts on the overdrive board. + * + * Bases on the IPR irq system + */ + +#include +#include +#include + +#include +#include + +#include + +struct od_data { + int overdrive_irq; + int irq_mask; +}; + +#define NUM_EXTERNAL_IRQS 16 +#define EXTERNAL_IRQ_NOT_IN_USE (-1) +#define EXTERNAL_IRQ_NOT_ASSIGNED (-1) + +/* + * This table is used to determine what to program into the FPGA's CT register + * for the specified Linux IRQ. + * + * The irq_mask gives the interrupt number from the PCI board (PCI_Int(6:0)) + * but is one greater than that because the because the FPGA treats 0 + * as disabled, a value of 1 asserts PCI_Int0, and so on. + * + * The overdrive_irq specifies which of the eight interrupt sources generates + * that interrupt, and but is multiplied by four to give the bit offset into + * the CT register. + * + * The seven interrupts levels (SH4 IRL's) we have available here is hardwired + * by the EPLD. The assignments here of which PCI interrupt generates each + * level is arbitary. + */ +static struct od_data od_data_table[NUM_EXTERNAL_IRQS] = { + /* overdrive_irq , irq_mask */ + {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 0 */ + {EXTERNAL_IRQ_NOT_ASSIGNED, 7}, /* 1 */ + {EXTERNAL_IRQ_NOT_ASSIGNED, 6}, /* 2 */ + {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 3 */ + {EXTERNAL_IRQ_NOT_ASSIGNED, 5}, /* 4 */ + {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 5 */ + {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 6 */ + {EXTERNAL_IRQ_NOT_ASSIGNED, 4}, /* 7 */ + {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 8 */ + {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 9 */ + {EXTERNAL_IRQ_NOT_ASSIGNED, 3}, /* 10 */ + {EXTERNAL_IRQ_NOT_ASSIGNED, 2}, /* 11 */ + {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 12 */ + {EXTERNAL_IRQ_NOT_ASSIGNED, 1}, /* 13 */ + {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}, /* 14 */ + {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE} /* 15 */ +}; + +static void set_od_data(int overdrive_irq, int irq) +{ + if (irq >= NUM_EXTERNAL_IRQS || irq < 0) + return; + od_data_table[irq].overdrive_irq = overdrive_irq << 2; +} + +static void enable_od_irq(unsigned int irq); +void disable_od_irq(unsigned int irq); + +/* shutdown is same as "disable" */ +#define shutdown_od_irq disable_od_irq + +static void mask_and_ack_od(unsigned int); +static void end_od_irq(unsigned int irq); + +static unsigned int startup_od_irq(unsigned int irq) +{ + enable_od_irq(irq); + return 0; /* never anything pending */ +} + +static struct hw_interrupt_type od_irq_type = { + "Overdrive-IRQ", + startup_od_irq, + shutdown_od_irq, + enable_od_irq, + disable_od_irq, + mask_and_ack_od, + end_od_irq +}; + +static void disable_od_irq(unsigned int irq) +{ + unsigned val, flags; + int overdrive_irq; + unsigned mask; + + /* Not a valid interrupt */ + if (irq < 0 || irq >= NUM_EXTERNAL_IRQS) + return; + + /* Is is necessary to use a cli here? Would a spinlock not be + * mroe efficient? + */ + local_irq_save(flags); + overdrive_irq = od_data_table[irq].overdrive_irq; + if (overdrive_irq != EXTERNAL_IRQ_NOT_ASSIGNED) { + mask = ~(0x7 << overdrive_irq); + val = ctrl_inl(OVERDRIVE_INT_CT); + val &= mask; + ctrl_outl(val, OVERDRIVE_INT_CT); + } + local_irq_restore(flags); +} + +static void enable_od_irq(unsigned int irq) +{ + unsigned val, flags; + int overdrive_irq; + unsigned mask; + + /* Not a valid interrupt */ + if (irq < 0 || irq >= NUM_EXTERNAL_IRQS) + return; + + /* Set priority in OD back to original value */ + local_irq_save(flags); + /* This one is not in use currently */ + overdrive_irq = od_data_table[irq].overdrive_irq; + if (overdrive_irq != EXTERNAL_IRQ_NOT_ASSIGNED) { + val = ctrl_inl(OVERDRIVE_INT_CT); + mask = ~(0x7 << overdrive_irq); + val &= mask; + mask = od_data_table[irq].irq_mask << overdrive_irq; + val |= mask; + ctrl_outl(val, OVERDRIVE_INT_CT); + } + local_irq_restore(flags); +} + + + +/* this functions sets the desired irq handler to be an overdrive type */ +static void __init make_od_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].handler = &od_irq_type; + disable_od_irq(irq); +} + + +static void mask_and_ack_od(unsigned int irq) +{ + disable_od_irq(irq); +} + +static void end_od_irq(unsigned int irq) +{ + enable_od_irq(irq); +} + +void __init init_overdrive_irq(void) +{ + int i; + + /* Disable all interrupts */ + ctrl_outl(0, OVERDRIVE_INT_CT); + + /* Update interrupt pin mode to use encoded interrupts */ + i = ctrl_inw(INTC_ICR); + i &= ~INTC_ICR_IRLM; + ctrl_outw(i, INTC_ICR); + + for (i = 0; i < NUM_EXTERNAL_IRQS; i++) { + if (od_data_table[i].irq_mask != EXTERNAL_IRQ_NOT_IN_USE) { + make_od_irq(i); + } else if (i != 15) { // Cannot use imask on level 15 + make_imask_irq(i); + } + } + + /* Set up the interrupts */ + set_od_data(OVERDRIVE_PCI_INTA, OVERDRIVE_PCI_IRQ1); + set_od_data(OVERDRIVE_PCI_INTB, OVERDRIVE_PCI_IRQ2); + set_od_data(OVERDRIVE_AUDIO_INT, OVERDRIVE_ESS_IRQ); +} diff -urN linux-2.5.70-bk19/arch/sh/boards/overdrive/led.c linux-2.5.71/arch/sh/boards/overdrive/led.c --- linux-2.5.70-bk19/arch/sh/boards/overdrive/led.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/overdrive/led.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,59 @@ +/* + * linux/arch/sh/overdrive/led.c + * + * Copyright (C) 1999 Stuart Menefy + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file contains an Overdrive specific LED feature. + */ + +#include +#include +#include +#include + +static void mach_led(int position, int value) +{ + unsigned long flags; + unsigned long reg; + + local_irq_save(flags); + + reg = readl(OVERDRIVE_CTRL); + if (value) { + reg |= (1<<3); + } else { + reg &= ~(1<<3); + } + writel(reg, OVERDRIVE_CTRL); + + local_irq_restore(flags); +} + +#ifdef CONFIG_HEARTBEAT + +#include + +/* acts like an actual heart beat -- ie thump-thump-pause... */ +void heartbeat_od(void) +{ + static unsigned cnt = 0, period = 0, dist = 0; + + if (cnt == 0 || cnt == dist) + mach_led( -1, 1); + else if (cnt == 7 || cnt == dist+7) + mach_led( -1, 0); + + if (++cnt > period) { + cnt = 0; + /* The hyperbolic function below modifies the heartbeat period + * length in dependency of the current (5min) load. It goes + * through the points f(0)=126, f(1)=86, f(5)=51, + * f(inf)->30. */ + period = ((672< + +#include +#include +#include + +#include +#include +#include + +void heartbeat_od(void); +void init_overdrive_irq(void); +void galileo_pcibios_init(void); + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_od __initmv = { + mv_nr_irqs: 48, + + mv_inb: od_inb, + mv_inw: od_inw, + mv_inl: od_inl, + mv_outb: od_outb, + mv_outw: od_outw, + mv_outl: od_outl, + + mv_inb_p: od_inb_p, + mv_inw_p: od_inw_p, + mv_inl_p: od_inl_p, + mv_outb_p: od_outb_p, + mv_outw_p: od_outw_p, + mv_outl_p: od_outl_p, + + mv_insb: od_insb, + mv_insw: od_insw, + mv_insl: od_insl, + mv_outsb: od_outsb, + mv_outsw: od_outsw, + mv_outsl: od_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_ioremap: generic_ioremap, + mv_iounmap: generic_iounmap, + + mv_isa_port2addr: generic_isa_port2addr, + +#ifdef CONFIG_PCI + mv_init_irq: init_overdrive_irq, +#endif +#ifdef CONFIG_HEARTBEAT + mv_heartbeat: heartbeat_od, +#endif +}; + +ALIAS_MV(od) diff -urN linux-2.5.70-bk19/arch/sh/boards/overdrive/pcidma.c linux-2.5.71/arch/sh/boards/overdrive/pcidma.c --- linux-2.5.70-bk19/arch/sh/boards/overdrive/pcidma.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/overdrive/pcidma.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2000 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Dynamic DMA mapping support. + * + * On the overdrive, we can only DMA from memory behind the PCI bus! + * this means that all DMA'able memory must come from there. + * this restriction will not apply to later boards. + */ + +#include +#include +#include +#include +#include + +void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t * dma_handle) +{ + void *ret; + int gfp = GFP_ATOMIC; + + printk("BUG: pci_alloc_consistent() called - not yet supported\n"); + /* We ALWAYS need DMA memory on the overdrive hardware, + * due to it's extreme wierdness + * Need to flush the cache here as well, since the memory + * can still be seen through the cache! + */ + gfp |= GFP_DMA; + ret = (void *) __get_free_pages(gfp, get_order(size)); + + if (ret != NULL) { + memset(ret, 0, size); + *dma_handle = virt_to_bus(ret); + } + return ret; +} + +void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + free_pages((unsigned long) vaddr, get_order(size)); +} diff -urN linux-2.5.70-bk19/arch/sh/boards/overdrive/setup.c linux-2.5.71/arch/sh/boards/overdrive/setup.c --- linux-2.5.70-bk19/arch/sh/boards/overdrive/setup.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/overdrive/setup.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,41 @@ +/* + * arch/sh/overdrive/setup.c + * + * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * STMicroelectronics Overdrive Support. + */ + +#include +#include +#include +#include + +#include +#include + +extern void od_time_init(void); + +const char *get_system_type(void) +{ + return "SH7750 Overdrive"; +} + +/* + * Initialize the board + */ +int __init platform_setup(void) +{ +#ifdef CONFIG_PCI + init_overdrive_fpga(); + galileo_init(); +#endif + + board_time_init = od_time_init; + + /* Enable RS232 receive buffers */ + writel(0x1e, OVERDRIVE_CTRL); +} diff -urN linux-2.5.70-bk19/arch/sh/boards/overdrive/time.c linux-2.5.71/arch/sh/boards/overdrive/time.c --- linux-2.5.70-bk19/arch/sh/boards/overdrive/time.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/overdrive/time.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,119 @@ +/* + * arch/sh/boards/overdrive/time.c + * + * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) + * Copyright (C) 2002 Paul Mundt (lethal@chaoticdreams.org) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * STMicroelectronics Overdrive Support. + */ + +void od_time_init(void) +{ + struct frqcr_data { + unsigned short frqcr; + struct { + unsigned char multiplier; + unsigned char divisor; + } factor[3]; + }; + + static struct frqcr_data st40_frqcr_table[] = { + { 0x000, {{1,1}, {1,1}, {1,2}}}, + { 0x002, {{1,1}, {1,1}, {1,4}}}, + { 0x004, {{1,1}, {1,1}, {1,8}}}, + { 0x008, {{1,1}, {1,2}, {1,2}}}, + { 0x00A, {{1,1}, {1,2}, {1,4}}}, + { 0x00C, {{1,1}, {1,2}, {1,8}}}, + { 0x011, {{1,1}, {2,3}, {1,6}}}, + { 0x013, {{1,1}, {2,3}, {1,3}}}, + { 0x01A, {{1,1}, {1,2}, {1,4}}}, + { 0x01C, {{1,1}, {1,2}, {1,8}}}, + { 0x023, {{1,1}, {2,3}, {1,3}}}, + { 0x02C, {{1,1}, {1,2}, {1,8}}}, + { 0x048, {{1,2}, {1,2}, {1,4}}}, + { 0x04A, {{1,2}, {1,2}, {1,6}}}, + { 0x04C, {{1,2}, {1,2}, {1,8}}}, + { 0x05A, {{1,2}, {1,3}, {1,6}}}, + { 0x05C, {{1,2}, {1,3}, {1,6}}}, + { 0x063, {{1,2}, {1,4}, {1,4}}}, + { 0x06C, {{1,2}, {1,4}, {1,8}}}, + { 0x091, {{1,3}, {1,3}, {1,6}}}, + { 0x093, {{1,3}, {1,3}, {1,6}}}, + { 0x0A3, {{1,3}, {1,6}, {1,6}}}, + { 0x0DA, {{1,4}, {1,4}, {1,8}}}, + { 0x0DC, {{1,4}, {1,4}, {1,8}}}, + { 0x0EC, {{1,4}, {1,8}, {1,8}}}, + { 0x123, {{1,4}, {1,4}, {1,8}}}, + { 0x16C, {{1,4}, {1,8}, {1,8}}}, + }; + + struct memclk_data { + unsigned char multiplier; + unsigned char divisor; + }; + static struct memclk_data st40_memclk_table[8] = { + {1,1}, // 000 + {1,2}, // 001 + {1,3}, // 010 + {2,3}, // 011 + {1,4}, // 100 + {1,6}, // 101 + {1,8}, // 110 + {1,8} // 111 + }; + + unsigned long pvr; + + /* + * This should probably be moved into the SH3 probing code, and then + * use the processor structure to determine which CPU we are running + * on. + */ + pvr = ctrl_inl(CCN_PVR); + printk("PVR %08x\n", pvr); + + if (((pvr >> CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1) { + /* + * Unfortunatly the STB1 FRQCR values are different from the + * 7750 ones. + */ + struct frqcr_data *d; + int a; + unsigned long memclkcr; + struct memclk_data *e; + + for (a=0; afrqcr == (frqcr & 0x1ff)) + break; + } + if (a == ARRAY_SIZE(st40_frqcr_table)) { + d = st40_frqcr_table; + printk("ERROR: Unrecognised FRQCR value, using default multipliers\n"); + } + + memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR); + e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK]; + + printk("Clock multipliers: CPU: %d/%d Bus: %d/%d Mem: %d/%d Periph: %d/%d\n", + d->factor[0].multiplier, d->factor[0].divisor, + d->factor[1].multiplier, d->factor[1].divisor, + e->multiplier, e->divisor, + d->factor[2].multiplier, d->factor[2].divisor); + + current_cpu_data.master_clock = current_cpu_data.module_clock * + d->factor[2].divisor / + d->factor[2].multiplier; + current_cpu_data.bus_clock = current_cpu_data.master_clock * + d->factor[1].multiplier / + d->factor[1].divisor; + current_cpu_data.memory_clock = current_cpu_data.master_clock * + e->multiplier / e->divisor; + current_cpu_data.cpu_clock = current_cpu_data.master_clock * + d->factor[0].multiplier / + d->factor[0].divisor; +} + diff -urN linux-2.5.70-bk19/arch/sh/boards/saturn/Makefile linux-2.5.71/arch/sh/boards/saturn/Makefile --- linux-2.5.70-bk19/arch/sh/boards/saturn/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/saturn/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,12 @@ +# +# Makefile for the Sega Saturn specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := mach.o setup.o io.o irq.o + +obj-$(CONFIG_SMP) += smp.o + diff -urN linux-2.5.70-bk19/arch/sh/boards/saturn/io.c linux-2.5.71/arch/sh/boards/saturn/io.c --- linux-2.5.70-bk19/arch/sh/boards/saturn/io.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/saturn/io.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,26 @@ +/* + * arch/sh/boards/saturn/io.c + * + * I/O routines for the Sega Saturn. + * + * Copyright (C) 2002 Paul Mundt + * + * Released under the terms of the GNU GPL v2.0. + */ +#include +#include + +unsigned long saturn_isa_port2addr(unsigned long offset) +{ + return offset; +} + +void *saturn_ioremap(unsigned long offset, unsigned long size) +{ + return (void *)offset; +} + +void saturn_iounmap(void *addr) +{ +} + diff -urN linux-2.5.70-bk19/arch/sh/boards/saturn/irq.c linux-2.5.71/arch/sh/boards/saturn/irq.c --- linux-2.5.70-bk19/arch/sh/boards/saturn/irq.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/saturn/irq.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,119 @@ +/* + * arch/sh/boards/saturn/irq.c + * + * Copyright (C) 2002 Paul Mundt + * + * Released under the terms of the GNU GPL v2.0. + */ +#include +#include +#include +#include +#include +#include + +/* + * Interrupts map out as follows: + * + * Vector Name Mask + * + * 64 VBLANKIN 0x0001 + * 65 VBLANKOUT 0x0002 + * 66 HBLANKIN 0x0004 + * 67 TIMER0 0x0008 + * 68 TIMER1 0x0010 + * 69 DSPEND 0x0020 + * 70 SOUNDREQUEST 0x0040 + * 71 SYSTEMMANAGER 0x0080 + * 72 PAD 0x0100 + * 73 LEVEL2DMAEND 0x0200 + * 74 LEVEL1DMAEND 0x0400 + * 75 LEVEL0DMAEND 0x0800 + * 76 DMAILLEGAL 0x1000 + * 77 SRITEDRAWEND 0x2000 + * 78 ABUS 0x8000 + * + */ +#define SATURN_IRQ_MIN 64 /* VBLANKIN */ +#define SATURN_IRQ_MAX 78 /* ABUS */ + +#define SATURN_IRQ_MASK 0xbfff + +static inline u32 saturn_irq_mask(unsigned int irq_nr) +{ + u32 mask; + + mask = (1 << (irq_nr - SATURN_IRQ_MIN)); + mask <<= (irq_nr == SATURN_IRQ_MAX); + mask &= SATURN_IRQ_MASK; + + return mask; +} + +static inline void mask_saturn_irq(unsigned int irq_nr) +{ + u32 mask; + + mask = ctrl_inl(SATURN_IMR); + mask |= saturn_irq_mask(irq_nr); + ctrl_outl(mask, SATURN_IMR); +} + +static inline void unmask_saturn_irq(unsigned int irq_nr) +{ + u32 mask; + + mask = ctrl_inl(SATURN_IMR); + mask &= ~saturn_irq_mask(irq_nr); + ctrl_outl(SATURN_IMR); +} + +static void disable_saturn_irq(unsigned int irq_nr) +{ + mask_saturn_irq(irq_nr); +} + +static void enable_saturn_irq(unsigned int irq_nr) +{ + unmask_saturn_irq(irq_nr); +} + +static void mask_and_ack_saturn_irq(unsigned int irq_nr) +{ + mask_saturn_irq(irq_nr); +} + +static void end_saturn_irq(unsigned int irq_nr) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + unmask_saturn_irq(irq_nr); +} + +static unsigned int startup_saturn_irq(unsigned int irq_nr) +{ + unmask_saturn_irq(irq_nr); + + return 0; +} + +static void shutdown_saturn_irq(unsigned int irq_nr) +{ + mask_saturn_irq(irq_nr); +} + +static struct hw_interrupt_type saturn_int = { + typename: "Saturn", + enable: enable_saturn_irq, + disable: disable_saturn_irq, + ack: mask_and_ack_saturn_irq, + end: end_saturn_irq, + startup: startup_saturn_irq, + shutdown: shutdown_saturn_irq, +}; + +int saturn_irq_demux(int irq_nr) +{ + /* FIXME */ + return irq_nr; +} + diff -urN linux-2.5.70-bk19/arch/sh/boards/saturn/mach.c linux-2.5.71/arch/sh/boards/saturn/mach.c --- linux-2.5.70-bk19/arch/sh/boards/saturn/mach.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/saturn/mach.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,61 @@ +/* + * arch/sh/boards/saturn/mach.c + * + * machvec definitions for the Sega Saturn. + * + * Copyright (C) 2002 Paul Mundt + * + * Released under the terms of the GNU GPL v2.0. + */ +#include +#include +#include +#include +#include +#include + +/* + * The Machine Vector + */ +struct sh_machine_vector mv_saturn __initmv = { + mv_nr_irqs: 80, /* Fix this later */ + + mv_inb: generic_inb, + mv_inw: generic_inw, + mv_inl: generic_inl, + mv_outb: generic_outb, + mv_outw: generic_outw, + mv_outl: generic_outl, + + mv_inb_p: generic_inb_p, + mv_inw_p: generic_inw_p, + mv_inl_p: generic_inl_p, + mv_outb_p: generic_outb_p, + mv_outw_p: generic_outw_p, + mv_outl_p: generic_outl_p, + + mv_insb: generic_insb, + mv_insw: generic_insw, + mv_insl: generic_insl, + mv_outsb: generic_outsb, + mv_outsw: generic_outsw, + mv_outsl: generic_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_isa_port2addr: saturn_isa_port2addr, + mv_irq_demux: saturn_irq_demux, + + mv_ioremap: saturn_ioremap, + mv_iounmap: saturn_iounmap, + + mv_hw_saturn: 1, +}; + +ALIAS_MV(saturn) + diff -urN linux-2.5.70-bk19/arch/sh/boards/saturn/setup.c linux-2.5.71/arch/sh/boards/saturn/setup.c --- linux-2.5.70-bk19/arch/sh/boards/saturn/setup.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/saturn/setup.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,22 @@ +/* + * arch/sh/boards/saturn/setup.c + * + * Hardware support for the Sega Saturn. + * + * Copyright (c) 2002 Paul Mundt + * + * Released under the terms of the GNU GPL v2.0. + */ +#include +#include + +const char *get_system_type(void) +{ + return "Sega Saturn"; +} + +int __init platform_setup(void) +{ + return 0; +} + diff -urN linux-2.5.70-bk19/arch/sh/boards/saturn/smp.c linux-2.5.71/arch/sh/boards/saturn/smp.c --- linux-2.5.70-bk19/arch/sh/boards/saturn/smp.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/saturn/smp.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,68 @@ +/* + * arch/sh/boards/saturn/smp.c + * + * SMP support for the Sega Saturn. + * + * Copyright (c) 2002 Paul Mundt + * + * Released under the terms of the GNU GPL v2.0. + */ +#include +#include +#include + +#include + +extern void start_secondary(void); + +void __smp_send_ipi(unsigned int cpu, unsigned int action) +{ + /* Nothing here yet .. */ +} + +unsigned int __smp_probe_cpus(void) +{ + /* + * This is just a straightforward master/slave configuration, + * and probing isn't really supported.. + */ + return 2; +} + +/* + * We're only allowed to do byte-access to SMPC registers. In + * addition to which, we treat them as write-only, since + * reading from them will return undefined data. + */ +static inline void smpc_slave_off(unsigned int cpu) +{ + smpc_barrier(); + ctrl_outb(1, SMPC_STATUS); + + ctrl_outb(SMPC_CMD_SSHOFF, SMPC_COMMAND); + smpc_barrier(); +} + +static inline void smpc_slave_on(unsigned int cpu) +{ + ctrl_outb(1, SMPC_STATUS); + ctrl_outb(SMPC_CMD_SSHON, SMPC_COMMAND); + + smpc_barrier(); +} + +void __smp_slave_init(unsigned int cpu) +{ + register unsigned long vbr; + void **entry; + + __asm__ __volatile__ ("stc vbr, %0\n\t" : "=r" (vbr)); + entry = (void **)(vbr + 0x310 + 0x94); + + smpc_slave_stop(cpu); + + *(void **)entry = (void *)start_secondary; + + smpc_slave_start(cpu); +} + diff -urN linux-2.5.70-bk19/arch/sh/boards/se/770x/Makefile linux-2.5.71/arch/sh/boards/se/770x/Makefile --- linux-2.5.70-bk19/arch/sh/boards/se/770x/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/se/770x/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,10 @@ +# +# Makefile for the 770x SolutionEngine specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := mach.o setup.o io.o irq.o led.o + diff -urN linux-2.5.70-bk19/arch/sh/boards/se/770x/io.c linux-2.5.71/arch/sh/boards/se/770x/io.c --- linux-2.5.70-bk19/arch/sh/boards/se/770x/io.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/se/770x/io.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,252 @@ +/* $Id: io.c,v 1.1.2.2 2002/01/20 05:03:25 mrbrown Exp $ + * + * linux/arch/sh/kernel/io_se.c + * + * Copyright (C) 2000 Kazumoto Kojima + * + * I/O routine for Hitachi SolutionEngine. + * + */ + +#include +#include +#include +#include + +/* SH pcmcia io window base, start and end. */ +int sh_pcic_io_wbase = 0xb8400000; +int sh_pcic_io_start; +int sh_pcic_io_stop; +int sh_pcic_io_type; +int sh_pcic_io_dummy; + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); +} + +/* MS7750 requires special versions of in*, out* routines, since + PC-like io ports are located at upper half byte of 16-bit word which + can be accessed only with 16-bit wide. */ + +static inline volatile __u16 * +port2adr(unsigned int port) +{ + if (port >= 0x2000) + return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000)); + else if (port >= 0x1000) + return (volatile __u16 *) (PA_83902 + (port << 1)); + else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) + return (volatile __u16 *) (sh_pcic_io_wbase + (port &~ 1)); + else + return (volatile __u16 *) (PA_SUPERIO + (port << 1)); +} + +static inline int +shifted_port(unsigned long port) +{ + /* For IDE registers, value is not shifted */ + if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6) + return 0; + else + return 1; +} + +#define maybebadio(name,port) \ + printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \ + #name, (port), (__u32) __builtin_return_address(0)) + +unsigned char se_inb(unsigned long port) +{ + if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) + return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); + else if (shifted_port(port)) + return (*port2adr(port) >> 8); + else + return (*port2adr(port))&0xff; +} + +unsigned char se_inb_p(unsigned long port) +{ + unsigned long v; + + if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) + v = *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); + else if (shifted_port(port)) + v = (*port2adr(port) >> 8); + else + v = (*port2adr(port))&0xff; + delay(); + return v; +} + +unsigned short se_inw(unsigned long port) +{ + if (port >= 0x2000 || + (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)) + return *port2adr(port); + else + maybebadio(inw, port); + return 0; +} + +unsigned int se_inl(unsigned long port) +{ + maybebadio(inl, port); + return 0; +} + +void se_outb(unsigned char value, unsigned long port) +{ + if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) + *(__u8 *)(sh_pcic_io_wbase + port) = value; + else if (shifted_port(port)) + *(port2adr(port)) = value << 8; + else + *(port2adr(port)) = value; +} + +void se_outb_p(unsigned char value, unsigned long port) +{ + if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) + *(__u8 *)(sh_pcic_io_wbase + port) = value; + else if (shifted_port(port)) + *(port2adr(port)) = value << 8; + else + *(port2adr(port)) = value; + delay(); +} + +void se_outw(unsigned short value, unsigned long port) +{ + if (port >= 0x2000 || + (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)) + *port2adr(port) = value; + else + maybebadio(outw, port); +} + +void se_outl(unsigned int value, unsigned long port) +{ + maybebadio(outl, port); +} + +void se_insb(unsigned long port, void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + + if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) { + volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port); + while (count--) + *((__u8 *) addr)++ = *bp; + } else if (shifted_port(port)) { + while (count--) + *((__u8 *) addr)++ = *p >> 8; + } else { + while (count--) + *((__u8 *) addr)++ = *p; + } +} + +void se_insw(unsigned long port, void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + while (count--) + *((__u16 *) addr)++ = *p; +} + +void se_insl(unsigned long port, void *addr, unsigned long count) +{ + maybebadio(insl, port); +} + +void se_outsb(unsigned long port, const void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + + if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) { + volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + port); + while (count--) + *bp = *((__u8 *) addr)++; + } else if (shifted_port(port)) { + while (count--) + *p = *((__u8 *) addr)++ << 8; + } else { + while (count--) + *p = *((__u8 *) addr)++; + } +} + +void se_outsw(unsigned long port, const void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + while (count--) + *p = *((__u16 *) addr)++; +} + +void se_outsl(unsigned long port, const void *addr, unsigned long count) +{ + maybebadio(outsw, port); +} + +unsigned char se_readb(unsigned long addr) +{ + return *(volatile unsigned char*)addr; +} + +unsigned short se_readw(unsigned long addr) +{ + return *(volatile unsigned short*)addr; +} + +unsigned int se_readl(unsigned long addr) +{ + return *(volatile unsigned long*)addr; +} + +void se_writeb(unsigned char b, unsigned long addr) +{ + *(volatile unsigned char*)addr = b; +} + +void se_writew(unsigned short b, unsigned long addr) +{ + *(volatile unsigned short*)addr = b; +} + +void se_writel(unsigned int b, unsigned long addr) +{ + *(volatile unsigned long*)addr = b; +} + +/* Map ISA bus address to the real address. Only for PCMCIA. */ + +/* ISA page descriptor. */ +static __u32 sh_isa_memmap[256]; + +static int +sh_isa_mmap(__u32 start, __u32 length, __u32 offset) +{ + int idx; + + if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000)) + return -1; + + idx = start >> 12; + sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff); +#if 0 + printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n", + start, length, offset, idx, sh_isa_memmap[idx]); +#endif + return 0; +} + +unsigned long +se_isa_port2addr(unsigned long offset) +{ + int idx; + + idx = (offset >> 12) & 0xff; + offset &= 0xfff; + return sh_isa_memmap[idx] + offset; +} diff -urN linux-2.5.70-bk19/arch/sh/boards/se/770x/irq.c linux-2.5.71/arch/sh/boards/se/770x/irq.c --- linux-2.5.70-bk19/arch/sh/boards/se/770x/irq.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/se/770x/irq.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,53 @@ +/* $Id: irq.c,v 1.1.2.2 2002/10/29 00:56:09 lethal Exp $ + * + * linux/arch/sh/boards/se/770x/irq.c + * + * Copyright (C) 2000 Kazumoto Kojima + * + * Hitachi SolutionEngine Support. + * + */ + +#include +#include +#include +#include +#include + +/* + * Initialize IRQ setting + */ +void __init init_se_IRQ(void) +{ + /* + * Super I/O (Just mimic PC): + * 1: keyboard + * 3: serial 0 + * 4: serial 1 + * 5: printer + * 6: floppy + * 8: rtc + * 12: mouse + * 14: ide0 + */ + make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-14); + make_ipr_irq(12, BCR_ILCRA, 1, 0x0f-12); + make_ipr_irq( 8, BCR_ILCRB, 1, 0x0f- 8); + make_ipr_irq( 6, BCR_ILCRC, 3, 0x0f- 6); + make_ipr_irq( 5, BCR_ILCRC, 2, 0x0f- 5); + make_ipr_irq( 4, BCR_ILCRC, 1, 0x0f- 4); + make_ipr_irq( 3, BCR_ILCRC, 0, 0x0f- 3); + make_ipr_irq( 1, BCR_ILCRD, 3, 0x0f- 1); + + make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */ + + make_ipr_irq( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */ + make_ipr_irq(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */ + make_ipr_irq( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */ + make_ipr_irq( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */ + + /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */ + /* NOTE: #2 and #13 are not used on PC */ + make_ipr_irq(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */ + make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */ +} diff -urN linux-2.5.70-bk19/arch/sh/boards/se/770x/led.c linux-2.5.71/arch/sh/boards/se/770x/led.c --- linux-2.5.70-bk19/arch/sh/boards/se/770x/led.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/se/770x/led.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,68 @@ +/* + * linux/arch/sh/kernel/led_se.c + * + * Copyright (C) 2000 Stuart Menefy + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file contains Solution Engine specific LED code. + */ + +#include +#include + +static void mach_led(int position, int value) +{ + volatile unsigned short* p = (volatile unsigned short*)PA_LED; + + if (value) { + *p |= (1<<8); + } else { + *p &= ~(1<<8); + } +} + +#ifdef CONFIG_HEARTBEAT + +#include + +/* Cycle the LED's in the clasic Knightrider/Sun pattern */ +void heartbeat_se(void) +{ + static unsigned int cnt = 0, period = 0; + volatile unsigned short* p = (volatile unsigned short*)PA_LED; + static unsigned bit = 0, up = 1; + + cnt += 1; + if (cnt < period) { + return; + } + + cnt = 0; + + /* Go through the points (roughly!): + * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110 + */ + period = 110 - ( (300< +#include + +#include +#include +#include + +#include + +void heartbeat_se(void); +void setup_se(void); +void init_se_IRQ(void); + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_se __initmv = { +#if defined(CONFIG_CPU_SH4) + mv_nr_irqs: 48, +#elif defined(CONFIG_CPU_SUBTYPE_SH7708) + mv_nr_irqs: 32, +#elif defined(CONFIG_CPU_SUBTYPE_SH7709) + mv_nr_irqs: 61, +#endif + + mv_inb: se_inb, + mv_inw: se_inw, + mv_inl: se_inl, + mv_outb: se_outb, + mv_outw: se_outw, + mv_outl: se_outl, + + mv_inb_p: se_inb_p, + mv_inw_p: se_inw, + mv_inl_p: se_inl, + mv_outb_p: se_outb_p, + mv_outw_p: se_outw, + mv_outl_p: se_outl, + + mv_insb: se_insb, + mv_insw: se_insw, + mv_insl: se_insl, + mv_outsb: se_outsb, + mv_outsw: se_outsw, + mv_outsl: se_outsl, + + mv_readb: se_readb, + mv_readw: se_readw, + mv_readl: se_readl, + mv_writeb: se_writeb, + mv_writew: se_writew, + mv_writel: se_writel, + + mv_ioremap: generic_ioremap, + mv_iounmap: generic_iounmap, + + mv_isa_port2addr: se_isa_port2addr, + + mv_init_irq: init_se_IRQ, +#ifdef CONFIG_HEARTBEAT + mv_heartbeat: heartbeat_se, +#endif + mv_hw_se: 1, +}; +ALIAS_MV(se) diff -urN linux-2.5.70-bk19/arch/sh/boards/se/770x/setup.c linux-2.5.71/arch/sh/boards/se/770x/setup.c --- linux-2.5.70-bk19/arch/sh/boards/se/770x/setup.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/se/770x/setup.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,85 @@ +/* $Id: setup.c,v 1.1.2.4 2002/03/02 21:57:07 lethal Exp $ + * + * linux/arch/sh/boards/se/770x/setup.c + * + * Copyright (C) 2000 Kazumoto Kojima + * + * Hitachi SolutionEngine Support. + * + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * Configure the Super I/O chip + */ +static void __init smsc_config(int index, int data) +{ + outb_p(index, INDEX_PORT); + outb_p(data, DATA_PORT); +} + +static void __init init_smsc(void) +{ + outb_p(CONFIG_ENTER, CONFIG_PORT); + outb_p(CONFIG_ENTER, CONFIG_PORT); + + /* FDC */ + smsc_config(CURRENT_LDN_INDEX, LDN_FDC); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */ + + /* IDE1 */ + smsc_config(CURRENT_LDN_INDEX, LDN_IDE1); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */ + + /* AUXIO (GPIO): to use IDE1 */ + smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO); + smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */ + smsc_config(GPIO47_INDEX, 0x00); /* nIOWOP */ + + /* COM1 */ + smsc_config(CURRENT_LDN_INDEX, LDN_COM1); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IO_BASE_HI_INDEX, 0x03); + smsc_config(IO_BASE_LO_INDEX, 0xf8); + smsc_config(IRQ_SELECT_INDEX, 4); /* IRQ4 */ + + /* COM2 */ + smsc_config(CURRENT_LDN_INDEX, LDN_COM2); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IO_BASE_HI_INDEX, 0x02); + smsc_config(IO_BASE_LO_INDEX, 0xf8); + smsc_config(IRQ_SELECT_INDEX, 3); /* IRQ3 */ + + /* RTC */ + smsc_config(CURRENT_LDN_INDEX, LDN_RTC); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */ + + /* XXX: PARPORT, KBD, and MOUSE will come here... */ + outb_p(CONFIG_EXIT, CONFIG_PORT); +} + +const char *get_system_type(void) +{ + return "SolutionEngine"; +} + +/* + * Initialize the board + */ +void __init platform_setup(void) +{ + init_smsc(); + /* XXX: RTC setting comes here */ +} diff -urN linux-2.5.70-bk19/arch/sh/boards/se/7751/Makefile linux-2.5.71/arch/sh/boards/se/7751/Makefile --- linux-2.5.70-bk19/arch/sh/boards/se/7751/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/se/7751/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,12 @@ +# +# Makefile for the 7751 SolutionEngine specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := mach.o setup.o io.o irq.o led.o + +obj-$(CONFIG_PCI) += pci.o + diff -urN linux-2.5.70-bk19/arch/sh/boards/se/7751/io.c linux-2.5.71/arch/sh/boards/se/7751/io.c --- linux-2.5.70-bk19/arch/sh/boards/se/7751/io.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/se/7751/io.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,304 @@ +/* + * linux/arch/sh/kernel/io_7751se.c + * + * Copyright (C) 2001 Ian da Silva, Jeremy Siegel + * Based largely on io_se.c. + * + * I/O routine for Hitachi 7751 SolutionEngine. + * + * Initial version only to support LAN access; some + * placeholder code from io_se.c left in with the + * expectation of later SuperIO and PCMCIA access. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#if 0 +/****************************************************************** + * Variables from io_se.c, related to PCMCIA (not PCI); we're not + * compiling them in, and have removed references from functions + * which follow. [Many checked for IO ports in the range bounded + * by sh_pcic_io_start/stop, and used sh_pcic_io_wbase as offset. + * As start/stop are uninitialized, only port 0x0 would match?] + * When used, remember to adjust names to avoid clash with io_se? + *****************************************************************/ +/* SH pcmcia io window base, start and end. */ +int sh_pcic_io_wbase = 0xb8400000; +int sh_pcic_io_start; +int sh_pcic_io_stop; +int sh_pcic_io_type; +int sh_pcic_io_dummy; +/*************************************************************/ +#endif + +/* + * The 7751 Solution Engine uses the built-in PCI controller (PCIC) + * of the 7751 processor, and has a SuperIO accessible via the PCI. + * The board also includes a PCMCIA controller on its memory bus, + * like the other Solution Engine boards. + */ + +#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR) +#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR) +#define PCI_IO_AREA SH7751_PCI_IO_BASE +#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE + +#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK)) + +#define maybebadio(name,port) \ + printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \ + #name, (port), (__u32) __builtin_return_address(0)) + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); +} + +static inline volatile __u16 * +port2adr(unsigned int port) +{ + if (port >= 0x2000) + return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000)); +#if 0 + else + return (volatile __u16 *) (PA_SUPERIO + (port << 1)); +#endif + maybebadio(name,(unsigned long)port); + return (volatile __u16*)port; +} + +#if 0 +/* The 7751 Solution Engine seems to have everything hooked */ +/* up pretty normally (nothing on high-bytes only...) so this */ +/* shouldn't be needed */ +static inline int +shifted_port(unsigned long port) +{ + /* For IDE registers, value is not shifted */ + if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6) + return 0; + else + return 1; +} +#endif + +/* In case someone configures the kernel w/o PCI support: in that */ +/* scenario, don't ever bother to check for PCI-window addresses */ + +/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */ +#if defined(CONFIG_PCI) +#define CHECK_SH7751_PCIIO(port) \ + ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE))) +#else +#define CHECK_SH7751_PCIIO(port) (0) +#endif + +/* + * General outline: remap really low stuff [eventually] to SuperIO, + * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO) + * is mapped through the PCI IO window. Stuff with high bits (PXSEG) + * should be way beyond the window, and is used w/o translation for + * compatibility. + */ +unsigned char sh7751se_inb(unsigned long port) +{ + if (PXSEG(port)) + return *(volatile unsigned char *)port; + else if (CHECK_SH7751_PCIIO(port)) + return *(volatile unsigned char *)PCI_IOMAP(port); + else + return (*port2adr(port))&0xff; +} + +unsigned char sh7751se_inb_p(unsigned long port) +{ + unsigned char v; + + if (PXSEG(port)) + v = *(volatile unsigned char *)port; + else if (CHECK_SH7751_PCIIO(port)) + v = *(volatile unsigned char *)PCI_IOMAP(port); + else + v = (*port2adr(port))&0xff; + delay(); + return v; +} + +unsigned short sh7751se_inw(unsigned long port) +{ + if (PXSEG(port)) + return *(volatile unsigned short *)port; + else if (CHECK_SH7751_PCIIO(port)) + return *(volatile unsigned short *)PCI_IOMAP(port); + else if (port >= 0x2000) + return *port2adr(port); + else + maybebadio(inw, port); + return 0; +} + +unsigned int sh7751se_inl(unsigned long port) +{ + if (PXSEG(port)) + return *(volatile unsigned long *)port; + else if (CHECK_SH7751_PCIIO(port)) + return *(volatile unsigned int *)PCI_IOMAP(port); + else if (port >= 0x2000) + return *port2adr(port); + else + maybebadio(inl, port); + return 0; +} + +void sh7751se_outb(unsigned char value, unsigned long port) +{ + + if (PXSEG(port)) + *(volatile unsigned char *)port = value; + else if (CHECK_SH7751_PCIIO(port)) + *((unsigned char*)PCI_IOMAP(port)) = value; + else + *(port2adr(port)) = value; +} + +void sh7751se_outb_p(unsigned char value, unsigned long port) +{ + if (PXSEG(port)) + *(volatile unsigned char *)port = value; + else if (CHECK_SH7751_PCIIO(port)) + *((unsigned char*)PCI_IOMAP(port)) = value; + else + *(port2adr(port)) = value; + delay(); +} + +void sh7751se_outw(unsigned short value, unsigned long port) +{ + if (PXSEG(port)) + *(volatile unsigned short *)port = value; + else if (CHECK_SH7751_PCIIO(port)) + *((unsigned short *)PCI_IOMAP(port)) = value; + else if (port >= 0x2000) + *port2adr(port) = value; + else + maybebadio(outw, port); +} + +void sh7751se_outl(unsigned int value, unsigned long port) +{ + if (PXSEG(port)) + *(volatile unsigned long *)port = value; + else if (CHECK_SH7751_PCIIO(port)) + *((unsigned long*)PCI_IOMAP(port)) = value; + else + maybebadio(outl, port); +} + +void sh7751se_insb(unsigned long port, void *addr, unsigned long count) +{ + unsigned char *p = addr; + while (count--) *p++ = sh7751se_inb(port); +} + +void sh7751se_insw(unsigned long port, void *addr, unsigned long count) +{ + unsigned short *p = addr; + while (count--) *p++ = sh7751se_inw(port); +} + +void sh7751se_insl(unsigned long port, void *addr, unsigned long count) +{ + maybebadio(insl, port); +} + +void sh7751se_outsb(unsigned long port, const void *addr, unsigned long count) +{ + unsigned char *p = (unsigned char*)addr; + while (count--) sh7751se_outb(*p++, port); +} + +void sh7751se_outsw(unsigned long port, const void *addr, unsigned long count) +{ + unsigned short *p = (unsigned short*)addr; + while (count--) sh7751se_outw(*p++, port); +} + +void sh7751se_outsl(unsigned long port, const void *addr, unsigned long count) +{ + maybebadio(outsw, port); +} + +/* For read/write calls, just copy generic (pass-thru); PCIMBR is */ +/* already set up. For a larger memory space, these would need to */ +/* reset PCIMBR as needed on a per-call basis... */ + +unsigned char sh7751se_readb(unsigned long addr) +{ + return *(volatile unsigned char*)addr; +} + +unsigned short sh7751se_readw(unsigned long addr) +{ + return *(volatile unsigned short*)addr; +} + +unsigned int sh7751se_readl(unsigned long addr) +{ + return *(volatile unsigned long*)addr; +} + +void sh7751se_writeb(unsigned char b, unsigned long addr) +{ + *(volatile unsigned char*)addr = b; +} + +void sh7751se_writew(unsigned short b, unsigned long addr) +{ + *(volatile unsigned short*)addr = b; +} + +void sh7751se_writel(unsigned int b, unsigned long addr) +{ + *(volatile unsigned long*)addr = b; +} + + + +/* Map ISA bus address to the real address. Only for PCMCIA. */ + +/* ISA page descriptor. */ +static __u32 sh_isa_memmap[256]; + +#if 0 +static int +sh_isa_mmap(__u32 start, __u32 length, __u32 offset) +{ + int idx; + + if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000)) + return -1; + + idx = start >> 12; + sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff); + printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n", + start, length, offset, idx, sh_isa_memmap[idx]); + return 0; +} +#endif + +unsigned long +sh7751se_isa_port2addr(unsigned long offset) +{ + int idx; + + idx = (offset >> 12) & 0xff; + offset &= 0xfff; + return sh_isa_memmap[idx] + offset; +} diff -urN linux-2.5.70-bk19/arch/sh/boards/se/7751/irq.c linux-2.5.71/arch/sh/boards/se/7751/irq.c --- linux-2.5.70-bk19/arch/sh/boards/se/7751/irq.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/se/7751/irq.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,67 @@ +/* + * linux/arch/sh/boards/se/7751/irq.c + * + * Copyright (C) 2000 Kazumoto Kojima + * + * Hitachi SolutionEngine Support. + * + * Modified for 7751 Solution Engine by + * Ian da Silva and Jeremy Siegel, 2001. + */ + +#include +#include +#include +#include +#include + +/* + * Initialize IRQ setting + */ +void __init init_7751se_IRQ(void) +{ + + /* Leave old Solution Engine code in for reference. */ +#if defined(CONFIG_SH_SOLUTION_ENGINE) + /* + * Super I/O (Just mimic PC): + * 1: keyboard + * 3: serial 0 + * 4: serial 1 + * 5: printer + * 6: floppy + * 8: rtc + * 12: mouse + * 14: ide0 + */ + make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-14); + make_ipr_irq(12, BCR_ILCRA, 1, 0x0f-12); + make_ipr_irq( 8, BCR_ILCRB, 1, 0x0f- 8); + make_ipr_irq( 6, BCR_ILCRC, 3, 0x0f- 6); + make_ipr_irq( 5, BCR_ILCRC, 2, 0x0f- 5); + make_ipr_irq( 4, BCR_ILCRC, 1, 0x0f- 4); + make_ipr_irq( 3, BCR_ILCRC, 0, 0x0f- 3); + make_ipr_irq( 1, BCR_ILCRD, 3, 0x0f- 1); + + make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */ + + make_ipr_irq( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */ + make_ipr_irq(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */ + make_ipr_irq( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */ + make_ipr_irq( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */ + + /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */ + /* NOTE: #2 and #13 are not used on PC */ + make_ipr_irq(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */ + make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */ + +#elif defined(CONFIG_SH_7751_SOLUTION_ENGINE) + + make_ipr_irq(13, BCR_ILCRD, 3, 2); + + /* Add additional calls to make_ipr_irq() as drivers are added + * and tested. + */ +#endif + +} diff -urN linux-2.5.70-bk19/arch/sh/boards/se/7751/led.c linux-2.5.71/arch/sh/boards/se/7751/led.c --- linux-2.5.70-bk19/arch/sh/boards/se/7751/led.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/se/7751/led.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,68 @@ +/* + * linux/arch/sh/kernel/led_se.c + * + * Copyright (C) 2000 Stuart Menefy + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * This file contains Solution Engine specific LED code. + */ + +#include +#include + +static void mach_led(int position, int value) +{ + volatile unsigned short* p = (volatile unsigned short*)PA_LED; + + if (value) { + *p |= (1<<8); + } else { + *p &= ~(1<<8); + } +} + +#ifdef CONFIG_HEARTBEAT + +#include + +/* Cycle the LED's in the clasic Knightrider/Sun pattern */ +void heartbeat_7751se(void) +{ + static unsigned int cnt = 0, period = 0; + volatile unsigned short* p = (volatile unsigned short*)PA_LED; + static unsigned bit = 0, up = 1; + + cnt += 1; + if (cnt < period) { + return; + } + + cnt = 0; + + /* Go through the points (roughly!): + * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110 + */ + period = 110 - ( (300< +#include + +#include +#include +#include + +#include + +void heartbeat_7751se(void); +void init_7751se_IRQ(void); + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_7751se __initmv = { + mv_nr_irqs: 72, + + mv_inb: sh7751se_inb, + mv_inw: sh7751se_inw, + mv_inl: sh7751se_inl, + mv_outb: sh7751se_outb, + mv_outw: sh7751se_outw, + mv_outl: sh7751se_outl, + + mv_inb_p: sh7751se_inb_p, + mv_inw_p: sh7751se_inw, + mv_inl_p: sh7751se_inl, + mv_outb_p: sh7751se_outb_p, + mv_outw_p: sh7751se_outw, + mv_outl_p: sh7751se_outl, + + mv_insb: sh7751se_insb, + mv_insw: sh7751se_insw, + mv_insl: sh7751se_insl, + mv_outsb: sh7751se_outsb, + mv_outsw: sh7751se_outsw, + mv_outsl: sh7751se_outsl, + + mv_readb: sh7751se_readb, + mv_readw: sh7751se_readw, + mv_readl: sh7751se_readl, + mv_writeb: sh7751se_writeb, + mv_writew: sh7751se_writew, + mv_writel: sh7751se_writel, + + mv_ioremap: generic_ioremap, + mv_iounmap: generic_iounmap, + + mv_isa_port2addr: sh7751se_isa_port2addr, + + mv_init_irq: init_7751se_IRQ, +#ifdef CONFIG_HEARTBEAT + mv_heartbeat: heartbeat_7751se, +#endif + mv_hw_7751se: 1, +}; +ALIAS_MV(7751se) diff -urN linux-2.5.70-bk19/arch/sh/boards/se/7751/pci.c linux-2.5.71/arch/sh/boards/se/7751/pci.c --- linux-2.5.70-bk19/arch/sh/boards/se/7751/pci.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/se/7751/pci.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,127 @@ +/* + * linux/arch/sh/kernel/pci-7751se.c + * + * Author: Ian DaSilva (idasilva@mvista.com) + * + * Highly leveraged from pci-bigsur.c, written by Dustin McIntire. + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * PCI initialization for the Hitachi SH7751 Solution Engine board (MS7751SE01) + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define PCIMCR_MRSET_OFF 0xBFFFFFFF +#define PCIMCR_RFSH_OFF 0xFFFFFFFB + +/* + * Only long word accesses of the PCIC's internal local registers and the + * configuration registers from the CPU is supported. + */ +#define PCIC_WRITE(x,v) writel((v), PCI_REG(x)) +#define PCIC_READ(x) readl(PCI_REG(x)) + +/* + * Description: This function sets up and initializes the pcic, sets + * up the BARS, maps the DRAM into the address space etc, etc. + */ +int __init pcibios_init_platform(void) +{ + unsigned long bcr1, wcr1, wcr2, wcr3, mcr; + unsigned short bcr2; + + /* + * Initialize the slave bus controller on the pcic. The values used + * here should not be hardcoded, but they should be taken from the bsc + * on the processor, to make this function as generic as possible. + * (i.e. Another sbc may usr different SDRAM timing settings -- in order + * for the pcic to work, its settings need to be exactly the same.) + */ + bcr1 = (*(volatile unsigned long*)(SH7751_BCR1)); + bcr2 = (*(volatile unsigned short*)(SH7751_BCR2)); + wcr1 = (*(volatile unsigned long*)(SH7751_WCR1)); + wcr2 = (*(volatile unsigned long*)(SH7751_WCR2)); + wcr3 = (*(volatile unsigned long*)(SH7751_WCR3)); + mcr = (*(volatile unsigned long*)(SH7751_MCR)); + + bcr1 = bcr1 | 0x00080000; /* Enable Bit 19, BREQEN */ + (*(volatile unsigned long*)(SH7751_BCR1)) = bcr1; + + bcr1 = bcr1 | 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */ + PCIC_WRITE(SH7751_PCIBCR1, bcr1); /* PCIC BCR1 */ + PCIC_WRITE(SH7751_PCIBCR2, bcr2); /* PCIC BCR2 */ + PCIC_WRITE(SH7751_PCIWCR1, wcr1); /* PCIC WCR1 */ + PCIC_WRITE(SH7751_PCIWCR2, wcr2); /* PCIC WCR2 */ + PCIC_WRITE(SH7751_PCIWCR3, wcr3); /* PCIC WCR3 */ + mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF; + PCIC_WRITE(SH7751_PCIMCR, mcr); /* PCIC MCR */ + + + /* Enable all interrupts, so we know what to fix */ + PCIC_WRITE(SH7751_PCIINTM, 0x0000c3ff); + PCIC_WRITE(SH7751_PCIAINTM, 0x0000380f); + + /* Set up standard PCI config registers */ + PCIC_WRITE(SH7751_PCICONF1, 0xF39000C7); /* Bus Master, Mem & I/O access */ + PCIC_WRITE(SH7751_PCICONF2, 0x00000000); /* PCI Class code & Revision ID */ + PCIC_WRITE(SH7751_PCICONF4, 0xab000001); /* PCI I/O address (local regs) */ + PCIC_WRITE(SH7751_PCICONF5, 0x0c000000); /* PCI MEM address (local RAM) */ + PCIC_WRITE(SH7751_PCICONF6, 0xd0000000); /* PCI MEM address (unused) */ + PCIC_WRITE(SH7751_PCICONF11, 0x35051054); /* PCI Subsystem ID & Vendor ID */ + PCIC_WRITE(SH7751_PCILSR0, 0x03f00000); /* MEM (full 64M exposed) */ + PCIC_WRITE(SH7751_PCILSR1, 0x00000000); /* MEM (unused) */ + PCIC_WRITE(SH7751_PCILAR0, 0x0c000000); /* MEM (direct map from PCI) */ + PCIC_WRITE(SH7751_PCILAR1, 0x00000000); /* MEM (unused) */ + + /* Now turn it on... */ + PCIC_WRITE(SH7751_PCICR, 0xa5000001); + + /* + * Set PCIMBR and PCIIOBR here, assuming a single window + * (16M MEM, 256K IO) is enough. If a larger space is + * needed, the readx/writex and inx/outx functions will + * have to do more (e.g. setting registers for each call). + */ + + /* + * Set the MBR so PCI address is one-to-one with window, + * meaning all calls go straight through... use ifdef to + * catch erroneous assumption. + */ +#if PCIBIOS_MIN_MEM != SH7751_PCI_MEMORY_BASE +#error One-to-one assumption for PCI memory mapping is wrong!?!?!? +#endif + PCIC_WRITE(SH7751_PCIMBR, PCIBIOS_MIN_MEM); + + /* Set IOBR for window containing area specified in pci.h */ + PCIC_WRITE(SH7751_PCIIOBR, (PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK)); + + /* All done, may as well say so... */ + printk("SH7751 PCI: Finished initialization of the PCI controller\n"); + + return 1; +} + +int __init pcibios_map_platform_irq(u8 slot, u8 pin) +{ + switch (slot) { + case 0: return 13; + case 1: return 13; /* AMD Ethernet controller */ + case 2: return -1; + case 3: return -1; + case 4: return -1; + default: + printk("PCI: Bad IRQ mapping request for slot %d\n", slot); + return -1; + } +} diff -urN linux-2.5.70-bk19/arch/sh/boards/se/7751/setup.c linux-2.5.71/arch/sh/boards/se/7751/setup.c --- linux-2.5.70-bk19/arch/sh/boards/se/7751/setup.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/se/7751/setup.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,228 @@ +/* + * linux/arch/sh/kernel/setup_7751se.c + * + * Copyright (C) 2000 Kazumoto Kojima + * + * Hitachi SolutionEngine Support. + * + * Modified for 7751 Solution Engine by + * Ian da Silva and Jeremy Siegel, 2001. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_SH_KGDB +#include +#endif + +/* + * Configure the Super I/O chip + */ +#if 0 +/* Leftover code from regular Solution Engine, for reference. */ +/* The SH7751 Solution Engine has a different SuperIO. */ +static void __init smsc_config(int index, int data) +{ + outb_p(index, INDEX_PORT); + outb_p(data, DATA_PORT); +} + +static void __init init_smsc(void) +{ + outb_p(CONFIG_ENTER, CONFIG_PORT); + outb_p(CONFIG_ENTER, CONFIG_PORT); + + /* FDC */ + smsc_config(CURRENT_LDN_INDEX, LDN_FDC); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */ + + /* IDE1 */ + smsc_config(CURRENT_LDN_INDEX, LDN_IDE1); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */ + + /* AUXIO (GPIO): to use IDE1 */ + smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO); + smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */ + smsc_config(GPIO47_INDEX, 0x00); /* nIOWOP */ + + /* COM1 */ + smsc_config(CURRENT_LDN_INDEX, LDN_COM1); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IO_BASE_HI_INDEX, 0x03); + smsc_config(IO_BASE_LO_INDEX, 0xf8); + smsc_config(IRQ_SELECT_INDEX, 4); /* IRQ4 */ + + /* COM2 */ + smsc_config(CURRENT_LDN_INDEX, LDN_COM2); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IO_BASE_HI_INDEX, 0x02); + smsc_config(IO_BASE_LO_INDEX, 0xf8); + smsc_config(IRQ_SELECT_INDEX, 3); /* IRQ3 */ + + /* RTC */ + smsc_config(CURRENT_LDN_INDEX, LDN_RTC); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */ + + /* XXX: PARPORT, KBD, and MOUSE will come here... */ + outb_p(CONFIG_EXIT, CONFIG_PORT); +} +#endif + +const char *get_system_type(void) +{ + return "7751 SolutionEngine"; +} + +#ifdef CONFIG_SH_KGDB +static int kgdb_uart_setup(void); +static struct kgdb_sermap kgdb_uart_sermap = +{ "ttyS", 0, kgdb_uart_setup, NULL }; +#endif + +/* + * Initialize the board + */ +void __init platform_setup(void) +{ + /* Call init_smsc() replacement to set up SuperIO. */ + /* XXX: RTC setting comes here */ +#ifdef CONFIG_SH_KGDB + kgdb_register_sermap(&kgdb_uart_sermap); +#endif +} + +/********************************************************************* + * Currently a hack (e.g. does not interact well w/serial.c, lots of * + * hardcoded stuff) but may be useful if SCI/F needs debugging. * + * Mostly copied from x86 code (see files asm-i386/kgdb_local.h and * + * arch/i386/lib/kgdb_serial.c). * + *********************************************************************/ + +#ifdef CONFIG_SH_KGDB +#include +#include +#include +#include + +#define COM1_PORT 0x3f8 /* Base I/O address */ +#define COM1_IRQ 4 /* IRQ not used yet */ +#define COM2_PORT 0x2f8 /* Base I/O address */ +#define COM2_IRQ 3 /* IRQ not used yet */ + +#define SB_CLOCK 1843200 /* Serial baud clock */ +#define SB_BASE (SB_CLOCK/16) +#define SB_MCR UART_MCR_OUT2 | UART_MCR_DTR | UART_MCR_RTS + +struct uart_port { + int base; +}; +#define UART_NPORTS 2 +struct uart_port uart_ports[] = { + { COM1_PORT }, + { COM2_PORT }, +}; +struct uart_port *kgdb_uart_port; + +#define UART_IN(reg) inb_p(kgdb_uart_port->base + reg) +#define UART_OUT(reg,v) outb_p((v), kgdb_uart_port->base + reg) + +/* Basic read/write functions for the UART */ +#define UART_LSR_RXCERR (UART_LSR_BI | UART_LSR_FE | UART_LSR_PE) +static int kgdb_uart_getchar(void) +{ + int lsr; + int c = -1; + + while (c == -1) { + lsr = UART_IN(UART_LSR); + if (lsr & UART_LSR_DR) + c = UART_IN(UART_RX); + if ((lsr & UART_LSR_RXCERR)) + c = -1; + } + return c; +} + +static void kgdb_uart_putchar(int c) +{ + while ((UART_IN(UART_LSR) & UART_LSR_THRE) == 0) + ; + UART_OUT(UART_TX, c); +} + +/* + * Initialize UART to configured/requested values. + * (But we don't interrupts yet, or interact w/serial.c) + */ +static int kgdb_uart_setup(void) +{ + int port; + int lcr = 0; + int bdiv = 0; + + if (kgdb_portnum >= UART_NPORTS) { + KGDB_PRINTK("uart port %d invalid.\n", kgdb_portnum); + return -1; + } + + kgdb_uart_port = &uart_ports[kgdb_portnum]; + + /* Init sequence from gdb_hook_interrupt */ + UART_IN(UART_RX); + UART_OUT(UART_IER, 0); + + UART_IN(UART_RX); /* Serial driver comments say */ + UART_IN(UART_IIR); /* this clears interrupt regs */ + UART_IN(UART_MSR); + + /* Figure basic LCR values */ + switch (kgdb_bits) { + case '7': + lcr |= UART_LCR_WLEN7; + break; + default: case '8': + lcr |= UART_LCR_WLEN8; + break; + } + switch (kgdb_parity) { + case 'O': + lcr |= UART_LCR_PARITY; + break; + case 'E': + lcr |= (UART_LCR_PARITY | UART_LCR_EPAR); + break; + default: break; + } + + /* Figure the baud rate divisor */ + bdiv = (SB_BASE/kgdb_baud); + + /* Set the baud rate and LCR values */ + UART_OUT(UART_LCR, (lcr | UART_LCR_DLAB)); + UART_OUT(UART_DLL, (bdiv & 0xff)); + UART_OUT(UART_DLM, ((bdiv >> 8) & 0xff)); + UART_OUT(UART_LCR, lcr); + + /* Set the MCR */ + UART_OUT(UART_MCR, SB_MCR); + + /* Turn off FIFOs for now */ + UART_OUT(UART_FCR, 0); + + /* Setup complete: initialize function pointers */ + kgdb_getchar = kgdb_uart_getchar; + kgdb_putchar = kgdb_uart_putchar; + + return 0; +} +#endif /* CONFIG_SH_KGDB */ diff -urN linux-2.5.70-bk19/arch/sh/boards/sh2000/Makefile linux-2.5.71/arch/sh/boards/sh2000/Makefile --- linux-2.5.70-bk19/arch/sh/boards/sh2000/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/sh2000/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,10 @@ +# +# Makefile for the SH2000 specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := mach.o setup.o io.o + diff -urN linux-2.5.70-bk19/arch/sh/boards/sh2000/io.c linux-2.5.71/arch/sh/boards/sh2000/io.c --- linux-2.5.70-bk19/arch/sh/boards/sh2000/io.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/sh2000/io.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,19 @@ +/* + * I/O routine for SH-2000 + */ +#include +#include +#include + +#define IDE_OFFSET 0xb6200000 +#define NIC_OFFSET 0xb6000000 +#define EXTBUS_OFFSET 0xba000000 + +unsigned long sh2000_isa_port2addr(unsigned long offset) +{ + if((offset & ~7) == 0x1f0 || offset == 0x3f6) + return IDE_OFFSET + offset; + else if((offset & ~0x1f) == 0x300) + return NIC_OFFSET + offset; + return EXTBUS_OFFSET + offset; +} diff -urN linux-2.5.70-bk19/arch/sh/boards/sh2000/mach.c linux-2.5.71/arch/sh/boards/sh2000/mach.c --- linux-2.5.70-bk19/arch/sh/boards/sh2000/mach.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/sh2000/mach.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,59 @@ +/* + * linux/arch/sh/boards/sh2000/mach.c + * + * Original copyright message: + * Copyright (C) 2001 SUGIOKA Tochinobu + * + * Split into mach.c from setup.c by M. R. Brown + */ + +#include +#include +#include +#include +#include +#include + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_sh2000 __initmv = { + mv_nr_irqs: 80, + + mv_inb: generic_inb, + mv_inw: generic_inw, + mv_inl: generic_inl, + mv_outb: generic_outb, + mv_outw: generic_outw, + mv_outl: generic_outl, + + mv_inb_p: generic_inb_p, + mv_inw_p: generic_inw_p, + mv_inl_p: generic_inl_p, + mv_outb_p: generic_outb_p, + mv_outw_p: generic_outw_p, + mv_outl_p: generic_outl_p, + + mv_insb: generic_insb, + mv_insw: generic_insw, + mv_insl: generic_insl, + mv_outsb: generic_outsb, + mv_outsw: generic_outsw, + mv_outsl: generic_outsl, + + mv_readb: generic_readb, + mv_readw: generic_readw, + mv_readl: generic_readl, + mv_writeb: generic_writeb, + mv_writew: generic_writew, + mv_writel: generic_writel, + + mv_isa_port2addr: sh2000_isa_port2addr, + + mv_ioremap: generic_ioremap, + mv_iounmap: generic_iounmap, + + mv_hw_sh2000: 1, +}; +ALIAS_MV(sh2000) diff -urN linux-2.5.70-bk19/arch/sh/boards/sh2000/setup.c linux-2.5.71/arch/sh/boards/sh2000/setup.c --- linux-2.5.70-bk19/arch/sh/boards/sh2000/setup.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/sh2000/setup.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,46 @@ +/* + * linux/arch/sh/kernel/setup_sh2000.c + * + * Copyright (C) 2001 SUGIOKA Tochinobu + * + * SH-2000 Support. + * + */ + +#include +#include +#include + +#include + +#define CF_CIS_BASE 0xb4200000 + +#define PORT_PECR 0xa4000108 +#define PORT_PHCR 0xa400010E +#define PORT_ICR1 0xa4000010 +#define PORT_IRR0 0xa4000004 + +const char *get_system_type(void) +{ + return "sh2000"; +} + +/* + * Initialize the board + */ +int __init platform_setup(void) +{ + /* XXX: RTC setting comes here */ + + /* These should be done by BIOS/IPL ... */ + /* Enable nCE2A, nCE2B output */ + ctrl_outw(ctrl_inw(PORT_PECR) & ~0xf00, PORT_PECR); + /* Enable the Compact Flash card, and set the level interrupt */ + ctrl_outw(0x0042, CF_CIS_BASE+0x0200); + /* Enable interrupt */ + ctrl_outw(ctrl_inw(PORT_PHCR) & ~0x03f3, PORT_PHCR); + ctrl_outw(1, PORT_ICR1); + ctrl_outw(ctrl_inw(PORT_IRR0) & ~0xff3f, PORT_IRR0); + printk(KERN_INFO "SH-2000 Setup...done\n"); + return 0; +} diff -urN linux-2.5.70-bk19/arch/sh/boards/unknown/Makefile linux-2.5.71/arch/sh/boards/unknown/Makefile --- linux-2.5.70-bk19/arch/sh/boards/unknown/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/unknown/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,10 @@ +# +# Makefile for unknown SH boards +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := mach.o io.o setup.o + diff -urN linux-2.5.70-bk19/arch/sh/boards/unknown/io.c linux-2.5.71/arch/sh/boards/unknown/io.c --- linux-2.5.70-bk19/arch/sh/boards/unknown/io.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/unknown/io.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,46 @@ +/* + * linux/arch/sh/kernel/io_unknown.c + * + * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * I/O routine for unknown hardware. + */ + +static unsigned int unknown_handler(void) +{ + return 0; +} + +#define UNKNOWN_ALIAS(fn) \ + void unknown_##fn(void) __attribute__ ((alias ("unknown_handler"))); + +UNKNOWN_ALIAS(inb) +UNKNOWN_ALIAS(inw) +UNKNOWN_ALIAS(inl) +UNKNOWN_ALIAS(outb) +UNKNOWN_ALIAS(outw) +UNKNOWN_ALIAS(outl) +UNKNOWN_ALIAS(inb_p) +UNKNOWN_ALIAS(inw_p) +UNKNOWN_ALIAS(inl_p) +UNKNOWN_ALIAS(outb_p) +UNKNOWN_ALIAS(outw_p) +UNKNOWN_ALIAS(outl_p) +UNKNOWN_ALIAS(insb) +UNKNOWN_ALIAS(insw) +UNKNOWN_ALIAS(insl) +UNKNOWN_ALIAS(outsb) +UNKNOWN_ALIAS(outsw) +UNKNOWN_ALIAS(outsl) +UNKNOWN_ALIAS(readb) +UNKNOWN_ALIAS(readw) +UNKNOWN_ALIAS(readl) +UNKNOWN_ALIAS(writeb) +UNKNOWN_ALIAS(writew) +UNKNOWN_ALIAS(writel) +UNKNOWN_ALIAS(isa_port2addr) +UNKNOWN_ALIAS(ioremap) +UNKNOWN_ALIAS(iounmap) diff -urN linux-2.5.70-bk19/arch/sh/boards/unknown/mach.c linux-2.5.71/arch/sh/boards/unknown/mach.c --- linux-2.5.70-bk19/arch/sh/boards/unknown/mach.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/unknown/mach.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,67 @@ +/* + * linux/arch/sh/kernel/mach_unknown.c + * + * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Machine specific code for an unknown machine (internal peripherials only) + */ + +#include +#include + +#include +#include + +#include + +#include +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_unknown __initmv = { +#if defined(CONFIG_CPU_SH4) + mv_nr_irqs: 48, +#elif defined(CONFIG_CPU_SUBTYPE_SH7708) + mv_nr_irqs: 32, +#elif defined(CONFIG_CPU_SUBTYPE_SH7709) + mv_nr_irqs: 61, +#endif + + mv_inb: unknown_inb, + mv_inw: unknown_inw, + mv_inl: unknown_inl, + mv_outb: unknown_outb, + mv_outw: unknown_outw, + mv_outl: unknown_outl, + + mv_inb_p: unknown_inb_p, + mv_inw_p: unknown_inw_p, + mv_inl_p: unknown_inl_p, + mv_outb_p: unknown_outb_p, + mv_outw_p: unknown_outw_p, + mv_outl_p: unknown_outl_p, + + mv_insb: unknown_insb, + mv_insw: unknown_insw, + mv_insl: unknown_insl, + mv_outsb: unknown_outsb, + mv_outsw: unknown_outsw, + mv_outsl: unknown_outsl, + + mv_readb: unknown_readb, + mv_readw: unknown_readw, + mv_readl: unknown_readl, + mv_writeb: unknown_writeb, + mv_writew: unknown_writew, + mv_writel: unknown_writel, + + mv_ioremap: unknown_ioremap, + mv_iounmap: unknown_iounmap, + + mv_isa_port2addr: unknown_isa_port2addr, +}; +ALIAS_MV(unknown) diff -urN linux-2.5.70-bk19/arch/sh/boards/unknown/setup.c linux-2.5.71/arch/sh/boards/unknown/setup.c --- linux-2.5.70-bk19/arch/sh/boards/unknown/setup.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/boards/unknown/setup.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,23 @@ +/* + * linux/arch/sh/boards/unknown/setup.c + * + * Copyright (C) 2002 Paul Mundt + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Setup code for an unknown machine (internal peripherials only) + */ + +#include +#include + +const char *get_system_type(void) +{ + return "Unknown"; +} + +void __init platform_setup(void) +{ +} + diff -urN linux-2.5.70-bk19/arch/sh/boot/compressed/Makefile linux-2.5.71/arch/sh/boot/compressed/Makefile --- linux-2.5.70-bk19/arch/sh/boot/compressed/Makefile 2003-05-26 18:00:40.000000000 -0700 +++ linux-2.5.71/arch/sh/boot/compressed/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -4,40 +4,34 @@ # create a compressed vmlinux image from the original vmlinux # -HEAD = head.o -SYSTEM = $(TOPDIR)/vmlinux +targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o +EXTRA_AFLAGS := -traditional -OBJECTS = $(HEAD) misc.o +OBJECTS = $(obj)/head.o $(obj)/misc.o ifdef CONFIG_SH_STANDARD_BIOS -OBJECTS += ../../kernel/sh_bios.o +OBJECTS += $(obj)/../../kernel/sh_bios.o endif -ZLDFLAGS = -e startup -T $(TOPDIR)/arch/sh/vmlinux.lds - # -# ZIMAGE_OFFSET is the load offset of the compression loader +# IMAGE_OFFSET is the load offset of the compression loader # -ZIMAGE_OFFSET = $(shell printf "0x%8x" $$[0x80000000+0x$(CONFIG_MEMORY_START)+0x200000+0x10000]) +IMAGE_OFFSET = $(shell printf "0x%8x" $$[0x80000000+0x$(CONFIG_MEMORY_START)+0x200000+0x10000]) -ZLINKFLAGS = -Ttext $(ZIMAGE_OFFSET) $(ZLDFLAGS) +LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../vmlinux.lds.s -all: vmlinux +$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE + $(call if_changed,ld) + @: -vmlinux: piggy.o $(OBJECTS) - $(LD) $(LDFLAGS) $(ZLINKFLAGS) -o vmlinux $(OBJECTS) piggy.o +$(obj)/vmlinux.bin: vmlinux FORCE + $(call if_changed,objcopy) -head.o: head.S - $(CC) $(AFLAGS) -traditional -c head.S +$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE + $(call if_changed,gzip) -piggy.o: $(SYSTEM) - tmppiggy=_tmp_$$$$piggy; \ - rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk; \ - $(OBJCOPY) $(OBJCOPYFLAGS) -R .empty_zero_page $(SYSTEM) $$tmppiggy; \ - gzip -f -9 < $$tmppiggy > $$tmppiggy.gz; \ - echo "SECTIONS { .data : { input_len = .; LONG(input_data_end - input_data) input_data = .; *(.data) input_data_end = .; }}" > $$tmppiggy.lnk; \ - $(LD) $(LDFLAGS) -r -o piggy.o -b binary $$tmppiggy.gz -b elf32-sh-linux -T $$tmppiggy.lnk; \ - rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk +LDFLAGS_piggy.o := -r --format binary --oformat elf32-sh-linux -T +OBJCOPYFLAGS += -R .empty_zero_page -clean: - rm -f vmlinux _tmp_* +$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE + $(call if_changed,ld) diff -urN linux-2.5.70-bk19/arch/sh/cchips/hd6446x/hd64461/Makefile linux-2.5.71/arch/sh/cchips/hd6446x/hd64461/Makefile --- linux-2.5.70-bk19/arch/sh/cchips/hd6446x/hd64461/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/cchips/hd6446x/hd64461/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,10 @@ +# +# Makefile for the HD64461 +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := setup.o io.o + diff -urN linux-2.5.70-bk19/arch/sh/cchips/hd6446x/hd64461/io.c linux-2.5.71/arch/sh/cchips/hd6446x/hd64461/io.c --- linux-2.5.70-bk19/arch/sh/cchips/hd6446x/hd64461/io.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/cchips/hd6446x/hd64461/io.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,136 @@ +/* + * $Id: io.c,v 1.1.2.2 2002/01/20 05:03:25 mrbrown Exp $ + * Copyright (C) 2000 YAEGASHI Takeshi + * Typical I/O routines for HD64461 system. + */ + +#include +#include +#include + +static __inline__ unsigned long PORT2ADDR(unsigned long port) +{ + /* 16550A: HD64461 internal */ + if (0x3f8<=port && port<=0x3ff) + return CONFIG_HD64461_IOBASE + 0x8000 + ((port-0x3f8)<<1); + if (0x2f8<=port && port<=0x2ff) + return CONFIG_HD64461_IOBASE + 0x7000 + ((port-0x2f8)<<1); + +#ifdef CONFIG_HD64461_ENABLER + /* NE2000: HD64461 PCMCIA channel 0 (I/O) */ + if (0x300<=port && port<=0x31f) + return 0xba000000 + port; + + /* ide0: HD64461 PCMCIA channel 1 (memory) */ + /* On HP690, CF in slot 1 is configured as a memory card + device. See CF+ and CompactFlash Specification for the + detail of CF's memory mapped addressing. */ + if (0x1f0<=port && port<=0x1f7) return 0xb5000000 + port; + if (port == 0x3f6) return 0xb50001fe; + if (port == 0x3f7) return 0xb50001ff; + + /* ide1 */ + if (0x170<=port && port<=0x177) return 0xba000000 + port; + if (port == 0x376) return 0xba000376; + if (port == 0x377) return 0xba000377; +#endif + + /* ??? */ + if (port < 0x10000) return 0xa0000000 + port; + + /* HD64461 internal devices (0xb0000000) */ + if (port < 0x20000) return CONFIG_HD64461_IOBASE + port - 0x10000; + + /* PCMCIA channel 0, I/O (0xba000000) */ + if (port < 0x30000) return 0xba000000 + port - 0x20000; + + /* PCMCIA channel 1, memory (0xb5000000) */ + if (port < 0x40000) return 0xb5000000 + port - 0x30000; + + /* Whole physical address space (0xa0000000) */ + return 0xa0000000 + (port & 0x1fffffff); +} + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); +} + +unsigned char hd64461_inb(unsigned long port) +{ + return *(volatile unsigned char*)PORT2ADDR(port); +} + +unsigned char hd64461_inb_p(unsigned long port) +{ + unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); + delay(); + return v; +} + +unsigned short hd64461_inw(unsigned long port) +{ + return *(volatile unsigned short*)PORT2ADDR(port); +} + +unsigned int hd64461_inl(unsigned long port) +{ + return *(volatile unsigned long*)PORT2ADDR(port); +} + +void hd64461_insb(unsigned long port, void *buffer, unsigned long count) +{ + unsigned char *buf=buffer; + while(count--) *buf++=inb(port); +} + +void hd64461_insw(unsigned long port, void *buffer, unsigned long count) +{ + unsigned short *buf=buffer; + while(count--) *buf++=inw(port); +} + +void hd64461_insl(unsigned long port, void *buffer, unsigned long count) +{ + unsigned long *buf=buffer; + while(count--) *buf++=inl(port); +} + +void hd64461_outb(unsigned char b, unsigned long port) +{ + *(volatile unsigned char*)PORT2ADDR(port) = b; +} + +void hd64461_outb_p(unsigned char b, unsigned long port) +{ + *(volatile unsigned char*)PORT2ADDR(port) = b; + delay(); +} + +void hd64461_outw(unsigned short b, unsigned long port) +{ + *(volatile unsigned short*)PORT2ADDR(port) = b; +} + +void hd64461_outl(unsigned int b, unsigned long port) +{ + *(volatile unsigned long*)PORT2ADDR(port) = b; +} + +void hd64461_outsb(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned char *buf=buffer; + while(count--) outb(*buf++, port); +} + +void hd64461_outsw(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned short *buf=buffer; + while(count--) outw(*buf++, port); +} + +void hd64461_outsl(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned long *buf=buffer; + while(count--) outl(*buf++, port); +} diff -urN linux-2.5.70-bk19/arch/sh/cchips/hd6446x/hd64461/setup.c linux-2.5.71/arch/sh/cchips/hd6446x/hd64461/setup.c --- linux-2.5.70-bk19/arch/sh/cchips/hd6446x/hd64461/setup.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/cchips/hd6446x/hd64461/setup.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,145 @@ +/* + * $Id: setup.c,v 1.1.2.3 2002/11/04 20:33:57 lethal Exp $ + * Copyright (C) 2000 YAEGASHI Takeshi + * Hitachi HD64461 companion chip support + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +static void disable_hd64461_irq(unsigned int irq) +{ + unsigned long flags; + unsigned short nimr; + unsigned short mask = 1 << (irq - HD64461_IRQBASE); + + local_irq_save(flags); + nimr = inw(HD64461_NIMR); + nimr |= mask; + outw(nimr, HD64461_NIMR); + local_irq_restore(flags); +} + + +static void enable_hd64461_irq(unsigned int irq) +{ + unsigned long flags; + unsigned short nimr; + unsigned short mask = 1 << (irq - HD64461_IRQBASE); + + local_irq_save(flags); + nimr = inw(HD64461_NIMR); + nimr &= ~mask; + outw(nimr, HD64461_NIMR); + local_irq_restore(flags); +} + + +static void mask_and_ack_hd64461(unsigned int irq) +{ + disable_hd64461_irq(irq); +#ifdef CONFIG_HD64461_ENABLER + if (irq == HD64461_IRQBASE + 13) + outb(0x00, HD64461_PCC1CSCR); +#endif +} + + +static void end_hd64461_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_hd64461_irq(irq); +} + + +static unsigned int startup_hd64461_irq(unsigned int irq) +{ + enable_hd64461_irq(irq); + return 0; +} + + +static void shutdown_hd64461_irq(unsigned int irq) +{ + disable_hd64461_irq(irq); +} + + +static struct hw_interrupt_type hd64461_irq_type = { + "HD64461-IRQ", + startup_hd64461_irq, + shutdown_hd64461_irq, + enable_hd64461_irq, + disable_hd64461_irq, + mask_and_ack_hd64461, + end_hd64461_irq +}; + + +static void hd64461_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + printk(KERN_INFO + "HD64461: spurious interrupt, nirr: 0x%x nimr: 0x%x\n", + inw(HD64461_NIRR), inw(HD64461_NIMR)); +} + +int hd64461_irq_demux(int irq) +{ + if (irq == CONFIG_HD64461_IRQ) { + unsigned short bit; + unsigned short nirr = inw(HD64461_NIRR); + unsigned short nimr = inw(HD64461_NIMR); + nirr &= ~nimr; + for (bit = 1, irq = 0; irq < 16; bit <<= 1, irq++) + if (nirr & bit) break; + if (irq == 16) irq = CONFIG_HD64461_IRQ; + else irq += HD64461_IRQBASE; + } + return __irq_demux(irq); +} + +static struct irqaction irq0 = { hd64461_interrupt, SA_INTERRUPT, 0, "HD64461", NULL, NULL}; + + +int __init setup_hd64461(void) +{ + int i; + + if (!MACH_HD64461) + return 0; + + printk(KERN_INFO "HD64461 configured at 0x%x on irq %d(mapped into %d to %d)\n", + CONFIG_HD64461_IOBASE, CONFIG_HD64461_IRQ, + HD64461_IRQBASE, HD64461_IRQBASE+15); + +#if defined(CONFIG_CPU_SUBTYPE_SH7709) /* Should be at processor specific part.. */ + outw(0x2240, INTC_ICR1); +#endif + outw(0xffff, HD64461_NIMR); + + for (i = HD64461_IRQBASE; i < HD64461_IRQBASE + 16; i++) { + irq_desc[i].handler = &hd64461_irq_type; + } + + setup_irq(CONFIG_HD64461_IRQ, &irq0); + +#ifdef CONFIG_HD64461_ENABLER + printk(KERN_INFO "HD64461: enabling PCMCIA devices\n"); + outb(0x4c, HD64461_PCC1CSCIER); + outb(0x00, HD64461_PCC1CSCR); +#endif + + return 0; +} + +module_init(setup_hd64461); diff -urN linux-2.5.70-bk19/arch/sh/cchips/hd6446x/hd64465/Makefile linux-2.5.71/arch/sh/cchips/hd6446x/hd64465/Makefile --- linux-2.5.70-bk19/arch/sh/cchips/hd6446x/hd64465/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/cchips/hd6446x/hd64465/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,10 @@ +# +# Makefile for the HD64465 +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := setup.o io.o gpio.o + diff -urN linux-2.5.70-bk19/arch/sh/cchips/hd6446x/hd64465/gpio.c linux-2.5.71/arch/sh/cchips/hd6446x/hd64465/gpio.c --- linux-2.5.70-bk19/arch/sh/cchips/hd6446x/hd64465/gpio.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/cchips/hd6446x/hd64465/gpio.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,184 @@ +/* + * $Id: gpio.c,v 1.1.2.3 2002/11/04 20:33:57 lethal Exp $ + * by Greg Banks + * (c) 2000 PocketPenguins Inc + * + * GPIO pin support for HD64465 companion chip. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define _PORTOF(portpin) (((portpin)>>3)&0x7) +#define _PINOF(portpin) ((portpin)&0x7) + +/* Register addresses parametrised on port */ +#define GPIO_CR(port) (HD64465_REG_GPACR+((port)<<1)) +#define GPIO_DR(port) (HD64465_REG_GPADR+((port)<<1)) +#define GPIO_ICR(port) (HD64465_REG_GPAICR+((port)<<1)) +#define GPIO_ISR(port) (HD64465_REG_GPAISR+((port)<<1)) + +#define GPIO_NPORTS 5 + +#define MODNAME "hd64465_gpio" + +EXPORT_SYMBOL(hd64465_gpio_configure); +EXPORT_SYMBOL(hd64465_gpio_get_pin); +EXPORT_SYMBOL(hd64465_gpio_get_port); +EXPORT_SYMBOL(hd64465_gpio_register_irq); +EXPORT_SYMBOL(hd64465_gpio_set_pin); +EXPORT_SYMBOL(hd64465_gpio_set_port); +EXPORT_SYMBOL(hd64465_gpio_unregister_irq); + +/* TODO: each port should be protected with a spinlock */ + + +void hd64465_gpio_configure(int portpin, int direction) +{ + unsigned short cr; + unsigned int shift = (_PINOF(portpin)<<1); + + cr = inw(GPIO_CR(_PORTOF(portpin))); + cr &= ~(3< + * (c) 2000 PocketPenguins Inc + * + * Derived from io_hd64461.c, which bore the message: + * Copyright (C) 2000 YAEGASHI Takeshi + * + * Typical I/O routines for HD64465 system. + */ + +#include +#include +#include +#include +#include + + +#define HD64465_DEBUG 0 + +#if HD64465_DEBUG +#define DPRINTK(args...) printk(args) +#define DIPRINTK(n, args...) if (hd64465_io_debug>(n)) printk(args) +#else +#define DPRINTK(args...) +#define DIPRINTK(n, args...) +#endif + + + +/* This is a hack suitable only for debugging IO port problems */ +int hd64465_io_debug; +EXPORT_SYMBOL(hd64465_io_debug); + +/* Low iomap maps port 0-1K to addresses in 8byte chunks */ +#define HD64465_IOMAP_LO_THRESH 0x400 +#define HD64465_IOMAP_LO_SHIFT 3 +#define HD64465_IOMAP_LO_MASK ((1<>HD64465_IOMAP_LO_SHIFT) +static unsigned long hd64465_iomap_lo[HD64465_IOMAP_LO_NMAP]; +static unsigned char hd64465_iomap_lo_shift[HD64465_IOMAP_LO_NMAP]; + +/* High iomap maps port 1K-64K to addresses in 1K chunks */ +#define HD64465_IOMAP_HI_THRESH 0x10000 +#define HD64465_IOMAP_HI_SHIFT 10 +#define HD64465_IOMAP_HI_MASK ((1<>HD64465_IOMAP_HI_SHIFT) +static unsigned long hd64465_iomap_hi[HD64465_IOMAP_HI_NMAP]; +static unsigned char hd64465_iomap_hi_shift[HD64465_IOMAP_HI_NMAP]; + +#ifndef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) +#endif + +#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x)) + +void hd64465_port_map(unsigned short baseport, unsigned int nports, + unsigned long addr, unsigned char shift) +{ + unsigned int port, endport = baseport + nports; + + DPRINTK("hd64465_port_map(base=0x%04hx, n=0x%04hx, addr=0x%08lx,endport=0x%04x)\n", + baseport, nports, addr,endport); + + for (port = baseport ; + port < endport && port < HD64465_IOMAP_LO_THRESH ; + port += (1<>HD64465_IOMAP_LO_SHIFT] = addr; + hd64465_iomap_lo_shift[port>>HD64465_IOMAP_LO_SHIFT] = shift; + addr += (1<<(HD64465_IOMAP_LO_SHIFT)); + } + + for (port = MAX(baseport, HD64465_IOMAP_LO_THRESH) ; + port < endport && port < HD64465_IOMAP_HI_THRESH ; + port += (1<>HD64465_IOMAP_HI_SHIFT] = addr; + hd64465_iomap_hi_shift[port>>HD64465_IOMAP_HI_SHIFT] = shift; + addr += (1<<(HD64465_IOMAP_HI_SHIFT)); + } +} +EXPORT_SYMBOL(hd64465_port_map); + +void hd64465_port_unmap(unsigned short baseport, unsigned int nports) +{ + unsigned int port, endport = baseport + nports; + + DPRINTK("hd64465_port_unmap(base=0x%04hx, n=0x%04hx)\n", + baseport, nports); + + for (port = baseport ; + port < endport && port < HD64465_IOMAP_LO_THRESH ; + port += (1<>HD64465_IOMAP_LO_SHIFT] = 0; + } + + for (port = MAX(baseport, HD64465_IOMAP_LO_THRESH) ; + port < endport && port < HD64465_IOMAP_HI_THRESH ; + port += (1<>HD64465_IOMAP_HI_SHIFT] = 0; + } +} +EXPORT_SYMBOL(hd64465_port_unmap); + +unsigned long hd64465_isa_port2addr(unsigned long port) +{ + unsigned long addr = 0; + unsigned char shift; + + /* handle remapping of low IO ports */ + if (port < HD64465_IOMAP_LO_THRESH) { + addr = hd64465_iomap_lo[port >> HD64465_IOMAP_LO_SHIFT]; + shift = hd64465_iomap_lo_shift[port >> HD64465_IOMAP_LO_SHIFT]; + if (addr != 0) + addr += (port & HD64465_IOMAP_LO_MASK) << shift; + else + printk(KERN_NOTICE "io_hd64465: access to un-mapped port %lx\n", port); + } else if (port < HD64465_IOMAP_HI_THRESH) { + addr = hd64465_iomap_hi[port >> HD64465_IOMAP_HI_SHIFT]; + shift = hd64465_iomap_hi_shift[port >> HD64465_IOMAP_HI_SHIFT]; + if (addr != 0) + addr += (port & HD64465_IOMAP_HI_MASK) << shift; + else + printk(KERN_NOTICE "io_hd64465: access to un-mapped port %lx\n", port); + } + + /* HD64465 internal devices (0xb0000000) */ + else if (port < 0x20000) + addr = CONFIG_HD64465_IOBASE + port - 0x10000; + + /* Whole physical address space (0xa0000000) */ + else + addr = P2SEGADDR(port); + + DIPRINTK(2, "PORT2ADDR(0x%08lx) = 0x%08lx\n", port, addr); + + return addr; +} + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); +} + +unsigned char hd64465_inb(unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + unsigned long b = (addr == 0 ? 0 : *(volatile unsigned char*)addr); + + DIPRINTK(0, "inb(%08lx) = %02x\n", addr, (unsigned)b); + return b; +} + +unsigned char hd64465_inb_p(unsigned long port) +{ + unsigned long v; + unsigned long addr = PORT2ADDR(port); + + v = (addr == 0 ? 0 : *(volatile unsigned char*)addr); + delay(); + DIPRINTK(0, "inb_p(%08lx) = %02x\n", addr, (unsigned)v); + return v; +} + +unsigned short hd64465_inw(unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + unsigned long b = (addr == 0 ? 0 : *(volatile unsigned short*)addr); + DIPRINTK(0, "inw(%08lx) = %04lx\n", addr, b); + return b; +} + +unsigned int hd64465_inl(unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + unsigned int b = (addr == 0 ? 0 : *(volatile unsigned long*)addr); + DIPRINTK(0, "inl(%08lx) = %08x\n", addr, b); + return b; +} + +void hd64465_insb(unsigned long port, void *buffer, unsigned long count) +{ + unsigned char *buf=buffer; + while(count--) *buf++=inb(port); +} + +void hd64465_insw(unsigned long port, void *buffer, unsigned long count) +{ + unsigned short *buf=buffer; + while(count--) *buf++=inw(port); +} + +void hd64465_insl(unsigned long port, void *buffer, unsigned long count) +{ + unsigned long *buf=buffer; + while(count--) *buf++=inl(port); +} + +void hd64465_outb(unsigned char b, unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + + DIPRINTK(0, "outb(%02x, %08lx)\n", (unsigned)b, addr); + if (addr != 0) + *(volatile unsigned char*)addr = b; +} + +void hd64465_outb_p(unsigned char b, unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + + DIPRINTK(0, "outb_p(%02x, %08lx)\n", (unsigned)b, addr); + if (addr != 0) + *(volatile unsigned char*)addr = b; + delay(); +} + +void hd64465_outw(unsigned short b, unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + DIPRINTK(0, "outw(%04x, %08lx)\n", (unsigned)b, addr); + if (addr != 0) + *(volatile unsigned short*)addr = b; +} + +void hd64465_outl(unsigned int b, unsigned long port) +{ + unsigned long addr = PORT2ADDR(port); + DIPRINTK(0, "outl(%08x, %08lx)\n", b, addr); + if (addr != 0) + *(volatile unsigned long*)addr = b; +} + +void hd64465_outsb(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned char *buf=buffer; + while(count--) outb(*buf++, port); +} + +void hd64465_outsw(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned short *buf=buffer; + while(count--) outw(*buf++, port); +} + +void hd64465_outsl(unsigned long port, const void *buffer, unsigned long count) +{ + const unsigned long *buf=buffer; + while(count--) outl(*buf++, port); +} diff -urN linux-2.5.70-bk19/arch/sh/cchips/hd6446x/hd64465/setup.c linux-2.5.71/arch/sh/cchips/hd6446x/hd64465/setup.c --- linux-2.5.70-bk19/arch/sh/cchips/hd6446x/hd64465/setup.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/arch/sh/cchips/hd6446x/hd64465/setup.c 2003-06-14 13:53:23.000000000 -0700 @@ -0,0 +1,208 @@ +/* + * $Id: setup.c,v 1.1.2.3 2002/11/04 20:33:57 lethal Exp $ + * + * Setup and IRQ handling code for the HD64465 companion chip. + * by Greg Banks + * Copyright (c) 2000 PocketPenguins Inc + * + * Derived from setup_hd64461.c which bore the message: + * Copyright (C) 2000 YAEGASHI Takeshi + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#undef HD64465_DEBUG + +#ifdef HD64465_DEBUG +#define DPRINTK(args...) printk(args) +#else +#define DPRINTK(args...) +#endif + +static void disable_hd64465_irq(unsigned int irq) +{ + unsigned long flags; + unsigned short nimr; + unsigned short mask = 1 << (irq - HD64465_IRQ_BASE); + + DPRINTK("disable_hd64465_irq(%d): mask=%x\n", irq, mask); + local_irq_save(flags); + nimr = inw(HD64465_REG_NIMR); + nimr |= mask; + outw(nimr, HD64465_REG_NIMR); + local_irq_restore(flags); +} + + +static void enable_hd64465_irq(unsigned int irq) +{ + unsigned long flags; + unsigned short nimr; + unsigned short mask = 1 << (irq - HD64465_IRQ_BASE); + + DPRINTK("enable_hd64465_irq(%d): mask=%x\n", irq, mask); + local_irq_save(flags); + nimr = inw(HD64465_REG_NIMR); + nimr &= ~mask; + outw(nimr, HD64465_REG_NIMR); + local_irq_restore(flags); +} + + +static void mask_and_ack_hd64465(unsigned int irq) +{ + disable_hd64465_irq(irq); +} + + +static void end_hd64465_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_hd64465_irq(irq); +} + + +static unsigned int startup_hd64465_irq(unsigned int irq) +{ + enable_hd64465_irq(irq); + return 0; +} + + +static void shutdown_hd64465_irq(unsigned int irq) +{ + disable_hd64465_irq(irq); +} + + +static struct hw_interrupt_type hd64465_irq_type = { + typename: "HD64465-IRQ", + startup: startup_hd64465_irq, + shutdown: shutdown_hd64465_irq, + enable: enable_hd64465_irq, + disable: disable_hd64465_irq, + ack: mask_and_ack_hd64465, + end: end_hd64465_irq +}; + + +static void hd64465_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + printk(KERN_INFO + "HD64465: spurious interrupt, nirr: 0x%x nimr: 0x%x\n", + inw(HD64465_REG_NIRR), inw(HD64465_REG_NIMR)); +} + + +/*====================================================*/ + +/* + * Support for a secondary IRQ demux step. This is necessary + * because the HD64465 presents a very thin interface to the + * PCMCIA bus; a lot of features (such as remapping interrupts) + * normally done in hardware by other PCMCIA host bridges is + * instead done in software. + */ +static struct +{ + int (*func)(int, void *); + void *dev; +} hd64465_demux[HD64465_IRQ_NUM]; + +void hd64465_register_irq_demux(int irq, + int (*demux)(int irq, void *dev), void *dev) +{ + hd64465_demux[irq - HD64465_IRQ_BASE].func = demux; + hd64465_demux[irq - HD64465_IRQ_BASE].dev = dev; +} +EXPORT_SYMBOL(hd64465_register_irq_demux); + +void hd64465_unregister_irq_demux(int irq) +{ + hd64465_demux[irq - HD64465_IRQ_BASE].func = 0; +} +EXPORT_SYMBOL(hd64465_unregister_irq_demux); + + + +int hd64465_irq_demux(int irq) +{ + if (irq == CONFIG_HD64465_IRQ) { + unsigned short i, bit; + unsigned short nirr = inw(HD64465_REG_NIRR); + unsigned short nimr = inw(HD64465_REG_NIMR); + + DPRINTK("hd64465_irq_demux, nirr=%04x, nimr=%04x\n", nirr, nimr); + nirr &= ~nimr; + for (bit = 1, i = 0 ; i < HD64465_IRQ_NUM ; bit <<= 1, i++) + if (nirr & bit) + break; + + if (i < HD64465_IRQ_NUM) { + irq = HD64465_IRQ_BASE + i; + if (hd64465_demux[i].func != 0) + irq = hd64465_demux[i].func(irq, hd64465_demux[i].dev); + } + } + return irq; +} + +static struct irqaction irq0 = { hd64465_interrupt, SA_INTERRUPT, 0, "HD64465", NULL, NULL}; + + +static int __init setup_hd64465(void) +{ + int i; + unsigned short rev; + unsigned short smscr; + + if (!MACH_HD64465) + return 0; + + printk(KERN_INFO "HD64465 configured at 0x%x on irq %d(mapped into %d to %d)\n", + CONFIG_HD64465_IOBASE, + CONFIG_HD64465_IRQ, + HD64465_IRQ_BASE, + HD64465_IRQ_BASE+HD64465_IRQ_NUM-1); + + if (inw(HD64465_REG_SDID) != HD64465_SDID) { + printk(KERN_ERR "HD64465 device ID not found, check base address\n"); + } + + rev = inw(HD64465_REG_SRR); + printk(KERN_INFO "HD64465 hardware revision %d.%d\n", (rev >> 8) & 0xff, rev & 0xff); + + outw(0xffff, HD64465_REG_NIMR); /* mask all interrupts */ + + for (i = 0; i < HD64465_IRQ_NUM ; i++) { + irq_desc[HD64465_IRQ_BASE + i].handler = &hd64465_irq_type; + } + + setup_irq(CONFIG_HD64465_IRQ, &irq0); + +#ifdef CONFIG_SERIAL + /* wake up the UART from STANDBY at this point */ + smscr = inw(HD64465_REG_SMSCR); + outw(smscr & (~HD64465_SMSCR_UARTST), HD64465_REG_SMSCR); + + /* remap IO ports for first ISA serial port to HD64465 UART */ + hd64465_port_map(0x3f8, 8, CONFIG_HD64465_IOBASE + 0x8000, 1); +#endif + + return 0; +} + +module_init(setup_hd64465); diff -urN linux-2.5.70-bk19/arch/sh/kernel/Makefile linux-2.5.71/arch/sh/kernel/Makefile --- linux-2.5.70-bk19/arch/sh/kernel/Makefile 2003-05-26 18:00:41.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -4,68 +4,23 @@ extra-y := head.o init_task.o -obj-y := process.o signal.o entry.o traps.o irq.o irq_ipr.o \ +obj-y := process.o signal.o entry.o traps.o irq.o \ ptrace.o setup.o time.o sys_sh.o semaphore.o \ - irq_imask.o io.o io_generic.o sh_ksyms.o + io.o io_generic.o sh_ksyms.o +obj-y += cpu/ + +obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_CF_ENABLER) += cf-enabler.o -obj-$(CONFIG_CPU_SH4) += fpu.o -obj-$(CONFIG_SH_RTC) += rtc.o -obj-$(CONFIG_SH_DMA) += dma.o obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o +obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o +obj-$(CONFIG_CPU_FREQ) += cpufreq.o -ifeq ($(CONFIG_PCI),y) -ifeq ($(CONFIG_SH_DREAMCAST),y) -obj-y += pci-dc.o pcibios.o -else -obj-y += pci-dma.o pcibios.o -obj-$(CONFIG_CPU_SUBTYPE_ST40STB1)+= pci_st40.o -obj-$(CONFIG_CPU_SUBTYPE_SH7751)+= pci-sh7751.o -obj-$(CONFIG_SH_BIGSUR)+= pci-bigsur.o -obj-$(CONFIG_SH_7751_SOLUTION_ENGINE)+= pci-7751se.o -endif +ifneq ($(CONFIG_SH_DREAMCAST),y) +obj-$(CONFIG_PCI) += pci-dma.o endif +obj-$(CONFIG_PCI) += pci.o +obj-$(CONFIG_PCI_AUTO) += pci_auto.o -obj-$(CONFIG_SH_HP600) += mach_hp600.o -machine-specific-objs += mach_hp600.o - -obj-$(CONFIG_SH_SOLUTION_ENGINE)+= mach_se.o setup_se.o io_se.o led_se.o -machine-specific-objs += mach_se.o setup_se.o io_se.o led_se.o - -obj-$(CONFIG_SH_7751_SOLUTION_ENGINE)+= mach_7751se.o setup_7751se.o \ - io_7751se.o led_7751se.o -machine-specific-objs += mach_7751se.o 7751setup_se.o \ - io_7751se.o led_7751se.o pci-7751se.o - -obj-$(CONFIG_SH_BIGSUR) += mach_bigsur.o setup_bigsur.o io_bigsur.o led_bigsur.o -machine-specific-objs += mach_bigsur.o setup_bigsur.o io_bigsur.o led_bigsur.o - -obj-$(CONFIG_SH_SH2000) += setup_sh2000.o io_sh2000.o -machine-specific-objs += setup_sh2000.o io_sh2000.o - -obj-$(CONFIG_SH_CAT68701) += mach_cat68701.o io_cat68701.o -machine-specific-objs += mach_cat68701.o io_cat68701.o +USE_STANDARD_AS_RULE := true -obj-$(CONFIG_SH_CQREEK) += setup_cqreek.o -machine-specific-objs += setup_cqreek.o - -obj-$(CONFIG_SH_UNKNOWN) += mach_unknown.o io_unknown.o -machine-specific-objs += mach_unknown.o io_unknown.o - -obj-$(CONFIG_HD64461) += setup_hd64461.o io_hd64461.o -machine-specific-objs += setup_hd64461.o io_hd64461.o - -obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) +=irq_intc2.o - -obj-$(CONFIG_SH_ADX) += mach_adx.o setup_adx.o io_adx.o irq_maskreg.o -machine-specific-objs += mach_adx.o setup_adx.o io_adx.o irq_maskreg.o - -# Doesn't compile well, so don't include in machine-specific-objs -obj-$(CONFIG_HD64465) += setup_hd64465.o io_hd64465.o hd64465_gpio.o -obj-$(CONFIG_SH_DMIDA) += mach_dmida.o -obj-$(CONFIG_SH_EC3104) += setup_ec3104.o io_ec3104.o mach_ec3104.o -obj-$(CONFIG_SH_DREAMCAST) += mach_dc.o setup_dc.o io_dc.o rtc-aica.o - -ifeq ($(CONFIG_SH_GENERIC),y) -obj-y += $(machine-specific-objs) -endif diff -urN linux-2.5.70-bk19/arch/sh/kernel/hd64465_gpio.c linux-2.5.71/arch/sh/kernel/hd64465_gpio.c --- linux-2.5.70-bk19/arch/sh/kernel/hd64465_gpio.c 2003-05-26 18:00:45.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/hd64465_gpio.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,191 +0,0 @@ -/* - * $Id: hd64465_gpio.c,v 1.2 2001/05/24 00:13:47 gniibe Exp $ - * by Greg Banks - * (c) 2000 PocketPenguins Inc - * - * GPIO pin support for HD64465 companion chip. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define _PORTOF(portpin) (((portpin)>>3)&0x7) -#define _PINOF(portpin) ((portpin)&0x7) - -/* Register addresses parametrised on port */ -#define GPIO_CR(port) (HD64465_REG_GPACR+((port)<<1)) -#define GPIO_DR(port) (HD64465_REG_GPADR+((port)<<1)) -#define GPIO_ICR(port) (HD64465_REG_GPAICR+((port)<<1)) -#define GPIO_ISR(port) (HD64465_REG_GPAISR+((port)<<1)) - -#define GPIO_NPORTS 5 - -#define MODNAME "hd64465_gpio" - -EXPORT_SYMBOL(hd64465_gpio_configure); -EXPORT_SYMBOL(hd64465_gpio_get_pin); -EXPORT_SYMBOL(hd64465_gpio_get_port); -EXPORT_SYMBOL(hd64465_gpio_register_irq); -EXPORT_SYMBOL(hd64465_gpio_set_pin); -EXPORT_SYMBOL(hd64465_gpio_set_port); -EXPORT_SYMBOL(hd64465_gpio_unregister_irq); - -/* TODO: each port should be protected with a spinlock */ - - -void hd64465_gpio_configure(int portpin, int direction) -{ - unsigned short cr; - unsigned int shift = (_PINOF(portpin)<<1); - - cr = inw(GPIO_CR(_PORTOF(portpin))); - cr &= ~(3< -#include -#include -#include -#include - -#include -#include - -#if 0 -/****************************************************************** - * Variables from io_se.c, related to PCMCIA (not PCI); we're not - * compiling them in, and have removed references from functions - * which follow. [Many checked for IO ports in the range bounded - * by sh_pcic_io_start/stop, and used sh_pcic_io_wbase as offset. - * As start/stop are uninitialized, only port 0x0 would match?] - * When used, remember to adjust names to avoid clash with io_se? - *****************************************************************/ -/* SH pcmcia io window base, start and end. */ -int sh_pcic_io_wbase = 0xb8400000; -int sh_pcic_io_start; -int sh_pcic_io_stop; -int sh_pcic_io_type; -int sh_pcic_io_dummy; -/*************************************************************/ -#endif - -/* - * The 7751 Solution Engine uses the built-in PCI controller (PCIC) - * of the 7751 processor, and has a SuperIO accessible via the PCI. - * The board also includes a PCMCIA controller on its memory bus, - * like the other Solution Engine boards. - */ - -#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR) -#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR) -#define PCI_IO_AREA SH7751_PCI_IO_BASE -#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE - -#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK)) - -#define maybebadio(name,port) \ - printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \ - #name, (port), (__u32) __builtin_return_address(0)) - -static inline void delay(void) -{ - ctrl_inw(0xa0000000); -} - -static inline volatile __u16 * -port2adr(unsigned int port) -{ - if (port >= 0x2000) - return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000)); -#if 0 - else - return (volatile __u16 *) (PA_SUPERIO + (port << 1)); -#endif - maybebadio(name,(unsigned long)port); - return (volatile __u16*)port; -} - -#if 0 -/* The 7751 Solution Engine seems to have everything hooked */ -/* up pretty normally (nothing on high-bytes only...) so this */ -/* shouldn't be needed */ -static inline int -shifted_port(unsigned long port) -{ - /* For IDE registers, value is not shifted */ - if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6) - return 0; - else - return 1; -} -#endif - -/* In case someone configures the kernel w/o PCI support: in that */ -/* scenario, don't ever bother to check for PCI-window addresses */ - -/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */ -#if defined(CONFIG_PCI) -#define CHECK_SH7751_PCIIO(port) \ - ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE))) -#else -#define CHECK_SH_7751_PCIIO(port) (0) -#endif - -/* - * General outline: remap really low stuff [eventually] to SuperIO, - * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO) - * is mapped through the PCI IO window. Stuff with high bits (PXSEG) - * should be way beyond the window, and is used w/o translation for - * compatibility. - */ -unsigned char sh7751se_inb(unsigned long port) -{ - if (PXSEG(port)) - return *(volatile unsigned char *)port; - else if (CHECK_SH7751_PCIIO(port)) - return *(volatile unsigned char *)PCI_IOMAP(port); - else - return (*port2adr(port))&0xff; -} - -unsigned char sh7751se_inb_p(unsigned long port) -{ - unsigned char v; - - if (PXSEG(port)) - v = *(volatile unsigned char *)port; - else if (CHECK_SH7751_PCIIO(port)) - v = *(volatile unsigned char *)PCI_IOMAP(port); - else - v = (*port2adr(port))&0xff; - delay(); - return v; -} - -unsigned short sh7751se_inw(unsigned long port) -{ - if (PXSEG(port)) - return *(volatile unsigned short *)port; - else if (CHECK_SH7751_PCIIO(port)) - return *(volatile unsigned short *)PCI_IOMAP(port); - else if (port >= 0x2000) - return *port2adr(port); - else - maybebadio(inw, port); - return 0; -} - -unsigned int sh7751se_inl(unsigned long port) -{ - if (PXSEG(port)) - return *(volatile unsigned long *)port; - else if (CHECK_SH7751_PCIIO(port)) - return *(volatile unsigned int *)PCI_IOMAP(port); - else if (port >= 0x2000) - return *port2adr(port); - else - maybebadio(inl, port); - return 0; -} - -void sh7751se_outb(unsigned char value, unsigned long port) -{ - - if (PXSEG(port)) - *(volatile unsigned char *)port = value; - else if (CHECK_SH7751_PCIIO(port)) - *((unsigned char*)PCI_IOMAP(port)) = value; - else - *(port2adr(port)) = value; -} - -void sh7751se_outb_p(unsigned char value, unsigned long port) -{ - if (PXSEG(port)) - *(volatile unsigned char *)port = value; - else if (CHECK_SH7751_PCIIO(port)) - *((unsigned char*)PCI_IOMAP(port)) = value; - else - *(port2adr(port)) = value; - delay(); -} - -void sh7751se_outw(unsigned short value, unsigned long port) -{ - if (PXSEG(port)) - *(volatile unsigned short *)port = value; - else if (CHECK_SH7751_PCIIO(port)) - *((unsigned short *)PCI_IOMAP(port)) = value; - else if (port >= 0x2000) - *port2adr(port) = value; - else - maybebadio(outw, port); -} - -void sh7751se_outl(unsigned int value, unsigned long port) -{ - if (PXSEG(port)) - *(volatile unsigned long *)port = value; - else if (CHECK_SH7751_PCIIO(port)) - *((unsigned long*)PCI_IOMAP(port)) = value; - else - maybebadio(outl, port); -} - -void sh7751se_insb(unsigned long port, void *addr, unsigned long count) -{ - unsigned char *p = addr; - while (count--) *p++ = sh7751se_inb(port); -} - -void sh7751se_insw(unsigned long port, void *addr, unsigned long count) -{ - unsigned short *p = addr; - while (count--) *p++ = sh7751se_inw(port); -} - -void sh7751se_insl(unsigned long port, void *addr, unsigned long count) -{ - maybebadio(insl, port); -} - -void sh7751se_outsb(unsigned long port, const void *addr, unsigned long count) -{ - unsigned char *p = (unsigned char*)addr; - while (count--) sh7751se_outb(*p++, port); -} - -void sh7751se_outsw(unsigned long port, const void *addr, unsigned long count) -{ - unsigned short *p = (unsigned short*)addr; - while (count--) sh7751se_outw(*p++, port); -} - -void sh7751se_outsl(unsigned long port, const void *addr, unsigned long count) -{ - maybebadio(outsw, port); -} - -/* For read/write calls, just copy generic (pass-thru); PCIMBR is */ -/* already set up. For a larger memory space, these would need to */ -/* reset PCIMBR as needed on a per-call basis... */ - -unsigned char sh7751se_readb(unsigned long addr) -{ - return *(volatile unsigned char*)addr; -} - -unsigned short sh7751se_readw(unsigned long addr) -{ - return *(volatile unsigned short*)addr; -} - -unsigned int sh7751se_readl(unsigned long addr) -{ - return *(volatile unsigned long*)addr; -} - -void sh7751se_writeb(unsigned char b, unsigned long addr) -{ - *(volatile unsigned char*)addr = b; -} - -void sh7751se_writew(unsigned short b, unsigned long addr) -{ - *(volatile unsigned short*)addr = b; -} - -void sh7751se_writel(unsigned int b, unsigned long addr) -{ - *(volatile unsigned long*)addr = b; -} - - - -/* Map ISA bus address to the real address. Only for PCMCIA. */ - -/* ISA page descriptor. */ -static __u32 sh_isa_memmap[256]; - -#if 0 -static int -sh_isa_mmap(__u32 start, __u32 length, __u32 offset) -{ - int idx; - - if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000)) - return -1; - - idx = start >> 12; - sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff); - printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n", - start, length, offset, idx, sh_isa_memmap[idx]); - return 0; -} -#endif - -unsigned long -sh7751se_isa_port2addr(unsigned long offset) -{ - int idx; - - idx = (offset >> 12) & 0xff; - offset &= 0xfff; - return sh_isa_memmap[idx] + offset; -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/io_adx.c linux-2.5.71/arch/sh/kernel/io_adx.c --- linux-2.5.70-bk19/arch/sh/kernel/io_adx.c 2003-05-26 18:00:40.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/io_adx.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,192 +0,0 @@ -/* - * linux/arch/sh/kernel/io_adx.c - * - * Copyright (C) 2001 A&D Co., Ltd. - * - * I/O routine and setup routines for A&D ADX Board - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - */ - -#include -#include -#include - -#define PORT2ADDR(x) (adx_isa_port2addr(x)) - -static inline void delay(void) -{ - ctrl_inw(0xa0000000); -} - -unsigned char adx_inb(unsigned long port) -{ - return *(volatile unsigned char*)PORT2ADDR(port); -} - -unsigned short adx_inw(unsigned long port) -{ - return *(volatile unsigned short*)PORT2ADDR(port); -} - -unsigned int adx_inl(unsigned long port) -{ - return *(volatile unsigned long*)PORT2ADDR(port); -} - -unsigned char adx_inb_p(unsigned long port) -{ - unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); - - delay(); - return v; -} - -unsigned short adx_inw_p(unsigned long port) -{ - unsigned long v = *(volatile unsigned short*)PORT2ADDR(port); - - delay(); - return v; -} - -unsigned int adx_inl_p(unsigned long port) -{ - unsigned long v = *(volatile unsigned long*)PORT2ADDR(port); - - delay(); - return v; -} - -void adx_insb(unsigned long port, void *buffer, unsigned long count) -{ - unsigned char *buf = buffer; - while(count--) *buf++ = inb(port); -} - -void adx_insw(unsigned long port, void *buffer, unsigned long count) -{ - unsigned short *buf = buffer; - while(count--) *buf++ = inw(port); -} - -void adx_insl(unsigned long port, void *buffer, unsigned long count) -{ - unsigned long *buf = buffer; - while(count--) *buf++ = inl(port); -} - -void adx_outb(unsigned char b, unsigned long port) -{ - *(volatile unsigned char*)PORT2ADDR(port) = b; -} - -void adx_outw(unsigned short b, unsigned long port) -{ - *(volatile unsigned short*)PORT2ADDR(port) = b; -} - -void adx_outl(unsigned int b, unsigned long port) -{ - *(volatile unsigned long*)PORT2ADDR(port) = b; -} - -void adx_outb_p(unsigned char b, unsigned long port) -{ - *(volatile unsigned char*)PORT2ADDR(port) = b; - delay(); -} - -void adx_outw_p(unsigned short b, unsigned long port) -{ - *(volatile unsigned short*)PORT2ADDR(port) = b; - delay(); -} - -void adx_outl_p(unsigned int b, unsigned long port) -{ - *(volatile unsigned long*)PORT2ADDR(port) = b; - delay(); -} - -void adx_outsb(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned char *buf = buffer; - while(count--) outb(*buf++, port); -} - -void adx_outsw(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned short *buf = buffer; - while(count--) outw(*buf++, port); -} - -void adx_outsl(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned long *buf = buffer; - while(count--) outl(*buf++, port); -} - -unsigned char adx_readb(unsigned long addr) -{ - return *(volatile unsigned char*)addr; -} - -unsigned short adx_readw(unsigned long addr) -{ - return *(volatile unsigned short*)addr; -} - -unsigned int adx_readl(unsigned long addr) -{ - return *(volatile unsigned long*)addr; -} - -void adx_writeb(unsigned char b, unsigned long addr) -{ - *(volatile unsigned char*)addr = b; -} - -void adx_writew(unsigned short b, unsigned long addr) -{ - *(volatile unsigned short*)addr = b; -} - -void adx_writel(unsigned int b, unsigned long addr) -{ - *(volatile unsigned long*)addr = b; -} - -void *adx_ioremap(unsigned long offset, unsigned long size) -{ - return (void *)P2SEGADDR(offset); -} - -EXPORT_SYMBOL (adx_ioremap); - -void adx_iounmap(void *addr) -{ -} - -EXPORT_SYMBOL(adx_iounmap); - -#include -extern void *cf_io_base; - -unsigned long adx_isa_port2addr(unsigned long offset) -{ - /* CompactFlash (IDE) */ - if (((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset == 0x3f6)) { - return (unsigned long)cf_io_base + offset; - } - - /* eth0 */ - if ((offset >= 0x300) && (offset <= 0x30f)) { - return 0xa5000000 + offset; /* COMM BOARD (AREA1) */ - } - - return offset + 0xb0000000; /* IOBUS (AREA 4)*/ -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/io_bigsur.c linux-2.5.71/arch/sh/kernel/io_bigsur.c --- linux-2.5.70-bk19/arch/sh/kernel/io_bigsur.c 2003-05-26 18:00:41.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/io_bigsur.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,249 +0,0 @@ -/* - * include/asm-sh/io_bigsur.c - * - * By Dustin McIntire (dustin@sensoria.com) (c)2001 - * Derived from io_hd64465.h, which bore the message: - * By Greg Banks - * (c) 2000 PocketPenguins Inc. - * and from io_hd64461.h, which bore the message: - * Copyright 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * IO functions for a Hitachi Big Sur Evaluation Board. - */ - -#include -#include -#include -#include -#include -#include - -//#define BIGSUR_DEBUG 2 -#undef BIGSUR_DEBUG - -#ifdef BIGSUR_DEBUG -#define DPRINTK(args...) printk(args) -#define DIPRINTK(n, args...) if (BIGSUR_DEBUG>(n)) printk(args) -#else -#define DPRINTK(args...) -#define DIPRINTK(n, args...) -#endif - - -/* Low iomap maps port 0-1K to addresses in 8byte chunks */ -#define BIGSUR_IOMAP_LO_THRESH 0x400 -#define BIGSUR_IOMAP_LO_SHIFT 3 -#define BIGSUR_IOMAP_LO_MASK ((1<>BIGSUR_IOMAP_LO_SHIFT) -static u32 bigsur_iomap_lo[BIGSUR_IOMAP_LO_NMAP]; -static u8 bigsur_iomap_lo_shift[BIGSUR_IOMAP_LO_NMAP]; - -/* High iomap maps port 1K-64K to addresses in 1K chunks */ -#define BIGSUR_IOMAP_HI_THRESH 0x10000 -#define BIGSUR_IOMAP_HI_SHIFT 10 -#define BIGSUR_IOMAP_HI_MASK ((1<>BIGSUR_IOMAP_HI_SHIFT) -static u32 bigsur_iomap_hi[BIGSUR_IOMAP_HI_NMAP]; -static u8 bigsur_iomap_hi_shift[BIGSUR_IOMAP_HI_NMAP]; - -#ifndef MAX -#define MAX(a,b) ((a)>(b)?(a):(b)) -#endif - -#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x)) - -void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift) -{ - u32 port, endport = baseport + nports; - - DPRINTK("bigsur_port_map(base=0x%0x, n=0x%0x, addr=0x%08x)\n", - baseport, nports, addr); - - for (port = baseport ; - port < endport && port < BIGSUR_IOMAP_LO_THRESH ; - port += (1<>BIGSUR_IOMAP_LO_SHIFT] = addr; - bigsur_iomap_lo_shift[port>>BIGSUR_IOMAP_LO_SHIFT] = shift; - addr += (1<<(BIGSUR_IOMAP_LO_SHIFT)); - } - - for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ; - port < endport && port < BIGSUR_IOMAP_HI_THRESH ; - port += (1<>BIGSUR_IOMAP_HI_SHIFT] = addr; - bigsur_iomap_hi_shift[port>>BIGSUR_IOMAP_HI_SHIFT] = shift; - addr += (1<<(BIGSUR_IOMAP_HI_SHIFT)); - } -} -EXPORT_SYMBOL(bigsur_port_map); - -void bigsur_port_unmap(u32 baseport, u32 nports) -{ - u32 port, endport = baseport + nports; - - DPRINTK("bigsur_port_unmap(base=0x%0x, n=0x%0x)\n", baseport, nports); - - for (port = baseport ; - port < endport && port < BIGSUR_IOMAP_LO_THRESH ; - port += (1<>BIGSUR_IOMAP_LO_SHIFT] = 0; - } - - for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ; - port < endport && port < BIGSUR_IOMAP_HI_THRESH ; - port += (1<>BIGSUR_IOMAP_HI_SHIFT] = 0; - } -} -EXPORT_SYMBOL(bigsur_port_unmap); - -unsigned long bigsur_isa_port2addr(unsigned long port) -{ - unsigned long addr = 0; - unsigned char shift; - - /* Physical address not in P0, do nothing */ - if (PXSEG(port)) addr = port; - /* physical address in P0, map to P2 */ - else if (port >= 0x30000) - addr = P2SEGADDR(port); - /* Big Sur I/O + HD64465 registers 0x10000-0x30000 */ - else if (port >= BIGSUR_IOMAP_HI_THRESH) - addr = BIGSUR_INTERNAL_BASE + (port - BIGSUR_IOMAP_HI_THRESH); - /* Handle remapping of high IO/PCI IO ports */ - else if (port >= BIGSUR_IOMAP_LO_THRESH) { - addr = bigsur_iomap_hi[port >> BIGSUR_IOMAP_HI_SHIFT]; - shift = bigsur_iomap_hi_shift[port >> BIGSUR_IOMAP_HI_SHIFT]; - if (addr != 0) - addr += (port & BIGSUR_IOMAP_HI_MASK) << shift; - } - /* Handle remapping of low IO ports */ - else { - addr = bigsur_iomap_lo[port >> BIGSUR_IOMAP_LO_SHIFT]; - shift = bigsur_iomap_lo_shift[port >> BIGSUR_IOMAP_LO_SHIFT]; - if (addr != 0) - addr += (port & BIGSUR_IOMAP_LO_MASK) << shift; - } - - DIPRINTK(2, "PORT2ADDR(0x%08lx) = 0x%08lx\n", port, addr); - - return addr; -} - -static inline void delay(void) -{ - ctrl_inw(0xa0000000); -} - -unsigned char bigsur_inb(unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - unsigned long b = (addr == 0 ? 0 : *(volatile unsigned char*)addr); - - DIPRINTK(0, "inb(%08lx) = %02x\n", addr, (unsigned)b); - return b; -} - -unsigned char bigsur_inb_p(unsigned long port) -{ - unsigned long v; - unsigned long addr = PORT2ADDR(port); - - v = (addr == 0 ? 0 : *(volatile unsigned char*)addr); - delay(); - DIPRINTK(0, "inb_p(%08lx) = %02x\n", addr, (unsigned)v); - return v; -} - -unsigned short bigsur_inw(unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - unsigned long b = (addr == 0 ? 0 : *(volatile unsigned short*)addr); - DIPRINTK(0, "inw(%08lx) = %04lx\n", addr, b); - return b; -} - -unsigned int bigsur_inl(unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - unsigned int b = (addr == 0 ? 0 : *(volatile unsigned long*)addr); - DIPRINTK(0, "inl(%08lx) = %08x\n", addr, b); - return b; -} - -void bigsur_insb(unsigned long port, void *buffer, unsigned long count) -{ - unsigned char *buf=buffer; - while(count--) *buf++=inb(port); -} - -void bigsur_insw(unsigned long port, void *buffer, unsigned long count) -{ - unsigned short *buf=buffer; - while(count--) *buf++=inw(port); -} - -void bigsur_insl(unsigned long port, void *buffer, unsigned long count) -{ - unsigned long *buf=buffer; - while(count--) *buf++=inl(port); -} - -void bigsur_outb(unsigned char b, unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - - DIPRINTK(0, "outb(%02x, %08lx)\n", (unsigned)b, addr); - if (addr != 0) - *(volatile unsigned char*)addr = b; -} - -void bigsur_outb_p(unsigned char b, unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - - DIPRINTK(0, "outb_p(%02x, %08lx)\n", (unsigned)b, addr); - if (addr != 0) - *(volatile unsigned char*)addr = b; - delay(); -} - -void bigsur_outw(unsigned short b, unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - DIPRINTK(0, "outw(%04x, %08lx)\n", (unsigned)b, addr); - if (addr != 0) - *(volatile unsigned short*)addr = b; -} - -void bigsur_outl(unsigned int b, unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - DIPRINTK(0, "outl(%08x, %08lx)\n", b, addr); - if (addr != 0) - *(volatile unsigned long*)addr = b; -} - -void bigsur_outsb(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned char *buf=buffer; - while(count--) outb(*buf++, port); -} - -void bigsur_outsw(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned short *buf=buffer; - while(count--) outw(*buf++, port); -} - -void bigsur_outsl(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned long *buf=buffer; - while(count--) outl(*buf++, port); -} - diff -urN linux-2.5.70-bk19/arch/sh/kernel/io_cat68701.c linux-2.5.71/arch/sh/kernel/io_cat68701.c --- linux-2.5.70-bk19/arch/sh/kernel/io_cat68701.c 2003-05-26 18:00:24.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/io_cat68701.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,249 +0,0 @@ -/* - * linux/arch/sh/kernel/io_cat68701.c - * - * Copyright (C) 2000 Niibe Yutaka - * 2001 Yutaro Ebihara - * - * I/O routine and setup routines for A-ONE Corp CAT-68701 SH7708 Board - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - */ - -#include -#include -#include -#include - -#define SH3_PCMCIA_BUG_WORKAROUND 1 -#define DUMMY_READ_AREA6 0xba000000 - -#define PORT2ADDR(x) (cat68701_isa_port2addr(x)) - -static inline void delay(void) -{ - ctrl_inw(0xa0000000); -} - -unsigned char cat68701_inb(unsigned long port) -{ - return *(volatile unsigned char*)PORT2ADDR(port); -} - -unsigned short cat68701_inw(unsigned long port) -{ - return *(volatile unsigned short*)PORT2ADDR(port); -} - -unsigned int cat68701_inl(unsigned long port) -{ - return *(volatile unsigned long*)PORT2ADDR(port); -} - -unsigned char cat68701_inb_p(unsigned long port) -{ - unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); - - delay(); - return v; -} - -unsigned short cat68701_inw_p(unsigned long port) -{ - unsigned long v = *(volatile unsigned short*)PORT2ADDR(port); - - delay(); - return v; -} - -unsigned int cat68701_inl_p(unsigned long port) -{ - unsigned long v = *(volatile unsigned long*)PORT2ADDR(port); - - delay(); - return v; -} - -void cat68701_insb(unsigned long port, void *buffer, unsigned long count) -{ - unsigned char *buf=buffer; - while(count--) *buf++=inb(port); -} - -void cat68701_insw(unsigned long port, void *buffer, unsigned long count) -{ - unsigned short *buf=buffer; - while(count--) *buf++=inw(port); -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif -} - -void cat68701_insl(unsigned long port, void *buffer, unsigned long count) -{ - unsigned long *buf=buffer; - while(count--) *buf++=inl(port); -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif -} - -void cat68701_outb(unsigned char b, unsigned long port) -{ - *(volatile unsigned char*)PORT2ADDR(port) = b; -} - -void cat68701_outw(unsigned short b, unsigned long port) -{ - *(volatile unsigned short*)PORT2ADDR(port) = b; -} - -void cat68701_outl(unsigned int b, unsigned long port) -{ - *(volatile unsigned long*)PORT2ADDR(port) = b; -} - -void cat68701_outb_p(unsigned char b, unsigned long port) -{ - *(volatile unsigned char*)PORT2ADDR(port) = b; - delay(); -} - -void cat68701_outw_p(unsigned short b, unsigned long port) -{ - *(volatile unsigned short*)PORT2ADDR(port) = b; - delay(); -} - -void cat68701_outl_p(unsigned int b, unsigned long port) -{ - *(volatile unsigned long*)PORT2ADDR(port) = b; - delay(); -} - -void cat68701_outsb(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned char *buf=buffer; - while(count--) outb(*buf++, port); -} - -void cat68701_outsw(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned short *buf=buffer; - while(count--) outw(*buf++, port); -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif -} - -void cat68701_outsl(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned long *buf=buffer; - while(count--) outl(*buf++, port); -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif -} - -unsigned char cat68701_readb(unsigned long addr) -{ - return *(volatile unsigned char*)addr; -} - -unsigned short cat68701_readw(unsigned long addr) -{ - return *(volatile unsigned short*)addr; -} - -unsigned int cat68701_readl(unsigned long addr) -{ - return *(volatile unsigned long*)addr; -} - -void cat68701_writeb(unsigned char b, unsigned long addr) -{ - *(volatile unsigned char*)addr = b; -} - -void cat68701_writew(unsigned short b, unsigned long addr) -{ - *(volatile unsigned short*)addr = b; -} - -void cat68701_writel(unsigned int b, unsigned long addr) -{ - *(volatile unsigned long*)addr = b; -} - -void * cat68701_ioremap(unsigned long offset, unsigned long size) -{ - return (void *) P2SEGADDR(offset); -} -EXPORT_SYMBOL(cat68701_ioremap); - -void cat68701_iounmap(void *addr) -{ -} -EXPORT_SYMBOL(cat68701_iounmap); - -unsigned long cat68701_isa_port2addr(unsigned long offset) -{ - /* CompactFlash (IDE) */ - if(((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset==0x3f6)) - return 0xba000000 + offset; - - /* INPUT PORT */ - if((offset >= 0x3fc) && (offset <= 0x3fd)) - return 0xb4007000 + offset; - - /* OUTPUT PORT */ - if((offset >= 0x3fe) && (offset <= 0x3ff)) - return 0xb4007400 + offset; - - return offset + 0xb4000000; /* other I/O (EREA 5)*/ -} - - -int cat68701_irq_demux(int irq) -{ - if(irq==13) return 14; - if(irq==7) return 10; - return irq; -} - - - -/*-------------------------------------------------------*/ - -void setup_cat68701(){ - /* dummy read erea5 (CS8900A) */ -} - -void init_cat68701_IRQ(){ - make_imask_irq(10); - make_imask_irq(14); -} - -#ifdef CONFIG_HEARTBEAT -#include -void heartbeat_cat68701() -{ - static unsigned int cnt = 0, period = 0 , bit = 0; - cnt += 1; - if (cnt < period) { - return; - } - cnt = 0; - - /* Go through the points (roughly!): - * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110 - */ - period = 110 - ( (300< -#include - -unsigned long dreamcast_isa_port2addr(unsigned long offset) -{ - return offset + 0xa0000000; -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/io_ec3104.c linux-2.5.71/arch/sh/kernel/io_ec3104.c --- linux-2.5.70-bk19/arch/sh/kernel/io_ec3104.c 2003-05-26 18:00:37.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/io_ec3104.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,81 +0,0 @@ -/* - * linux/arch/sh/kernel/io_ec3104.c - * EC3104 companion chip support - * - * Copyright (C) 2000 Philipp Rumpf - * - */ -/* EC3104 note: - * This code was written without any documentation about the EC3104 chip. While - * I hope I got most of the basic functionality right, the register names I use - * are most likely completely different from those in the chip documentation. - * - * If you have any further information about the EC3104, please tell me - * (prumpf@tux.org). - */ - -#include -#include -#include -#include -#include - -/* - * EC3104 has a real ISA bus which we redirect low port accesses to (the - * actual device on mine is a ESS 1868, and I don't want to hack the driver - * more than strictly necessary). I am not going to duplicate the - * hard coding of PC addresses (for the 16550s aso) here though; it's just - * too ugly. - */ - -#define low_port(port) ((port) < 0x10000) - -static inline unsigned long port2addr(unsigned long port) -{ - switch(port >> 16) { - case 0: - return EC3104_ISA_BASE + port * 2; - - /* XXX hack. it's unclear what to do about the serial ports */ - case 1: - return EC3104_BASE + (port&0xffff) * 4; - - default: - /* XXX PCMCIA */ - return 0; - } -} - -unsigned char ec3104_inb(unsigned long port) -{ - u8 ret; - - ret = *(volatile u8 *)port2addr(port); - - return ret; -} - -unsigned short ec3104_inw(unsigned long port) -{ - BUG(); -} - -unsigned long ec3104_inl(unsigned long port) -{ - BUG(); -} - -void ec3104_outb(unsigned char data, unsigned long port) -{ - *(volatile u8 *)port2addr(port) = data; -} - -void ec3104_outw(unsigned short data, unsigned long port) -{ - BUG(); -} - -void ec3104_outl(unsigned long data, unsigned long port) -{ - BUG(); -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/io_generic.c linux-2.5.71/arch/sh/kernel/io_generic.c --- linux-2.5.70-bk19/arch/sh/kernel/io_generic.c 2003-05-26 18:00:37.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/io_generic.c 2003-06-14 13:53:23.000000000 -0700 @@ -1,4 +1,4 @@ -/* $Id: io_generic.c,v 1.12 2000/11/14 16:45:11 sugioka Exp $ +/* $Id: io_generic.c,v 1.1.1.1.4.2.2.1 2003/01/10 17:26:56 lethal Exp $ * * linux/arch/sh/kernel/io_generic.c * @@ -17,7 +17,7 @@ #include #include -#if defined(__sh3__) +#if defined(CONFIG_CPU_SH3) /* I'm not sure SH7709 has this kind of bug */ #define SH3_PCMCIA_BUG_WORKAROUND 1 #define DUMMY_READ_AREA6 0xba000000 diff -urN linux-2.5.70-bk19/arch/sh/kernel/io_hd64461.c linux-2.5.71/arch/sh/kernel/io_hd64461.c --- linux-2.5.70-bk19/arch/sh/kernel/io_hd64461.c 2003-05-26 18:00:43.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/io_hd64461.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,136 +0,0 @@ -/* - * $Id: io_hd64461.c,v 1.6 2000/11/16 23:28:44 yaegashi Exp $ - * Copyright (C) 2000 YAEGASHI Takeshi - * Typical I/O routines for HD64461 system. - */ - -#include -#include -#include - -static __inline__ unsigned long PORT2ADDR(unsigned long port) -{ - /* 16550A: HD64461 internal */ - if (0x3f8<=port && port<=0x3ff) - return CONFIG_HD64461_IOBASE + 0x8000 + ((port-0x3f8)<<1); - if (0x2f8<=port && port<=0x2ff) - return CONFIG_HD64461_IOBASE + 0x7000 + ((port-0x2f8)<<1); - -#ifdef CONFIG_HD64461_ENABLER - /* NE2000: HD64461 PCMCIA channel 0 (I/O) */ - if (0x300<=port && port<=0x31f) - return 0xba000000 + port; - - /* ide0: HD64461 PCMCIA channel 1 (memory) */ - /* On HP690, CF in slot 1 is configured as a memory card - device. See CF+ and CompactFlash Specification for the - detail of CF's memory mapped addressing. */ - if (0x1f0<=port && port<=0x1f7) return 0xb5000000 + port; - if (port == 0x3f6) return 0xb50001fe; - if (port == 0x3f7) return 0xb50001ff; - - /* ide1 */ - if (0x170<=port && port<=0x177) return 0xba000000 + port; - if (port == 0x376) return 0xba000376; - if (port == 0x377) return 0xba000377; -#endif - - /* ??? */ - if (port < 0x10000) return 0xa0000000 + port; - - /* HD64461 internal devices (0xb0000000) */ - if (port < 0x20000) return CONFIG_HD64461_IOBASE + port - 0x10000; - - /* PCMCIA channel 0, I/O (0xba000000) */ - if (port < 0x30000) return 0xba000000 + port - 0x20000; - - /* PCMCIA channel 1, memory (0xb5000000) */ - if (port < 0x40000) return 0xb5000000 + port - 0x30000; - - /* Whole physical address space (0xa0000000) */ - return 0xa0000000 + (port & 0x1fffffff); -} - -static inline void delay(void) -{ - ctrl_inw(0xa0000000); -} - -unsigned char hd64461_inb(unsigned long port) -{ - return *(volatile unsigned char*)PORT2ADDR(port); -} - -unsigned char hd64461_inb_p(unsigned long port) -{ - unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); - delay(); - return v; -} - -unsigned short hd64461_inw(unsigned long port) -{ - return *(volatile unsigned short*)PORT2ADDR(port); -} - -unsigned int hd64461_inl(unsigned long port) -{ - return *(volatile unsigned long*)PORT2ADDR(port); -} - -void hd64461_insb(unsigned long port, void *buffer, unsigned long count) -{ - unsigned char *buf=buffer; - while(count--) *buf++=inb(port); -} - -void hd64461_insw(unsigned long port, void *buffer, unsigned long count) -{ - unsigned short *buf=buffer; - while(count--) *buf++=inw(port); -} - -void hd64461_insl(unsigned long port, void *buffer, unsigned long count) -{ - unsigned long *buf=buffer; - while(count--) *buf++=inl(port); -} - -void hd64461_outb(unsigned char b, unsigned long port) -{ - *(volatile unsigned char*)PORT2ADDR(port) = b; -} - -void hd64461_outb_p(unsigned char b, unsigned long port) -{ - *(volatile unsigned char*)PORT2ADDR(port) = b; - delay(); -} - -void hd64461_outw(unsigned short b, unsigned long port) -{ - *(volatile unsigned short*)PORT2ADDR(port) = b; -} - -void hd64461_outl(unsigned int b, unsigned long port) -{ - *(volatile unsigned long*)PORT2ADDR(port) = b; -} - -void hd64461_outsb(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned char *buf=buffer; - while(count--) outb(*buf++, port); -} - -void hd64461_outsw(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned short *buf=buffer; - while(count--) outw(*buf++, port); -} - -void hd64461_outsl(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned long *buf=buffer; - while(count--) outl(*buf++, port); -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/io_hd64465.c linux-2.5.71/arch/sh/kernel/io_hd64465.c --- linux-2.5.70-bk19/arch/sh/kernel/io_hd64465.c 2003-05-26 18:00:25.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/io_hd64465.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,251 +0,0 @@ -/* - * $Id: io_hd64465.c,v 1.7 2001/05/09 07:39:36 gniibe Exp $ - * by Greg Banks - * (c) 2000 PocketPenguins Inc - * - * Derived from io_hd64461.c, which bore the message: - * Copyright (C) 2000 YAEGASHI Takeshi - * - * Typical I/O routines for HD64465 system. - */ - -#include -#include -#include -#include -#include - - -#define HD64465_DEBUG 0 - -#if HD64465_DEBUG -#define DPRINTK(args...) printk(args) -#define DIPRINTK(n, args...) if (hd64465_io_debug>(n)) printk(args) -#else -#define DPRINTK(args...) -#define DIPRINTK(n, args...) -#endif - - - -/* This is a hack suitable only for debugging IO port problems */ -int hd64465_io_debug; -EXPORT_SYMBOL(hd64465_io_debug); - -/* Low iomap maps port 0-1K to addresses in 8byte chunks */ -#define HD64465_IOMAP_LO_THRESH 0x400 -#define HD64465_IOMAP_LO_SHIFT 3 -#define HD64465_IOMAP_LO_MASK ((1<>HD64465_IOMAP_LO_SHIFT) -static unsigned long hd64465_iomap_lo[HD64465_IOMAP_LO_NMAP]; -static unsigned char hd64465_iomap_lo_shift[HD64465_IOMAP_LO_NMAP]; - -/* High iomap maps port 1K-64K to addresses in 1K chunks */ -#define HD64465_IOMAP_HI_THRESH 0x10000 -#define HD64465_IOMAP_HI_SHIFT 10 -#define HD64465_IOMAP_HI_MASK ((1<>HD64465_IOMAP_HI_SHIFT) -static unsigned long hd64465_iomap_hi[HD64465_IOMAP_HI_NMAP]; -static unsigned char hd64465_iomap_hi_shift[HD64465_IOMAP_HI_NMAP]; - -#ifndef MAX -#define MAX(a,b) ((a)>(b)?(a):(b)) -#endif - -#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x)) - -void hd64465_port_map(unsigned short baseport, unsigned int nports, - unsigned long addr, unsigned char shift) -{ - unsigned int port, endport = baseport + nports; - - DPRINTK("hd64465_port_map(base=0x%04hx, n=0x%04hx, addr=0x%08lx,endport=0x%04x)\n", - baseport, nports, addr,endport); - - for (port = baseport ; - port < endport && port < HD64465_IOMAP_LO_THRESH ; - port += (1<>HD64465_IOMAP_LO_SHIFT] = addr; - hd64465_iomap_lo_shift[port>>HD64465_IOMAP_LO_SHIFT] = shift; - addr += (1<<(HD64465_IOMAP_LO_SHIFT)); - } - - for (port = MAX(baseport, HD64465_IOMAP_LO_THRESH) ; - port < endport && port < HD64465_IOMAP_HI_THRESH ; - port += (1<>HD64465_IOMAP_HI_SHIFT] = addr; - hd64465_iomap_hi_shift[port>>HD64465_IOMAP_HI_SHIFT] = shift; - addr += (1<<(HD64465_IOMAP_HI_SHIFT)); - } -} -EXPORT_SYMBOL(hd64465_port_map); - -void hd64465_port_unmap(unsigned short baseport, unsigned int nports) -{ - unsigned int port, endport = baseport + nports; - - DPRINTK("hd64465_port_unmap(base=0x%04hx, n=0x%04hx)\n", - baseport, nports); - - for (port = baseport ; - port < endport && port < HD64465_IOMAP_LO_THRESH ; - port += (1<>HD64465_IOMAP_LO_SHIFT] = 0; - } - - for (port = MAX(baseport, HD64465_IOMAP_LO_THRESH) ; - port < endport && port < HD64465_IOMAP_HI_THRESH ; - port += (1<>HD64465_IOMAP_HI_SHIFT] = 0; - } -} -EXPORT_SYMBOL(hd64465_port_unmap); - -unsigned long hd64465_isa_port2addr(unsigned long port) -{ - unsigned long addr = 0; - unsigned char shift; - - /* handle remapping of low IO ports */ - if (port < HD64465_IOMAP_LO_THRESH) { - addr = hd64465_iomap_lo[port >> HD64465_IOMAP_LO_SHIFT]; - shift = hd64465_iomap_lo_shift[port >> HD64465_IOMAP_LO_SHIFT]; - if (addr != 0) - addr += (port & HD64465_IOMAP_LO_MASK) << shift; - else - printk(KERN_NOTICE "io_hd64465: access to un-mapped port %lx\n", port); - } else if (port < HD64465_IOMAP_HI_THRESH) { - addr = hd64465_iomap_hi[port >> HD64465_IOMAP_HI_SHIFT]; - shift = hd64465_iomap_hi_shift[port >> HD64465_IOMAP_HI_SHIFT]; - if (addr != 0) - addr += (port & HD64465_IOMAP_HI_MASK) << shift; - else - printk(KERN_NOTICE "io_hd64465: access to un-mapped port %lx\n", port); - } - - /* HD64465 internal devices (0xb0000000) */ - else if (port < 0x20000) - addr = CONFIG_HD64465_IOBASE + port - 0x10000; - - /* Whole physical address space (0xa0000000) */ - else - addr = P2SEGADDR(port); - - DIPRINTK(2, "PORT2ADDR(0x%08lx) = 0x%08lx\n", port, addr); - - return addr; -} - -static inline void delay(void) -{ - ctrl_inw(0xa0000000); -} - -unsigned char hd64465_inb(unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - unsigned long b = (addr == 0 ? 0 : *(volatile unsigned char*)addr); - - DIPRINTK(0, "inb(%08lx) = %02x\n", addr, (unsigned)b); - return b; -} - -unsigned char hd64465_inb_p(unsigned long port) -{ - unsigned long v; - unsigned long addr = PORT2ADDR(port); - - v = (addr == 0 ? 0 : *(volatile unsigned char*)addr); - delay(); - DIPRINTK(0, "inb_p(%08lx) = %02x\n", addr, (unsigned)v); - return v; -} - -unsigned short hd64465_inw(unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - unsigned long b = (addr == 0 ? 0 : *(volatile unsigned short*)addr); - DIPRINTK(0, "inw(%08lx) = %04lx\n", addr, b); - return b; -} - -unsigned int hd64465_inl(unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - unsigned int b = (addr == 0 ? 0 : *(volatile unsigned long*)addr); - DIPRINTK(0, "inl(%08lx) = %08x\n", addr, b); - return b; -} - -void hd64465_insb(unsigned long port, void *buffer, unsigned long count) -{ - unsigned char *buf=buffer; - while(count--) *buf++=inb(port); -} - -void hd64465_insw(unsigned long port, void *buffer, unsigned long count) -{ - unsigned short *buf=buffer; - while(count--) *buf++=inw(port); -} - -void hd64465_insl(unsigned long port, void *buffer, unsigned long count) -{ - unsigned long *buf=buffer; - while(count--) *buf++=inl(port); -} - -void hd64465_outb(unsigned char b, unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - - DIPRINTK(0, "outb(%02x, %08lx)\n", (unsigned)b, addr); - if (addr != 0) - *(volatile unsigned char*)addr = b; -} - -void hd64465_outb_p(unsigned char b, unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - - DIPRINTK(0, "outb_p(%02x, %08lx)\n", (unsigned)b, addr); - if (addr != 0) - *(volatile unsigned char*)addr = b; - delay(); -} - -void hd64465_outw(unsigned short b, unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - DIPRINTK(0, "outw(%04x, %08lx)\n", (unsigned)b, addr); - if (addr != 0) - *(volatile unsigned short*)addr = b; -} - -void hd64465_outl(unsigned int b, unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - DIPRINTK(0, "outl(%08x, %08lx)\n", b, addr); - if (addr != 0) - *(volatile unsigned long*)addr = b; -} - -void hd64465_outsb(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned char *buf=buffer; - while(count--) outb(*buf++, port); -} - -void hd64465_outsw(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned short *buf=buffer; - while(count--) outw(*buf++, port); -} - -void hd64465_outsl(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned long *buf=buffer; - while(count--) outl(*buf++, port); -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/io_se.c linux-2.5.71/arch/sh/kernel/io_se.c --- linux-2.5.70-bk19/arch/sh/kernel/io_se.c 2003-05-26 18:00:20.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/io_se.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,252 +0,0 @@ -/* $Id: io_se.c,v 1.12 2001/08/11 01:23:28 jzs Exp $ - * - * linux/arch/sh/kernel/io_se.c - * - * Copyright (C) 2000 Kazumoto Kojima - * - * I/O routine for Hitachi SolutionEngine. - * - */ - -#include -#include -#include -#include - -/* SH pcmcia io window base, start and end. */ -int sh_pcic_io_wbase = 0xb8400000; -int sh_pcic_io_start; -int sh_pcic_io_stop; -int sh_pcic_io_type; -int sh_pcic_io_dummy; - -static inline void delay(void) -{ - ctrl_inw(0xa0000000); -} - -/* MS7750 requires special versions of in*, out* routines, since - PC-like io ports are located at upper half byte of 16-bit word which - can be accessed only with 16-bit wide. */ - -static inline volatile __u16 * -port2adr(unsigned int port) -{ - if (port >= 0x2000) - return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000)); - else if (port >= 0x1000) - return (volatile __u16 *) (PA_83902 + (port << 1)); - else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) - return (volatile __u16 *) (sh_pcic_io_wbase + (port &~ 1)); - else - return (volatile __u16 *) (PA_SUPERIO + (port << 1)); -} - -static inline int -shifted_port(unsigned long port) -{ - /* For IDE registers, value is not shifted */ - if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6) - return 0; - else - return 1; -} - -#define maybebadio(name,port) \ - printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \ - #name, (port), (__u32) __builtin_return_address(0)) - -unsigned char se_inb(unsigned long port) -{ - if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) - return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); - else if (shifted_port(port)) - return (*port2adr(port) >> 8); - else - return (*port2adr(port))&0xff; -} - -unsigned char se_inb_p(unsigned long port) -{ - unsigned long v; - - if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) - v = *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); - else if (shifted_port(port)) - v = (*port2adr(port) >> 8); - else - v = (*port2adr(port))&0xff; - delay(); - return v; -} - -unsigned short se_inw(unsigned long port) -{ - if (port >= 0x2000 || - (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)) - return *port2adr(port); - else - maybebadio(inw, port); - return 0; -} - -unsigned int se_inl(unsigned long port) -{ - maybebadio(inl, port); - return 0; -} - -void se_outb(unsigned char value, unsigned long port) -{ - if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) - *(__u8 *)(sh_pcic_io_wbase + port) = value; - else if (shifted_port(port)) - *(port2adr(port)) = value << 8; - else - *(port2adr(port)) = value; -} - -void se_outb_p(unsigned char value, unsigned long port) -{ - if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) - *(__u8 *)(sh_pcic_io_wbase + port) = value; - else if (shifted_port(port)) - *(port2adr(port)) = value << 8; - else - *(port2adr(port)) = value; - delay(); -} - -void se_outw(unsigned short value, unsigned long port) -{ - if (port >= 0x2000 || - (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)) - *port2adr(port) = value; - else - maybebadio(outw, port); -} - -void se_outl(unsigned int value, unsigned long port) -{ - maybebadio(outl, port); -} - -void se_insb(unsigned long port, void *addr, unsigned long count) -{ - volatile __u16 *p = port2adr(port); - - if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) { - volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port); - while (count--) - *((__u8 *) addr)++ = *bp; - } else if (shifted_port(port)) { - while (count--) - *((__u8 *) addr)++ = *p >> 8; - } else { - while (count--) - *((__u8 *) addr)++ = *p; - } -} - -void se_insw(unsigned long port, void *addr, unsigned long count) -{ - volatile __u16 *p = port2adr(port); - while (count--) - *((__u16 *) addr)++ = *p; -} - -void se_insl(unsigned long port, void *addr, unsigned long count) -{ - maybebadio(insl, port); -} - -void se_outsb(unsigned long port, const void *addr, unsigned long count) -{ - volatile __u16 *p = port2adr(port); - - if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) { - volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + port); - while (count--) - *bp = *((__u8 *) addr)++; - } else if (shifted_port(port)) { - while (count--) - *p = *((__u8 *) addr)++ << 8; - } else { - while (count--) - *p = *((__u8 *) addr)++; - } -} - -void se_outsw(unsigned long port, const void *addr, unsigned long count) -{ - volatile __u16 *p = port2adr(port); - while (count--) - *p = *((__u16 *) addr)++; -} - -void se_outsl(unsigned long port, const void *addr, unsigned long count) -{ - maybebadio(outsw, port); -} - -unsigned char se_readb(unsigned long addr) -{ - return *(volatile unsigned char*)addr; -} - -unsigned short se_readw(unsigned long addr) -{ - return *(volatile unsigned short*)addr; -} - -unsigned int se_readl(unsigned long addr) -{ - return *(volatile unsigned long*)addr; -} - -void se_writeb(unsigned char b, unsigned long addr) -{ - *(volatile unsigned char*)addr = b; -} - -void se_writew(unsigned short b, unsigned long addr) -{ - *(volatile unsigned short*)addr = b; -} - -void se_writel(unsigned int b, unsigned long addr) -{ - *(volatile unsigned long*)addr = b; -} - -/* Map ISA bus address to the real address. Only for PCMCIA. */ - -/* ISA page descriptor. */ -static __u32 sh_isa_memmap[256]; - -static int -sh_isa_mmap(__u32 start, __u32 length, __u32 offset) -{ - int idx; - - if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000)) - return -1; - - idx = start >> 12; - sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff); -#if 0 - printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n", - start, length, offset, idx, sh_isa_memmap[idx]); -#endif - return 0; -} - -unsigned long -se_isa_port2addr(unsigned long offset) -{ - int idx; - - idx = (offset >> 12) & 0xff; - offset &= 0xfff; - return sh_isa_memmap[idx] + offset; -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/io_sh2000.c linux-2.5.71/arch/sh/kernel/io_sh2000.c --- linux-2.5.70-bk19/arch/sh/kernel/io_sh2000.c 2003-05-26 18:00:23.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/io_sh2000.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,19 +0,0 @@ -/* - * I/O routine for SH-2000 - */ -#include -#include -#include - -#define IDE_OFFSET 0xb6200000 -#define NIC_OFFSET 0xb6000000 -#define EXTBUS_OFFSET 0xba000000 - -unsigned long sh2000_isa_port2addr(unsigned long offset) -{ - if((offset & ~7) == 0x1f0 || offset == 0x3f6) - return IDE_OFFSET + offset; - else if((offset & ~0x1f) == 0x300) - return NIC_OFFSET + offset; - return EXTBUS_OFFSET + offset; -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/io_unknown.c linux-2.5.71/arch/sh/kernel/io_unknown.c --- linux-2.5.70-bk19/arch/sh/kernel/io_unknown.c 2003-05-26 18:00:42.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/io_unknown.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,46 +0,0 @@ -/* - * linux/arch/sh/kernel/io_unknown.c - * - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * I/O routine for unknown hardware. - */ - -static unsigned int unknown_handler(void) -{ - return 0; -} - -#define UNKNOWN_ALIAS(fn) \ - void unknown_##fn(void) __attribute__ ((alias ("unknown_handler"))); - -UNKNOWN_ALIAS(inb) -UNKNOWN_ALIAS(inw) -UNKNOWN_ALIAS(inl) -UNKNOWN_ALIAS(outb) -UNKNOWN_ALIAS(outw) -UNKNOWN_ALIAS(outl) -UNKNOWN_ALIAS(inb_p) -UNKNOWN_ALIAS(inw_p) -UNKNOWN_ALIAS(inl_p) -UNKNOWN_ALIAS(outb_p) -UNKNOWN_ALIAS(outw_p) -UNKNOWN_ALIAS(outl_p) -UNKNOWN_ALIAS(insb) -UNKNOWN_ALIAS(insw) -UNKNOWN_ALIAS(insl) -UNKNOWN_ALIAS(outsb) -UNKNOWN_ALIAS(outsw) -UNKNOWN_ALIAS(outsl) -UNKNOWN_ALIAS(readb) -UNKNOWN_ALIAS(readw) -UNKNOWN_ALIAS(readl) -UNKNOWN_ALIAS(writeb) -UNKNOWN_ALIAS(writew) -UNKNOWN_ALIAS(writel) -UNKNOWN_ALIAS(isa_port2addr) -UNKNOWN_ALIAS(ioremap) -UNKNOWN_ALIAS(iounmap) diff -urN linux-2.5.70-bk19/arch/sh/kernel/irq_imask.c linux-2.5.71/arch/sh/kernel/irq_imask.c --- linux-2.5.70-bk19/arch/sh/kernel/irq_imask.c 2003-05-26 18:00:21.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/irq_imask.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,116 +0,0 @@ -/* $Id: irq_imask.c,v 1.13 2001/07/12 08:13:56 gniibe Exp $ - * - * linux/arch/sh/kernel/irq_imask.c - * - * Copyright (C) 1999, 2000 Niibe Yutaka - * - * Simple interrupt handling using IMASK of SR register. - * - */ - -/* NOTE: Will not work on level 15 */ - - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -/* Bitmap of IRQ masked */ -static unsigned long imask_mask = 0x7fff; -static int interrupt_priority = 0; - -static void enable_imask_irq(unsigned int irq); -static void disable_imask_irq(unsigned int irq); -static void shutdown_imask_irq(unsigned int irq); -static void mask_and_ack_imask(unsigned int); -static void end_imask_irq(unsigned int irq); - -#define IMASK_PRIORITY 15 - -static unsigned int startup_imask_irq(unsigned int irq) -{ - /* Nothing to do */ - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type imask_irq_type = { - "SR.IMASK", - startup_imask_irq, - shutdown_imask_irq, - enable_imask_irq, - disable_imask_irq, - mask_and_ack_imask, - end_imask_irq -}; - -void static inline set_interrupt_registers(int ip) -{ - unsigned long __dummy; - - asm volatile("ldc %2, r6_bank\n\t" - "stc sr, %0\n\t" - "and #0xf0, %0\n\t" - "shlr2 %0\n\t" - "cmp/eq #0x3c, %0\n\t" - "bt/s 1f ! CLI-ed\n\t" - " stc sr, %0\n\t" - "and %1, %0\n\t" - "or %2, %0\n\t" - "ldc %0, sr\n" - "1:" - : "=&z" (__dummy) - : "r" (~0xf0), "r" (ip << 4) - : "t"); -} - -static void disable_imask_irq(unsigned int irq) -{ - clear_bit(irq, &imask_mask); - if (interrupt_priority < IMASK_PRIORITY - irq) - interrupt_priority = IMASK_PRIORITY - irq; - - set_interrupt_registers(interrupt_priority); -} - -static void enable_imask_irq(unsigned int irq) -{ - set_bit(irq, &imask_mask); - interrupt_priority = IMASK_PRIORITY - ffz(imask_mask); - - set_interrupt_registers(interrupt_priority); -} - -static void mask_and_ack_imask(unsigned int irq) -{ - disable_imask_irq(irq); -} - -static void end_imask_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_imask_irq(irq); -} - -static void shutdown_imask_irq(unsigned int irq) -{ - /* Nothing to do */ -} - -void make_imask_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - irq_desc[irq].handler = &imask_irq_type; - enable_irq(irq); -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/irq_intc2.c linux-2.5.71/arch/sh/kernel/irq_intc2.c --- linux-2.5.70-bk19/arch/sh/kernel/irq_intc2.c 2003-05-26 18:00:43.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/irq_intc2.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,127 +0,0 @@ -/* - * linux/arch/sh/kernel/irq_intc2.c - * - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Interrupt handling for INTC2-based IRQ. - * - * These are the "new Hitachi style" interrupts, as present on the - * Hitachi 7751 and the STM ST40 STB1. - */ - -#include -#include -#include - -#include -#include -#include - - -struct intc2_data { - unsigned int addr; /* Address of Interrupt Priority Register */ - int mask; /*Mask to apply */ -}; - - -static struct intc2_data intc2_data[NR_INTC2_IRQS]; - -static void enable_intc2_irq(unsigned int irq); -static void disable_intc2_irq(unsigned int irq); - -/* shutdown is same as "disable" */ -#define shutdown_intc2_irq disable_intc2_irq - -static void mask_and_ack_intc2(unsigned int); -static void end_intc2_irq(unsigned int irq); - -static unsigned int startup_intc2_irq(unsigned int irq) -{ - enable_intc2_irq(irq); - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type intc2_irq_type = { - "INTC2-IRQ", - startup_intc2_irq, - shutdown_intc2_irq, - enable_intc2_irq, - disable_intc2_irq, - mask_and_ack_intc2, - end_intc2_irq -}; - -static void disable_intc2_irq(unsigned int irq) -{ - unsigned addr; - int offset=irq-INTC2_FIRST_IRQ; - unsigned val,flags; - - // Sanity check - if(offset<0 || offset>=NR_INTC2_IRQS) return; - - addr=intc2_data[offset].addr+INTC2_INTMSK_OFFSET; - - save_and_cli(flags); - val=ctrl_inl(addr); - val|=intc2_data[offset].mask; - ctrl_outl(val,addr); - - restore_flags(flags); -} - -static void enable_intc2_irq(unsigned int irq) -{ - int offset=irq-INTC2_FIRST_IRQ; - - // Sanity check - if(offset<0 || offset>=NR_INTC2_IRQS) return; - - ctrl_outl(intc2_data[offset].mask, - intc2_data[offset].addr+INTC2_INTMSKCLR_OFFSET); - -} - -static void mask_and_ack_intc2(unsigned int irq) -{ - disable_intc2_irq(irq); -} - -static void end_intc2_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_intc2_irq(irq); -} - -void make_intc2_irq(unsigned int irq, unsigned int addr, - unsigned int group,int pos, int priority) -{ - int offset=irq-INTC2_FIRST_IRQ; - unsigned flags,val; - - if(offset<0 || offset>=NR_INTC2_IRQS) { - return; - } - - disable_irq_nosync(irq); - /* Fill the data we need */ - intc2_data[offset].addr=addr; - intc2_data[offset].mask=1< -#include -#include - -#include -#include -#include - -struct ipr_data { - unsigned int addr; /* Address of Interrupt Priority Register */ - int shift; /* Shifts of the 16-bit data */ - int priority; /* The priority */ -}; -static struct ipr_data ipr_data[NR_IRQS]; - -static void enable_ipr_irq(unsigned int irq); -static void disable_ipr_irq(unsigned int irq); - -/* shutdown is same as "disable" */ -#define shutdown_ipr_irq disable_ipr_irq - -static void mask_and_ack_ipr(unsigned int); -static void end_ipr_irq(unsigned int irq); - -static unsigned int startup_ipr_irq(unsigned int irq) -{ - enable_ipr_irq(irq); - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type ipr_irq_type = { - "IPR-IRQ", - startup_ipr_irq, - shutdown_ipr_irq, - enable_ipr_irq, - disable_ipr_irq, - mask_and_ack_ipr, - end_ipr_irq -}; - -static void disable_ipr_irq(unsigned int irq) -{ - unsigned long val, flags; - unsigned int addr = ipr_data[irq].addr; - unsigned short mask = 0xffff ^ (0x0f << ipr_data[irq].shift); - - /* Set the priority in IPR to 0 */ - save_and_cli(flags); - val = ctrl_inw(addr); - val &= mask; - ctrl_outw(val, addr); - restore_flags(flags); -} - -static void enable_ipr_irq(unsigned int irq) -{ - unsigned long val, flags; - unsigned int addr = ipr_data[irq].addr; - int priority = ipr_data[irq].priority; - unsigned short value = (priority << ipr_data[irq].shift); - - /* Set priority in IPR back to original value */ - save_and_cli(flags); - val = ctrl_inw(addr); - val |= value; - ctrl_outw(val, addr); - restore_flags(flags); -} - -static void mask_and_ack_ipr(unsigned int irq) -{ - disable_ipr_irq(irq); - -#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) - /* This is needed when we use edge triggered setting */ - /* XXX: Is it really needed? */ - if (IRQ0_IRQ <= irq && irq <= IRQ5_IRQ) { - /* Clear external interrupt request */ - int a = ctrl_inb(INTC_IRR0); - a &= ~(1 << (irq - IRQ0_IRQ)); - ctrl_outb(a, INTC_IRR0); - } -#endif -} - -static void end_ipr_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_ipr_irq(irq); -} - -void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority) -{ - disable_irq_nosync(irq); - ipr_data[irq].addr = addr; - ipr_data[irq].shift = pos*4; /* POSition (0-3) x 4 means shift */ - ipr_data[irq].priority = priority; - - irq_desc[irq].handler = &ipr_irq_type; - disable_ipr_irq(irq); -} - -#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) -static unsigned char pint_map[256]; -static unsigned long portcr_mask = 0; - -static void enable_pint_irq(unsigned int irq); -static void disable_pint_irq(unsigned int irq); - -/* shutdown is same as "disable" */ -#define shutdown_pint_irq disable_pint_irq - -static void mask_and_ack_pint(unsigned int); -static void end_pint_irq(unsigned int irq); - -static unsigned int startup_pint_irq(unsigned int irq) -{ - enable_pint_irq(irq); - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type pint_irq_type = { - "PINT-IRQ", - startup_pint_irq, - shutdown_pint_irq, - enable_pint_irq, - disable_pint_irq, - mask_and_ack_pint, - end_pint_irq -}; - -static void disable_pint_irq(unsigned int irq) -{ - unsigned long val, flags; - - save_and_cli(flags); - val = ctrl_inw(INTC_INTER); - val &= ~(1 << (irq - PINT_IRQ_BASE)); - ctrl_outw(val, INTC_INTER); /* disable PINTn */ - portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2); - restore_flags(flags); -} - -static void enable_pint_irq(unsigned int irq) -{ - unsigned long val, flags; - - save_and_cli(flags); - val = ctrl_inw(INTC_INTER); - val |= 1 << (irq - PINT_IRQ_BASE); - ctrl_outw(val, INTC_INTER); /* enable PINTn */ - portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2; - restore_flags(flags); -} - -static void mask_and_ack_pint(unsigned int irq) -{ - disable_pint_irq(irq); -} - -static void end_pint_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_pint_irq(irq); -} - -void make_pint_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - irq_desc[irq].handler = &pint_irq_type; - disable_pint_irq(irq); -} -#endif - -void __init init_IRQ(void) -{ -#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) - int i; -#endif - - make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY); - make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY); - -#ifdef SCI_ERI_IRQ - make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); - make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); - make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); -#endif - -#ifdef SCIF1_ERI_IRQ - make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); - make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); - make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); - make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); -#endif - -#ifdef SCIF_ERI_IRQ - make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); - make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); - make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); - make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); -#endif - -#ifdef IRDA_ERI_IRQ - make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); - make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); - make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); - make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); -#endif - -#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) - /* - * Initialize the Interrupt Controller (INTC) - * registers to their power on values - */ - - /* - * Enable external irq (INTC IRQ mode). - * You should set corresponding bits of PFC to "00" - * to enable these interrupts. - */ - make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY); - make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY); - make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY); - make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY); - make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY); - make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY); - make_ipr_irq(PINT0_IRQ, PINT0_IPR_ADDR, PINT0_IPR_POS, PINT0_PRIORITY); - make_ipr_irq(PINT8_IRQ, PINT8_IPR_ADDR, PINT8_IPR_POS, PINT8_PRIORITY); - enable_ipr_irq(PINT0_IRQ); - enable_ipr_irq(PINT8_IRQ); - - for(i = 0; i < 16; i++) - make_pint_irq(PINT_IRQ_BASE + i); - for(i = 0; i < 256; i++) - { - if(i & 1) pint_map[i] = 0; - else if(i & 2) pint_map[i] = 1; - else if(i & 4) pint_map[i] = 2; - else if(i & 8) pint_map[i] = 3; - else if(i & 0x10) pint_map[i] = 4; - else if(i & 0x20) pint_map[i] = 5; - else if(i & 0x40) pint_map[i] = 6; - else if(i & 0x80) pint_map[i] = 7; - } -#endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 */ - - /* Perform the machine specific initialisation */ - if (sh_mv.mv_init_irq != NULL) { - sh_mv.mv_init_irq(); - } -} -#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) -int ipr_irq_demux(int irq) -{ - unsigned long creg, dreg, d, sav; - - if(irq == PINT0_IRQ) - { -#if defined(CONFIG_CPU_SUBTYPE_SH7707) - creg = PORT_PACR; - dreg = PORT_PADR; -#else - creg = PORT_PCCR; - dreg = PORT_PCDR; -#endif - sav = ctrl_inw(creg); - ctrl_outw(sav | portcr_mask, creg); - d = (~ctrl_inb(dreg) ^ ctrl_inw(INTC_ICR2)) & ctrl_inw(INTC_INTER) & 0xff; - ctrl_outw(sav, creg); - if(d == 0) return irq; - return PINT_IRQ_BASE + pint_map[d]; - } - else if(irq == PINT8_IRQ) - { -#if defined(CONFIG_CPU_SUBTYPE_SH7707) - creg = PORT_PBCR; - dreg = PORT_PBDR; -#else - creg = PORT_PFCR; - dreg = PORT_PFDR; -#endif - sav = ctrl_inw(creg); - ctrl_outw(sav | (portcr_mask >> 16), creg); - d = (~ctrl_inb(dreg) ^ (ctrl_inw(INTC_ICR2) >> 8)) & (ctrl_inw(INTC_INTER) >> 8) & 0xff; - ctrl_outw(sav, creg); - if(d == 0) return irq; - return PINT_IRQ_BASE + 8 + pint_map[d]; - } - return irq; -} -#endif diff -urN linux-2.5.70-bk19/arch/sh/kernel/irq_maskreg.c linux-2.5.71/arch/sh/kernel/irq_maskreg.c --- linux-2.5.70-bk19/arch/sh/kernel/irq_maskreg.c 2003-05-26 18:00:20.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/irq_maskreg.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,107 +0,0 @@ -/* - * linux/arch/sh/kernel/irq_maskreg.c - * - * Copyright (C) 2001 A&D Co., Ltd. - * - * This file may be copied or modified under the terms of the GNU - * General Public License. See linux/COPYING for more information. - * - * Interrupt handling for Simple external interrupt mask register - * - * This is for the machine which have single 16 bit register - * for masking external IRQ individually. - * Each bit of the register is for masking each interrupt. - */ - -#include -#include -#include -#include - -#include -#include -#include - -/* address of external interrupt mask register - * address must be set prior to use these (maybe in init_XXX_irq()) - * XXX : is it better to use .config than specifying it in code? */ -unsigned short *irq_mask_register = 0; - -/* forward declaration */ -static unsigned int startup_maskreg_irq(unsigned int irq); -static void shutdown_maskreg_irq(unsigned int irq); -static void enable_maskreg_irq(unsigned int irq); -static void disable_maskreg_irq(unsigned int irq); -static void mask_and_ack_maskreg(unsigned int); -static void end_maskreg_irq(unsigned int irq); - -/* hw_interrupt_type */ -static struct hw_interrupt_type maskreg_irq_type = { - " Mask Register", - startup_maskreg_irq, - shutdown_maskreg_irq, - enable_maskreg_irq, - disable_maskreg_irq, - mask_and_ack_maskreg, - end_maskreg_irq -}; - -/* actual implementatin */ -static unsigned int startup_maskreg_irq(unsigned int irq) -{ - enable_maskreg_irq(irq); - return 0; /* never anything pending */ -} - -static void shutdown_maskreg_irq(unsigned int irq) -{ - disable_maskreg_irq(irq); -} - -static void disable_maskreg_irq(unsigned int irq) -{ - if (irq_mask_register) { - unsigned long flags; - unsigned short val, mask = 0x01 << irq; - - /* Set "irq"th bit */ - save_and_cli(flags); - val = ctrl_inw((unsigned long)irq_mask_register); - val |= mask; - ctrl_outw(val, (unsigned long)irq_mask_register); - restore_flags(flags); - } -} - -static void enable_maskreg_irq(unsigned int irq) -{ - if (irq_mask_register) { - unsigned long flags; - unsigned short val, mask = ~(0x01 << irq); - - /* Clear "irq"th bit */ - save_and_cli(flags); - val = ctrl_inw((unsigned long)irq_mask_register); - val &= mask; - ctrl_outw(val, (unsigned long)irq_mask_register); - restore_flags(flags); - } -} - -static void mask_and_ack_maskreg(unsigned int irq) -{ - disable_maskreg_irq(irq); -} - -static void end_maskreg_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_maskreg_irq(irq); -} - -void make_maskreg_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - irq_desc[irq].handler = &maskreg_irq_type; - disable_maskreg_irq(irq); -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/led_7751se.c linux-2.5.71/arch/sh/kernel/led_7751se.c --- linux-2.5.70-bk19/arch/sh/kernel/led_7751se.c 2003-05-26 18:00:58.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/led_7751se.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,68 +0,0 @@ -/* - * linux/arch/sh/kernel/led_se.c - * - * Copyright (C) 2000 Stuart Menefy - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * This file contains Solution Engine specific LED code. - */ - -#include -#include - -static void mach_led(int position, int value) -{ - volatile unsigned short* p = (volatile unsigned short*)PA_LED; - - if (value) { - *p |= (1<<8); - } else { - *p &= ~(1<<8); - } -} - -#ifdef CONFIG_HEARTBEAT - -#include - -/* Cycle the LED's in the clasic Knightrider/Sun pattern */ -void heartbeat_7751se(void) -{ - static unsigned int cnt = 0, period = 0; - volatile unsigned short* p = (volatile unsigned short*)PA_LED; - static unsigned bit = 0, up = 1; - - cnt += 1; - if (cnt < period) { - return; - } - - cnt = 0; - - /* Go through the points (roughly!): - * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110 - */ - period = 110 - ( (300< - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * This file contains Big Sur specific LED code. - */ - -#include -#include -#include - -static void mach_led(int position, int value) -{ - int word; - - word = bigsur_inl(BIGSUR_CSLR); - if (value) { - bigsur_outl(word & ~BIGSUR_LED, BIGSUR_CSLR); - } else { - bigsur_outl(word | BIGSUR_LED, BIGSUR_CSLR); - } -} - -#ifdef CONFIG_HEARTBEAT - -#include - -/* Cycle the LED on/off */ -void heartbeat_bigsur(void) -{ - static unsigned cnt = 0, period = 0, dist = 0; - - if (cnt == 0 || cnt == dist) - mach_led( -1, 1); - else if (cnt == 7 || cnt == dist+7) - mach_led( -1, 0); - - if (++cnt > period) { - cnt = 0; - /* The hyperbolic function below modifies the heartbeat period - * length in dependency of the current (5min) load. It goes - * through the points f(0)=126, f(1)=86, f(5)=51, - * f(inf)->30. */ - period = ((672< - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * This file contains Solution Engine specific LED code. - */ - -#include -#include - -static void mach_led(int position, int value) -{ - volatile unsigned short* p = (volatile unsigned short*)PA_LED; - - if (value) { - *p |= (1<<8); - } else { - *p &= ~(1<<8); - } -} - -#ifdef CONFIG_HEARTBEAT - -#include - -/* Cycle the LED's in the clasic Knightrider/Sun pattern */ -void heartbeat_se(void) -{ - static unsigned int cnt = 0, period = 0; - volatile unsigned short* p = (volatile unsigned short*)PA_LED; - static unsigned bit = 0, up = 1; - - cnt += 1; - if (cnt < period) { - return; - } - - cnt = 0; - - /* Go through the points (roughly!): - * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110 - */ - period = 110 - ( (300< -#include - -#include -#include -#include - -#include - -void heartbeat_7751se(void); -void setup_7751se(void); -void init_7751se_IRQ(void); - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_7751se __initmv = { - .mv_name = "7751 SolutionEngine", - - .mv_nr_irqs = 72, - - .mv_inb = sh7751se_inb, - .mv_inw = sh7751se_inw, - .mv_inl = sh7751se_inl, - .mv_outb = sh7751se_outb, - .mv_outw = sh7751se_outw, - .mv_outl = sh7751se_outl, - - .mv_inb_p = sh7751se_inb_p, - .mv_inw_p = sh7751se_inw, - .mv_inl_p = sh7751se_inl, - .mv_outb_p = sh7751se_outb_p, - .mv_outw_p = sh7751se_outw, - .mv_outl_p = sh7751se_outl, - - .mv_insb = sh7751se_insb, - .mv_insw = sh7751se_insw, - .mv_insl = sh7751se_insl, - .mv_outsb = sh7751se_outsb, - .mv_outsw = sh7751se_outsw, - .mv_outsl = sh7751se_outsl, - - .mv_readb = sh7751se_readb, - .mv_readw = sh7751se_readw, - .mv_readl = sh7751se_readl, - .mv_writeb = sh7751se_writeb, - .mv_writew = sh7751se_writew, - .mv_writel = sh7751se_writel, - - .mv_ioremap = generic_ioremap, - .mv_iounmap = generic_iounmap, - - .mv_isa_port2addr = sh7751se_isa_port2addr, - - .mv_init_arch = setup_7751se, - .mv_init_irq = init_7751se_IRQ, -#ifdef CONFIG_HEARTBEAT - .mv_heartbeat = heartbeat_7751se, -#endif - - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, - - .mv_hw_7751se = 1, -}; -ALIAS_MV(7751se) diff -urN linux-2.5.70-bk19/arch/sh/kernel/mach_adx.c linux-2.5.71/arch/sh/kernel/mach_adx.c --- linux-2.5.70-bk19/arch/sh/kernel/mach_adx.c 2003-05-26 18:00:40.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/mach_adx.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,73 +0,0 @@ -/* - * linux/arch/sh/kernel/mach_adx.c - * - * Copyright (C) 2001 A&D Co., Ltd. - * - * This file may be copied or modified under the terms of the GNU - * General Public License. See linux/COPYING for more information. - * - * Machine vector for the A&D ADX Board - */ - -#include -#include - -#include -#include -#include -#include - -extern void setup_adx(void); -extern void init_adx_IRQ(void); - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_adx __initmv = { - .mv_name = "A&D_ADX", - - .mv_nr_irqs = 48, - - .mv_inb = adx_inb, - .mv_inw = adx_inw, - .mv_inl = adx_inl, - .mv_outb = adx_outb, - .mv_outw = adx_outw, - .mv_outl = adx_outl, - - .mv_inb_p = adx_inb_p, - .mv_inw_p = adx_inw, - .mv_inl_p = adx_inl, - .mv_outb_p = adx_outb_p, - .mv_outw_p = adx_outw, - .mv_outl_p = adx_outl, - - .mv_insb = adx_insb, - .mv_insw = adx_insw, - .mv_insl = adx_insl, - .mv_outsb = adx_outsb, - .mv_outsw = adx_outsw, - .mv_outsl = adx_outsl, - - .mv_readb = adx_readb, - .mv_readw = adx_readw, - .mv_readl = adx_readl, - .mv_writeb = adx_writeb, - .mv_writew = adx_writew, - .mv_writel = adx_writel, - - .mv_ioremap = adx_ioremap, - .mv_iounmap = adx_iounmap, - - .mv_isa_port2addr = adx_isa_port2addr, - - .mv_init_arch = setup_adx, - .mv_init_irq = init_adx_IRQ, - - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, - - .mv_hw_adx = 1, -}; -ALIAS_MV(adx) diff -urN linux-2.5.70-bk19/arch/sh/kernel/mach_bigsur.c linux-2.5.71/arch/sh/kernel/mach_bigsur.c --- linux-2.5.70-bk19/arch/sh/kernel/mach_bigsur.c 2003-05-26 18:00:44.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/mach_bigsur.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,77 +0,0 @@ -/* - * linux/arch/sh/kernel/mach_bigsur.c - * - * By Dustin McIntire (dustin@sensoria.com) (c)2001 - * Derived from mach_se.h, which bore the message: - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Machine vector for the Hitachi Big Sur Evaluation Board - */ - -#include -#include - -#include -#include -#include -#include -#include -#include - -/* - * The Machine Vector - */ -extern void heartbeat_bigsur(void); -extern void setup_bigsur(void); -extern void init_bigsur_IRQ(void); - -struct sh_machine_vector mv_bigsur __initmv = { - .mv_name = "Big Sur", - .mv_nr_irqs = NR_IRQS, // Defined in - .mv_inb = bigsur_inb, - .mv_inw = bigsur_inw, - .mv_inl = bigsur_inl, - .mv_outb = bigsur_outb, - .mv_outw = bigsur_outw, - .mv_outl = bigsur_outl, - - .mv_inb_p = bigsur_inb_p, - .mv_inw_p = bigsur_inw, - .mv_inl_p = bigsur_inl, - .mv_outb_p = bigsur_outb_p, - .mv_outw_p = bigsur_outw, - .mv_outl_p = bigsur_outl, - - .mv_insb = bigsur_insb, - .mv_insw = bigsur_insw, - .mv_insl = bigsur_insl, - .mv_outsb = bigsur_outsb, - .mv_outsw = bigsur_outsw, - .mv_outsl = bigsur_outsl, - - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_ioremap = generic_ioremap, - .mv_iounmap = generic_iounmap, - - .mv_isa_port2addr = bigsur_isa_port2addr, - .mv_irq_demux = bigsur_irq_demux, - - .mv_init_arch = setup_bigsur, - .mv_init_irq = init_bigsur_IRQ, -#ifdef CONFIG_HEARTBEAT - .mv_heartbeat = heartbeat_bigsur, -#endif - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, - -}; -ALIAS_MV(bigsur) diff -urN linux-2.5.70-bk19/arch/sh/kernel/mach_cat68701.c linux-2.5.71/arch/sh/kernel/mach_cat68701.c --- linux-2.5.70-bk19/arch/sh/kernel/mach_cat68701.c 2003-05-26 18:00:59.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/mach_cat68701.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,72 +0,0 @@ -/* - * linux/arch/sh/kernel/mach_cat68701.c - * - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * 2001 Yutaro Ebihara (ebihara@si-linux.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Machine vector for the A-ONE corp. CAT-68701 SH7708 board - */ - -#include -#include - -#include -#include -#include -#include - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_cat68701 __initmv = { - .mv_name = "CAT-68701", - .mv_nr_irqs = 32, - .mv_inb = cat68701_inb, - .mv_inw = cat68701_inw, - .mv_inl = cat68701_inl, - .mv_outb = cat68701_outb, - .mv_outw = cat68701_outw, - .mv_outl = cat68701_outl, - - .mv_inb_p = cat68701_inb_p, - .mv_inw_p = cat68701_inw, - .mv_inl_p = cat68701_inl, - .mv_outb_p = cat68701_outb_p, - .mv_outw_p = cat68701_outw, - .mv_outl_p = cat68701_outl, - - .mv_insb = cat68701_insb, - .mv_insw = cat68701_insw, - .mv_insl = cat68701_insl, - .mv_outsb = cat68701_outsb, - .mv_outsw = cat68701_outsw, - .mv_outsl = cat68701_outsl, - - .mv_readb = cat68701_readb, - .mv_readw = cat68701_readw, - .mv_readl = cat68701_readl, - .mv_writeb = cat68701_writeb, - .mv_writew = cat68701_writew, - .mv_writel = cat68701_writel, - - .mv_ioremap = cat68701_ioremap, - .mv_iounmap = cat68701_iounmap, - - .mv_isa_port2addr = cat68701_isa_port2addr, - .mv_irq_demux = cat68701_irq_demux, - - .mv_init_arch = setup_cat68701, - .mv_init_irq = init_cat68701_IRQ, -#ifdef CONFIG_HEARTBEAT - .mv_heartbeat = heartbeat_cat68701, -#endif - - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, - -}; -ALIAS_MV(cat68701) diff -urN linux-2.5.70-bk19/arch/sh/kernel/mach_dc.c linux-2.5.71/arch/sh/kernel/mach_dc.c --- linux-2.5.70-bk19/arch/sh/kernel/mach_dc.c 2003-05-26 18:00:25.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/mach_dc.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,73 +0,0 @@ -/* - * $Id: mach_dc.c,v 1.5 2001/09/01 14:34:31 mrbrown Exp $ - * SEGA Dreamcast machine vector - */ - -#include -#include -#include - -#include -#include - -#include -#include -#include - -void __init setup_dreamcast(void); -void __init dreamcast_pcibios_init(void); - -/* Custom Dreamcast RTC routines */ -void aica_rtc_gettimeofday(struct timeval *tv); -int aica_rtc_settimeofday(const struct timeval *tv); - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_dreamcast __initmv = { - .mv_name = "dreamcast", - - .mv_nr_irqs = NR_IRQS, - - .mv_inb = generic_inb, - .mv_inw = generic_inw, - .mv_inl = generic_inl, - .mv_outb = generic_outb, - .mv_outw = generic_outw, - .mv_outl = generic_outl, - - .mv_inb_p = generic_inb_p, - .mv_inw_p = generic_inw, - .mv_inl_p = generic_inl, - .mv_outb_p = generic_outb_p, - .mv_outw_p = generic_outw, - .mv_outl_p = generic_outl, - - .mv_insb = generic_insb, - .mv_insw = generic_insw, - .mv_insl = generic_insl, - .mv_outsb = generic_outsb, - .mv_outsw = generic_outsw, - .mv_outsl = generic_outsl, - - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_ioremap = generic_ioremap, - .mv_iounmap = generic_iounmap, - - .mv_init_arch = setup_dreamcast, - .mv_isa_port2addr = dreamcast_isa_port2addr, - .mv_irq_demux = systemasic_irq_demux, - - .mv_rtc_gettimeofday = aica_rtc_gettimeofday, - .mv_rtc_settimeofday = aica_rtc_settimeofday, - - .mv_hw_dreamcast = 1, -}; -ALIAS_MV(dreamcast) diff -urN linux-2.5.70-bk19/arch/sh/kernel/mach_dmida.c linux-2.5.71/arch/sh/kernel/mach_dmida.c --- linux-2.5.70-bk19/arch/sh/kernel/mach_dmida.c 2003-05-26 18:00:24.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/mach_dmida.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,73 +0,0 @@ -/* - * linux/arch/sh/kernel/mach_dmida.c - * - * by Greg Banks - * (c) 2000 PocketPenguins Inc - * - * Derived from mach_hp600.c, which bore the message: - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Machine vector for the DataMyte Industrial Digital Assistant(tm). - * See http://www.dmida.com - * - */ - -#include - -#include -#include -#include - -#include -#include -#include - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_dmida __initmv = { - .mv_name = "DMIDA", - - .mv_nr_irqs = HD64465_IRQ_BASE+HD64465_IRQ_NUM, - - .mv_inb = hd64465_inb, - .mv_inw = hd64465_inw, - .mv_inl = hd64465_inl, - .mv_outb = hd64465_outb, - .mv_outw = hd64465_outw, - .mv_outl = hd64465_outl, - - .mv_inb_p = hd64465_inb_p, - .mv_inw_p = hd64465_inw, - .mv_inl_p = hd64465_inl, - .mv_outb_p = hd64465_outb_p, - .mv_outw_p = hd64465_outw, - .mv_outl_p = hd64465_outl, - - .mv_insb = hd64465_insb, - .mv_insw = hd64465_insw, - .mv_insl = hd64465_insl, - .mv_outsb = hd64465_outsb, - .mv_outsw = hd64465_outsw, - .mv_outsl = hd64465_outsl, - - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_irq_demux = hd64465_irq_demux, - - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, - - .mv_hw_hd64465 = 1, -}; -ALIAS_MV(dmida) - diff -urN linux-2.5.70-bk19/arch/sh/kernel/mach_ec3104.c linux-2.5.71/arch/sh/kernel/mach_ec3104.c --- linux-2.5.70-bk19/arch/sh/kernel/mach_ec3104.c 2003-05-26 18:00:46.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/mach_ec3104.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,69 +0,0 @@ -/* - * linux/arch/sh/kernel/mach_ec3104.c - * EC3104 companion chip support - * - * Copyright (C) 2000 Philipp Rumpf - * - */ -/* EC3104 note: - * This code was written without any documentation about the EC3104 chip. While - * I hope I got most of the basic functionality right, the register names I use - * are most likely completely different from those in the chip documentation. - * - * If you have any further information about the EC3104, please tell me - * (prumpf@tux.org). - */ - -#include - -#include -#include -#include - -#include -#include - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_ec3104 __initmv = { - .mv_name = "EC3104", - - .mv_nr_irqs = 96, - - .mv_inb = ec3104_inb, - .mv_inw = ec3104_inw, - .mv_inl = ec3104_inl, - .mv_outb = ec3104_outb, - .mv_outw = ec3104_outw, - .mv_outl = ec3104_outl, - - .mv_inb_p = generic_inb_p, - .mv_inw_p = generic_inw, - .mv_inl_p = generic_inl, - .mv_outb_p = generic_outb_p, - .mv_outw_p = generic_outw, - .mv_outl_p = generic_outl, - - .mv_insb = generic_insb, - .mv_insw = generic_insw, - .mv_insl = generic_insl, - .mv_outsb = generic_outsb, - .mv_outsw = generic_outsw, - .mv_outsl = generic_outsl, - - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_irq_demux = ec3104_irq_demux, - - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, -}; - -ALIAS_MV(ec3104) diff -urN linux-2.5.70-bk19/arch/sh/kernel/mach_hp600.c linux-2.5.71/arch/sh/kernel/mach_hp600.c --- linux-2.5.70-bk19/arch/sh/kernel/mach_hp600.c 2003-05-26 18:00:41.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/mach_hp600.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,158 +0,0 @@ -/* - * linux/arch/sh/kernel/mach_hp600.c - * - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Machine vector for the HP600 - */ - -#include - -#include -#include -#include - -#include -#include -#include - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_hp620 __initmv = { - .mv_name = "hp620", - - .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM, - - .mv_inb = hd64461_inb, - .mv_inw = hd64461_inw, - .mv_inl = hd64461_inl, - .mv_outb = hd64461_outb, - .mv_outw = hd64461_outw, - .mv_outl = hd64461_outl, - - .mv_inb_p = hd64461_inb_p, - .mv_inw_p = hd64461_inw, - .mv_inl_p = hd64461_inl, - .mv_outb_p = hd64461_outb_p, - .mv_outw_p = hd64461_outw, - .mv_outl_p = hd64461_outl, - - .mv_insb = hd64461_insb, - .mv_insw = hd64461_insw, - .mv_insl = hd64461_insl, - .mv_outsb = hd64461_outsb, - .mv_outsw = hd64461_outsw, - .mv_outsl = hd64461_outsl, - - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_irq_demux = hd64461_irq_demux, - - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, - - .mv_hw_hp600 = 1, - .mv_hw_hp620 = 1, - .mv_hw_hd64461 = 1, -}; -ALIAS_MV(hp620) - - -struct sh_machine_vector mv_hp680 __initmv = { - .mv_name = "hp680", - - .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM, - - .mv_inb = hd64461_inb, - .mv_inw = hd64461_inw, - .mv_inl = hd64461_inl, - .mv_outb = hd64461_outb, - .mv_outw = hd64461_outw, - .mv_outl = hd64461_outl, - - .mv_inb_p = hd64461_inb_p, - .mv_inw_p = hd64461_inw, - .mv_inl_p = hd64461_inl, - .mv_outb_p = hd64461_outb_p, - .mv_outw_p = hd64461_outw, - .mv_outl_p = hd64461_outl, - - .mv_insb = hd64461_insb, - .mv_insw = hd64461_insw, - .mv_insl = hd64461_insl, - .mv_outsb = hd64461_outsb, - .mv_outsw = hd64461_outsw, - .mv_outsl = hd64461_outsl, - - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_irq_demux = hd64461_irq_demux, - - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, - - .mv_hw_hp600 = 1, - .mv_hw_hp680 = 1, - .mv_hw_hd64461 = 1, -}; -ALIAS_MV(hp680) - - -struct sh_machine_vector mv_hp690 __initmv = { - .mv_name = "hp690", - - .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM, - - .mv_inb = hd64461_inb, - .mv_inw = hd64461_inw, - .mv_inl = hd64461_inl, - .mv_outb = hd64461_outb, - .mv_outw = hd64461_outw, - .mv_outl = hd64461_outl, - - .mv_inb_p = hd64461_inb_p, - .mv_inw_p = hd64461_inw, - .mv_inl_p = hd64461_inl, - .mv_outb_p = hd64461_outb_p, - .mv_outw_p = hd64461_outw, - .mv_outl_p = hd64461_outl, - - .mv_insb = hd64461_insb, - .mv_insw = hd64461_insw, - .mv_insl = hd64461_insl, - .mv_outsb = hd64461_outsb, - .mv_outsw = hd64461_outsw, - .mv_outsl = hd64461_outsl, - - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_irq_demux = hd64461_irq_demux, - - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, - - .mv_hw_hp600 = 1, - .mv_hw_hp690 = 1, - .mv_hw_hd64461 = 1, -}; -ALIAS_MV(hp690) diff -urN linux-2.5.70-bk19/arch/sh/kernel/mach_se.c linux-2.5.71/arch/sh/kernel/mach_se.c --- linux-2.5.70-bk19/arch/sh/kernel/mach_se.c 2003-05-26 18:00:56.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/mach_se.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,84 +0,0 @@ -/* - * linux/arch/sh/kernel/mach_se.c - * - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Machine vector for the Hitachi SolutionEngine - */ - -#include -#include - -#include -#include -#include - -#include - -void heartbeat_se(void); -void setup_se(void); -void init_se_IRQ(void); - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_se __initmv = { - .mv_name = "SolutionEngine", - -#if defined(__SH4__) - .mv_nr_irqs = 48, -#elif defined(CONFIG_CPU_SUBTYPE_SH7708) - .mv_nr_irqs = 32, -#elif defined(CONFIG_CPU_SUBTYPE_SH7709) - .mv_nr_irqs = 61, -#endif - - .mv_inb = se_inb, - .mv_inw = se_inw, - .mv_inl = se_inl, - .mv_outb = se_outb, - .mv_outw = se_outw, - .mv_outl = se_outl, - - .mv_inb_p = se_inb_p, - .mv_inw_p = se_inw, - .mv_inl_p = se_inl, - .mv_outb_p = se_outb_p, - .mv_outw_p = se_outw, - .mv_outl_p = se_outl, - - .mv_insb = se_insb, - .mv_insw = se_insw, - .mv_insl = se_insl, - .mv_outsb = se_outsb, - .mv_outsw = se_outsw, - .mv_outsl = se_outsl, - - .mv_readb = se_readb, - .mv_readw = se_readw, - .mv_readl = se_readl, - .mv_writeb = se_writeb, - .mv_writew = se_writew, - .mv_writel = se_writel, - - .mv_ioremap = generic_ioremap, - .mv_iounmap = generic_iounmap, - - .mv_isa_port2addr = se_isa_port2addr, - - .mv_init_arch = setup_se, - .mv_init_irq = init_se_IRQ, -#ifdef CONFIG_HEARTBEAT - .mv_heartbeat = heartbeat_se, -#endif - - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, - - .mv_hw_se = 1, -}; -ALIAS_MV(se) diff -urN linux-2.5.70-bk19/arch/sh/kernel/mach_unknown.c linux-2.5.71/arch/sh/kernel/mach_unknown.c --- linux-2.5.70-bk19/arch/sh/kernel/mach_unknown.c 2003-05-26 18:00:21.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/mach_unknown.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,72 +0,0 @@ -/* - * linux/arch/sh/kernel/mach_unknown.c - * - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Machine specific code for an unknown machine (internal peripherials only) - */ - -#include -#include - -#include -#include - -#include - -#include -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_unknown __initmv = { - .mv_name = "Unknown", - -#if defined(__SH4__) - .mv_nr_irqs = 48, -#elif defined(CONFIG_CPU_SUBTYPE_SH7708) - .mv_nr_irqs = 32, -#elif defined(CONFIG_CPU_SUBTYPE_SH7709) - .mv_nr_irqs = 61, -#endif - - .mv_inb = unknown_inb, - .mv_inw = unknown_inw, - .mv_inl = unknown_inl, - .mv_outb = unknown_outb, - .mv_outw = unknown_outw, - .mv_outl = unknown_outl, - - .mv_inb_p = unknown_inb_p, - .mv_inw_p = unknown_inw_p, - .mv_inl_p = unknown_inl_p, - .mv_outb_p = unknown_outb_p, - .mv_outw_p = unknown_outw_p, - .mv_outl_p = unknown_outl_p, - - .mv_insb = unknown_insb, - .mv_insw = unknown_insw, - .mv_insl = unknown_insl, - .mv_outsb = unknown_outsb, - .mv_outsw = unknown_outsw, - .mv_outsl = unknown_outsl, - - .mv_readb = unknown_readb, - .mv_readw = unknown_readw, - .mv_readl = unknown_readl, - .mv_writeb = unknown_writeb, - .mv_writew = unknown_writew, - .mv_writel = unknown_writel, - - .mv_ioremap = unknown_ioremap, - .mv_iounmap = unknown_iounmap, - - .mv_isa_port2addr = unknown_isa_port2addr, - - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, -}; -ALIAS_MV(unknown) diff -urN linux-2.5.70-bk19/arch/sh/kernel/pci-7751se.c linux-2.5.71/arch/sh/kernel/pci-7751se.c --- linux-2.5.70-bk19/arch/sh/kernel/pci-7751se.c 2003-05-26 18:00:20.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/pci-7751se.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,127 +0,0 @@ -/* - * linux/arch/sh/kernel/pci-7751se.c - * - * Author: Ian DaSilva (idasilva@mvista.com) - * - * Highly leveraged from pci-bigsur.c, written by Dustin McIntire. - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * PCI initialization for the Hitachi SH7751 Solution Engine board (MS7751SE01) - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#define PCIMCR_MRSET_OFF 0xBFFFFFFF -#define PCIMCR_RFSH_OFF 0xFFFFFFFB - -/* - * Only long word accesses of the PCIC's internal local registers and the - * configuration registers from the CPU is supported. - */ -#define PCIC_WRITE(x,v) writel((v), PCI_REG(x)) -#define PCIC_READ(x) readl(PCI_REG(x)) - -/* - * Description: This function sets up and initializes the pcic, sets - * up the BARS, maps the DRAM into the address space etc, etc. - */ -int __init pcibios_init_platform(void) -{ - unsigned long bcr1, wcr1, wcr2, wcr3, mcr; - unsigned short bcr2; - - /* - * Initialize the slave bus controller on the pcic. The values used - * here should not be hardcoded, but they should be taken from the bsc - * on the processor, to make this function as generic as possible. - * (i.e. Another sbc may usr different SDRAM timing settings -- in order - * for the pcic to work, its settings need to be exactly the same.) - */ - bcr1 = (*(volatile unsigned long*)(SH7751_BCR1)); - bcr2 = (*(volatile unsigned short*)(SH7751_BCR2)); - wcr1 = (*(volatile unsigned long*)(SH7751_WCR1)); - wcr2 = (*(volatile unsigned long*)(SH7751_WCR2)); - wcr3 = (*(volatile unsigned long*)(SH7751_WCR3)); - mcr = (*(volatile unsigned long*)(SH7751_MCR)); - - bcr1 = bcr1 | 0x00080000; /* Enable Bit 19, BREQEN */ - (*(volatile unsigned long*)(SH7751_BCR1)) = bcr1; - - bcr1 = bcr1 | 0x40080000; /* Enable Bit 19 BREQEN, set PCIC to slave */ - PCIC_WRITE(SH7751_PCIBCR1, bcr1); /* PCIC BCR1 */ - PCIC_WRITE(SH7751_PCIBCR2, bcr2); /* PCIC BCR2 */ - PCIC_WRITE(SH7751_PCIWCR1, wcr1); /* PCIC WCR1 */ - PCIC_WRITE(SH7751_PCIWCR2, wcr2); /* PCIC WCR2 */ - PCIC_WRITE(SH7751_PCIWCR3, wcr3); /* PCIC WCR3 */ - mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF; - PCIC_WRITE(SH7751_PCIMCR, mcr); /* PCIC MCR */ - - - /* Enable all interrupts, so we know what to fix */ - PCIC_WRITE(SH7751_PCIINTM, 0x0000c3ff); - PCIC_WRITE(SH7751_PCIAINTM, 0x0000380f); - - /* Set up standard PCI config registers */ - PCIC_WRITE(SH7751_PCICONF1, 0xF39000C7); /* Bus Master, Mem & I/O access */ - PCIC_WRITE(SH7751_PCICONF2, 0x00000000); /* PCI Class code & Revision ID */ - PCIC_WRITE(SH7751_PCICONF4, 0xab000001); /* PCI I/O address (local regs) */ - PCIC_WRITE(SH7751_PCICONF5, 0x0c000000); /* PCI MEM address (local RAM) */ - PCIC_WRITE(SH7751_PCICONF6, 0xd0000000); /* PCI MEM address (unused) */ - PCIC_WRITE(SH7751_PCICONF11, 0x35051054); /* PCI Subsystem ID & Vendor ID */ - PCIC_WRITE(SH7751_PCILSR0, 0x03f00000); /* MEM (full 64M exposed) */ - PCIC_WRITE(SH7751_PCILSR1, 0x00000000); /* MEM (unused) */ - PCIC_WRITE(SH7751_PCILAR0, 0x0c000000); /* MEM (direct map from PCI) */ - PCIC_WRITE(SH7751_PCILAR1, 0x00000000); /* MEM (unused) */ - - /* Now turn it on... */ - PCIC_WRITE(SH7751_PCICR, 0xa5000001); - - /* - * Set PCIMBR and PCIIOBR here, assuming a single window - * (16M MEM, 256K IO) is enough. If a larger space is - * needed, the readx/writex and inx/outx functions will - * have to do more (e.g. setting registers for each call). - */ - - /* - * Set the MBR so PCI address is one-to-one with window, - * meaning all calls go straight through... use ifdef to - * catch erroneous assumption. - */ -#if PCIBIOS_MIN_MEM != SH7751_PCI_MEMORY_BASE -#error One-to-one assumption for PCI memory mapping is wrong!?!?!? -#endif - PCIC_WRITE(SH7751_PCIMBR, PCIBIOS_MIN_MEM); - - /* Set IOBR for window containing area specified in pci.h */ - PCIC_WRITE(SH7751_PCIIOBR, (PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK)); - - /* All done, may as well say so... */ - printk("SH7751 PCI: Finished initialization of the PCI controller\n"); - - return 1; -} - -int __init pcibios_map_platform_irq(u8 slot, u8 pin) -{ - switch (slot) { - case 0: return 13; - case 1: return 13; /* AMD Ethernet controller */ - case 2: return -1; - case 3: return -1; - case 4: return -1; - default: - printk("PCI: Bad IRQ mapping request for slot %d\n", slot); - return -1; - } -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/pci-bigsur.c linux-2.5.71/arch/sh/kernel/pci-bigsur.c --- linux-2.5.70-bk19/arch/sh/kernel/pci-bigsur.c 2003-05-26 18:00:46.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/pci-bigsur.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,163 +0,0 @@ -/* - * linux/arch/sh/kernel/pci-bigsur.c - * - * By Dustin McIntire (dustin@sensoria.com) (c)2001 - - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * PCI initialization for the Hitachi Big Sur Evaluation Board - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define PCI_REG(reg) (SH7751_PCIREG_BASE+reg) - -/* - * Initialize the Big Sur PCI interface - * Setup hardware to be Central Funtion - * Copy the BSR regs to the PCI interface - * Setup PCI windows into local RAM - */ -int __init pcibios_init_platform(void) { - u32 reg; - u32 word; - - PCIDBG(1,"PCI: bigsur_pci_init called\n"); - /* Set the BCR's to enable PCI access */ - reg = inl(SH7751_BCR1); - reg |= 0x80000; - outl(reg, SH7751_BCR1); - - /* Setup the host hardware */ - if(inl(PCI_REG(SH7751_PCICONF0)) != - (u32)((SH7751_DEVICE_ID <<16) | (SH7751_VENDOR_ID))) { - printk("PCI: Unkown PCI host bridge.\n"); - return 0; - } - printk("PCI: SH7751 PCI host bridge found.\n"); - - /* Turn the clocks back on (not done in reset)*/ - outl(0, PCI_REG(SH7751_PCICLKR)); - /* Clear Powerdown IRQ's (not done in reset) */ - word = SH7751_PCIPINT_D3 | SH7751_PCIPINT_D0; - outl(word, PCI_REG(SH7751_PCICLKR)); - - /* toggle PCI reset pin */ - word = SH7751_PCICR_PREFIX | SH7751_PCICR_PRST; - outl(word,PCI_REG(SH7751_PCICR)); - /* Wait for a long time... not 1 sec. but long enough */ - mdelay(100); - word = SH7751_PCICR_PREFIX; - outl(word,PCI_REG(SH7751_PCICR)); - - /* set the command/status bits to: - * Wait Cycle Control + Parity Enable + Bus Master + - * Mem space enable - */ - word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER | - SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES; - outl(word, PCI_REG(SH7751_PCICONF1)); - - /* define this host as the host bridge */ - word = SH7751_PCI_HOST_BRIDGE << 24; - outl(word, PCI_REG(SH7751_PCICONF2)); - - /* Set IO and Mem windows to local address - * Make PCI and local address the same for easy 1 to 1 mapping - * Window0 = BIGSUR_LSR0_SIZE @ non-cached CS3 base = SDRAM - * Window1 = BIGSUR_LSR1_SIZE @ cached CS3 base = SDRAM - */ - word = BIGSUR_LSR0_SIZE - 1; - outl(word, PCI_REG(SH7751_PCILSR0)); - word = BIGSUR_LSR1_SIZE - 1; - outl(word, PCI_REG(SH7751_PCILSR1)); - /* Set the values on window 0 PCI config registers */ - word = P2SEGADDR(SH7751_CS3_BASE_ADDR); - outl(word, PCI_REG(SH7751_PCILAR0)); - outl(word, PCI_REG(SH7751_PCICONF5)); - /* Set the values on window 1 PCI config registers */ - word = PHYSADDR(SH7751_CS3_BASE_ADDR); - outl(word, PCI_REG(SH7751_PCILAR1)); - outl(word, PCI_REG(SH7751_PCICONF6)); - - /* Set the local 16MB PCI memory space window to - * the lowest PCI mapped address - */ - word = PCIBIOS_MIN_MEM & SH7751_PCIMBR_MASK; - PCIDBG(2,"PCI: Setting upper bits of Memory window to 0x%x\n", word); - outl(word , PCI_REG(SH7751_PCIMBR)); - - /* Map IO space into PCI IO window - * The IO window is 64K-PCIBIOS_MIN_IO in size - * IO addresses will be translated to the - * PCI IO window base address - */ - PCIDBG(3,"PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n", PCIBIOS_MIN_IO, - (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO); - bigsur_port_map(PCIBIOS_MIN_IO, (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO,0); - - /* Make sure the MSB's of IO window are set to access PCI space correctly */ - word = PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK; - PCIDBG(2,"PCI: Setting upper bits of IO window to 0x%x\n", word); - outl(word, PCI_REG(SH7751_PCIIOBR)); - - /* Set PCI WCRx, BCRx's, copy from BSC locations */ - word = inl(SH7751_BCR1); - /* check BCR for SDRAM in area 3 */ - if(((word >> 3) & 1) == 0) { - printk("PCI: Area 3 is not configured for SDRAM. BCR1=0x%x\n", word); - return 0; - } - outl(word, PCI_REG(SH7751_PCIBCR1)); - word = (u16)inw(SH7751_BCR2); - /* check BCR2 for 32bit SDRAM interface*/ - if(((word >> 6) & 0x3) != 0x3) { - printk("PCI: Area 3 is not 32 bit SDRAM. BCR2=0x%x\n", word); - return 0; - } - outl(word, PCI_REG(SH7751_PCIBCR2)); - /* configure the wait control registers */ - word = inl(SH7751_WCR1); - outl(word, PCI_REG(SH7751_PCIWCR1)); - word = inl(SH7751_WCR2); - outl(word, PCI_REG(SH7751_PCIWCR2)); - word = inl(SH7751_WCR3); - outl(word, PCI_REG(SH7751_PCIWCR3)); - word = inl(SH7751_MCR); - outl(word, PCI_REG(SH7751_PCIMCR)); - - /* NOTE: I'm ignoring the PCI error IRQs for now.. - * TODO: add support for the internal error interrupts and - * DMA interrupts... - */ - - /* SH7751 init done, set central function init complete */ - word = SH7751_PCICR_PREFIX | SH7751_PCICR_CFIN; - outl(word,PCI_REG(SH7751_PCICR)); - PCIDBG(2,"PCI: bigsur_pci_init finished\n"); - - return 1; -} - -int pcibios_map_platform_irq(u8 slot, u8 pin) -{ - /* The Big Sur can be used in a CPCI chassis, but the SH7751 PCI interface is on the - * wrong end of the board so that it can also support a V320 CPI interface chip... - * Therefor the IRQ mapping is somewhat use dependent... I'l assume a linear map for - * now, i.e. INTA=slot0,pin0... INTD=slot3,pin0... - */ - int irq = (slot + pin-1)%4 + BIGSUR_SH7751_PCI_IRQ_BASE; - PCIDBG(2,"PCI: Mapping Big Sur IRQ for slot %d, pin %c to irq %d\n", slot, pin-1+'A', irq); - return irq; - -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/pci-dc.c linux-2.5.71/arch/sh/kernel/pci-dc.c --- linux-2.5.70-bk19/arch/sh/kernel/pci-dc.c 2003-05-26 18:00:27.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/pci-dc.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,198 +0,0 @@ -/* - $ $Id: pci-dc.c,v 1.5 2001/08/24 12:38:19 dwmw2 Exp $ - * Dreamcast PCI: Supports SEGA Broadband Adaptor only. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define GAPSPCI_REGS 0x01001400 -#define GAPSPCI_DMA_BASE 0x01840000 -#define GAPSPCI_DMA_SIZE 32768 -#define GAPSPCI_BBA_CONFIG 0x01001600 - -#define GAPSPCI_IRQ HW_EVENT_EXTERNAL - -static int gapspci_dma_used; - -static struct pci_bus *pci_root_bus; - -struct pci_fixup pcibios_fixups[] = { - {0, 0, 0, NULL} -}; - -#define BBA_SELECTED(bus,devfn) (bus->number==0 && devfn==0) - -static int gapspci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) -{ - switch (size) { - case 1: - if (BBA_SELECTED(bus, devfn)) - *val = (u8)inb(GAPSPCI_BBA_CONFIG+where); - else - *val = (u8)0xff; - break; - case 2: - if (BBA_SELECTED(bus, devfn)) - *val = (u16)inw(GAPSPCI_BBA_CONFIG+where); - else - *val = (u16)0xffff; - break; - case 4: - if (BBA_SELECTED(bus, devfn)) - *val = inl(GAPSPCI_BBA_CONFIG+where); - else - *val = 0xffffffff; - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static int gapspci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) -{ - if (BBA_SELECTED(bus, devfn)) { - switch (size) { - case 1: - if (BBA_SELECTED(bus, devfn)) - outb((u8)val, GAPSPCI_BBA_CONFIG+where); - break; - case 2: - if (BBA_SELECTED(bus, devfn)) - outw((u16)val, GAPSPCI_BBA_CONFIG+where); - break; - case 4: - if (BBA_SELECTED(bus, devfn)) - outl(val, GAPSPCI_BBA_CONFIG+where); - break; - } - } - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops pci_config_ops = { - .read = gapspci_read, - .write = gapspci_write, -}; - - -void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t * dma_handle) -{ - unsigned long buf; - - if (gapspci_dma_used+size > GAPSPCI_DMA_SIZE) - return NULL; - - buf = GAPSPCI_DMA_BASE+gapspci_dma_used; - - gapspci_dma_used = PAGE_ALIGN(gapspci_dma_used+size); - - printk("pci_alloc_consistent: %ld bytes at 0x%lx\n", (long)size, buf); - - *dma_handle = (dma_addr_t)buf; - - return (void *)P2SEGADDR(buf); -} - - -void pci_free_consistent(struct pci_dev *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - /* XXX */ - gapspci_dma_used = 0; -} - - -void __init pcibios_fixup_bus(struct pci_bus *bus) -{ - struct list_head *ln; - struct pci_dev *dev; - - for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { - dev = pci_dev_b(ln); - if (!BBA_SELECTED(bus, dev->devfn)) continue; - - printk("PCI: MMIO fixup to %s\n", dev->name); - dev->resource[1].start=0x01001700; - dev->resource[1].end=0x010017ff; - } -} - - -static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin) -{ - return PCI_SLOT(dev->devfn); -} - - -static int __init map_dc_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - return GAPSPCI_IRQ; -} - - -void __init pcibios_init(void) -{ - pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL); - /* pci_assign_unassigned_resources(); */ - pci_fixup_irqs(no_swizzle, map_dc_irq); -} - - -/* Haven't done anything here as yet */ -char * __init pcibios_setup(char *str) -{ - return str; -} - - -int __init gapspci_init(void) -{ - int i; - char idbuf[16]; - - for(i=0; i<16; i++) - idbuf[i]=inb(GAPSPCI_REGS+i); - - if(strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16)) - return -1; - - outl(0x5a14a501, GAPSPCI_REGS+0x18); - - for(i=0; i<1000000; i++); - - if(inl(GAPSPCI_REGS+0x18)!=1) - return -1; - - outl(0x01000000, GAPSPCI_REGS+0x20); - outl(0x01000000, GAPSPCI_REGS+0x24); - - outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28); - outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c); - - outl(1, GAPSPCI_REGS+0x14); - outl(1, GAPSPCI_REGS+0x34); - - gapspci_dma_used=0; - - /* Setting Broadband Adapter */ - outw(0xf900, GAPSPCI_BBA_CONFIG+0x06); - outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30); - outb(0x00, GAPSPCI_BBA_CONFIG+0x3c); - outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d); - outw(0x0006, GAPSPCI_BBA_CONFIG+0x04); - outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10); - outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14); - - return 0; -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/pci-sh7751.c linux-2.5.71/arch/sh/kernel/pci-sh7751.c --- linux-2.5.70-bk19/arch/sh/kernel/pci-sh7751.c 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/pci-sh7751.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,510 +0,0 @@ -/* - * Low-Level PCI Support for the SH7751 - * - * Dustin McIntire (dustin@sensoria.com) - * Derived from arch/i386/kernel/pci-*.c which bore the message: - * (c) 1999--2000 Martin Mares - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -struct pci_ops *pci_check_direct(void); -void pcibios_resource_survey(void); -static u8 pcibios_swizzle(struct pci_dev *dev, u8 *pin); -static int pcibios_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin); - -unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1; -int pcibios_last_bus = -1; -struct pci_bus *pci_root_bus; -struct pci_ops *pci_root_ops; - -/* - * Direct access to PCI hardware... - */ - -#ifdef CONFIG_PCI_DIRECT - - -#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3)) - -#define PCI_REG(reg) (SH7751_PCIREG_BASE+reg) - -/* - * Functions for accessing PCI configuration space with type 1 accesses - */ -static int pci_conf1_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) -{ - u32 word; - unsigned long flags; - - /* PCIPDR may only be accessed as 32 bit words, - * so we must do byte alignment by hand - */ - save_and_cli(flags); - outl(CONFIG_CMD(bus,devfn,where), PCI_REG(SH7751_PCIPAR)); - word = inl(PCI_REG(SH7751_PCIPDR)); - restore_flags(flags); - - switch (size) { - case 1: - switch (where & 0x3) { - case 3: - *value = (u8)(word >> 24); - break; - case 2: - *value = (u8)(word >> 16); - break; - case 1: - *value = (u8)(word >> 8); - break; - default: - *value = (u8)word; - break; - } - case 2: - switch (where & 0x3) { - case 3: /*This should never happen.*/ - printk(KERN_ERR "PCI BIOS: read_config: Illegal u16 alignment"); - return PCIBIOS_BAD_REGISTER_NUMBER; - case 2: - *value = (u16)(word >> 16); - break; - case 1: - *value = (u16)(word >> 8); - break; - default: - *value = (u16)word; - break; - } - case 4: - *value = word; - break; - } - PCIDBG(4,"pci_conf1_read@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),*value); - return PCIBIOS_SUCCESSFUL; -} - -/* - * Since SH7751 only does 32bit access we'll have to do a read,mask,write operation. - * We'll allow an odd byte offset, though it should be illegal. - */ -static int pci_conf1_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) -{ - u32 word,mask; - unsigned long flags; - u32 shift = (where & 3) * 8; - - if(size == 1) { - mask = ((1 << 8) - 1) << shift; // create the byte mask - } else if(size == 2){ - if(shift == 24) - return PCIBIOS_BAD_REGISTER_NUMBER; - mask = ((1 << 16) - 1) << shift; // create the word mask - } - save_and_cli(flags); - outl(CONFIG_CMD(bus,devfn,where), PCI_REG(SH7751_PCIPAR)); - if(size == 4){ - outl(value, PCI_REG(SH7751_PCIPDR)); - restore_flags(flags); - PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),value); - return PCIBIOS_SUCCESSFUL; - } - word = inl(PCI_REG(SH7751_PCIPDR)) ; - word &= ~mask; - word |= value << shift; - outl(word, PCI_REG(SH7751_PCIPDR)); - restore_flags(flags); - PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),word); - return PCIBIOS_SUCCESSFUL; -} - -#undef CONFIG_CMD - -static struct pci_ops pci_direct_conf1 = { - .read = pci_conf1_read, - .write = pci_conf1_write, -}; - -struct pci_ops * __init pci_check_direct(void) -{ - unsigned int tmp, id; - - /* check for SH7751 hardware */ - id = (SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID; - if(inl(SH7751_PCIREG_BASE+SH7751_PCICONF0) != id) { - PCIDBG(2,"PCI: This is not an SH7751\n"); - return NULL; - } - /* - * Check if configuration works. - */ - if (pci_probe & PCI_PROBE_CONF1) { - tmp = inl (PCI_REG(SH7751_PCIPAR)); - outl (0x80000000, PCI_REG(SH7751_PCIPAR)); - if (inl (PCI_REG(SH7751_PCIPAR)) == 0x80000000) { - outl (tmp, PCI_REG(SH7751_PCIPAR)); - printk(KERN_INFO "PCI: Using configuration type 1\n"); - request_region(PCI_REG(SH7751_PCIPAR), 8, "PCI conf1"); - return &pci_direct_conf1; - } - outl (tmp, PCI_REG(SH7751_PCIPAR)); - } - - PCIDBG(2,"PCI: pci_check_direct failed\n"); - return NULL; -} - -#endif - -/* - * BIOS32 and PCI BIOS handling. - * - * The BIOS version of the pci functions is not yet implemented but it is left - * in for completeness. Currently an error will be generated at compile time. - */ - -#ifdef CONFIG_PCI_BIOS - -#error PCI BIOS is not yet supported on SH7751 - -#endif /* CONFIG_PCI_BIOS */ - -/***************************************************************************************/ - -/* - * Handle bus scanning and fixups .... - */ - - -/* - * Discover remaining PCI buses in case there are peer host bridges. - * We use the number of last PCI bus provided by the PCI BIOS. - */ -static void __init pcibios_fixup_peer_bridges(void) -{ - int n; - struct pci_bus bus; - struct pci_dev dev; - u16 l; - - if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff) - return; - PCIDBG(2,"PCI: Peer bridge fixup\n"); - for (n=0; n <= pcibios_last_bus; n++) { - if (pci_bus_exists(&pci_root_buses, n)) - continue; - bus.number = n; - bus.ops = pci_root_ops; - dev.bus = &bus; - for(dev.devfn=0; dev.devfn<256; dev.devfn += 8) - if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) && - l != 0x0000 && l != 0xffff) { - PCIDBG(3,"Found device at %02x:%02x [%04x]\n", n, dev.devfn, l); - printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n); - pci_scan_bus(n, pci_root_ops, NULL); - break; - } - } -} - - -static void __init pci_fixup_ide_bases(struct pci_dev *d) -{ - int i; - - /* - * PCI IDE controllers use non-standard I/O port decoding, respect it. - */ - if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) - return; - PCIDBG(3,"PCI: IDE base address fixup for %s\n", d->slot_name); - for(i=0; i<4; i++) { - struct resource *r = &d->resource[i]; - if ((r->start & ~0x80) == 0x374) { - r->start |= 2; - r->end = r->start; - } - } -} - - -/* Add future fixups here... */ -struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, - { 0 } -}; - -/* - * Called after each bus is probed, but before its children - * are examined. - */ - -void __init pcibios_fixup_bus(struct pci_bus *b) -{ - pci_read_bridge_bases(b); -} - -/* - * Initialization. Try all known PCI access methods. Note that we support - * using both PCI BIOS and direct access: in such cases, we use I/O ports - * to access config space. - * - * Note that the platform specific initialization (BSC registers, and memory - * space mapping) will be called via the machine vectors (sh_mv.mv_pci_init()) if it - * exitst and via the platform defined function pcibios_init_platform(). - * See pci_bigsur.c for implementation; - * - * The BIOS version of the pci functions is not yet implemented but it is left - * in for completeness. Currently an error will be genereated at compile time. - */ - -void __init pcibios_init(void) -{ - struct pci_ops *bios = NULL; - struct pci_ops *dir = NULL; - - PCIDBG(1,"PCI: Starting initialization.\n"); -#ifdef CONFIG_PCI_BIOS - if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios()))) { - pci_probe |= PCI_BIOS_SORT; - pci_bios_present = 1; - } -#endif -#ifdef CONFIG_PCI_DIRECT - if (pci_probe & PCI_PROBE_CONF1 ) - dir = pci_check_direct(); -#endif - if (dir) { - pci_root_ops = dir; - if(!pcibios_init_platform()) - PCIDBG(1,"PCI: Initialization failed\n"); - if (sh_mv.mv_init_pci != NULL) - sh_mv.mv_init_pci(); - } - else if (bios) - pci_root_ops = bios; - else { - PCIDBG(1,"PCI: No PCI bus detected\n"); - return; - } - - PCIDBG(1,"PCI: Probing PCI hardware\n"); - pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL); - //pci_assign_unassigned_resources(); - pci_fixup_irqs(pcibios_swizzle, pcibios_lookup_irq); - pcibios_fixup_peer_bridges(); - pcibios_resource_survey(); - -#ifdef CONFIG_PCI_BIOS - if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT)) - pcibios_sort(); -#endif -} - -char * __init pcibios_setup(char *str) -{ - if (!strcmp(str, "off")) { - pci_probe = 0; - return NULL; - } -#ifdef CONFIG_PCI_BIOS - else if (!strcmp(str, "bios")) { - pci_probe = PCI_PROBE_BIOS; - return NULL; - } else if (!strcmp(str, "nobios")) { - pci_probe &= ~PCI_PROBE_BIOS; - return NULL; - } else if (!strcmp(str, "nosort")) { - pci_probe |= PCI_NO_SORT; - return NULL; - } else if (!strcmp(str, "biosirq")) { - pci_probe |= PCI_BIOS_IRQ_SCAN; - return NULL; - } -#endif -#ifdef CONFIG_PCI_DIRECT - else if (!strcmp(str, "conf1")) { - pci_probe = PCI_PROBE_CONF1 | PCI_NO_CHECKS; - return NULL; - } -#endif - else if (!strcmp(str, "rom")) { - pci_probe |= PCI_ASSIGN_ROMS; - return NULL; - } else if (!strncmp(str, "lastbus=", 8)) { - pcibios_last_bus = simple_strtol(str+8, NULL, 0); - return NULL; - } - return str; -} - -/* - * Allocate the bridge and device resources - */ - -static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) -{ - struct list_head *ln; - struct pci_bus *bus; - struct pci_dev *dev; - int idx; - struct resource *r, *pr; - - PCIDBG(2,"PCI: pcibios_allocate_bus_reasources called\n" ); - /* Depth-First Search on bus tree */ - for (ln=bus_list->next; ln != bus_list; ln=ln->next) { - bus = pci_bus_b(ln); - if ((dev = bus->self)) { - for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { - r = &dev->resource[idx]; - if (!r->start) - continue; - pr = pci_find_parent_resource(dev, r); - if (!pr || request_resource(pr, r) < 0) - printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name); - } - } - pcibios_allocate_bus_resources(&bus->children); - } -} - -static void __init pcibios_allocate_resources(int pass) -{ - struct pci_dev *dev = NULL; - int idx, disabled; - u16 command; - struct resource *r, *pr; - - PCIDBG(2,"PCI: pcibios_allocate_resources pass %d called\n", pass); - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - pci_read_config_word(dev, PCI_COMMAND, &command); - for(idx = 0; idx < 6; idx++) { - r = &dev->resource[idx]; - if (r->parent) /* Already allocated */ - continue; - if (!r->start) /* Address not assigned at all */ - continue; - if (r->flags & IORESOURCE_IO) - disabled = !(command & PCI_COMMAND_IO); - else - disabled = !(command & PCI_COMMAND_MEMORY); - if (pass == disabled) { - PCIDBG(3,"PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n", - r->start, r->end, r->flags, disabled, pass); - pr = pci_find_parent_resource(dev, r); - if (!pr || request_resource(pr, r) < 0) { - printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, dev->slot_name); - /* We'll assign a new address later */ - r->end -= r->start; - r->start = 0; - } - } - } - if (!pass) { - r = &dev->resource[PCI_ROM_RESOURCE]; - if (r->flags & PCI_ROM_ADDRESS_ENABLE) { - /* Turn the ROM off, leave the resource region, but keep it unregistered. */ - u32 reg; - PCIDBG(3,"PCI: Switching off ROM of %s\n", dev->slot_name); - r->flags &= ~PCI_ROM_ADDRESS_ENABLE; - pci_read_config_dword(dev, dev->rom_base_reg, ®); - pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE); - } - } - } -} - -static void __init pcibios_assign_resources(void) -{ - struct pci_dev *devn = NULL; - int idx; - struct resource *r; - - PCIDBG(2,"PCI: pcibios_assign_resources called\n"); - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - int class = dev->class >> 8; - - /* Don't touch classless devices and host bridges */ - if (!class || class == PCI_CLASS_BRIDGE_HOST) - continue; - - for(idx=0; idx<6; idx++) { - r = &dev->resource[idx]; - - /* - * Don't touch IDE controllers and I/O ports of video cards! - */ - if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) || - (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO))) - continue; - - /* - * We shall assign a new address to this resource, either because - * the BIOS forgot to do so or because we have decided the old - * address was unusable for some reason. - */ - if (!r->start && r->end) - pci_assign_resource(dev, idx); - } - - if (pci_probe & PCI_ASSIGN_ROMS) { - r = &dev->resource[PCI_ROM_RESOURCE]; - r->end -= r->start; - r->start = 0; - if (r->end) - pci_assign_resource(dev, PCI_ROM_RESOURCE); - } - } -} - -void __init pcibios_resource_survey(void) -{ - PCIDBG(1,"PCI: Allocating resources\n"); - pcibios_allocate_bus_resources(&pci_root_buses); - pcibios_allocate_resources(0); - pcibios_allocate_resources(1); - pcibios_assign_resources(); -} - - -/***************************************************************************************/ -/* - * IRQ functions - */ -static u8 __init pcibios_swizzle(struct pci_dev *dev, u8 *pin) -{ - /* no swizzling */ - return PCI_SLOT(dev->devfn); -} - -static int pcibios_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - int irq = -1; - - /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */ - irq = pcibios_map_platform_irq(slot,pin); - if( irq < 0 ) { - PCIDBG(3,"PCI: Error mapping IRQ on device %s\n", dev->name); - return irq; - } - - PCIDBG(2,"Setting IRQ for slot %s to %d\n", dev->slot_name, irq); - - return irq; -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/pci_st40.c linux-2.5.71/arch/sh/kernel/pci_st40.c --- linux-2.5.70-bk19/arch/sh/kernel/pci_st40.c 2003-05-26 18:00:57.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/pci_st40.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,423 +0,0 @@ -/* - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Support functions for the ST40 PCI hardware. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pci_st40.h" - -/* This is in P2 of course */ -#define ST40PCI_BASE_ADDRESS (0xb0000000) -#define ST40PCI_MEM_ADDRESS (ST40PCI_BASE_ADDRESS+0x0) -#define ST40PCI_IO_ADDRESS (ST40PCI_BASE_ADDRESS+0x06000000) -#define ST40PCI_REG_ADDRESS (ST40PCI_BASE_ADDRESS+0x07000000) - -#define ST40PCI_REG(x) (ST40PCI_REG_ADDRESS+(ST40PCI_##x)) - -#define ST40PCI_WRITE(reg,val) writel((val),ST40PCI_REG(reg)) -#define ST40PCI_WRITE_SHORT(reg,val) writew((val),ST40PCI_REG(reg)) -#define ST40PCI_WRITE_BYTE(reg,val) writeb((val),ST40PCI_REG(reg)) - -#define ST40PCI_READ(reg) readl(ST40PCI_REG(reg)) -#define ST40PCI_READ_SHORT(reg) readw(ST40PCI_REG(reg)) -#define ST40PCI_READ_BYTE(reg) readb(ST40PCI_REG(reg)) - -#define ST40PCI_SERR_IRQ 64 -#define ST40PCI_SERR_INT_GROUP 0 -#define ST40PCI_SERR_INT_POS 0 -#define ST40PCI_SERR_INT_PRI 15 - -#define ST40PCI_ERR_IRQ 65 -#define ST40PCI_ERR_INT_GROUP 1 -#define ST40PCI_ERR_INT_POS 1 -#define ST40PCI_ERR_INT_PRI 14 - - -/* Macros to extract PLL params */ -#define PLL_MDIV(reg) ( ((unsigned)reg) & 0xff ) -#define PLL_NDIV(reg) ( (((unsigned)reg)>>8) & 0xff ) -#define PLL_PDIV(reg) ( (((unsigned)reg)>>16) & 0x3 ) -#define PLL_SETUP(reg) ( (((unsigned)reg)>>19) & 0x1ff ) - -/* Build up the appropriate settings */ -#define PLL_SET(mdiv,ndiv,pdiv,setup) \ -( ((mdiv)&0xff) | (((ndiv)&0xff)<<8) | (((pdiv)&3)<<16)| (((setup)&0x1ff)<<19)) - -#define PLLPCICR (0xbb040000+0x10) - -#define PLLPCICR_POWERON (1<<28) -#define PLLPCICR_OUT_EN (1<<29) -#define PLLPCICR_LOCKSELECT (1<<30) -#define PLLPCICR_LOCK (1<<31) - - -#define PLL_25MHZ 0x793c8512 -#define PLL_33MHZ PLL_SET(18,88,3,295) - - -static __init void SetPCIPLL(void) -{ - /* Stop the PLL */ - writel(0, PLLPCICR); - - /* Always run at 33Mhz. The PCI clock is totally async - * to the rest of the system - */ - writel(PLL_33MHZ | PLLPCICR_POWERON, PLLPCICR); - - printk("ST40PCI: Waiting for PCI PLL to lock\n"); - while ((readl(PLLPCICR) & PLLPCICR_LOCK) == 0); - writel(readl(PLLPCICR) | PLLPCICR_OUT_EN, PLLPCICR); -} - - -static void st40_pci_irq(int irq, void *dev_instance, struct pt_regs *regs) -{ - - unsigned pci_int, pci_air, pci_cir, pci_aint; - - pci_int = ST40PCI_READ(INT); - pci_cir = ST40PCI_READ(CIR); - pci_air = ST40PCI_READ(AIR); - - if (pci_int) { - printk("PCI INTERRUPT!\n"); - printk("PCI INT -> 0x%x\n", pci_int & 0xffff); - printk("PCI AIR -> 0x%x\n", pci_air); - printk("PCI CIR -> 0x%x\n", pci_cir); - ST40PCI_WRITE(INT, ~0); - } - - pci_aint = ST40PCI_READ(AINT); - if (pci_aint) { - printk("PCI ARB INTERRUPT!\n"); - printk("PCI AINT -> 0x%x\n", pci_aint); - printk("PCI AIR -> 0x%x\n", pci_air); - printk("PCI CIR -> 0x%x\n", pci_cir); - ST40PCI_WRITE(AINT, ~0); - } - -} - - -/* Rounds a number UP to the nearest power of two. Used for - * sizing the PCI window. - */ -static u32 __init r2p2(u32 num) -{ - int i = 31; - u32 tmp = num; - - if (num == 0) - return 0; - - do { - if (tmp & (1 << 31)) - break; - i--; - tmp <<= 1; - } while (i >= 0); - - tmp = 1 << i; - /* If the original number isn't a power of 2, round it up */ - if (tmp != num) - tmp <<= 1; - - return tmp; -} - -static void __init pci_fixup_ide_bases(struct pci_dev *d) -{ - int i; - - /* - * PCI IDE controllers use non-standard I/O port decoding, respect it. - */ - if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) - return; - printk("PCI: IDE base address fixup for %s\n", d->slot_name); - for(i=0; i<4; i++) { - struct resource *r = &d->resource[i]; - if ((r->start & ~0x80) == 0x374) { - r->start |= 2; - r->end = r->start; - } - } -} - - -/* Add future fixups here... */ -struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, - { 0 } -}; - -int __init st40pci_init(unsigned memStart, unsigned memSize) -{ - u32 lsr0; - - SetPCIPLL(); - - /* Initialises the ST40 pci subsystem, performing a reset, then programming - * up the address space decoders appropriately - */ - - /* Should reset core here as well methink */ - - ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_SOFT_RESET); - - /* Loop while core resets */ - while (ST40PCI_READ(CR) & CR_SOFT_RESET); - - /* Now, lets reset all the cards on the bus with extreme prejudice */ - ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_RSTCTL); - udelay(250); - - /* Set bus active, take it out of reset */ - ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_CFINT | CR_PFCS | CR_PFE); - - /* The PCI spec says that no access must be made to the bus until 1 second - * after reset. This seem ludicrously long, but some delay is needed here - */ - mdelay(1000); - - /* Switch off interrupts */ - ST40PCI_WRITE(INTM, 0); - ST40PCI_WRITE(AINT, 0); - - /* Allow it to be a master */ - - ST40PCI_WRITE_SHORT(CSR_CMD, - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | - PCI_COMMAND_IO); - - /* Accesse to the 0xb0000000 -> 0xb6000000 area will go through to 0x10000000 -> 0x16000000 - * on the PCI bus. This allows a nice 1-1 bus to phys mapping. - */ - - - ST40PCI_WRITE(MBR, 0x10000000); - /* Always set the max size 128M (actually, it is only 96MB wide) */ - ST40PCI_WRITE(MBMR, 0x07ff0000); - - /* I/O addresses are mapped at 0xb6000000 -> 0xb7000000. These are changed to 0, to - * allow cards that have legacy io such as vga to function correctly. This gives a - * maximum of 64K of io/space as only the bottom 16 bits of the address are copied - * over to the bus when the transaction is made. 64K of io space is more than enough - */ - ST40PCI_WRITE(IOBR, 0x0); - /* Set up the 64K window */ - ST40PCI_WRITE(IOBMR, 0x0); - - /* Now we set up the mbars so the PCI bus can see the memory of the machine */ - - if (memSize < (64 * 1024)) { - printk("Ridiculous memory size of 0x%x?\n",memSize); - return 0; - } - - lsr0 = - (memSize > - (512 * 1024 * 1024)) ? 0x1fff0001 : ((r2p2(memSize) - - 0x10000) | 0x1); - - ST40PCI_WRITE(LSR0, lsr0); - - ST40PCI_WRITE(CSR_MBAR0, memStart); - ST40PCI_WRITE(LAR0, memStart); - - /* Maximise timeout values */ - ST40PCI_WRITE_BYTE(CSR_TRDY, 0xff); - ST40PCI_WRITE_BYTE(CSR_RETRY, 0xff); - ST40PCI_WRITE_BYTE(CSR_MIT, 0xff); - - - /* Install the pci interrupt handlers */ - make_intc2_irq(ST40PCI_SERR_IRQ, INTC2_BASE0, - ST40PCI_SERR_INT_GROUP, ST40PCI_SERR_INT_POS, - ST40PCI_SERR_INT_PRI); - - make_intc2_irq(ST40PCI_ERR_IRQ, INTC2_BASE0, ST40PCI_ERR_INT_GROUP, - ST40PCI_ERR_INT_POS, ST40PCI_ERR_INT_PRI); - - - return 1; -} - -char * __init pcibios_setup(char *str) -{ - return str; -} - - -#define SET_CONFIG_BITS(bus,devfn,where)\ - (((bus) << 16) | ((devfn) << 8) | ((where) & ~3) | (bus!=0)) - -#define CONFIG_CMD(bus, devfn, where) SET_CONFIG_BITS(bus->number,devfn,where) - - -static int CheckForMasterAbort(void) -{ - if (ST40PCI_READ(INT) & INT_MADIM) { - /* Should we clear config space version as well ??? */ - ST40PCI_WRITE(INT, INT_MADIM); - ST40PCI_WRITE_SHORT(CSR_STATUS, 0); - return 1; - } - - return 0; -} - -/* Write to config register */ -static int st40pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) -{ - ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); - switch (size) { - case 1: - *val = (u8)ST40PCI_READ_BYTE(PDR + (where & 3)); - break; - case 2: - *val = (u16)ST40PCI_READ_SHORT(PDR + (where & 2)); - break; - case 4: - *val = ST40PCI_READ(PDR); - break; - } - - if (CheckForMasterAbort()){ - switch (size) { - case 1: - *val = (u8)0xff; - break; - case 2: - *val = (u16)0xffff; - break; - case 4: - *val = 0xffffffff; - break; - } - } - - return PCIBIOS_SUCCESSFUL; -} - -static int st40pci_write(struct pci_bus *bus, unsigned int devfn; int where, int size, u32 val) -{ - ST40PCI_WRITE(PAR, CONFIG_CMD(dev, where)); - - switch (size) { - case 1: - ST40PCI_WRITE_BYTE(PDR + (where & 3), (u8)val); - break; - case 2: - ST40PCI_WRITE_SHORT(PDR + (where & 2), (u16)val); - break; - case 4: - ST40PCI_WRITE(PDR, val); - break; - } - - CheckForMasterAbort(); - - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops pci_config_ops = { - .read = st40pci_read, - .write = st40pci_write, -}; - - -/* Everything hangs off this */ -static struct pci_bus *pci_root_bus; - - -static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin) -{ - return PCI_SLOT(dev->devfn); -} - - -/* This needs to be shunted out of here into the board specific bit */ -#define HARP_PCI_IRQ 1 -#define HARP_BRIDGE_IRQ 2 -#define OVERDRIVE_SLOT0_IRQ 0 - -static int __init map_harp_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - switch (slot) { -#ifdef CONFIG_SH_STB1_HARP - case 2: /*This is the PCI slot on the */ - return HARP_PCI_IRQ; - case 1: /* this is the bridge */ - return HARP_BRIDGE_IRQ; -#elif defined(CONFIG_SH_STB1_OVERDRIVE) - case 1: - case 2: - case 3: - return slot - 1; -#else -#error Unknown board -#endif - default: - return -1; - } -} - - -void __init pcibios_init(void) -{ - extern unsigned long memory_start, memory_end; - - if (sh_mv.mv_init_pci != NULL) { - sh_mv.mv_init_pci(); - } - - /* The pci subsytem needs to know where memory is and how much - * of it there is. I've simply made these globals. A better mechanism - * is probably needed. - */ - st40pci_init(PHYSADDR(memory_start), - PHYSADDR(memory_end) - PHYSADDR(memory_start)); - - if (request_irq(ST40PCI_ERR_IRQ, st40_pci_irq, - SA_INTERRUPT, "st40pci", NULL)) { - printk(KERN_ERR "st40pci: Cannot hook interrupt\n"); - return; - } - - /* Enable the PCI interrupts on the device */ - ST40PCI_WRITE(INTM, ~0); - ST40PCI_WRITE(AINT, ~0); - - /* Map the io address apprioately */ -#ifdef CONFIG_HD64465 - hd64465_port_map(PCIBIOS_MIN_IO, (64 * 1024) - PCIBIOS_MIN_IO + 1, - ST40_IO_ADDR + PCIBIOS_MIN_IO, 0); -#endif - - /* ok, do the scan man */ - pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL); - pci_assign_unassigned_resources(); - pci_fixup_irqs(no_swizzle, map_harp_irq); - -} - -void __init pcibios_fixup_bus(struct pci_bus *bus) -{ -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/pci_st40.h linux-2.5.71/arch/sh/kernel/pci_st40.h --- linux-2.5.70-bk19/arch/sh/kernel/pci_st40.h 2003-05-26 18:00:46.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/pci_st40.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Defintions for the ST40 PCI hardware. - */ - -#ifndef __PCI_ST40_H__ -#define __PCI_ST40_H__ - -#define ST40PCI_VCR_STATUS 0x00 - -#define ST40PCI_VCR_VERSION 0x08 - -#define ST40PCI_CR 0x10 - -#define CR_SOFT_RESET (1<<12) -#define CR_PFCS (1<<11) -#define CR_PFE (1<<9) -#define CR_BMAM (1<<6) -#define CR_HOST (1<<5) -#define CR_CLKEN (1<<4) -#define CR_SOCS (1<<3) -#define CR_IOCS (1<<2) -#define CR_RSTCTL (1<<1) -#define CR_CFINT (1<<0) -#define CR_LOCK_MASK 0x5a000000 - - -#define ST40PCI_LSR0 0X14 -#define ST40PCI_LAR0 0x1c - -#define ST40PCI_INT 0x24 -#define INT_MADIM (1<<2) - - -#define ST40PCI_INTM 0x28 -#define ST40PCI_AIR 0x2c -#define ST40PCI_CIR 0x30 -#define ST40PCI_AINT 0x40 -#define ST40PCI_AINTM 0x44 -#define ST40PCI_BMIR 0x48 -#define ST40PCI_PAR 0x4c -#define ST40PCI_MBR 0x50 -#define ST40PCI_IOBR 0x54 -#define ST40PCI_PINT 0x58 -#define ST40PCI_PINTM 0x5c -#define ST40PCI_MBMR 0x70 -#define ST40PCI_IOBMR 0x74 -#define ST40PCI_PDR 0x78 - -/* These are configs space registers */ -#define ST40PCI_CSR_VID 0x10000 -#define ST40PCI_CSR_DID 0x10002 -#define ST40PCI_CSR_CMD 0x10004 -#define ST40PCI_CSR_STATUS 0x10006 -#define ST40PCI_CSR_MBAR0 0x10010 -#define ST40PCI_CSR_TRDY 0x10040 -#define ST40PCI_CSR_RETRY 0x10041 -#define ST40PCI_CSR_MIT 0x1000d - -#define ST40_IO_ADDR 0xb6000000 - -#endif /* __PCI_ST40_H__ */ diff -urN linux-2.5.70-bk19/arch/sh/kernel/rtc-aica.c linux-2.5.71/arch/sh/kernel/rtc-aica.c --- linux-2.5.70-bk19/arch/sh/kernel/rtc-aica.c 2003-05-26 18:00:39.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/rtc-aica.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,70 +0,0 @@ -/* arch/sh/kernel/rtc-aica.c - * - * Dreamcast AICA RTC routines. - * - * Copyright (c) 2001 M. R. Brown - * - * Released under the terms of the GNU GPL v2.0. - * - */ - -#include - -#include - -/* The AICA RTC has an Epoch of 1/1/1950, so we must subtract 20 years (in - seconds to get the standard Unix Epoch when getting the time, and add 20 - years when setting the time. */ -#define TWENTY_YEARS ((20 * 365LU + 5) * 86400) - -/* The AICA RTC is represented by a 32-bit seconds counter stored in 2 16-bit - registers.*/ -#define AICA_RTC_SECS_H 0xa0710000 -#define AICA_RTC_SECS_L 0xa0710004 - -/** - * aica_rtc_gettimeofday - Get the time from the AICA RTC - * @tv: pointer to resulting timeval - * - * Grabs the current RTC seconds counter and adjusts it to the Unix Epoch. - */ -void aica_rtc_gettimeofday(struct timeval *tv) { - unsigned long val1, val2; - - do { - val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | - (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); - - val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | - (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); - } while (val1 != val2); - - tv->tv_sec = val1 - TWENTY_YEARS; - - /* Can't get microseconds with just a seconds counter. */ - tv->tv_usec = 0; -} - -/** - * aica_rtc_settimeofday - Set the AICA RTC to the current time - * @tv: contains the timeval to set - * - * Adjusts the given @tv to the AICA Epoch and sets the RTC seconds counter. - */ -int aica_rtc_settimeofday(const struct timeval *tv) { - unsigned long val1, val2; - unsigned long secs = tv->tv_sec + TWENTY_YEARS; - - do { - ctrl_outl((secs & 0xffff0000) >> 16, AICA_RTC_SECS_H); - ctrl_outl((secs & 0xffff), AICA_RTC_SECS_L); - - val1 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | - (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); - - val2 = ((ctrl_inl(AICA_RTC_SECS_H) & 0xffff) << 16) | - (ctrl_inl(AICA_RTC_SECS_L) & 0xffff); - } while (val1 != val2); - - return 0; -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/setup_7751se.c linux-2.5.71/arch/sh/kernel/setup_7751se.c --- linux-2.5.70-bk19/arch/sh/kernel/setup_7751se.c 2003-05-26 18:01:03.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/setup_7751se.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,136 +0,0 @@ -/* - * linux/arch/sh/kernel/setup_7751se.c - * - * Copyright (C) 2000 Kazumoto Kojima - * - * Hitachi SolutionEngine Support. - * - * Modified for 7751 Solution Engine by - * Ian da Silva and Jeremy Siegel, 2001. - */ - -#include -#include -#include - -#include -#include -#include -#include - -/* - * Configure the Super I/O chip - */ -#if 0 -/* Leftover code from regular Solution Engine, for reference. */ -/* The SH7751 Solution Engine has a different SuperIO. */ -static void __init smsc_config(int index, int data) -{ - outb_p(index, INDEX_PORT); - outb_p(data, DATA_PORT); -} - -static void __init init_smsc(void) -{ - outb_p(CONFIG_ENTER, CONFIG_PORT); - outb_p(CONFIG_ENTER, CONFIG_PORT); - - /* FDC */ - smsc_config(CURRENT_LDN_INDEX, LDN_FDC); - smsc_config(ACTIVATE_INDEX, 0x01); - smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */ - - /* IDE1 */ - smsc_config(CURRENT_LDN_INDEX, LDN_IDE1); - smsc_config(ACTIVATE_INDEX, 0x01); - smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */ - - /* AUXIO (GPIO): to use IDE1 */ - smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO); - smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */ - smsc_config(GPIO47_INDEX, 0x00); /* nIOWOP */ - - /* COM1 */ - smsc_config(CURRENT_LDN_INDEX, LDN_COM1); - smsc_config(ACTIVATE_INDEX, 0x01); - smsc_config(IO_BASE_HI_INDEX, 0x03); - smsc_config(IO_BASE_LO_INDEX, 0xf8); - smsc_config(IRQ_SELECT_INDEX, 4); /* IRQ4 */ - - /* COM2 */ - smsc_config(CURRENT_LDN_INDEX, LDN_COM2); - smsc_config(ACTIVATE_INDEX, 0x01); - smsc_config(IO_BASE_HI_INDEX, 0x02); - smsc_config(IO_BASE_LO_INDEX, 0xf8); - smsc_config(IRQ_SELECT_INDEX, 3); /* IRQ3 */ - - /* RTC */ - smsc_config(CURRENT_LDN_INDEX, LDN_RTC); - smsc_config(ACTIVATE_INDEX, 0x01); - smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */ - - /* XXX: PARPORT, KBD, and MOUSE will come here... */ - outb_p(CONFIG_EXIT, CONFIG_PORT); -} -#endif - -/* - * Initialize IRQ setting - */ -void __init init_7751se_IRQ(void) -{ - - /* Leave old Solution Engine code in for reference. */ -#if defined(CONFIG_SH_SOLUTION_ENGINE) - /* - * Super I/O (Just mimic PC): - * 1: keyboard - * 3: serial 0 - * 4: serial 1 - * 5: printer - * 6: floppy - * 8: rtc - * 12: mouse - * 14: ide0 - */ - make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-14); - make_ipr_irq(12, BCR_ILCRA, 1, 0x0f-12); - make_ipr_irq( 8, BCR_ILCRB, 1, 0x0f- 8); - make_ipr_irq( 6, BCR_ILCRC, 3, 0x0f- 6); - make_ipr_irq( 5, BCR_ILCRC, 2, 0x0f- 5); - make_ipr_irq( 4, BCR_ILCRC, 1, 0x0f- 4); - make_ipr_irq( 3, BCR_ILCRC, 0, 0x0f- 3); - make_ipr_irq( 1, BCR_ILCRD, 3, 0x0f- 1); - - make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */ - - make_ipr_irq( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */ - make_ipr_irq(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */ - make_ipr_irq( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */ - make_ipr_irq( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */ - - /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */ - /* NOTE: #2 and #13 are not used on PC */ - make_ipr_irq(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */ - make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */ - -#elif defined(CONFIG_SH_7751_SOLUTION_ENGINE) - - make_ipr_irq(13, BCR_ILCRD, 3, 2); - - /* Add additional calls to make_ipr_irq() as drivers are added - * and tested. - */ -#endif - -} - - -/* - * Initialize the board - */ -void __init setup_7751se(void) -{ - /* Call init_smsc() replacement to set up SuperIO. */ - /* XXX: RTC setting comes here */ -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/setup_adx.c linux-2.5.71/arch/sh/kernel/setup_adx.c --- linux-2.5.70-bk19/arch/sh/kernel/setup_adx.c 2003-05-26 18:00:57.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/setup_adx.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,40 +0,0 @@ -/* - * linux/arch/sh/kernel/setup_adx.c - * - * Copyright (C) 2001 A&D Co., Ltd. - * - * I/O routine and setup routines for A&D ADX Board - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - */ - -#include -#include -#include -#include - -void setup_adx(void) -{ - /* nothing to do just yet */ -/* printk("setup_adx()\n");*/ -} - -void init_adx_IRQ(void) -{ - int i; - -/* printk("init_adx_IRQ()\n");*/ - /* setup irq_mask_register */ - irq_mask_register = (unsigned short *)0xa6000008; - - /* cover all external interrupt area by maskreg_irq_type - * (Actually, irq15 doesn't exist) - */ - for (i = 0; i < 16; i++) { - make_maskreg_irq(i); - disable_irq(i); - } -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/setup_bigsur.c linux-2.5.71/arch/sh/kernel/setup_bigsur.c --- linux-2.5.70-bk19/arch/sh/kernel/setup_bigsur.c 2003-05-26 18:00:56.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/setup_bigsur.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,383 +0,0 @@ -/* - * - * By Dustin McIntire (dustin@sensoria.com) (c)2001 - * - * Setup and IRQ handling code for the HD64465 companion chip. - * by Greg Banks - * Copyright (c) 2000 PocketPenguins Inc - * - * Derived from setup_hd64465.c which bore the message: - * Greg Banks - * Copyright (c) 2000 PocketPenguins Inc and - * Copyright (C) 2000 YAEGASHI Takeshi - * and setup_cqreek.c which bore message: - * Copyright (C) 2000 Niibe Yutaka - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Setup and IRQ functions for a Hitachi Big Sur Evaluation Board. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -//#define BIGSUR_DEBUG 3 -#undef BIGSUR_DEBUG - -#ifdef BIGSUR_DEBUG -#define DPRINTK(args...) printk(args) -#define DIPRINTK(n, args...) if (BIGSUR_DEBUG>(n)) printk(args) -#else -#define DPRINTK(args...) -#define DIPRINTK(n, args...) -#endif /* BIGSUR_DEBUG */ - -#ifdef CONFIG_HD64465 -extern int hd64465_irq_demux(int irq); -#endif /* CONFIG_HD64465 */ - - -/*===========================================================*/ -// Big Sur CPLD IRQ Routines -/*===========================================================*/ - -/* Level 1 IRQ routines */ -static void disable_bigsur_l1irq(unsigned int irq) -{ - unsigned long flags; - unsigned char mask; - unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0; - unsigned char bit = (1 << ((irq - MGATE_IRQ_LOW)%8) ); - - if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) { - DPRINTK("Disable L1 IRQ %d\n", irq); - DIPRINTK(2,"disable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n", - mask_port, bit); - save_and_cli(flags); - - /* Disable IRQ - set mask bit */ - mask = inb(mask_port) | bit; - outb(mask, mask_port); - restore_flags(flags); - return; - } - DPRINTK("disable_bigsur_l1irq: Invalid IRQ %d\n", irq); -} - -static void enable_bigsur_l1irq(unsigned int irq) -{ - unsigned long flags; - unsigned char mask; - unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0; - unsigned char bit = (1 << ((irq - MGATE_IRQ_LOW)%8) ); - - if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) { - DPRINTK("Enable L1 IRQ %d\n", irq); - DIPRINTK(2,"enable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n", - mask_port, bit); - save_and_cli(flags); - /* Enable L1 IRQ - clear mask bit */ - mask = inb(mask_port) & ~bit; - outb(mask, mask_port); - restore_flags(flags); - return; - } - DPRINTK("enable_bigsur_l1irq: Invalid IRQ %d\n", irq); -} - - -/* Level 2 irq masks and registers for L2 decoding */ -/* Level2 bitmasks for each level 1 IRQ */ -const u32 bigsur_l2irq_mask[] = - {0x40,0x80,0x08,0x01,0x01,0x3C,0x3E,0xFF,0x40,0x80,0x06,0x03}; -/* Level2 to ISR[n] map for each level 1 IRQ */ -const u32 bigsur_l2irq_reg[] = - { 2, 2, 3, 3, 1, 2, 1, 0, 1, 1, 3, 2}; -/* Level2 to Level 1 IRQ map */ -const u32 bigsur_l2_l1_map[] = - {7,7,7,7,7,7,7,7, 4,6,6,6,6,6,8,9, 11,11,5,5,5,5,0,1, 3,10,10,2,-1,-1,-1,-1}; -/* IRQ inactive level (high or low) */ -const u32 bigsur_l2_inactv_state[] = {0x00, 0xBE, 0xFC, 0xF7}; - -/* CPLD external status and mask registers base and offsets */ -static const u32 isr_base = BIGSUR_IRQ0; -static const u32 isr_offset = BIGSUR_IRQ0 - BIGSUR_IRQ1; -static const u32 imr_base = BIGSUR_IMR0; -static const u32 imr_offset = BIGSUR_IMR0 - BIGSUR_IMR1; - -#define REG_NUM(irq) ((irq-BIGSUR_2NDLVL_IRQ_LOW)/8 ) - -/* Level 2 IRQ routines */ -static void disable_bigsur_l2irq(unsigned int irq) -{ - unsigned long flags; - unsigned char mask; - unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8); - unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset; - - if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) { - DPRINTK("Disable L2 IRQ %d\n", irq); - DIPRINTK(2,"disable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n", - mask_port, bit); - save_and_cli(flags); - - /* Disable L2 IRQ - set mask bit */ - mask = inb(mask_port) | bit; - outb(mask, mask_port); - restore_flags(flags); - return; - } - DPRINTK("disable_bigsur_l2irq: Invalid IRQ %d\n", irq); -} - -static void enable_bigsur_l2irq(unsigned int irq) -{ - unsigned long flags; - unsigned char mask; - unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8); - unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset; - - if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) { - DPRINTK("Enable L2 IRQ %d\n", irq); - DIPRINTK(2,"enable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n", - mask_port, bit); - save_and_cli(flags); - - /* Enable L2 IRQ - clear mask bit */ - mask = inb(mask_port) & ~bit; - outb(mask, mask_port); - restore_flags(flags); - return; - } - DPRINTK("enable_bigsur_l2irq: Invalid IRQ %d\n", irq); -} - -static void mask_and_ack_bigsur(unsigned int irq) -{ - DPRINTK("mask_and_ack_bigsur IRQ %d\n", irq); - if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) - disable_bigsur_l1irq(irq); - else - disable_bigsur_l2irq(irq); -} - -static void end_bigsur_irq(unsigned int irq) -{ - DPRINTK("end_bigsur_irq IRQ %d\n", irq); - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) { - if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) - enable_bigsur_l1irq(irq); - else - enable_bigsur_l2irq(irq); - } -} - -static unsigned int startup_bigsur_irq(unsigned int irq) -{ - u8 mask; - u32 reg; - - DPRINTK("startup_bigsur_irq IRQ %d\n", irq); - - if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) { - /* Enable the L1 IRQ */ - enable_bigsur_l1irq(irq); - /* Enable all L2 IRQs in this L1 IRQ */ - mask = ~(bigsur_l2irq_mask[irq-BIGSUR_IRQ_LOW]); - reg = imr_base - bigsur_l2irq_reg[irq-BIGSUR_IRQ_LOW] * imr_offset; - mask &= inb(reg); - outb(mask,reg); - DIPRINTK(2,"startup_bigsur_irq: IMR=0x%08x mask=0x%x\n",reg,inb(reg)); - } - else { - /* Enable the L2 IRQ - clear mask bit */ - enable_bigsur_l2irq(irq); - /* Enable the L1 bit masking this L2 IRQ */ - enable_bigsur_l1irq(bigsur_l2_l1_map[irq-BIGSUR_2NDLVL_IRQ_LOW]); - DIPRINTK(2,"startup_bigsur_irq: L1=%d L2=%d\n", - bigsur_l2_l1_map[irq-BIGSUR_2NDLVL_IRQ_LOW],irq); - } - return 0; -} - -static void shutdown_bigsur_irq(unsigned int irq) -{ - DPRINTK("shutdown_bigsur_irq IRQ %d\n", irq); - if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) - disable_bigsur_l1irq(irq); - else - disable_bigsur_l2irq(irq); -} - -/* Define the IRQ structures for the L1 and L2 IRQ types */ -static struct hw_interrupt_type bigsur_l1irq_type = { - "BigSur-CPLD-Level1-IRQ", - startup_bigsur_irq, - shutdown_bigsur_irq, - enable_bigsur_l1irq, - disable_bigsur_l1irq, - mask_and_ack_bigsur, - end_bigsur_irq -}; - -static struct hw_interrupt_type bigsur_l2irq_type = { - "BigSur-CPLD-Level2-IRQ", - startup_bigsur_irq, - shutdown_bigsur_irq, - enable_bigsur_l2irq, - disable_bigsur_l2irq, - mask_and_ack_bigsur, - end_bigsur_irq -}; - - -static void make_bigsur_l1isr(unsigned int irq) { - - /* sanity check first */ - if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) { - /* save the handler in the main description table */ - irq_desc[irq].handler = &bigsur_l1irq_type; - irq_desc[irq].status = IRQ_DISABLED; - irq_desc[irq].action = 0; - irq_desc[irq].depth = 1; - - disable_bigsur_l1irq(irq); - return; - } - DPRINTK("make_bigsur_l1isr: bad irq, %d\n", irq); - return; -} - -static void make_bigsur_l2isr(unsigned int irq) { - - /* sanity check first */ - if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) { - /* save the handler in the main description table */ - irq_desc[irq].handler = &bigsur_l2irq_type; - irq_desc[irq].status = IRQ_DISABLED; - irq_desc[irq].action = 0; - irq_desc[irq].depth = 1; - - disable_bigsur_l2irq(irq); - return; - } - DPRINTK("make_bigsur_l2isr: bad irq, %d\n", irq); - return; -} - -/* The IRQ's will be decoded as follows: - * If a level 2 handler exists and there is an unmasked active - * IRQ, the 2nd level handler will be called. - * If a level 2 handler does not exist for the active IRQ - * the 1st level handler will be called. - */ - -int bigsur_irq_demux(int irq) -{ - int dmux_irq = irq; - u8 mask, actv_irqs; - u32 reg_num; - - DIPRINTK(3,"bigsur_irq_demux, irq=%d\n", irq); - /* decode the 1st level IRQ */ - if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) { - /* Get corresponding L2 ISR bitmask and ISR number */ - mask = bigsur_l2irq_mask[irq-BIGSUR_IRQ_LOW]; - reg_num = bigsur_l2irq_reg[irq-BIGSUR_IRQ_LOW]; - /* find the active IRQ's (XOR with inactive level)*/ - actv_irqs = inb(isr_base-reg_num*isr_offset) ^ - bigsur_l2_inactv_state[reg_num]; - /* decode active IRQ's */ - actv_irqs = actv_irqs & mask & ~(inb(imr_base-reg_num*imr_offset)); - /* if NEZ then we have an active L2 IRQ */ - if(actv_irqs) dmux_irq = ffz(~actv_irqs) + reg_num*8+BIGSUR_2NDLVL_IRQ_LOW; - /* if no 2nd level IRQ action, but has 1st level, use 1st level handler */ - if(!irq_desc[dmux_irq].action && irq_desc[irq].action) - dmux_irq = irq; - DIPRINTK(1,"bigsur_irq_demux: irq=%d dmux_irq=%d mask=0x%04x reg=%d\n", - irq, dmux_irq, mask, reg_num); - } -#ifdef CONFIG_HD64465 - dmux_irq = hd64465_irq_demux(dmux_irq); -#endif /* CONFIG_HD64465 */ - DIPRINTK(3,"bigsur_irq_demux, demux_irq=%d\n", dmux_irq); - - return dmux_irq; -} - -/*===========================================================*/ -// Big Sur Init Routines -/*===========================================================*/ -void __init init_bigsur_IRQ(void) -{ - int i; - - if (!MACH_BIGSUR) return; - - /* Create ISR's for Big Sur CPLD IRQ's */ - /*==============================================================*/ - for(i=BIGSUR_IRQ_LOW;i -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define BRIDGE_FEATURE 0x0002 - -#define BRIDGE_IDE_CTRL 0x0018 -#define BRIDGE_IDE_INTR_LVL 0x001A -#define BRIDGE_IDE_INTR_MASK 0x001C -#define BRIDGE_IDE_INTR_STAT 0x001E - -#define BRIDGE_ISA_CTRL 0x0028 -#define BRIDGE_ISA_INTR_LVL 0x002A -#define BRIDGE_ISA_INTR_MASK 0x002C -#define BRIDGE_ISA_INTR_STAT 0x002E - -#define IDE_OFFSET 0xA4000000UL -#define ISA_OFFSET 0xA4A00000UL - -static unsigned long cqreek_port2addr(unsigned long port) -{ - if (0x0000<=port && port<=0x0040) - return IDE_OFFSET + port; - if ((0x01f0<=port && port<=0x01f7) || port == 0x03f6) - return IDE_OFFSET + port; - - return ISA_OFFSET + port; -} - -struct cqreek_irq_data { - unsigned short mask_port; /* Port of Interrupt Mask Register */ - unsigned short stat_port; /* Port of Interrupt Status Register */ - unsigned short bit; /* Value of the bit */ -}; -static struct cqreek_irq_data cqreek_irq_data[NR_IRQS]; - -static void disable_cqreek_irq(unsigned int irq) -{ - unsigned long flags; - unsigned short mask; - unsigned short mask_port = cqreek_irq_data[irq].mask_port; - unsigned short bit = cqreek_irq_data[irq].bit; - - save_and_cli(flags); - /* Disable IRQ */ - mask = inw(mask_port) & ~bit; - outw_p(mask, mask_port); - restore_flags(flags); -} - -static void enable_cqreek_irq(unsigned int irq) -{ - unsigned long flags; - unsigned short mask; - unsigned short mask_port = cqreek_irq_data[irq].mask_port; - unsigned short bit = cqreek_irq_data[irq].bit; - - save_and_cli(flags); - /* Enable IRQ */ - mask = inw(mask_port) | bit; - outw_p(mask, mask_port); - restore_flags(flags); -} - -static void mask_and_ack_cqreek(unsigned int irq) -{ - unsigned short stat_port = cqreek_irq_data[irq].stat_port; - unsigned short bit = cqreek_irq_data[irq].bit; - - disable_cqreek_irq(irq); - /* Clear IRQ (it might be edge IRQ) */ - inw(stat_port); - outw_p(bit, stat_port); -} - -static void end_cqreek_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_cqreek_irq(irq); -} - -static unsigned int startup_cqreek_irq(unsigned int irq) -{ - enable_cqreek_irq(irq); - return 0; -} - -static void shutdown_cqreek_irq(unsigned int irq) -{ - disable_cqreek_irq(irq); -} - -static struct hw_interrupt_type cqreek_irq_type = { - "CqREEK-IRQ", - startup_cqreek_irq, - shutdown_cqreek_irq, - enable_cqreek_irq, - disable_cqreek_irq, - mask_and_ack_cqreek, - end_cqreek_irq -}; - -static int has_ide, has_isa; - -/* XXX: This is just for test for my NE2000 ISA board - What we really need is virtualized IRQ and demultiplexer like HP600 port */ -void __init init_cqreek_IRQ(void) -{ - if (has_ide) { - cqreek_irq_data[14].mask_port = BRIDGE_IDE_INTR_MASK; - cqreek_irq_data[14].stat_port = BRIDGE_IDE_INTR_STAT; - cqreek_irq_data[14].bit = 1; - - irq_desc[14].handler = &cqreek_irq_type; - irq_desc[14].status = IRQ_DISABLED; - irq_desc[14].action = 0; - irq_desc[14].depth = 1; - - disable_cqreek_irq(14); - } - - if (has_isa) { - cqreek_irq_data[10].mask_port = BRIDGE_ISA_INTR_MASK; - cqreek_irq_data[10].stat_port = BRIDGE_ISA_INTR_STAT; - cqreek_irq_data[10].bit = (1 << 10); - - /* XXX: Err... we may need demultiplexer for ISA irq... */ - irq_desc[10].handler = &cqreek_irq_type; - irq_desc[10].status = IRQ_DISABLED; - irq_desc[10].action = 0; - irq_desc[10].depth = 1; - - disable_cqreek_irq(10); - } -} - -/* - * Initialize the board - */ -void __init setup_cqreek(void) -{ - int i; -/* udelay is not available at setup time yet... */ -#define DELAY() do {for (i=0; i<10000; i++) ctrl_inw(0xa0000000);} while(0) - - if ((inw (BRIDGE_FEATURE) & 1)) { /* We have IDE interface */ - outw_p(0, BRIDGE_IDE_INTR_LVL); - outw_p(0, BRIDGE_IDE_INTR_MASK); - - outw_p(0, BRIDGE_IDE_CTRL); - DELAY(); - - outw_p(0x8000, BRIDGE_IDE_CTRL); - DELAY(); - - outw_p(0xffff, BRIDGE_IDE_INTR_STAT); /* Clear interrupt status */ - outw_p(0x0f-14, BRIDGE_IDE_INTR_LVL); /* Use 14 IPR */ - outw_p(1, BRIDGE_IDE_INTR_MASK); /* Enable interrupt */ - has_ide=1; - } - - if ((inw (BRIDGE_FEATURE) & 2)) { /* We have ISA interface */ - outw_p(0, BRIDGE_ISA_INTR_LVL); - outw_p(0, BRIDGE_ISA_INTR_MASK); - - outw_p(0, BRIDGE_ISA_CTRL); - DELAY(); - outw_p(0x8000, BRIDGE_ISA_CTRL); - DELAY(); - - outw_p(0xffff, BRIDGE_ISA_INTR_STAT); /* Clear interrupt status */ - outw_p(0x0f-10, BRIDGE_ISA_INTR_LVL); /* Use 10 IPR */ - outw_p(0xfff8, BRIDGE_ISA_INTR_MASK); /* Enable interrupt */ - has_isa=1; - } - - printk(KERN_INFO "CqREEK Setup (IDE=%d, ISA=%d)...done\n", has_ide, has_isa); -} - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_cqreek __initmv = { - .mv_name = "CqREEK", - -#if defined(__SH4__) - .mv_nr_irqs = 48, -#elif defined(CONFIG_CPU_SUBTYPE_SH7708) - .mv_nr_irqs = 32, -#elif defined(CONFIG_CPU_SUBTYPE_SH7709) - .mv_nr_irqs = 61, -#endif - - .mv_inb = generic_inb, - .mv_inw = generic_inw, - .mv_inl = generic_inl, - .mv_outb = generic_outb, - .mv_outw = generic_outw, - .mv_outl = generic_outl, - - .mv_inb_p = generic_inb_p, - .mv_inw_p = generic_inw_p, - .mv_inl_p = generic_inl_p, - .mv_outb_p = generic_outb_p, - .mv_outw_p = generic_outw_p, - .mv_outl_p = generic_outl_p, - - .mv_insb = generic_insb, - .mv_insw = generic_insw, - .mv_insl = generic_insl, - .mv_outsb = generic_outsb, - .mv_outsw = generic_outsw, - .mv_outsl = generic_outsl, - - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_init_arch = setup_cqreek, - .mv_init_irq = init_cqreek_IRQ, - - .mv_isa_port2addr = cqreek_port2addr, - - .mv_ioremap = generic_ioremap, - .mv_iounmap = generic_iounmap, - - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, -}; -ALIAS_MV(cqreek) diff -urN linux-2.5.70-bk19/arch/sh/kernel/setup_dc.c linux-2.5.71/arch/sh/kernel/setup_dc.c --- linux-2.5.70-bk19/arch/sh/kernel/setup_dc.c 2003-05-26 18:00:21.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/setup_dc.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,213 +0,0 @@ -/* arch/sh/kernel/setup_dc.c - * - * Hardware support for the Sega Dreamcast. - * - * Copyright (c) 2001 M. R. Brown - * - * This file is part of the LinuxDC project (www.linuxdc.org) - * - * Released under the terms of the GNU GPL v2.0. - * - * This file originally bore the message (with enclosed-$): - * Id: setup_dc.c,v 1.5 2001/05/24 05:09:16 mrbrown Exp - * SEGA Dreamcast support - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -int __init gapspci_init(void); - -#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) - -/* Dreamcast System ASIC Hardware Events - - - The Dreamcast's System ASIC (located on the PowerVR2 chip) is responsible - for receiving hardware events from system peripherals and triggering an - SH7750 IRQ. Hardware events can trigger IRQs 13, 11, or 9 depending on - which bits are set in the Event Mask Registers (EMRs). When a hardware - event is triggered, it's corresponding bit in the Event Status Registers - (ESRs) is set, and that bit should be rewritten to the ESR to acknowledge - that event. - - There are three 32-bit ESRs located at 0xa05f8900 - 0xa05f6908. Event - types can be found in include/asm-sh/dc_sysasic.h. There are three groups - of EMRs that parallel the ESRs. Each EMR group corresponds to an IRQ, so - 0xa05f6910 - 0xa05f6918 triggers IRQ 13, 0xa05f6920 - 0xa05f6928 triggers - IRQ 11, and 0xa05f6930 - 0xa05f6938 triggers IRQ 9. - - In the kernel, these events are mapped to virtual IRQs so that drivers can - respond to them as they would a normal interrupt. In order to keep this - mapping simple, the events are mapped as: - - 6900/6910 - Events 0-31, IRQ 13 - 6904/6924 - Events 32-63, IRQ 11 - 6908/6938 - Events 64-95, IRQ 9 - -*/ - -#define ESR_BASE 0x005f6900 /* Base event status register */ -#define EMR_BASE 0x005f6910 /* Base event mask register */ - -/* Helps us determine the EMR group that this event belongs to: 0 = 0x6910, - 1 = 0x6920, 2 = 0x6930; also determine the event offset */ -#define LEVEL(event) (((event) - HW_EVENT_IRQ_BASE) / 32) - -/* Return the hardware event's bit positon within the EMR/ESR */ -#define EVENT_BIT(event) (((event) - HW_EVENT_IRQ_BASE) & 31) - -/* For each of these *_irq routines, the IRQ passed in is the virtual IRQ - (logically mapped to the corresponding bit for the hardware event). */ - -/* Disable the hardware event by masking its bit in its EMR */ -static inline void disable_systemasic_irq(unsigned int irq) -{ - unsigned long flags; - __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2); - __u32 mask; - - save_and_cli(flags); - mask = inl(emr); - mask &= ~(1 << EVENT_BIT(irq)); - outl(mask, emr); - restore_flags(flags); -} - -/* Enable the hardware event by setting its bit in its EMR */ -static inline void enable_systemasic_irq(unsigned int irq) -{ - unsigned long flags; - __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2); - __u32 mask; - - save_and_cli(flags); - mask = inl(emr); - mask |= (1 << EVENT_BIT(irq)); - outl(mask, emr); - restore_flags(flags); -} - -/* Acknowledge a hardware event by writing its bit back to its ESR */ -static void ack_systemasic_irq(unsigned int irq) -{ - __u32 esr = ESR_BASE + (LEVEL(irq) << 2); - disable_systemasic_irq(irq); - outl((1 << EVENT_BIT(irq)), esr); -} - -/* After a IRQ has been ack'd and responded to, it needs to be renabled */ -static void end_systemasic_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_systemasic_irq(irq); -} - -static unsigned int startup_systemasic_irq(unsigned int irq) -{ - enable_systemasic_irq(irq); - - return 0; -} - -static void shutdown_systemasic_irq(unsigned int irq) -{ - disable_systemasic_irq(irq); -} - -static struct hw_interrupt_type systemasic_int = { - .typename = "System ASIC", - .startup = startup_systemasic_irq, - .shutdown = shutdown_systemasic_irq, - .enable = enable_systemasic_irq, - .disable = disable_systemasic_irq, - .ack = ack_systemasic_irq, - .end = end_systemasic_irq, -}; - -/* - * Map the hardware event indicated by the processor IRQ to a virtual IRQ. - */ -int systemasic_irq_demux(int irq) -{ - __u32 emr, esr, status, level; - __u32 j, bit; - - switch (irq) { - case 13: - level = 0; - break; - case 11: - level = 1; - break; - case 9: - level = 2; - break; - default: - return irq; - } - emr = EMR_BASE + (level << 4) + (level << 2); - esr = ESR_BASE + (level << 2); - - /* Mask the ESR to filter any spurious, unwanted interrtupts */ - status = inl(esr); - status &= inl(emr); - - /* Now scan and find the first set bit as the event to map */ - for (bit = 1, j = 0; j < 32; bit <<= 1, j++) { - if (status & bit) { - irq = HW_EVENT_IRQ_BASE + j + (level << 5); - return irq; - } - } - - /* Not reached */ - return irq; -} - -int __init setup_dreamcast(void) -{ - int i; - - /* Mask all hardware events */ - /* XXX */ - - /* Acknowledge any previous events */ - /* XXX */ - - /* Assign all virtual IRQs to the System ASIC int. handler */ - for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++) - irq_desc[i].handler = &systemasic_int; - -#ifdef CONFIG_PCI - gapspci_init(); -#endif - - printk(KERN_INFO "SEGA Dreamcast support.\n"); -#if 0 - printk(KERN_INFO "BCR1: 0x%08x\n", ctrl_inl(0xff800000)); - printk(KERN_INFO "BCR2: 0x%08x\n", ctrl_inw(0xff800004)); - printk(KERN_INFO "WCR1: 0x%08x\n", ctrl_inl(0xff800008)); - printk(KERN_INFO "WCR2: 0x%08x\n", ctrl_inl(0xff80000c)); - printk(KERN_INFO "WCR3: 0x%08x\n", ctrl_inl(0xff800010)); - printk(KERN_INFO "MCR: 0x%08x\n", ctrl_inl(0xff800014)); - printk(KERN_INFO "PCR: 0x%08x\n", ctrl_inw(0xff800018)); -/* - * BCR1: 0xa3020008 - * BCR2: 0x0001 - * WCR1: 0x01110111 - * WCR2: 0x618066d8 - * WCR3: 0x07777777 - * MCR: 0xc00a0e24 - * PCR: 0x0000 - */ -#endif - return 0; -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/setup_ec3104.c linux-2.5.71/arch/sh/kernel/setup_ec3104.c --- linux-2.5.70-bk19/arch/sh/kernel/setup_ec3104.c 2003-05-26 18:00:56.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/setup_ec3104.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,242 +0,0 @@ -/* - * linux/arch/sh/kernel/setup_ec3104.c - * EC3104 companion chip support - * - * Copyright (C) 2000 Philipp Rumpf - * - */ -/* EC3104 note: - * This code was written without any documentation about the EC3104 chip. While - * I hope I got most of the basic functionality right, the register names I use - * are most likely completely different from those in the chip documentation. - * - * If you have any further information about the EC3104, please tell me - * (prumpf@tux.org). - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* This is for debugging mostly; here's the table that I intend to keep - * in here: - * - * index function base addr power interrupt bit - * 0 power b0ec0000 --- 00000001 (unused) - * 1 irqs b0ec1000 --- 00000002 (unused) - * 2 ?? b0ec2000 b0ec0008 00000004 - * 3 PS2 (1) b0ec3000 b0ec000c 00000008 - * 4 PS2 (2) b0ec4000 b0ec0010 00000010 - * 5 ?? b0ec5000 b0ec0014 00000020 - * 6 I2C b0ec6000 b0ec0018 00000040 - * 7 serial (1) b0ec7000 b0ec001c 00000080 - * 8 serial (2) b0ec8000 b0ec0020 00000100 - * 9 serial (3) b0ec9000 b0ec0024 00000200 - * 10 serial (4) b0eca000 b0ec0028 00000400 - * 12 GPIO (1) b0ecc000 b0ec0030 - * 13 GPIO (2) b0ecc000 b0ec0030 - * 16 pcmcia (1) b0ed0000 b0ec0040 00010000 - * 17 pcmcia (2) b0ed1000 b0ec0044 00020000 - */ - -/* I used the register names from another interrupt controller I worked with, - * since it seems to be identical to the ec3104 except that all bits are - * inverted: - * - * IRR: Interrupt Request Register (pending and enabled interrupts) - * IMR: Interrupt Mask Register (which interrupts are enabled) - * IPR: Interrupt Pending Register (pending interrupts, even disabled ones) - * - * 0 bits mean pending or enabled, 1 bits mean not pending or disabled. all - * IRQs seem to be level-triggered. - */ - -#define EC3104_IRR (EC3104_BASE + 0x1000) -#define EC3104_IMR (EC3104_BASE + 0x1004) -#define EC3104_IPR (EC3104_BASE + 0x1008) - -#define ctrl_readl(addr) (*(volatile u32 *)(addr)) -#define ctrl_writel(data,addr) (*(volatile u32 *)(addr) = (data)) -#define ctrl_readb(addr) (*(volatile u8 *)(addr)) - -static char *ec3104_name(unsigned index) -{ - switch(index) { - case 0: - return "power management"; - case 1: - return "interrupts"; - case 3: - return "PS2 (1)"; - case 4: - return "PS2 (2)"; - case 5: - return "I2C (1)"; - case 6: - return "I2C (2)"; - case 7: - return "serial (1)"; - case 8: - return "serial (2)"; - case 9: - return "serial (3)"; - case 10: - return "serial (4)"; - case 16: - return "pcmcia (1)"; - case 17: - return "pcmcia (2)"; - default: { - static char buf[32]; - - sprintf(buf, "unknown (%d)", index); - - return buf; - } - } -} - -int get_pending_interrupts(char *buf) -{ - u32 ipr; - u32 bit; - char *p = buf; - - p += sprintf(p, "pending: ("); - - ipr = ctrl_inl(EC3104_IPR); - - for (bit = 1; bit < 32; bit++) - if (!(ipr & (1< -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -static void disable_hd64461_irq(unsigned int irq) -{ - unsigned long flags; - unsigned short nimr; - unsigned short mask = 1 << (irq - HD64461_IRQBASE); - - save_and_cli(flags); - nimr = inw(HD64461_NIMR); - nimr |= mask; - outw(nimr, HD64461_NIMR); - restore_flags(flags); -} - - -static void enable_hd64461_irq(unsigned int irq) -{ - unsigned long flags; - unsigned short nimr; - unsigned short mask = 1 << (irq - HD64461_IRQBASE); - - save_and_cli(flags); - nimr = inw(HD64461_NIMR); - nimr &= ~mask; - outw(nimr, HD64461_NIMR); - restore_flags(flags); -} - - -static void mask_and_ack_hd64461(unsigned int irq) -{ - disable_hd64461_irq(irq); -#ifdef CONFIG_HD64461_ENABLER - if (irq == HD64461_IRQBASE + 13) - outb(0x00, HD64461_PCC1CSCR); -#endif -} - - -static void end_hd64461_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_hd64461_irq(irq); -} - - -static unsigned int startup_hd64461_irq(unsigned int irq) -{ - enable_hd64461_irq(irq); - return 0; -} - - -static void shutdown_hd64461_irq(unsigned int irq) -{ - disable_hd64461_irq(irq); -} - - -static struct hw_interrupt_type hd64461_irq_type = { - "HD64461-IRQ", - startup_hd64461_irq, - shutdown_hd64461_irq, - enable_hd64461_irq, - disable_hd64461_irq, - mask_and_ack_hd64461, - end_hd64461_irq -}; - - -static void hd64461_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - printk(KERN_INFO - "HD64461: spurious interrupt, nirr: 0x%x nimr: 0x%x\n", - inw(HD64461_NIRR), inw(HD64461_NIMR)); -} - -int hd64461_irq_demux(int irq) -{ - if (irq == CONFIG_HD64461_IRQ) { - unsigned short bit; - unsigned short nirr = inw(HD64461_NIRR); - unsigned short nimr = inw(HD64461_NIMR); - nirr &= ~nimr; - for (bit = 1, irq = 0; irq < 16; bit <<= 1, irq++) - if (nirr & bit) break; - if (irq == 16) irq = CONFIG_HD64461_IRQ; - else irq += HD64461_IRQBASE; - } - return __irq_demux(irq); -} - -static struct irqaction irq0 = { hd64461_interrupt, SA_INTERRUPT, 0, "HD64461", NULL, NULL}; - - -int __init setup_hd64461(void) -{ - int i; - - if (!MACH_HD64461) - return 0; - - printk(KERN_INFO "HD64461 configured at 0x%x on irq %d(mapped into %d to %d)\n", - CONFIG_HD64461_IOBASE, CONFIG_HD64461_IRQ, - HD64461_IRQBASE, HD64461_IRQBASE+15); - -#if defined(CONFIG_CPU_SUBTYPE_SH7709) /* Should be at processor specific part.. */ - outw(0x2240, INTC_ICR1); -#endif - outw(0xffff, HD64461_NIMR); - - for (i = HD64461_IRQBASE; i < HD64461_IRQBASE + 16; i++) { - irq_desc[i].handler = &hd64461_irq_type; - } - - setup_irq(CONFIG_HD64461_IRQ, &irq0); - -#ifdef CONFIG_HD64461_ENABLER - printk(KERN_INFO "HD64461: enabling PCMCIA devices\n"); - outb(0x4c, HD64461_PCC1CSCIER); - outb(0x00, HD64461_PCC1CSCR); -#endif - - return 0; -} - -module_init(setup_hd64461); diff -urN linux-2.5.70-bk19/arch/sh/kernel/setup_hd64465.c linux-2.5.71/arch/sh/kernel/setup_hd64465.c --- linux-2.5.70-bk19/arch/sh/kernel/setup_hd64465.c 2003-05-26 18:01:00.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/setup_hd64465.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,208 +0,0 @@ -/* - * $Id: setup_hd64465.c,v 1.4 2001/07/15 23:26:56 gniibe Exp $ - * - * Setup and IRQ handling code for the HD64465 companion chip. - * by Greg Banks - * Copyright (c) 2000 PocketPenguins Inc - * - * Derived from setup_hd64461.c which bore the message: - * Copyright (C) 2000 YAEGASHI Takeshi - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#undef HD64465_DEBUG - -#ifdef HD64465_DEBUG -#define DPRINTK(args...) printk(args) -#else -#define DPRINTK(args...) -#endif - -static void disable_hd64465_irq(unsigned int irq) -{ - unsigned long flags; - unsigned short nimr; - unsigned short mask = 1 << (irq - HD64465_IRQ_BASE); - - DPRINTK("disable_hd64465_irq(%d): mask=%x\n", irq, mask); - save_and_cli(flags); - nimr = inw(HD64465_REG_NIMR); - nimr |= mask; - outw(nimr, HD64465_REG_NIMR); - restore_flags(flags); -} - - -static void enable_hd64465_irq(unsigned int irq) -{ - unsigned long flags; - unsigned short nimr; - unsigned short mask = 1 << (irq - HD64465_IRQ_BASE); - - DPRINTK("enable_hd64465_irq(%d): mask=%x\n", irq, mask); - save_and_cli(flags); - nimr = inw(HD64465_REG_NIMR); - nimr &= ~mask; - outw(nimr, HD64465_REG_NIMR); - restore_flags(flags); -} - - -static void mask_and_ack_hd64465(unsigned int irq) -{ - disable_hd64465_irq(irq); -} - - -static void end_hd64465_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_hd64465_irq(irq); -} - - -static unsigned int startup_hd64465_irq(unsigned int irq) -{ - enable_hd64465_irq(irq); - return 0; -} - - -static void shutdown_hd64465_irq(unsigned int irq) -{ - disable_hd64465_irq(irq); -} - - -static struct hw_interrupt_type hd64465_irq_type = { - .typename = "HD64465-IRQ", - .startup = startup_hd64465_irq, - .shutdown = shutdown_hd64465_irq, - .enable = enable_hd64465_irq, - .disable = disable_hd64465_irq, - .ack = mask_and_ack_hd64465, - .end = end_hd64465_irq -}; - - -static void hd64465_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - printk(KERN_INFO - "HD64465: spurious interrupt, nirr: 0x%x nimr: 0x%x\n", - inw(HD64465_REG_NIRR), inw(HD64465_REG_NIMR)); -} - - -/*====================================================*/ - -/* - * Support for a secondary IRQ demux step. This is necessary - * because the HD64465 presents a very thin interface to the - * PCMCIA bus; a lot of features (such as remapping interrupts) - * normally done in hardware by other PCMCIA host bridges is - * instead done in software. - */ -static struct -{ - int (*func)(int, void *); - void *dev; -} hd64465_demux[HD64465_IRQ_NUM]; - -void hd64465_register_irq_demux(int irq, - int (*demux)(int irq, void *dev), void *dev) -{ - hd64465_demux[irq - HD64465_IRQ_BASE].func = demux; - hd64465_demux[irq - HD64465_IRQ_BASE].dev = dev; -} -EXPORT_SYMBOL(hd64465_register_irq_demux); - -void hd64465_unregister_irq_demux(int irq) -{ - hd64465_demux[irq - HD64465_IRQ_BASE].func = 0; -} -EXPORT_SYMBOL(hd64465_unregister_irq_demux); - - - -int hd64465_irq_demux(int irq) -{ - if (irq == CONFIG_HD64465_IRQ) { - unsigned short i, bit; - unsigned short nirr = inw(HD64465_REG_NIRR); - unsigned short nimr = inw(HD64465_REG_NIMR); - - DPRINTK("hd64465_irq_demux, nirr=%04x, nimr=%04x\n", nirr, nimr); - nirr &= ~nimr; - for (bit = 1, i = 0 ; i < HD64465_IRQ_NUM ; bit <<= 1, i++) - if (nirr & bit) - break; - - if (i < HD64465_IRQ_NUM) { - irq = HD64465_IRQ_BASE + i; - if (hd64465_demux[i].func != 0) - irq = hd64465_demux[i].func(irq, hd64465_demux[i].dev); - } - } - return irq; -} - -static struct irqaction irq0 = { hd64465_interrupt, SA_INTERRUPT, 0, "HD64465", NULL, NULL}; - - -static int __init setup_hd64465(void) -{ - int i; - unsigned short rev; - unsigned short smscr; - - if (!MACH_HD64465) - return 0; - - printk(KERN_INFO "HD64465 configured at 0x%x on irq %d(mapped into %d to %d)\n", - CONFIG_HD64465_IOBASE, - CONFIG_HD64465_IRQ, - HD64465_IRQ_BASE, - HD64465_IRQ_BASE+HD64465_IRQ_NUM-1); - - if (inw(HD64465_REG_SDID) != HD64465_SDID) { - printk(KERN_ERR "HD64465 device ID not found, check base address\n"); - } - - rev = inw(HD64465_REG_SRR); - printk(KERN_INFO "HD64465 hardware revision %d.%d\n", (rev >> 8) & 0xff, rev & 0xff); - - outw(0xffff, HD64465_REG_NIMR); /* mask all interrupts */ - - for (i = 0; i < HD64465_IRQ_NUM ; i++) { - irq_desc[HD64465_IRQ_BASE + i].handler = &hd64465_irq_type; - } - - setup_irq(CONFIG_HD64465_IRQ, &irq0); - -#ifdef CONFIG_SERIAL - /* wake up the UART from STANDBY at this point */ - smscr = inw(HD64465_REG_SMSCR); - outw(smscr & (~HD64465_SMSCR_UARTST), HD64465_REG_SMSCR); - - /* remap IO ports for first ISA serial port to HD64465 UART */ - hd64465_port_map(0x3f8, 8, CONFIG_HD64465_IOBASE + 0x8000, 1); -#endif - - return 0; -} - -module_init(setup_hd64465); diff -urN linux-2.5.70-bk19/arch/sh/kernel/setup_se.c linux-2.5.71/arch/sh/kernel/setup_se.c --- linux-2.5.70-bk19/arch/sh/kernel/setup_se.c 2003-05-26 18:01:02.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/setup_se.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,119 +0,0 @@ -/* $Id: setup_se.c,v 1.6 2000/05/14 08:41:25 gniibe Exp $ - * - * linux/arch/sh/kernel/setup_se.c - * - * Copyright (C) 2000 Kazumoto Kojima - * - * Hitachi SolutionEngine Support. - * - */ - -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * Configure the Super I/O chip - */ -static void __init smsc_config(int index, int data) -{ - outb_p(index, INDEX_PORT); - outb_p(data, DATA_PORT); -} - -static void __init init_smsc(void) -{ - outb_p(CONFIG_ENTER, CONFIG_PORT); - outb_p(CONFIG_ENTER, CONFIG_PORT); - - /* FDC */ - smsc_config(CURRENT_LDN_INDEX, LDN_FDC); - smsc_config(ACTIVATE_INDEX, 0x01); - smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */ - - /* IDE1 */ - smsc_config(CURRENT_LDN_INDEX, LDN_IDE1); - smsc_config(ACTIVATE_INDEX, 0x01); - smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */ - - /* AUXIO (GPIO): to use IDE1 */ - smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO); - smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */ - smsc_config(GPIO47_INDEX, 0x00); /* nIOWOP */ - - /* COM1 */ - smsc_config(CURRENT_LDN_INDEX, LDN_COM1); - smsc_config(ACTIVATE_INDEX, 0x01); - smsc_config(IO_BASE_HI_INDEX, 0x03); - smsc_config(IO_BASE_LO_INDEX, 0xf8); - smsc_config(IRQ_SELECT_INDEX, 4); /* IRQ4 */ - - /* COM2 */ - smsc_config(CURRENT_LDN_INDEX, LDN_COM2); - smsc_config(ACTIVATE_INDEX, 0x01); - smsc_config(IO_BASE_HI_INDEX, 0x02); - smsc_config(IO_BASE_LO_INDEX, 0xf8); - smsc_config(IRQ_SELECT_INDEX, 3); /* IRQ3 */ - - /* RTC */ - smsc_config(CURRENT_LDN_INDEX, LDN_RTC); - smsc_config(ACTIVATE_INDEX, 0x01); - smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */ - - /* XXX: PARPORT, KBD, and MOUSE will come here... */ - outb_p(CONFIG_EXIT, CONFIG_PORT); -} - -/* - * Initialize IRQ setting - */ -void __init init_se_IRQ(void) -{ - /* - * Super I/O (Just mimic PC): - * 1: keyboard - * 3: serial 0 - * 4: serial 1 - * 5: printer - * 6: floppy - * 8: rtc - * 12: mouse - * 14: ide0 - */ - make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-14); - make_ipr_irq(12, BCR_ILCRA, 1, 0x0f-12); - make_ipr_irq( 8, BCR_ILCRB, 1, 0x0f- 8); - make_ipr_irq( 6, BCR_ILCRC, 3, 0x0f- 6); - make_ipr_irq( 5, BCR_ILCRC, 2, 0x0f- 5); - make_ipr_irq( 4, BCR_ILCRC, 1, 0x0f- 4); - make_ipr_irq( 3, BCR_ILCRC, 0, 0x0f- 3); - make_ipr_irq( 1, BCR_ILCRD, 3, 0x0f- 1); - - make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */ - - make_ipr_irq( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */ - make_ipr_irq(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */ - make_ipr_irq( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */ - make_ipr_irq( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */ - - /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */ - /* NOTE: #2 and #13 are not used on PC */ - make_ipr_irq(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */ - make_ipr_irq( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */ -} - - -/* - * Initialize the board - */ -void __init setup_se(void) -{ - init_smsc(); - /* XXX: RTC setting comes here */ -} diff -urN linux-2.5.70-bk19/arch/sh/kernel/setup_sh2000.c linux-2.5.71/arch/sh/kernel/setup_sh2000.c --- linux-2.5.70-bk19/arch/sh/kernel/setup_sh2000.c 2003-05-26 18:00:27.000000000 -0700 +++ linux-2.5.71/arch/sh/kernel/setup_sh2000.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,95 +0,0 @@ -/* - * linux/arch/sh/kernel/setup_sh2000.c - * - * Copyright (C) 2001 SUGIOKA Tochinobu - * - * SH-2000 Support. - * - */ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#define CF_CIS_BASE 0xb4200000 - -#define PORT_PECR 0xa4000108 -#define PORT_PHCR 0xa400010E -#define PORT_ICR1 0xa4000010 -#define PORT_IRR0 0xa4000004 - -/* - * Initialize the board - */ -int __init setup_sh2000(void) -{ - /* XXX: RTC setting comes here */ - - /* These should be done by BIOS/IPL ... */ - /* Enable nCE2A, nCE2B output */ - ctrl_outw(ctrl_inw(PORT_PECR) & ~0xf00, PORT_PECR); - /* Enable the Compact Flash card, and set the level interrupt */ - ctrl_outw(0x0042, CF_CIS_BASE+0x0200); - /* Enable interrupt */ - ctrl_outw(ctrl_inw(PORT_PHCR) & ~0x03f3, PORT_PHCR); - ctrl_outw(1, PORT_ICR1); - ctrl_outw(ctrl_inw(PORT_IRR0) & ~0xff3f, PORT_IRR0); - printk(KERN_INFO "SH-2000 Setup...done\n"); - return 0; -} -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_sh2000 __initmv = { - .mv_name = "sh2000", - - .mv_nr_irqs = 80, - - .mv_inb = generic_inb, - .mv_inw = generic_inw, - .mv_inl = generic_inl, - .mv_outb = generic_outb, - .mv_outw = generic_outw, - .mv_outl = generic_outl, - - .mv_inb_p = generic_inb_p, - .mv_inw_p = generic_inw_p, - .mv_inl_p = generic_inl_p, - .mv_outb_p = generic_outb_p, - .mv_outw_p = generic_outw_p, - .mv_outl_p = generic_outl_p, - - .mv_insb = generic_insb, - .mv_insw = generic_insw, - .mv_insl = generic_insl, - .mv_outsb = generic_outsb, - .mv_outsw = generic_outsw, - .mv_outsl = generic_outsl, - - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_init_arch = setup_sh2000, - - .mv_isa_port2addr = sh2000_isa_port2addr, - - .mv_ioremap = generic_ioremap, - .mv_iounmap = generic_iounmap, - - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, - - .mv_hw_sh2000 = 1, -}; -ALIAS_MV(sh2000) diff -urN linux-2.5.70-bk19/arch/sh/stboards/Makefile linux-2.5.71/arch/sh/stboards/Makefile --- linux-2.5.70-bk19/arch/sh/stboards/Makefile 2003-05-26 18:00:24.000000000 -0700 +++ linux-2.5.71/arch/sh/stboards/Makefile 1969-12-31 16:00:00.000000000 -0800 @@ -1,5 +0,0 @@ -# -# Makefile for STMicroelectronics board specific parts of the kernel -# - -obj-y := irq.o setup.o mach.o led.o diff -urN linux-2.5.70-bk19/arch/sh/stboards/harp.h linux-2.5.71/arch/sh/stboards/harp.h --- linux-2.5.70-bk19/arch/sh/stboards/harp.h 2003-05-26 18:00:40.000000000 -0700 +++ linux-2.5.71/arch/sh/stboards/harp.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Defintions applicable to the STMicroelectronics ST40STB1 HARP and - * compatible boards. - */ - -#if defined(CONFIG_SH_STB1_HARP) - -#define EPLD_BASE 0xa0800000 - -#define EPLD_LED (EPLD_BASE+0x000c0000) -#define EPLD_INTSTAT0 (EPLD_BASE+0x00200000) -#define EPLD_INTSTAT1 (EPLD_BASE+0x00240000) -#define EPLD_INTMASK0 (EPLD_BASE+0x00280000) -#define EPLD_INTMASK1 (EPLD_BASE+0x002c0000) -#define EPLD_PAGEADDR (EPLD_BASE+0x00300000) -#define EPLD_REVID1 (EPLD_BASE+0x00380000) -#define EPLD_REVID2 (EPLD_BASE+0x003c0000) - -#define EPLD_LED_ON 1 -#define EPLD_LED_OFF 0 - -#elif defined(CONFIG_SH_STB1_OVERDRIVE) - -#define EPLD_BASE 0xa7000000 - -#define EPLD_REVID (EPLD_BASE+0x00000000) -#define EPLD_LED (EPLD_BASE+0x00040000) -#define EPLD_INTMASK0 (EPLD_BASE+0x001c0000) -#define EPLD_INTMASK1 (EPLD_BASE+0x00200000) -#define EPLD_INTSTAT0 (EPLD_BASE+0x00240000) -#define EPLD_INTSTAT1 (EPLD_BASE+0x00280000) - -#define EPLD_LED_ON 0 -#define EPLD_LED_OFF 1 - -#else -#error Unknown board -#endif diff -urN linux-2.5.70-bk19/arch/sh/stboards/irq.c linux-2.5.71/arch/sh/stboards/irq.c --- linux-2.5.70-bk19/arch/sh/stboards/irq.c 2003-05-26 18:00:40.000000000 -0700 +++ linux-2.5.71/arch/sh/stboards/irq.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2000 David J. Mckay (david.mckay@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Looks after interrupts on the HARP board. - * - * Bases on the IPR irq system - */ - -#include -#include -#include - -#include -#include - -#include "harp.h" - - -#define NUM_EXTERNAL_IRQS 16 - -// Early versions of the STB1 Overdrive required this nasty frig -//#define INVERT_INTMASK_WRITES - -static void enable_harp_irq(unsigned int irq); -static void disable_harp_irq(unsigned int irq); - -/* shutdown is same as "disable" */ -#define shutdown_harp_irq disable_harp_irq - -static void mask_and_ack_harp(unsigned int); -static void end_harp_irq(unsigned int irq); - -static unsigned int startup_harp_irq(unsigned int irq) -{ - enable_harp_irq(irq); - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type harp_irq_type = { - "Harp-IRQ", - startup_harp_irq, - shutdown_harp_irq, - enable_harp_irq, - disable_harp_irq, - mask_and_ack_harp, - end_harp_irq -}; - -static void disable_harp_irq(unsigned int irq) -{ - unsigned val, flags; - unsigned maskReg; - unsigned mask; - int pri; - - if (irq < 0 || irq >= NUM_EXTERNAL_IRQS) - return; - - pri = 15 - irq; - - if (pri < 8) { - maskReg = EPLD_INTMASK0; - } else { - maskReg = EPLD_INTMASK1; - pri -= 8; - } - - save_and_cli(flags); - mask = ctrl_inl(maskReg); - mask &= (~(1 << pri)); -#if defined(INVERT_INTMASK_WRITES) - mask ^= 0xff; -#endif - ctrl_outl(mask, maskReg); - restore_flags(flags); -} - -static void enable_harp_irq(unsigned int irq) -{ - unsigned flags; - unsigned maskReg; - unsigned mask; - int pri; - - if (irq < 0 || irq >= NUM_EXTERNAL_IRQS) - return; - - pri = 15 - irq; - - if (pri < 8) { - maskReg = EPLD_INTMASK0; - } else { - maskReg = EPLD_INTMASK1; - pri -= 8; - } - - save_and_cli(flags); - mask = ctrl_inl(maskReg); - - - mask |= (1 << pri); - -#if defined(INVERT_INTMASK_WRITES) - mask ^= 0xff; -#endif - ctrl_outl(mask, maskReg); - - restore_flags(flags); -} - -/* This functions sets the desired irq handler to be an overdrive type */ -static void __init make_harp_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - irq_desc[irq].handler = &harp_irq_type; - disable_harp_irq(irq); -} - -static void mask_and_ack_harp(unsigned int irq) -{ - disable_harp_irq(irq); -} - -static void end_harp_irq(unsigned int irq) -{ - enable_harp_irq(irq); -} - -void __init init_harp_irq(void) -{ - int i; - -#if !defined(INVERT_INTMASK_WRITES) - // On the harp these are set to enable an interrupt - ctrl_outl(0x00, EPLD_INTMASK0); - ctrl_outl(0x00, EPLD_INTMASK1); -#else - // On the Overdrive the data is inverted before being stored in the reg - ctrl_outl(0xff, EPLD_INTMASK0); - ctrl_outl(0xff, EPLD_INTMASK1); -#endif - - for (i = 0; i < NUM_EXTERNAL_IRQS; i++) { - make_harp_irq(i); - } -} diff -urN linux-2.5.70-bk19/arch/sh/stboards/led.c linux-2.5.71/arch/sh/stboards/led.c --- linux-2.5.70-bk19/arch/sh/stboards/led.c 2003-05-26 18:00:24.000000000 -0700 +++ linux-2.5.71/arch/sh/stboards/led.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,52 +0,0 @@ -/* - * linux/arch/sh/stboards/led.c - * - * Copyright (C) 2000 Stuart Menefy - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * This file contains ST40STB1 HARP and compatible code. - */ - -#include -#include -#include "harp.h" - -/* Harp: Flash LD10 (front pannel) connected to EPLD (IC8) */ -/* Overdrive: Flash LD1 (front panel) connected to EPLD (IC4) */ -/* Works for HARP and overdrive */ -static void mach_led(int position, int value) -{ - if (value) { - ctrl_outl(EPLD_LED_ON, EPLD_LED); - } else { - ctrl_outl(EPLD_LED_OFF, EPLD_LED); - } -} - -#ifdef CONFIG_HEARTBEAT - -#include - -/* acts like an actual heart beat -- ie thump-thump-pause... */ -void heartbeat_harp(void) -{ - static unsigned cnt = 0, period = 0, dist = 0; - - if (cnt == 0 || cnt == dist) - mach_led( -1, 1); - else if (cnt == 7 || cnt == dist+7) - mach_led( -1, 0); - - if (++cnt > period) { - cnt = 0; - /* The hyperbolic function below modifies the heartbeat period - * length in dependency of the current (5min) load. It goes - * through the points f(0)=126, f(1)=86, f(5)=51, - * f(inf)->30. */ - period = ((672< - -#include -#include -#include -#include -#include - -void setup_harp(void); -void init_harp_irq(void); -void heartbeat_harp(void); - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_harp __initmv = { - .mv_name = "STB1 Harp", - - .mv_nr_irqs = 89 + HD64465_IRQ_NUM, - - .mv_inb = hd64465_inb, - .mv_inw = hd64465_inw, - .mv_inl = hd64465_inl, - .mv_outb = hd64465_outb, - .mv_outw = hd64465_outw, - .mv_outl = hd64465_outl, - - .mv_inb_p = hd64465_inb_p, - .mv_inw_p = hd64465_inw, - .mv_inl_p = hd64465_inl, - .mv_outb_p = hd64465_outb_p, - .mv_outw_p = hd64465_outw, - .mv_outl_p = hd64465_outl, - - .mv_insb = hd64465_insb, - .mv_insw = hd64465_insw, - .mv_insl = hd64465_insl, - .mv_outsb = hd64465_outsb, - .mv_outsw = hd64465_outsw, - .mv_outsl = hd64465_outsl, - - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_ioremap = generic_ioremap, - .mv_iounmap = generic_iounmap, - - .mv_isa_port2addr = hd64465_isa_port2addr, - - .mv_init_arch = setup_harp, -#ifdef CONFIG_PCI - .mv_init_irq = init_harp_irq, -#endif -#ifdef CONFIG_HEARTBEAT - .mv_heartbeat = heartbeat_harp, -#endif - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, -}; - -ALIAS_MV(harp) diff -urN linux-2.5.70-bk19/arch/sh/stboards/pcidma.c linux-2.5.71/arch/sh/stboards/pcidma.c --- linux-2.5.70-bk19/arch/sh/stboards/pcidma.c 2003-05-26 18:00:39.000000000 -0700 +++ linux-2.5.71/arch/sh/stboards/pcidma.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Dynamic DMA mapping support. - */ - -#include -#include -#include -#include -#include -#include - - -void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t * dma_handle) -{ - void *ret; - int gfp = GFP_ATOMIC; - - ret = (void *) __get_free_pages(gfp, get_order(size)); - - if (ret != NULL) { - /* Is it necessary to do the memset? */ - memset(ret, 0, size); - *dma_handle = virt_to_bus(ret); - } - /* We must flush the cache before we pass it on to the device */ - flush_cache_all(); - return P2SEGADDR(ret); -} - -void pci_free_consistent(struct pci_dev *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - unsigned long p1addr=P1SEGADDR((unsigned long)vaddr); - - free_pages(p1addr, get_order(size)); -} diff -urN linux-2.5.70-bk19/arch/sh/stboards/setup.c linux-2.5.71/arch/sh/stboards/setup.c --- linux-2.5.70-bk19/arch/sh/stboards/setup.c 2003-05-26 18:00:26.000000000 -0700 +++ linux-2.5.71/arch/sh/stboards/setup.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,50 +0,0 @@ -/* - * arch/sh/stboard/setup.c - * - * Copyright (C) 2001 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * STMicroelectronics ST40STB1 HARP and compatible support. - */ - -#include -#include -#include -#include -#include "harp.h" -/* - * Initialize the board - */ -int __init setup_harp(void) -{ -#ifdef CONFIG_SH_STB1_HARP - unsigned long ic8_version, ic36_version; - - ic8_version = ctrl_inl(EPLD_REVID2); - ic36_version = ctrl_inl(EPLD_REVID1); - - printk("STMicroelectronics STB1 HARP initialisaton\n"); - printk("EPLD versions: IC8: %d.%02d, IC36: %d.%02d\n", - (ic8_version >> 4) & 0xf, ic8_version & 0xf, - (ic36_version >> 4) & 0xf, ic36_version & 0xf); -#elif defined(CONFIG_SH_STB1_OVERDRIVE) - unsigned long version; - - version = ctrl_inl(EPLD_REVID); - - printk("STMicroelectronics STB1 Overdrive initialisaton\n"); - printk("EPLD version: %d.%02d\n", - (version >> 4) & 0xf, version & 0xf); -#else -#error Undefined machine -#endif - - /* Currently all STB1 chips have problems with the sleep instruction, - * so disable it here. - */ - disable_hlt(); - - return 0; -} diff -urN linux-2.5.70-bk19/arch/sh/vmlinux.lds.S linux-2.5.71/arch/sh/vmlinux.lds.S --- linux-2.5.70-bk19/arch/sh/vmlinux.lds.S 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/arch/sh/vmlinux.lds.S 2003-06-14 13:53:23.000000000 -0700 @@ -1,4 +1,4 @@ -/* $Id: vmlinux.lds.in,v 1.5 2001/07/27 11:45:55 gniibe Exp $ +/* $Id: vmlinux.lds.S,v 1.8 2003/05/16 17:18:14 lethal Exp $ * ld script to make SuperH Linux kernel * Written by Niibe Yutaka */ @@ -7,16 +7,14 @@ #ifdef CONFIG_CPU_LITTLE_ENDIAN OUTPUT_FORMAT("elf32-sh-linux", "elf32-sh-linux", "elf32-sh-linux") -jiffies = jiffies_64; #else OUTPUT_FORMAT("elf32-shbig-linux", "elf32-shbig-linux", "elf32-shbig-linux") -jiffies = jiffies_64 + 4; #endif OUTPUT_ARCH(sh) ENTRY(_start) SECTIONS { - . = 0x80000000 + CONFIG_MEMORY_START + 0x1000; + . = 0x80000000 + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET; _text = .; /* Text and read-only data */ text = .; /* Text and read-only data */ .empty_zero_page : { @@ -42,6 +40,15 @@ CONSTRUCTORS } + . = ALIGN(4096); + .data.page_aligned : { *(.data.idt) } + + . = ALIGN(32); + __per_cpu_start = .; + .data.percpu : { *(.data.percpu) } + __per_cpu_end = .; + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + _edata = .; /* End of data section */ . = ALIGN(8192); /* init_task */ @@ -51,12 +58,17 @@ . = ALIGN(4096); /* Init code and data */ __init_begin = .; - .text.init : { *(.text.init) } - .data.init : { *(.data.init) } + _sinittext = .; + .init.text : { *(.init.text) } + _einittext = .; + .init.data : { *(.init.data) } . = ALIGN(16); __setup_start = .; - .setup.init : { *(.setup.init) } + .init.setup : { *(.init.setup) } __setup_end = .; + __start___param = .; + __param : { *(__param) } + __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) @@ -72,27 +84,19 @@ .con_initcall.init : { *(.con_initcall.init) } __con_initcall_end = .; SECURITY_INIT + __initramfs_start = .; + .init.ramfs : { *(.init.ramfs) } + __initramfs_end = .; __machvec_start = .; - .machvec.init : { *(.machvec.init) } + .init.machvec : { *(.init.machvec) } __machvec_end = .; . = ALIGN(4096); __init_end = .; - . = ALIGN(4096); - .data.page_aligned : { *(.data.idt) } - -#ifdef CONFIG_CPU_SH3 - . = ALIGN(16); -#else - . = ALIGN(32); -#endif - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - . = ALIGN(4); __bss_start = .; /* BSS */ - .bss : { - *(.bss) - } + .bss : { *(.bss) } + . = ALIGN(4); _end = . ; @@ -102,8 +106,8 @@ * it's a module. */ /DISCARD/ : { - *(.text.exit) - *(.data.exit) + *(.exit.text) + *(.exit.data) *(.exitcall.exit) } diff -urN linux-2.5.70-bk19/drivers/char/Makefile linux-2.5.71/drivers/char/Makefile --- linux-2.5.70-bk19/drivers/char/Makefile 2003-05-26 18:00:59.000000000 -0700 +++ linux-2.5.71/drivers/char/Makefile 2003-06-14 13:53:23.000000000 -0700 @@ -82,8 +82,11 @@ # Files generated that shall be removed upon make clean clean-files := consolemap_deftbl.c defkeymap.c qtronixmap.c +quiet_cmd_conmk = CONMK $@ + cmd_conmk = scripts/conmakehash $< > $@ + $(obj)/consolemap_deftbl.c: $(src)/$(FONTMAPFILE) - $(call do_cmd,CONMK $@,$(objtree)/scripts/conmakehash $< > $@) + $(call cmd,conmk) $(obj)/defkeymap.o: $(obj)/defkeymap.c diff -urN linux-2.5.70-bk19/drivers/char/agp/intel-agp.c linux-2.5.71/drivers/char/agp/intel-agp.c --- linux-2.5.70-bk19/drivers/char/agp/intel-agp.c 2003-06-14 13:53:17.000000000 -0700 +++ linux-2.5.71/drivers/char/agp/intel-agp.c 2003-06-14 13:53:23.000000000 -0700 @@ -951,7 +951,7 @@ .cleanup = intel_cleanup, .tlb_flush = intel_tlbflush, .mask_memory = agp_generic_mask_memory, - .masks = NULL, + .masks = intel_generic_masks, .agp_enable = agp_generic_enable, .cache_flush = global_cache_flush, .create_gatt_table = agp_generic_create_gatt_table, diff -urN linux-2.5.70-bk19/drivers/net/acenic.c linux-2.5.71/drivers/net/acenic.c --- linux-2.5.70-bk19/drivers/net/acenic.c 2003-06-14 13:53:18.000000000 -0700 +++ linux-2.5.71/drivers/net/acenic.c 2003-06-14 13:53:24.000000000 -0700 @@ -642,8 +642,7 @@ (pdev->device == PCI_DEVICE_ID_SGI_ACENIC))) continue; - dev = init_etherdev(NULL, sizeof(struct ace_private)); - + dev = alloc_etherdev(sizeof(struct ace_private)); if (dev == NULL) { printk(KERN_ERR "acenic: Unable to allocate " "net_device structure!\n"); @@ -653,13 +652,6 @@ SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); - if (!dev->priv) - dev->priv = kmalloc(sizeof(*ap), GFP_KERNEL); - if (!dev->priv) { - printk(KERN_ERR "acenic: Unable to allocate memory\n"); - return -ENOMEM; - } - ap = dev->priv; ap->pdev = pdev; @@ -739,6 +731,12 @@ break; } + if (register_netdev(dev)) { + printk(KERN_ERR "acenic: device registration failed\n"); + kfree(dev); + continue; + } + switch(pdev->vendor) { case PCI_VENDOR_ID_ALTEON: if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) { diff -urN linux-2.5.70-bk19/drivers/net/dummy.c linux-2.5.71/drivers/net/dummy.c --- linux-2.5.70-bk19/drivers/net/dummy.c 2003-05-26 18:00:39.000000000 -0700 +++ linux-2.5.71/drivers/net/dummy.c 2003-06-14 13:53:24.000000000 -0700 @@ -51,15 +51,9 @@ } #endif -static int __init dummy_init(struct net_device *dev) +static void __init dummy_setup(struct net_device *dev) { /* Initialize the device structure. */ - - dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct net_device_stats)); - dev->get_stats = dummy_get_stats; dev->hard_start_xmit = dummy_xmit; dev->set_multicast_list = set_multicast_list; @@ -72,8 +66,7 @@ dev->tx_queue_len = 0; dev->flags |= IFF_NOARP; dev->flags &= ~IFF_MULTICAST; - - return 0; + SET_MODULE_OWNER(dev); } static int dummy_xmit(struct sk_buff *skb, struct net_device *dev) @@ -92,32 +85,30 @@ return dev->priv; } -static struct net_device dev_dummy; +static struct net_device *dev_dummy; static int __init dummy_init_module(void) { int err; - dev_dummy.init = dummy_init; - SET_MODULE_OWNER(&dev_dummy); + dev_dummy = alloc_netdev(sizeof(struct net_device_stats), + "dummy%d", dummy_setup); - /* Find a name for this unit */ - err=dev_alloc_name(&dev_dummy,"dummy%d"); - if(err<0) - return err; - err = register_netdev(&dev_dummy); - if (err<0) - return err; - return 0; + if (!dev_dummy) + return -ENOMEM; + + if ((err = register_netdev(dev_dummy))) { + kfree(dev_dummy); + dev_dummy = NULL; + } + return err; } static void __exit dummy_cleanup_module(void) { - unregister_netdev(&dev_dummy); - kfree(dev_dummy.priv); - - memset(&dev_dummy, 0, sizeof(dev_dummy)); - dev_dummy.init = dummy_init; + unregister_netdev(dev_dummy); + kfree(dev_dummy); + dev_dummy = NULL; } module_init(dummy_init_module); diff -urN linux-2.5.70-bk19/drivers/net/net_init.c linux-2.5.71/drivers/net/net_init.c --- linux-2.5.70-bk19/drivers/net/net_init.c 2003-06-14 13:53:18.000000000 -0700 +++ linux-2.5.71/drivers/net/net_init.c 2003-06-14 13:53:24.000000000 -0700 @@ -70,7 +70,7 @@ */ -static struct net_device *alloc_netdev(int sizeof_priv, const char *mask, +struct net_device *alloc_netdev(int sizeof_priv, const char *mask, void (*setup)(struct net_device *)) { struct net_device *dev; @@ -96,6 +96,7 @@ return dev; } +EXPORT_SYMBOL(alloc_netdev); static struct net_device *init_alloc_dev(int sizeof_priv) { diff -urN linux-2.5.70-bk19/drivers/net/ppp_deflate.c linux-2.5.71/drivers/net/ppp_deflate.c --- linux-2.5.70-bk19/drivers/net/ppp_deflate.c 2003-06-14 13:53:18.000000000 -0700 +++ linux-2.5.71/drivers/net/ppp_deflate.c 2003-06-14 13:53:24.000000000 -0700 @@ -456,10 +456,10 @@ /* Check the sequence number. */ seq = (ibuf[PPP_HDRLEN] << 8) + ibuf[PPP_HDRLEN+1]; - if (seq != state->seqno) { + if (seq != (state->seqno & 0xffff)) { if (state->debug) printk(KERN_DEBUG "z_decompress%d: bad seq # %d, expected %d\n", - state->unit, seq, state->seqno); + state->unit, seq, state->seqno & 0xffff); return DECOMP_ERROR; } ++state->seqno; diff -urN linux-2.5.70-bk19/drivers/net/slip.c linux-2.5.71/drivers/net/slip.c --- linux-2.5.70-bk19/drivers/net/slip.c 2003-05-26 18:01:03.000000000 -0700 +++ linux-2.5.71/drivers/net/slip.c 2003-06-14 13:53:24.000000000 -0700 @@ -1381,27 +1381,23 @@ local_bh_enable(); } while (busy && time_before(jiffies, timeout)); - busy = 0; for (i = 0; i < slip_maxdev; i++) { struct slip_ctrl *slc = slip_ctrls[i]; if (slc) { unregister_netdev(&slc->dev); if (slc->ctrl.tty) { printk(KERN_ERR "%s: tty discipline is still running\n", slc->dev.name); - /* Pin module forever */ - MOD_INC_USE_COUNT; - busy++; - continue; + /* Intentionally leak the control block. */ + } else { + sl_free_bufs(&slc->ctrl); + kfree(slc); } - sl_free_bufs(&slc->ctrl); - kfree(slc); slip_ctrls[i] = NULL; } } - if (!busy) { - kfree(slip_ctrls); - slip_ctrls = NULL; - } + + kfree(slip_ctrls); + slip_ctrls = NULL; } if ((i = tty_register_ldisc(N_SLIP, NULL))) { diff -urN linux-2.5.70-bk19/drivers/net/sungem.c linux-2.5.71/drivers/net/sungem.c --- linux-2.5.70-bk19/drivers/net/sungem.c 2003-06-14 13:53:18.000000000 -0700 +++ linux-2.5.71/drivers/net/sungem.c 2003-06-14 13:53:24.000000000 -0700 @@ -2676,7 +2676,7 @@ */ if (pdev->vendor == PCI_VENDOR_ID_SUN && pdev->device == PCI_DEVICE_ID_SUN_GEM && - !pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff)) { + !pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL)) { pci_using_dac = 1; } else { err = pci_set_dma_mask(pdev, (u64) 0xffffffff); diff -urN linux-2.5.70-bk19/drivers/net/sungem.h linux-2.5.71/drivers/net/sungem.h --- linux-2.5.70-bk19/drivers/net/sungem.h 2003-06-14 13:53:18.000000000 -0700 +++ linux-2.5.71/drivers/net/sungem.h 2003-06-14 13:53:24.000000000 -0700 @@ -805,14 +805,14 @@ u64 buffer; }; -#define TXDCTRL_BUFSZ 0x0000000000007fff /* Buffer Size */ -#define TXDCTRL_CSTART 0x00000000001f8000 /* CSUM Start Offset */ -#define TXDCTRL_COFF 0x000000001fe00000 /* CSUM Stuff Offset */ -#define TXDCTRL_CENAB 0x0000000020000000 /* CSUM Enable */ -#define TXDCTRL_EOF 0x0000000040000000 /* End of Frame */ -#define TXDCTRL_SOF 0x0000000080000000 /* Start of Frame */ -#define TXDCTRL_INTME 0x0000000100000000 /* "Interrupt Me" */ -#define TXDCTRL_NOCRC 0x0000000200000000 /* No CRC Present */ +#define TXDCTRL_BUFSZ 0x0000000000007fffULL /* Buffer Size */ +#define TXDCTRL_CSTART 0x00000000001f8000ULL /* CSUM Start Offset */ +#define TXDCTRL_COFF 0x000000001fe00000ULL /* CSUM Stuff Offset */ +#define TXDCTRL_CENAB 0x0000000020000000ULL /* CSUM Enable */ +#define TXDCTRL_EOF 0x0000000040000000ULL /* End of Frame */ +#define TXDCTRL_SOF 0x0000000080000000ULL /* Start of Frame */ +#define TXDCTRL_INTME 0x0000000100000000ULL /* "Interrupt Me" */ +#define TXDCTRL_NOCRC 0x0000000200000000ULL /* No CRC Present */ /* GEM requires that RX descriptors are provided four at a time, * aligned. Also, the RX ring may not wrap around. This means that @@ -840,13 +840,13 @@ u64 buffer; }; -#define RXDCTRL_TCPCSUM 0x000000000000ffff /* TCP Pseudo-CSUM */ -#define RXDCTRL_BUFSZ 0x000000007fff0000 /* Buffer Size */ -#define RXDCTRL_OWN 0x0000000080000000 /* GEM owns this entry */ -#define RXDCTRL_HASHVAL 0x0ffff00000000000 /* Hash Value */ -#define RXDCTRL_HPASS 0x1000000000000000 /* Passed Hash Filter */ -#define RXDCTRL_ALTMAC 0x2000000000000000 /* Matched ALT MAC */ -#define RXDCTRL_BAD 0x4000000000000000 /* Frame has bad CRC */ +#define RXDCTRL_TCPCSUM 0x000000000000ffffULL /* TCP Pseudo-CSUM */ +#define RXDCTRL_BUFSZ 0x000000007fff0000ULL /* Buffer Size */ +#define RXDCTRL_OWN 0x0000000080000000ULL /* GEM owns this entry */ +#define RXDCTRL_HASHVAL 0x0ffff00000000000ULL /* Hash Value */ +#define RXDCTRL_HPASS 0x1000000000000000ULL /* Passed Hash Filter */ +#define RXDCTRL_ALTMAC 0x2000000000000000ULL /* Matched ALT MAC */ +#define RXDCTRL_BAD 0x4000000000000000ULL /* Frame has bad CRC */ #define RXDCTRL_FRESH(gp) \ ((((RX_BUF_ALLOC_SIZE(gp) - RX_OFFSET) << 16) & RXDCTRL_BUFSZ) | \ diff -urN linux-2.5.70-bk19/drivers/net/tg3.c linux-2.5.71/drivers/net/tg3.c --- linux-2.5.70-bk19/drivers/net/tg3.c 2003-06-14 13:53:18.000000000 -0700 +++ linux-2.5.71/drivers/net/tg3.c 2003-06-14 13:53:24.000000000 -0700 @@ -32,10 +32,6 @@ #include #include -#ifndef PCI_DMA_BUS_IS_PHYS -#define PCI_DMA_BUS_IS_PHYS 1 -#endif - #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) #define TG3_VLAN_TAG_USED 1 #else @@ -55,8 +51,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.5" -#define DRV_MODULE_RELDATE "March 21, 2003" +#define DRV_MODULE_VERSION "1.6" +#define DRV_MODULE_RELDATE "June 11, 2003" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -2234,73 +2230,17 @@ schedule_work(&tp->reset_task); } -#if !PCI_DMA_BUS_IS_PHYS -static void tg3_set_txd_addr(struct tg3 *tp, int entry, dma_addr_t mapping) -{ - if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) { - struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry]; - - txd->addr_hi = ((u64) mapping >> 32); - txd->addr_lo = ((u64) mapping & 0xffffffff); - } else { - unsigned long txd; - - txd = (tp->regs + - NIC_SRAM_WIN_BASE + - NIC_SRAM_TX_BUFFER_DESC); - txd += (entry * TXD_SIZE); - - if (sizeof(dma_addr_t) != sizeof(u32)) - writel(((u64) mapping >> 32), - txd + TXD_ADDR + TG3_64BIT_REG_HIGH); - - writel(((u64) mapping & 0xffffffff), - txd + TXD_ADDR + TG3_64BIT_REG_LOW); - } -} -#endif - static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32); static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, u32 guilty_entry, int guilty_len, u32 last_plus_one, u32 *start, u32 mss) { + struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC); dma_addr_t new_addr; u32 entry = *start; int i; -#if !PCI_DMA_BUS_IS_PHYS - /* IOMMU, just map the guilty area again which is guaranteed to - * use different addresses. - */ - - i = 0; - while (entry != guilty_entry) { - entry = NEXT_TX(entry); - i++; - } - if (i == 0) { - new_addr = pci_map_single(tp->pdev, skb->data, guilty_len, - PCI_DMA_TODEVICE); - } else { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; - - new_addr = pci_map_page(tp->pdev, - frag->page, frag->page_offset, - guilty_len, PCI_DMA_TODEVICE); - } - pci_unmap_single(tp->pdev, pci_unmap_addr(&tp->tx_buffers[guilty_entry], - mapping), - guilty_len, PCI_DMA_TODEVICE); - tg3_set_txd_addr(tp, guilty_entry, new_addr); - pci_unmap_addr_set(&tp->tx_buffers[guilty_entry], mapping, - new_addr); - *start = last_plus_one; -#else - /* Oh well, no IOMMU, have to allocate a whole new SKB. */ - struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC); - if (!new_skb) { dev_kfree_skb(skb); return -1; @@ -2337,7 +2277,6 @@ } dev_kfree_skb(skb); -#endif return 0; } diff -urN linux-2.5.70-bk19/drivers/net/tun.c linux-2.5.71/drivers/net/tun.c --- linux-2.5.70-bk19/drivers/net/tun.c 2003-06-14 13:53:18.000000000 -0700 +++ linux-2.5.71/drivers/net/tun.c 2003-06-14 13:53:24.000000000 -0700 @@ -122,12 +122,6 @@ DBG(KERN_INFO "%s: tun_net_init\n", tun->name); - SET_MODULE_OWNER(dev); - dev->open = tun_net_open; - dev->hard_start_xmit = tun_net_xmit; - dev->stop = tun_net_close; - dev->get_stats = tun_net_stats; - switch (tun->flags & TUN_TYPE_MASK) { case TUN_TUN_DEV: /* Point-to-Point TUN Device */ @@ -199,14 +193,14 @@ skb_reserve(skb, 2); memcpy_fromiovec(skb_put(skb, len), iv, len); - skb->dev = &tun->dev; + skb->dev = tun->dev; switch (tun->flags & TUN_TYPE_MASK) { case TUN_TUN_DEV: skb->mac.raw = skb->data; skb->protocol = pi.proto; break; case TUN_TAP_DEV: - skb->protocol = eth_type_trans(skb, &tun->dev); + skb->protocol = eth_type_trans(skb, tun->dev); break; }; @@ -325,7 +319,7 @@ schedule(); continue; } - netif_start_queue(&tun->dev); + netif_start_queue(tun->dev); ret = tun_put_user(tun, skb, (struct iovec *) iv, len); @@ -347,6 +341,24 @@ return tun_chr_readv(file, &iv, 1, pos); } +static void tun_setup(struct net_device *dev) +{ + struct tun_struct *tun = dev->priv; + + skb_queue_head_init(&tun->readq); + init_waitqueue_head(&tun->read_wait); + + tun->owner = -1; + dev->init = tun_net_init; + tun->name = dev->name; + SET_MODULE_OWNER(dev); + dev->open = tun_net_open; + dev->hard_start_xmit = tun_net_xmit; + dev->stop = tun_net_close; + dev->get_stats = tun_net_stats; + dev->destructor = (void (*)(struct net_device *))kfree; +} + static int tun_set_iff(struct file *file, struct ifreq *ifr) { struct tun_struct *tun; @@ -367,30 +379,18 @@ return -EPERM; } else { char *name; - - /* Allocate new device */ - if (!(tun = kmalloc(sizeof(struct tun_struct), GFP_KERNEL)) ) - return -ENOMEM; - memset(tun, 0, sizeof(struct tun_struct)); - - skb_queue_head_init(&tun->readq); - init_waitqueue_head(&tun->read_wait); - - tun->owner = -1; - tun->dev.init = tun_net_init; - tun->dev.priv = tun; - SET_MODULE_OWNER(&tun->dev); + unsigned long flags = 0; err = -EINVAL; /* Set dev type */ if (ifr->ifr_flags & IFF_TUN) { /* TUN device */ - tun->flags |= TUN_TUN_DEV; + flags |= TUN_TUN_DEV; name = "tun%d"; } else if (ifr->ifr_flags & IFF_TAP) { /* TAP device */ - tun->flags |= TUN_TAP_DEV; + flags |= TUN_TAP_DEV; name = "tap%d"; } else goto failed; @@ -398,12 +398,27 @@ if (*ifr->ifr_name) name = ifr->ifr_name; - if ((err = dev_alloc_name(&tun->dev, name)) < 0) - goto failed; - if ((err = register_netdevice(&tun->dev))) + dev = alloc_netdev(sizeof(struct tun_struct), name, + tun_setup); + if (!dev) + return -ENOMEM; + + tun = dev->priv; + tun->flags = flags; + + if (strchr(dev->name, '%')) { + err = dev_alloc_name(dev, dev->name); + if (err < 0) { + kfree(dev); + goto failed; + } + } + + if ((err = register_netdevice(tun->dev))) { + kfree(dev); goto failed; + } - tun->name = tun->dev.name; } DBG(KERN_INFO "%s: tun_set_iff\n", tun->name); @@ -419,9 +434,7 @@ strcpy(ifr->ifr_name, tun->name); return 0; - -failed: - kfree(tun); + failed: return err; } @@ -548,10 +561,8 @@ /* Drop read queue */ skb_queue_purge(&tun->readq); - if (!(tun->flags & TUN_PERSIST)) { - dev_close(&tun->dev); - unregister_netdevice(&tun->dev); - } + if (!(tun->flags & TUN_PERSIST)) + unregister_netdevice(tun->dev); rtnl_unlock(); @@ -574,11 +585,10 @@ .fasync = tun_chr_fasync }; -static struct miscdevice tun_miscdev= -{ - TUN_MINOR, - "net/tun", - &tun_fops +static struct miscdevice tun_miscdev = { + .minor = TUN_MINOR, + .name = "net/tun", + .fops = &tun_fops }; int __init tun_init(void) diff -urN linux-2.5.70-bk19/drivers/pci/Makefile linux-2.5.71/drivers/pci/Makefile --- linux-2.5.70-bk19/drivers/pci/Makefile 2003-06-14 13:53:18.000000000 -0700 +++ linux-2.5.71/drivers/pci/Makefile 2003-06-14 13:53:24.000000000 -0700 @@ -42,16 +42,17 @@ host-progs := gen-devlist -# Files generated that shall be removed upon make clean -clean-files := devlist.h classlist.h - # Dependencies on generated files need to be listed explicitly - $(obj)/names.o: $(obj)/devlist.h $(obj)/classlist.h +$(obj)/classlist.h: $(obj)/devlist.h # And that's how to generate them - +quiet_cmd_devlist = DEVLIST $@ + cmd_devlist = ( cd $(obj); ./gen-devlist ) < $< $(obj)/devlist.h: $(src)/pci.ids $(obj)/gen-devlist - ( cd $(obj); ./gen-devlist ) < $< + $(call cmd,devlist) + +# Files generated that shall be removed upon make clean +clean-files := devlist.h classlist.h + -$(obj)/classlist.h: $(obj)/devlist.h diff -urN linux-2.5.70-bk19/drivers/serial/8250.c linux-2.5.71/drivers/serial/8250.c --- linux-2.5.70-bk19/drivers/serial/8250.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/drivers/serial/8250.c 2003-06-14 13:53:25.000000000 -0700 @@ -2061,9 +2061,11 @@ return __register_serial(req, -1); } -int __init early_serial_setup(struct serial_struct *req) +int __init early_serial_setup(struct uart_port *port) { - __register_serial(req, req->line); + serial8250_isa_init_ports(); + serial8250_ports[port->line].port = *port; + serial8250_ports[port->line].port.ops = &serial8250_pops; return 0; } diff -urN linux-2.5.70-bk19/drivers/serial/8250_acpi.c linux-2.5.71/drivers/serial/8250_acpi.c --- linux-2.5.70-bk19/drivers/serial/8250_acpi.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/drivers/serial/8250_acpi.c 2003-06-14 13:53:25.000000000 -0700 @@ -0,0 +1,110 @@ +/* + * serial/acpi.c + * Copyright (c) 2002-2003 Matthew Wilcox for Hewlett-Packard + * + * 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. + */ + +#include +#include +#include +#include + +#include + +#include +#include + +static void acpi_serial_address(struct serial_struct *req, + struct acpi_resource_address32 *addr32) +{ + unsigned long size; + + size = addr32->max_address_range - addr32->min_address_range + 1; + req->iomap_base = addr32->min_address_range; + req->iomem_base = ioremap(req->iomap_base, size); + req->io_type = SERIAL_IO_MEM; +} + +static void acpi_serial_irq(struct serial_struct *req, + struct acpi_resource_ext_irq *ext_irq) +{ + if (ext_irq->number_of_interrupts > 0) { +#ifdef CONFIG_IA64 + req->irq = acpi_register_irq(ext_irq->interrupts[0], + ext_irq->active_high_low, ext_irq->edge_level); +#else + req->irq = ext_irq->interrupts[0]; +#endif + } +} + +static int acpi_serial_add(struct acpi_device *device) +{ + acpi_status result; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct serial_struct serial_req; + int line, offset = 0; + + memset(&serial_req, 0, sizeof(serial_req)); + result = acpi_get_current_resources(device->handle, &buffer); + if (ACPI_FAILURE(result)) { + result = -ENODEV; + goto out; + } + + while (offset <= buffer.length) { + struct acpi_resource *res = buffer.pointer + offset; + if (res->length == 0) + break; + offset += res->length; + if (res->id == ACPI_RSTYPE_ADDRESS32) { + acpi_serial_address(&serial_req, &res->data.address32); + } else if (res->id == ACPI_RSTYPE_EXT_IRQ) { + acpi_serial_irq(&serial_req, &res->data.extended_irq); + } + } + + serial_req.baud_base = BASE_BAUD; + serial_req.flags = ASYNC_SKIP_TEST|ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ; + + result = 0; + line = register_serial(&serial_req); + if (line < 0) + result = -ENODEV; + + out: + acpi_os_free(buffer.pointer); + return result; +} + +static int acpi_serial_remove(struct acpi_device *device, int type) +{ + return 0; +} + +static struct acpi_driver acpi_serial_driver = { + .name = "serial", + .class = "", + .ids = "PNP0501", + .ops = { + .add = acpi_serial_add, + .remove = acpi_serial_remove, + }, +}; + +static int __init acpi_serial_init(void) +{ + return acpi_bus_register_driver(&acpi_serial_driver); +} + +static void __exit acpi_serial_exit(void) +{ + acpi_bus_unregister_driver(&acpi_serial_driver); +} + +module_init(acpi_serial_init); +module_exit(acpi_serial_exit); diff -urN linux-2.5.70-bk19/drivers/serial/8250_hcdp.c linux-2.5.71/drivers/serial/8250_hcdp.c --- linux-2.5.70-bk19/drivers/serial/8250_hcdp.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/drivers/serial/8250_hcdp.c 2003-06-14 13:53:25.000000000 -0700 @@ -0,0 +1,249 @@ +/* + * linux/drivers/char/hcdp_serial.c + * + * Copyright (C) 2002 Hewlett-Packard Co. + * Khalid Aziz + * + * Parse the EFI HCDP table to locate serial console and debug ports and + * initialize them. + * + * 2002/08/29 davidm Adjust it to new 2.5 serial driver infrastructure. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "8250_hcdp.h" + +#undef SERIAL_DEBUG_HCDP + +/* + * Parse the HCDP table to find descriptions for headless console and debug + * serial ports and add them to rs_table[]. A pointer to HCDP table is + * passed as parameter. This function should be called before + * serial_console_init() is called to make sure the HCDP serial console will + * be available for use. IA-64 kernel calls this function from setup_arch() + * after the EFI and ACPI tables have been parsed. + */ +void __init +setup_serial_hcdp(void *tablep) +{ + hcdp_dev_t *hcdp_dev; + struct uart_port port; + unsigned long iobase; + hcdp_t hcdp; + int gsi, nr; +#if 0 + static int shift_once = 1; +#endif + +#ifdef SERIAL_DEBUG_HCDP + printk("Entering setup_serial_hcdp()\n"); +#endif + + /* Verify we have a valid table pointer */ + if (!tablep) + return; + + memset(&port, 0, sizeof(port)); + + /* + * Don't trust firmware to give us a table starting at an aligned + * address. Make a local copy of the HCDP table with aligned + * structures. + */ + memcpy(&hcdp, tablep, sizeof(hcdp)); + + /* + * Perform a sanity check on the table. Table should have a signature + * of "HCDP" and it should be atleast 82 bytes long to have any + * useful information. + */ + if ((strncmp(hcdp.signature, HCDP_SIGNATURE, HCDP_SIG_LEN) != 0)) + return; + if (hcdp.len < 82) + return; + +#ifdef SERIAL_DEBUG_HCDP + printk("setup_serial_hcdp(): table pointer = 0x%p, sig = '%.4s'\n", + tablep, hcdp.signature); + printk(" length = %d, rev = %d, ", hcdp.len, hcdp.rev); + printk("OEM ID = %.6s, # of entries = %d\n", hcdp.oemid, + hcdp.num_entries); +#endif + + /* + * Parse each device entry + */ + for (nr = 0; nr < hcdp.num_entries; nr++) { + hcdp_dev = hcdp.hcdp_dev + nr; + /* + * We will parse only the primary console device which is + * the first entry for these devices. We will ignore rest + * of the entries for the same type device that has already + * been parsed and initialized + */ + if (hcdp_dev->type != HCDP_DEV_CONSOLE) + continue; + + iobase = ((u64) hcdp_dev->base_addr.addrhi << 32) | + hcdp_dev->base_addr.addrlo; + gsi = hcdp_dev->global_int; + + /* See PCI spec v2.2, Appendix D (Class Codes): */ + switch (hcdp_dev->pci_prog_intfc) { + case 0x00: + port.type = PORT_8250; + break; + case 0x01: + port.type = PORT_16450; + break; + case 0x02: + port.type = PORT_16550; + break; + case 0x03: + port.type = PORT_16650; + break; + case 0x04: + port.type = PORT_16750; + break; + case 0x05: + port.type = PORT_16850; + break; + case 0x06: + port.type = PORT_16C950; + break; + default: + printk(KERN_WARNING "warning: EFI HCDP table reports " + "unknown serial programming interface 0x%02x; " + "will autoprobe.\n", hcdp_dev->pci_prog_intfc); + port.type = PORT_UNKNOWN; + break; + } + +#ifdef SERIAL_DEBUG_HCDP + printk(" type = %s, uart = %d\n", + ((hcdp_dev->type == HCDP_DEV_CONSOLE) ? + "Headless Console" : + ((hcdp_dev->type == HCDP_DEV_DEBUG) ? + "Debug port" : "Huh????")), port.type); + printk(" base address space = %s, base address = 0x%lx\n", + ((hcdp_dev->base_addr.space_id == ACPI_MEM_SPACE) ? + "Memory Space" : + ((hcdp_dev->base_addr.space_id == ACPI_IO_SPACE) ? + "I/O space" : "PCI space")), + iobase); + printk(" gsi = %d, baud rate = %lu, bits = %d, clock = %d\n", + gsi, (unsigned long) hcdp_dev->baud, hcdp_dev->bits, + hcdp_dev->clock_rate); + if (hcdp_dev->base_addr.space_id == ACPI_PCICONF_SPACE) + printk(" PCI id: %02x:%02x:%02x, vendor ID=0x%x, " + "dev ID=0x%x\n", hcdp_dev->pci_seg, + hcdp_dev->pci_bus, hcdp_dev->pci_dev, + hcdp_dev->pci_vendor_id, hcdp_dev->pci_dev_id); +#endif + /* + * Now fill in a port structure to update the 8250 port table.. + */ + if (hcdp_dev->clock_rate) + port.uartclk = hcdp_dev->clock_rate; + else + port.uartclk = BASE_BAUD * 16; + + /* + * Check if this is an I/O mapped address or a memory mapped + * address + */ + if (hcdp_dev->base_addr.space_id == ACPI_MEM_SPACE) { + port.iobase = 0; + port.mapbase = iobase; + port.membase = ioremap(iobase, 64); + port.iotype = SERIAL_IO_MEM; + } else if (hcdp_dev->base_addr.space_id == ACPI_IO_SPACE) { + port.iobase = iobase; + port.mapbase = 0; + port.membase = NULL; + port.iotype = SERIAL_IO_PORT; + } else if (hcdp_dev->base_addr.space_id == ACPI_PCICONF_SPACE) { + printk(KERN_WARNING"warning: No support for PCI serial console\n"); + return; + } +#ifdef CONFIG_IA64 + port.irq = acpi_register_irq(gsi, ACPI_ACTIVE_HIGH, + ACPI_EDGE_SENSITIVE); +#else + port.irq = gsi; +#endif + port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF; + if (gsi) + port.flags |= ASYNC_AUTO_IRQ; + + /* + * Note: the above memset() initializes port.line to 0, + * so we register this port as ttyS0. + */ + if (early_serial_setup(&port) < 0) { + printk("setup_serial_hcdp(): early_serial_setup() " + "for HCDP serial console port failed. " + "Will try any additional consoles in HCDP.\n"); + continue; + } + break; + } + +#ifdef SERIAL_DEBUG_HCDP + printk("Leaving setup_serial_hcdp()\n"); +#endif +} + +#ifdef CONFIG_IA64_EARLY_PRINTK_UART +unsigned long +hcdp_early_uart (void) +{ + efi_system_table_t *systab; + efi_config_table_t *config_tables; + unsigned long addr = 0; + hcdp_t *hcdp = 0; + hcdp_dev_t *dev; + int i; + + systab = (efi_system_table_t *) ia64_boot_param->efi_systab; + if (!systab) + return 0; + systab = __va(systab); + + config_tables = (efi_config_table_t *) systab->tables; + if (!config_tables) + return 0; + config_tables = __va(config_tables); + + for (i = 0; i < systab->nr_tables; i++) { + if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) { + hcdp = (hcdp_t *) config_tables[i].table; + break; + } + } + if (!hcdp) + return 0; + hcdp = __va(hcdp); + + for (i = 0, dev = hcdp->hcdp_dev; i < hcdp->num_entries; i++, dev++) { + if (dev->type == HCDP_DEV_CONSOLE) { + addr = (u64) dev->base_addr.addrhi << 32 | dev->base_addr.addrlo; + break; + } + } + return addr; +} +#endif /* CONFIG_IA64_EARLY_PRINTK_UART */ diff -urN linux-2.5.70-bk19/drivers/serial/8250_hcdp.h linux-2.5.71/drivers/serial/8250_hcdp.h --- linux-2.5.70-bk19/drivers/serial/8250_hcdp.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/drivers/serial/8250_hcdp.h 2003-06-14 13:53:25.000000000 -0700 @@ -0,0 +1,79 @@ +/* + * drivers/serial/8250_hcdp.h + * + * Copyright (C) 2002 Hewlett-Packard Co. + * Khalid Aziz + * + * Definitions for HCDP defined serial ports (Serial console and debug + * ports) + */ + +/* ACPI table signatures */ +#define HCDP_SIG_LEN 4 +#define HCDP_SIGNATURE "HCDP" + +/* Space ID as defined in ACPI generic address structure */ +#define ACPI_MEM_SPACE 0 +#define ACPI_IO_SPACE 1 +#define ACPI_PCICONF_SPACE 2 + +/* + * Maximum number of HCDP devices we want to read in + */ +#define MAX_HCDP_DEVICES 6 + +/* + * Default UART clock rate if clock rate is 0 in HCDP table. + */ +#define DEFAULT_UARTCLK 115200 + +/* + * ACPI Generic Address Structure + */ +typedef struct { + u8 space_id; + u8 bit_width; + u8 bit_offset; + u8 resv; + u32 addrlo; + u32 addrhi; +} acpi_gen_addr; + +/* HCDP Device descriptor entry types */ +#define HCDP_DEV_CONSOLE 0 +#define HCDP_DEV_DEBUG 1 + +/* HCDP Device descriptor type */ +typedef struct { + u8 type; + u8 bits; + u8 parity; + u8 stop_bits; + u8 pci_seg; + u8 pci_bus; + u8 pci_dev; + u8 pci_func; + u64 baud; + acpi_gen_addr base_addr; + u16 pci_dev_id; + u16 pci_vendor_id; + u32 global_int; + u32 clock_rate; + u8 pci_prog_intfc; + u8 resv; +} hcdp_dev_t; + +/* HCDP Table format */ +typedef struct { + u8 signature[4]; + u32 len; + u8 rev; + u8 chksum; + u8 oemid[6]; + u8 oem_tabid[8]; + u32 oem_rev; + u8 creator_id[4]; + u32 creator_rev; + u32 num_entries; + hcdp_dev_t hcdp_dev[MAX_HCDP_DEVICES]; +} hcdp_t; diff -urN linux-2.5.70-bk19/drivers/serial/Kconfig linux-2.5.71/drivers/serial/Kconfig --- linux-2.5.70-bk19/drivers/serial/Kconfig 2003-05-26 18:00:57.000000000 -0700 +++ linux-2.5.71/drivers/serial/Kconfig 2003-06-14 13:53:25.000000000 -0700 @@ -77,6 +77,15 @@ a module, say M here and read . If unsure, say N. +config SERIAL_HCDP + bool "8250/16550 device discovery support via EFI HCDP table" + depends on IA64 + ---help--- + If you wish to make the serial console port described by the EFI + HCDP table available for use as serial console or general + purpose port, say Y here. See + . + config SERIAL_8250_EXTENDED bool "Extended 8250/16550 serial driver options" depends on SERIAL_8250 diff -urN linux-2.5.70-bk19/drivers/serial/Makefile linux-2.5.71/drivers/serial/Makefile --- linux-2.5.70-bk19/drivers/serial/Makefile 2003-05-26 18:00:40.000000000 -0700 +++ linux-2.5.71/drivers/serial/Makefile 2003-06-14 13:53:25.000000000 -0700 @@ -8,6 +8,8 @@ serial-8250-$(CONFIG_GSC) += 8250_gsc.o serial-8250-$(CONFIG_PCI) += 8250_pci.o serial-8250-$(CONFIG_PNP) += 8250_pnp.o +serial-8250-$(CONFIG_SERIAL_HCDP) += 8250_hcdp.o + obj-$(CONFIG_SERIAL_CORE) += core.o obj-$(CONFIG_SERIAL_21285) += 21285.o obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y) diff -urN linux-2.5.70-bk19/include/asm-i386/cpufeature.h linux-2.5.71/include/asm-i386/cpufeature.h --- linux-2.5.70-bk19/include/asm-i386/cpufeature.h 2003-05-26 18:00:45.000000000 -0700 +++ linux-2.5.71/include/asm-i386/cpufeature.h 2003-06-14 13:53:26.000000000 -0700 @@ -70,6 +70,7 @@ #define X86_FEATURE_P4 (3*32+ 7) /* P4 */ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ +#define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */ /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ #define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn) */ diff -urN linux-2.5.70-bk19/include/asm-i386/msr.h linux-2.5.71/include/asm-i386/msr.h --- linux-2.5.70-bk19/include/asm-i386/msr.h 2003-05-26 18:00:20.000000000 -0700 +++ linux-2.5.71/include/asm-i386/msr.h 2003-06-14 13:53:26.000000000 -0700 @@ -77,6 +77,9 @@ #define MSR_P6_EVNTSEL0 0x186 #define MSR_P6_EVNTSEL1 0x187 +#define MSR_IA32_PERF_STATUS 0x198 +#define MSR_IA32_PERF_CTL 0x199 + #define MSR_IA32_THERM_CONTROL 0x19a #define MSR_IA32_THERM_INTERRUPT 0x19b #define MSR_IA32_THERM_STATUS 0x19c diff -urN linux-2.5.70-bk19/include/asm-ppc64/bug.h linux-2.5.71/include/asm-ppc64/bug.h --- linux-2.5.70-bk19/include/asm-ppc64/bug.h 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/include/asm-ppc64/bug.h 2003-06-14 13:53:26.000000000 -0700 @@ -1,8 +1,6 @@ #ifndef _PPC64_BUG_H #define _PPC64_BUG_H -#include - /* * Define an illegal instr to trap on the bug. * We don't use 0 because that marks the end of a function @@ -13,29 +11,48 @@ #ifndef __ASSEMBLY__ -#ifdef CONFIG_XMON -struct pt_regs; -extern void xmon(struct pt_regs *excp); -#define BUG() do { \ - printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ - xmon(0); \ -} while (0) -#else -#define BUG() do { \ - printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ - __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \ +struct bug_entry { + unsigned long bug_addr; + long line; + const char *file; + const char *function; +}; + +/* + * If this bit is set in the line number it means that the trap + * is for WARN_ON rather than BUG or BUG_ON. + */ +#define BUG_WARNING_TRAP 0x1000000 + +#define BUG() do { \ + __asm__ __volatile__( \ + "1: twi 31,0,0\n" \ + ".section __bug_table,\"a\"\n\t" \ + " .llong 1b,%0,%1,%2\n" \ + ".previous" \ + : : "i" (__LINE__), "i" (__FILE__), "i" (__FUNCTION__)); \ } while (0) -#endif -#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0) +#define BUG_ON(x) do { \ + __asm__ __volatile__( \ + "1: tdnei %0,0\n" \ + ".section __bug_table,\"a\"\n\t" \ + " .llong 1b,%1,%2,%3\n" \ + ".previous" \ + : : "r" (x), "i" (__LINE__), "i" (__FILE__), \ + "i" (__FUNCTION__)); \ +} while (0) #define PAGE_BUG(page) do { BUG(); } while (0) -#define WARN_ON(condition) do { \ - if (unlikely((condition)!=0)) { \ - printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \ - dump_stack(); \ - } \ +#define WARN_ON(x) do { \ + __asm__ __volatile__( \ + "1: tdnei %0,0\n" \ + ".section __bug_table,\"a\"\n\t" \ + " .llong 1b,%1,%2,%3\n" \ + ".previous" \ + : : "r" (x), "i" (__LINE__ + BUG_WARNING_TRAP), \ + "i" (__FILE__), "i" (__FUNCTION__)); \ } while (0) #endif diff -urN linux-2.5.70-bk19/include/asm-ppc64/cputable.h linux-2.5.71/include/asm-ppc64/cputable.h --- linux-2.5.70-bk19/include/asm-ppc64/cputable.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.5.71/include/asm-ppc64/cputable.h 2003-06-14 13:53:26.000000000 -0700 @@ -0,0 +1,152 @@ +/* + * include/asm-ppc64/cputable.h + * + * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org) + * + * Modifications for ppc64: + * Copyright (C) 2003 Dave Engebretsen + * + * 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. + */ + +#ifndef __ASM_PPC_CPUTABLE_H +#define __ASM_PPC_CPUTABLE_H + +/* Exposed to userland CPU features - Must match ppc32 definitions */ +#define PPC_FEATURE_32 0x80000000 +#define PPC_FEATURE_64 0x40000000 +#define PPC_FEATURE_601_INSTR 0x20000000 +#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 +#define PPC_FEATURE_HAS_FPU 0x08000000 +#define PPC_FEATURE_HAS_MMU 0x04000000 +#define PPC_FEATURE_HAS_4xxMAC 0x02000000 +#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 + +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ + +/* This structure can grow, it's real size is used by head.S code + * via the mkdefs mecanism. + */ +struct cpu_spec; + +typedef void (*cpu_setup_t)(unsigned long offset, struct cpu_spec* spec); + +struct cpu_spec { + /* CPU is matched via (PVR & pvr_mask) == pvr_value */ + unsigned int pvr_mask; + unsigned int pvr_value; + + char *cpu_name; + unsigned long cpu_features; /* Kernel features */ + unsigned int cpu_user_features; /* Userland features */ + + /* cache line sizes */ + unsigned int icache_bsize; + unsigned int dcache_bsize; + + /* this is called to initialize various CPU bits like L1 cache, + * BHT, SPD, etc... from head.S before branching to identify_machine + */ + cpu_setup_t cpu_setup; + + /* This is used to identify firmware features which are available + * to the kernel. + */ + unsigned long firmware_features; +}; + +extern struct cpu_spec cpu_specs[]; +extern struct cpu_spec *cur_cpu_spec; + + +/* firmware feature bitmask values */ +#define FIRMWARE_MAX_FEATURES 63 + +#define FW_FEATURE_PFT (1UL<<0) +#define FW_FEATURE_TCE (1UL<<1) +#define FW_FEATURE_SPRG0 (1UL<<2) +#define FW_FEATURE_DABR (1UL<<3) +#define FW_FEATURE_COPY (1UL<<4) +#define FW_FEATURE_ASR (1UL<<5) +#define FW_FEATURE_DEBUG (1UL<<6) +#define FW_FEATURE_PERF (1UL<<7) +#define FW_FEATURE_DUMP (1UL<<8) +#define FW_FEATURE_INTERRUPT (1UL<<9) +#define FW_FEATURE_MIGRATE (1UL<<10) + +typedef struct { + unsigned long val; + char * name; +} firmware_feature_t; + +extern firmware_feature_t firmware_features_table[]; + +#endif /* __ASSEMBLY__ */ + +/* CPU kernel features */ + +/* Retain the 32b definitions for the time being - use bottom half of word */ +#define CPU_FTR_SPLIT_ID_CACHE 0x0000000000000001 +#define CPU_FTR_L2CR 0x0000000000000002 +#define CPU_FTR_SPEC7450 0x0000000000000004 +#define CPU_FTR_ALTIVEC 0x0000000000000008 +#define CPU_FTR_TAU 0x0000000000000010 +#define CPU_FTR_CAN_DOZE 0x0000000000000020 +#define CPU_FTR_USE_TB 0x0000000000000040 +#define CPU_FTR_604_PERF_MON 0x0000000000000080 +#define CPU_FTR_601 0x0000000000000100 +#define CPU_FTR_HPTE_TABLE 0x0000000000000200 +#define CPU_FTR_CAN_NAP 0x0000000000000400 +#define CPU_FTR_L3CR 0x0000000000000800 +#define CPU_FTR_L3_DISABLE_NAP 0x0000000000001000 +#define CPU_FTR_NAP_DISABLE_L2_PR 0x0000000000002000 +#define CPU_FTR_DUAL_PLL_750FX 0x0000000000004000 + +/* Add the 64b processor unique features in the top half of the word */ +#define CPU_FTR_SLB 0x0000000100000000 +#define CPU_FTR_16M_PAGE 0x0000000200000000 +#define CPU_FTR_TLBIEL 0x0000000400000000 +#define CPU_FTR_NOEXECUTE 0x0000000800000000 +#define CPU_FTR_NODSISRALIGN 0x0000001000000000 + +/* Platform firmware features */ +#define FW_FTR_ 0x0000000000000001 + +#ifndef __ASSEMBLY__ +#define COMMON_USER_PPC64 (PPC_FEATURE_32 | PPC_FEATURE_64 | \ + PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_MMU) + +#define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_SLB | CPU_FTR_16M_PAGE | \ + CPU_FTR_TLBIEL | CPU_FTR_NOEXECUTE | \ + CPU_FTR_NODSISRALIGN) + +#define COMMON_PPC64_FW (0) +#endif + +#ifdef __ASSEMBLY__ + +#define BEGIN_FTR_SECTION 98: + +#define END_FTR_SECTION(msk, val) \ +99: \ + .section __ftr_fixup,"a"; \ + .align 3; \ + .llong msk; \ + .llong val; \ + .llong 98b; \ + .llong 99b; \ + .previous + +#define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk)) +#define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0) + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_PPC_CPUTABLE_H */ +#endif /* __KERNEL__ */ + diff -urN linux-2.5.70-bk19/include/asm-ppc64/machdep.h linux-2.5.71/include/asm-ppc64/machdep.h --- linux-2.5.70-bk19/include/asm-ppc64/machdep.h 2003-05-26 18:00:28.000000000 -0700 +++ linux-2.5.71/include/asm-ppc64/machdep.h 2003-06-14 13:53:26.000000000 -0700 @@ -67,7 +67,6 @@ void (*get_cpuinfo)(struct seq_file *m); void (*init_IRQ)(void); - void (*init_ras_IRQ)(void); int (*get_irq)(struct pt_regs *); /* Optional, may be NULL. */ diff -urN linux-2.5.70-bk19/include/asm-ppc64/module.h linux-2.5.71/include/asm-ppc64/module.h --- linux-2.5.70-bk19/include/asm-ppc64/module.h 2003-05-26 18:00:23.000000000 -0700 +++ linux-2.5.71/include/asm-ppc64/module.h 2003-06-14 13:53:26.000000000 -0700 @@ -1,6 +1,9 @@ #ifndef _ASM_PPC64_MODULE_H #define _ASM_PPC64_MODULE_H +#include +#include + struct mod_arch_specific { /* Index of stubs section within module. */ @@ -8,8 +11,15 @@ /* What section is the TOC? */ unsigned int toc_section; + + /* List of BUG addresses, source line numbers and filenames */ + struct list_head bug_list; + struct bug_entry *bug_table; + unsigned int num_bugs; }; +extern struct bug_entry *module_find_bug(unsigned long bugaddr); + #define Elf_Shdr Elf64_Shdr #define Elf_Sym Elf64_Sym #define Elf_Ehdr Elf64_Ehdr diff -urN linux-2.5.70-bk19/include/asm-ppc64/processor.h linux-2.5.71/include/asm-ppc64/processor.h --- linux-2.5.70-bk19/include/asm-ppc64/processor.h 2003-05-26 18:00:22.000000000 -0700 +++ linux-2.5.71/include/asm-ppc64/processor.h 2003-06-14 13:53:26.000000000 -0700 @@ -730,18 +730,6 @@ #define spin_lock_prefetch(x) prefetchw(x) -#define cpu_has_largepage() (processor_type() == PV_POWER4 || \ - processor_type() == PV_POWER4p) - -#define cpu_has_slb() (processor_type() == PV_POWER4 || \ - processor_type() == PV_POWER4p) - -#define cpu_has_tlbiel() (processor_type() == PV_POWER4 || \ - processor_type() == PV_POWER4p) - -#define cpu_has_noexecute() (processor_type() == PV_POWER4 || \ - processor_type() == PV_POWER4p) - /* XXX we have to call HV to set when in LPAR */ #define cpu_has_dabr() (1) diff -urN linux-2.5.70-bk19/include/asm-ppc64/uaccess.h linux-2.5.71/include/asm-ppc64/uaccess.h --- linux-2.5.70-bk19/include/asm-ppc64/uaccess.h 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/include/asm-ppc64/uaccess.h 2003-06-14 13:53:26.000000000 -0700 @@ -24,8 +24,10 @@ * For historical reasons, these macros are grossly misnamed. */ -#define KERNEL_DS ((mm_segment_t) { 0 }) -#define USER_DS ((mm_segment_t) { 1 }) +#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) + +#define KERNEL_DS MAKE_MM_SEG(0UL) +#define USER_DS MAKE_MM_SEG(0xf000000000000000UL) #define get_ds() (KERNEL_DS) #define get_fs() (current->thread.fs) @@ -33,12 +35,25 @@ #define segment_eq(a,b) ((a).seg == (b).seg) -#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS)) -#define __user_ok(addr,size) (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size))) -#define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size))) -#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size)) +/* + * Use the alpha trick for checking ranges: + * + * Is a address valid? This does a straightforward calculation rather + * than tests. + * + * Address valid if: + * - "addr" doesn't have any high-bits set + * - AND "size" doesn't have any high-bits set + * - AND "addr+size" doesn't have any high-bits set + * - OR we are in kernel mode. + */ +#define __access_ok(addr,size,segment) \ + (((segment).seg & (addr | size | (addr+size))) == 0) + +#define access_ok(type,addr,size) \ + __access_ok(((unsigned long)(addr)),(size),get_fs()) -static inline int verify_area(int type, const void * addr, unsigned long size) +static inline int verify_area(int type, const void *addr, unsigned long size) { return access_ok(type,addr,size) ? 0 : -EFAULT; } @@ -96,32 +111,32 @@ extern long __put_user_bad(void); -#define __put_user_nocheck(x,ptr,size) \ -({ \ - long __pu_err; \ - __put_user_size((x),(ptr),(size),__pu_err); \ - __pu_err; \ -}) - -#define __put_user_check(x,ptr,size) \ +#define __put_user_nocheck(x,ptr,size) \ ({ \ - long __pu_err = -EFAULT; \ - __typeof__(*(ptr)) *__pu_addr = (ptr); \ - if (access_ok(VERIFY_WRITE,__pu_addr,size)) \ - __put_user_size((x),__pu_addr,(size),__pu_err); \ + long __pu_err; \ + __put_user_size((x),(ptr),(size),__pu_err,-EFAULT); \ __pu_err; \ }) -#define __put_user_size(x,ptr,size,retval) \ -do { \ - retval = 0; \ - switch (size) { \ - case 1: __put_user_asm(x,ptr,retval,"stb"); break; \ - case 2: __put_user_asm(x,ptr,retval,"sth"); break; \ - case 4: __put_user_asm(x,ptr,retval,"stw"); break; \ - case 8: __put_user_asm(x,ptr,retval,"std"); break; \ - default: __put_user_bad(); \ - } \ +#define __put_user_check(x,ptr,size) \ +({ \ + long __pu_err = -EFAULT; \ + __typeof__(*(ptr)) *__pu_addr = (ptr); \ + if (access_ok(VERIFY_WRITE,__pu_addr,size)) \ + __put_user_size((x),__pu_addr,(size),__pu_err,-EFAULT); \ + __pu_err; \ +}) + +#define __put_user_size(x,ptr,size,retval,errret) \ +do { \ + retval = 0; \ + switch (size) { \ + case 1: __put_user_asm(x,ptr,retval,"stb",errret); break; \ + case 2: __put_user_asm(x,ptr,retval,"sth",errret); break; \ + case 4: __put_user_asm(x,ptr,retval,"stw",errret); break; \ + case 8: __put_user_asm(x,ptr,retval,"std",errret); break; \ + default: __put_user_bad(); \ + } \ } while (0) /* @@ -129,7 +144,7 @@ * because we do not write to any memory gcc knows about, so there * are no aliasing issues. */ -#define __put_user_asm(x, addr, err, op) \ +#define __put_user_asm(x, addr, err, op, errret) \ __asm__ __volatile__( \ "1: "op" %1,0(%2) # put_user\n" \ "2:\n" \ @@ -142,13 +157,13 @@ " .llong 1b,3b\n" \ ".previous" \ : "=r"(err) \ - : "r"(x), "b"(addr), "i"(-EFAULT), "0"(err)) + : "r"(x), "b"(addr), "i"(errret), "0"(err)) #define __get_user_nocheck(x,ptr,size) \ ({ \ long __gu_err, __gu_val; \ - __get_user_size(__gu_val,(ptr),(size),__gu_err); \ + __get_user_size(__gu_val,(ptr),(size),__gu_err,-EFAULT);\ (x) = (__typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) @@ -158,26 +173,26 @@ long __gu_err = -EFAULT, __gu_val = 0; \ const __typeof__(*(ptr)) *__gu_addr = (ptr); \ if (access_ok(VERIFY_READ,__gu_addr,size)) \ - __get_user_size(__gu_val,__gu_addr,(size),__gu_err); \ + __get_user_size(__gu_val,__gu_addr,(size),__gu_err,-EFAULT);\ (x) = (__typeof__(*(ptr)))__gu_val; \ __gu_err; \ }) extern long __get_user_bad(void); -#define __get_user_size(x,ptr,size,retval) \ -do { \ - retval = 0; \ - switch (size) { \ - case 1: __get_user_asm(x,ptr,retval,"lbz"); break; \ - case 2: __get_user_asm(x,ptr,retval,"lhz"); break; \ - case 4: __get_user_asm(x,ptr,retval,"lwz"); break; \ - case 8: __get_user_asm(x,ptr,retval,"ld"); break; \ - default: (x) = __get_user_bad(); \ - } \ +#define __get_user_size(x,ptr,size,retval,errret) \ +do { \ + retval = 0; \ + switch (size) { \ + case 1: __get_user_asm(x,ptr,retval,"lbz",errret); break; \ + case 2: __get_user_asm(x,ptr,retval,"lhz",errret); break; \ + case 4: __get_user_asm(x,ptr,retval,"lwz",errret); break; \ + case 8: __get_user_asm(x,ptr,retval,"ld",errret); break; \ + default: (x) = __get_user_bad(); \ + } \ } while (0) -#define __get_user_asm(x, addr, err, op) \ +#define __get_user_asm(x, addr, err, op, errret) \ __asm__ __volatile__( \ "1: "op" %1,0(%2) # get_user\n" \ "2:\n" \ @@ -191,57 +206,97 @@ " .llong 1b,3b\n" \ ".previous" \ : "=r"(err), "=r"(x) \ - : "b"(addr), "i"(-EFAULT), "0"(err)) + : "b"(addr), "i"(errret), "0"(err)) /* more complex routines */ -extern unsigned long __copy_tofrom_user(void *to, const void *from, unsigned long size); +extern unsigned long __copy_tofrom_user(void *to, const void *from, + unsigned long size); +/* XXX should zero destination if fault happened */ static inline unsigned long -copy_from_user(void *to, const void *from, unsigned long n) +__copy_from_user(void *to, const void __user *from, unsigned long n) { - unsigned long over; + if (__builtin_constant_p(n)) { + unsigned long ret; - if (access_ok(VERIFY_READ, from, n)) - return __copy_tofrom_user(to, from, n); - if ((unsigned long)from < TASK_SIZE) { - over = (unsigned long)from + n - TASK_SIZE; - memset(to + over, 0, over); - return __copy_tofrom_user(to, from, n - over) + over; + switch (n) { + case 1: + __get_user_size(*(u8 *)to, from, 1, ret, 1); + return ret; + case 2: + __get_user_size(*(u16 *)to, from, 2, ret, 2); + return ret; + case 4: + __get_user_size(*(u32 *)to, from, 4, ret, 4); + return ret; + case 8: + __get_user_size(*(u64 *)to, from, 8, ret, 8); + return ret; + } } - return n; + return __copy_tofrom_user(to, from, n); } static inline unsigned long -copy_to_user(void *to, const void *from, unsigned long n) +__copy_to_user(void __user *to, const void *from, unsigned long n) { - unsigned long over; + if (__builtin_constant_p(n)) { + unsigned long ret; - if (access_ok(VERIFY_WRITE, to, n)) - return __copy_tofrom_user(to, from, n); - if ((unsigned long)to < TASK_SIZE) { - over = (unsigned long)to + n - TASK_SIZE; - return __copy_tofrom_user(to, from, n - over) + over; + switch (n) { + case 1: + __put_user_size(*(u8 *)from, (u8 *)to, 1, ret, 1); + return ret; + case 2: + __put_user_size(*(u16 *)from, (u16 *)to, 2, ret, 2); + return ret; + case 4: + __put_user_size(*(u32 *)from, (u32 *)to, 4, ret, 4); + return ret; + case 8: + __put_user_size(*(u64 *)from, (u64 *)to, 8, ret, 8); + return ret; + } } - return n; + return __copy_tofrom_user(to, from, n); } -#define __copy_from_user(to, from, size) \ - __copy_tofrom_user((to), (from), (size)) -#define __copy_to_user(to, from, size) \ +#define __copy_in_user(to, from, size) \ __copy_tofrom_user((to), (from), (size)) +static inline unsigned long +copy_from_user(void *to, const void *from, unsigned long n) +{ + if (likely(access_ok(VERIFY_READ, from, n))) + n = __copy_from_user(to, from, n); + return n; +} + +static inline unsigned long +copy_to_user(void *to, const void *from, unsigned long n) +{ + if (likely(access_ok(VERIFY_WRITE, to, n))) + n = __copy_to_user(to, from, n); + return n; +} + +static inline unsigned long +copy_in_user(void *to, const void *from, unsigned long n) +{ + if (likely(access_ok(VERIFY_READ, from, n) && + access_ok(VERIFY_WRITE, to, n))) + n =__copy_tofrom_user(to, from, n); + return n; +} + extern unsigned long __clear_user(void *addr, unsigned long size); static inline unsigned long clear_user(void *addr, unsigned long size) { - if (access_ok(VERIFY_WRITE, addr, size)) - return __clear_user(addr, size); - if ((unsigned long)addr < TASK_SIZE) { - unsigned long over = (unsigned long)addr + size - TASK_SIZE; - return __clear_user(addr, size - over) + over; - } + if (likely(access_ok(VERIFY_WRITE, addr, size))) + size = __clear_user(addr, size); return size; } @@ -250,7 +305,7 @@ static inline long strncpy_from_user(char *dst, const char *src, long count) { - if (access_ok(VERIFY_READ, src, 1)) + if (likely(access_ok(VERIFY_READ, src, 1))) return __strncpy_from_user(dst, src, count); return -EFAULT; } @@ -260,24 +315,18 @@ * * Return 0 for error */ - -extern int __strnlen_user(const char *str, long len, unsigned long top); +extern int __strnlen_user(const char *str, long len); /* * Returns the length of the string at str (including the null byte), * or 0 if we hit a page we can't access, * or something > len if we didn't find a null byte. - * - * The `top' parameter to __strnlen_user is to make sure that - * we can never overflow from the user area into kernel space. */ static inline int strnlen_user(const char *str, long len) { - unsigned long top = __kernel_ok? ~0UL: TASK_SIZE - 1; - - if ((unsigned long)str > top) - return 0; - return __strnlen_user(str, len, top); + if (likely(access_ok(VERIFY_READ, str, 1))) + return __strnlen_user(str, len); + return 0; } #define strlen_user(str) strnlen_user((str), 0x7ffffffe) diff -urN linux-2.5.70-bk19/include/asm-ppc64/unistd.h linux-2.5.71/include/asm-ppc64/unistd.h --- linux-2.5.70-bk19/include/asm-ppc64/unistd.h 2003-05-26 18:00:20.000000000 -0700 +++ linux-2.5.71/include/asm-ppc64/unistd.h 2003-06-14 13:53:26.000000000 -0700 @@ -267,6 +267,104 @@ #ifndef __ASSEMBLY__ +/* On powerpc a system call basically clobbers the same registers like a + * function call, with the exception of LR (which is needed for the + * "sc; bnslr" sequence) and CR (where only CR0.SO is clobbered to signal + * an error return status). + */ + +#define __syscall_nr(nr, type, name, args...) \ + unsigned long __sc_ret, __sc_err; \ + { \ + register unsigned long __sc_0 __asm__ ("r0"); \ + register unsigned long __sc_3 __asm__ ("r3"); \ + register unsigned long __sc_4 __asm__ ("r4"); \ + register unsigned long __sc_5 __asm__ ("r5"); \ + register unsigned long __sc_6 __asm__ ("r6"); \ + register unsigned long __sc_7 __asm__ ("r7"); \ + \ + __sc_loadargs_##nr(name, args); \ + __asm__ __volatile__ \ + ("sc \n\t" \ + "mfcr %0 " \ + : "=&r" (__sc_0), \ + "=&r" (__sc_3), "=&r" (__sc_4), \ + "=&r" (__sc_5), "=&r" (__sc_6), \ + "=&r" (__sc_7) \ + : __sc_asm_input_##nr \ + : "cr0", "ctr", "memory", \ + "r8", "r9", "r10","r11", "r12"); \ + __sc_ret = __sc_3; \ + __sc_err = __sc_0; \ + } \ + if (__sc_err & 0x10000000) \ + { \ + errno = __sc_ret; \ + __sc_ret = -1; \ + } \ + return (type) __sc_ret + +#define __sc_loadargs_0(name, dummy...) \ + __sc_0 = __NR_##name +#define __sc_loadargs_1(name, arg1) \ + __sc_loadargs_0(name); \ + __sc_3 = (unsigned long) (arg1) +#define __sc_loadargs_2(name, arg1, arg2) \ + __sc_loadargs_1(name, arg1); \ + __sc_4 = (unsigned long) (arg2) +#define __sc_loadargs_3(name, arg1, arg2, arg3) \ + __sc_loadargs_2(name, arg1, arg2); \ + __sc_5 = (unsigned long) (arg3) +#define __sc_loadargs_4(name, arg1, arg2, arg3, arg4) \ + __sc_loadargs_3(name, arg1, arg2, arg3); \ + __sc_6 = (unsigned long) (arg4) +#define __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5) \ + __sc_loadargs_4(name, arg1, arg2, arg3, arg4); \ + __sc_7 = (unsigned long) (arg5) + +#define __sc_asm_input_0 "0" (__sc_0) +#define __sc_asm_input_1 __sc_asm_input_0, "1" (__sc_3) +#define __sc_asm_input_2 __sc_asm_input_1, "2" (__sc_4) +#define __sc_asm_input_3 __sc_asm_input_2, "3" (__sc_5) +#define __sc_asm_input_4 __sc_asm_input_3, "4" (__sc_6) +#define __sc_asm_input_5 __sc_asm_input_4, "5" (__sc_7) + +#define _syscall0(type,name) \ +type name(void) \ +{ \ + __syscall_nr(0, type, name); \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ + __syscall_nr(1, type, name, arg1); \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1, type2 arg2) \ +{ \ + __syscall_nr(2, type, name, arg1, arg2); \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1, type2 arg2, type3 arg3) \ +{ \ + __syscall_nr(3, type, name, arg1, arg2, arg3); \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ + __syscall_nr(4, type, name, arg1, arg2, arg3, arg4); \ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ +{ \ + __syscall_nr(5, type, name, arg1, arg2, arg3, arg4, arg5); \ +} + #ifdef __KERNEL_SYSCALLS__ /* diff -urN linux-2.5.70-bk19/include/linux/acpi_serial.h linux-2.5.71/include/linux/acpi_serial.h --- linux-2.5.70-bk19/include/linux/acpi_serial.h 2003-05-26 18:00:40.000000000 -0700 +++ linux-2.5.71/include/linux/acpi_serial.h 2003-06-14 13:53:26.000000000 -0700 @@ -9,6 +9,8 @@ * */ +#include + extern void setup_serial_acpi(void *); #define ACPI_SIG_LEN 4 diff -urN linux-2.5.70-bk19/include/linux/etherdevice.h linux-2.5.71/include/linux/etherdevice.h --- linux-2.5.70-bk19/include/linux/etherdevice.h 2003-05-26 18:00:56.000000000 -0700 +++ linux-2.5.71/include/linux/etherdevice.h 2003-06-14 13:53:26.000000000 -0700 @@ -40,7 +40,6 @@ unsigned char *haddr); extern struct net_device *init_etherdev(struct net_device *dev, int sizeof_priv); extern struct net_device *alloc_etherdev(int sizeof_priv); - static inline void eth_copy_and_sum (struct sk_buff *dest, unsigned char *src, int len, int base) { memcpy (dest->data, src, len); diff -urN linux-2.5.70-bk19/include/linux/highmem.h linux-2.5.71/include/linux/highmem.h --- linux-2.5.70-bk19/include/linux/highmem.h 2003-05-26 18:00:45.000000000 -0700 +++ linux-2.5.71/include/linux/highmem.h 2003-06-14 13:53:26.000000000 -0700 @@ -32,13 +32,6 @@ #endif /* CONFIG_HIGHMEM */ -#if defined(CONFIG_DEBUG_HIGHMEM) && defined(CONFIG_HIGHMEM) -extern void check_highmem_ptes(void); -#else -static inline void check_highmem_ptes(void) -{} -#endif - /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */ static inline void clear_user_highpage(struct page *page, unsigned long vaddr) { diff -urN linux-2.5.70-bk19/include/linux/if_tun.h linux-2.5.71/include/linux/if_tun.h --- linux-2.5.70-bk19/include/linux/if_tun.h 2003-05-26 18:00:27.000000000 -0700 +++ linux-2.5.71/include/linux/if_tun.h 2003-06-14 13:53:26.000000000 -0700 @@ -40,7 +40,7 @@ wait_queue_head_t read_wait; struct sk_buff_head readq; - struct net_device dev; + struct net_device *dev; struct net_device_stats stats; struct fasync_struct *fasync; diff -urN linux-2.5.70-bk19/include/linux/kernel.h linux-2.5.71/include/linux/kernel.h --- linux-2.5.70-bk19/include/linux/kernel.h 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/include/linux/kernel.h 2003-06-14 13:53:26.000000000 -0700 @@ -199,7 +199,7 @@ /* * Check at compile time that something is of a particular type. - * Always evaluates to 1 so you may use it easily in conparisons. + * Always evaluates to 1 so you may use it easily in comparisons. */ #define typecheck(type,x) \ ({ type __dummy; \ diff -urN linux-2.5.70-bk19/include/linux/netdevice.h linux-2.5.71/include/linux/netdevice.h --- linux-2.5.70-bk19/include/linux/netdevice.h 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/include/linux/netdevice.h 2003-06-14 13:53:26.000000000 -0700 @@ -816,6 +816,8 @@ extern void fc_setup(struct net_device *dev); extern void fc_freedev(struct net_device *dev); /* Support for loadable net-drivers */ +extern struct net_device *alloc_netdev(int sizeof_priv, const char *name, + void (*setup)(struct net_device *)); extern int register_netdev(struct net_device *dev); extern void unregister_netdev(struct net_device *dev); /* Functions used for multicast support */ diff -urN linux-2.5.70-bk19/include/linux/netfilter_arp/arp_tables.h linux-2.5.71/include/linux/netfilter_arp/arp_tables.h --- linux-2.5.70-bk19/include/linux/netfilter_arp/arp_tables.h 2003-05-26 18:00:27.000000000 -0700 +++ linux-2.5.71/include/linux/netfilter_arp/arp_tables.h 2003-06-14 13:53:26.000000000 -0700 @@ -111,7 +111,7 @@ #define ARPT_INV_ARPHRD 0x0080 /* Invert the sense of ARP HRD. */ #define ARPT_INV_ARPPRO 0x0100 /* Invert the sense of ARP PRO. */ #define ARPT_INV_ARPHLN 0x0200 /* Invert the sense of ARP HLN. */ -#define ARPT_INV_MASK 0x007F /* All possible flag bits mask. */ +#define ARPT_INV_MASK 0x03FF /* All possible flag bits mask. */ /* This structure defines each of the firewall rules. Consists of 3 parts which are 1) general ARP header stuff 2) match specific diff -urN linux-2.5.70-bk19/include/linux/ppp-comp.h linux-2.5.71/include/linux/ppp-comp.h --- linux-2.5.70-bk19/include/linux/ppp-comp.h 2003-05-26 18:00:19.000000000 -0700 +++ linux-2.5.71/include/linux/ppp-comp.h 2003-06-14 13:53:26.000000000 -0700 @@ -182,7 +182,7 @@ #define CI_DEFLATE_DRAFT 24 /* value used in original draft RFC */ #define CILEN_DEFLATE 4 /* length of its config option */ -#define DEFLATE_MIN_SIZE 8 +#define DEFLATE_MIN_SIZE 9 #define DEFLATE_MAX_SIZE 15 #define DEFLATE_METHOD_VAL 8 #define DEFLATE_SIZE(x) (((x) >> 4) + DEFLATE_MIN_SIZE) diff -urN linux-2.5.70-bk19/include/linux/serial.h linux-2.5.71/include/linux/serial.h --- linux-2.5.70-bk19/include/linux/serial.h 2003-05-26 18:00:25.000000000 -0700 +++ linux-2.5.71/include/linux/serial.h 2003-06-14 13:53:26.000000000 -0700 @@ -180,14 +180,9 @@ extern int register_serial(struct serial_struct *req); extern void unregister_serial(int line); -/* Allow complicated architectures to specify rs_table[] at run time */ -extern int early_serial_setup(struct serial_struct *req); - -#ifdef CONFIG_ACPI -/* tty ports reserved for the ACPI serial console port and debug port */ -#define ACPI_SERIAL_CONSOLE_PORT 4 -#define ACPI_SERIAL_DEBUG_PORT 5 -#endif +/* Allow architectures to override entries in serial8250_ports[] at run time: */ +struct uart_port; /* forward declaration */ +extern int early_serial_setup(struct uart_port *port); #endif /* __KERNEL__ */ #endif /* _LINUX_SERIAL_H */ diff -urN linux-2.5.70-bk19/include/net/flow.h linux-2.5.71/include/net/flow.h --- linux-2.5.70-bk19/include/net/flow.h 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/include/net/flow.h 2003-06-14 13:53:27.000000000 -0700 @@ -87,7 +87,7 @@ extern void *flow_cache_lookup(struct flowi *key, u16 family, u8 dir, flow_resolve_t resolver); -extern void flow_cache_flush(void *object); +extern void flow_cache_flush(void); extern atomic_t flow_cache_genid; #endif diff -urN linux-2.5.70-bk19/include/net/sctp/sctp.h linux-2.5.71/include/net/sctp/sctp.h --- linux-2.5.70-bk19/include/net/sctp/sctp.h 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/include/net/sctp/sctp.h 2003-06-14 13:53:27.000000000 -0700 @@ -119,12 +119,10 @@ */ /* - * sctp_protocol.c + * sctp/protocol.c */ -extern struct sctp_protocol sctp_proto; extern struct sock *sctp_get_ctl_sock(void); -extern int sctp_copy_local_addr_list(struct sctp_protocol *, - struct sctp_bind_addr *, +extern int sctp_copy_local_addr_list(struct sctp_bind_addr *, sctp_scope_t, int gfp, int flags); extern struct sctp_pf *sctp_get_pf_specific(sa_family_t family); extern int sctp_register_pf(struct sctp_pf *, sa_family_t); @@ -275,6 +273,7 @@ extern atomic_t sctp_dbg_objcnt_transport; extern atomic_t sctp_dbg_objcnt_chunk; extern atomic_t sctp_dbg_objcnt_bind_addr; +extern atomic_t sctp_dbg_objcnt_bind_bucket; extern atomic_t sctp_dbg_objcnt_addr; extern atomic_t sctp_dbg_objcnt_ssnmap; extern atomic_t sctp_dbg_objcnt_datamsg; @@ -418,6 +417,10 @@ static __u32 sctp_rand; __s32 ret; + /* Avoid divide by zero. */ + if (!rto) + rto = 1; + sctp_rand += jiffies; sctp_rand ^= (sctp_rand << 12); sctp_rand ^= (sctp_rand >> 20); @@ -448,7 +451,7 @@ * there is room for a param header too. */ #define sctp_walk_params(pos, chunk, member)\ -_sctp_walk_params((pos), (chunk), ntohs((chunk)->chunk_hdr.length), member) +_sctp_walk_params((pos), (chunk), WORD_ROUND(ntohs((chunk)->chunk_hdr.length)), member) #define _sctp_walk_params(pos, chunk, end, member)\ for (pos.v = chunk->member;\ @@ -456,6 +459,18 @@ pos.v <= (void *)chunk + end - WORD_ROUND(ntohs(pos.p->length)); \ pos.v += WORD_ROUND(ntohs(pos.p->length))) +#define sctp_walk_errors(err, chunk_hdr)\ +_sctp_walk_errors((err), (chunk_hdr), ntohs((chunk_hdr)->length)) + +#define _sctp_walk_errors(err, chunk_hdr, end)\ +for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \ + sizeof(sctp_chunkhdr_t));\ + (void *)err <= (void *)chunk_hdr + end - sizeof(sctp_errhdr_t) &&\ + (void *)err <= (void *)chunk_hdr + end - \ + WORD_ROUND(ntohs(err->length));\ + err = (sctp_errhdr_t *)((void *)err + \ + WORD_ROUND(ntohs(err->length)))) + /* Round an int up to the next multiple of 4. */ #define WORD_ROUND(s) (((s)+3)&~3) @@ -491,12 +506,6 @@ /* Static inline functions. */ -/* Return the SCTP protocol structure. */ -static inline struct sctp_protocol *sctp_get_protocol(void) -{ - return &sctp_proto; -} - /* Convert from an IP version number to an Address Family symbol. */ static inline int ipver2af(__u8 ipver) { @@ -524,24 +533,21 @@ /* This is the hash function for the SCTP port hash table. */ static inline int sctp_phashfn(__u16 lport) { - struct sctp_protocol *sctp_proto = sctp_get_protocol(); - return (lport & (sctp_proto->port_hashsize - 1)); + return (lport & (sctp_port_hashsize - 1)); } /* This is the hash function for the endpoint hash table. */ static inline int sctp_ep_hashfn(__u16 lport) { - struct sctp_protocol *sctp_proto = sctp_get_protocol(); - return (lport & (sctp_proto->ep_hashsize - 1)); + return (lport & (sctp_ep_hashsize - 1)); } /* This is the hash function for the association hash table. */ static inline int sctp_assoc_hashfn(__u16 lport, __u16 rport) { - struct sctp_protocol *sctp_proto = sctp_get_protocol(); int h = (lport << 16) + rport; h ^= h>>8; - return (h & (sctp_proto->assoc_hashsize - 1)); + return (h & (sctp_assoc_hashsize - 1)); } /* This is the hash function for the association hash table. This is @@ -550,10 +556,9 @@ */ static inline int sctp_vtag_hashfn(__u16 lport, __u16 rport, __u32 vtag) { - struct sctp_protocol *sctp_proto = sctp_get_protocol(); int h = (lport << 16) + rport; h ^= vtag; - return (h & (sctp_proto->assoc_hashsize-1)); + return (h & (sctp_assoc_hashsize-1)); } /* WARNING: Do not change the layout of the members in sctp_sock! */ diff -urN linux-2.5.70-bk19/include/net/sctp/structs.h linux-2.5.71/include/net/sctp/structs.h --- linux-2.5.70-bk19/include/net/sctp/structs.h 2003-05-26 18:01:00.000000000 -0700 +++ linux-2.5.71/include/net/sctp/structs.h 2003-06-14 13:53:27.000000000 -0700 @@ -71,7 +71,7 @@ }; /* Forward declarations for data structures. */ -struct sctp_protocol; +struct sctp_globals; struct sctp_endpoint; struct sctp_association; struct sctp_transport; @@ -92,28 +92,28 @@ /* Structures useful for managing bind/connect. */ -typedef struct sctp_bind_bucket { +struct sctp_bind_bucket { unsigned short port; unsigned short fastreuse; struct sctp_bind_bucket *next; struct sctp_bind_bucket **pprev; struct sock *sk; -} sctp_bind_bucket_t; +}; -typedef struct sctp_bind_hashbucket { +struct sctp_bind_hashbucket { spinlock_t lock; struct sctp_bind_bucket *chain; -} sctp_bind_hashbucket_t; +}; /* Used for hashing all associations. */ -typedef struct sctp_hashbucket { +struct sctp_hashbucket { rwlock_t lock; struct sctp_ep_common *chain; -} sctp_hashbucket_t __attribute__((__aligned__(8))); +} __attribute__((__aligned__(8))); -/* The SCTP protocol structure. */ -struct sctp_protocol { +/* The SCTP globals structure. */ +extern struct sctp_globals { /* RFC2960 Section 14. Suggested SCTP Protocol Parameter Values * * The following protocol parameters are RECOMMENDED: @@ -167,17 +167,17 @@ /* This is the hash of all endpoints. */ int ep_hashsize; - sctp_hashbucket_t *ep_hashbucket; + struct sctp_hashbucket *ep_hashbucket; /* This is the hash of all associations. */ int assoc_hashsize; - sctp_hashbucket_t *assoc_hashbucket; + struct sctp_hashbucket *assoc_hashbucket; /* This is the sctp port control hash. */ int port_hashsize; int port_rover; spinlock_t port_alloc_lock; /* Protects port_rover. */ - sctp_bind_hashbucket_t *port_hashtable; + struct sctp_bind_hashbucket *port_hashtable; /* This is the global local address list. * We actively maintain this complete list of interfaces on @@ -187,8 +187,33 @@ */ struct list_head local_addr_list; spinlock_t local_addr_lock; -}; +} sctp_globals; +#define sctp_rto_initial (sctp_globals.rto_initial) +#define sctp_rto_min (sctp_globals.rto_min) +#define sctp_rto_max (sctp_globals.rto_max) +#define sctp_rto_alpha (sctp_globals.rto_alpha) +#define sctp_rto_beta (sctp_globals.rto_beta) +#define sctp_max_burst (sctp_globals.max_burst) +#define sctp_valid_cookie_life (sctp_globals.valid_cookie_life) +#define sctp_cookie_preserve_enable (sctp_globals.cookie_preserve_enable) +#define sctp_max_retrans_association (sctp_globals.max_retrans_association) +#define sctp_max_retrans_path (sctp_globals.max_retrans_path) +#define sctp_max_retrans_init (sctp_globals.max_retrans_init) +#define sctp_hb_interval (sctp_globals.hb_interval) +#define sctp_max_instreams (sctp_globals.max_instreams) +#define sctp_max_outstreams (sctp_globals.max_outstreams) +#define sctp_address_families (sctp_globals.address_families) +#define sctp_ep_hashsize (sctp_globals.ep_hashsize) +#define sctp_ep_hashbucket (sctp_globals.ep_hashbucket) +#define sctp_assoc_hashsize (sctp_globals.assoc_hashsize) +#define sctp_assoc_hashbucket (sctp_globals.assoc_hashbucket) +#define sctp_port_hashsize (sctp_globals.port_hashsize) +#define sctp_port_rover (sctp_globals.port_rover) +#define sctp_port_alloc_lock (sctp_globals.port_alloc_lock) +#define sctp_port_hashtable (sctp_globals.port_hashtable) +#define sctp_local_addr_list (sctp_globals.local_addr_list) +#define sctp_local_addr_lock (sctp_globals.local_addr_lock) /* * Pointers to address related SCTP functions. @@ -239,7 +264,9 @@ int (*is_any) (const union sctp_addr *); int (*available) (const union sctp_addr *); int (*skb_iif) (const struct sk_buff *sk); - int (*is_ce) (const struct sk_buff *sk); + int (*is_ce) (const struct sk_buff *sk); + void (*seq_dump_addr)(struct seq_file *seq, + union sctp_addr *addr); __u16 net_header_len; int sockaddr_len; sa_family_t sa_family; @@ -289,6 +316,10 @@ /* Various Socket Options. */ __u16 default_stream; __u32 default_ppid; + __u16 default_flags; + __u32 default_context; + __u32 default_timetolive; + struct sctp_initmsg initmsg; struct sctp_rtoinfo rtoinfo; struct sctp_paddrparams paddrparam; @@ -461,7 +492,7 @@ /* Reference counting. */ atomic_t refcnt; /* When is this message no longer interesting to the peer? */ - unsigned long expires_at; + unsigned long expires_at; /* Did the messenge fail to send? */ int send_error; char send_failed; @@ -1492,13 +1523,12 @@ */ int counters[SCTP_NUMBER_COUNTERS]; - struct { - __u16 stream; - __u16 flags; - __u32 ppid; - __u32 context; - __u32 timetolive; - } defaults; + /* Default send parameters. */ + __u16 default_stream; + __u16 default_flags; + __u32 default_ppid; + __u32 default_context; + __u32 default_timetolive; /* This tracks outbound ssn for a given stream. */ struct sctp_ssnmap *ssnmap; diff -urN linux-2.5.70-bk19/include/net/sctp/user.h linux-2.5.71/include/net/sctp/user.h --- linux-2.5.70-bk19/include/net/sctp/user.h 2003-05-26 18:00:20.000000000 -0700 +++ linux-2.5.71/include/net/sctp/user.h 2003-06-14 13:53:27.000000000 -0700 @@ -485,6 +485,11 @@ __u32 spinfo_mtu; }; +/* Peer addresses's state. */ +enum sctp_spinfo_state { + SCTP_INACTIVE, + SCTP_ACTIVE, +}; /* * 7.1.1 Retransmission Timeout Parameters (SCTP_RTOINFO) diff -urN linux-2.5.70-bk19/kernel/sched.c linux-2.5.71/kernel/sched.c --- linux-2.5.70-bk19/kernel/sched.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/kernel/sched.c 2003-06-14 13:53:27.000000000 -0700 @@ -1258,7 +1258,6 @@ } } - check_highmem_ptes(); need_resched: preempt_disable(); prev = current; @@ -2297,7 +2296,7 @@ * it is sufficient to simply update the task's cpu field. */ if (!p->array && !task_running(rq, p)) { - set_task_cpu(p, __ffs(p->cpus_allowed)); + set_task_cpu(p, any_online_cpu(p->cpus_allowed)); task_rq_unlock(rq, &flags); return; } @@ -2311,9 +2310,35 @@ wait_for_completion(&req.done); } +/* Move (not current) task off this cpu, onto dest cpu. */ +static void move_task_away(struct task_struct *p, int dest_cpu) +{ + runqueue_t *rq_dest; + unsigned long flags; + + rq_dest = cpu_rq(dest_cpu); + + local_irq_save(flags); + double_rq_lock(this_rq(), rq_dest); + if (task_cpu(p) != smp_processor_id()) + goto out; /* Already moved */ + + set_task_cpu(p, dest_cpu); + if (p->array) { + deactivate_task(p, this_rq()); + activate_task(p, rq_dest); + if (p->prio < rq_dest->curr->prio) + resched_task(rq_dest->curr); + } + out: + double_rq_unlock(this_rq(), rq_dest); + local_irq_restore(flags); +} + /* * migration_thread - this is a highprio system thread that performs - * thread migration by 'pulling' threads into the target runqueue. + * thread migration by bumping thread off CPU then 'pushing' onto + * another runqueue. */ static int migration_thread(void * data) { @@ -2327,8 +2352,9 @@ set_fs(KERNEL_DS); /* - * Either we are running on the right CPU, or there's a - * a migration thread on the target CPU, guaranteed. + * Either we are running on the right CPU, or there's a a + * migration thread on this CPU, guaranteed (we're started + * serially). */ set_cpus_allowed(current, 1UL << cpu); @@ -2338,51 +2364,23 @@ rq->migration_thread = current; for (;;) { - runqueue_t *rq_src, *rq_dest; struct list_head *head; - int cpu_src, cpu_dest; migration_req_t *req; - unsigned long flags; - task_t *p; - spin_lock_irqsave(&rq->lock, flags); + spin_lock_irq(&rq->lock); head = &rq->migration_queue; current->state = TASK_INTERRUPTIBLE; if (list_empty(head)) { - spin_unlock_irqrestore(&rq->lock, flags); + spin_unlock_irq(&rq->lock); schedule(); continue; } req = list_entry(head->next, migration_req_t, list); list_del_init(head->next); - spin_unlock_irqrestore(&rq->lock, flags); - - p = req->task; - cpu_dest = __ffs(p->cpus_allowed & cpu_online_map); - rq_dest = cpu_rq(cpu_dest); -repeat: - cpu_src = task_cpu(p); - rq_src = cpu_rq(cpu_src); - - local_irq_save(flags); - double_rq_lock(rq_src, rq_dest); - if (task_cpu(p) != cpu_src) { - double_rq_unlock(rq_src, rq_dest); - local_irq_restore(flags); - goto repeat; - } - if (rq_src == rq) { - set_task_cpu(p, cpu_dest); - if (p->array) { - deactivate_task(p, rq_src); - __activate_task(p, rq_dest); - if (p->prio < rq_dest->curr->prio) - resched_task(rq_dest->curr); - } - } - double_rq_unlock(rq_src, rq_dest); - local_irq_restore(flags); + spin_unlock_irq(&rq->lock); + move_task_away(req->task, + any_online_cpu(req->task->cpus_allowed)); complete(&req->done); } } diff -urN linux-2.5.70-bk19/lib/Makefile linux-2.5.71/lib/Makefile --- linux-2.5.70-bk19/lib/Makefile 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/lib/Makefile 2003-06-14 13:53:27.000000000 -0700 @@ -1,10 +1,6 @@ # # Makefile for some libs needed in the kernel. # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \ @@ -24,15 +20,18 @@ obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/ obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/ -include $(TOPDIR)/drivers/net/Makefile.lib -include $(TOPDIR)/drivers/usb/Makefile.lib -include $(TOPDIR)/fs/Makefile.lib -include $(TOPDIR)/net/bluetooth/bnep/Makefile.lib +include drivers/net/Makefile.lib +include drivers/usb/Makefile.lib +include fs/Makefile.lib +include net/bluetooth/bnep/Makefile.lib -host-progs := gen_crc32table -clean-files := crc32table.h +host-progs := gen_crc32table +clean-files := crc32table.h $(obj)/crc32.o: $(obj)/crc32table.h +quiet_cmd_crc32 = GEN $@ + cmd_crc32 = $< > $@ + $(obj)/crc32table.h: $(obj)/gen_crc32table - ./$< > $@ + $(call cmd,crc32) diff -urN linux-2.5.70-bk19/mm/highmem.c linux-2.5.71/mm/highmem.c --- linux-2.5.70-bk19/mm/highmem.c 2003-05-26 18:00:41.000000000 -0700 +++ linux-2.5.71/mm/highmem.c 2003-06-14 13:53:27.000000000 -0700 @@ -472,23 +472,6 @@ __blk_queue_bounce(q, bio_orig, pool); } -#if defined(CONFIG_DEBUG_HIGHMEM) && defined(CONFIG_HIGHMEM) -void check_highmem_ptes(void) -{ - int idx, type; - - preempt_disable(); - for (type = 0; type < KM_TYPE_NR; type++) { - idx = type + KM_TYPE_NR*smp_processor_id(); - if (!pte_none(*(kmap_pte-idx))) { - printk("scheduling with KM_TYPE %d held!\n", type); - BUG(); - } - } - preempt_enable(); -} -#endif - #if defined(HASHED_PAGE_VIRTUAL) #define PA_HASH_ORDER 7 diff -urN linux-2.5.70-bk19/net/8021q/vlan.c linux-2.5.71/net/8021q/vlan.c --- linux-2.5.70-bk19/net/8021q/vlan.c 2003-05-26 18:00:46.000000000 -0700 +++ linux-2.5.71/net/8021q/vlan.c 2003-06-14 13:53:27.000000000 -0700 @@ -334,6 +334,33 @@ return ret; } +static void vlan_setup(struct net_device *new_dev) +{ + SET_MODULE_OWNER(new_dev); + + /* new_dev->ifindex = 0; it will be set when added to + * the global list. + * iflink is set as well. + */ + new_dev->get_stats = vlan_dev_get_stats; + + /* Make this thing known as a VLAN device */ + new_dev->priv_flags |= IFF_802_1Q_VLAN; + + /* Set us up to have no queue, as the underlying Hardware device + * can do all the queueing we could want. + */ + new_dev->tx_queue_len = 0; + + /* set up method calls */ + new_dev->change_mtu = vlan_dev_change_mtu; + new_dev->open = vlan_dev_open; + new_dev->stop = vlan_dev_stop; + new_dev->set_mac_address = vlan_dev_set_mac_address; + new_dev->set_multicast_list = vlan_dev_set_multicast_list; + new_dev->destructor = (void (*)(struct net_device *)) kfree; +} + /* Attach a VLAN device to a mac address (ie Ethernet Card). * Returns the device that was created, or NULL if there was * an error of some kind. @@ -344,8 +371,8 @@ struct vlan_group *grp; struct net_device *new_dev; struct net_device *real_dev; /* the ethernet device */ - int malloc_size = 0; int r; + char name[IFNAMSIZ]; #ifdef VLAN_DEBUG printk(VLAN_DBG "%s: if_name -:%s:- vid: %i\n", @@ -403,21 +430,6 @@ goto out_unlock; } - malloc_size = (sizeof(struct net_device)); - new_dev = (struct net_device *) kmalloc(malloc_size, GFP_KERNEL); - VLAN_MEM_DBG("net_device malloc, addr: %p size: %i\n", - new_dev, malloc_size); - - if (new_dev == NULL) - goto out_unlock; - - memset(new_dev, 0, malloc_size); - - /* Set us up to have no queue, as the underlying Hardware device - * can do all the queueing we could want. - */ - new_dev->tx_queue_len = 0; - /* Gotta set up the fields for the device. */ #ifdef VLAN_DEBUG printk(VLAN_DBG "About to allocate name, vlan_name_type: %i\n", @@ -426,54 +438,44 @@ switch (vlan_name_type) { case VLAN_NAME_TYPE_RAW_PLUS_VID: /* name will look like: eth1.0005 */ - sprintf(new_dev->name, "%s.%.4i", real_dev->name, VLAN_ID); + snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, VLAN_ID); break; case VLAN_NAME_TYPE_PLUS_VID_NO_PAD: /* Put our vlan.VID in the name. * Name will look like: vlan5 */ - sprintf(new_dev->name, "vlan%i", VLAN_ID); + snprintf(name, IFNAMSIZ, "vlan%i", VLAN_ID); break; case VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD: /* Put our vlan.VID in the name. * Name will look like: eth0.5 */ - sprintf(new_dev->name, "%s.%i", real_dev->name, VLAN_ID); + snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, VLAN_ID); break; case VLAN_NAME_TYPE_PLUS_VID: /* Put our vlan.VID in the name. * Name will look like: vlan0005 */ default: - sprintf(new_dev->name, "vlan%.4i", VLAN_ID); + snprintf(name, IFNAMSIZ, "vlan%.4i", VLAN_ID); }; + new_dev = alloc_netdev(sizeof(struct vlan_dev_info), name, + vlan_setup); + if (new_dev == NULL) + goto out_unlock; + #ifdef VLAN_DEBUG printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name); #endif - /* set up method calls */ - new_dev->init = vlan_dev_init; - new_dev->destructor = vlan_dev_destruct; - SET_MODULE_OWNER(new_dev); - - /* new_dev->ifindex = 0; it will be set when added to - * the global list. - * iflink is set as well. - */ - new_dev->get_stats = vlan_dev_get_stats; - /* IFF_BROADCAST|IFF_MULTICAST; ??? */ new_dev->flags = real_dev->flags; new_dev->flags &= ~IFF_UP; - /* Make this thing known as a VLAN device */ - new_dev->priv_flags |= IFF_802_1Q_VLAN; - /* need 4 bytes for extra VLAN header info, * hope the underlying device can handle it. */ new_dev->mtu = real_dev->mtu; - new_dev->change_mtu = vlan_dev_change_mtu; /* TODO: maybe just assign it to be ETHERNET? */ new_dev->type = real_dev->type; @@ -484,24 +486,14 @@ new_dev->hard_header_len += VLAN_HLEN; } - new_dev->priv = kmalloc(sizeof(struct vlan_dev_info), - GFP_KERNEL); VLAN_MEM_DBG("new_dev->priv malloc, addr: %p size: %i\n", new_dev->priv, sizeof(struct vlan_dev_info)); - if (new_dev->priv == NULL) - goto out_free_newdev; - - memset(new_dev->priv, 0, sizeof(struct vlan_dev_info)); - memcpy(new_dev->broadcast, real_dev->broadcast, real_dev->addr_len); memcpy(new_dev->dev_addr, real_dev->dev_addr, real_dev->addr_len); new_dev->addr_len = real_dev->addr_len; - new_dev->open = vlan_dev_open; - new_dev->stop = vlan_dev_stop; - if (real_dev->features & NETIF_F_HW_VLAN_TX) { new_dev->hard_header = real_dev->hard_header; new_dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit; @@ -512,8 +504,6 @@ new_dev->rebuild_header = vlan_dev_rebuild_header; } new_dev->hard_header_parse = real_dev->hard_header_parse; - new_dev->set_mac_address = vlan_dev_set_mac_address; - new_dev->set_multicast_list = vlan_dev_set_multicast_list; VLAN_DEV_INFO(new_dev)->vlan_id = VLAN_ID; /* 1 through VLAN_VID_MASK */ VLAN_DEV_INFO(new_dev)->real_dev = real_dev; @@ -526,7 +516,7 @@ #endif if (register_netdevice(new_dev)) - goto out_free_newdev_priv; + goto out_free_newdev; /* So, got the sucker initialized, now lets place * it into our local structure. @@ -572,9 +562,7 @@ out_free_unregister: unregister_netdev(new_dev); - -out_free_newdev_priv: - kfree(new_dev->priv); + goto out_put_dev; out_free_newdev: kfree(new_dev); diff -urN linux-2.5.70-bk19/net/8021q/vlan.h linux-2.5.71/net/8021q/vlan.h --- linux-2.5.70-bk19/net/8021q/vlan.h 2003-05-26 18:00:42.000000000 -0700 +++ linux-2.5.71/net/8021q/vlan.h 2003-06-14 13:53:27.000000000 -0700 @@ -65,8 +65,6 @@ int vlan_dev_set_mac_address(struct net_device *dev, void* addr); int vlan_dev_open(struct net_device* dev); int vlan_dev_stop(struct net_device* dev); -int vlan_dev_init(struct net_device* dev); -void vlan_dev_destruct(struct net_device* dev); int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio); int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio); int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val); diff -urN linux-2.5.70-bk19/net/8021q/vlan_dev.c linux-2.5.71/net/8021q/vlan_dev.c --- linux-2.5.70-bk19/net/8021q/vlan_dev.c 2003-05-26 18:00:57.000000000 -0700 +++ linux-2.5.71/net/8021q/vlan_dev.c 2003-06-14 13:53:27.000000000 -0700 @@ -766,28 +766,6 @@ vlan_flush_mc_list(dev); return 0; } - -int vlan_dev_init(struct net_device *dev) -{ - /* TODO: figure this out, maybe do nothing?? */ - return 0; -} - -void vlan_dev_destruct(struct net_device *dev) -{ - if (dev) { - vlan_flush_mc_list(dev); - if (dev->priv) { - if (VLAN_DEV_INFO(dev)->dent) - BUG(); - - kfree(dev->priv); - dev->priv = NULL; - } - kfree(dev); - } -} - /** Taken from Gleb + Lennert's VLAN code, and modified... */ void vlan_dev_set_multicast_list(struct net_device *vlan_dev) { diff -urN linux-2.5.70-bk19/net/bridge/br_device.c linux-2.5.71/net/bridge/br_device.c --- linux-2.5.70-bk19/net/bridge/br_device.c 2003-05-26 18:00:19.000000000 -0700 +++ linux-2.5.71/net/bridge/br_device.c 2003-06-14 13:53:27.000000000 -0700 @@ -110,10 +110,6 @@ return -1; } -static void br_dev_destruct(struct net_device *dev) -{ - kfree(dev->priv); -} void br_dev_setup(struct net_device *dev) { @@ -124,10 +120,13 @@ dev->hard_start_xmit = br_dev_xmit; dev->open = br_dev_open; dev->set_multicast_list = br_dev_set_multicast_list; - dev->destructor = br_dev_destruct; + dev->destructor = (void (*)(struct net_device *))kfree; SET_MODULE_OWNER(dev); dev->stop = br_dev_stop; dev->accept_fastpath = br_dev_accept_fastpath; dev->tx_queue_len = 0; dev->set_mac_address = NULL; + dev->priv_flags = IFF_EBRIDGE; + + ether_setup(dev); } diff -urN linux-2.5.70-bk19/net/bridge/br_if.c linux-2.5.71/net/bridge/br_if.c --- linux-2.5.70-bk19/net/bridge/br_if.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/bridge/br_if.c 2003-06-14 13:53:27.000000000 -0700 @@ -78,17 +78,14 @@ struct net_bridge *br; struct net_device *dev; - if ((br = kmalloc(sizeof(*br), GFP_KERNEL)) == NULL) + dev = alloc_netdev(sizeof(struct net_bridge), name, + br_dev_setup); + + if (!dev) return NULL; - memset(br, 0, sizeof(*br)); - dev = &br->dev; - - strlcpy(dev->name, name, sizeof(dev->name)); - dev->priv = br; - dev->priv_flags = IFF_EBRIDGE; - ether_setup(dev); - br_dev_setup(dev); + br = dev->priv; + br->dev = dev; br->lock = SPIN_LOCK_UNLOCKED; INIT_LIST_HEAD(&br->port_list); @@ -159,9 +156,9 @@ if ((br = new_nb(name)) == NULL) return -ENOMEM; - ret = register_netdev(&br->dev); + ret = register_netdev(br->dev); if (ret) - kfree(br); + kfree(br->dev); return ret; } @@ -219,7 +216,7 @@ br_stp_recalculate_bridge_id(br); br_fdb_insert(br, p, dev->dev_addr, 1); - if ((br->dev.flags & IFF_UP) && (dev->flags & IFF_UP)) + if ((br->dev->flags & IFF_UP) && (dev->flags & IFF_UP)) br_stp_enable_port(p); spin_unlock_bh(&br->lock); diff -urN linux-2.5.70-bk19/net/bridge/br_input.c linux-2.5.71/net/bridge/br_input.c --- linux-2.5.70-bk19/net/bridge/br_input.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/bridge/br_input.c 2003-06-14 13:53:27.000000000 -0700 @@ -40,7 +40,7 @@ br->statistics.rx_bytes += skb->len; indev = skb->dev; - skb->dev = &br->dev; + skb->dev = br->dev; NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, br_pass_frame_up_finish); @@ -67,7 +67,7 @@ br = p->br; passedup = 0; - if (br->dev.flags & IFF_PROMISC) { + if (br->dev->flags & IFF_PROMISC) { struct sk_buff *skb2; skb2 = skb_clone(skb, GFP_ATOMIC); @@ -140,7 +140,7 @@ return -1; } - if (!memcmp(p->br->dev.dev_addr, dest, ETH_ALEN)) + if (!memcmp(p->br->dev->dev_addr, dest, ETH_ALEN)) skb->pkt_type = PACKET_HOST; NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, diff -urN linux-2.5.70-bk19/net/bridge/br_netfilter.c linux-2.5.71/net/bridge/br_netfilter.c --- linux-2.5.70-bk19/net/bridge/br_netfilter.c 2003-05-26 18:00:59.000000000 -0700 +++ linux-2.5.71/net/bridge/br_netfilter.c 2003-06-14 13:53:27.000000000 -0700 @@ -37,7 +37,7 @@ sizeof(struct bridge_skb_cb))) #define has_bridge_parent(device) ((device)->br_port != NULL) -#define bridge_parent(device) (&((device)->br_port->br->dev)) +#define bridge_parent(device) ((device)->br_port->br->dev) /* We need these fake structures to make netfilter happy -- * lots of places assume that skb->dst != NULL, which isn't diff -urN linux-2.5.70-bk19/net/bridge/br_notify.c linux-2.5.71/net/bridge/br_notify.c --- linux-2.5.70-bk19/net/bridge/br_notify.c 2003-05-26 18:00:21.000000000 -0700 +++ linux-2.5.71/net/bridge/br_notify.c 2003-06-14 13:53:27.000000000 -0700 @@ -52,7 +52,7 @@ break; case NETDEV_DOWN: - if (br->dev.flags & IFF_UP) { + if (br->dev->flags & IFF_UP) { spin_lock_bh(&br->lock); br_stp_disable_port(p); spin_unlock_bh(&br->lock); @@ -60,7 +60,7 @@ break; case NETDEV_UP: - if (!(br->dev.flags & IFF_UP)) { + if (!(br->dev->flags & IFF_UP)) { spin_lock_bh(&br->lock); br_stp_enable_port(p); spin_unlock_bh(&br->lock); diff -urN linux-2.5.70-bk19/net/bridge/br_private.h linux-2.5.71/net/bridge/br_private.h --- linux-2.5.70-bk19/net/bridge/br_private.h 2003-05-26 18:00:26.000000000 -0700 +++ linux-2.5.71/net/bridge/br_private.h 2003-06-14 13:53:27.000000000 -0700 @@ -81,7 +81,7 @@ { spinlock_t lock; struct list_head port_list; - struct net_device dev; + struct net_device *dev; struct net_device_stats statistics; rwlock_t hash_lock; struct hlist_head hash[BR_HASH_SIZE]; diff -urN linux-2.5.70-bk19/net/bridge/br_stp.c linux-2.5.71/net/bridge/br_stp.c --- linux-2.5.70-bk19/net/bridge/br_stp.c 2003-05-26 18:00:25.000000000 -0700 +++ linux-2.5.71/net/bridge/br_stp.c 2003-06-14 13:53:27.000000000 -0700 @@ -26,7 +26,7 @@ void br_log_state(const struct net_bridge_port *p) { pr_info("%s: port %d(%s) entering %s state\n", - p->br->dev.name, p->port_no, p->dev->name, + p->br->dev->name, p->port_no, p->dev->name, br_port_state_names[p->state]); } @@ -130,7 +130,7 @@ br_topology_change_detection(br); del_timer(&br->tcn_timer); - if (br->dev.flags & IFF_UP) { + if (br->dev->flags & IFF_UP) { br_config_bpdu_generation(br); mod_timer(&br->hello_timer, jiffies + br->hello_time); } @@ -289,10 +289,10 @@ /* called under bridge lock */ void br_topology_change_detection(struct net_bridge *br) { - if (!(br->dev.flags & IFF_UP)) + if (!(br->dev->flags & IFF_UP)) return; - pr_info("%s: topology change detected", br->dev.name); + pr_info("%s: topology change detected", br->dev->name); if (br_is_root_bridge(br)) { printk(", propagating"); br->topology_change = 1; @@ -446,7 +446,7 @@ { if (br_is_designated_port(p)) { pr_info("%s: received tcn bpdu on port %i(%s)\n", - p->br->dev.name, p->port_no, p->dev->name); + p->br->dev->name, p->port_no, p->dev->name); br_topology_change_detection(p->br); br_topology_change_acknowledge(p); diff -urN linux-2.5.70-bk19/net/bridge/br_stp_bpdu.c linux-2.5.71/net/bridge/br_stp_bpdu.c --- linux-2.5.70-bk19/net/bridge/br_stp_bpdu.c 2003-05-26 18:00:46.000000000 -0700 +++ linux-2.5.71/net/bridge/br_stp_bpdu.c 2003-06-14 13:53:27.000000000 -0700 @@ -145,7 +145,7 @@ spin_lock_bh(&br->lock); if (p->state == BR_STATE_DISABLED - || !(br->dev.flags & IFF_UP) + || !(br->dev->flags & IFF_UP) || !br->stp_enabled || memcmp(buf, header, 6)) goto out; diff -urN linux-2.5.70-bk19/net/bridge/br_stp_if.c linux-2.5.71/net/bridge/br_stp_if.c --- linux-2.5.70-bk19/net/bridge/br_stp_if.c 2003-05-26 18:00:56.000000000 -0700 +++ linux-2.5.71/net/bridge/br_stp_if.c 2003-06-14 13:53:27.000000000 -0700 @@ -93,7 +93,7 @@ br = p->br; printk(KERN_INFO "%s: port %i(%s) entering %s state\n", - br->dev.name, p->port_no, p->dev->name, "disabled"); + br->dev->name, p->port_no, p->dev->name, "disabled"); wasroot = br_is_root_bridge(br); br_become_designated_port(p); @@ -124,7 +124,7 @@ memcpy(oldaddr, br->bridge_id.addr, ETH_ALEN); memcpy(br->bridge_id.addr, addr, ETH_ALEN); - memcpy(br->dev.dev_addr, addr, ETH_ALEN); + memcpy(br->dev->dev_addr, addr, ETH_ALEN); list_for_each_entry(p, &br->port_list, list) { if (!memcmp(p->designated_bridge.addr, oldaddr, ETH_ALEN)) diff -urN linux-2.5.70-bk19/net/bridge/br_stp_timer.c linux-2.5.71/net/bridge/br_stp_timer.c --- linux-2.5.70-bk19/net/bridge/br_stp_timer.c 2003-05-26 18:00:40.000000000 -0700 +++ linux-2.5.71/net/bridge/br_stp_timer.c 2003-06-14 13:53:27.000000000 -0700 @@ -38,9 +38,9 @@ { struct net_bridge *br = (struct net_bridge *)arg; - pr_debug("%s: hello timer expired\n", br->dev.name); + pr_debug("%s: hello timer expired\n", br->dev->name); spin_lock_bh(&br->lock); - if (br->dev.flags & IFF_UP) { + if (br->dev->flags & IFF_UP) { br_config_bpdu_generation(br); br->hello_timer.expires = jiffies + br->hello_time; @@ -61,7 +61,7 @@ pr_info("%s: neighbor %.2x%.2x.%.2x:%.2x:%.2x:%.2x:%.2x:%.2x lost on port %d(%s)\n", - br->dev.name, + br->dev->name, id->prio[0], id->prio[1], id->addr[0], id->addr[1], id->addr[2], id->addr[3], id->addr[4], id->addr[5], @@ -89,7 +89,7 @@ struct net_bridge *br = p->br; pr_debug("%s: %d(%s) forward delay timer\n", - br->dev.name, p->port_no, p->dev->name); + br->dev->name, p->port_no, p->dev->name); spin_lock_bh(&br->lock); if (p->state == BR_STATE_LISTENING) { p->state = BR_STATE_LEARNING; @@ -108,9 +108,9 @@ { struct net_bridge *br = (struct net_bridge *) arg; - pr_debug("%s: tcn timer expired\n", br->dev.name); + pr_debug("%s: tcn timer expired\n", br->dev->name); spin_lock_bh(&br->lock); - if (br->dev.flags & IFF_UP) { + if (br->dev->flags & IFF_UP) { br_transmit_tcn(br); br->tcn_timer.expires = jiffies + br->bridge_hello_time; @@ -123,7 +123,7 @@ { struct net_bridge *br = (struct net_bridge *) arg; - pr_debug("%s: topo change timer expired\n", br->dev.name); + pr_debug("%s: topo change timer expired\n", br->dev->name); spin_lock_bh(&br->lock); br->topology_change_detected = 0; br->topology_change = 0; @@ -135,7 +135,7 @@ struct net_bridge_port *p = (struct net_bridge_port *) arg; pr_debug("%s: %d(%s) hold timer expired\n", - p->br->dev.name, p->port_no, p->dev->name); + p->br->dev->name, p->port_no, p->dev->name); spin_lock_bh(&p->br->lock); if (p->config_pending) diff -urN linux-2.5.70-bk19/net/bridge/netfilter/ebt_redirect.c linux-2.5.71/net/bridge/netfilter/ebt_redirect.c --- linux-2.5.70-bk19/net/bridge/netfilter/ebt_redirect.c 2003-05-26 18:00:46.000000000 -0700 +++ linux-2.5.71/net/bridge/netfilter/ebt_redirect.c 2003-06-14 13:53:27.000000000 -0700 @@ -22,7 +22,7 @@ if (hooknr != NF_BR_BROUTING) memcpy((**pskb).mac.ethernet->h_dest, - in->br_port->br->dev.dev_addr, ETH_ALEN); + in->br_port->br->dev->dev_addr, ETH_ALEN); else { memcpy((**pskb).mac.ethernet->h_dest, in->dev_addr, ETH_ALEN); diff -urN linux-2.5.70-bk19/net/bridge/netfilter/ebtables.c linux-2.5.71/net/bridge/netfilter/ebtables.c --- linux-2.5.70-bk19/net/bridge/netfilter/ebtables.c 2003-05-26 18:00:37.000000000 -0700 +++ linux-2.5.71/net/bridge/netfilter/ebtables.c 2003-06-14 13:53:27.000000000 -0700 @@ -135,10 +135,10 @@ if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT)) return 1; if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check( - e->logical_in, &in->br_port->br->dev), EBT_ILOGICALIN)) + e->logical_in, in->br_port->br->dev), EBT_ILOGICALIN)) return 1; if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check( - e->logical_out, &out->br_port->br->dev), EBT_ILOGICALOUT)) + e->logical_out, out->br_port->br->dev), EBT_ILOGICALOUT)) return 1; if (e->bitmask & EBT_SOURCEMAC) { diff -urN linux-2.5.70-bk19/net/core/dev.c linux-2.5.71/net/core/dev.c --- linux-2.5.70-bk19/net/core/dev.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/core/dev.c 2003-06-14 13:53:27.000000000 -0700 @@ -3005,14 +3005,15 @@ #ifdef CONFIG_HOTPLUG struct net_hotplug_todo { - struct net_hotplug_todo *next; + struct list_head list; char ifname[IFNAMSIZ]; int is_register; }; static spinlock_t net_hotplug_list_lock = SPIN_LOCK_UNLOCKED; -static struct net_hotplug_todo *net_hotplug_list; +static DECLARE_MUTEX(net_hotplug_run); +static struct list_head net_hotplug_list = LIST_HEAD_INIT(net_hotplug_list); -static void net_run_hotplug_one(struct net_hotplug_todo *ent) +static inline void net_run_hotplug_one(struct net_hotplug_todo *ent) { char *argv[3], *envp[5], ifname[12 + IFNAMSIZ], action_str[32]; int i; @@ -3037,23 +3038,37 @@ call_usermodehelper(argv [0], argv, envp, 0); } +/* Run all queued hotplug requests. + * Requests are run in FIFO order. + */ static void net_run_hotplug_todo(void) { - struct net_hotplug_todo *list; + struct list_head list = LIST_HEAD_INIT(list); + + /* This is racy but okay since any other requests will get + * processed when the other guy does rtnl_unlock. + */ + if (list_empty(&net_hotplug_list)) + return; + + /* Need to guard against multiple cpu's getting out of order. */ + down(&net_hotplug_run); + /* Snapshot list, allow later requests */ spin_lock(&net_hotplug_list_lock); - list = net_hotplug_list; - net_hotplug_list = NULL; + list_splice_init(&net_hotplug_list, &list); spin_unlock(&net_hotplug_list_lock); - while (list != NULL) { - struct net_hotplug_todo *next = list->next; + while (!list_empty(&list)) { + struct net_hotplug_todo *ent; - net_run_hotplug_one(list); - - kfree(list); - list = next; + ent = list_entry(list.next, struct net_hotplug_todo, list); + list_del(&ent->list); + net_run_hotplug_one(ent); + kfree(ent); } + + up(&net_hotplug_run); } /* Notify userspace when a netdevice event occurs, @@ -3065,15 +3080,17 @@ { struct net_hotplug_todo *ent = kmalloc(sizeof(*ent), GFP_KERNEL); + ASSERT_RTNL(); + if (!ent) return; + INIT_LIST_HEAD(&ent->list); memcpy(ent->ifname, dev->name, IFNAMSIZ); ent->is_register = is_register; spin_lock(&net_hotplug_list_lock); - ent->next = net_hotplug_list; - net_hotplug_list = ent; + list_add(&ent->list, &net_hotplug_list); spin_unlock(&net_hotplug_list_lock); } #endif diff -urN linux-2.5.70-bk19/net/core/flow.c linux-2.5.71/net/core/flow.c --- linux-2.5.70-bk19/net/core/flow.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/core/flow.c 2003-06-14 13:53:27.000000000 -0700 @@ -15,6 +15,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -33,7 +36,10 @@ static u32 flow_hash_shift; #define flow_hash_size (1 << flow_hash_shift) -static struct flow_cache_entry **flow_table; +static DEFINE_PER_CPU(struct flow_cache_entry **, flow_tables) = { NULL }; + +#define flow_table(cpu) (per_cpu(flow_tables, cpu)) + static kmem_cache_t *flow_cachep; static int flow_lwm, flow_hwm; @@ -43,30 +49,39 @@ u32 hash_rnd; int count; } ____cacheline_aligned; -static struct flow_percpu_info flow_hash_info[NR_CPUS]; +static DEFINE_PER_CPU(struct flow_percpu_info, flow_hash_info) = { 0 }; -#define flow_hash_rnd_recalc(cpu) (flow_hash_info[cpu].hash_rnd_recalc) -#define flow_hash_rnd(cpu) (flow_hash_info[cpu].hash_rnd) -#define flow_count(cpu) (flow_hash_info[cpu].count) +#define flow_hash_rnd_recalc(cpu) \ + (per_cpu(flow_hash_info, cpu).hash_rnd_recalc) +#define flow_hash_rnd(cpu) \ + (per_cpu(flow_hash_info, cpu).hash_rnd) +#define flow_count(cpu) \ + (per_cpu(flow_hash_info, cpu).count) static struct timer_list flow_hash_rnd_timer; #define FLOW_HASH_RND_PERIOD (10 * 60 * HZ) struct flow_flush_info { - void *object; atomic_t cpuleft; + unsigned long cpumap; struct completion completion; }; -static struct tasklet_struct flow_flush_tasklets[NR_CPUS]; -static DECLARE_MUTEX(flow_flush_sem); +static DEFINE_PER_CPU(struct tasklet_struct, flow_flush_tasklets) = { NULL }; + +#define flow_flush_tasklet(cpu) (&per_cpu(flow_flush_tasklets, cpu)) + +static DECLARE_MUTEX(flow_cache_cpu_sem); +static unsigned long flow_cache_cpu_map; +static unsigned int flow_cache_cpu_count; static void flow_cache_new_hashrnd(unsigned long arg) { int i; for (i = 0; i < NR_CPUS; i++) - flow_hash_rnd_recalc(i) = 1; + if (test_bit(i, &flow_cache_cpu_map)) + flow_hash_rnd_recalc(i) = 1; flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD; add_timer(&flow_hash_rnd_timer); @@ -80,7 +95,7 @@ for (i = 0; i < flow_hash_size; i++) { int k = 0; - flp = &flow_table[cpu*flow_hash_size+i]; + flp = &flow_table(cpu)[i]; while ((fle = *flp) != NULL && k < shrink_to) { k++; flp = &fle->next; @@ -160,11 +175,16 @@ local_bh_disable(); cpu = smp_processor_id(); + + fle = NULL; + if (!test_bit(cpu, &flow_cache_cpu_map)) + goto nocache; + if (flow_hash_rnd_recalc(cpu)) flow_new_hash_rnd(cpu); hash = flow_hash_code(key, cpu); - head = &flow_table[(cpu << flow_hash_shift) + hash]; + head = &flow_table(cpu)[hash]; for (fle = *head; fle; fle = fle->next) { if (fle->family == family && fle->dir == dir && @@ -198,6 +218,7 @@ } } +nocache: { void *obj; atomic_t *obj_ref; @@ -224,18 +245,20 @@ static void flow_cache_flush_tasklet(unsigned long data) { struct flow_flush_info *info = (void *)data; - void *object = info->object; int i; int cpu; cpu = smp_processor_id(); for (i = 0; i < flow_hash_size; i++) { - struct flow_cache_entry *fle, **flp; + struct flow_cache_entry *fle; - flp = &flow_table[(cpu << flow_hash_shift) + i]; - for (; (fle = *flp) != NULL; flp = &fle->next) { - if (fle->object != object) + fle = flow_table(cpu)[i]; + for (; fle; fle = fle->next) { + unsigned genid = atomic_read(&flow_cache_genid); + + if (!fle->object || fle->genid == genid) continue; + fle->object = NULL; atomic_dec(fle->object_ref); } @@ -245,6 +268,7 @@ complete(&info->completion); } +static void flow_cache_flush_per_cpu(void *) __attribute__((__unused__)); static void flow_cache_flush_per_cpu(void *data) { struct flow_flush_info *info = data; @@ -252,24 +276,31 @@ struct tasklet_struct *tasklet; cpu = smp_processor_id(); - tasklet = &flow_flush_tasklets[cpu]; - tasklet_init(tasklet, flow_cache_flush_tasklet, (unsigned long)info); + if (!test_bit(cpu, &info->cpumap)) + return; + + tasklet = flow_flush_tasklet(cpu); + tasklet->data = (unsigned long)info; tasklet_schedule(tasklet); } -void flow_cache_flush(void *object) +void flow_cache_flush(void) { struct flow_flush_info info; + static DECLARE_MUTEX(flow_flush_sem); + + down(&flow_cache_cpu_sem); + info.cpumap = flow_cache_cpu_map; + atomic_set(&info.cpuleft, flow_cache_cpu_count); + up(&flow_cache_cpu_sem); - info.object = object; - atomic_set(&info.cpuleft, num_online_cpus()); init_completion(&info.completion); down(&flow_flush_sem); - smp_call_function(flow_cache_flush_per_cpu, &info, 1, 0); local_bh_disable(); - flow_cache_flush_per_cpu(&info); + smp_call_function(flow_cache_flush_per_cpu, &info, 1, 0); + flow_cache_flush_tasklet((unsigned long)&info); local_bh_enable(); wait_for_completion(&info.completion); @@ -277,11 +308,51 @@ up(&flow_flush_sem); } -static int __init flow_cache_init(void) +static void __devinit flow_cache_cpu_online(int cpu) { + struct tasklet_struct *tasklet; unsigned long order; - int i; + flow_hash_rnd_recalc(cpu) = 1; + + for (order = 0; + (PAGE_SIZE << order) < + (sizeof(struct flow_cache_entry *)*flow_hash_size); + order++) + /* NOTHING */; + + flow_table(cpu) = (struct flow_cache_entry **) + __get_free_pages(GFP_KERNEL, order); + + memset(flow_table(cpu), 0, PAGE_SIZE << order); + + tasklet = flow_flush_tasklet(cpu); + tasklet_init(tasklet, flow_cache_flush_tasklet, 0); + + down(&flow_cache_cpu_sem); + set_bit(cpu, &flow_cache_cpu_map); + flow_cache_cpu_count++; + up(&flow_cache_cpu_sem); +} + +static int __devinit flow_cache_cpu_notify(struct notifier_block *self, + unsigned long action, void *hcpu) +{ + unsigned long cpu = (unsigned long)cpu; + switch (action) { + case CPU_UP_PREPARE: + flow_cache_cpu_online(cpu); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block __devinitdata flow_cache_cpu_nb = { + .notifier_call = flow_cache_cpu_notify, +}; + +static int __init flow_cache_init(void) +{ flow_cachep = kmem_cache_create("flow_cache", sizeof(struct flow_cache_entry), 0, SLAB_HWCACHE_ALIGN, @@ -294,27 +365,13 @@ flow_lwm = 2 * flow_hash_size; flow_hwm = 4 * flow_hash_size; - for (i = 0; i < NR_CPUS; i++) - flow_hash_rnd_recalc(i) = 1; - init_timer(&flow_hash_rnd_timer); flow_hash_rnd_timer.function = flow_cache_new_hashrnd; flow_hash_rnd_timer.expires = jiffies + FLOW_HASH_RND_PERIOD; add_timer(&flow_hash_rnd_timer); - for (order = 0; - (PAGE_SIZE << order) < - (NR_CPUS*sizeof(struct flow_entry *)*flow_hash_size); - order++) - /* NOTHING */; - - flow_table = (struct flow_cache_entry **) - __get_free_pages(GFP_ATOMIC, order); - - if (!flow_table) - panic("Failed to allocate flow cache hash table\n"); - - memset(flow_table, 0, PAGE_SIZE << order); + flow_cache_cpu_online(smp_processor_id()); + register_cpu_notifier(&flow_cache_cpu_nb); return 0; } diff -urN linux-2.5.70-bk19/net/core/neighbour.c linux-2.5.71/net/core/neighbour.c --- linux-2.5.70-bk19/net/core/neighbour.c 2003-05-26 18:00:21.000000000 -0700 +++ linux-2.5.71/net/core/neighbour.c 2003-06-14 13:53:27.000000000 -0700 @@ -1094,6 +1094,7 @@ kfree(p); return NULL; } + p->sysctl_table = NULL; write_lock_bh(&tbl->lock); p->next = tbl->parms.next; tbl->parms.next = p; @@ -1113,9 +1114,6 @@ if (*p == parms) { *p = parms->next; write_unlock_bh(&tbl->lock); -#ifdef CONFIG_SYSCTL - neigh_sysctl_unregister(parms); -#endif kfree(parms); return; } @@ -1178,9 +1176,6 @@ } } write_unlock(&neigh_tbl_lock); -#ifdef CONFIG_SYSCTL - neigh_sysctl_unregister(&tbl->parms); -#endif return 0; } diff -urN linux-2.5.70-bk19/net/core/net-sysfs.c linux-2.5.71/net/core/net-sysfs.c --- linux-2.5.70-bk19/net/core/net-sysfs.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/core/net-sysfs.c 2003-06-14 13:53:27.000000000 -0700 @@ -3,10 +3,6 @@ * * Copyright (c) 2003 Stephen Hemminber * - * - * TODO: - * last_tx - * last_rx */ #include @@ -16,33 +12,61 @@ #include #include -#define to_net_dev(class) container_of((class), struct net_device, class_dev) +#define to_class_dev(obj) container_of(obj,struct class_device,kobj) +#define to_net_dev(class) container_of(class, struct net_device, class_dev) + +/* use same locking rules as GIF* ioctl's */ +static ssize_t netdev_show(const struct class_device *cd, char *buf, + ssize_t (*format)(const struct net_device *, char *)) +{ + struct net_device *net = to_net_dev(cd); + ssize_t ret = -EINVAL; + + read_lock(&dev_base_lock); + if (!net->deadbeaf) + ret = (*format)(net, buf); + read_unlock(&dev_base_lock); + + return ret; +} -/* generate a show function for simple field */ +/* generate a show function for simple field */ #define NETDEVICE_SHOW(field, format_string) \ -static ssize_t show_##field(struct class_device *dev, char *buf) \ +static ssize_t format_##field(const struct net_device *net, char *buf) \ { \ - return sprintf(buf, format_string, to_net_dev(dev)->field); \ + return sprintf(buf, format_string, net->field); \ +} \ +static ssize_t show_##field(struct class_device *cd, char *buf) \ +{ \ + return netdev_show(cd, buf, format_##field); \ } -/* generate a store function for a field with locking */ -#define NETDEVICE_STORE(field) \ -static ssize_t \ -store_##field(struct class_device *dev, const char *buf, size_t len) \ -{ \ - char *endp; \ - long new = simple_strtol(buf, &endp, 16); \ - \ - if (endp == buf || new < 0) \ - return -EINVAL; \ - \ - if (!capable(CAP_NET_ADMIN)) \ - return -EPERM; \ - \ - rtnl_lock(); \ - to_net_dev(dev)->field = new; \ - rtnl_unlock(); \ - return len; \ + +/* use same locking and permission rules as SIF* ioctl's */ +static ssize_t netdev_store(struct class_device *dev, + const char *buf, size_t len, + int (*set)(struct net_device *, unsigned long)) +{ + struct net_device *net = to_net_dev(dev); + char *endp; + unsigned long new; + int ret = -EINVAL; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + new = simple_strtoul(buf, &endp, 0); + if (endp == buf) + goto err; + + rtnl_lock(); + if (!net->deadbeaf) { + if ((ret = (*set)(net, new)) == 0) + ret = len; + } + rtnl_unlock(); + err: + return ret; } /* generate a read-only network device class attribute */ @@ -56,6 +80,7 @@ NETDEVICE_ATTR(features, "%#x\n"); NETDEVICE_ATTR(type, "%d\n"); +/* use same locking rules as GIFHWADDR ioctl's */ static ssize_t format_addr(char *buf, const unsigned char *addr, int len) { int i; @@ -72,12 +97,16 @@ static ssize_t show_address(struct class_device *dev, char *buf) { struct net_device *net = to_net_dev(dev); + if (net->deadbeaf) + return -EINVAL; return format_addr(buf, net->dev_addr, net->addr_len); } static ssize_t show_broadcast(struct class_device *dev, char *buf) { struct net_device *net = to_net_dev(dev); + if (net->deadbeaf) + return -EINVAL; return format_addr(buf, net->broadcast, net->addr_len); } @@ -87,54 +116,45 @@ /* read-write attributes */ NETDEVICE_SHOW(mtu, "%d\n"); -static ssize_t store_mtu(struct class_device *dev, const char *buf, size_t len) +static int change_mtu(struct net_device *net, unsigned long new_mtu) { - char *endp; - int new_mtu; - int err; - - new_mtu = simple_strtoul(buf, &endp, 10); - if (endp == buf) - return -EINVAL; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - rtnl_lock(); - err = dev_set_mtu(to_net_dev(dev), new_mtu); - rtnl_unlock(); + return dev_set_mtu(net, (int) new_mtu); +} - return err == 0 ? len : err; +static ssize_t store_mtu(struct class_device *dev, const char *buf, size_t len) +{ + return netdev_store(dev, buf, len, change_mtu); } static CLASS_DEVICE_ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu); NETDEVICE_SHOW(flags, "%#x\n"); +static int change_flags(struct net_device *net, unsigned long new_flags) +{ + return dev_change_flags(net, (unsigned) new_flags); +} + static ssize_t store_flags(struct class_device *dev, const char *buf, size_t len) { - unsigned long new_flags; - char *endp; - int err = 0; + return netdev_store(dev, buf, len, change_flags); +} - new_flags = simple_strtoul(buf, &endp, 16); - if (endp == buf) - return -EINVAL; +static CLASS_DEVICE_ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags); - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - rtnl_lock(); - err = dev_change_flags(to_net_dev(dev), new_flags); - rtnl_unlock(); +NETDEVICE_SHOW(tx_queue_len, "%lu\n"); - return err ? err : len; +static int change_tx_queue_len(struct net_device *net, unsigned long new_len) +{ + net->tx_queue_len = new_len; + return 0; } -static CLASS_DEVICE_ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags); +static ssize_t store_tx_queue_len(struct class_device *dev, const char *buf, size_t len) +{ + return netdev_store(dev, buf,len, change_tx_queue_len); +} -NETDEVICE_SHOW(tx_queue_len, "%lu\n"); -NETDEVICE_STORE(tx_queue_len); static CLASS_DEVICE_ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len, store_tx_queue_len); @@ -237,16 +257,17 @@ { struct netstat_fs_entry *entry = container_of(attr, struct netstat_fs_entry, attr); - struct class_device *class_dev - = container_of(kobj->parent, struct class_device, kobj); struct net_device *dev - = to_net_dev(class_dev); - struct net_device_stats *stats - = dev->get_stats ? dev->get_stats(dev) : NULL; - - if (stats && entry->show) - return entry->show(stats, buf); - return -EINVAL; + = to_net_dev(to_class_dev(kobj->parent)); + struct net_device_stats *stats; + ssize_t ret = -EINVAL; + + read_lock(&dev_base_lock); + if (!dev->deadbeaf && entry->show && dev->get_stats && + (stats = (*dev->get_stats)(dev))) + ret = entry->show(stats, buf); + read_unlock(&dev_base_lock); + return ret; } static struct sysfs_ops netstat_sysfs_ops = { @@ -278,17 +299,11 @@ goto out_unreg; } - net->stats_kobj.parent = NULL; if (net->get_stats) { struct kobject *k = &net->stats_kobj; - k->parent = kobject_get(&class_dev->kobj); - if (!k->parent) { - ret = -EBUSY; - goto out_unreg; - } - + k->parent = &class_dev->kobj; strlcpy(k->name, "statistics", KOBJ_NAME_LEN); k->ktype = &netstat_ktype; diff -urN linux-2.5.70-bk19/net/ipv4/devinet.c linux-2.5.71/net/ipv4/devinet.c --- linux-2.5.70-bk19/net/ipv4/devinet.c 2003-05-26 18:00:26.000000000 -0700 +++ linux-2.5.71/net/ipv4/devinet.c 2003-06-14 13:53:27.000000000 -0700 @@ -197,7 +197,9 @@ /* in_dev_put following below will kill the in_device */ write_unlock_bh(&inetdev_lock); - +#ifdef CONFIG_SYSCTL + neigh_sysctl_unregister(in_dev->arp_parms); +#endif neigh_parms_release(&arp_tbl, in_dev->arp_parms); in_dev_put(in_dev); } diff -urN linux-2.5.70-bk19/net/ipv4/ip_gre.c linux-2.5.71/net/ipv4/ip_gre.c --- linux-2.5.70-bk19/net/ipv4/ip_gre.c 2003-05-26 18:00:45.000000000 -0700 +++ linux-2.5.71/net/ipv4/ip_gre.c 2003-06-14 13:53:27.000000000 -0700 @@ -114,20 +114,13 @@ */ static int ipgre_tunnel_init(struct net_device *dev); +static void ipgre_tunnel_setup(struct net_device *dev); /* Fallback tunnel: no source, no destination, no key, no options */ static int ipgre_fb_tunnel_init(struct net_device *dev); -static struct net_device ipgre_fb_tunnel_dev = { - .name = "gre0", - .init = ipgre_fb_tunnel_init -}; - -static struct ip_tunnel ipgre_fb_tunnel = { - .dev = &ipgre_fb_tunnel_dev, - .parms ={ .name = "gre0" } -}; +static struct net_device *ipgre_fb_tunnel_dev; /* Tunnel hash table */ @@ -190,8 +183,9 @@ if (t->parms.i_key == key && (t->dev->flags&IFF_UP)) return t; } - if (ipgre_fb_tunnel_dev.flags&IFF_UP) - return &ipgre_fb_tunnel; + + if (ipgre_fb_tunnel_dev->flags&IFF_UP) + return ipgre_fb_tunnel_dev->priv; return NULL; } @@ -246,6 +240,7 @@ struct net_device *dev; unsigned h = HASH(key); int prio = 0; + char name[IFNAMSIZ]; if (local) prio |= 1; @@ -262,32 +257,28 @@ if (!create) return NULL; - dev = kmalloc(sizeof(*dev) + sizeof(*t), GFP_KERNEL); - if (dev == NULL) - return NULL; - - memset(dev, 0, sizeof(*dev) + sizeof(*t)); - dev->priv = (void*)(dev+1); - nt = (struct ip_tunnel*)dev->priv; - nt->dev = dev; - dev->init = ipgre_tunnel_init; - memcpy(&nt->parms, parms, sizeof(*parms)); - nt->parms.name[IFNAMSIZ-1] = '\0'; - strcpy(dev->name, nt->parms.name); - if (dev->name[0] == 0) { + if (parms->name[0]) + strlcpy(name, parms->name, IFNAMSIZ); + else { int i; for (i=1; i<100; i++) { - sprintf(dev->name, "gre%d", i); - if (__dev_get_by_name(dev->name) == NULL) + sprintf(name, "gre%d", i); + if (__dev_get_by_name(name) == NULL) break; } if (i==100) goto failed; - memcpy(nt->parms.name, dev->name, IFNAMSIZ); } - SET_MODULE_OWNER(dev); - if (register_netdevice(dev) < 0) + + dev = alloc_netdev(sizeof(*t), name, ipgre_tunnel_setup); + if (register_netdevice(dev) < 0) { + kfree(dev); goto failed; + } + + nt = dev->priv; + dev->init = ipgre_tunnel_init; + nt->parms = *parms; dev_hold(dev); ipgre_tunnel_link(nt); @@ -295,16 +286,9 @@ return nt; failed: - kfree(dev); return NULL; } -static void ipgre_tunnel_destructor(struct net_device *dev) -{ - if (dev != &ipgre_fb_tunnel_dev) - kfree(dev); -} - static void ipgre_tunnel_uninit(struct net_device *dev) { ipgre_tunnel_unlink((struct ip_tunnel*)dev->priv); @@ -916,7 +900,7 @@ switch (cmd) { case SIOCGETTUNNEL: t = NULL; - if (dev == &ipgre_fb_tunnel_dev) { + if (dev == ipgre_fb_tunnel_dev) { if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { err = -EFAULT; break; @@ -955,8 +939,7 @@ t = ipgre_tunnel_locate(&p, cmd == SIOCADDTUNNEL); - if (dev != &ipgre_fb_tunnel_dev && cmd == SIOCCHGTUNNEL && - t != &ipgre_fb_tunnel) { + if (dev != ipgre_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { if (t != NULL) { if (t->dev != dev) { err = -EEXIST; @@ -1006,7 +989,7 @@ if (!capable(CAP_NET_ADMIN)) goto done; - if (dev == &ipgre_fb_tunnel_dev) { + if (dev == ipgre_fb_tunnel_dev) { err = -EFAULT; if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) goto done; @@ -1014,7 +997,7 @@ if ((t = ipgre_tunnel_locate(&p, 0)) == NULL) goto done; err = -EPERM; - if (t == &ipgre_fb_tunnel) + if (t == ipgre_fb_tunnel_dev->priv) goto done; dev = t->dev; } @@ -1140,12 +1123,11 @@ #endif -static void ipgre_tunnel_init_gen(struct net_device *dev) +static void ipgre_tunnel_setup(struct net_device *dev) { - struct ip_tunnel *t = (struct ip_tunnel*)dev->priv; - + SET_MODULE_OWNER(dev); dev->uninit = ipgre_tunnel_uninit; - dev->destructor = ipgre_tunnel_destructor; + dev->destructor = (void (*)(struct net_device *))kfree; dev->hard_start_xmit = ipgre_tunnel_xmit; dev->get_stats = ipgre_tunnel_get_stats; dev->do_ioctl = ipgre_tunnel_ioctl; @@ -1157,8 +1139,6 @@ dev->flags = IFF_NOARP; dev->iflink = 0; dev->addr_len = 4; - memcpy(dev->dev_addr, &t->parms.iph.saddr, 4); - memcpy(dev->broadcast, &t->parms.iph.daddr, 4); } static int ipgre_tunnel_init(struct net_device *dev) @@ -1173,7 +1153,9 @@ tunnel = (struct ip_tunnel*)dev->priv; iph = &tunnel->parms.iph; - ipgre_tunnel_init_gen(dev); + tunnel->dev = dev; + memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); + memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); /* Guess output device to choose reasonable mtu and hard_header_len */ @@ -1231,18 +1213,15 @@ int __init ipgre_fb_tunnel_init(struct net_device *dev) { struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv; - struct iphdr *iph; - - ipgre_tunnel_init_gen(dev); + struct iphdr *iph = &tunnel->parms.iph; - iph = &ipgre_fb_tunnel.parms.iph; iph->version = 4; iph->protocol = IPPROTO_GRE; iph->ihl = 5; tunnel->hlen = sizeof(struct iphdr) + 4; dev_hold(dev); - tunnels_wc[0] = &ipgre_fb_tunnel; + tunnels_wc[0] = tunnel; return 0; } @@ -1259,6 +1238,8 @@ int __init ipgre_init(void) { + int err = -EINVAL; + printk(KERN_INFO "GRE over IPv4 tunneling driver\n"); if (inet_add_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) { @@ -1266,10 +1247,23 @@ return -EAGAIN; } - ipgre_fb_tunnel_dev.priv = (void*)&ipgre_fb_tunnel; - SET_MODULE_OWNER(&ipgre_fb_tunnel_dev); - register_netdev(&ipgre_fb_tunnel_dev); - return 0; + ipgre_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "gre0", + ipgre_tunnel_setup); + if (!ipgre_fb_tunnel_dev) { + err = -ENOMEM; + goto fail; + } + + ipgre_fb_tunnel_dev->init = ipgre_fb_tunnel_init; + + if ((err = register_netdev(ipgre_fb_tunnel_dev))) + goto fail; +out: + return err; +fail: + inet_del_protocol(&ipgre_protocol, IPPROTO_GRE); + kfree(ipgre_fb_tunnel_dev); + goto out; } void ipgre_fini(void) @@ -1277,7 +1271,7 @@ if (inet_del_protocol(&ipgre_protocol, IPPROTO_GRE) < 0) printk(KERN_INFO "ipgre close: can't remove protocol\n"); - unregister_netdev(&ipgre_fb_tunnel_dev); + unregister_netdev(ipgre_fb_tunnel_dev); } #ifdef MODULE diff -urN linux-2.5.70-bk19/net/ipv4/ipip.c linux-2.5.71/net/ipv4/ipip.c --- linux-2.5.70-bk19/net/ipv4/ipip.c 2003-05-26 18:01:03.000000000 -0700 +++ linux-2.5.71/net/ipv4/ipip.c 2003-06-14 13:53:27.000000000 -0700 @@ -122,16 +122,9 @@ static int ipip_fb_tunnel_init(struct net_device *dev); static int ipip_tunnel_init(struct net_device *dev); +static void ipip_tunnel_setup(struct net_device *dev); -static struct net_device ipip_fb_tunnel_dev = { - .name = "tunl0", - .init = ipip_fb_tunnel_init, -}; - -static struct ip_tunnel ipip_fb_tunnel = { - .dev = &ipip_fb_tunnel_dev, - .parms ={ .name = "tunl0", } -}; +static struct net_device *ipip_fb_tunnel_dev; static struct ip_tunnel *tunnels_r_l[HASH_SIZE]; static struct ip_tunnel *tunnels_r[HASH_SIZE]; @@ -216,6 +209,7 @@ struct net_device *dev; unsigned h = 0; int prio = 0; + char name[IFNAMSIZ]; if (remote) { prio |= 2; @@ -232,32 +226,33 @@ if (!create) return NULL; - dev = kmalloc(sizeof(*dev) + sizeof(*t), GFP_KERNEL); - if (dev == NULL) - return NULL; - - memset(dev, 0, sizeof(*dev) + sizeof(*t)); - dev->priv = (void*)(dev+1); - nt = (struct ip_tunnel*)dev->priv; - nt->dev = dev; - dev->init = ipip_tunnel_init; - memcpy(&nt->parms, parms, sizeof(*parms)); - nt->parms.name[IFNAMSIZ-1] = '\0'; - strcpy(dev->name, nt->parms.name); - if (dev->name[0] == 0) { + if (parms->name[0]) + strlcpy(name, parms->name, IFNAMSIZ); + else { int i; for (i=1; i<100; i++) { - sprintf(dev->name, "tunl%d", i); - if (__dev_get_by_name(dev->name) == NULL) + sprintf(name, "tunl%d", i); + if (__dev_get_by_name(name) == NULL) break; } if (i==100) goto failed; - memcpy(nt->parms.name, dev->name, IFNAMSIZ); } + + dev = alloc_netdev(sizeof(*t), name, ipip_tunnel_setup); + if (dev == NULL) + return NULL; + + nt = dev->priv; SET_MODULE_OWNER(dev); - if (register_netdevice(dev) < 0) + dev->init = ipip_tunnel_init; + dev->destructor = (void (*)(struct net_device *))kfree; + nt->parms = *parms; + + if (register_netdevice(dev) < 0) { + kfree(dev); goto failed; + } dev_hold(dev); ipip_tunnel_link(nt); @@ -265,19 +260,12 @@ return nt; failed: - kfree(dev); return NULL; } -static void ipip_tunnel_destructor(struct net_device *dev) -{ - if (dev != &ipip_fb_tunnel_dev) - kfree(dev); -} - static void ipip_tunnel_uninit(struct net_device *dev) { - if (dev == &ipip_fb_tunnel_dev) { + if (dev == ipip_fb_tunnel_dev) { write_lock_bh(&ipip_lock); tunnels_wc[0] = NULL; write_unlock_bh(&ipip_lock); @@ -682,7 +670,7 @@ switch (cmd) { case SIOCGETTUNNEL: t = NULL; - if (dev == &ipip_fb_tunnel_dev) { + if (dev == ipip_fb_tunnel_dev) { if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { err = -EFAULT; break; @@ -715,8 +703,7 @@ t = ipip_tunnel_locate(&p, cmd == SIOCADDTUNNEL); - if (dev != &ipip_fb_tunnel_dev && cmd == SIOCCHGTUNNEL && - t != &ipip_fb_tunnel) { + if (dev != ipip_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { if (t != NULL) { if (t->dev != dev) { err = -EEXIST; @@ -757,7 +744,7 @@ if (!capable(CAP_NET_ADMIN)) goto done; - if (dev == &ipip_fb_tunnel_dev) { + if (dev == ipip_fb_tunnel_dev) { err = -EFAULT; if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) goto done; @@ -765,7 +752,7 @@ if ((t = ipip_tunnel_locate(&p, 0)) == NULL) goto done; err = -EPERM; - if (t == &ipip_fb_tunnel) + if (t->dev == ipip_fb_tunnel_dev) goto done; dev = t->dev; } @@ -793,12 +780,10 @@ return 0; } -static void ipip_tunnel_init_gen(struct net_device *dev) +static void ipip_tunnel_setup(struct net_device *dev) { - struct ip_tunnel *t = (struct ip_tunnel*)dev->priv; - + SET_MODULE_OWNER(dev); dev->uninit = ipip_tunnel_uninit; - dev->destructor = ipip_tunnel_destructor; dev->hard_start_xmit = ipip_tunnel_xmit; dev->get_stats = ipip_tunnel_get_stats; dev->do_ioctl = ipip_tunnel_ioctl; @@ -810,8 +795,6 @@ dev->flags = IFF_NOARP; dev->iflink = 0; dev->addr_len = 4; - memcpy(dev->dev_addr, &t->parms.iph.saddr, 4); - memcpy(dev->broadcast, &t->parms.iph.daddr, 4); } static int ipip_tunnel_init(struct net_device *dev) @@ -822,8 +805,9 @@ tunnel = (struct ip_tunnel*)dev->priv; iph = &tunnel->parms.iph; - - ipip_tunnel_init_gen(dev); + tunnel->dev = dev; + memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); + memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); if (iph->daddr) { struct flowi fl = { .oif = tunnel->parms.link, @@ -854,17 +838,15 @@ static int __init ipip_fb_tunnel_init(struct net_device *dev) { - struct iphdr *iph; - - ipip_tunnel_init_gen(dev); + struct ip_tunnel *tunnel = dev->priv; + struct iphdr *iph = &tunnel->parms.iph; - iph = &ipip_fb_tunnel.parms.iph; iph->version = 4; iph->protocol = IPPROTO_IPIP; iph->ihl = 5; dev_hold(dev); - tunnels_wc[0] = &ipip_fb_tunnel; + tunnels_wc[0] = tunnel; return 0; } @@ -878,6 +860,8 @@ int __init ipip_init(void) { + int err; + printk(banner); if (xfrm4_tunnel_register(&ipip_handler) < 0) { @@ -885,10 +869,24 @@ return -EAGAIN; } - ipip_fb_tunnel_dev.priv = (void*)&ipip_fb_tunnel; - SET_MODULE_OWNER(&ipip_fb_tunnel_dev); - register_netdev(&ipip_fb_tunnel_dev); - return 0; + ipip_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), + "tunl0", + ipip_tunnel_setup); + if (!ipip_fb_tunnel_dev) { + err = -ENOMEM; + goto fail; + } + + ipip_fb_tunnel_dev->init = ipip_fb_tunnel_init; + + if ((err = register_netdev(ipip_fb_tunnel_dev))) + goto fail; + out: + return err; + fail: + xfrm4_tunnel_deregister(&ipip_handler); + kfree(ipip_fb_tunnel_dev); + goto out; } static void __exit ipip_fini(void) @@ -896,7 +894,7 @@ if (xfrm4_tunnel_deregister(&ipip_handler) < 0) printk(KERN_INFO "ipip close: can't deregister tunnel\n"); - unregister_netdev(&ipip_fb_tunnel_dev); + unregister_netdev(ipip_fb_tunnel_dev); } #ifdef MODULE diff -urN linux-2.5.70-bk19/net/ipv4/netfilter/iptable_filter.c linux-2.5.71/net/ipv4/netfilter/iptable_filter.c --- linux-2.5.70-bk19/net/ipv4/netfilter/iptable_filter.c 2003-05-26 18:00:38.000000000 -0700 +++ linux-2.5.71/net/ipv4/netfilter/iptable_filter.c 2003-06-14 13:53:27.000000000 -0700 @@ -107,10 +107,6 @@ const struct net_device *out, int (*okfn)(struct sk_buff *)) { - /* FIXME: Push down to extensions --RR */ - if (skb_is_nonlinear(*pskb) && skb_linearize(*pskb, GFP_ATOMIC) != 0) - return NF_DROP; - /* root is playing with raw sockets. */ if ((*pskb)->len < sizeof(struct iphdr) || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) { diff -urN linux-2.5.70-bk19/net/ipv4/netfilter/iptable_mangle.c linux-2.5.71/net/ipv4/netfilter/iptable_mangle.c --- linux-2.5.70-bk19/net/ipv4/netfilter/iptable_mangle.c 2003-05-26 18:00:56.000000000 -0700 +++ linux-2.5.71/net/ipv4/netfilter/iptable_mangle.c 2003-06-14 13:53:27.000000000 -0700 @@ -145,10 +145,6 @@ u_int32_t saddr, daddr; unsigned long nfmark; - /* FIXME: Push down to extensions --RR */ - if (skb_is_nonlinear(*pskb) && skb_linearize(*pskb, GFP_ATOMIC) != 0) - return NF_DROP; - /* root is playing with raw sockets. */ if ((*pskb)->len < sizeof(struct iphdr) || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) { diff -urN linux-2.5.70-bk19/net/ipv4/xfrm4_policy.c linux-2.5.71/net/ipv4/xfrm4_policy.c --- linux-2.5.70-bk19/net/ipv4/xfrm4_policy.c 2003-05-26 18:00:45.000000000 -0700 +++ linux-2.5.71/net/ipv4/xfrm4_policy.c 2003-06-14 13:53:27.000000000 -0700 @@ -172,6 +172,7 @@ struct iphdr *iph = skb->nh.iph; u8 *xprth = skb->nh.raw + iph->ihl*4; + memset(fl, 0, sizeof(struct flowi)); if (!(iph->frag_off & htons(IP_MF | IP_OFFSET))) { switch (iph->protocol) { case IPPROTO_UDP: @@ -212,8 +213,6 @@ fl->fl_ipsec_spi = 0; break; }; - } else { - memset(fl, 0, sizeof(struct flowi)); } fl->proto = iph->protocol; fl->fl4_dst = iph->daddr; diff -urN linux-2.5.70-bk19/net/ipv6/addrconf.c linux-2.5.71/net/ipv6/addrconf.c --- linux-2.5.70-bk19/net/ipv6/addrconf.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/ipv6/addrconf.c 2003-06-14 13:53:27.000000000 -0700 @@ -1893,10 +1893,11 @@ /* Shot the device (if unregistered) */ if (how == 1) { - neigh_parms_release(&nd_tbl, idev->nd_parms); #ifdef CONFIG_SYSCTL addrconf_sysctl_unregister(&idev->cnf); + neigh_sysctl_unregister(idev->nd_parms); #endif + neigh_parms_release(&nd_tbl, idev->nd_parms); in6_dev_put(idev); } return 0; diff -urN linux-2.5.70-bk19/net/ipv6/mcast.c linux-2.5.71/net/ipv6/mcast.c --- linux-2.5.70-bk19/net/ipv6/mcast.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/ipv6/mcast.c 2003-06-14 13:53:27.000000000 -0700 @@ -1210,7 +1210,7 @@ IPV6_TLV_ROUTERALERT, 2, 0, 0, IPV6_TLV_PADN, 0 }; - skb = sock_alloc_send_skb(sk, size + dev->hard_header_len+15, 0, &err); + skb = sock_alloc_send_skb(sk, size + dev->hard_header_len+15, 1, &err); if (skb == 0) return 0; @@ -1545,7 +1545,7 @@ payload_len = len + sizeof(ra); full_len = sizeof(struct ipv6hdr) + payload_len; - skb = sock_alloc_send_skb(sk, dev->hard_header_len + full_len + 15, 0, &err); + skb = sock_alloc_send_skb(sk, dev->hard_header_len + full_len + 15, 1, &err); if (skb == NULL) return; diff -urN linux-2.5.70-bk19/net/ipv6/ndisc.c linux-2.5.71/net/ipv6/ndisc.c --- linux-2.5.70-bk19/net/ipv6/ndisc.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/ipv6/ndisc.c 2003-06-14 13:53:27.000000000 -0700 @@ -1487,6 +1487,9 @@ void ndisc_cleanup(void) { +#ifdef CONFIG_SYSCTL + neigh_sysctl_unregister(&nd_tbl.parms); +#endif neigh_table_clear(&nd_tbl); sock_release(ndisc_socket); ndisc_socket = NULL; /* For safety. */ diff -urN linux-2.5.70-bk19/net/ipv6/reassembly.c linux-2.5.71/net/ipv6/reassembly.c --- linux-2.5.70-bk19/net/ipv6/reassembly.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/ipv6/reassembly.c 2003-06-14 13:53:27.000000000 -0700 @@ -596,10 +596,8 @@ BUG_TRAP(FRAG6_CB(head)->offset == 0); /* Unfragmented part is taken from the first segment. */ - payload_len = (head->data - head->nh.raw) - sizeof(struct ipv6hdr) + fq->len; - nhoff = head->h.raw - head->nh.raw; - - if (payload_len > 65535 + 8) + payload_len = (head->data - head->nh.raw) - sizeof(struct ipv6hdr) + fq->len - sizeof(struct frag_hdr); + if (payload_len > 65535) goto out_oversize; /* Head of list must not be cloned. */ @@ -633,9 +631,10 @@ * header in order to calculate ICV correctly. */ nhoff = fq->nhoffset; head->nh.raw[nhoff] = head->h.raw[0]; - memmove(head->head+8, head->head, (head->data-head->head)-8); - head->mac.raw += 8; - head->nh.raw += 8; + memmove(head->head + sizeof(struct frag_hdr), head->head, + (head->data - head->head) - sizeof(struct frag_hdr)); + head->mac.raw += sizeof(struct frag_hdr); + head->nh.raw += sizeof(struct frag_hdr); skb_shinfo(head)->frag_list = head->next; head->h.raw = head->data; diff -urN linux-2.5.70-bk19/net/ipv6/sit.c linux-2.5.71/net/ipv6/sit.c --- linux-2.5.70-bk19/net/ipv6/sit.c 2003-05-26 18:00:58.000000000 -0700 +++ linux-2.5.71/net/ipv6/sit.c 2003-06-14 13:53:27.000000000 -0700 @@ -61,16 +61,9 @@ static int ipip6_fb_tunnel_init(struct net_device *dev); static int ipip6_tunnel_init(struct net_device *dev); +static void ipip6_tunnel_setup(struct net_device *dev); -static struct net_device ipip6_fb_tunnel_dev = { - .name = "sit0", - .init = ipip6_fb_tunnel_init -}; - -static struct ip_tunnel ipip6_fb_tunnel = { - .dev = &ipip6_fb_tunnel_dev, - .parms = { .name = "sit0" } -}; +static struct net_device *ipip6_fb_tunnel_dev; static struct ip_tunnel *tunnels_r_l[HASH_SIZE]; static struct ip_tunnel *tunnels_r[HASH_SIZE]; @@ -154,6 +147,7 @@ struct net_device *dev; unsigned h = 0; int prio = 0; + char name[IFNAMSIZ]; if (remote) { prio |= 2; @@ -168,54 +162,47 @@ return t; } if (!create) - return NULL; - - dev = kmalloc(sizeof(*dev) + sizeof(*t), GFP_KERNEL); - if (dev == NULL) - return NULL; + goto failed; - memset(dev, 0, sizeof(*dev) + sizeof(*t)); - dev->priv = (void*)(dev+1); - nt = (struct ip_tunnel*)dev->priv; - nt->dev = dev; - dev->init = ipip6_tunnel_init; - memcpy(&nt->parms, parms, sizeof(*parms)); - nt->parms.name[IFNAMSIZ-1] = '\0'; - strcpy(dev->name, nt->parms.name); - if (dev->name[0] == 0) { + if (parms->name[0]) + strlcpy(name, parms->name, IFNAMSIZ); + else { int i; for (i=1; i<100; i++) { - sprintf(dev->name, "sit%d", i); - if (__dev_get_by_name(dev->name) == NULL) + sprintf(name, "sit%d", i); + if (__dev_get_by_name(name) == NULL) break; } if (i==100) goto failed; - memcpy(nt->parms.name, dev->name, IFNAMSIZ); } - SET_MODULE_OWNER(dev); - if (register_netdevice(dev) < 0) + + dev = alloc_netdev(sizeof(*t), name, ipip6_tunnel_setup); + if (dev == NULL) + return NULL; + + nt = dev->priv; + dev->init = ipip6_tunnel_init; + nt->parms = *parms; + + if (register_netdevice(dev) < 0) { + kfree(dev); goto failed; + } dev_hold(dev); + ipip6_tunnel_link(nt); /* Do not decrement MOD_USE_COUNT here. */ return nt; failed: - kfree(dev); return NULL; } -static void ipip6_tunnel_destructor(struct net_device *dev) -{ - if (dev != &ipip6_fb_tunnel_dev) - kfree(dev); -} - static void ipip6_tunnel_uninit(struct net_device *dev) { - if (dev == &ipip6_fb_tunnel_dev) { + if (dev == ipip6_fb_tunnel_dev) { write_lock_bh(&ipip6_lock); tunnels_wc[0] = NULL; write_unlock_bh(&ipip6_lock); @@ -621,7 +608,7 @@ switch (cmd) { case SIOCGETTUNNEL: t = NULL; - if (dev == &ipip6_fb_tunnel_dev) { + if (dev == ipip6_fb_tunnel_dev) { if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { err = -EFAULT; break; @@ -654,8 +641,7 @@ t = ipip6_tunnel_locate(&p, cmd == SIOCADDTUNNEL); - if (dev != &ipip6_fb_tunnel_dev && cmd == SIOCCHGTUNNEL && - t != &ipip6_fb_tunnel) { + if (dev != ipip6_fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { if (t != NULL) { if (t->dev != dev) { err = -EEXIST; @@ -695,7 +681,7 @@ if (!capable(CAP_NET_ADMIN)) goto done; - if (dev == &ipip6_fb_tunnel_dev) { + if (dev == ipip6_fb_tunnel_dev) { err = -EFAULT; if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) goto done; @@ -703,7 +689,7 @@ if ((t = ipip6_tunnel_locate(&p, 0)) == NULL) goto done; err = -EPERM; - if (t == &ipip6_fb_tunnel) + if (t == ipip6_fb_tunnel_dev->priv) goto done; dev = t->dev; } @@ -731,12 +717,11 @@ return 0; } -static void ipip6_tunnel_init_gen(struct net_device *dev) +static void ipip6_tunnel_setup(struct net_device *dev) { - struct ip_tunnel *t = (struct ip_tunnel*)dev->priv; - - dev->destructor = ipip6_tunnel_destructor; + SET_MODULE_OWNER(dev); dev->uninit = ipip6_tunnel_uninit; + dev->destructor = (void (*)(struct net_device *))kfree; dev->hard_start_xmit = ipip6_tunnel_xmit; dev->get_stats = ipip6_tunnel_get_stats; dev->do_ioctl = ipip6_tunnel_ioctl; @@ -748,8 +733,6 @@ dev->flags = IFF_NOARP; dev->iflink = 0; dev->addr_len = 4; - memcpy(dev->dev_addr, &t->parms.iph.saddr, 4); - memcpy(dev->broadcast, &t->parms.iph.daddr, 4); } static int ipip6_tunnel_init(struct net_device *dev) @@ -760,8 +743,9 @@ tunnel = (struct ip_tunnel*)dev->priv; iph = &tunnel->parms.iph; - - ipip6_tunnel_init_gen(dev); + tunnel->dev = dev; + memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); + memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); if (iph->daddr) { struct flowi fl = { .nl_u = { .ip4_u = @@ -793,18 +777,16 @@ int __init ipip6_fb_tunnel_init(struct net_device *dev) { - struct iphdr *iph; + struct ip_tunnel *tunnel = dev->priv; + struct iphdr *iph = &tunnel->parms.iph; - ipip6_tunnel_init_gen(dev); - - iph = &ipip6_fb_tunnel.parms.iph; iph->version = 4; iph->protocol = IPPROTO_IPV6; iph->ihl = 5; iph->ttl = 64; dev_hold(dev); - tunnels_wc[0] = &ipip6_fb_tunnel; + tunnels_wc[0] = tunnel; return 0; } @@ -817,12 +799,14 @@ void sit_cleanup(void) { inet_del_protocol(&sit_protocol, IPPROTO_IPV6); - unregister_netdev(&ipip6_fb_tunnel_dev); + unregister_netdev(ipip6_fb_tunnel_dev); } #endif int __init sit_init(void) { + int err; + printk(KERN_INFO "IPv6 over IPv4 tunneling driver\n"); if (inet_add_protocol(&sit_protocol, IPPROTO_IPV6) < 0) { @@ -830,9 +814,22 @@ return -EAGAIN; } - ipip6_fb_tunnel_dev.priv = (void*)&ipip6_fb_tunnel; - strcpy(ipip6_fb_tunnel_dev.name, ipip6_fb_tunnel.parms.name); - SET_MODULE_OWNER(&ipip6_fb_tunnel_dev); - register_netdev(&ipip6_fb_tunnel_dev); - return 0; + ipip6_fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", + ipip6_tunnel_setup); + if (!ipip6_fb_tunnel_dev) { + err = -ENOMEM; + goto fail; + } + + ipip6_fb_tunnel_dev->init = ipip6_fb_tunnel_init; + + if ((err = register_netdev(ipip6_fb_tunnel_dev))) + goto fail; + + out: + return err; + fail: + inet_del_protocol(&sit_protocol, IPPROTO_IPV6); + kfree(ipip6_fb_tunnel_dev); + goto out; } diff -urN linux-2.5.70-bk19/net/ipv6/udp.c linux-2.5.71/net/ipv6/udp.c --- linux-2.5.70-bk19/net/ipv6/udp.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/ipv6/udp.c 2003-06-14 13:53:27.000000000 -0700 @@ -584,7 +584,7 @@ for (; s; s = s->sk_next) { struct inet_opt *inet = inet_sk(s); - if (inet->num == num && sk->sk_family == PF_INET6) { + if (inet->num == num && s->sk_family == PF_INET6) { struct ipv6_pinfo *np = inet6_sk(s); if (inet->dport) { if (inet->dport != rmt_port) diff -urN linux-2.5.70-bk19/net/ipv6/xfrm6_policy.c linux-2.5.71/net/ipv6/xfrm6_policy.c --- linux-2.5.70-bk19/net/ipv6/xfrm6_policy.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/ipv6/xfrm6_policy.c 2003-06-14 13:53:27.000000000 -0700 @@ -177,6 +177,7 @@ struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); u8 nexthdr = skb->nh.ipv6h->nexthdr; + memset(fl, 0, sizeof(struct flowi)); ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr); ipv6_addr_copy(&fl->fl6_src, &hdr->saddr); diff -urN linux-2.5.70-bk19/net/llc/llc_proc.c linux-2.5.71/net/llc/llc_proc.c --- linux-2.5.70-bk19/net/llc/llc_proc.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/llc/llc_proc.c 2003-06-14 13:53:27.000000000 -0700 @@ -183,7 +183,7 @@ timer_pending(&llc->pf_cycle_timer.timer), timer_pending(&llc->rej_sent_timer.timer), timer_pending(&llc->busy_state_timer.timer), - !!sk->sk_backlog.tail, sock_owned_by_user(sk)); + !!sk->sk_backlog.tail, !!sock_owned_by_user(sk)); out: return 0; } diff -urN linux-2.5.70-bk19/net/netsyms.c linux-2.5.71/net/netsyms.c --- linux-2.5.70-bk19/net/netsyms.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/netsyms.c 2003-06-14 13:53:27.000000000 -0700 @@ -190,6 +190,7 @@ #endif #ifdef CONFIG_SYSCTL EXPORT_SYMBOL(neigh_sysctl_register); +EXPORT_SYMBOL(neigh_sysctl_unregister); #endif EXPORT_SYMBOL(pneigh_lookup); EXPORT_SYMBOL(pneigh_enqueue); diff -urN linux-2.5.70-bk19/net/sctp/associola.c linux-2.5.71/net/sctp/associola.c --- linux-2.5.70-bk19/net/sctp/associola.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/sctp/associola.c 2003-06-14 13:53:27.000000000 -0700 @@ -96,7 +96,6 @@ int gfp) { struct sctp_opt *sp; - struct sctp_protocol *proto = sctp_get_protocol(); int i; /* Retrieve the SCTP per socket area. */ @@ -129,26 +128,26 @@ asoc->state_timestamp = jiffies; /* Set things that have constant value. */ - asoc->cookie_life.tv_sec = sctp_proto.valid_cookie_life / HZ; - asoc->cookie_life.tv_usec = (sctp_proto.valid_cookie_life % HZ) * + asoc->cookie_life.tv_sec = sctp_valid_cookie_life / HZ; + asoc->cookie_life.tv_usec = (sctp_valid_cookie_life % HZ) * 1000000L / HZ; asoc->pmtu = 0; asoc->frag_point = 0; /* Initialize the default association max_retrans and RTO values. */ - asoc->max_retrans = proto->max_retrans_association; - asoc->rto_initial = proto->rto_initial; - asoc->rto_max = proto->rto_max; - asoc->rto_min = proto->rto_min; + asoc->max_retrans = sctp_max_retrans_association; + asoc->rto_initial = sctp_rto_initial; + asoc->rto_max = sctp_rto_max; + asoc->rto_min = sctp_rto_min; - asoc->overall_error_threshold = 0; + asoc->overall_error_threshold = asoc->max_retrans; asoc->overall_error_count = 0; /* Initialize the maximum mumber of new data packets that can be sent * in a burst. */ - asoc->max_burst = proto->max_burst; + asoc->max_burst = sctp_max_burst; /* Copy things from the endpoint. */ for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) { @@ -277,6 +276,12 @@ asoc->autoclose = sp->autoclose; + asoc->default_stream = sp->default_stream; + asoc->default_ppid = sp->default_ppid; + asoc->default_flags = sp->default_flags; + asoc->default_context = sp->default_context; + asoc->default_timetolive = sp->default_timetolive; + return asoc; fail_init: @@ -478,16 +483,8 @@ peer->partial_bytes_acked = 0; peer->flight_size = 0; - peer->error_threshold = peer->max_retrans; - /* Update the overall error threshold value of the association - * taking the new peer's error threshold into account. - */ - asoc->overall_error_threshold = - min(asoc->overall_error_threshold + peer->error_threshold, - asoc->max_retrans); - /* By default, enable heartbeat for peer address. */ peer->hb_allowed = 1; @@ -550,12 +547,12 @@ /* Record the transition on the transport. */ switch (command) { case SCTP_TRANSPORT_UP: - transport->active = 1; + transport->active = SCTP_ACTIVE; spc_state = ADDRESS_AVAILABLE; break; case SCTP_TRANSPORT_DOWN: - transport->active = 0; + transport->active = SCTP_INACTIVE; spc_state = ADDRESS_UNREACHABLE; break; diff -urN linux-2.5.70-bk19/net/sctp/bind_addr.c linux-2.5.71/net/sctp/bind_addr.c --- linux-2.5.70-bk19/net/sctp/bind_addr.c 2003-05-26 18:00:56.000000000 -0700 +++ linux-2.5.71/net/sctp/bind_addr.c 2003-06-14 13:53:27.000000000 -0700 @@ -329,12 +329,10 @@ union sctp_addr *addr, sctp_scope_t scope, int gfp, int flags) { - struct sctp_protocol *proto = sctp_get_protocol(); int error = 0; if (sctp_is_any(addr)) { - error = sctp_copy_local_addr_list(proto, dest, scope, - gfp, flags); + error = sctp_copy_local_addr_list(dest, scope, gfp, flags); } else if (sctp_in_scope(addr, scope)) { /* Now that the address is in scope, check to see if * the address type is supported by local sock as diff -urN linux-2.5.70-bk19/net/sctp/input.c linux-2.5.71/net/sctp/input.c --- linux-2.5.70-bk19/net/sctp/input.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/sctp/input.c 2003-06-14 13:53:27.000000000 -0700 @@ -503,9 +503,10 @@ goto discard; if (SCTP_CID_ERROR == ch->type) { - err = (sctp_errhdr_t *)(ch + sizeof(sctp_chunkhdr_t)); - if (SCTP_ERROR_STALE_COOKIE == err->cause) - goto discard; + sctp_walk_errors(err, ch) { + if (SCTP_ERROR_STALE_COOKIE == err->cause) + goto discard; + } } ch = (sctp_chunkhdr_t *) ch_end; @@ -522,12 +523,12 @@ { struct sctp_ep_common **epp; struct sctp_ep_common *epb; - sctp_hashbucket_t *head; + struct sctp_hashbucket *head; epb = &ep->base; epb->hashent = sctp_ep_hashfn(epb->bind_addr.port); - head = &sctp_proto.ep_hashbucket[epb->hashent]; + head = &sctp_ep_hashbucket[epb->hashent]; sctp_write_lock(&head->lock); epp = &head->chain; @@ -550,14 +551,14 @@ /* Remove endpoint from the hash table. */ void __sctp_unhash_endpoint(struct sctp_endpoint *ep) { - sctp_hashbucket_t *head; + struct sctp_hashbucket *head; struct sctp_ep_common *epb; epb = &ep->base; epb->hashent = sctp_ep_hashfn(epb->bind_addr.port); - head = &sctp_proto.ep_hashbucket[epb->hashent]; + head = &sctp_ep_hashbucket[epb->hashent]; sctp_write_lock(&head->lock); @@ -582,13 +583,13 @@ /* Look up an endpoint. */ struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr) { - sctp_hashbucket_t *head; + struct sctp_hashbucket *head; struct sctp_ep_common *epb; struct sctp_endpoint *ep; int hash; hash = sctp_ep_hashfn(laddr->v4.sin_port); - head = &sctp_proto.ep_hashbucket[hash]; + head = &sctp_ep_hashbucket[hash]; read_lock(&head->lock); for (epb = head->chain; epb; epb = epb->next) { ep = sctp_ep(epb); @@ -619,14 +620,14 @@ { struct sctp_ep_common **epp; struct sctp_ep_common *epb; - sctp_hashbucket_t *head; + struct sctp_hashbucket *head; epb = &asoc->base; /* Calculate which chain this entry will belong to. */ epb->hashent = sctp_assoc_hashfn(epb->bind_addr.port, asoc->peer.port); - head = &sctp_proto.assoc_hashbucket[epb->hashent]; + head = &sctp_assoc_hashbucket[epb->hashent]; sctp_write_lock(&head->lock); epp = &head->chain; @@ -649,7 +650,7 @@ /* Remove association from the hash table. */ void __sctp_unhash_established(struct sctp_association *asoc) { - sctp_hashbucket_t *head; + struct sctp_hashbucket *head; struct sctp_ep_common *epb; epb = &asoc->base; @@ -657,7 +658,7 @@ epb->hashent = sctp_assoc_hashfn(epb->bind_addr.port, asoc->peer.port); - head = &sctp_proto.assoc_hashbucket[epb->hashent]; + head = &sctp_assoc_hashbucket[epb->hashent]; sctp_write_lock(&head->lock); @@ -677,7 +678,7 @@ const union sctp_addr *peer, struct sctp_transport **pt) { - sctp_hashbucket_t *head; + struct sctp_hashbucket *head; struct sctp_ep_common *epb; struct sctp_association *asoc; struct sctp_transport *transport; @@ -687,7 +688,7 @@ * have wildcards anyways. */ hash = sctp_assoc_hashfn(local->v4.sin_port, peer->v4.sin_port); - head = &sctp_proto.assoc_hashbucket[hash]; + head = &sctp_assoc_hashbucket[hash]; read_lock(&head->lock); for (epb = head->chain; epb; epb = epb->next) { asoc = sctp_assoc(epb); @@ -766,6 +767,7 @@ sctp_chunkhdr_t *ch; union sctp_params params; sctp_init_chunk_t *init; + struct sctp_transport *transport; ch = (sctp_chunkhdr_t *) skb->data; @@ -805,7 +807,7 @@ continue; sctp_param2sockaddr(paddr, params.addr, ntohs(sh->source), 0); - asoc = __sctp_lookup_association(laddr, paddr, transportp); + asoc = __sctp_lookup_association(laddr, paddr, &transport); if (asoc) return asoc; } diff -urN linux-2.5.70-bk19/net/sctp/ipv6.c linux-2.5.71/net/sctp/ipv6.c --- linux-2.5.70-bk19/net/sctp/ipv6.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/sctp/ipv6.c 2003-06-14 13:53:28.000000000 -0700 @@ -61,6 +61,7 @@ #include #include #include +#include #include #include @@ -578,6 +579,13 @@ return *((__u32 *)(skb->nh.ipv6h)) & htonl(1<<20); } +/* Dump the v6 addr to the seq file. */ +static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) +{ + seq_printf(seq, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", + NIP6(addr->v6.sin6_addr)); +} + /* Initialize a PF_INET6 socket msg_name. */ static void sctp_inet6_msgname(char *msgname, int *addr_len) { @@ -840,6 +848,7 @@ .available = sctp_v6_available, .skb_iif = sctp_v6_skb_iif, .is_ce = sctp_v6_is_ce, + .seq_dump_addr = sctp_v6_seq_dump_addr, .net_header_len = sizeof(struct ipv6hdr), .sockaddr_len = sizeof(struct sockaddr_in6), .sa_family = AF_INET6, diff -urN linux-2.5.70-bk19/net/sctp/objcnt.c linux-2.5.71/net/sctp/objcnt.c --- linux-2.5.70-bk19/net/sctp/objcnt.c 2003-05-26 18:00:21.000000000 -0700 +++ linux-2.5.71/net/sctp/objcnt.c 2003-06-14 13:53:28.000000000 -0700 @@ -53,6 +53,7 @@ SCTP_DBG_OBJCNT(transport); SCTP_DBG_OBJCNT(assoc); SCTP_DBG_OBJCNT(bind_addr); +SCTP_DBG_OBJCNT(bind_bucket); SCTP_DBG_OBJCNT(chunk); SCTP_DBG_OBJCNT(addr); SCTP_DBG_OBJCNT(ssnmap); @@ -68,6 +69,7 @@ SCTP_DBG_OBJCNT_ENTRY(transport), SCTP_DBG_OBJCNT_ENTRY(chunk), SCTP_DBG_OBJCNT_ENTRY(bind_addr), + SCTP_DBG_OBJCNT_ENTRY(bind_bucket), SCTP_DBG_OBJCNT_ENTRY(addr), SCTP_DBG_OBJCNT_ENTRY(ssnmap), SCTP_DBG_OBJCNT_ENTRY(datamsg), diff -urN linux-2.5.70-bk19/net/sctp/proc.c linux-2.5.71/net/sctp/proc.c --- linux-2.5.70-bk19/net/sctp/proc.c 2003-05-26 18:00:38.000000000 -0700 +++ linux-2.5.71/net/sctp/proc.c 2003-06-14 13:53:28.000000000 -0700 @@ -128,3 +128,162 @@ { remove_proc_entry("snmp", proc_net_sctp); } + +/* Dump local addresses of an association/endpoint. */ +static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_common *epb) +{ + struct list_head *pos; + struct sockaddr_storage_list *laddr; + union sctp_addr *addr; + struct sctp_af *af; + + list_for_each(pos, &epb->bind_addr.address_list) { + laddr = list_entry(pos, struct sockaddr_storage_list, list); + addr = (union sctp_addr *)&laddr->a; + af = sctp_get_af_specific(addr->sa.sa_family); + af->seq_dump_addr(seq, addr); + } +} + +/* Dump remote addresses of an association. */ +static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_association *assoc) +{ + struct list_head *pos; + struct sctp_transport *transport; + union sctp_addr *addr; + struct sctp_af *af; + + list_for_each(pos, &assoc->peer.transport_addr_list) { + transport = list_entry(pos, struct sctp_transport, transports); + addr = (union sctp_addr *)&transport->ipaddr; + af = sctp_get_af_specific(addr->sa.sa_family); + af->seq_dump_addr(seq, addr); + } +} + +/* Display sctp endpoints (/proc/net/sctp/eps). */ +static int sctp_eps_seq_show(struct seq_file *seq, void *v) +{ + struct sctp_hashbucket *head; + struct sctp_ep_common *epb; + struct sctp_endpoint *ep; + struct sock *sk; + int hash; + + seq_printf(seq, " ENDPT SOCK STY SST HBKT LPORT LADDRS\n"); + for (hash = 0; hash < sctp_ep_hashsize; hash++) { + head = &sctp_ep_hashbucket[hash]; + read_lock(&head->lock); + for (epb = head->chain; epb; epb = epb->next) { + ep = sctp_ep(epb); + sk = epb->sk; + seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d ", ep, sk, + sctp_sk(sk)->type, sk->sk_state, hash, + epb->bind_addr.port); + sctp_seq_dump_local_addrs(seq, epb); + seq_printf(seq, "\n"); + } + read_unlock(&head->lock); + } + + return 0; +} + +/* Initialize the seq file operations for 'eps' object. */ +static int sctp_eps_seq_open(struct inode *inode, struct file *file) +{ + return single_open(file, sctp_eps_seq_show, NULL); +} + +static struct file_operations sctp_eps_seq_fops = { + .open = sctp_eps_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* Set up the proc fs entry for 'eps' object. */ +int __init sctp_eps_proc_init(void) +{ + struct proc_dir_entry *p; + + p = create_proc_entry("eps", S_IRUGO, proc_net_sctp); + if (!p) + return -ENOMEM; + + p->proc_fops = &sctp_eps_seq_fops; + + return 0; +} + +/* Cleanup the proc fs entry for 'eps' object. */ +void sctp_eps_proc_exit(void) +{ + remove_proc_entry("eps", proc_net_sctp); +} + +/* Display sctp associations (/proc/net/sctp/assocs). */ +static int sctp_assocs_seq_show(struct seq_file *seq, void *v) +{ + struct sctp_hashbucket *head; + struct sctp_ep_common *epb; + struct sctp_association *assoc; + struct sock *sk; + int hash; + + seq_printf(seq, " ASSOC SOCK STY SST ST HBKT LPORT RPORT " + "LADDRS <-> RADDRS\n"); + for (hash = 0; hash < sctp_assoc_hashsize; hash++) { + head = &sctp_assoc_hashbucket[hash]; + read_lock(&head->lock); + for (epb = head->chain; epb; epb = epb->next) { + assoc = sctp_assoc(epb); + sk = epb->sk; + seq_printf(seq, + "%8p %8p %-3d %-3d %-2d %-4d %-5d %-5d ", + assoc, sk, sctp_sk(sk)->type, sk->sk_state, + assoc->state, hash, epb->bind_addr.port, + assoc->peer.port); + sctp_seq_dump_local_addrs(seq, epb); + seq_printf(seq, "<-> "); + sctp_seq_dump_remote_addrs(seq, assoc); + seq_printf(seq, "\n"); + } + read_unlock(&head->lock); + } + + return 0; +} + +/* Initialize the seq file operations for 'assocs' object. */ +static int sctp_assocs_seq_open(struct inode *inode, struct file *file) +{ + return single_open(file, sctp_assocs_seq_show, NULL); +} + +static struct file_operations sctp_assocs_seq_fops = { + .open = sctp_assocs_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +/* Set up the proc fs entry for 'assocs' object. */ +int __init sctp_assocs_proc_init(void) +{ + struct proc_dir_entry *p; + + p = create_proc_entry("assocs", S_IRUGO, proc_net_sctp); + if (!p) + return -ENOMEM; + + p->proc_fops = &sctp_assocs_seq_fops; + + return 0; +} + +/* Cleanup the proc fs entry for 'assocs' object. */ +void sctp_assocs_proc_exit(void) +{ + remove_proc_entry("assocs", proc_net_sctp); +} diff -urN linux-2.5.70-bk19/net/sctp/protocol.c linux-2.5.71/net/sctp/protocol.c --- linux-2.5.70-bk19/net/sctp/protocol.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/sctp/protocol.c 2003-06-14 13:53:28.000000000 -0700 @@ -1,7 +1,7 @@ /* SCTP kernel reference Implementation * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. - * Copyright (c) 2001-2002 International Business Machines, Corp. + * Copyright (c) 2001-2003 International Business Machines, Corp. * Copyright (c) 2001 Intel Corp. * Copyright (c) 2001 Nokia, Inc. * Copyright (c) 2001 La Monte H.P. Yarroll @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -59,7 +60,7 @@ #include /* Global data structures. */ -struct sctp_protocol sctp_proto; +struct sctp_globals sctp_globals; struct proc_dir_entry *proc_net_sctp; DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics); @@ -74,10 +75,17 @@ static struct sctp_af *sctp_af_v4_specific; static struct sctp_af *sctp_af_v6_specific; +kmem_cache_t *sctp_chunk_cachep; +kmem_cache_t *sctp_bucket_cachep; + extern struct net_proto_family inet_family_ops; extern int sctp_snmp_proc_init(void); extern int sctp_snmp_proc_exit(void); +extern int sctp_eps_proc_init(void); +extern int sctp_eps_proc_exit(void); +extern int sctp_assocs_proc_init(void); +extern int sctp_assocs_proc_exit(void); /* Return the address of the control sock. */ struct sock *sctp_get_ctl_sock(void) @@ -88,8 +96,6 @@ /* Set up the proc fs entry for the SCTP protocol. */ __init int sctp_proc_init(void) { - int rc = 0; - if (!proc_net_sctp) { struct proc_dir_entry *ent; ent = proc_mkdir("net/sctp", 0); @@ -97,20 +103,31 @@ ent->owner = THIS_MODULE; proc_net_sctp = ent; } else - rc = -ENOMEM; + goto out_nomem; } if (sctp_snmp_proc_init()) - rc = -ENOMEM; + goto out_nomem; + if (sctp_eps_proc_init()) + goto out_nomem; + if (sctp_assocs_proc_init()) + goto out_nomem; + + return 0; - return rc; +out_nomem: + return -ENOMEM; } -/* Clean up the proc fs entry for the SCTP protocol. */ +/* Clean up the proc fs entry for the SCTP protocol. + * Note: Do not make this __exit as it is used in the init error + * path. + */ void sctp_proc_exit(void) { - sctp_snmp_proc_exit(); + sctp_eps_proc_exit(); + sctp_assocs_proc_exit(); if (proc_net_sctp) { proc_net_sctp = NULL; @@ -153,7 +170,7 @@ /* Extract our IP addresses from the system and stash them in the * protocol structure. */ -static void __sctp_get_local_addr_list(struct sctp_protocol *proto) +static void __sctp_get_local_addr_list(void) { struct net_device *dev; struct list_head *pos; @@ -161,30 +178,30 @@ read_lock(&dev_base_lock); for (dev = dev_base; dev; dev = dev->next) { - list_for_each(pos, &proto->address_families) { + __list_for_each(pos, &sctp_address_families) { af = list_entry(pos, struct sctp_af, list); - af->copy_addrlist(&proto->local_addr_list, dev); + af->copy_addrlist(&sctp_local_addr_list, dev); } } read_unlock(&dev_base_lock); } -static void sctp_get_local_addr_list(struct sctp_protocol *proto) +static void sctp_get_local_addr_list(void) { unsigned long flags; - sctp_spin_lock_irqsave(&sctp_proto.local_addr_lock, flags); - __sctp_get_local_addr_list(&sctp_proto); - sctp_spin_unlock_irqrestore(&sctp_proto.local_addr_lock, flags); + sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); + __sctp_get_local_addr_list(); + sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags); } /* Free the existing local addresses. */ -static void __sctp_free_local_addr_list(struct sctp_protocol *proto) +static void __sctp_free_local_addr_list(void) { struct sockaddr_storage_list *addr; struct list_head *pos, *temp; - list_for_each_safe(pos, temp, &proto->local_addr_list) { + list_for_each_safe(pos, temp, &sctp_local_addr_list) { addr = list_entry(pos, struct sockaddr_storage_list, list); list_del(pos); kfree(addr); @@ -192,18 +209,17 @@ } /* Free the existing local addresses. */ -static void sctp_free_local_addr_list(struct sctp_protocol *proto) +static void sctp_free_local_addr_list(void) { unsigned long flags; - sctp_spin_lock_irqsave(&proto->local_addr_lock, flags); - __sctp_free_local_addr_list(proto); - sctp_spin_unlock_irqrestore(&proto->local_addr_lock, flags); + sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); + __sctp_free_local_addr_list(); + sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags); } /* Copy the local addresses which are valid for 'scope' into 'bp'. */ -int sctp_copy_local_addr_list(struct sctp_protocol *proto, - struct sctp_bind_addr *bp, sctp_scope_t scope, +int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope, int gfp, int copy_flags) { struct sockaddr_storage_list *addr; @@ -211,8 +227,8 @@ struct list_head *pos; unsigned long flags; - sctp_spin_lock_irqsave(&proto->local_addr_lock, flags); - list_for_each(pos, &proto->local_addr_list) { + sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); + list_for_each(pos, &sctp_local_addr_list) { addr = list_entry(pos, struct sockaddr_storage_list, list); if (sctp_in_scope(&addr->a, scope)) { /* Now that the address is in scope, check to see if @@ -233,7 +249,7 @@ } end_copy: - sctp_spin_unlock_irqrestore(&proto->local_addr_lock, flags); + sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags); return error; } @@ -564,6 +580,12 @@ return newsk; } +/* Dump the v4 addr to the seq file. */ +static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) +{ + seq_printf(seq, "%d.%d.%d.%d ", NIPQUAD(addr->v4.sin_addr)); +} + /* Event handler for inet address addition/deletion events. * Basically, whenever there is an event, we re-build our local address list. */ @@ -572,10 +594,10 @@ { unsigned long flags; - sctp_spin_lock_irqsave(&sctp_proto.local_addr_lock, flags); - __sctp_free_local_addr_list(&sctp_proto); - __sctp_get_local_addr_list(&sctp_proto); - sctp_spin_unlock_irqrestore(&sctp_proto.local_addr_lock, flags); + sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags); + __sctp_free_local_addr_list(); + __sctp_get_local_addr_list(); + sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags); return NOTIFY_DONE; } @@ -626,7 +648,7 @@ } INIT_LIST_HEAD(&af->list); - list_add_tail(&af->list, &sctp_proto.address_families); + list_add_tail(&af->list, &sctp_address_families); return 1; } @@ -839,6 +861,7 @@ .scope = sctp_v4_scope, .skb_iif = sctp_v4_skb_iif, .is_ce = sctp_v4_is_ce, + .seq_dump_addr = sctp_v4_seq_dump_addr, .net_header_len = sizeof(struct iphdr), .sockaddr_len = sizeof(struct sockaddr_in), .sa_family = AF_INET, @@ -914,6 +937,22 @@ inet_register_protosw(&sctp_seqpacket_protosw); inet_register_protosw(&sctp_stream_protosw); + /* Allocate a cache pools. */ + sctp_bucket_cachep = kmem_cache_create("sctp_bind_bucket", + sizeof(struct sctp_bind_bucket), + 0, SLAB_HWCACHE_ALIGN, + NULL, NULL); + + if (!sctp_bucket_cachep) + goto err_bucket_cachep; + + sctp_chunk_cachep = kmem_cache_create("sctp_chunk", + sizeof(struct sctp_chunk), + 0, SLAB_HWCACHE_ALIGN, + NULL, NULL); + if (!sctp_chunk_cachep) + goto err_chunk_cachep; + /* Allocate and initialise sctp mibs. */ status = init_sctp_mibs(); if (status) @@ -932,91 +971,91 @@ */ /* The following protocol parameters are RECOMMENDED: */ /* RTO.Initial - 3 seconds */ - sctp_proto.rto_initial = SCTP_RTO_INITIAL; + sctp_rto_initial = SCTP_RTO_INITIAL; /* RTO.Min - 1 second */ - sctp_proto.rto_min = SCTP_RTO_MIN; + sctp_rto_min = SCTP_RTO_MIN; /* RTO.Max - 60 seconds */ - sctp_proto.rto_max = SCTP_RTO_MAX; + sctp_rto_max = SCTP_RTO_MAX; /* RTO.Alpha - 1/8 */ - sctp_proto.rto_alpha = SCTP_RTO_ALPHA; + sctp_rto_alpha = SCTP_RTO_ALPHA; /* RTO.Beta - 1/4 */ - sctp_proto.rto_beta = SCTP_RTO_BETA; + sctp_rto_beta = SCTP_RTO_BETA; /* Valid.Cookie.Life - 60 seconds */ - sctp_proto.valid_cookie_life = 60 * HZ; + sctp_valid_cookie_life = 60 * HZ; /* Whether Cookie Preservative is enabled(1) or not(0) */ - sctp_proto.cookie_preserve_enable = 1; + sctp_cookie_preserve_enable = 1; /* Max.Burst - 4 */ - sctp_proto.max_burst = SCTP_MAX_BURST; + sctp_max_burst = SCTP_MAX_BURST; /* Association.Max.Retrans - 10 attempts * Path.Max.Retrans - 5 attempts (per destination address) * Max.Init.Retransmits - 8 attempts */ - sctp_proto.max_retrans_association = 10; - sctp_proto.max_retrans_path = 5; - sctp_proto.max_retrans_init = 8; + sctp_max_retrans_association = 10; + sctp_max_retrans_path = 5; + sctp_max_retrans_init = 8; /* HB.interval - 30 seconds */ - sctp_proto.hb_interval = 30 * HZ; + sctp_hb_interval = 30 * HZ; /* Implementation specific variables. */ /* Initialize default stream count setup information. */ - sctp_proto.max_instreams = SCTP_DEFAULT_INSTREAMS; - sctp_proto.max_outstreams = SCTP_DEFAULT_OUTSTREAMS; + sctp_max_instreams = SCTP_DEFAULT_INSTREAMS; + sctp_max_outstreams = SCTP_DEFAULT_OUTSTREAMS; /* Allocate and initialize the association hash table. */ - sctp_proto.assoc_hashsize = 4096; - sctp_proto.assoc_hashbucket = (sctp_hashbucket_t *) - kmalloc(4096 * sizeof(sctp_hashbucket_t), GFP_KERNEL); - if (!sctp_proto.assoc_hashbucket) { + sctp_assoc_hashsize = 4096; + sctp_assoc_hashbucket = (struct sctp_hashbucket *) + kmalloc(4096 * sizeof(struct sctp_hashbucket), GFP_KERNEL); + if (!sctp_assoc_hashbucket) { printk(KERN_ERR "SCTP: Failed association hash alloc.\n"); status = -ENOMEM; goto err_ahash_alloc; } - for (i = 0; i < sctp_proto.assoc_hashsize; i++) { - sctp_proto.assoc_hashbucket[i].lock = RW_LOCK_UNLOCKED; - sctp_proto.assoc_hashbucket[i].chain = NULL; + for (i = 0; i < sctp_assoc_hashsize; i++) { + sctp_assoc_hashbucket[i].lock = RW_LOCK_UNLOCKED; + sctp_assoc_hashbucket[i].chain = NULL; } /* Allocate and initialize the endpoint hash table. */ - sctp_proto.ep_hashsize = 64; - sctp_proto.ep_hashbucket = (sctp_hashbucket_t *) - kmalloc(64 * sizeof(sctp_hashbucket_t), GFP_KERNEL); - if (!sctp_proto.ep_hashbucket) { + sctp_ep_hashsize = 64; + sctp_ep_hashbucket = (struct sctp_hashbucket *) + kmalloc(64 * sizeof(struct sctp_hashbucket), GFP_KERNEL); + if (!sctp_ep_hashbucket) { printk(KERN_ERR "SCTP: Failed endpoint_hash alloc.\n"); status = -ENOMEM; goto err_ehash_alloc; } - for (i = 0; i < sctp_proto.ep_hashsize; i++) { - sctp_proto.ep_hashbucket[i].lock = RW_LOCK_UNLOCKED; - sctp_proto.ep_hashbucket[i].chain = NULL; + for (i = 0; i < sctp_ep_hashsize; i++) { + sctp_ep_hashbucket[i].lock = RW_LOCK_UNLOCKED; + sctp_ep_hashbucket[i].chain = NULL; } /* Allocate and initialize the SCTP port hash table. */ - sctp_proto.port_hashsize = 4096; - sctp_proto.port_hashtable = (sctp_bind_hashbucket_t *) - kmalloc(4096 * sizeof(sctp_bind_hashbucket_t), GFP_KERNEL); - if (!sctp_proto.port_hashtable) { + sctp_port_hashsize = 4096; + sctp_port_hashtable = (struct sctp_bind_hashbucket *) + kmalloc(4096 * sizeof(struct sctp_bind_hashbucket),GFP_KERNEL); + if (!sctp_port_hashtable) { printk(KERN_ERR "SCTP: Failed bind hash alloc."); status = -ENOMEM; goto err_bhash_alloc; } - sctp_proto.port_alloc_lock = SPIN_LOCK_UNLOCKED; - sctp_proto.port_rover = sysctl_local_port_range[0] - 1; - for (i = 0; i < sctp_proto.port_hashsize; i++) { - sctp_proto.port_hashtable[i].lock = SPIN_LOCK_UNLOCKED; - sctp_proto.port_hashtable[i].chain = NULL; + sctp_port_alloc_lock = SPIN_LOCK_UNLOCKED; + sctp_port_rover = sysctl_local_port_range[0] - 1; + for (i = 0; i < sctp_port_hashsize; i++) { + sctp_port_hashtable[i].lock = SPIN_LOCK_UNLOCKED; + sctp_port_hashtable[i].chain = NULL; } sctp_sysctl_register(); - INIT_LIST_HEAD(&sctp_proto.address_families); + INIT_LIST_HEAD(&sctp_address_families); sctp_register_af(&sctp_ipv4_specific); status = sctp_v6_init(); @@ -1031,13 +1070,13 @@ } /* Initialize the local address list. */ - INIT_LIST_HEAD(&sctp_proto.local_addr_list); - sctp_proto.local_addr_lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&sctp_local_addr_list); + sctp_local_addr_lock = SPIN_LOCK_UNLOCKED; /* Register notifier for inet address additions/deletions. */ register_inetaddr_notifier(&sctp_inetaddr_notifier); - sctp_get_local_addr_list(&sctp_proto); + sctp_get_local_addr_list(); __unsafe(THIS_MODULE); return 0; @@ -1047,16 +1086,20 @@ err_v6_init: sctp_sysctl_unregister(); list_del(&sctp_ipv4_specific.list); - kfree(sctp_proto.port_hashtable); + kfree(sctp_port_hashtable); err_bhash_alloc: - kfree(sctp_proto.ep_hashbucket); + kfree(sctp_ep_hashbucket); err_ehash_alloc: - kfree(sctp_proto.assoc_hashbucket); + kfree(sctp_assoc_hashbucket); err_ahash_alloc: sctp_dbg_objcnt_exit(); sctp_proc_exit(); cleanup_sctp_mibs(); err_init_mibs: + kmem_cache_destroy(sctp_chunk_cachep); +err_chunk_cachep: + kmem_cache_destroy(sctp_bucket_cachep); +err_bucket_cachep: inet_del_protocol(&sctp_protocol, IPPROTO_SCTP); inet_unregister_protosw(&sctp_seqpacket_protosw); inet_unregister_protosw(&sctp_stream_protosw); @@ -1074,7 +1117,7 @@ unregister_inetaddr_notifier(&sctp_inetaddr_notifier); /* Free the local address list. */ - sctp_free_local_addr_list(&sctp_proto); + sctp_free_local_addr_list(); /* Free the control endpoint. */ sock_release(sctp_ctl_socket); @@ -1083,9 +1126,12 @@ sctp_sysctl_unregister(); list_del(&sctp_ipv4_specific.list); - kfree(sctp_proto.assoc_hashbucket); - kfree(sctp_proto.ep_hashbucket); - kfree(sctp_proto.port_hashtable); + kfree(sctp_assoc_hashbucket); + kfree(sctp_ep_hashbucket); + kfree(sctp_port_hashtable); + + kmem_cache_destroy(sctp_chunk_cachep); + kmem_cache_destroy(sctp_bucket_cachep); sctp_dbg_objcnt_exit(); sctp_proc_exit(); diff -urN linux-2.5.70-bk19/net/sctp/sm_make_chunk.c linux-2.5.71/net/sctp/sm_make_chunk.c --- linux-2.5.70-bk19/net/sctp/sm_make_chunk.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/sctp/sm_make_chunk.c 2003-06-14 13:53:28.000000000 -0700 @@ -68,6 +68,8 @@ #include #include +extern kmem_cache_t *sctp_chunk_cachep; + /* What was the inbound interface for this chunk? */ int sctp_chunk_iif(const struct sctp_chunk *chunk) { @@ -874,7 +876,7 @@ const void *payload, const size_t paylen) { struct sctp_chunk *retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT, - 0, paylen); + 0, paylen); if (!retval) goto nodata; @@ -976,7 +978,9 @@ const struct sctp_association *asoc, struct sock *sk) { - struct sctp_chunk *retval = t_new(struct sctp_chunk, GFP_ATOMIC); + struct sctp_chunk *retval; + + retval = kmem_cache_alloc(sctp_chunk_cachep, SLAB_ATOMIC); if (!retval) goto nodata; @@ -1048,7 +1052,7 @@ * arguments, reserving enough space for a 'paylen' byte payload. */ struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc, - __u8 type, __u8 flags, int paylen) + __u8 type, __u8 flags, int paylen) { struct sctp_chunk *retval; sctp_chunkhdr_t *chunk_hdr; @@ -1075,13 +1079,12 @@ } retval->chunk_hdr = chunk_hdr; - retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(sctp_chunkhdr_t); + retval->chunk_end = ((__u8 *)chunk_hdr) + sizeof(struct sctp_chunkhdr); /* Set the skb to the belonging sock for accounting. */ skb->sk = sk; return retval; - nodata: return NULL; } @@ -1090,12 +1093,11 @@ /* Release the memory occupied by a chunk. */ static void sctp_chunk_destroy(struct sctp_chunk *chunk) { - /* Free the chunk skb data and the SCTP_chunk stub itself. */ dev_kfree_skb(chunk->skb); - kfree(chunk); SCTP_DBG_OBJCNT_DEC(chunk); + kmem_cache_free(sctp_chunk_cachep, chunk); } /* Possibly, free the chunk. */ @@ -1728,8 +1730,12 @@ sctp_walk_params(param, peer_init, init_hdr.params) { - if (!sctp_verify_param(asoc, param, cid, chunk, errp)) - return 0; + if (!sctp_verify_param(asoc, param, cid, chunk, errp)) { + if (SCTP_PARAM_HOST_NAME_ADDRESS == param.p->type) + return 0; + else + return 1; + } } /* for (loop through all parameters) */ @@ -1907,7 +1913,7 @@ break; case SCTP_PARAM_COOKIE_PRESERVATIVE: - if (!sctp_proto.cookie_preserve_enable) + if (!sctp_cookie_preserve_enable) break; stale = ntohl(param.life->lifespan_increment); diff -urN linux-2.5.70-bk19/net/sctp/sm_sideeffect.c linux-2.5.71/net/sctp/sm_sideeffect.c --- linux-2.5.70-bk19/net/sctp/sm_sideeffect.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/sctp/sm_sideeffect.c 2003-06-14 13:53:28.000000000 -0700 @@ -415,7 +415,8 @@ struct sctp_ulpevent *event; event = sctp_ulpevent_make_assoc_change(asoc,0, SCTP_CANT_STR_ASSOC, - 0, 0, 0, GFP_ATOMIC); + (__u16)error, 0, 0, + GFP_ATOMIC); if (event) sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, diff -urN linux-2.5.70-bk19/net/sctp/sm_statefuns.c linux-2.5.71/net/sctp/sm_statefuns.c --- linux-2.5.70-bk19/net/sctp/sm_statefuns.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/sctp/sm_statefuns.c 2003-06-14 13:53:28.000000000 -0700 @@ -738,7 +738,7 @@ { struct sctp_transport *transport = (struct sctp_transport *) arg; - if (asoc->overall_error_count >= asoc->overall_error_threshold) { + if (asoc->overall_error_count > asoc->overall_error_threshold) { /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(SCTP_ERROR_NO_ERROR)); @@ -1238,7 +1238,6 @@ * parameter type. */ sctp_addto_chunk(repl, len, unk_param); - sctp_chunk_free(err_chunk); } sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); @@ -1788,24 +1787,17 @@ struct sctp_chunk *chunk = arg; sctp_errhdr_t *err; - err = (sctp_errhdr_t *)(chunk->skb->data); - - /* If we have gotten too many failures, give up. */ - if (1 + asoc->counters[SCTP_COUNTER_INIT_ERROR] > - asoc->max_init_attempts) { - /* INIT_FAILED will issue an ulpevent. */ - sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, - SCTP_U32(err->cause)); - return SCTP_DISPOSITION_DELETE_TCB; - } - /* Process the error here */ - switch (err->cause) { - case SCTP_ERROR_STALE_COOKIE: - return sctp_sf_do_5_2_6_stale(ep, asoc, type, arg, commands); - default: - return sctp_sf_pdiscard(ep, asoc, type, arg, commands); + /* FUTURE FIXME: When PR-SCTP related and other optional + * parms are emitted, this will have to change to handle multiple + * errors. + */ + sctp_walk_errors(err, chunk->chunk_hdr) { + if (SCTP_ERROR_STALE_COOKIE == err->cause) + return sctp_sf_do_5_2_6_stale(ep, asoc, type, + arg, commands); } + return sctp_sf_pdiscard(ep, asoc, type, arg, commands); } /* @@ -2067,6 +2059,7 @@ struct sctp_chunk *chunk = arg; sctp_shutdownhdr_t *sdh; sctp_disposition_t disposition; + struct sctp_ulpevent *ev; /* Convert the elaborate header. */ sdh = (sctp_shutdownhdr_t *)chunk->skb->data; @@ -2097,12 +2090,28 @@ arg, commands); } + if (SCTP_DISPOSITION_NOMEM == disposition) + goto out; + /* - verify, by checking the Cumulative TSN Ack field of the * chunk, that all its outstanding DATA chunks have been * received by the SHUTDOWN sender. */ sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN, SCTP_U32(chunk->subh.shutdown_hdr->cum_tsn_ack)); + + /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT + * When a peer sends a SHUTDOWN, SCTP delivers this notification to + * inform the application that it should cease sending data. + */ + ev = sctp_ulpevent_make_shutdown_event(asoc, 0, GFP_ATOMIC); + if (!ev) { + disposition = SCTP_DISPOSITION_NOMEM; + goto out; + } + sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev)); + +out: return disposition; } @@ -2334,7 +2343,7 @@ if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) { /* Do real work as sideffect. */ - sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE, + sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE, SCTP_U32(tsn)); } } @@ -2375,7 +2384,7 @@ * PMTU. In cases, such as loopback, this might be a rather * large spill over. */ - if (!asoc->rwnd || asoc->rwnd_over || + if (!asoc->rwnd || asoc->rwnd_over || (datalen > asoc->rwnd + asoc->frag_point)) { /* If this is the next TSN, consider reneging to make @@ -2594,7 +2603,7 @@ if (af && af->is_ce(chunk->skb) && asoc->peer.ecn_capable) { /* Do real work as sideffect. */ - sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE, + sctp_add_cmd_sf(commands, SCTP_CMD_ECN_CE, SCTP_U32(tsn)); } } @@ -2740,6 +2749,9 @@ /* Pull the SACK chunk from the data buffer */ sackh = sctp_sm_pull_sack(chunk); + /* Was this a bogus SACK? */ + if (!sackh) + return sctp_sf_pdiscard(ep, asoc, type, arg, commands); chunk->subh.sack_hdr = sackh; ctsn = ntohl(sackh->cum_tsn_ack); @@ -4406,22 +4418,27 @@ ********************************************************************/ /* Pull the SACK chunk based on the SACK header. */ -sctp_sackhdr_t *sctp_sm_pull_sack(struct sctp_chunk *chunk) +struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk) { - sctp_sackhdr_t *sack; + struct sctp_sackhdr *sack; + unsigned int len; __u16 num_blocks; __u16 num_dup_tsns; - /* FIXME: Protect ourselves from reading too far into + /* Protect ourselves from reading too far into * the skb from a bogus sender. */ - sack = (sctp_sackhdr_t *) chunk->skb->data; - skb_pull(chunk->skb, sizeof(sctp_sackhdr_t)); + sack = (struct sctp_sackhdr *) chunk->skb->data; num_blocks = ntohs(sack->num_gap_ack_blocks); num_dup_tsns = ntohs(sack->num_dup_tsns); + len = sizeof(struct sctp_sackhdr); + len = (num_blocks + num_dup_tsns) * sizeof(__u32); + if (len > chunk->skb->len) + return NULL; + + skb_pull(chunk->skb, len); - skb_pull(chunk->skb, (num_blocks + num_dup_tsns) * sizeof(__u32)); return sack; } diff -urN linux-2.5.70-bk19/net/sctp/sm_statetable.c linux-2.5.71/net/sctp/sm_statetable.c --- linux-2.5.70-bk19/net/sctp/sm_statetable.c 2003-05-26 18:01:00.000000000 -0700 +++ linux-2.5.71/net/sctp/sm_statetable.c 2003-06-14 13:53:28.000000000 -0700 @@ -436,51 +436,6 @@ TYPE_SCTP_SHUTDOWN_COMPLETE, }; /* state_fn_t chunk_event_table[][] */ -static sctp_sm_table_entry_t -chunk_event_table_asconf[SCTP_STATE_NUM_STATES] = { - /* SCTP_STATE_EMPTY */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_CLOSED */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_COOKIE_WAIT */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_COOKIE_ECHOED */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_ESTABLISHED */ - {.fn = sctp_sf_discard_chunk, - .name = "sctp_sf_discard_chunk (will be sctp_addip_do_asconf)"}, - /* SCTP_STATE_SHUTDOWN_PENDING */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_SHUTDOWN_SENT */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_SHUTDOWN_RECEIVED */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_SHUTDOWN_ACK_SENT */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, -}; /* chunk asconf */ - -static sctp_sm_table_entry_t -chunk_event_table_asconf_ack[SCTP_STATE_NUM_STATES] = { - /* SCTP_STATE_EMPTY */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_CLOSED */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_COOKIE_WAIT */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_COOKIE_ECHOED */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_ESTABLISHED */ - {.fn = sctp_sf_discard_chunk, - .name = "sctp_sf_discard_chunk (will be sctp_addip_do_asconf_ack)"}, - /* SCTP_STATE_SHUTDOWN_PENDING */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_SHUTDOWN_SENT */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_SHUTDOWN_RECEIVED */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, - /* SCTP_STATE_SHUTDOWN_ACK_SENT */ - {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, -}; /* chunk asconf_ack */ static sctp_sm_table_entry_t chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { @@ -783,7 +738,7 @@ /* SCTP_STATE_ESTABLISHED */ \ {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ /* SCTP_STATE_SHUTDOWN_PENDING */ \ - {.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \ + {.fn = sctp_sf_t5_timer_expire, .name = "sctp_sf_t5_timer_expire"}, \ /* SCTP_STATE_SHUTDOWN_SENT */ \ {.fn = sctp_sf_t5_timer_expire, .name = "sctp_sf_t5_timer_expire"}, \ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ @@ -877,13 +832,5 @@ return &chunk_event_table[cid][state]; } - switch (cid) { - case SCTP_CID_ASCONF: - return &chunk_event_table_asconf[state]; - - case SCTP_CID_ASCONF_ACK: - return &chunk_event_table_asconf_ack[state]; - default: - return &chunk_event_table_unknown[state]; - } + return &chunk_event_table_unknown[state]; } diff -urN linux-2.5.70-bk19/net/sctp/socket.c linux-2.5.71/net/sctp/socket.c --- linux-2.5.70-bk19/net/sctp/socket.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/sctp/socket.c 2003-06-14 13:53:28.000000000 -0700 @@ -99,6 +99,8 @@ struct sctp_association *, sctp_socket_type_t); static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG; +extern kmem_cache_t *sctp_bucket_cachep; + /* Look up the association by its id. If this is not a UDP-style * socket, the ID field is always ignored. */ @@ -106,10 +108,16 @@ { struct sctp_association *asoc = NULL; - /* If this is not a UDP-style socket, assoc id should be - * ignored. - */ + /* If this is not a UDP-style socket, assoc id should be ignored. */ if (!sctp_style(sk, UDP)) { + /* Return NULL if the socket state is not ESTABLISHED. It + * could be a TCP-style listening socket or a socket which + * hasn't yet called connect() to establish an association. + */ + if (!sctp_sstate(sk, ESTABLISHED)) + return NULL; + + /* Get the first and the only association from the list. */ if (!list_empty(&sctp_sk(sk)->ep->asocs)) asoc = list_entry(sctp_sk(sk)->ep->asocs.next, struct sctp_association, asocs); @@ -132,6 +140,30 @@ return asoc; } +/* Look up the transport from an address and an assoc id. If both address and + * id are specified, the associations matching the address and the id should be + * the same. + */ +struct sctp_transport *sctp_addr_id2transport(struct sock *sk, + struct sockaddr_storage *addr, + sctp_assoc_t id) +{ + struct sctp_association *addr_asoc = NULL, *id_asoc = NULL; + struct sctp_transport *transport; + + addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep, + (union sctp_addr *)addr, + &transport); + if (!addr_asoc) + return NULL; + + id_asoc = sctp_id2assoc(sk, id); + if (id_asoc && (id_asoc != addr_asoc)) + return NULL; + + return transport; +} + /* API 3.1.2 bind() - UDP Style Syntax * The syntax of bind() is, * @@ -710,7 +742,7 @@ struct sctp_association *asoc; struct list_head *pos, *temp; - printk("sctp_close(sk: 0x%p, timeout:%ld)\n", sk, timeout); + SCTP_DEBUG_PRINTK("sctp_close(sk: 0x%p, timeout:%ld)\n", sk, timeout); sctp_lock_sock(sk); sk->sk_shutdown = SHUTDOWN_MASK; @@ -1061,11 +1093,11 @@ /* If the user didn't specify SNDRCVINFO, make up one with * some defaults. */ - default_sinfo.sinfo_stream = asoc->defaults.stream; - default_sinfo.sinfo_flags = asoc->defaults.flags; - default_sinfo.sinfo_ppid = asoc->defaults.ppid; - default_sinfo.sinfo_context = asoc->defaults.context; - default_sinfo.sinfo_timetolive = asoc->defaults.timetolive; + default_sinfo.sinfo_stream = asoc->default_stream; + default_sinfo.sinfo_flags = asoc->default_flags; + default_sinfo.sinfo_ppid = asoc->default_ppid; + default_sinfo.sinfo_context = asoc->default_context; + default_sinfo.sinfo_timetolive = asoc->default_timetolive; default_sinfo.sinfo_assoc_id = sctp_assoc2id(asoc); sinfo = &default_sinfo; } @@ -1333,6 +1365,13 @@ return err; } +/* 7.1.12 Enable/Disable message fragmentation (SCTP_DISABLE_FRAGMENTS) + * + * This option is a on/off flag. If enabled no SCTP message + * fragmentation will be performed. Instead if a message being sent + * exceeds the current PMTU size, the message will NOT be sent and + * instead a error will be indicated to the user. + */ static int sctp_setsockopt_disable_fragments(struct sock *sk, char *optval, int optlen) { @@ -1359,6 +1398,17 @@ return 0; } +/* 7.1.8 Automatic Close of associations (SCTP_AUTOCLOSE) + * + * This socket option is applicable to the UDP-style socket only. When + * set it will cause associations that are idle for more than the + * specified number of seconds to automatically close. An association + * being idle is defined an association that has NOT sent or received + * user data. The special value of '0' indicates that no automatic + * close of any associations should be performed. The option expects an + * integer defining the number of seconds of idle time before an + * association is closed. + */ static int sctp_setsockopt_autoclose(struct sock *sk, char *optval, int optlen) { @@ -1376,12 +1426,41 @@ return 0; } +/* 7.1.13 Peer Address Parameters (SCTP_SET_PEER_ADDR_PARAMS) + * + * Applications can enable or disable heartbeats for any peer address of + * an association, modify an address's heartbeat interval, force a + * heartbeat to be sent immediately, and adjust the address's maximum + * number of retransmissions sent before an address is considered + * unreachable. The following structure is used to access and modify an + * address's parameters: + * + * struct sctp_paddrparams { + * sctp_assoc_t spp_assoc_id; + * struct sockaddr_storage spp_address; + * uint32_t spp_hbinterval; + * uint16_t spp_pathmaxrxt; + * }; + * + * spp_assoc_id - (UDP style socket) This is filled in the application, + * and identifies the association for this query. + * spp_address - This specifies which address is of interest. + * spp_hbinterval - This contains the value of the heartbeat interval, + * in milliseconds. A value of 0, when modifying the + * parameter, specifies that the heartbeat on this + * address should be disabled. A value of UINT32_MAX + * (4294967295), when modifying the parameter, + * specifies that a heartbeat should be sent + * immediately to the peer address, and the current + * interval should remain unchanged. + * spp_pathmaxrxt - This contains the maximum number of + * retransmissions before this address shall be + * considered unreachable. + */ static int sctp_setsockopt_peer_addr_params(struct sock *sk, char *optval, int optlen) { struct sctp_paddrparams params; - struct sctp_association *asoc; - union sctp_addr *addr; struct sctp_transport *trans; int error; @@ -1390,15 +1469,10 @@ if (copy_from_user(¶ms, optval, optlen)) return -EFAULT; - asoc = sctp_id2assoc(sk, params.spp_assoc_id); - if (!asoc) - return -EINVAL; - - addr = (union sctp_addr *) &(params.spp_address); - - trans = sctp_assoc_lookup_paddr(asoc, addr); + trans = sctp_addr_id2transport(sk, ¶ms.spp_address, + params.spp_assoc_id); if (!trans) - return -ENOENT; + return -EINVAL; /* Applications can enable or disable heartbeats for any peer address * of an association, modify an address's heartbeat interval, force a @@ -1412,7 +1486,7 @@ * and the current interval should remain unchanged. */ if (0xffffffff == params.spp_hbinterval) { - error = sctp_primitive_REQUESTHEARTBEAT (asoc, trans); + error = sctp_primitive_REQUESTHEARTBEAT (trans->asoc, trans); if (error) return error; } else { @@ -1435,6 +1509,17 @@ return 0; } +/* 7.1.3 Initialization Parameters (SCTP_INITMSG) + * + * Applications can specify protocol parameters for the default association + * initialization. The option name argument to setsockopt() and getsockopt() + * is SCTP_INITMSG. + * + * Setting initialization parameters is effective only on an unconnected + * socket (for UDP-style sockets only future associations are effected + * by the change). With TCP-style sockets, this option is inherited by + * sockets derived from a listener socket. + */ static int sctp_setsockopt_initmsg(struct sock *sk, char *optval, int optlen) { if (optlen != sizeof(struct sctp_initmsg)) @@ -1445,7 +1530,7 @@ } /* - * 7.1.15 Set default send parameters (SET_DEFAULT_SEND_PARAM) + * 7.1.14 Set default send parameters (SET_DEFAULT_SEND_PARAM) * * Applications that wish to use the sendto() system call may wish to * specify a default set of parameters that would normally be supplied @@ -1463,6 +1548,7 @@ { struct sctp_sndrcvinfo info; struct sctp_association *asoc; + struct sctp_opt *sp = sctp_sk(sk); if (optlen != sizeof(struct sctp_sndrcvinfo)) return -EINVAL; @@ -1470,14 +1556,23 @@ return -EFAULT; asoc = sctp_id2assoc(sk, info.sinfo_assoc_id); - if (!asoc) + if (!asoc && info.sinfo_assoc_id && sctp_style(sk, UDP)) return -EINVAL; - asoc->defaults.stream = info.sinfo_stream; - asoc->defaults.flags = info.sinfo_flags; - asoc->defaults.ppid = info.sinfo_ppid; - asoc->defaults.context = info.sinfo_context; - asoc->defaults.timetolive = info.sinfo_timetolive; + if (asoc) { + asoc->default_stream = info.sinfo_stream; + asoc->default_flags = info.sinfo_flags; + asoc->default_ppid = info.sinfo_ppid; + asoc->default_context = info.sinfo_context; + asoc->default_timetolive = info.sinfo_timetolive; + } else { + sp->default_stream = info.sinfo_stream; + sp->default_flags = info.sinfo_flags; + sp->default_ppid = info.sinfo_ppid; + sp->default_context = info.sinfo_context; + sp->default_timetolive = info.sinfo_timetolive; + } + return 0; } @@ -1490,8 +1585,6 @@ static int sctp_setsockopt_peer_prim(struct sock *sk, char *optval, int optlen) { struct sctp_setpeerprim prim; - struct sctp_association *asoc; - union sctp_addr *addr; struct sctp_transport *trans; if (optlen != sizeof(struct sctp_setpeerprim)) @@ -1500,18 +1593,11 @@ if (copy_from_user(&prim, optval, sizeof(struct sctp_setpeerprim))) return -EFAULT; - asoc = sctp_id2assoc(sk, prim.sspp_assoc_id); - if (!asoc) - return -EINVAL; - - /* Find the requested address. */ - addr = (union sctp_addr *) &(prim.sspp_addr); - - trans = sctp_assoc_lookup_paddr(asoc, addr); + trans = sctp_addr_id2transport(sk, &prim.sspp_addr, prim.sspp_assoc_id); if (!trans) - return -ENOENT; + return -EINVAL; - sctp_assoc_set_primary(asoc, trans); + sctp_assoc_set_primary(trans->asoc, trans); return 0; } @@ -1906,13 +1992,10 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) { struct sctp_endpoint *ep; - struct sctp_protocol *proto; struct sctp_opt *sp; SCTP_DEBUG_PRINTK("sctp_init_sock(sk: %p)\n", sk); - proto = sctp_get_protocol(); - sp = sctp_sk(sk); /* Initialize the SCTP per socket area. */ @@ -1933,23 +2016,26 @@ */ sp->default_stream = 0; sp->default_ppid = 0; + sp->default_flags = 0; + sp->default_context = 0; + sp->default_timetolive = 0; /* Initialize default setup parameters. These parameters * can be modified with the SCTP_INITMSG socket option or * overridden by the SCTP_INIT CMSG. */ - sp->initmsg.sinit_num_ostreams = proto->max_outstreams; - sp->initmsg.sinit_max_instreams = proto->max_instreams; - sp->initmsg.sinit_max_attempts = proto->max_retrans_init; - sp->initmsg.sinit_max_init_timeo = proto->rto_max / HZ; + sp->initmsg.sinit_num_ostreams = sctp_max_outstreams; + sp->initmsg.sinit_max_instreams = sctp_max_instreams; + sp->initmsg.sinit_max_attempts = sctp_max_retrans_init; + sp->initmsg.sinit_max_init_timeo = sctp_rto_max / HZ; /* Initialize default RTO related parameters. These parameters can * be modified for with the SCTP_RTOINFO socket option. * FIXME: These are not used yet. */ - sp->rtoinfo.srto_initial = proto->rto_initial; - sp->rtoinfo.srto_max = proto->rto_max; - sp->rtoinfo.srto_min = proto->rto_min; + sp->rtoinfo.srto_initial = sctp_rto_initial; + sp->rtoinfo.srto_max = sctp_rto_max; + sp->rtoinfo.srto_min = sctp_rto_min; /* Initialize default event subscriptions. * the struct sock is initialized to zero, so only @@ -1964,8 +2050,8 @@ /* Default Peer Address Parameters. These defaults can * be modified via SCTP_SET_PEER_ADDR_PARAMS */ - sp->paddrparam.spp_hbinterval = proto->hb_interval / HZ; - sp->paddrparam.spp_pathmaxrxt = proto->max_retrans_path; + sp->paddrparam.spp_hbinterval = sctp_hb_interval / HZ; + sp->paddrparam.spp_pathmaxrxt = sctp_max_retrans_path; /* If enabled no SCTP message fragmentation will be performed. * Configure through SCTP_DISABLE_FRAGMENTS socket option. @@ -2131,6 +2217,64 @@ return (retval); } + +/* 7.2.2 Peer Address Information (SCTP_GET_PEER_ADDR_INFO) + * + * Applications can retrieve information about a specific peer address + * of an association, including its reachability state, congestion + * window, and retransmission timer values. This information is + * read-only. + */ +static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len, + char *optval, int *optlen) +{ + struct sctp_paddrinfo pinfo; + struct sctp_transport *transport; + int retval = 0; + + if (len != sizeof(pinfo)) { + retval = -EINVAL; + goto out; + } + + if (copy_from_user(&pinfo, optval, sizeof(pinfo))) { + retval = -EFAULT; + goto out; + } + + transport = sctp_addr_id2transport(sk, &pinfo.spinfo_address, + pinfo.spinfo_assoc_id); + if (!transport) + return -EINVAL; + + pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc); + pinfo.spinfo_state = transport->active; + pinfo.spinfo_cwnd = transport->cwnd; + pinfo.spinfo_srtt = transport->srtt; + pinfo.spinfo_rto = transport->rto; + pinfo.spinfo_mtu = transport->pmtu; + + if (put_user(len, optlen)) { + retval = -EFAULT; + goto out; + } + + if (copy_to_user(optval, &pinfo, len)) { + retval = -EFAULT; + goto out; + } + +out: + return (retval); +} + +/* 7.1.12 Enable/Disable message fragmentation (SCTP_DISABLE_FRAGMENTS) + * + * This option is a on/off flag. If enabled no SCTP message + * fragmentation will be performed. Instead if a message being sent + * exceeds the current PMTU size, the message will NOT be sent and + * instead a error will be indicated to the user. + */ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len, char *optval, int *optlen) { @@ -2148,6 +2292,11 @@ return 0; } +/* 7.1.15 Set notification and ancillary events (SCTP_SET_EVENTS) + * + * This socket option is used to specify various notifications and + * ancillary data the user wishes to receive. + */ static int sctp_getsockopt_set_events(struct sock *sk, int len, char *optval, int *optlen) { if (len != sizeof(struct sctp_event_subscribe)) @@ -2157,6 +2306,17 @@ return 0; } +/* 7.1.8 Automatic Close of associations (SCTP_AUTOCLOSE) + * + * This socket option is applicable to the UDP-style socket only. When + * set it will cause associations that are idle for more than the + * specified number of seconds to automatically close. An association + * being idle is defined an association that has NOT sent or received + * user data. The special value of '0' indicates that no automatic + * close of any associations should be performed. The option expects an + * integer defining the number of seconds of idle time before an + * association is closed. + */ static int sctp_getsockopt_autoclose(struct sock *sk, int len, char *optval, int *optlen) { /* Applicable to UDP-style socket only */ @@ -2240,12 +2400,41 @@ return retval; } +/* 7.1.13 Peer Address Parameters (SCTP_SET_PEER_ADDR_PARAMS) + * + * Applications can enable or disable heartbeats for any peer address of + * an association, modify an address's heartbeat interval, force a + * heartbeat to be sent immediately, and adjust the address's maximum + * number of retransmissions sent before an address is considered + * unreachable. The following structure is used to access and modify an + * address's parameters: + * + * struct sctp_paddrparams { + * sctp_assoc_t spp_assoc_id; + * struct sockaddr_storage spp_address; + * uint32_t spp_hbinterval; + * uint16_t spp_pathmaxrxt; + * }; + * + * spp_assoc_id - (UDP style socket) This is filled in the application, + * and identifies the association for this query. + * spp_address - This specifies which address is of interest. + * spp_hbinterval - This contains the value of the heartbeat interval, + * in milliseconds. A value of 0, when modifying the + * parameter, specifies that the heartbeat on this + * address should be disabled. A value of UINT32_MAX + * (4294967295), when modifying the parameter, + * specifies that a heartbeat should be sent + * immediately to the peer address, and the current + * interval should remain unchanged. + * spp_pathmaxrxt - This contains the maximum number of + * retransmissions before this address shall be + * considered unreachable. + */ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len, char *optval, int *optlen) { struct sctp_paddrparams params; - struct sctp_association *asoc; - union sctp_addr *addr; struct sctp_transport *trans; if (len != sizeof(struct sctp_paddrparams)) @@ -2253,15 +2442,10 @@ if (copy_from_user(¶ms, optval, *optlen)) return -EFAULT; - asoc = sctp_id2assoc(sk, params.spp_assoc_id); - if (!asoc) - return -EINVAL; - - addr = (union sctp_addr *) &(params.spp_address); - - trans = sctp_assoc_lookup_paddr(asoc, addr); + trans = sctp_addr_id2transport(sk, ¶ms.spp_address, + params.spp_assoc_id); if (!trans) - return -ENOENT; + return -EINVAL; /* The value of the heartbeat interval, in milliseconds. A value of 0, * when modifying the parameter, specifies that the heartbeat on this @@ -2286,6 +2470,17 @@ return 0; } +/* 7.1.3 Initialization Parameters (SCTP_INITMSG) + * + * Applications can specify protocol parameters for the default association + * initialization. The option name argument to setsockopt() and getsockopt() + * is SCTP_INITMSG. + * + * Setting initialization parameters is effective only on an unconnected + * socket (for UDP-style sockets only future associations are effected + * by the change). With TCP-style sockets, this option is inherited by + * sockets derived from a listener socket. + */ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char *optval, int *optlen) { if (len != sizeof(struct sctp_initmsg)) @@ -2491,7 +2686,7 @@ /* * - * 7.1.15 Set default send parameters (SET_DEFAULT_SEND_PARAM) + * 7.1.14 Set default send parameters (SET_DEFAULT_SEND_PARAM) * * Applications that wish to use the sendto() system call may wish to * specify a default set of parameters that would normally be supplied @@ -2511,6 +2706,7 @@ { struct sctp_sndrcvinfo info; struct sctp_association *asoc; + struct sctp_opt *sp = sctp_sk(sk); if (len != sizeof(struct sctp_sndrcvinfo)) return -EINVAL; @@ -2518,14 +2714,22 @@ return -EFAULT; asoc = sctp_id2assoc(sk, info.sinfo_assoc_id); - if (!asoc) + if (!asoc && info.sinfo_assoc_id && sctp_style(sk, UDP)) return -EINVAL; - info.sinfo_stream = asoc->defaults.stream; - info.sinfo_flags = asoc->defaults.flags; - info.sinfo_ppid = asoc->defaults.ppid; - info.sinfo_context = asoc->defaults.context; - info.sinfo_timetolive = asoc->defaults.timetolive; + if (asoc) { + info.sinfo_stream = asoc->default_stream; + info.sinfo_flags = asoc->default_flags; + info.sinfo_ppid = asoc->default_ppid; + info.sinfo_context = asoc->default_context; + info.sinfo_timetolive = asoc->default_timetolive; + } else { + info.sinfo_stream = sp->default_stream; + info.sinfo_flags = sp->default_flags; + info.sinfo_ppid = sp->default_ppid; + info.sinfo_context = sp->default_context; + info.sinfo_timetolive = sp->default_timetolive; + } if (copy_to_user(optval, &info, sizeof(struct sctp_sndrcvinfo))) return -EFAULT; @@ -2698,6 +2902,10 @@ case SCTP_MAXSEG: retval = sctp_getsockopt_maxseg(sk, len, optval, optlen); break; + case SCTP_GET_PEER_ADDR_INFO: + retval = sctp_getsockopt_peer_addr_info(sk, len, optval, + optlen); + break; default: retval = -ENOPROTOOPT; break; @@ -2721,7 +2929,7 @@ * * The port hash table (contained in the 'global' SCTP protocol storage * returned by struct sctp_protocol *sctp_get_protocol()). The hash - * table is an array of 4096 lists (sctp_bind_hashbucket_t). Each + * table is an array of 4096 lists (sctp_bind_hashbucket). Each * list (the list number is the port number hashed out, so as you * would expect from a hash function, all the ports in a given list have * such a number that hashes out to the same list number; you were @@ -2729,13 +2937,13 @@ * link to the socket (struct sock) that uses it, the port number and * a fastreuse flag (FIXME: NPI ipg). */ -static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, - unsigned short snum); +static struct sctp_bind_bucket *sctp_bucket_create( + struct sctp_bind_hashbucket *head, unsigned short snum); + static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) { - sctp_bind_hashbucket_t *head; /* hash list */ - sctp_bind_bucket_t *pp; /* hash list port iterator */ - struct sctp_protocol *sctp = sctp_get_protocol(); + struct sctp_bind_hashbucket *head; /* hash list */ + struct sctp_bind_bucket *pp; /* hash list port iterator */ unsigned short snum; int ret; @@ -2750,8 +2958,8 @@ if (snum == 0) { /* Search for an available port. * - * 'sctp->port_rover' was the last port assigned, so - * we start to search from 'sctp->port_rover + + * 'sctp_port_rover' was the last port assigned, so + * we start to search from 'sctp_port_rover + * 1'. What we do is first check if port 'rover' is * already in the hash table; if not, we use that; if * it is, we try next. @@ -2762,14 +2970,14 @@ int rover; int index; - sctp_spin_lock(&sctp->port_alloc_lock); - rover = sctp->port_rover; + sctp_spin_lock(&sctp_port_alloc_lock); + rover = sctp_port_rover; do { rover++; if ((rover < low) || (rover > high)) rover = low; index = sctp_phashfn(rover); - head = &sctp->port_hashtable[index]; + head = &sctp_port_hashtable[index]; sctp_spin_lock(&head->lock); for (pp = head->chain; pp; pp = pp->next) if (pp->port == rover) @@ -2778,8 +2986,8 @@ next: sctp_spin_unlock(&head->lock); } while (--remaining > 0); - sctp->port_rover = rover; - sctp_spin_unlock(&sctp->port_alloc_lock); + sctp_port_rover = rover; + sctp_spin_unlock(&sctp_port_alloc_lock); /* Exhausted local port range during search? */ ret = 1; @@ -2799,7 +3007,7 @@ * to the port number (snum) - we detect that with the * port iterator, pp being NULL. */ - head = &sctp->port_hashtable[sctp_phashfn(snum)]; + head = &sctp_port_hashtable[sctp_phashfn(snum)]; sctp_spin_lock(&head->lock); for (pp = head->chain; pp; pp = pp->next) { if (pp->port == snum) @@ -3105,12 +3313,13 @@ * 2nd Level Abstractions ********************************************************************/ -static sctp_bind_bucket_t *sctp_bucket_create(sctp_bind_hashbucket_t *head, unsigned short snum) +static struct sctp_bind_bucket *sctp_bucket_create( + struct sctp_bind_hashbucket *head, unsigned short snum) { - sctp_bind_bucket_t *pp; + struct sctp_bind_bucket *pp; - SCTP_DEBUG_PRINTK( "sctp_bucket_create() begins, snum=%d\n", snum); - pp = kmalloc(sizeof(sctp_bind_bucket_t), GFP_ATOMIC); + pp = kmem_cache_alloc(sctp_bucket_cachep, SLAB_ATOMIC); + SCTP_DBG_OBJCNT_INC(bind_bucket); if (pp) { pp->port = snum; pp->fastreuse = 0; @@ -3120,31 +3329,36 @@ head->chain = pp; pp->pprev = &head->chain; } - SCTP_DEBUG_PRINTK("sctp_bucket_create() ends, pp=%p\n", pp); return pp; } +/* Caller must hold hashbucket lock for this tb with local BH disabled */ +static void sctp_bucket_destroy(struct sctp_bind_bucket *pp) +{ + if (!pp->sk) { + if (pp->next) + pp->next->pprev = pp->pprev; + *(pp->pprev) = pp->next; + kmem_cache_free(sctp_bucket_cachep, pp); + SCTP_DBG_OBJCNT_DEC(bind_bucket); + } +} + /* FIXME: Comments! */ static __inline__ void __sctp_put_port(struct sock *sk) { - struct sctp_protocol *sctp_proto = sctp_get_protocol(); - sctp_bind_hashbucket_t *head = - &sctp_proto->port_hashtable[sctp_phashfn(inet_sk(sk)->num)]; - sctp_bind_bucket_t *pp; + struct sctp_bind_hashbucket *head = + &sctp_port_hashtable[sctp_phashfn(inet_sk(sk)->num)]; + struct sctp_bind_bucket *pp; sctp_spin_lock(&head->lock); - pp = (sctp_bind_bucket_t *)sk->sk_prev; + pp = (struct sctp_bind_bucket *)sk->sk_prev; if (sk->sk_bind_next) sk->sk_bind_next->sk_bind_pprev = sk->sk_bind_pprev; *(sk->sk_bind_pprev) = sk->sk_bind_next; sk->sk_prev = NULL; inet_sk(sk)->num = 0; - if (pp->sk) { - if (pp->next) - pp->next->pprev = pp->pprev; - *(pp->pprev) = pp->next; - kfree(pp); - } + sctp_bucket_destroy(pp); sctp_spin_unlock(&head->lock); } diff -urN linux-2.5.70-bk19/net/sctp/sysctl.c linux-2.5.71/net/sctp/sysctl.c --- linux-2.5.70-bk19/net/sctp/sysctl.c 2003-05-26 18:00:38.000000000 -0700 +++ linux-2.5.71/net/sctp/sysctl.c 2003-06-14 13:53:28.000000000 -0700 @@ -42,13 +42,11 @@ #include #include -extern struct sctp_protocol sctp_proto; - static ctl_table sctp_table[] = { { .ctl_name = NET_SCTP_RTO_INITIAL, .procname = "rto_initial", - .data = &sctp_proto.rto_initial, + .data = &sctp_rto_initial, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, @@ -57,7 +55,7 @@ { .ctl_name = NET_SCTP_RTO_MIN, .procname = "rto_min", - .data = &sctp_proto.rto_min, + .data = &sctp_rto_min, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, @@ -66,7 +64,7 @@ { .ctl_name = NET_SCTP_RTO_MAX, .procname = "rto_max", - .data = &sctp_proto.rto_max, + .data = &sctp_rto_max, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, @@ -75,7 +73,7 @@ { .ctl_name = NET_SCTP_VALID_COOKIE_LIFE, .procname = "valid_cookie_life", - .data = &sctp_proto.valid_cookie_life, + .data = &sctp_valid_cookie_life, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, @@ -84,7 +82,7 @@ { .ctl_name = NET_SCTP_MAX_BURST, .procname = "max_burst", - .data = &sctp_proto.max_burst, + .data = &sctp_max_burst, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec @@ -92,7 +90,7 @@ { .ctl_name = NET_SCTP_ASSOCIATION_MAX_RETRANS, .procname = "association_max_retrans", - .data = &sctp_proto.max_retrans_association, + .data = &sctp_max_retrans_association, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec @@ -100,7 +98,7 @@ { .ctl_name = NET_SCTP_PATH_MAX_RETRANS, .procname = "path_max_retrans", - .data = &sctp_proto.max_retrans_path, + .data = &sctp_max_retrans_path, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec @@ -108,7 +106,7 @@ { .ctl_name = NET_SCTP_MAX_INIT_RETRANSMITS, .procname = "max_init_retransmits", - .data = &sctp_proto.max_retrans_init, + .data = &sctp_max_retrans_init, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec @@ -116,7 +114,7 @@ { .ctl_name = NET_SCTP_HB_INTERVAL, .procname = "hb_interval", - .data = &sctp_proto.hb_interval, + .data = &sctp_hb_interval, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, @@ -125,7 +123,7 @@ { .ctl_name = NET_SCTP_PRESERVE_ENABLE, .procname = "cookie_preserve_enable", - .data = &sctp_proto.cookie_preserve_enable, + .data = &sctp_cookie_preserve_enable, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec_jiffies, @@ -134,7 +132,7 @@ { .ctl_name = NET_SCTP_RTO_ALPHA, .procname = "rto_alpha_exp_divisor", - .data = &sctp_proto.rto_alpha, + .data = &sctp_rto_alpha, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec @@ -142,7 +140,7 @@ { .ctl_name = NET_SCTP_RTO_BETA, .procname = "rto_beta_exp_divisor", - .data = &sctp_proto.rto_beta, + .data = &sctp_rto_beta, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec diff -urN linux-2.5.70-bk19/net/sctp/transport.c linux-2.5.71/net/sctp/transport.c --- linux-2.5.70-bk19/net/sctp/transport.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/sctp/transport.c 2003-06-14 13:53:28.000000000 -0700 @@ -82,8 +82,6 @@ const union sctp_addr *addr, int gfp) { - struct sctp_protocol *proto = sctp_get_protocol(); - /* Copy in the address. */ peer->ipaddr = *addr; peer->af_specific = sctp_get_af_specific(addr->sa.sa_family); @@ -99,7 +97,7 @@ * parameter 'RTO.Initial'. */ peer->rtt = 0; - peer->rto = proto->rto_initial; + peer->rto = sctp_rto_initial; peer->rttvar = 0; peer->srtt = 0; peer->rto_pending = 0; @@ -108,11 +106,11 @@ peer->last_time_used = jiffies; peer->last_time_ecne_reduced = jiffies; - peer->active = 1; + peer->active = SCTP_ACTIVE; peer->hb_allowed = 0; /* Initialize the default path max_retrans. */ - peer->max_retrans = proto->max_retrans_path; + peer->max_retrans = sctp_max_retrans_path; peer->error_threshold = 0; peer->error_count = 0; @@ -272,8 +270,6 @@ /* Update transport's RTO based on the newly calculated RTT. */ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) { - struct sctp_protocol *proto = sctp_get_protocol(); - /* Check for valid transport. */ SCTP_ASSERT(tp, "NULL transport", return); @@ -292,10 +288,10 @@ * For example, assuming the default value of RTO.Alpha of * 1/8, rto_alpha would be expressed as 3. */ - tp->rttvar = tp->rttvar - (tp->rttvar >> proto->rto_beta) - + ((abs(tp->srtt - rtt)) >> proto->rto_beta); - tp->srtt = tp->srtt - (tp->srtt >> proto->rto_alpha) - + (rtt >> proto->rto_alpha); + tp->rttvar = tp->rttvar - (tp->rttvar >> sctp_rto_beta) + + ((abs(tp->srtt - rtt)) >> sctp_rto_beta); + tp->srtt = tp->srtt - (tp->srtt >> sctp_rto_alpha) + + (rtt >> sctp_rto_alpha); } else { /* 6.3.1 C2) When the first RTT measurement R is made, set * SRTT <- R, RTTVAR <- R/2. diff -urN linux-2.5.70-bk19/net/xfrm/xfrm_policy.c linux-2.5.71/net/xfrm/xfrm_policy.c --- linux-2.5.70-bk19/net/xfrm/xfrm_policy.c 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/net/xfrm/xfrm_policy.c 2003-06-14 13:53:28.000000000 -0700 @@ -224,7 +224,7 @@ atomic_dec(&policy->refcnt); if (atomic_read(&policy->refcnt) > 1) - flow_cache_flush(policy); + flow_cache_flush(); xfrm_pol_put(policy); } diff -urN linux-2.5.70-bk19/scripts/Makefile.lib linux-2.5.71/scripts/Makefile.lib --- linux-2.5.70-bk19/scripts/Makefile.lib 2003-06-14 13:53:19.000000000 -0700 +++ linux-2.5.71/scripts/Makefile.lib 2003-06-14 13:53:28.000000000 -0700 @@ -227,24 +227,6 @@ cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1)) -# do_cmd is a shorthand used to support both compressed, verbose -# and silent output in a single line. -# Compared to cmd described avobe, do_cmd does no rely on any variables -# previously assigned a value. -# -# Usage $(call do_cmd,CMD $@,cmd_to_execute bla bla) -# Example: -# $(call do_cmd,CP $@,cp -b $< $@) -# make -s => nothing will be printed -# make KBUILD_VERBOSE=1 => cp -b path/to/src.file path/to/dest.file -# make KBUILD_VERBOSE=0 => CP path/to/dest.file -define do_cmd - @$(if $(filter quiet_,$(quiet)), echo ' $(1)' &&, - $(if $(filter silent_,$(quiet)),, - echo "$(2)" &&)) \ - $(2) -endef - # $(call descend,,) # Recursively call a sub-make in with target # Usage is deprecated, because make do not see this as an invocation of make.