diff -uNr linux-2.4.21/CHANGES linux-2.4.21-ben2/CHANGES --- linux-2.4.21/CHANGES 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/CHANGES 2003-06-27 15:41:25.000000000 +0200 @@ -0,0 +1,5 @@ + +2.4.21-ben2 : - Fixed a crashed during boot with radeonfb on some + configurations. + +2.4.21-ben1 : Never released on kernel.org, only rsync \ No newline at end of file diff -uNr linux-2.4.21/Documentation/Configure.help linux-2.4.21-ben2/Documentation/Configure.help --- linux-2.4.21/Documentation/Configure.help 2003-06-13 16:51:29.000000000 +0200 +++ linux-2.4.21-ben2/Documentation/Configure.help 2003-06-27 15:41:36.000000000 +0200 @@ -15972,6 +15972,24 @@ compile it as a module, say M here and read . +Apple Extended file system support (read-only) (EXPERIMENTAL) +CONFIG_HFSPLUS_FS + If you say Y here, you will be able to mount extended format + Macintosh-formatted hard drive partitions with read-only access. + Most of the UNIX related filesystem data saved by Mac OSX should + be readable. + + This file system is often called HFS+ and was introduced with + MacOS 8.1. It includes all Mac specific filesystem data such as + data forks and creator codes, but it also has several UNIX + style features such as file ownership and permissions. No Mac + specific data can currently be accessed with this driver. + + This file system is also available as a module ( = code which can + be inserted in and removed from the running kernel whenever you + want). The module is called hfsplus.o. If you want to compile it + as a module, say M here and read Documentation/modules.txt. + ROM file system support CONFIG_ROMFS_FS This is a very small read-only file system mainly intended for @@ -26565,6 +26583,29 @@ If unsure, say N. +CONFIG_CPU_FREQ + Clock scaling allows you to change the clock speed of CPUs on the + 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 + at + + If in doubt, say N. + +CONFIG_CPU_FREQ_24_API + This enables the /proc/sys/cpu/ sysctl interface for controlling + CPUFreq, as known from the 2.4.-kernel patches for CPUFreq. Note + that some drivers do not support this interface or offer less + functionality. + + If you say N here, you'll be able to control CPUFreq using the + new /proc/cpufreq interface. + + For details, take a look at linux/Documentation/cpufreq. + + If in doubt, say N. + NatSemi SCx200 support CONFIG_SCx200 This provides basic support for the National Semiconductor SCx200 @@ -26572,6 +26613,7 @@ If you don't know what to do here, say N. + This support is also available as a module. If compiled as a module, it will be called scx200.o. @@ -26580,8 +26622,10 @@ Enable the built-in watchdog timer support on the National Semiconductor SCx200 processors. + If compiled as a module, it will be called scx200_watchdog.o. + Flash device mapped with DOCCS on NatSemi SCx200 CONFIG_MTD_SCx200_DOCFLASH Enable support for a flash chip mapped using the DOCCS signal on a diff -uNr linux-2.4.21/Documentation/cpufreq linux-2.4.21-ben2/Documentation/cpufreq --- linux-2.4.21/Documentation/cpufreq 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/Documentation/cpufreq 2003-06-27 15:41:24.000000000 +0200 @@ -0,0 +1,361 @@ + CPU frequency and voltage scaling code in the Linux(TM) kernel + + + L i n u x C P U F r e q + + + + + Dominik Brodowski + David Kimdon + + + + Clock scaling allows you to change the clock speed of the CPUs on the + fly. This is a nice method to save battery power, because the lower + the clock speed, the less power the CPU consumes. + + + +Contents: +--------- +1. Supported architectures +2. User interface +2.1 /proc/cpufreq interface [2.6] +2.2. /proc/sys/cpu/ interface [2.4] +3. CPUFreq core and interfaces +3.1 General information +3.2 CPUFreq notifiers +3.3 CPUFreq architecture drivers +4. Mailing list and Links + + + +1. Supported architectures +========================== + +ARM: + ARM Integrator, SA 1100, SA1110 +-------------------------------- + This driver will be ported to new CPUFreq core soon, so + far it will not work. + + +AMD Elan: + SC400, SC410 +-------------------------------- + You need to specify the highest allowed CPU frequency as + a module parameter ("max_freq") or as boot parameter + ("elanfreq="). Else the available speed range will be + limited to the speed at which the CPU runs while this + module is loaded. + + +VIA Cyrix Longhaul: + VIA Samuel/CyrixIII, VIA Cyrix Samuel/C3, + VIA Cyrix Ezra, VIA Cyrix Ezra-T +-------------------------------- + If you do not want to scale the Front Side Bus or voltage, + pass the module parameter "dont_scale_fsb 1" or + "dont_scale_voltage 1". Additionally, it is advised that + you pass the current Front Side Bus speed (in MHz) to + this module as module parameter "current_fsb", e.g. + "current_fsb 133" for a Front Side Bus speed of 133 MHz. + + +Intel SpeedStep: + certain mobile Intel Pentium III (Coppermine), and all mobile + Intel Pentium III-M (Tualatin) and mobile Intel Pentium 4 P4-Ms. +-------------------------------- + Unfortunately only modern Intel ICH2-M and ICH3-M chipsets are + supported. + + +P4 CPU Clock Modulation: + Intel Pentium 4 Xeon processors +--------------------------------- + Note that you can only switch the speed of two logical CPUs at + once - but each phyiscal CPU may have different throttling levels. + + +PowerNow! K6: + mobile AMD K6-2+ / mobile K6-3+: +-------------------------------- + No known issues. + + +Transmeta Crusoe Longrun: + Transmeta Crusoe processors: +-------------------------------- + Does not work with the 2.4. /proc/sys/cpu/ interface. + + + +2. User Interface +================= + +2.1 /proc/cpufreq interface [2.6] +*********************************** + +Starting in the patches for kernel 2.5.33, CPUFreq uses a "policy" +interface /proc/cpufreq. + +When you "cat" this file, you'll find something like: + +-- + minimum CPU frequency - maximum CPU frequency - policy +CPU 0 1200000 ( 75%) - 1600000 (100%) - performance +-- + +This means the current policy allows this CPU to be run anywhere +between 1.2 GHz (the value is in kHz) and 1.6 GHz with an eye towards +performance. + +To change the policy, "echo" the desired new policy into +/proc/cpufreq. Use one of the following formats: + +cpu_nr:min_freq:max_freq:policy +cpu_nr%min_freq%max_freq%policy +min_freq:max_freq:policy +min_freq%max_freq%policy + +with cpu_nr being the CPU which shall be affected, min_freq and +max_freq the lower and upper limit of the CPU core frequency in kHz, +and policy either "performance" or "powersave". +A few examples: + +root@notebook:#echo -n "0:0:0:powersave" > /proc/cpufreq + sets the CPU #0 to the lowest supported frequency. + +root@notebook:#echo -n "1%100%100%performance" > /proc/cpufreq + sets the CPU #1 to the highest supported frequency. + +root@notebook:#echo -n "1000000:2000000:performance" > /proc/cpufreq + to set the frequency of all CPUs between 1 GHz and 2 GHz and to + the policy "performance". + +Please note that the values you "echo" into /proc/cpufreq are +validated first, and may be limited by hardware or thermal +considerations. Because of this, a read from /proc/cpufreq might +differ from what was written into it. + + +When you read /proc/cpufreq for the first time after a CPUFreq driver +has been initialized, you'll see the "default policy" for this +driver. If this does not suit your needs, you can pass a boot +parameter to the cpufreq core. Use the following syntax for this: + "cpufreq=min_freq:max_freq:policy", i.e. you may not chose a +specific CPU and you need to specify the limits in kHz and not in +per cent. + + +2.2 /proc/cpufreq interface [2.4] +*********************************** + +Previsiously (and still available as a config option), CPUFreq used +a "sysctl" interface which is located in + /proc/sys/cpu/0/ + /proc/sys/cpu/1/ ... (SMP only) + +In these directories, you will find three files of importance for +CPUFreq: speed-max, speed-min and speed: + +speed shows the current CPU frequency in kHz, +speed-min the minimum supported CPU frequency, and +speed-max the maximum supported CPU frequency. + + +To change the CPU frequency, "echo" the desired CPU frequency (in kHz) +to speed. For example, to set the CPU speed to the lowest/highest +allowed frequency do: + +root@notebook:# cat /proc/sys/cpu/0/speed-min > /proc/sys/cpu/0/speed +root@notebook:# cat /proc/sys/cpu/0/speed-max > /proc/sys/cpu/0/speed + + + +3. CPUFreq core and interfaces +=============================== + +3.1 General information +************************* + +The CPUFreq core code is located in linux/kernel/cpufreq.c. This +cpufreq code offers a standardized interface for the CPUFreq +architecture drivers (those pieces of code that do actual +frequency transitions), as well as to "notifiers". These are device +drivers or other part of the kernel that need to be informed of +policy changes (like thermal modules like ACPI) or of all +frequency changes (like timing code) or even need to force certain +speed limits (like LCD drivers on ARM architecture). Additionally, the +kernel "constant" loops_per_jiffy is updated on frequency changes +here. + + +3.2 CPUFreq notifiers +*********************** + +CPUFreq notifiers conform to the standard kernel notifier interface. +See linux/include/linux/notifier.h for details on notifiers. + +There are two different CPUFreq notifiers - policy notifiers and +transition notifiers. + + +3.2.1 CPUFreq policy notifiers +****************************** + +These are notified when a new policy is intended to be set. Each +CPUFreq policy notifier is called three times for a policy transition: + +1.) During CPUFREQ_ADJUST all CPUFreq notifiers may change the limit if + they see a need for this - may it be thermal considerations or + hardware limitations. + +2.) During CPUFREQ_INCOMPATIBLE only changes may be done in order to avoid + hardware failure. + +3.) And during CPUFREQ_NOTIFY all notifiers are informed of the new policy + - if two hardware drivers failed to agree on a new policy before this + stage, the incompatible hardware shall be shut down, and the user + informed of this. + +The phase is specified in the second argument to the notifier. + +The third argument, a void *pointer, points to a struct cpufreq_policy +consisting of five values: cpu, min, max, policy and max_cpu_freq. Min +and max are the lower and upper frequencies (in kHz) of the new +policy, policy the new policy, cpu the number of the affected CPU or +CPUFREQ_ALL_CPUS for all CPUs; and max_cpu_freq the maximum supported +CPU frequency. This value is given for informational purposes only. + + +3.2.2 CPUFreq transition notifiers +********************************** + +These are notified twice when the CPUfreq driver switches the CPU core +frequency and this change has any external implications. + +The second argument specifies the phase - CPUFREQ_PRECHANGE or +CPUFREQ_POSTCHANGE. + +The third argument is a struct cpufreq_freqs with the following +values: +cpu - number of the affected CPU or CPUFREQ_ALL_CPUS +old - old frequency +new - new frequency + + +3.3 CPUFreq architecture drivers +********************************** + +CPUFreq architecture drivers are the pieces of kernel code that +actually perform CPU frequency transitions. These need to be +initialized separately (separate initcalls), and may be +modularized. They interact with the CPUFreq core in the following way: + +cpufreq_register() +------------------ +cpufreq_register registers an arch driver to the CPUFreq core. Please +note that only one arch driver may be registered at any time. -EBUSY +is returned when an arch driver is already registered. The argument to +cpufreq_register, struct cpufreq_driver *driver, is described later. + +cpufreq_unregister() +-------------------- +cpufreq_unregister unregisters an arch driver, e.g. on module +unloading. Please note that there is no check done that this is called +from the driver which actually registered itself to the core, so +please only call this function when you are sure the arch driver got +registered correctly before. + +cpufreq_notify_transition() +--------------------------- +On "dumb" hardware where only fixed frequency can be set, the driver +must call cpufreq_notify_transition() once before, and once after the +actual transition. + +struct cpufreq_driver +--------------------- +On initialization, the arch driver is supposed to pass a pointer +to a struct cpufreq_driver *cpufreq_driver consisting of the following +entries: + +cpufreq_verify_t verify: This is a pointer to a function with the + following definition: + void verify_function (struct cpufreq_policy *policy). + This function must verify the new policy is within the limits + supported by the CPU, and at least one supported CPU is within + this range. It may be useful to use cpufreq.h / + cpufreq_verify_within_limits for this. + +cpufreq_setpolicy_t setpolicy: This is a pointer to a function with + the following definition: + void setpolicy_function (struct cpufreq_policy *policy). + This function must set the CPU to the new policy. If it is a + "dumb" CPU which only allows fixed frequencies to be set, it + shall set it to the lowest within the limit for + CPUFREQ_POLICY_POWERSAVE, and to the highest for + CPUFREQ_POLICY_PERFORMANCE. Once CONFIG_CPU_FREQ_DYNAMIC is + implemented, it can use a dynamic method to adjust the speed + between the lower and upper limit. + +struct cpufreq_policy *policy: This is an array of NR_CPUS struct + cpufreq_policies, containing the current policies set for these + CPUs. Note that policy[0].max_cpu_freq must contain the + absolute maximum CPU frequency supported by _all_ CPUs. + +In case the driver is expected to run with the 2.4.-style API +(/proc/sys/cpu/.../), two more values must be passed +#ifdef CONFIG_CPU_FREQ_24_API + unsigned int cpu_min_freq; + unsigned int cpu_cur_freq[NR_CPUS]; +#endif + with cpu_min_freq being the minimum CPU frequency supported by + the CPUs; and the entries in cpu_cur_freq reflecting the + current speed of the appropriate CPU. + +Some Requirements to CPUFreq architecture drivers +------------------------------------------------- +* Only call cpufreq_register() when the ability to switch CPU + frequencies is _verified_ or can't be missing +* cpufreq_unregister() may only be called if cpufreq_register() has + been successfully(!) called before. +* kfree() the struct cpufreq_driver only after the call to + cpufreq_unregister(), unless cpufreq_register() failed. +* Be aware that there is currently no error management in the + setpolicy() code in the CPUFreq core. So only call yourself a + cpufreq_driver if you are really a working cpufreq_driver! + + + +4. Mailing list and Links +************************* + + +Mailing List +------------ +There is a CPU frequency changing CVS commit and general list where +you can report bugs, problems or submit patches. To post a message, +send an email to cpufreq@www.linux.org.uk, to subscribe go to +http://www.linux.org.uk/mailman/listinfo/cpufreq. Previous post to the +mailing list are available to subscribers at +http://www.linux.org.uk/mailman/private/cpufreq/. + + +Links +----- +the FTP archives: +* ftp://ftp.linux.org.uk/pub/linux/cpufreq/ + +how to access the CVS repository: +* http://cvs.arm.linux.org.uk/ + +the CPUFreq Mailing list: +* http://www.linux.org.uk/mailman/listinfo/cpufreq + +Clock and voltage scaling for the SA-1100: +* http://www.lart.tudelft.nl/projects/scaling + +CPUFreq project homepage +* http://www.brodo.de/cpufreq/ diff -uNr linux-2.4.21/Documentation/laptop-mode.sh linux-2.4.21-ben2/Documentation/laptop-mode.sh --- linux-2.4.21/Documentation/laptop-mode.sh 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/Documentation/laptop-mode.sh 2003-06-27 15:41:05.000000000 +0200 @@ -0,0 +1,42 @@ +#!/bin/sh +# +# start of stop laptop mode, best run by a power management daemon when +# ac gets connected/disconnected from a laptop +# +# FIXME: assumes HZ == 100 + +# age time, in seconds. should be put into a sysconfig file +MAX_AGE=600 + +# kernel default dirty buffer age +DEF_AGE=30 +DEF_UPDATE=5 + +if [ ! -w /proc/sys/vm/laptop_mode ]; then + echo "Kernel is not patched with laptop_mode patch" + exit 1 +fi + +case "$1" in + start) + AGE=$((100*$MAX_AGE)) + echo -n "Starting laptop mode" + echo "1" > /proc/sys/vm/laptop_mode + echo "30 500 0 0 $AGE $AGE 60 20 0" > /proc/sys/vm/bdflush + echo "." + ;; + stop) + U_AGE=$((100*$DEF_UPDATE)) + B_AGE=$((100*$DEF_AGE)) + echo -n "Stopping laptop mode" + echo "0" > /proc/sys/vm/laptop_mode + echo "30 500 0 0 $U_AGE $B_AGE 60 20 0" > /proc/sys/vm/bdflush + echo "." + ;; + *) + echo "$0 {start|stop}" + ;; + +esac + +exit 0 diff -uNr linux-2.4.21/Documentation/laptop-mode.txt linux-2.4.21-ben2/Documentation/laptop-mode.txt --- linux-2.4.21/Documentation/laptop-mode.txt 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/Documentation/laptop-mode.txt 2003-06-27 15:41:06.000000000 +0200 @@ -0,0 +1,72 @@ +Laptop mode +=========== + +This small doc describes the 2.4 laptop mode patch. + +Last updated 2003-05-25, Jens Axboe + +Introduction +------------ + +A few properties of the Linux vm makes it virtually impossible to attempt +to spin down the hard drive in a laptop for a longer period of time (more +than a handful of seconds). This means you are lucky if you can even reach +the break even point with regards to power consumption, let alone expect any +decrease. + +One problem is the age time of dirty buffers. Linux uses 30 seconds per +default, so if you dirty any data then flusing of that data will commence +at most 30 seconds from then. Another is the journal commit interval of +journalled file systems such as ext3, which is 5 seconds on a stock kernel. +Both of these are tweakable either from proc/sysctl or as mount options +though, and thus partly solvable from user space. + +The kernel update daemon (kupdated) also runs at specific intervals, flushing +old dirty data out. Default is every 5 seconds, this too can be tweaked +from sysctl. + +So what does the laptop mode patch do? It attempts to fully utilize the +hard drive once it has been spun up, flushing the old dirty data out to +disk. Instead of flushing just the expired data, it will clean everything. +When a read causes the disk to spin up, we kick off this flushing after +a few seconds. This means that once the disk spins down again, everything +is up to date. That allows longer dirty data and journal expire times. + +It follows that you have to set long expire times to get long spin downs. +This means you could potentially loose 10 minutes worth of data, if you +set a 10 minute expire count instead of just 30 seconds worth. The biggest +risk here is undoubtedly running out of battery. + +Settings +-------- + +The main knob is /proc/sys/vm/laptop mode. Setting that to 1 switches the +vm (and block layer) to laptop mode. Leaving it to 0 makes the kernel work +like before. When in laptop mode, you also want to extend the intervals +desribed above. See the laptop-mode.sh script for how to do that. + +It can happen that the disk still keeps spinning up and you don't quite +know why or what causes it. The laptop mode patch has a little helper for +that as well, /proc/sys/vm/block-dump. When set to 1, it will dump info to +the kernel message buffer about what process caused the io. Be very careful +when playing with this setting, it is advisable to shut down syslog first! + +Result +------ + +Using the laptop-mode.sh script with its default settings, I get the full +10 minutes worth of drive spin down. Provided your work load is cached, +the disk will only spin up every 10 minutes (well actually, 9 minutes and 55 +seconds due to the 5 second delay in flushing dirty data after the last read +completes). I can't tell you exactly how much extra battery life you will +gain in laptop mode, it will vary greatly on the laptop and workload in +question. The only way to know for sure is to try it out. Getting 10% extra +battery life is not unrealistic. + +Notes +----- + +Patch only changes journal expire time for ext3. reiserfs uses a hardwire +value, should be trivial to adapt though (basically just make it call +get_buffer_flushtime() and uses that). I have not looked at other +journalling file systems, I'll happily accept patches to rectify that! diff -uNr linux-2.4.21/MAINTAINERS linux-2.4.21-ben2/MAINTAINERS --- linux-2.4.21/MAINTAINERS 2003-06-13 16:51:29.000000000 +0200 +++ linux-2.4.21-ben2/MAINTAINERS 2003-06-27 15:41:07.000000000 +0200 @@ -681,6 +681,12 @@ L: linux-kernel@vger.kernel.org S: Maintained +HFSPLUS FILESYSTEM +P: Brad Boyer +M: flar@allandria.com +W: http://sourceforge.net/projects/linux-hfsplus/ +S: Maintained + HGA FRAMEBUFFER DRIVER P: Ferenc Bakonyi M: fero@drama.obuda.kando.hu @@ -1229,7 +1235,7 @@ NVIDIA (RIVA) FRAMEBUFFER DRIVER P: Ani Joshi M: ajoshi@kernel.crashing.org -L: linux-nvidia@lists.surfsouth.com +L: linux-fbdev-devel@lists.sourceforge.net S: Maintained OLYMPIC NETWORK DRIVER @@ -1400,13 +1406,13 @@ RADEON FRAMEBUFFER DISPLAY DRIVER P: Ani Joshi -M: ajoshi@shell.unixbox.com +M: ajoshi@kernel.crashing.org L: linux-fbdev-devel@lists.sourceforge.net S: Maintained RAGE128 FRAMEBUFFER DISPLAY DRIVER P: Ani Joshi -M: ajoshi@shell.unixbox.com +M: ajoshi@kernel.crashing.org L: linux-fbdev-devel@lists.sourceforge.net S: Maintained diff -uNr linux-2.4.21/Makefile linux-2.4.21-ben2/Makefile --- linux-2.4.21/Makefile 2003-06-13 16:51:39.000000000 +0200 +++ linux-2.4.21-ben2/Makefile 2003-06-27 15:41:48.000000000 +0200 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 21 -EXTRAVERSION = +EXTRAVERSION = -ben2 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) diff -uNr linux-2.4.21/README.BENH linux-2.4.21-ben2/README.BENH --- linux-2.4.21/README.BENH 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/README.BENH 2003-06-27 15:41:06.000000000 +0200 @@ -0,0 +1,32 @@ +Welcome to my PowerMac tree. + +In addition to the standard feature set of kernel.org's 2.4.21, this +tree includes small fixes that didn't make it into 2.4.21, including all +of what was present as of 2.4.20-ben10. Some of the major additions are: + + - Laptop mode patch (Jens Axboe). See Documentation/laptop_mode.sh script + - Updated ieee1394 stack from SVN linux_2_4 branch + - HFS+ filesystem read/write by Roman Zippel (Ardistech) based on initial + work by Brad Boyer. + - Andrea Arcangeli's silent-stack-overflow patch + - Better support for recent Apple machines + - CPU Frequency switching support on some laptops + - Support for UniNorth AGP in the agpgart driver (though it's strongly + recommended that you use Michel's Danzer DRM module for that to work + properly) + - Support for blinking the laptop LED on internal HD activity + (Jens and me) + - Improved support for lba48 capable disks (Jens Axboe) + - ADB "query" request support for proper probing of ADB devices from + userland (installers) + - Updated radeonfb with plenty of fixes and proper power management + support for M6, M7 and M9 chipsets + - Updated rivafb with support for more cards & eMac + - Updated sungem driver, supports more chips & recent PHYs + - Small additions to mace & bmac drivers for very basic ethtool informations + return. + - Updated airport/orinoco driver + - Updated dmasound driver to support tumbler & snapper + - Add reporting of OF device path of IDE interfaces in /proc/ide + - Fixes for CompactFlash cards + diff -uNr linux-2.4.21/arch/alpha/mm/fault.c linux-2.4.21-ben2/arch/alpha/mm/fault.c --- linux-2.4.21/arch/alpha/mm/fault.c 2002-11-29 00:53:08.000000000 +0100 +++ linux-2.4.21-ben2/arch/alpha/mm/fault.c 2003-06-27 15:41:05.000000000 +0200 @@ -124,7 +124,7 @@ goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if (expand_stack(vma, address)) + if (expand_stack(vma, address, NULL)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so diff -uNr linux-2.4.21/arch/arm/mm/fault-common.c linux-2.4.21-ben2/arch/arm/mm/fault-common.c --- linux-2.4.21/arch/arm/mm/fault-common.c 2002-11-29 00:53:09.000000000 +0100 +++ linux-2.4.21-ben2/arch/arm/mm/fault-common.c 2003-06-27 15:41:51.000000000 +0200 @@ -229,7 +229,7 @@ goto survive; check_stack: - if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr)) + if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr, NULL)) goto good_area; out: return fault; diff -uNr linux-2.4.21/arch/cris/mm/fault.c linux-2.4.21-ben2/arch/cris/mm/fault.c --- linux-2.4.21/arch/cris/mm/fault.c 2002-11-29 00:53:09.000000000 +0100 +++ linux-2.4.21-ben2/arch/cris/mm/fault.c 2003-06-27 15:41:34.000000000 +0200 @@ -315,7 +315,7 @@ if (address + PAGE_SIZE < rdusp()) goto bad_area; } - if (expand_stack(vma, address)) + if (expand_stack(vma, address, NULL)) goto bad_area; /* diff -uNr linux-2.4.21/arch/i386/mm/fault.c linux-2.4.21-ben2/arch/i386/mm/fault.c --- linux-2.4.21/arch/i386/mm/fault.c 2002-11-29 00:53:09.000000000 +0100 +++ linux-2.4.21-ben2/arch/i386/mm/fault.c 2003-06-27 15:41:03.000000000 +0200 @@ -32,7 +32,7 @@ */ int __verify_write(const void * addr, unsigned long size) { - struct vm_area_struct * vma; + struct vm_area_struct * vma, * prev_vma; unsigned long start = (unsigned long) addr; if (!size) @@ -78,7 +78,8 @@ check_stack: if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if (expand_stack(vma, start) == 0) + find_vma_prev(current->mm, start, &prev_vma); + if (expand_stack(vma, start, prev_vma) == 0) goto good_area; bad_area: @@ -141,7 +142,7 @@ { struct task_struct *tsk; struct mm_struct *mm; - struct vm_area_struct * vma; + struct vm_area_struct * vma, * prev_vma; unsigned long address; unsigned long page; unsigned long fixup; @@ -202,7 +203,8 @@ if (address + 32 < regs->esp) goto bad_area; } - if (expand_stack(vma, address)) + find_vma_prev(mm, address, &prev_vma); + if (expand_stack(vma, address, prev_vma)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so diff -uNr linux-2.4.21/arch/ia64/mm/fault.c linux-2.4.21-ben2/arch/ia64/mm/fault.c --- linux-2.4.21/arch/ia64/mm/fault.c 2003-06-13 16:51:29.000000000 +0200 +++ linux-2.4.21-ben2/arch/ia64/mm/fault.c 2003-06-27 15:41:05.000000000 +0200 @@ -132,7 +132,7 @@ if (rgn_index(address) != rgn_index(vma->vm_start) || rgn_offset(address) >= RGN_MAP_LIMIT) goto bad_area; - if (expand_stack(vma, address)) + if (expand_stack(vma, address, NULL)) goto bad_area; } else { vma = prev_vma; diff -uNr linux-2.4.21/arch/m68k/mm/fault.c linux-2.4.21-ben2/arch/m68k/mm/fault.c --- linux-2.4.21/arch/m68k/mm/fault.c 2002-11-29 00:53:09.000000000 +0100 +++ linux-2.4.21-ben2/arch/m68k/mm/fault.c 2003-06-27 15:41:25.000000000 +0200 @@ -120,7 +120,7 @@ if (address + 256 < rdusp()) goto map_err; } - if (expand_stack(vma, address)) + if (expand_stack(vma, address, NULL)) goto map_err; /* diff -uNr linux-2.4.21/arch/mips/mm/fault.c linux-2.4.21-ben2/arch/mips/mm/fault.c --- linux-2.4.21/arch/mips/mm/fault.c 2002-11-29 00:53:10.000000000 +0100 +++ linux-2.4.21-ben2/arch/mips/mm/fault.c 2003-06-27 15:41:26.000000000 +0200 @@ -113,7 +113,7 @@ goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if (expand_stack(vma, address)) + if (expand_stack(vma, address, NULL)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so diff -uNr linux-2.4.21/arch/mips64/mm/fault.c linux-2.4.21-ben2/arch/mips64/mm/fault.c --- linux-2.4.21/arch/mips64/mm/fault.c 2002-11-29 00:53:10.000000000 +0100 +++ linux-2.4.21-ben2/arch/mips64/mm/fault.c 2003-06-27 15:41:20.000000000 +0200 @@ -137,7 +137,7 @@ goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if (expand_stack(vma, address)) + if (expand_stack(vma, address, NULL)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so diff -uNr linux-2.4.21/arch/ppc/8260_io/enet.c linux-2.4.21-ben2/arch/ppc/8260_io/enet.c --- linux-2.4.21/arch/ppc/8260_io/enet.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/8260_io/enet.c 2003-06-27 15:41:02.000000000 +0200 @@ -115,7 +115,7 @@ cbd_t *dirty_tx; /* The ring entries to be free()ed. */ scc_t *sccp; struct net_device_stats stats; - uint tx_full; + uint tx_free; spinlock_t lock; }; @@ -175,9 +175,9 @@ bdp = cep->cur_tx; #ifndef final_version - if (bdp->cbd_sc & BD_ENET_TX_READY) { + if (!cep->tx_free || (bdp->cbd_sc & BD_ENET_TX_READY)) { /* Ooops. All transmit buffers are full. Bail out. - * This should not happen, since cep->tx_full should be set. + * This should not happen, since the tx queue should be stopped. */ printk("%s: tx queue full!.\n", dev->name); return 1; @@ -223,10 +223,8 @@ else bdp++; - if (bdp->cbd_sc & BD_ENET_TX_READY) { + if (!--cep->tx_free) netif_stop_queue(dev); - cep->tx_full = 1; - } cep->cur_tx = (cbd_t *)bdp; @@ -246,8 +244,8 @@ { int i; cbd_t *bdp; - printk(" Ring data dump: cur_tx %p%s cur_rx %p.\n", - cep->cur_tx, cep->tx_full ? " (full)" : "", + printk(" Ring data dump: cur_tx %p tx_free %d cur_rx %p.\n", + cep->cur_tx, cep->tx_free, cep->cur_rx); bdp = cep->tx_bd_base; printk(" Tx @base %p :\n", bdp); @@ -265,7 +263,7 @@ bdp->cbd_bufaddr); } #endif - if (!cep->tx_full) + if (cep->tx_free) netif_wake_queue(dev); } @@ -309,7 +307,7 @@ spin_lock(&cep->lock); bdp = cep->dirty_tx; while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) { - if ((bdp==cep->cur_tx) && (cep->tx_full == 0)) + if (cep->tx_free == TX_RING_SIZE) break; if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */ @@ -365,8 +363,7 @@ /* Since we have freed up a buffer, the ring is no longer * full. */ - if (cep->tx_full) { - cep->tx_full = 0; + if (!cep->tx_free++) { if (netif_queue_stopped(dev)) { netif_wake_queue(dev); } @@ -395,13 +392,10 @@ } /* Check for receive busy, i.e. packets coming but no place to - * put them. This "can't happen" because the receive interrupt - * is tossing previous frames. + * put them. */ - if (int_events & SCCE_ENET_BSY) { + if (int_events & SCCE_ENET_BSY) cep->stats.rx_dropped++; - printk("SCC ENET: BSY can't happen.\n"); - } return; } @@ -693,6 +687,7 @@ cep->tx_bd_base = (cbd_t *)&immap->im_dprambase[i]; cep->dirty_tx = cep->cur_tx = cep->tx_bd_base; + cep->tx_free = TX_RING_SIZE; cep->cur_rx = cep->rx_bd_base; ep->sen_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB; diff -uNr linux-2.4.21/arch/ppc/8260_io/uart.c linux-2.4.21-ben2/arch/ppc/8260_io/uart.c --- linux-2.4.21/arch/ppc/8260_io/uart.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/8260_io/uart.c 2003-06-27 15:41:19.000000000 +0200 @@ -907,9 +907,9 @@ * enables, because we want to put them back if they were * present. */ - prev_mode = smcp->smc_smcmr; - smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART; - smcp->smc_smcmr |= (prev_mode & (SMCMR_REN | SMCMR_TEN)); + prev_mode = smcp->smc_smcmr & (SMCMR_REN | SMCMR_TEN); + smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART + | prev_mode; } else { sccp = &immr->im_scc[idx - SCC_IDX_BASE]; diff -uNr linux-2.4.21/arch/ppc/8xx_io/fec.c linux-2.4.21-ben2/arch/ppc/8xx_io/fec.c --- linux-2.4.21/arch/ppc/8xx_io/fec.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/8xx_io/fec.c 2003-06-27 15:41:30.000000000 +0200 @@ -163,7 +163,7 @@ cbd_t *dirty_tx; /* The ring entries to be free()ed. */ scc_t *sccp; struct net_device_stats stats; - uint tx_full; + uint tx_free; spinlock_t lock; #ifdef CONFIG_USE_MDIO @@ -229,6 +229,7 @@ mii_list_t *mii_free; mii_list_t *mii_head; mii_list_t *mii_tail; +int mii_stopped; typedef struct mdio_read_data { u16 regval; @@ -295,18 +296,13 @@ fep = dev->priv; fecp = (volatile fec_t*)dev->base_addr; - if (!fep->link) { - /* Link is down or autonegotiation is in progress. */ - return 1; - } - /* Fill in a Tx ring entry */ bdp = fep->cur_tx; #ifndef final_version - if (bdp->cbd_sc & BD_ENET_TX_READY) { + if (!fep->tx_free || (bdp->cbd_sc & BD_ENET_TX_READY)) { /* Ooops. All transmit buffers are full. Bail out. - * This should not happen, since dev->tbusy should be set. + * This should not happen, since the tx queue should be stopped. */ printk("%s: tx queue full!.\n", dev->name); return 1; @@ -357,10 +353,8 @@ bdp++; } - if (bdp->cbd_sc & BD_ENET_TX_READY) { + if (!--fep->tx_free) netif_stop_queue(dev); - fep->tx_full = 1; - } fep->cur_tx = (cbd_t *)bdp; @@ -381,11 +375,11 @@ int i; cbd_t *bdp; - printk("Ring data dump: cur_tx %lx%s, dirty_tx %lx cur_rx: %lx\n", - (unsigned long)fep->cur_tx, fep->tx_full ? " (full)" : "", + printk("Ring data dump: cur_tx %lx, tx_free %d, dirty_tx %lx, cur_rx %lx\n", + (unsigned long)fep->cur_tx, fep->tx_free, (unsigned long)fep->dirty_tx, (unsigned long)fep->cur_rx); - + bdp = fep->tx_bd_base; printk(" tx: %u buffers\n", TX_RING_SIZE); for (i = 0 ; i < TX_RING_SIZE; i++) { @@ -409,7 +403,7 @@ } } #endif - if (!fep->tx_full) + if (fep->tx_free) netif_wake_queue(dev); } @@ -469,7 +463,7 @@ bdp = fep->dirty_tx; while ((bdp->cbd_sc&BD_ENET_TX_READY) == 0) { - if (bdp == fep->cur_tx && fep->tx_full == 0) break; + if (fep->tx_free == TX_RING_SIZE) break; skb = fep->tx_skbuff[fep->skb_dirty]; /* Check for errors. */ @@ -519,8 +513,7 @@ /* Since we have freed up a buffer, the ring is no longer * full. */ - if (fep->tx_full) { - fep->tx_full = 0; + if (!fep->tx_free++) { if (netif_queue_stopped(dev)) netif_wake_queue(dev); } @@ -668,6 +661,12 @@ ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec); mii_reg = ep->fec_mii_data; + /* Ignore this answer if the request queue has been stopped. + * The request will be re-issued when the queue is restarted. + */ + if (mii_stopped) + return; + if ((mip = mii_head) == NULL) { printk("MII and no head!\n"); return; @@ -714,7 +713,8 @@ mii_tail = mip; } else { mii_head = mii_tail = mip; - (&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec))->fec_mii_data = regval; + if (!mii_stopped) + (&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec))->fec_mii_data = regval; } } else { retval = 1; @@ -725,6 +725,30 @@ return(retval); } +/* Functions to stop/start the transmission of requests through the MDIO. + * They are intended to be used before and after a FEC reset. + */ +static void stop_mii_queue(struct net_device *dev) +{ + unsigned long flags; + save_flags(flags); + cli(); + mii_stopped = 1; + restore_flags(flags); +} + +static void start_mii_queue(struct net_device *dev) +{ + unsigned long flags; + volatile fec_t *ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec); + save_flags(flags); + cli(); + mii_stopped = 0; + if(mii_head) + ep->fec_mii_data = mii_head->mii_regval; + restore_flags(flags); +} + static void mii_do_cmd(struct net_device *dev, const phy_cmd_t *c) { int k; @@ -1367,31 +1391,20 @@ #ifdef CONFIG_USE_MDIO struct net_device *dev = dev_id; struct fec_enet_private *fep = dev->priv; - volatile immap_t *immap = (immap_t *)IMAP_ADDR; - volatile fec_t *fecp = &(immap->im_cpm.cp_fec); - unsigned int ecntrl = fecp->fec_ecntrl; - - /* We need the FEC enabled to access the MII - */ - if ((ecntrl & FEC_ECNTRL_ETHER_EN) == 0) { - fecp->fec_ecntrl |= FEC_ECNTRL_ETHER_EN; - } -#endif /* CONFIG_USE_MDIO */ - -#if 0 - disable_irq(fep->mii_irq); /* disable now, enable later */ -#endif - -#ifdef CONFIG_USE_MDIO - mii_do_cmd(dev, fep->phy->ack_int); - mii_do_cmd(dev, phy_cmd_relink); /* restart and display status */ - - if ((ecntrl & FEC_ECNTRL_ETHER_EN) == 0) { - fecp->fec_ecntrl = ecntrl; /* restore old settings */ + /* + * Acknowledge the interrupt if possible. If we have not + * found the PHY yet we can't process or acknowledge the + * interrupt now. Instead we ignore this interrupt for now, + * which we can do since it is edge triggered. It will be + * acknowledged later by fec_enet_open(). + */ + if (fep->phy) { + mii_do_cmd(dev, fep->phy->ack_int); + mii_do_cmd(dev, phy_cmd_relink); /* restart and display status */ } #else -printk("%s[%d] %s: unexpected Link interrupt\n", __FILE__,__LINE__,__FUNCTION__); + printk ("FEC: unexpected Link interrupt\n"); #endif /* CONFIG_USE_MDIO */ } @@ -1927,6 +1940,11 @@ fep = dev->priv; +#ifdef CONFIG_USE_MDIO + /* Stop the MDIO communication prior to reset. */ + stop_mii_queue(dev); +#endif + /* Whack a reset. We should wait for this. */ fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET; @@ -1960,6 +1978,7 @@ fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base)); fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; + fep->tx_free = TX_RING_SIZE; fep->cur_rx = fep->rx_bd_base; /* Reset SKB transmit buffers. @@ -2043,12 +2062,10 @@ fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN; fecp->fec_r_des_active = 0x01000000; - /* The tx ring is no longer full. */ - if(fep->tx_full) - { - fep->tx_full = 0; - netif_wake_queue(dev); - } +#ifdef CONFIG_USE_MDIO + /* Re-start any pending MDIO communication. */ + start_mii_queue(dev); +#endif } static void @@ -2080,22 +2097,7 @@ printk ("FEC timeout on graceful transmit stop\n"); } - /* Clear outstanding MII command interrupts. - */ - fecp->fec_ievent = FEC_ENET_MII; - - /* Enable MII command finished interrupt - */ - fecp->fec_ivec = (FEC_INTERRUPT/2) << 29; + /* Disable FEC. Let only MII interrupts. */ fecp->fec_imask = FEC_ENET_MII; - -#ifdef CONFIG_USE_MDIO - /* Set MII speed. - */ - fecp->fec_mii_speed = fep->phy_speed; -#endif /* CONFIG_USE_MDIO */ - - /* Disable FEC - */ fecp->fec_ecntrl &= ~(FEC_ECNTRL_ETHER_EN); } diff -uNr linux-2.4.21/arch/ppc/8xx_io/uart.c linux-2.4.21-ben2/arch/ppc/8xx_io/uart.c --- linux-2.4.21/arch/ppc/8xx_io/uart.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/8xx_io/uart.c 2003-06-27 15:41:32.000000000 +0200 @@ -1023,9 +1023,9 @@ * enables, because we want to put them back if they were * present. */ - prev_mode = smcp->smc_smcmr; - new_mode = smcr_mk_clen(bits) | cval | SMCMR_SM_UART; - new_mode |= (prev_mode & (SMCMR_REN | SMCMR_TEN)); + prev_mode = smcp->smc_smcmr & (SMCMR_REN | SMCMR_TEN); + new_mode = smcr_mk_clen(bits) | cval | SMCMR_SM_UART + | prev_mode; if (!(prev_mode & SMCMR_PEN)) /* If parity is disabled, mask out even/odd */ prev_mode &= ~SMCMR_PM_EVEN; diff -uNr linux-2.4.21/arch/ppc/boot/common/misc-simple.c linux-2.4.21-ben2/arch/ppc/boot/common/misc-simple.c --- linux-2.4.21/arch/ppc/boot/common/misc-simple.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/boot/common/misc-simple.c 2003-06-27 15:41:09.000000000 +0200 @@ -75,14 +75,6 @@ extern void gunzip(void *, int, unsigned char *, int *); extern void serial_fixups(void); -/* Allow decompress_kernel to be hooked into. This is the default. */ -void * __attribute__ ((weak)) -load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, - void *bp) -{ - return decompress_kernel(load_addr, num_words, cksum, bp); -} - struct bi_record * decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum) { diff -uNr linux-2.4.21/arch/ppc/boot/prep/Makefile linux-2.4.21-ben2/arch/ppc/boot/prep/Makefile --- linux-2.4.21/arch/ppc/boot/prep/Makefile 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/boot/prep/Makefile 2003-06-27 15:41:52.000000000 +0200 @@ -18,7 +18,7 @@ TFTPIMAGE = /tftpboot/zImage.prep ifeq ($(CONFIG_SMP),y) -TFTPIMAGE := $(TFTPIMAGE).smp +TFTPIMAGE = $(TFTPBOOT).smp endif LD_ARGS = -T ../ld.script -Ttext 0x00800000 -Bstatic diff -uNr linux-2.4.21/arch/ppc/config.in linux-2.4.21-ben2/arch/ppc/config.in --- linux-2.4.21/arch/ppc/config.in 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/config.in 2003-06-27 15:41:04.000000000 +0200 @@ -51,6 +51,17 @@ define_bool CONFIG_PPC_STD_MMU n fi +bool 'CPU Frequency scaling' CONFIG_CPU_FREQ +if [ "$CONFIG_CPU_FREQ" = "y" ]; then + bool ' /proc/sys/cpu/ interface (2.4.)' CONFIG_CPU_FREQ_24_API + if [ "$CONFIG_CPU_FREQ_24_API" = "n" ]; then + define_bool CONFIG_CPU_FREQ_26_API y + fi + if [ "$CONFIG_ADB_PMU" = "y" ]; then + bool " Support for Apple PowerBooks" CONFIG_CPU_FREQ_PMAC + fi +fi + if [ "$CONFIG_8260" = "y" ]; then define_bool CONFIG_SERIAL_CONSOLE y bool 'Support for EST8260' CONFIG_EST8260 diff -uNr linux-2.4.21/arch/ppc/configs/IVMS8_defconfig linux-2.4.21-ben2/arch/ppc/configs/IVMS8_defconfig --- linux-2.4.21/arch/ppc/configs/IVMS8_defconfig 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/configs/IVMS8_defconfig 2003-06-27 15:41:49.000000000 +0200 @@ -76,7 +76,7 @@ # Parallel port support # # CONFIG_PARPORT is not set -CONFIG_GEN_RTC=y +CONFIG_PPC_RTC=y # CONFIG_CMDLINE_BOOL is not set # @@ -200,6 +200,7 @@ # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes @@ -218,7 +219,6 @@ # CONFIG_BLK_DEV_ATARAID is not set # CONFIG_BLK_DEV_ATARAID_PDC is not set # CONFIG_BLK_DEV_ATARAID_HPT is not set -# CONFIG_BLK_DEV_ATARAID_SII is not set # # SCSI support @@ -372,11 +372,6 @@ # Input core support is needed for joysticks # # CONFIG_QIC02_TAPE is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_DEVICE_INTERFACE is not set -# CONFIG_IPMI_KCS is not set -# CONFIG_IPMI_WATCHDOG is not set # # Watchdog Cards diff -uNr linux-2.4.21/arch/ppc/configs/SM850_defconfig linux-2.4.21-ben2/arch/ppc/configs/SM850_defconfig --- linux-2.4.21/arch/ppc/configs/SM850_defconfig 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/configs/SM850_defconfig 2003-06-27 15:41:09.000000000 +0200 @@ -77,7 +77,7 @@ # Parallel port support # # CONFIG_PARPORT is not set -CONFIG_GEN_RTC=y +CONFIG_PPC_RTC=y # CONFIG_CMDLINE_BOOL is not set # @@ -336,11 +336,6 @@ # Input core support is needed for joysticks # # CONFIG_QIC02_TAPE is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_DEVICE_INTERFACE is not set -# CONFIG_IPMI_KCS is not set -# CONFIG_IPMI_WATCHDOG is not set # # Watchdog Cards diff -uNr linux-2.4.21/arch/ppc/configs/SPD823TS_defconfig linux-2.4.21-ben2/arch/ppc/configs/SPD823TS_defconfig --- linux-2.4.21/arch/ppc/configs/SPD823TS_defconfig 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/configs/SPD823TS_defconfig 2003-06-27 15:41:06.000000000 +0200 @@ -76,7 +76,7 @@ # Parallel port support # # CONFIG_PARPORT is not set -CONFIG_GEN_RTC=y +CONFIG_PPC_RTC=y # CONFIG_CMDLINE_BOOL is not set # @@ -335,11 +335,6 @@ # Input core support is needed for joysticks # # CONFIG_QIC02_TAPE is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_DEVICE_INTERFACE is not set -# CONFIG_IPMI_KCS is not set -# CONFIG_IPMI_WATCHDOG is not set # # Watchdog Cards diff -uNr linux-2.4.21/arch/ppc/configs/TQM823L_defconfig linux-2.4.21-ben2/arch/ppc/configs/TQM823L_defconfig --- linux-2.4.21/arch/ppc/configs/TQM823L_defconfig 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/configs/TQM823L_defconfig 2003-06-27 15:41:15.000000000 +0200 @@ -77,7 +77,7 @@ # Parallel port support # # CONFIG_PARPORT is not set -CONFIG_GEN_RTC=y +CONFIG_PPC_RTC=y # CONFIG_CMDLINE_BOOL is not set # @@ -336,11 +336,6 @@ # Input core support is needed for joysticks # # CONFIG_QIC02_TAPE is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_DEVICE_INTERFACE is not set -# CONFIG_IPMI_KCS is not set -# CONFIG_IPMI_WATCHDOG is not set # # Watchdog Cards diff -uNr linux-2.4.21/arch/ppc/configs/TQM850L_defconfig linux-2.4.21-ben2/arch/ppc/configs/TQM850L_defconfig --- linux-2.4.21/arch/ppc/configs/TQM850L_defconfig 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/configs/TQM850L_defconfig 2003-06-27 15:41:51.000000000 +0200 @@ -77,7 +77,7 @@ # Parallel port support # # CONFIG_PARPORT is not set -CONFIG_GEN_RTC=y +CONFIG_PPC_RTC=y # CONFIG_CMDLINE_BOOL is not set # @@ -336,11 +336,6 @@ # Input core support is needed for joysticks # # CONFIG_QIC02_TAPE is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_DEVICE_INTERFACE is not set -# CONFIG_IPMI_KCS is not set -# CONFIG_IPMI_WATCHDOG is not set # # Watchdog Cards diff -uNr linux-2.4.21/arch/ppc/configs/TQM860L_defconfig linux-2.4.21-ben2/arch/ppc/configs/TQM860L_defconfig --- linux-2.4.21/arch/ppc/configs/TQM860L_defconfig 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/configs/TQM860L_defconfig 2003-06-27 15:41:08.000000000 +0200 @@ -77,7 +77,7 @@ # Parallel port support # # CONFIG_PARPORT is not set -CONFIG_GEN_RTC=y +CONFIG_PPC_RTC=y # CONFIG_CMDLINE_BOOL is not set # @@ -201,6 +201,7 @@ # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes @@ -219,7 +220,6 @@ # CONFIG_BLK_DEV_ATARAID is not set # CONFIG_BLK_DEV_ATARAID_PDC is not set # CONFIG_BLK_DEV_ATARAID_HPT is not set -# CONFIG_BLK_DEV_ATARAID_SII is not set # # SCSI support @@ -373,11 +373,6 @@ # Input core support is needed for joysticks # # CONFIG_QIC02_TAPE is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_DEVICE_INTERFACE is not set -# CONFIG_IPMI_KCS is not set -# CONFIG_IPMI_WATCHDOG is not set # # Watchdog Cards diff -uNr linux-2.4.21/arch/ppc/configs/briq_defconfig linux-2.4.21-ben2/arch/ppc/configs/briq_defconfig --- linux-2.4.21/arch/ppc/configs/briq_defconfig 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/configs/briq_defconfig 2003-06-27 15:41:23.000000000 +0200 @@ -1,5 +1,5 @@ # -# Automatically generated make config: don't edit +# Automatically generated by make menuconfig: don't edit # # CONFIG_UID16 is not set # CONFIG_RWSEM_GENERIC_SPINLOCK is not set @@ -30,23 +30,21 @@ # CONFIG_8xx is not set # CONFIG_8260 is not set CONFIG_PPC_STD_MMU=y +# CONFIG_CPU_FREQ is not set CONFIG_ALL_PPC=y # CONFIG_APUS is not set # CONFIG_SPRUCE is not set -# CONFIG_LOPEC is not set # CONFIG_PAL4 is not set # CONFIG_GEMINI is not set # CONFIG_SMP is not set CONFIG_ALTIVEC=y -CONFIG_TAU=y -# CONFIG_TAU_INT is not set -# CONFIG_TAU_AVERAGE is not set +# CONFIG_TAU is not set CONFIG_PPC_ISATIMER=y # # General setup # -# CONFIG_HIGHMEM is not set +CONFIG_HIGHMEM=y # CONFIG_ISA is not set # CONFIG_EISA is not set # CONFIG_SBUS is not set @@ -61,21 +59,26 @@ CONFIG_KERNEL_ELF=y CONFIG_BINFMT_MISC=m CONFIG_PCI_NAMES=y -# CONFIG_HOTPLUG is not set +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# # CONFIG_PCMCIA is not set # # Parallel port support # # CONFIG_PARPORT is not set -CONFIG_GEN_RTC=y -CONFIG_PPC601_SYNC_FIX=y +CONFIG_PPC_RTC=y +# CONFIG_PPC601_SYNC_FIX is not set CONFIG_PROC_DEVICETREE=y -CONFIG_PPC_RTAS=y +# CONFIG_PPC_RTAS is not set +# CONFIG_BOOTX_TEXT is not set # CONFIG_PREP_RESIDUAL is not set # CONFIG_PROC_PREPRESIDUAL is not set -CONFIG_PPCBUG_NVRAM=y -# CONFIG_CMDLINE_BOOL is not set +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttyS0,38400 root=/dev/hda2" # # Memory Technology Devices (MTD) @@ -91,7 +94,7 @@ # # Block devices # -CONFIG_BLK_DEV_FD=m +# CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set @@ -126,7 +129,7 @@ # CONFIG_NETLINK_DEV is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set -# CONFIG_FILTER is not set +CONFIG_FILTER=y CONFIG_UNIX=y CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -144,10 +147,8 @@ # CONFIG_IP_NF_CONNTRACK=m CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_TFTP=m CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_QUEUE is not set +CONFIG_IP_NF_QUEUE=m CONFIG_IP_NF_IPTABLES=m CONFIG_IP_NF_MATCH_LIMIT=m CONFIG_IP_NF_MATCH_MAC=m @@ -157,7 +158,7 @@ CONFIG_IP_NF_MATCH_TOS=m CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_DSCP=m -# CONFIG_IP_NF_MATCH_AH_ESP is not set +CONFIG_IP_NF_MATCH_AH_ESP=m CONFIG_IP_NF_MATCH_LENGTH=m CONFIG_IP_NF_MATCH_TTL=m CONFIG_IP_NF_MATCH_TCPMSS=m @@ -173,17 +174,20 @@ CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_AMANDA=m # CONFIG_IP_NF_NAT_LOCAL is not set CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -# CONFIG_IP_NF_MANGLE is not set -# CONFIG_IP_NF_TARGET_LOG is not set -# CONFIG_IP_NF_TARGET_ULOG is not set +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_TOS=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_DSCP=m +CONFIG_IP_NF_TARGET_MARK=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m CONFIG_IP_NF_TARGET_TCPMSS=m -# CONFIG_IP_NF_ARPTABLES is not set +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m CONFIG_IP_NF_COMPAT_IPCHAINS=m CONFIG_IP_NF_NAT_NEEDED=y # CONFIG_IP_NF_COMPAT_IPFWADM is not set @@ -191,10 +195,6 @@ # CONFIG_KHTTPD is not set # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set - -# -# -# # CONFIG_IPX is not set CONFIG_ATALK=m @@ -232,10 +232,6 @@ # IDE, ATA and ATAPI Block devices # CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# # CONFIG_BLK_DEV_HD_IDE is not set # CONFIG_BLK_DEV_HD is not set CONFIG_BLK_DEV_IDEDISK=y @@ -245,12 +241,9 @@ CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set CONFIG_BLK_DEV_IDEFLOPPY=y -CONFIG_BLK_DEV_IDESCSI=y -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# +# CONFIG_BLK_DEV_IDESCSI is not set +CONFIG_IDE_TASK_IOCTL=y +# CONFIG_IDE_TASKFILE_IO is not set # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_CMD640_ENHANCED is not set # CONFIG_BLK_DEV_ISAPNP is not set @@ -263,8 +256,8 @@ CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -# CONFIG_BLK_DEV_ADMA100 is not set +CONFIG_IDEDMA_PCI_WIP=y +CONFIG_BLK_DEV_ADMA=y # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set @@ -278,6 +271,7 @@ # CONFIG_HPT34X_AUTODMA is not set # CONFIG_BLK_DEV_HPT366 is not set # CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_NFORCE is not set # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_PDC202XX_OLD is not set @@ -304,85 +298,11 @@ # CONFIG_BLK_DEV_ATARAID is not set # CONFIG_BLK_DEV_ATARAID_PDC is not set # CONFIG_BLK_DEV_ATARAID_HPT is not set -# CONFIG_BLK_DEV_ATARAID_SII is not set # # SCSI support # -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=y -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_SR_EXTRA_DEVS=2 -CONFIG_CHR_DEV_SG=y - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_NCR53C8XX is not set -# CONFIG_SCSI_SYM53C8XX is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set -# CONFIG_SCSI_MESH is not set -# CONFIG_SCSI_MAC53C94 is not set +# CONFIG_SCSI is not set # # IEEE 1394 (FireWire) support (EXPERIMENTAL) @@ -433,7 +353,6 @@ # CONFIG_DGRS is not set # CONFIG_DM9102 is not set # CONFIG_EEPRO100 is not set -# CONFIG_EEPRO100_PIO is not set # CONFIG_E100 is not set # CONFIG_LNE390 is not set # CONFIG_FEALNX is not set @@ -474,14 +393,7 @@ # CONFIG_FDDI is not set # CONFIG_HIPPI is not set # CONFIG_PLIP is not set -CONFIG_PPP=m -CONFIG_PPP_MULTILINK=y -# CONFIG_PPP_FILTER is not set -CONFIG_PPP_ASYNC=m -CONFIG_PPP_SYNC_TTY=m -CONFIG_PPP_DEFLATE=m -CONFIG_PPP_BSDCOMP=m -CONFIG_PPPOE=m +# CONFIG_PPP is not set # CONFIG_SLIP is not set # @@ -560,6 +472,7 @@ # CONFIG_SERIAL_NONSTANDARD is not set CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_BRIQ_PANEL=y # # I2C support @@ -574,34 +487,14 @@ # # Mice # -CONFIG_BUSMOUSE=y -# CONFIG_ATIXL_BUSMOUSE is not set -# CONFIG_LOGIBUSMOUSE is not set -# CONFIG_MS_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set -# CONFIG_MK712_MOUSE is not set +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set # # Joysticks # # CONFIG_INPUT_GAMEPORT is not set - -# -# Input core support is needed for gameports -# - -# -# Input core support is needed for joysticks -# # CONFIG_QIC02_TAPE is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_DEVICE_INTERFACE is not set -# CONFIG_IPMI_KCS is not set -# CONFIG_IPMI_WATCHDOG is not set # # Watchdog Cards @@ -639,17 +532,17 @@ # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set +CONFIG_HFS_FS=m # CONFIG_BEFS_FS is not set # CONFIG_BEFS_DEBUG is not set # CONFIG_BFS_FS is not set CONFIG_EXT3_FS=y CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m # CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set +CONFIG_VFAT_FS=m # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set # CONFIG_JFFS2_FS is not set @@ -718,14 +611,14 @@ # CONFIG_ATARI_PARTITION is not set CONFIG_MAC_PARTITION=y CONFIG_MSDOS_PARTITION=y -CONFIG_BSD_DISKLABEL=y -CONFIG_MINIX_SUBPARTITION=y -CONFIG_SOLARIS_X86_PARTITION=y -CONFIG_UNIXWARE_DISKLABEL=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_LDM_PARTITION is not set -CONFIG_SGI_PARTITION=y -CONFIG_ULTRIX_PARTITION=y -CONFIG_SUN_PARTITION=y +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set # CONFIG_EFI_PARTITION is not set CONFIG_SMB_NLS=y CONFIG_NLS=y @@ -790,19 +683,17 @@ # # Library routines # -CONFIG_ZLIB_INFLATE=m -CONFIG_ZLIB_DEFLATE=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y # # Kernel hacking # CONFIG_DEBUG_KERNEL=y -CONFIG_MAGIC_SYSRQ=y +# CONFIG_MAGIC_SYSRQ is not set # CONFIG_DEBUG_HIGHMEM is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_WAITQ is not set # CONFIG_KGDB is not set -CONFIG_XMON=y +# CONFIG_XMON is not set # CONFIG_BDI_SWITCH is not set -# CONFIG_MORE_COMPILE_OPTIONS is not set -CONFIG_BOOTX_TEXT=y diff -uNr linux-2.4.21/arch/ppc/configs/gemini_defconfig linux-2.4.21-ben2/arch/ppc/configs/gemini_defconfig --- linux-2.4.21/arch/ppc/configs/gemini_defconfig 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/configs/gemini_defconfig 2003-06-27 15:41:02.000000000 +0200 @@ -33,7 +33,6 @@ # CONFIG_ALL_PPC is not set # CONFIG_APUS is not set # CONFIG_SPRUCE is not set -# CONFIG_LOPEC is not set # CONFIG_PAL4 is not set CONFIG_GEMINI=y # CONFIG_SMP is not set @@ -68,7 +67,6 @@ # Parallel port support # # CONFIG_PARPORT is not set -# CONFIG_GEN_RTC is not set # CONFIG_PPC_RTC is not set # CONFIG_CMDLINE_BOOL is not set @@ -221,7 +219,6 @@ # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set @@ -420,11 +417,6 @@ # Input core support is needed for joysticks # # CONFIG_QIC02_TAPE is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_DEVICE_INTERFACE is not set -# CONFIG_IPMI_KCS is not set -# CONFIG_IPMI_WATCHDOG is not set # # Watchdog Cards diff -uNr linux-2.4.21/arch/ppc/configs/ibmchrp_defconfig linux-2.4.21-ben2/arch/ppc/configs/ibmchrp_defconfig --- linux-2.4.21/arch/ppc/configs/ibmchrp_defconfig 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/configs/ibmchrp_defconfig 2003-06-27 15:41:05.000000000 +0200 @@ -33,7 +33,6 @@ CONFIG_ALL_PPC=y # CONFIG_APUS is not set # CONFIG_SPRUCE is not set -# CONFIG_LOPEC is not set # CONFIG_PAL4 is not set # CONFIG_GEMINI is not set # CONFIG_SMP is not set @@ -66,13 +65,13 @@ # Parallel port support # # CONFIG_PARPORT is not set -CONFIG_GEN_RTC=y +CONFIG_PPC_RTC=y # CONFIG_PPC601_SYNC_FIX is not set CONFIG_PROC_DEVICETREE=y CONFIG_PPC_RTAS=y +# CONFIG_BOOTX_TEXT is not set # CONFIG_PREP_RESIDUAL is not set # CONFIG_PROC_PREPRESIDUAL is not set -CONFIG_PPCBUG_NVRAM=y # CONFIG_CMDLINE_BOOL is not set # @@ -142,8 +141,6 @@ # CONFIG_IP_NF_CONNTRACK=m CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_TFTP=m CONFIG_IP_NF_IRC=m # CONFIG_IP_NF_QUEUE is not set CONFIG_IP_NF_IPTABLES=m @@ -171,12 +168,10 @@ CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_AMANDA=m # CONFIG_IP_NF_NAT_LOCAL is not set CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m # CONFIG_IP_NF_MANGLE is not set # CONFIG_IP_NF_TARGET_LOG is not set CONFIG_IP_NF_TARGET_ULOG=m @@ -265,7 +260,6 @@ # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set @@ -358,7 +352,6 @@ # CONFIG_DGRS is not set # CONFIG_DM9102 is not set # CONFIG_EEPRO100 is not set -# CONFIG_EEPRO100_PIO is not set # CONFIG_E100 is not set # CONFIG_LNE390 is not set # CONFIG_FEALNX is not set @@ -470,15 +463,12 @@ CONFIG_FB_MATROX=y CONFIG_FB_MATROX_MILLENIUM=y CONFIG_FB_MATROX_MYSTIQUE=y -# CONFIG_FB_MATROX_G450 is not set -CONFIG_FB_MATROX_G100A=y CONFIG_FB_MATROX_G100=y -CONFIG_FB_MATROX_PROC=y +# CONFIG_FB_MATROX_G450 is not set # CONFIG_FB_MATROX_MULTIHEAD is not set # CONFIG_FB_ATY is not set # CONFIG_FB_RADEON is not set # CONFIG_FB_ATY128 is not set -# CONFIG_FB_INTEL is not set # CONFIG_FB_SIS is not set # CONFIG_FB_NEOMAGIC is not set CONFIG_FB_3DFX=y @@ -533,6 +523,7 @@ # CONFIG_SERIAL_NONSTANDARD is not set CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 +# CONFIG_BRIQ_PANEL is not set # # I2C support @@ -587,11 +578,6 @@ # CONFIG_INPUT_GAMECON is not set # CONFIG_INPUT_TURBOGRAFX is not set # CONFIG_QIC02_TAPE is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_DEVICE_INTERFACE is not set -# CONFIG_IPMI_KCS is not set -# CONFIG_IPMI_WATCHDOG is not set # # Watchdog Cards @@ -794,4 +780,3 @@ CONFIG_XMON=y # CONFIG_BDI_SWITCH is not set # CONFIG_MORE_COMPILE_OPTIONS is not set -# CONFIG_BOOTX_TEXT is not set diff -uNr linux-2.4.21/arch/ppc/configs/pmac_defconfig linux-2.4.21-ben2/arch/ppc/configs/pmac_defconfig --- linux-2.4.21/arch/ppc/configs/pmac_defconfig 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/configs/pmac_defconfig 2003-06-27 15:41:04.000000000 +0200 @@ -30,6 +30,10 @@ # CONFIG_8xx is not set # CONFIG_8260 is not set CONFIG_PPC_STD_MMU=y +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_24_API is not set +CONFIG_CPU_FREQ_26_API=y +CONFIG_CPU_FREQ_PMAC=y CONFIG_ALL_PPC=y # CONFIG_APUS is not set # CONFIG_SPRUCE is not set @@ -38,15 +42,13 @@ # CONFIG_GEMINI is not set # CONFIG_SMP is not set CONFIG_ALTIVEC=y -CONFIG_TAU=y -# CONFIG_TAU_INT is not set -# CONFIG_TAU_AVERAGE is not set +# CONFIG_TAU is not set CONFIG_PPC_ISATIMER=y # # General setup # -# CONFIG_HIGHMEM is not set +CONFIG_HIGHMEM=y # CONFIG_ISA is not set # CONFIG_EISA is not set # CONFIG_SBUS is not set @@ -76,10 +78,11 @@ # Parallel port support # # CONFIG_PARPORT is not set -CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC is not set +CONFIG_PPC_RTC=y CONFIG_PPC601_SYNC_FIX=y CONFIG_PROC_DEVICETREE=y -CONFIG_PPC_RTAS=y +# CONFIG_PPC_RTAS is not set # CONFIG_PREP_RESIDUAL is not set # CONFIG_PROC_PREPRESIDUAL is not set CONFIG_PPCBUG_NVRAM=y @@ -99,7 +102,7 @@ # # Block devices # -CONFIG_BLK_DEV_FD=m +# CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set @@ -152,10 +155,10 @@ # CONFIG_IP_NF_CONNTRACK=m CONFIG_IP_NF_FTP=m -CONFIG_IP_NF_AMANDA=m -CONFIG_IP_NF_TFTP=m +# CONFIG_IP_NF_AMANDA is not set +# CONFIG_IP_NF_TFTP is not set CONFIG_IP_NF_IRC=m -# CONFIG_IP_NF_QUEUE is not set +CONFIG_IP_NF_QUEUE=m CONFIG_IP_NF_IPTABLES=m CONFIG_IP_NF_MATCH_LIMIT=m CONFIG_IP_NF_MATCH_MAC=m @@ -181,14 +184,16 @@ CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m -CONFIG_IP_NF_NAT_AMANDA=m # CONFIG_IP_NF_NAT_LOCAL is not set CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m CONFIG_IP_NF_NAT_FTP=m -CONFIG_IP_NF_NAT_TFTP=m -# CONFIG_IP_NF_MANGLE is not set -# CONFIG_IP_NF_TARGET_LOG is not set +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_TARGET_TOS=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_DSCP=m +CONFIG_IP_NF_TARGET_MARK=m +CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m CONFIG_IP_NF_TARGET_TCPMSS=m CONFIG_IP_NF_ARPTABLES=m @@ -198,7 +203,13 @@ # CONFIG_IP_NF_COMPAT_IPFWADM is not set # CONFIG_IPV6 is not set # CONFIG_KHTTPD is not set -# CONFIG_ATM is not set +CONFIG_ATM=y +CONFIG_ATM_CLIP=y +CONFIG_ATM_CLIP_NO_ICMP=y +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set # CONFIG_VLAN_8021Q is not set # @@ -255,7 +266,7 @@ # CONFIG_BLK_DEV_IDETAPE is not set CONFIG_BLK_DEV_IDEFLOPPY=y CONFIG_BLK_DEV_IDESCSI=y -# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASK_IOCTL=y # # IDE chipset support/bugfixes @@ -272,9 +283,9 @@ CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set +CONFIG_IDEDMA_PCI_WIP=y # CONFIG_BLK_DEV_ADMA100 is not set -# CONFIG_BLK_DEV_AEC62XX is not set +CONFIG_BLK_DEV_AEC62XX=y # CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_WDC_ALI15X3 is not set # CONFIG_BLK_DEV_AMD74XX is not set @@ -289,10 +300,10 @@ # CONFIG_BLK_DEV_PIIX is not set # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_PDC202XX_OLD is not set -# CONFIG_PDC202XX_BURST is not set -CONFIG_BLK_DEV_PDC202XX_NEW=m -# CONFIG_PDC202XX_FORCE is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +CONFIG_PDC202XX_BURST=y +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_PDC202XX_FORCE=y # CONFIG_BLK_DEV_RZ1000 is not set # CONFIG_BLK_DEV_SC1200 is not set # CONFIG_BLK_DEV_SVWKS is not set @@ -303,8 +314,10 @@ # CONFIG_BLK_DEV_VIA82CXXX is not set CONFIG_BLK_DEV_SL82C105=y CONFIG_BLK_DEV_IDE_PMAC=y +CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y CONFIG_BLK_DEV_IDEDMA_PMAC=y CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO=y +CONFIG_PMU_HD_BLINK=y CONFIG_BLK_DEV_IDEDMA=y CONFIG_BLK_DEV_IDEPCI=y # CONFIG_IDE_CHIPSETS is not set @@ -353,19 +366,12 @@ # CONFIG_SCSI_AHA1542 is not set # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AACRAID is not set -CONFIG_SCSI_AIC7XXX=m +CONFIG_SCSI_AIC7XXX=y CONFIG_AIC7XXX_CMDS_PER_DEVICE=253 CONFIG_AIC7XXX_RESET_DELAY_MS=15000 # CONFIG_AIC7XXX_PROBE_EISA_VL is not set # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set -# CONFIG_AIC7XXX_DEBUG_ENABLE is not set -CONFIG_AIC7XXX_DEBUG_MASK=0 -# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set # CONFIG_SCSI_AIC79XX is not set -CONFIG_SCSI_AIC7XXX_OLD=m -# CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT is not set -CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=8 -CONFIG_AIC7XXX_OLD_PROC_STATS=y # CONFIG_SCSI_DPT_I2O is not set CONFIG_SCSI_ADVANSYS=m # CONFIG_SCSI_IN2000 is not set @@ -407,7 +413,7 @@ # CONFIG_SCSI_DEBUG is not set CONFIG_SCSI_MESH=y CONFIG_SCSI_MESH_SYNC_RATE=5 -CONFIG_SCSI_MESH_RESET_DELAY_MS=500 +CONFIG_SCSI_MESH_RESET_DELAY_MS=4000 CONFIG_SCSI_MAC53C94=y # @@ -436,10 +442,11 @@ CONFIG_IEEE1394_SBP2=m # CONFIG_IEEE1394_SBP2_PHYS_DMA is not set CONFIG_IEEE1394_ETH1394=m -# CONFIG_IEEE1394_DV1394 is not set +CONFIG_IEEE1394_DV1394=m CONFIG_IEEE1394_RAWIO=m # CONFIG_IEEE1394_CMP is not set # CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y # # Network device support @@ -453,7 +460,7 @@ # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set +CONFIG_TUN=m # CONFIG_ETHERTAP is not set # @@ -537,6 +544,7 @@ CONFIG_PPP_DEFLATE=y CONFIG_PPP_BSDCOMP=m # CONFIG_PPPOE is not set +# CONFIG_PPPOATM is not set # CONFIG_SLIP is not set # @@ -554,6 +562,7 @@ CONFIG_APPLE_AIRPORT=m # CONFIG_PLX_HERMES is not set CONFIG_PCI_HERMES=m +# CONFIG_TMD_HERMES is not set # # Wireless Pcmcia cards support @@ -598,6 +607,21 @@ # CONFIG_AIRONET4500_CS is not set # +# ATM drivers +# +# CONFIG_ATM_TCP is not set +# CONFIG_ATM_LANAI is not set +# CONFIG_ATM_ENI is not set +# CONFIG_ATM_FIRESTREAM is not set +# CONFIG_ATM_ZATM is not set +# CONFIG_ATM_NICSTAR is not set +# CONFIG_ATM_IDT77252 is not set +# CONFIG_ATM_AMBASSADOR is not set +# CONFIG_ATM_HORIZON is not set +# CONFIG_ATM_IA is not set +# CONFIG_ATM_FORE200E_MAYBE is not set + +# # Amateur Radio support # # CONFIG_HAMRADIO is not set @@ -613,7 +637,7 @@ CONFIG_IRLAN=m CONFIG_IRNET=m CONFIG_IRCOMM=m -# CONFIG_IRDA_ULTRA is not set +CONFIG_IRDA_ULTRA=y # # IrDA options @@ -630,7 +654,7 @@ # SIR device drivers # CONFIG_IRTTY_SIR=m -# CONFIG_IRPORT_SIR is not set +CONFIG_IRPORT_SIR=m # # Dongle support @@ -652,7 +676,78 @@ # # ISDN subsystem # -# CONFIG_ISDN is not set +CONFIG_ISDN=m +CONFIG_ISDN_BOOL=y +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_ISDN_PPP_BSDCOMP=m +# CONFIG_ISDN_AUDIO is not set + +# +# ISDN feature submodules +# +# CONFIG_ISDN_DRV_LOOP is not set +# CONFIG_ISDN_DIVERSION is not set + +# +# low-level hardware drivers +# + +# +# Passive ISDN cards +# +CONFIG_ISDN_DRV_HISAX=m +CONFIG_ISDN_HISAX=y + +# +# D-channel protocol features +# +# CONFIG_HISAX_EURO is not set +# CONFIG_HISAX_1TR6 is not set +# CONFIG_HISAX_NI1 is not set +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +# CONFIG_HISAX_TELESPCI is not set +# CONFIG_HISAX_S0BOX is not set +# CONFIG_HISAX_FRITZPCI is not set +# CONFIG_HISAX_AVM_A1_PCMCIA is not set +# CONFIG_HISAX_ELSA is not set +# CONFIG_HISAX_DIEHLDIVA is not set +# CONFIG_HISAX_SEDLBAUER is not set +# CONFIG_HISAX_NETJET is not set +# CONFIG_HISAX_NETJET_U is not set +# CONFIG_HISAX_NICCY is not set +# CONFIG_HISAX_BKM_A4T is not set +# CONFIG_HISAX_SCT_QUADRO is not set +CONFIG_HISAX_GAZEL=y +# CONFIG_HISAX_HFC_PCI is not set +# CONFIG_HISAX_W6692 is not set +# CONFIG_HISAX_HFC_SX is not set +# CONFIG_HISAX_ENTERNOW_PCI is not set +# CONFIG_HISAX_DEBUG is not set +# CONFIG_HISAX_SEDLBAUER_CS is not set +# CONFIG_HISAX_ELSA_CS is not set +# CONFIG_HISAX_AVM_A1_CS is not set +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_FRITZ_PCIPNP is not set +# CONFIG_USB_AUERISDN is not set + +# +# Active ISDN cards +# +# CONFIG_ISDN_DRV_ICN is not set +# CONFIG_ISDN_DRV_PCBIT is not set +# CONFIG_ISDN_DRV_SC is not set +# CONFIG_ISDN_DRV_ACT2000 is not set +# CONFIG_ISDN_DRV_EICON is not set +# CONFIG_ISDN_DRV_TPAM is not set +# CONFIG_ISDN_CAPI is not set +# CONFIG_HYSDN is not set +# CONFIG_HYSDN_CAPI is not set # # Old CD-ROM drivers (not SCSI, not IDE) @@ -669,7 +764,7 @@ # CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_RIVA is not set +CONFIG_FB_RIVA=y # CONFIG_FB_CLGEN is not set # CONFIG_FB_PM2 is not set # CONFIG_FB_PM3 is not set @@ -682,16 +777,7 @@ CONFIG_FB_IMSTT=y # CONFIG_FB_S3TRIO is not set # CONFIG_FB_VGA16 is not set -CONFIG_FB_MATROX=y -CONFIG_FB_MATROX_MILLENIUM=y -CONFIG_FB_MATROX_MYSTIQUE=y -# CONFIG_FB_MATROX_G450 is not set -CONFIG_FB_MATROX_G100A=y -CONFIG_FB_MATROX_G100=y -# CONFIG_FB_MATROX_I2C is not set -# CONFIG_FB_MATROX_MAVEN is not set -CONFIG_FB_MATROX_PROC=y -# CONFIG_FB_MATROX_MULTIHEAD is not set +# CONFIG_FB_MATROX is not set CONFIG_FB_ATY=y CONFIG_FB_ATY_GX=y CONFIG_FB_ATY_CT=y @@ -742,11 +828,11 @@ CONFIG_PMAC_BACKLIGHT=y CONFIG_MAC_FLOPPY=y CONFIG_MAC_SERIAL=y -# CONFIG_SERIAL_CONSOLE is not set +CONFIG_SERIAL_CONSOLE=y CONFIG_ADB=y CONFIG_ADB_MACIO=y CONFIG_INPUT_ADBHID=y -CONFIG_MAC_ADBKEYCODES=y +# CONFIG_MAC_ADBKEYCODES is not set CONFIG_MAC_EMUMOUSEBTN=y CONFIG_MAC_HID=y # CONFIG_ANSLCD is not set @@ -756,21 +842,23 @@ # CONFIG_VT=y CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=m +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 +# CONFIG_BRIQ_PANEL is not set # # I2C support # -CONFIG_I2C=m +CONFIG_I2C=y # CONFIG_I2C_ALGOBIT is not set # CONFIG_I2C_ALGOPCF is not set -CONFIG_I2C_KEYWEST=m -CONFIG_I2C_CHARDEV=m -CONFIG_I2C_PROC=m +CONFIG_I2C_KEYWEST=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_PROC=y # # Mice @@ -842,19 +930,59 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set -# CONFIG_AGP is not set +CONFIG_AGP=m +# CONFIG_AGP_INTEL is not set +# CONFIG_AGP_I810 is not set +# CONFIG_AGP_VIA is not set +# CONFIG_AGP_AMD is not set +# CONFIG_AGP_AMD_8151 is not set +# CONFIG_AGP_SIS is not set +# CONFIG_AGP_ALI is not set +# CONFIG_AGP_SWORKS is not set +CONFIG_AGP_UNINORTH=y # CONFIG_DRM is not set # # PCMCIA character devices # -# CONFIG_PCMCIA_SERIAL_CS is not set +CONFIG_PCMCIA_SERIAL_CS=m # CONFIG_SYNCLINK_CS is not set # # Multimedia devices # -# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_DEV=m + +# +# Video For Linux +# +# CONFIG_VIDEO_PROC_FS is not set +# CONFIG_I2C_PARPORT is not set + +# +# Video Adapters +# +# CONFIG_VIDEO_BT848 is not set +# CONFIG_VIDEO_PMS is not set +CONFIG_VIDEO_PLANB=m +# CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_TUNER_3036 is not set +# CONFIG_VIDEO_STRADIS is not set +# CONFIG_VIDEO_ZORAN is not set +# CONFIG_VIDEO_ZORAN_BUZ is not set +# CONFIG_VIDEO_ZORAN_DC10 is not set +# CONFIG_VIDEO_ZORAN_LML33 is not set +# CONFIG_VIDEO_ZR36120 is not set +# CONFIG_VIDEO_MEYE is not set + +# +# Radio Adapters +# +# CONFIG_RADIO_GEMTEK_PCI is not set +# CONFIG_RADIO_MAXIRADIO is not set +# CONFIG_RADIO_MAESTRO is not set +# CONFIG_RADIO_MIROPCM20 is not set # # File systems @@ -871,6 +999,7 @@ CONFIG_HFS_FS=m # CONFIG_BEFS_FS is not set # CONFIG_BEFS_DEBUG is not set +CONFIG_HFSPLUS_FS=m # CONFIG_BFS_FS is not set CONFIG_EXT3_FS=y CONFIG_JBD=y @@ -897,7 +1026,7 @@ # CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y -CONFIG_DEVFS_FS=y +# CONFIG_DEVFS_FS is not set # CONFIG_DEVFS_MOUNT is not set # CONFIG_DEVFS_DEBUG is not set CONFIG_DEVPTS_FS=y @@ -963,7 +1092,7 @@ # Native Language Support # CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set +CONFIG_NLS_CODEPAGE_437=m # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set # CONFIG_NLS_CODEPAGE_850 is not set @@ -999,7 +1128,7 @@ # CONFIG_NLS_ISO8859_15 is not set # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set +CONFIG_NLS_UTF8=m # # Sound @@ -1007,8 +1136,6 @@ CONFIG_SOUND=m CONFIG_DMASOUND_PMAC=m CONFIG_DMASOUND=m -CONFIG_I2C=m -CONFIG_I2C_KEYWEST=m # CONFIG_SOUND_ALI5455 is not set # CONFIG_SOUND_BT878 is not set # CONFIG_SOUND_CMPCI is not set @@ -1056,20 +1183,20 @@ # # USB Device Class drivers # -# CONFIG_USB_AUDIO is not set +CONFIG_USB_AUDIO=m # CONFIG_USB_EMI26 is not set # CONFIG_USB_BLUETOOTH is not set # CONFIG_USB_MIDI is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_SDDR55 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set +CONFIG_USB_STORAGE=m +CONFIG_USB_STORAGE_DEBUG=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_HP8200e=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y CONFIG_USB_ACM=m CONFIG_USB_PRINTER=m @@ -1078,7 +1205,7 @@ # CONFIG_USB_HID=y CONFIG_USB_HIDINPUT=y -# CONFIG_USB_HIDDEV is not set +CONFIG_USB_HIDDEV=y # CONFIG_USB_AIPTEK is not set # CONFIG_USB_WACOM is not set # CONFIG_USB_KBTAB is not set @@ -1096,10 +1223,15 @@ # # USB Multimedia devices # - -# -# Video4Linux support is needed for USB Multimedia device support -# +# CONFIG_USB_IBMCAM is not set +# CONFIG_USB_KONICAWC is not set +CONFIG_USB_OV511=m +CONFIG_USB_PWC=m +# CONFIG_USB_SE401 is not set +# CONFIG_USB_STV680 is not set +# CONFIG_USB_VICAM is not set +# CONFIG_USB_DSBR is not set +# CONFIG_USB_DABUSB is not set # # USB Network adaptors @@ -1108,7 +1240,7 @@ # CONFIG_USB_RTL8150 is not set # CONFIG_USB_KAWETH is not set # CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set +CONFIG_USB_CDCETHER=m # CONFIG_USB_USBNET is not set # @@ -1132,8 +1264,20 @@ # CONFIG_USB_SERIAL_IR is not set # CONFIG_USB_SERIAL_EDGEPORT is not set # CONFIG_USB_SERIAL_EDGEPORT_TI is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_USA28=y +CONFIG_USB_SERIAL_KEYSPAN_USA28X=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y +CONFIG_USB_SERIAL_KEYSPAN_USA19=y +CONFIG_USB_SERIAL_KEYSPAN_USA18X=y +CONFIG_USB_SERIAL_KEYSPAN_USA19W=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +CONFIG_USB_SERIAL_KEYSPAN_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y # CONFIG_USB_SERIAL_MCT_U232 is not set # CONFIG_USB_SERIAL_KLSI is not set # CONFIG_USB_SERIAL_KOBIL_SCT is not set diff -uNr linux-2.4.21/arch/ppc/configs/power3_defconfig linux-2.4.21-ben2/arch/ppc/configs/power3_defconfig --- linux-2.4.21/arch/ppc/configs/power3_defconfig 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/configs/power3_defconfig 2003-06-27 15:41:04.000000000 +0200 @@ -72,12 +72,12 @@ # CONFIG_PARPORT_SUNBPP is not set # CONFIG_PARPORT_OTHER is not set # CONFIG_PARPORT_1284 is not set -CONFIG_GEN_RTC=y +# CONFIG_PPC_RTC is not set CONFIG_PROC_DEVICETREE=y CONFIG_PPC_RTAS=y +# CONFIG_BOOTX_TEXT is not set # CONFIG_PREP_RESIDUAL is not set # CONFIG_PROC_PREPRESIDUAL is not set -CONFIG_PPCBUG_NVRAM=y # CONFIG_CMDLINE_BOOL is not set # @@ -219,7 +219,6 @@ # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set @@ -314,7 +313,6 @@ # CONFIG_DGRS is not set # CONFIG_DM9102 is not set # CONFIG_EEPRO100 is not set -# CONFIG_EEPRO100_PIO is not set # CONFIG_E100 is not set # CONFIG_LNE390 is not set # CONFIG_FEALNX is not set @@ -426,17 +424,14 @@ CONFIG_FB_MATROX=y CONFIG_FB_MATROX_MILLENIUM=y CONFIG_FB_MATROX_MYSTIQUE=y -# CONFIG_FB_MATROX_G450 is not set -CONFIG_FB_MATROX_G100A=y CONFIG_FB_MATROX_G100=y CONFIG_FB_MATROX_I2C=y # CONFIG_FB_MATROX_MAVEN is not set -CONFIG_FB_MATROX_PROC=y +# CONFIG_FB_MATROX_G450 is not set CONFIG_FB_MATROX_MULTIHEAD=y # CONFIG_FB_ATY is not set # CONFIG_FB_RADEON is not set # CONFIG_FB_ATY128 is not set -# CONFIG_FB_INTEL is not set # CONFIG_FB_SIS is not set # CONFIG_FB_NEOMAGIC is not set # CONFIG_FB_3DFX is not set @@ -495,6 +490,7 @@ # CONFIG_LP_CONSOLE is not set # CONFIG_PPDEV is not set # CONFIG_TIPAR is not set +# CONFIG_BRIQ_PANEL is not set # # I2C support @@ -557,11 +553,6 @@ # CONFIG_INPUT_GAMECON is not set # CONFIG_INPUT_TURBOGRAFX is not set # CONFIG_QIC02_TAPE is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_IPMI_PANIC_EVENT is not set -# CONFIG_IPMI_DEVICE_INTERFACE is not set -# CONFIG_IPMI_KCS is not set -# CONFIG_IPMI_WATCHDOG is not set # # Watchdog Cards @@ -765,7 +756,6 @@ # CONFIG_SOUND_PSS is not set # CONFIG_SOUND_SB is not set # CONFIG_SOUND_AWE32_SYNTH is not set -# CONFIG_SOUND_KAHLUA is not set # CONFIG_SOUND_WAVEFRONT is not set # CONFIG_SOUND_MAUI is not set # CONFIG_SOUND_YM3812 is not set @@ -806,4 +796,3 @@ CONFIG_XMON=y # CONFIG_BDI_SWITCH is not set # CONFIG_MORE_COMPILE_OPTIONS is not set -# CONFIG_BOOTX_TEXT is not set diff -uNr linux-2.4.21/arch/ppc/kernel/btext.c linux-2.4.21-ben2/arch/ppc/kernel/btext.c --- linux-2.4.21/arch/ppc/kernel/btext.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/kernel/btext.c 2003-06-27 15:41:34.000000000 +0200 @@ -42,22 +42,14 @@ static unsigned char vga_font[cmapsz]; int boot_text_mapped; +int force_printk_to_btext; boot_infos_t disp_bi; extern char *klimit; -/* - * Powermac can use btext_* after boot for xmon, - * chrp only uses it during early boot. - */ -#ifdef CONFIG_XMON -#define BTEXT __pmac -#define BTDATA __pmacdata -#else -#define BTEXT __init -#define BTDATA __initdata -#endif /* CONFIG_XMON */ +#define BTEXT +#define BTDATA /* * This is called only when we are booted via BootX. diff -uNr linux-2.4.21/arch/ppc/kernel/cpu_setup_6xx.S linux-2.4.21-ben2/arch/ppc/kernel/cpu_setup_6xx.S --- linux-2.4.21/arch/ppc/kernel/cpu_setup_6xx.S 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/kernel/cpu_setup_6xx.S 2003-06-27 15:41:06.000000000 +0200 @@ -248,12 +248,13 @@ /* Definitions for the table use to save CPU states */ #define CS_HID0 0 #define CS_HID1 4 -#define CS_MSSCR0 8 -#define CS_MSSSR0 12 -#define CS_ICTRL 16 -#define CS_LDSTCR 20 -#define CS_LDSTDB 24 -#define CS_SIZE 28 +#define CS_HID2 8 +#define CS_MSSCR0 12 +#define CS_MSSSR0 16 +#define CS_ICTRL 20 +#define CS_LDSTCR 24 +#define CS_LDSTDB 28 +#define CS_SIZE 32 .data .balign L1_CACHE_LINE_SIZE @@ -316,6 +317,13 @@ /* Backup 750FX specific registers */ mfspr r4,SPRN_HID1 stw r4,CS_HID1(r5) + /* If rev 2.x, backup HID2 */ + mfspr r3,PVR + andi. r3,r3,0xff00 + cmpi cr0,r3,0x0200 + bne 1f + mfspr r4,SPRN_HID2 + stw r4,CS_HID2(r5) 1: mtcr r7 blr @@ -395,9 +403,19 @@ sync 2: bne cr5,1f /* Restore 750FX specific registers - * that is restore PLL config & switch - * to PLL 0 + * that is restore HID2 on rev 2.x and PLL config & switch + * to PLL 0 on all */ + /* If rev 2.x, restore HID2 with low voltage bit cleared */ + mfspr r3,PVR + andi. r3,r3,0xff00 + cmpi cr0,r3,0x0200 + bne 4f + lwz r4,CS_HID2(r5) + rlwinm r4,r4,0,19,17 + mtspr SPRN_HID2,r4 + sync +4: lwz r4,CS_HID1(r5) rlwinm r5,r4,0,16,14 mtspr SPRN_HID1,r5 diff -uNr linux-2.4.21/arch/ppc/kernel/cputable.c linux-2.4.21-ben2/arch/ppc/kernel/cputable.c --- linux-2.4.21/arch/ppc/kernel/cputable.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/kernel/cputable.c 2003-06-27 15:41:06.000000000 +0200 @@ -140,16 +140,25 @@ 32, 32, __setup_cpu_750cx }, + { /* 750FX rev 1.x */ + 0xffffff00, 0x70000100, "750FX", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | + CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP | + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_NO_DPM, + COMMON_PPC, + 32, 32, + __setup_cpu_750 + }, { /* 750FX rev 2.0 must disable HID0[DPM] */ 0xffffffff, 0x70000200, "750FX", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP | - CPU_FTR_NO_DPM, + CPU_FTR_DUAL_PLL_750FX | CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NO_DPM, COMMON_PPC, 32, 32, __setup_cpu_750 }, - { /* 750FX (All revs except 2.0) */ + { /* 750FX (All revs > 2.0) */ 0xffff0000, 0x70000000, "750FX", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_HPTE_TABLE | CPU_FTR_CAN_NAP | diff -uNr linux-2.4.21/arch/ppc/kernel/gen550_dbg.c linux-2.4.21-ben2/arch/ppc/kernel/gen550_dbg.c --- linux-2.4.21/arch/ppc/kernel/gen550_dbg.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/kernel/gen550_dbg.c 2003-06-27 15:41:26.000000000 +0200 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -56,6 +57,7 @@ unsigned long serial_init(int chan, void *ignored) { unsigned long com_port; + unsigned char lcr, dlm; /* We need to find out which type io we're expecting. If it's * 'SERIAL_IO_PORT', we get an offset from the isa_io_base. @@ -78,22 +80,38 @@ /* How far apart the registers are. */ shift = rs_table[chan].iomem_reg_shift; + + /* save the LCR */ + lcr = serial_inb(com_port + (UART_LCR << shift)); /* Access baud rate */ - serial_outb(com_port + (UART_LCR << shift), 0x80); + serial_outb(com_port + (UART_LCR << shift), UART_LCR_DLAB); + dlm = serial_inb(com_port + (UART_DLM << shift)); - /* Input clock. */ - serial_outb(com_port + (UART_DLL << shift), + /* + * Test if serial port is unconfigured + * We assume that no-one uses less than 110 baud or + * less than 7 bits per character these days. + * -- paulus. + */ + if ((dlm <= 4) && (lcr & 2)) { + /* port is configured, put the old LCR back */ + serial_outb(com_port + (UART_LCR << shift), lcr); + } + else { + /* Input clock. */ + serial_outb(com_port + (UART_DLL << shift), (rs_table[chan].baud_base / SERIAL_BAUD) & 0xFF); - serial_outb(com_port + (UART_DLM << shift), - (rs_table[chan].baud_base / SERIAL_BAUD) >> 8); - /* 8 data, 1 stop, no parity */ - serial_outb(com_port + (UART_LCR << shift), 0x03); - /* RTS/DTR */ - serial_outb(com_port + (UART_MCR << shift), 0x03); + serial_outb(com_port + (UART_DLM << shift), + (rs_table[chan].baud_base / SERIAL_BAUD) >> 8); + /* 8 data, 1 stop, no parity */ + serial_outb(com_port + (UART_LCR << shift), 0x03); + /* RTS/DTR */ + serial_outb(com_port + (UART_MCR << shift), 0x03); - /* Clear & enable FIFOs */ - serial_outb(com_port + (UART_FCR << shift), 0x07); + /* Clear & enable FIFOs */ + serial_outb(com_port + (UART_FCR << shift), 0x07); + } return (com_port); } @@ -136,6 +154,13 @@ #ifdef CONFIG_SERIAL_TEXT_DEBUG void +gen550_progress_init(void) +{ + if (ppc_md.early_serial_map) + ppc_md.early_serial_map(); +} + +void gen550_progress(char *s, unsigned short hex) { volatile unsigned int progress_debugport; diff -uNr linux-2.4.21/arch/ppc/kernel/head.S linux-2.4.21-ben2/arch/ppc/kernel/head.S --- linux-2.4.21/arch/ppc/kernel/head.S 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/kernel/head.S 2003-06-27 15:41:18.000000000 +0200 @@ -1268,7 +1268,7 @@ #endif /* Copy some CPU settings from CPU 0 */ bl __restore_cpu_setup - + lis r3,-KERNELBASE@h mr r4,r24 bl identify_cpu diff -uNr linux-2.4.21/arch/ppc/kernel/irq.c linux-2.4.21-ben2/arch/ppc/kernel/irq.c --- linux-2.4.21/arch/ppc/kernel/irq.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/kernel/irq.c 2003-06-27 15:41:09.000000000 +0200 @@ -75,6 +75,10 @@ unsigned long ppc_lost_interrupts[NR_MASK_WORDS]; atomic_t ppc_n_lost_interrupts; +#ifdef CONFIG_DEBUG_SPINLOCK +int debug_long_irqlock; +#endif /* CONFIG_DEBUG_SPINLOCK */ + /* nasty hack for shared irq's since we need to do kmalloc calls but * can't very early in the boot when we need to do a request irq. * this needs to be removed. @@ -578,6 +582,24 @@ unsigned long *stack; int cpu = smp_processor_id(); +#ifdef CONFIG_XMON + xmon_printf("\n%s, CPU %d:\n", str, cpu); + xmon_printf("irq: %d [%d %d]\n", + atomic_read(&global_irq_count), + local_irq_count(0), + local_irq_count(1)); + xmon_printf("bh: %d [%d %d]\n", + atomic_read(&global_bh_count), + local_bh_count(0), + local_bh_count(1)); + stack = (unsigned long *) &str; + for (i = 40; i ; i--) { + unsigned long x = *++stack; + if (x > (unsigned long) &init_task_union && x < (unsigned long) &vsprintf) { + xmon_printf("<[%08lx]> ", x); + } + } +#endif /* CONFIG_XMON */ printk("\n%s, CPU %d:\n", str, cpu); printk("irq: %d [%d %d]\n", atomic_read(&global_irq_count), @@ -694,6 +716,9 @@ do { do { if (loops-- == 0) { +#ifdef CONFIG_XMON + xmon_printf("get_irqlock(%d) waiting, global_irq_holder=%d\n", cpu, global_irq_holder); +#endif printk("get_irqlock(%d) waiting, global_irq_holder=%d\n", cpu, global_irq_holder); #ifdef CONFIG_XMON xmon(0); diff -uNr linux-2.4.21/arch/ppc/kernel/m8xx_setup.c linux-2.4.21-ben2/arch/ppc/kernel/m8xx_setup.c --- linux-2.4.21/arch/ppc/kernel/m8xx_setup.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/kernel/m8xx_setup.c 2003-06-27 15:41:25.000000000 +0200 @@ -43,6 +43,7 @@ #include #include #include +#include #include "ppc8xx_pic.h" diff -uNr linux-2.4.21/arch/ppc/kernel/misc.S linux-2.4.21-ben2/arch/ppc/kernel/misc.S --- linux-2.4.21/arch/ppc/kernel/misc.S 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/kernel/misc.S 2003-06-27 15:41:09.000000000 +0200 @@ -200,6 +200,59 @@ mr r4,r24 bctr +#ifdef CONFIG_CPU_FREQ_PMAC + +/* This gets called by via-pmu.c to switch the PLL selection + * on 750fx CPU. + */ +_GLOBAL(low_choose_750fx_pll) + /* Clear MSR:EE */ + mfmsr r7 + rlwinm r0,r7,0,17,15 + mtmsr r0 + + /* If switching to PLL1, disable HID0:BTIC */ + cmpli cr0,r3,0 + beq 1f + mfspr r5,HID0 + rlwinm r5,r5,0,27,25 + sync + mtspr HID0,r5 + isync + sync + +1: + /* Calc new HID1 value */ + mfspr r4,SPRN_HID1 /* Build a HID1:PS bit from parameter */ + rlwinm r5,r3,16,15,15 /* Clear out HID1:PS from value read */ + rlwinm r4,r4,0,16,14 /* Could have I used rlwimi here ? */ + or r4,r4,r5 + mtspr SPRN_HID1,r4 + + /* Store new HID1 image */ + lwz r6,PROCESSOR(r2) + slwi r6,r6,2 + addis r6,r6,nap_save_hid1@ha + stw r4,nap_save_hid1@l(r6) + + /* If switching to PLL0, enable HID0:BTIC */ + cmpli cr0,r3,0 + bne 1f + mfspr r5,HID0 + ori r5,r5,HID0_BTIC + sync + mtspr HID0,r5 + isync + sync + +1: + /* Return */ + mtmsr r7 + blr + +#endif /* CONFIG_CPU_FREQ_PMAC */ + + /* void __save_flags_ptr(unsigned long *flags) */ _GLOBAL(__save_flags_ptr) mfmsr r4 diff -uNr linux-2.4.21/arch/ppc/kernel/open_pic.c linux-2.4.21-ben2/arch/ppc/kernel/open_pic.c --- linux-2.4.21/arch/ppc/kernel/open_pic.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/kernel/open_pic.c 2003-06-27 15:41:49.000000000 +0200 @@ -594,11 +594,15 @@ void __init do_openpic_setup_cpu(void) { int i; - u32 msk = 1 << smp_hw_index[smp_processor_id()]; +#ifdef CONFIG_IRQ_ALL_CPUS + u32 msk; +#endif spin_lock(&openpic_setup_lock); #ifdef CONFIG_IRQ_ALL_CPUS + msk = 1 << smp_hw_index[smp_processor_id()]; + /* let the openpic know we want intrs. default affinity * is 0xffffffff until changed via /proc * That's how it's done on x86. If we want it differently, then @@ -656,6 +660,7 @@ 9 << OPENPIC_PRIORITY_SHIFT); } + /* * * All functions below take an offset'ed irq argument diff -uNr linux-2.4.21/arch/ppc/kernel/pci.c linux-2.4.21-ben2/arch/ppc/kernel/pci.c --- linux-2.4.21/arch/ppc/kernel/pci.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/kernel/pci.c 2003-06-27 15:41:51.000000000 +0200 @@ -1,5 +1,5 @@ /* - * Common pmac/prep/chrp pci routines. -- Cort + * Common PCI code for PPC architecture */ #include @@ -22,7 +22,7 @@ #include #include -#undef DEBUG +#define DEBUG #ifdef DEBUG #define DBG(x...) printk(x) @@ -115,7 +115,11 @@ int reg; struct pci_controller* hose = dev->sysdata; unsigned long io_offset; - + + if (dev->vendor == PCI_VENDOR_ID_APPLE && dev->device == PCI_DEVICE_ID_APPLE_KEYLARGO) { + printk("trying to reloc keylargo !! skipping\n"); + return; + } new = res->start; res->flags &= ~IORESOURCE_UNSET; if (hose && res->flags & IORESOURCE_IO) { @@ -217,7 +221,8 @@ } if (dev->device == PCI_DEVICE_ID_TI_1210 || dev->device == PCI_DEVICE_ID_TI_1211 || - dev->device == PCI_DEVICE_ID_TI_1410) { + dev->device == PCI_DEVICE_ID_TI_1410 || + dev->device == PCI_DEVICE_ID_TI_1510) { u8 val; /* 0x8c == TI122X_IRQMUX, 2 says to route the INTA signal out the MFUNC0 pin */ @@ -563,8 +568,9 @@ { struct resource *pr, *r = &dev->resource[idx]; - DBG("PCI:%s: Resource %d: %08lx-%08lx (f=%lx)\n", - dev->slot_name, idx, r->start, r->end, r->flags); + DBG("PCI:%s: Resource %d: %08lx-%08lx (f=%lx), vd: %04x, dev: %04x\n", + dev->slot_name, idx, r->start, r->end, r->flags, + dev->vendor, dev->device); pr = pci_find_parent_resource(dev, r); if (!pr || request_resource(pr, r) < 0) { printk(KERN_ERR "PCI: Cannot allocate resource region %d" @@ -1029,6 +1035,10 @@ } ranges += np; } + DBG("hose %s, pci_mem_offset: %08lx, start0: %08lx\n", + dev->name, hose->pci_mem_offset, hose->mem_resources[0].start); + DBG(" io_base_virt: %p, io_base_phys: %08lx, isa_mem_base: %08lx\n", + hose->io_base_virt, hose->io_base_phys, isa_mem_base); } /* We create the "pci-OF-bus-map" property now so it appears in the @@ -1341,6 +1351,9 @@ return PCI_SLOT(dev->devfn); } +/* Where does that come from ? Doesn't seem to be correct for us, but we + * don't use it anyway so ... -BenH. + */ void __init pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges) { diff -uNr linux-2.4.21/arch/ppc/kernel/ppc_ksyms.c linux-2.4.21-ben2/arch/ppc/kernel/ppc_ksyms.c --- linux-2.4.21/arch/ppc/kernel/ppc_ksyms.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/kernel/ppc_ksyms.c 2003-06-27 15:41:11.000000000 +0200 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -67,9 +68,10 @@ extern int pmac_newworld; extern int sys_sigreturn(struct pt_regs *regs); -long long __ashrdi3(long long, int); -long long __ashldi3(long long, int); -long long __lshrdi3(long long, int); +extern long long __ashrdi3(long long, int); +extern long long __ashldi3(long long, int); +extern long long __lshrdi3(long long, int); + int abs(int); extern unsigned char __res[]; @@ -128,7 +130,6 @@ EXPORT_SYMBOL(strcmp); EXPORT_SYMBOL(strncmp); EXPORT_SYMBOL(strcasecmp); -EXPORT_SYMBOL(__div64_32); /* EXPORT_SYMBOL(csum_partial); already in net/netsyms.c */ EXPORT_SYMBOL(csum_partial_copy_generic); @@ -192,6 +193,7 @@ EXPORT_SYMBOL(flush_icache_user_range); EXPORT_SYMBOL(flush_icache_page); EXPORT_SYMBOL(flush_dcache_page); +EXPORT_SYMBOL(local_flush_tlb_page); EXPORT_SYMBOL(xchg_u32); #ifdef CONFIG_ALTIVEC EXPORT_SYMBOL(last_task_used_altivec); @@ -288,6 +290,7 @@ EXPORT_SYMBOL_NOVERS(memscan); EXPORT_SYMBOL_NOVERS(memcmp); EXPORT_SYMBOL_NOVERS(memchr); +EXPORT_SYMBOL_NOVERS(__div64_32); EXPORT_SYMBOL(abs); @@ -314,7 +317,7 @@ EXPORT_SYMBOL(get_wchan); EXPORT_SYMBOL(console_drivers); #ifdef CONFIG_XMON -extern void xmon_printf(char *fmt, ...); +extern void xmon_printf(const char *fmt, ...); EXPORT_SYMBOL(xmon); EXPORT_SYMBOL(xmon_printf); #endif @@ -353,6 +356,10 @@ EXPORT_SYMBOL(next_mmu_context); EXPORT_SYMBOL(set_context); EXPORT_SYMBOL(handle_mm_fault); /* For MOL */ +#ifdef CONFIG_SMP +extern int *hash_table_lock; +EXPORT_SYMBOL_NOVERS(hash_table_lock); /* For MOL */ +#endif EXPORT_SYMBOL_NOVERS(disarm_decr); #ifdef CONFIG_PPC_STD_MMU EXPORT_SYMBOL(flush_hash_page); /* For MOL */ @@ -363,6 +370,10 @@ EXPORT_SYMBOL(ret_from_intercept); EXPORT_SYMBOL(cur_cpu_spec); #if defined(CONFIG_ALL_PPC) +extern int map_page(unsigned long va, unsigned long pa, int flags); + +EXPORT_SYMBOL(map_page); +EXPORT_SYMBOL(get_vm_area); extern unsigned long agp_special_page; EXPORT_SYMBOL_NOVERS(agp_special_page); #endif /* defined(CONFIG_ALL_PPC) */ diff -uNr linux-2.4.21/arch/ppc/kernel/process.c linux-2.4.21-ben2/arch/ppc/kernel/process.c --- linux-2.4.21/arch/ppc/kernel/process.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/kernel/process.c 2003-06-27 15:41:08.000000000 +0200 @@ -493,14 +493,19 @@ if (sp == NULL) asm("mr %0,1" : "=r" (sp)); printk("Call backtrace: "); + if (sp == NULL) + sp = (unsigned long *)_get_SP(); while (sp) { - if (__get_user( i, &sp[1] )) + if (__get_user(sp, (unsigned long **)sp)) + break; + if (sp == NULL) + break; + if (__get_user(i, &sp[1])) break; if (cnt++ % 7 == 0) printk("\n"); printk("%08lX ", i); - if (cnt > 32) break; - if (__get_user(sp, (unsigned long **)sp)) + if (cnt > 32) break; } printk("\n"); diff -uNr linux-2.4.21/arch/ppc/kernel/setup.c linux-2.4.21-ben2/arch/ppc/kernel/setup.c --- linux-2.4.21/arch/ppc/kernel/setup.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/kernel/setup.c 2003-06-27 15:41:07.000000000 +0200 @@ -52,6 +52,7 @@ struct ide_machdep_calls ppc_ide_md; char *sysmap; unsigned long sysmap_size; +int no_nap; /* Used with the BI_MEMSIZE bootinfo parameter to store the memory size value reported by the boot loader. */ @@ -152,7 +153,7 @@ return 0; pvr = cpu_data[i].pvr; lpj = cpu_data[i].loops_per_jiffy; - seq_printf(m, "processor\t: %lu\n", i); + seq_printf(m, "processor\t: %u\n", i); #else pvr = mfspr(PVR); lpj = loops_per_jiffy; @@ -329,6 +330,7 @@ unsigned long r6, unsigned long r7) { #ifdef CONFIG_BOOTX_TEXT + extern int force_printk_to_btext; if (boot_text_mapped) { btext_clearscreen(); btext_welcome(); @@ -415,6 +417,27 @@ } cmd_line[sizeof(cmd_line) - 1] = 0; + /* Debug stuff, do not merge ! */ +#ifdef CONFIG_ADB_PMU + if (strstr(cmd_line, "fake_sleep")) { + extern int __fake_sleep; + __fake_sleep = 1; + } +#endif /* CONFIG_ADB_PMU */ +#ifdef CONFIG_ADB + if (strstr(cmd_line, "adb_sync")) { + extern int __adb_probe_sync; + __adb_probe_sync = 1; + } +#endif /* CONFIG_ADB */ + if (strstr(cmd_line, "nol3") && cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR) + _set_L3CR(0); + if (strstr(cmd_line, "nonap")) + cur_cpu_spec[0]->cpu_features &= ~CPU_FTR_CAN_NAP; +#ifdef CONFIG_BOOTX_TEXT + if (strstr(cmd_line, "printkbtext")) + force_printk_to_btext = 1; +#endif switch (_machine) { case _MACH_Pmac: pmac_init(r3, r4, r5, r6, r7); @@ -504,6 +527,9 @@ platform_init(r3, r4, r5, r6, r7); + if (ppc_md.progress_init) + ppc_md.progress_init(); + if (ppc_md.progress) ppc_md.progress("id mach(): done", 0x200); } diff -uNr linux-2.4.21/arch/ppc/kernel/smp.c linux-2.4.21-ben2/arch/ppc/kernel/smp.c --- linux-2.4.21/arch/ppc/kernel/smp.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/kernel/smp.c 2003-06-27 15:41:32.000000000 +0200 @@ -66,6 +66,7 @@ /* Low level assembly function used to backup CPU 0 state */ extern void __save_cpu_setup(void); + /* Since OpenPIC has only 4 IPIs, we use slightly different message numbers. * * Make sure this matches openpic_request_IPIs in open_pic.c, or what shows up @@ -230,6 +231,10 @@ timeout = 1000000; while (atomic_read(&data.started) != cpus) { if (--timeout == 0) { +#ifdef CONFIG_XMON + xmon_printf("smp_call_function on cpu %d: other cpus not responding (%d)\n", + smp_processor_id(), atomic_read(&data.started)); +#endif printk("smp_call_function on cpu %d: other cpus not responding (%d)\n", smp_processor_id(), atomic_read(&data.started)); goto out; @@ -242,6 +247,10 @@ timeout = 1000000; while (atomic_read(&data.finished) != cpus) { if (--timeout == 0) { +#ifdef CONFIG_XMON + xmon_printf("smp_call_function on cpu %d: other cpus not finishing (%d/%d)\n", + smp_processor_id(), atomic_read(&data.finished), atomic_read(&data.started)); +#endif printk("smp_call_function on cpu %d: other cpus not finishing (%d/%d)\n", smp_processor_id(), atomic_read(&data.finished), atomic_read(&data.started)); goto out; diff -uNr linux-2.4.21/arch/ppc/kernel/traps.c linux-2.4.21-ben2/arch/ppc/kernel/traps.c --- linux-2.4.21/arch/ppc/kernel/traps.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/kernel/traps.c 2003-06-27 15:41:21.000000000 +0200 @@ -85,14 +85,25 @@ void die(const char * str, struct pt_regs * fp, long err) { +#ifdef CONFIG_BOOTX_TEXT + extern int force_printk_to_btext; +#endif console_verbose(); spin_lock_irq(&die_lock); +#ifdef CONFIG_BOOTX_TEXT + force_printk_to_btext = 1; +#endif #ifdef CONFIG_PMAC_BACKLIGHT - set_backlight_enable(1); - set_backlight_level(BACKLIGHT_MAX); -#endif + if (_machine == _MACH_Pmac) { + set_backlight_enable(1); + set_backlight_level(BACKLIGHT_MAX); + } +#endif printk("Oops: %s, sig: %ld\n", str, err); show_regs(fp); +#ifdef CONFIG_BOOTX_TEXT + force_printk_to_btext = 0; +#endif spin_unlock_irq(&die_lock); /* do_exit() should take care of panic'ing from an interrupt * context so we don't handle it here @@ -153,9 +164,11 @@ --nip; rb = (*nip >> 11) & 0x1f; +#if 0 printk(KERN_DEBUG "%s bad port %lx at %p\n", (*nip & 0x100)? "OUT to": "IN from", regs->gpr[rb] - _IO_BASE, nip); +#endif regs->nip = fixup; return 1; } diff -uNr linux-2.4.21/arch/ppc/lib/locks.c linux-2.4.21-ben2/arch/ppc/lib/locks.c --- linux-2.4.21/arch/ppc/lib/locks.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/lib/locks.c 2003-06-27 15:41:01.000000000 +0200 @@ -15,6 +15,14 @@ #if SPINLOCK_DEBUG +/* Route debug output to xmon when possible, there are more chances + * for it to work than the console + */ +#ifdef CONFIG_XMON +extern void xmon_printf(const char* fmt,...); +#define printk xmon_printf +#endif + #undef INIT_STUCK #define INIT_STUCK 200000000 /*0xffffffff*/ diff -uNr linux-2.4.21/arch/ppc/mm/fault.c linux-2.4.21-ben2/arch/ppc/mm/fault.c --- linux-2.4.21/arch/ppc/mm/fault.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/mm/fault.c 2003-06-27 15:41:48.000000000 +0200 @@ -96,7 +96,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long error_code) { - struct vm_area_struct * vma; + struct vm_area_struct * vma, * prev_vma; struct mm_struct *mm = current->mm; siginfo_t info; int code = SEGV_MAPERR; @@ -177,7 +177,8 @@ && (!user_mode(regs) || !store_updates_sp(regs))) goto bad_area; } - if (expand_stack(vma, address)) + vma = find_vma_prev(mm, address, &prev_vma); + if (expand_stack(vma, address, prev_vma)) goto bad_area; good_area: diff -uNr linux-2.4.21/arch/ppc/mm/init.c linux-2.4.21-ben2/arch/ppc/mm/init.c --- linux-2.4.21/arch/ppc/mm/init.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/mm/init.c 2003-06-27 15:41:03.000000000 +0200 @@ -457,6 +457,17 @@ high_memory = (void *) __va(PPC_MEMSTART + total_lowmem); num_physpages = max_mapnr; /* RAM is assumed contiguous */ + /* Sanity check: did ioremap_bot stomp over vmalloc space ? We keep + * a minimal 16Mb guard though if you only have 16Mb left, you'll + * probably run into trouble, so we also printk something if you + * have less than 64Mb. This is meant to help diagnosing such problems + * as debugging it can be really painful. --BenH. + */ + if (VMALLOC_END < (VMALLOC_START + 0x01000000UL)) + panic("Argh ! Virtual space exhausted !"); + if (VMALLOC_END < (VMALLOC_START + 0x04000000UL)) + printk(KERN_WARNING "Warning ! Virtual space small !"); + totalram_pages += free_all_bootmem(); #ifdef CONFIG_BLK_DEV_INITRD diff -uNr linux-2.4.21/arch/ppc/mm/pgtable.c linux-2.4.21-ben2/arch/ppc/mm/pgtable.c --- linux-2.4.21/arch/ppc/mm/pgtable.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/mm/pgtable.c 2003-06-27 15:41:25.000000000 +0200 @@ -238,7 +238,7 @@ printk(KERN_INFO "Memory BAT mapping: BAT2=%ldMb, BAT3=%ldMb," " residual: %ldMb\n", __bat2 >> 20, __bat3 >> 20, - (total_lowmem - (__bat2 - __bat3)) >> 20); + (total_memory - (__bat2 - __bat3)) >> 20); /* On SMP, we limit the lowmem to the area mapped with BATs. * We also assume nobody will do SMP with 601s diff -uNr linux-2.4.21/arch/ppc/platforms/Makefile linux-2.4.21-ben2/arch/ppc/platforms/Makefile --- linux-2.4.21/arch/ppc/platforms/Makefile 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/platforms/Makefile 2003-06-27 15:41:20.000000000 +0200 @@ -41,6 +41,9 @@ prep_time.o prep_setup.o pmac_sleep.o \ pmac_nvram.o obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o +ifeq ($(CONFIG_ALL_PPC),y) +obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o +endif obj-$(CONFIG_PPC_RTAS) += error_log.o proc_rtas.o obj-$(CONFIG_PREP_RESIDUAL) += residual.o obj-$(CONFIG_GEMINI) += gemini_pci.o gemini_setup.o gemini_prom.o diff -uNr linux-2.4.21/arch/ppc/platforms/pmac_cpufreq.c linux-2.4.21-ben2/arch/ppc/platforms/pmac_cpufreq.c --- linux-2.4.21/arch/ppc/platforms/pmac_cpufreq.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/arch/ppc/platforms/pmac_cpufreq.c 2003-06-27 15:41:35.000000000 +0200 @@ -0,0 +1,350 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG_FREQ + +extern void low_choose_750fx_pll(int pll); +extern void low_sleep_handler(void); +extern void openpic_sleep_save_intrs(void); +extern void openpic_sleep_restore_intrs(void); +extern void enable_kernel_altivec(void); +extern void enable_kernel_fp(void); + +static unsigned int low_freq; +static unsigned int hi_freq; +static unsigned int cur_freq; +static int cpufreq_uses_pmu; + +#define PMAC_CPU_LOW_SPEED 1 +#define PMAC_CPU_HIGH_SPEED 0 + +static inline void +wakeup_decrementer(void) +{ + set_dec(tb_ticks_per_jiffy); + /* No currently-supported powerbook has a 601, + * so use get_tbl, not native + */ + last_jiffy_stamp(0) = tb_last_stamp = get_tbl(); +} + +#ifdef DEBUG_FREQ +static inline void +debug_calc_bogomips(void) +{ + /* This will cause a recalc of bogomips and display the + * result. We backup/restore the value to avoid affecting the + * core cpufreq framework's own calculation. + */ + extern void calibrate_delay(void); + + unsigned long save_lpj = loops_per_jiffy; + calibrate_delay(); + loops_per_jiffy = save_lpj; +} +#endif + +/* Switch CPU speed under 750FX CPU control + */ +static int __pmac +cpu_750fx_cpu_speed(int low_speed) +{ +#ifdef DEBUG_FREQ + printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); +#endif + low_choose_750fx_pll(low_speed); +#ifdef DEBUG_FREQ + printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); + debug_calc_bogomips(); +#endif + + return 0; +} + +/* Switch CPU speed under PMU control + */ +static int __pmac +pmu_set_cpu_speed(unsigned int low_speed) +{ + struct adb_request req; + unsigned long save_l2cr; + unsigned long save_l3cr; + +#ifdef DEBUG_FREQ + printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); +#endif + /* Disable all interrupt sources on openpic */ + openpic_sleep_save_intrs(); + + /* Make sure the PMU is idle */ + pmu_suspend(); + + /* Make sure the decrementer won't interrupt us */ + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + /* Make sure any pending DEC interrupt occuring while we did + * the above didn't re-enable the DEC */ + mb(); + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + + /* We can now disable MSR_EE */ + local_irq_disable(); + + /* Giveup the FPU & vec */ + enable_kernel_fp(); + +#ifdef CONFIG_ALTIVEC + if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC) + enable_kernel_altivec(); +#endif /* CONFIG_ALTIVEC */ + + /* Save & disable L2 and L3 caches */ + save_l3cr = _get_L3CR(); /* (returns -1 if not available) */ + save_l2cr = _get_L2CR(); /* (returns -1 if not available) */ + if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0) + _set_L3CR(save_l3cr & 0x7fffffff); + if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0) + _set_L2CR(save_l2cr & 0x7fffffff); + + /* Send the new speed command. My assumption is that this command + * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep + */ + pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed); + while (!req.complete) + pmu_poll(); + + pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1); + + low_sleep_handler(); + + pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0); + + /* Restore L2 cache */ + if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0) + _set_L2CR(save_l2cr); + /* Restore L3 cache */ + if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0) + _set_L3CR(save_l3cr); + + /* Restore userland MMU context */ + set_context(current->active_mm->context, current->active_mm->pgd); + +#ifdef DEBUG_FREQ + printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); +#endif + + /* Restore decrementer */ + wakeup_decrementer(); + + /* Restore interrupts */ + openpic_sleep_restore_intrs(); + + pmu_resume(); + + /* Let interrupts flow again ... */ + local_irq_enable(); + +#ifdef DEBUG_FREQ + debug_calc_bogomips(); +#endif + + return 0; +} + +static int __pmac +do_set_cpu_speed(int speed_mode) +{ + struct cpufreq_freqs freqs; + int rc; + + freqs.old = cur_freq; + freqs.new = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq; + freqs.cpu = CPUFREQ_ALL_CPUS; + + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + if (cpufreq_uses_pmu) + rc = pmu_set_cpu_speed(speed_mode); + else + rc = cpu_750fx_cpu_speed(speed_mode); + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + cur_freq = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq; + + return rc; +} + +static int __pmac +pmac_cpufreq_verify(struct cpufreq_policy *policy) +{ + if (!policy) + return -EINVAL; + + policy->cpu = 0; /* UP only */ + + cpufreq_verify_within_limits(policy, low_freq, hi_freq); + + if ((policy->min > low_freq) && + (policy->max < hi_freq)) + policy->max = hi_freq; + + return 0; +} + +static int __pmac +pmac_cpufreq_setpolicy(struct cpufreq_policy *policy) +{ + int rc; + + if (!policy) + return -EINVAL; + if (policy->min > low_freq) + rc = do_set_cpu_speed(PMAC_CPU_HIGH_SPEED); + else if (policy->max < hi_freq) + rc = do_set_cpu_speed(PMAC_CPU_LOW_SPEED); + else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) + rc = do_set_cpu_speed(PMAC_CPU_LOW_SPEED); + else + rc = do_set_cpu_speed(PMAC_CPU_HIGH_SPEED); + + return rc; +} + +unsigned int __pmac +pmac_get_cur_cpufreq(void) +{ + return cur_freq; +} + + +/* Currently, we support the following machines: + * + * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz) + * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz) + * - iBook2 500 (PMU based, 400Mhz & 500Mhz) + * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage) + */ +static int __init +pmac_cpufreq_setup(void) +{ + struct device_node *cpunode; + struct cpufreq_driver *driver; + u32 *value; + int has_freq_ctl = 0; + int rc; + + memset(&driver, 0, sizeof(driver)); + + /* Assume only one CPU */ + cpunode = find_type_devices("cpu"); + if (!cpunode) + goto out; + + /* Get current cpu clock freq */ + value = (u32 *)get_property(cpunode, "clock-frequency", NULL); + if (!value) + goto out; + cur_freq = (*value) / 1000; + + /* Check for newer machines */ + if (machine_is_compatible("PowerBook3,4") || + machine_is_compatible("PowerBook3,5") || + machine_is_compatible("MacRISC3")) { + value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL); + if (!value) + goto out; + low_freq = (*value) / 1000; + /* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree + * here */ + if (low_freq < 100000) + low_freq *= 10; + + value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL); + if (!value) + goto out; + hi_freq = (*value) / 1000; + has_freq_ctl = 1; + cpufreq_uses_pmu = 1; + } + /* Else check for iBook2 500 */ + else if (machine_is_compatible("PowerBook4,1")) { + /* We only know about 500Mhz model */ + if (cur_freq < 450000 || cur_freq > 550000) + goto out; + hi_freq = cur_freq; + low_freq = 400000; + has_freq_ctl = 1; + cpufreq_uses_pmu = 1; + } + /* Else check for TiPb 500 */ + else if (machine_is_compatible("PowerBook3,2")) { + /* We only know about 500Mhz model */ + if (cur_freq < 450000 || cur_freq > 550000) + goto out; + hi_freq = cur_freq; + low_freq = 300000; + has_freq_ctl = 1; + cpufreq_uses_pmu = 1; + } + /* Else check for 750FX */ + else if (PVR_VER(mfspr(PVR)) == 0x7000) { + if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) + goto out; + hi_freq = cur_freq; + value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL); + if (!value) + goto out; + low_freq = (*value) / 1000; + cpufreq_uses_pmu = 0; + has_freq_ctl = 1; + } +out: + if (!has_freq_ctl) + return -ENODEV; + + /* initialization of main "cpufreq" code*/ + driver = kmalloc(sizeof(struct cpufreq_driver) + + NR_CPUS * sizeof(struct cpufreq_policy), GFP_KERNEL); + if (!driver) + return -ENOMEM; + + driver->policy = (struct cpufreq_policy *) (driver + 1); + +#ifdef CONFIG_CPU_FREQ_24_API + driver->cpu_min_freq[0] = low_freq; + driver->cpu_cur_freq[0] = cur_freq; +#endif + + driver->verify = &pmac_cpufreq_verify; + driver->setpolicy = &pmac_cpufreq_setpolicy; + + driver->policy[0].cpu = 0; + driver->policy[0].min = low_freq; + driver->policy[0].max = cur_freq; + driver->policy[0].max_cpu_freq = hi_freq; + driver->policy[0].policy = (cur_freq == low_freq) ? + CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE; + + rc = cpufreq_register(driver); + if (rc) + kfree(driver); + return rc; +} + +__initcall(pmac_cpufreq_setup); + diff -uNr linux-2.4.21/arch/ppc/platforms/pmac_feature.c linux-2.4.21-ben2/arch/ppc/platforms/pmac_feature.c --- linux-2.4.21/arch/ppc/platforms/pmac_feature.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/platforms/pmac_feature.c 2003-06-27 15:41:36.000000000 +0200 @@ -1157,9 +1157,6 @@ macio->type != macio_intrepid) return -ENODEV; - /* XXX Fix handling of 3rd USB controller in Intrepid, move the - * port connect stuff (KL4_*) to the sleep code eventually - */ prop = (char *)get_property(node, "AAPL,clock-id", NULL); if (!prop) return -ENODEV; @@ -1167,6 +1164,8 @@ number = 0; else if (strncmp(prop, "usb1u148", 8) == 0) number = 2; + else if (strncmp(prop, "usb2u248", 8) == 0) + number = 4; else return -ENODEV; @@ -1183,44 +1182,79 @@ mdelay(1); LOCK(flags); MACIO_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE); - } else { + } else if (number == 2) { MACIO_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1)); UNLOCK(flags); (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); LOCK(flags); MACIO_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE); + } else if (number == 4) { + MACIO_BIC(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1)); + UNLOCK(flags); + (void)MACIO_IN32(KEYLARGO_FCR1); + mdelay(1); + LOCK(flags); + MACIO_BIS(KEYLARGO_FCR0, KL1_USB2_CELL_ENABLE); + } + if (number < 4) { + reg = MACIO_IN32(KEYLARGO_FCR4); + reg &= ~(KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) | + KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number)); + reg &= ~(KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) | + KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1)); + MACIO_OUT32(KEYLARGO_FCR4, reg); + (void)MACIO_IN32(KEYLARGO_FCR4); + udelay(10); + } else { + reg = MACIO_IN32(KEYLARGO_FCR3); + reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) | + KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0)); + reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) | + KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1)); + MACIO_OUT32(KEYLARGO_FCR3, reg); + (void)MACIO_IN32(KEYLARGO_FCR3); + udelay(10); } - reg = MACIO_IN32(KEYLARGO_FCR4); - reg &= ~(KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) | - KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number)); - reg &= ~(KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) | - KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1)); - MACIO_OUT32(KEYLARGO_FCR4, reg); - (void)MACIO_IN32(KEYLARGO_FCR4); - udelay(10); } else { /* Turn OFF */ - reg = MACIO_IN32(KEYLARGO_FCR4); - reg |= KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) | - KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number); - reg |= KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) | - KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1); - MACIO_OUT32(KEYLARGO_FCR4, reg); - (void)MACIO_IN32(KEYLARGO_FCR4); - udelay(1); + if (number < 4) { + reg = MACIO_IN32(KEYLARGO_FCR4); + reg |= KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) | + KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number); + reg |= KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) | + KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1); + MACIO_OUT32(KEYLARGO_FCR4, reg); + (void)MACIO_IN32(KEYLARGO_FCR4); + udelay(1); + } else { + reg = MACIO_IN32(KEYLARGO_FCR3); + reg |= KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) | + KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0); + reg |= KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) | + KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1); + MACIO_OUT32(KEYLARGO_FCR3, reg); + (void)MACIO_IN32(KEYLARGO_FCR3); + udelay(1); + } if (number == 0) { MACIO_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE); (void)MACIO_IN32(KEYLARGO_FCR0); udelay(1); MACIO_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1)); (void)MACIO_IN32(KEYLARGO_FCR0); - } else { + } else if (number == 2) { MACIO_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE); (void)MACIO_IN32(KEYLARGO_FCR0); udelay(1); MACIO_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1)); (void)MACIO_IN32(KEYLARGO_FCR0); + } else if (number == 4) { + MACIO_BIC(KEYLARGO_FCR1, KL1_USB2_CELL_ENABLE); + (void)MACIO_IN32(KEYLARGO_FCR1); + udelay(1); + MACIO_BIS(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1)); + (void)MACIO_IN32(KEYLARGO_FCR1); } udelay(1); } @@ -1928,10 +1962,22 @@ PMAC_TYPE_RACKMAC, rackmac_features, 0, }, + { "RackMac1,2", "XServe rev. 2", + PMAC_TYPE_RACKMAC, rackmac_features, + 0, + }, { "PowerMac3,6", "PowerMac G4 Windtunnel", PMAC_TYPE_WINDTUNNEL, rackmac_features, 0, }, + { "PowerBook5,1", "PowerBook G4 17\"", + PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, + PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, + }, + { "PowerBook6,1", "PowerBook G4 12\"", + PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, + PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, + }, }; /* @@ -2028,8 +2074,8 @@ pmac_mb.features = pangea_features; break; case macio_intrepid: - pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA; - pmac_mb.model_name = "Unknown Pangea-based"; + pmac_mb.model_id = PMAC_TYPE_UNKNOWN_INTREPID; + pmac_mb.model_name = "Unknown Intrepid-based"; pmac_mb.features = intrepid_features; break; default: diff -uNr linux-2.4.21/arch/ppc/platforms/pmac_pci.c linux-2.4.21-ben2/arch/ppc/platforms/pmac_pci.c --- linux-2.4.21/arch/ppc/platforms/pmac_pci.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/platforms/pmac_pci.c 2003-06-27 15:41:25.000000000 +0200 @@ -314,6 +314,51 @@ early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val); } +/* + * Some Apple desktop machines have a NEC PD720100A USB2 controller + * on the motherboard. Open Firmware, on these, will disable the + * EHCI part of it so it behaves like a pair of OHCI's. This fixup + * code re-enables it ;) + */ +static void __init +fixup_nec_usb2(void) +{ + struct device_node *nec; + + for (nec = find_devices("usb"); nec != NULL; nec = nec->next) { + struct pci_controller *hose; + u32 data, *prop; + u8 bus, devfn; + + prop = (u32 *)get_property(nec, "vendor-id", NULL); + if (prop == NULL) + continue; + if (0x1033 != *prop) + continue; + prop = (u32 *)get_property(nec, "device-id", NULL); + if (prop == NULL) + continue; + if (0x0035 != *prop) + continue; + prop = (u32 *)get_property(nec, "reg", 0); + if (prop == NULL) + continue; + devfn = (prop[0] >> 8) & 0xff; + bus = (prop[0] >> 16) & 0xff; + if (PCI_FUNC(devfn) != 0) + continue; + hose = pci_find_hose_for_OF_device(nec); + if (!hose) + continue; + printk("Found NEC PD720100A USB2 chip, enabling EHCI...\n"); + early_read_config_dword(hose, bus, devfn, 0xe4, &data); + data &= ~1UL; + early_write_config_dword(hose, bus, devfn, 0xe4, data); + early_write_config_byte(hose, bus, devfn | 2, PCI_INTERRUPT_LINE, + nec->intrs[0].line); + } +} + void __init pmac_find_bridges(void) { @@ -321,6 +366,7 @@ add_bridges(find_devices("chaos")); add_bridges(find_devices("pci")); init_p2pbridge(); + fixup_nec_usb2(); } #define GRACKLE_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \ diff -uNr linux-2.4.21/arch/ppc/platforms/pmac_setup.c linux-2.4.21-ben2/arch/ppc/platforms/pmac_setup.c --- linux-2.4.21/arch/ppc/platforms/pmac_setup.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/platforms/pmac_setup.c 2003-06-27 15:41:05.000000000 +0200 @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -151,6 +152,14 @@ struct device_node *cpu_node; int *fp, s; +#ifdef CONFIG_CPU_FREQ_PMAC + extern unsigned int pmac_get_cur_cpufreq(void); + unsigned int freq = pmac_get_cur_cpufreq(); + if (freq != 0) { + seq_printf(m, "clock\t\t: %dMHz\n", freq/1000); + return 0; + } +#endif /* CONFIG_CPU_FREQ_PMAC */ cpu_node = find_type_devices("cpu"); if (!cpu_node) return 0; @@ -197,12 +206,27 @@ } seq_printf(m, "\n"); } + pp = (char *) get_property(np, "scb#", &plen); + if (pp != NULL) + seq_printf(m, "board revision\t: %08x\n", *((int *)pp)); } else seq_printf(m, "PowerMac\n"); /* print parsed model */ seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname); seq_printf(m, "pmac flags\t: %08x\n", mbflags); +#if 0 +{ + extern long nap_return_count; + extern long nap_enter_count; + extern long nap_save_msscr0; + extern long dbg_nap_ret; + seq_printf(m, "nap_return_count: %d\n", nap_return_count); + seq_printf(m, "nap_enter_count\t: %d\n", nap_enter_count); + seq_printf(m, "nap_save_msscr0\t: %x\n", nap_save_msscr0); + seq_printf(m, "dbg_nap_ret\t: %x\n", dbg_nap_ret); +} +#endif /* find l2 cache info */ np = find_devices("l2-cache"); @@ -309,6 +333,14 @@ sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000); ohare_init(); + /* Check & display some CPU config registers for diagnostic */ + if (pvr == 0x8000 || pvr == 0x8001) { /* 745x */ + printk(KERN_INFO "CPU MSCCR0 : 0x%08x\n", mfspr(SPRN_MSSCR0)); + printk(KERN_INFO "CPU HID1 : 0x%08x\n", mfspr(SPRN_HID1)); + } + if (pvr == 0x0008 || pvr == 0x7000) /* 750's */ + printk(KERN_INFO "CPU HID1 : 0x%08x\n", mfspr(SPRN_HID1)); + /* Lookup PCI hosts */ pmac_find_bridges(); @@ -329,6 +361,9 @@ } } +#if 0 + printk("MSSCR0: %x\n", mfspr(SPRN_MSSCR0)); +#endif if (ppc_override_l2cr) printk(KERN_INFO "L2CR overriden (0x%x), backside cache is %s\n", ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000) @@ -823,6 +858,12 @@ #endif /* CONFIG_VT */ } +static int __pmac +pmac_ide_reserved_hwifs(void) +{ + return 0; +} + void __init pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) @@ -864,6 +905,7 @@ select_adb_keyboard(); #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) + ppc_ide_md.reserved_hwifs = pmac_ide_reserved_hwifs; #ifdef CONFIG_BLK_DEV_IDE_PMAC ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports; ppc_ide_md.default_io_base = pmac_ide_get_base; diff -uNr linux-2.4.21/arch/ppc/platforms/pmac_sleep.S linux-2.4.21-ben2/arch/ppc/platforms/pmac_sleep.S --- linux-2.4.21/arch/ppc/platforms/pmac_sleep.S 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/platforms/pmac_sleep.S 2003-06-27 15:41:01.000000000 +0200 @@ -44,7 +44,7 @@ .text .align 5 -#if defined(CONFIG_PMAC_PBOOK) +#if defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_CPU_FREQ_PMAC) /* This gets called by via-pmu.c late during the sleep process. * The PMU was already send the sleep command and will shut us down @@ -372,7 +372,7 @@ isync rfi -#endif /* defined(CONFIG_PMAC_PBOOK) */ +#endif /* defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_CPU_FREQ) */ .data .balign L1_CACHE_LINE_SIZE diff -uNr linux-2.4.21/arch/ppc/platforms/pmac_smp.c linux-2.4.21-ben2/arch/ppc/platforms/pmac_smp.c --- linux-2.4.21/arch/ppc/platforms/pmac_smp.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/platforms/pmac_smp.c 2003-06-27 15:41:51.000000000 +0200 @@ -1,4 +1,7 @@ /* + * BK Id: %F% %I% %G% %U% %#% + */ +/* * SMP support for power macintosh. * * We support both the old "powersurge" SMP architecture @@ -414,6 +417,7 @@ */ if (smp_num_cpus < 2) goto sync_tb; + /* reset the entry point so if we get another intr we won't * try to startup again */ out_be32(psurge_start, 0x100); @@ -442,9 +446,7 @@ openpic_request_IPIs(); for (i = 1; i < ncpus; ++i) smp_hw_index[i] = i; -#ifdef CONFIG_6xx /* XXX */ powersave_nap = 0; -#endif /* Read cache setting of CPU 0 */ core99_init_caches(); } diff -uNr linux-2.4.21/arch/ppc/xmon/start.c linux-2.4.21-ben2/arch/ppc/xmon/start.c --- linux-2.4.21/arch/ppc/xmon/start.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/xmon/start.c 2003-06-27 15:41:05.000000000 +0200 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -24,16 +25,34 @@ #include #endif +#define CONFIG_XMON_FW + static volatile unsigned char *sccc, *sccd; unsigned int TXRDY, RXRDY, DLAB; extern void xmon_printf(const char *fmt, ...); static int xmon_expect(const char *str, unsigned int timeout); +extern char cmd_line[512]; static int use_screen; static int via_modem; static int xmon_use_sccb; static struct device_node *channel_node; +/* There are used when hooked via firewire */ +#ifdef CONFIG_XMON_FW +volatile unsigned int xmon_fw_outbuf_size; +volatile unsigned char xmon_fw_outbuf[1024]; +volatile unsigned int xmon_fw_oflags; +volatile unsigned int xmon_fw_iflags; +volatile unsigned int xmon_fw_idata; +#define XMON_FW_FLAGS_OUT_ENTERED 0x00000001 +#define XMON_FW_FLAGS_OUT_DATA 0x00000002 +#define XMON_FW_FLAGS_OUT_ACK 0x00000004 +#define XMON_FW_FLAGS_IN_ATTACHED 0x00000001 +#define XMON_FW_FLAGS_IN_DATA 0x00000002 +#define XMON_FW_FLAGS_IN_ACK 0x00000004 +#endif + #define TB_SPEED 25000000 static inline unsigned int readtb(void) @@ -112,7 +131,9 @@ volatile unsigned char *base; use_screen = 0; - + /* Typically used for firewire debugging */ + if (strstr(cmd_line, "xmon_noio")) + return; if (_machine == _MACH_Pmac) { struct device_node *np; unsigned long addr; @@ -236,6 +257,114 @@ #endif /* CONFIG_ADB_CUDA */ } +#if 0 +static void +bx_printf(const char* fmt, ...) +{ + static char dbgbuf[2048]; + va_list ap; + int n; + + va_start(ap, fmt); + n = vsprintf(dbgbuf, fmt, ap); + va_end(ap); + btext_drawstring(dbgbuf); +} +#endif + +#ifdef CONFIG_XMON_FW +static int +xmon_fw_write(void* ptr, int nb) +{ + char* p = (char *)ptr; + int c, i; + + while (nb && (xmon_fw_iflags & XMON_FW_FLAGS_IN_ATTACHED)) { + c = (nb > 1024) ? 1024 : nb; + memcpy((void *)xmon_fw_outbuf, p, c); + xmon_fw_outbuf_size = c; + wmb(); + xmon_fw_oflags |= XMON_FW_FLAGS_OUT_DATA; + wmb(); + for (i=0; i<1000; i++) { + rmb(); + if (xmon_fw_iflags & XMON_FW_FLAGS_IN_ACK) + break; + mdelay(1); + } + xmon_fw_oflags &= ~XMON_FW_FLAGS_OUT_DATA; + wmb(); + if ((xmon_fw_iflags & XMON_FW_FLAGS_IN_ACK) == 0) { + xmon_fw_iflags = 0; + break; + } + for (i=0; i<1000; i++) { + rmb(); + if ((xmon_fw_iflags & XMON_FW_FLAGS_IN_ACK) == 0) + break; + mdelay(1); + } + if ((xmon_fw_iflags & XMON_FW_FLAGS_IN_ACK) != 0) { + xmon_fw_iflags = 0; + break; + } + nb -= c; + p += c; + } + return (xmon_fw_iflags & XMON_FW_FLAGS_IN_ATTACHED) != 0; +} + +static int +xmon_fw_read(void* ptr, int nb) +{ + int t, on, i; + unsigned int k; + char c[3]; + char* p = (char *)ptr; + + while (nb) { + t = 0; + on = 0; + while(xmon_fw_iflags & XMON_FW_FLAGS_IN_ATTACHED) { + if (xmon_fw_iflags & XMON_FW_FLAGS_IN_DATA) + break; + if (--t < 0) { + on = 1 - on; + c[0] = on? 0xdb: 0x20; + c[1] = '\b'; + if (!xmon_fw_write(c, 2)) + break; + t = 2000000; + } + rmb(); + } + k = xmon_fw_idata & 0xff; + xmon_fw_oflags |= XMON_FW_FLAGS_OUT_ACK; + wmb(); + for (i=0; i<1000; i++) { + rmb(); + if ((xmon_fw_iflags & XMON_FW_FLAGS_IN_DATA) == 0) + break; + mdelay(1); + } + if (xmon_fw_iflags & XMON_FW_FLAGS_IN_DATA) { + xmon_fw_iflags = 0; + break; + } + xmon_fw_oflags &= ~XMON_FW_FLAGS_OUT_ACK; + wmb(); + if (on) { + c[0] = 0x20; c[1] = '\b'; + xmon_fw_write(c, 2); + } + *(p++) = k; + nb--; + } + return (xmon_fw_iflags & XMON_FW_FLAGS_IN_ATTACHED) != 0; +} + +#endif /* CONFIG_XMON_FW */ + int xmon_write(void *handle, void *ptr, int nb) { @@ -251,9 +380,17 @@ if (--lock_wait == 0) break; #endif - +#ifdef CONFIG_XMON_FW + if (xmon_fw_write(ptr, nb)) + goto out; +#endif /* CONFIG_XMON_FW */ #ifdef CONFIG_BOOTX_TEXT - if (use_screen) { +#ifdef CONFIG_MORE_DEBUG + if (1) +#else + if (use_screen) +#endif + { /* write it on the screen */ for (i = 0; i < nb; ++i) btext_drawchar(*p++); @@ -262,6 +399,9 @@ #endif if (!scc_initialized) xmon_init_scc(); + if (!sccd) + goto out; + ct = 0; for (i = 0; i < nb; ++i) { while ((*sccc & TXRDY) == 0) @@ -354,6 +494,10 @@ char *p = ptr; int i; +#ifdef CONFIG_XMON_FW + if (xmon_fw_read(ptr, nb)) + return nb; +#endif /* CONFIG_XMON_FW */ #ifdef CONFIG_BOOTX_TEXT if (use_screen) { for (i = 0; i < nb; ++i) @@ -363,6 +507,8 @@ #endif if (!scc_initialized) xmon_init_scc(); + if (sccd == NULL) + return 0; for (i = 0; i < nb; ++i) { while ((*sccc & RXRDY) == 0) do_poll_adb(); @@ -385,7 +531,8 @@ static unsigned char scc_inittab[] = { 13, 0, /* set baud rate divisor */ - 12, 1, +// 12, 1, + 12, 0, 14, 1, /* baud rate gen enable, src=rtxc */ 11, 0x50, /* clocks = br gen */ 5, 0xea, /* tx 8 bits, assert DTR & RTS */ @@ -396,6 +543,8 @@ void xmon_init_scc() { + if (sccd == NULL && channel_node == NULL) + return; if ( _machine == _MACH_chrp ) { sccd[3] = 0x83; eieio(); /* LCR = 8N1 + DLAB */ @@ -634,11 +783,19 @@ pmu_suspend(); } #endif +#ifdef CONFIG_XMON_FW + xmon_fw_oflags |= XMON_FW_FLAGS_OUT_ENTERED; + wmb(); +#endif /* CONFIG_XMON_FW */ } void xmon_leave(void) { +#ifdef CONFIG_XMON_FW + xmon_fw_oflags &= ~XMON_FW_FLAGS_OUT_ENTERED; + wmb(); +#endif /* CONFIG_XMON_FW */ #ifdef CONFIG_ADB_PMU if (_machine == _MACH_Pmac) { pmu_resume(); diff -uNr linux-2.4.21/arch/ppc/xmon/xmon.c linux-2.4.21-ben2/arch/ppc/xmon/xmon.c --- linux-2.4.21/arch/ppc/xmon/xmon.c 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc/xmon/xmon.c 2003-06-27 15:41:02.000000000 +0200 @@ -209,14 +209,16 @@ #endif /* CONFIG_SMP */ remove_bpts(); #ifdef CONFIG_PMAC_BACKLIGHT - if( setjmp(bus_error_jmp) == 0 ) { - debugger_fault_handler = handle_fault; - sync(); - set_backlight_enable(1); - set_backlight_level(BACKLIGHT_MAX); - sync(); + if (_machine == _MACH_Pmac) { + if( setjmp(bus_error_jmp) == 0 ) { + debugger_fault_handler = handle_fault; + sync(); + set_backlight_enable(1); + set_backlight_level(BACKLIGHT_MAX); + sync(); + } + debugger_fault_handler = 0; } - debugger_fault_handler = 0; #endif /* CONFIG_PMAC_BACKLIGHT */ cmd = cmds(excp); if (cmd == 's') { diff -uNr linux-2.4.21/arch/ppc64/config.in linux-2.4.21-ben2/arch/ppc64/config.in --- linux-2.4.21/arch/ppc64/config.in 2003-06-13 16:51:31.000000000 +0200 +++ linux-2.4.21-ben2/arch/ppc64/config.in 2003-06-27 15:41:32.000000000 +0200 @@ -8,6 +8,7 @@ define_bool CONFIG_GENERIC_BUST_SPINLOCK n define_bool CONFIG_GENERIC_ISA_DMA y define_bool CONFIG_HAVE_DEC_LOCK y +define_bool CONFIG_PPC_ISATIMER y mainmenu_name "64 bit PowerPC Linux Kernel Configuration" diff -uNr linux-2.4.21/arch/s390/mm/fault.c linux-2.4.21-ben2/arch/s390/mm/fault.c --- linux-2.4.21/arch/s390/mm/fault.c 2002-11-29 00:53:11.000000000 +0100 +++ linux-2.4.21-ben2/arch/s390/mm/fault.c 2003-06-27 15:41:06.000000000 +0200 @@ -210,7 +210,7 @@ goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if (expand_stack(vma, address)) + if (expand_stack(vma, address, NULL)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so diff -uNr linux-2.4.21/arch/s390x/mm/fault.c linux-2.4.21-ben2/arch/s390x/mm/fault.c --- linux-2.4.21/arch/s390x/mm/fault.c 2002-11-29 00:53:11.000000000 +0100 +++ linux-2.4.21-ben2/arch/s390x/mm/fault.c 2003-06-27 15:41:03.000000000 +0200 @@ -210,7 +210,7 @@ goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if (expand_stack(vma, address)) + if (expand_stack(vma, address, NULL)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so diff -uNr linux-2.4.21/arch/sh/mm/fault.c linux-2.4.21-ben2/arch/sh/mm/fault.c --- linux-2.4.21/arch/sh/mm/fault.c 2002-11-29 00:53:11.000000000 +0100 +++ linux-2.4.21-ben2/arch/sh/mm/fault.c 2003-06-27 15:41:34.000000000 +0200 @@ -74,7 +74,7 @@ check_stack: if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if (expand_stack(vma, start) == 0) + if (expand_stack(vma, start, NULL) == 0) goto good_area; bad_area: @@ -114,7 +114,7 @@ goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if (expand_stack(vma, address)) + if (expand_stack(vma, address, NULL)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so diff -uNr linux-2.4.21/arch/sparc/mm/fault.c linux-2.4.21-ben2/arch/sparc/mm/fault.c --- linux-2.4.21/arch/sparc/mm/fault.c 2003-06-13 16:51:32.000000000 +0200 +++ linux-2.4.21-ben2/arch/sparc/mm/fault.c 2003-06-27 15:41:16.000000000 +0200 @@ -251,7 +251,7 @@ goto good_area; if(!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if(expand_stack(vma, address)) + if(expand_stack(vma, address, NULL)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so @@ -498,7 +498,7 @@ goto good_area; if(!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; - if(expand_stack(vma, address)) + if(expand_stack(vma, address, NULL)) goto bad_area; good_area: info.si_code = SEGV_ACCERR; diff -uNr linux-2.4.21/arch/sparc64/mm/fault.c linux-2.4.21-ben2/arch/sparc64/mm/fault.c --- linux-2.4.21/arch/sparc64/mm/fault.c 2002-11-29 00:53:12.000000000 +0100 +++ linux-2.4.21-ben2/arch/sparc64/mm/fault.c 2003-06-27 15:41:25.000000000 +0200 @@ -389,7 +389,7 @@ goto bad_area; } } - if (expand_stack(vma, address)) + if (expand_stack(vma, address, NULL)) goto bad_area; /* * Ok, we have a good vm_area for this memory access, so diff -uNr linux-2.4.21/drivers/block/ll_rw_blk.c linux-2.4.21-ben2/drivers/block/ll_rw_blk.c --- linux-2.4.21/drivers/block/ll_rw_blk.c 2003-06-13 16:51:32.000000000 +0200 +++ linux-2.4.21-ben2/drivers/block/ll_rw_blk.c 2003-06-27 15:41:22.000000000 +0200 @@ -121,6 +121,10 @@ unsigned long blk_max_low_pfn, blk_max_pfn; int blk_nohighio = 0; +int block_dump = 0; + +static struct timer_list writeback_timer; + static inline int get_max_sectors(kdev_t dev) { if (!max_sectors[MAJOR(dev)]) @@ -158,6 +162,12 @@ return i; } +void blk_queue_activity_fn(request_queue_t *q, activity_fn *fn, void *data) +{ + q->activity_fn = fn; + q->activity_data = data; +} + /** * blk_cleanup_queue: - release a &request_queue_t when it is no longer needed * @q: the request queue to be released @@ -501,6 +511,7 @@ q->head_active = 1; blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH); + blk_queue_activity_fn(q, NULL, NULL); } #define blkdev_free_rq(list) list_entry((list)->next, struct request, queue); @@ -798,6 +809,9 @@ static inline void add_request(request_queue_t * q, struct request * req, struct list_head *insert_here) { + if (q->activity_fn) + q->activity_fn(q->activity_data, req->cmd); + drive_stat_acct(req->rq_dev, req->cmd, req->nr_sectors, 1); if (!q->plugged && q->head_active && insert_here == &q->queue_head) { @@ -1206,6 +1220,9 @@ kstat.pgpgin += count; break; } + + if (block_dump) + printk("%s: %s block %lu/%u on %s\n", current->comm, rw == WRITE ? "WRITE" : "READ", bh->b_rsector, count, kdevname(bh->b_rdev)); } /** @@ -1317,6 +1334,11 @@ extern int stram_device_init (void); #endif +static void blk_writeback_timer(unsigned long data) +{ + wakeup_bdflush(); + wakeup_kupdate(); +} /** * end_that_request_first - end I/O on one buffer. @@ -1372,10 +1394,18 @@ return 0; } +extern int laptop_mode; + void end_that_request_last(struct request *req) { struct completion *waiting = req->waiting; + /* + * schedule the writeout of pending dirty data when the disk is idle + */ + if (laptop_mode && req->cmd == READ) + mod_timer(&writeback_timer, jiffies + 5 * HZ); + req_finished_io(req); blkdev_release_request(req); if (waiting) @@ -1403,6 +1433,9 @@ blk_max_low_pfn = max_low_pfn - 1; blk_max_pfn = max_pfn - 1; + init_timer(&writeback_timer); + writeback_timer.function = blk_writeback_timer; + #ifdef CONFIG_AMIGA_Z2RAM z2_init(); #endif diff -uNr linux-2.4.21/drivers/block/swim3.c linux-2.4.21-ben2/drivers/block/swim3.c --- linux-2.4.21/drivers/block/swim3.c 2002-08-03 02:39:43.000000000 +0200 +++ linux-2.4.21-ben2/drivers/block/swim3.c 2003-06-27 15:41:05.000000000 +0200 @@ -2,7 +2,7 @@ * Driver for the SWIM3 (Super Woz Integrated Machine 3) * floppy controller found on Power Macintoshes. * - * Copyright (C) 1996 Paul Mackerras. + * Copyright (C) 1996-2003 Paul Mackerras. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -146,7 +146,7 @@ #define RELAX 3 /* also eject in progress */ #define READ_DATA_0 4 #define TWOMEG_DRIVE 5 -#define SINGLE_SIDED 6 +#define SINGLE_SIDED 6 /* drive or diskette is 4MB type? */ #define DRIVE_PRESENT 7 #define DISK_IN 8 #define WRITE_PROT 9 @@ -186,6 +186,7 @@ int req_sector; /* sector number ditto */ int scount; /* # sectors we're transferring at present */ int retries; + int settle_time; int secpercyl; /* disk geometry information */ int secpertrack; int total_secs; @@ -233,6 +234,7 @@ static void act(struct floppy_state *fs); static void scan_timeout(unsigned long data); static void seek_timeout(unsigned long data); +static void settle_timeout(unsigned long data); static void xfer_timeout(unsigned long data); static void swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs); /*static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs);*/ @@ -275,7 +277,6 @@ udelay(2); out_8(&sw->select, sw->select & ~LSTRB); udelay(1); - out_8(&sw->select, RELAX); } static int swim3_readbit(struct floppy_state *fs, int bit) @@ -284,9 +285,8 @@ int stat; swim3_select(fs, bit); - udelay(10); + udelay(1); stat = in_8(&sw->status); - out_8(&sw->select, RELAX); return (stat & DATA) == 0; } @@ -377,13 +377,13 @@ static inline void scan_track(struct floppy_state *fs) { volatile struct swim3 *sw = fs->swim3; - int xx; swim3_select(fs, READ_DATA_0); - xx = sw->intr; /* clear SEEN_SECTOR bit */ + in_8(&sw->intr); /* clear SEEN_SECTOR bit */ + in_8(&sw->error); + out_8(&sw->intr_enable, SEEN_SECTOR); out_8(&sw->control_bis, DO_ACTION); /* enable intr when track found */ - out_8(&sw->intr_enable, ERROR_INTR | SEEN_SECTOR); set_timeout(fs, HZ, scan_timeout); /* enable timeout */ } @@ -398,12 +398,14 @@ swim3_action(fs, SEEK_NEGATIVE); sw->nseek = -n; } - fs->expect_cyl = (fs->cur_cyl > 0)? fs->cur_cyl + n: -1; + fs->expect_cyl = (fs->cur_cyl >= 0)? fs->cur_cyl + n: -1; swim3_select(fs, STEP); - out_8(&sw->control_bis, DO_SEEK); + in_8(&sw->error); /* enable intr when seek finished */ - out_8(&sw->intr_enable, ERROR_INTR | SEEK_DONE); - set_timeout(fs, HZ/2, seek_timeout); /* enable timeout */ + out_8(&sw->intr_enable, SEEK_DONE); + out_8(&sw->control_bis, DO_SEEK); + set_timeout(fs, 3*HZ, seek_timeout); /* enable timeout */ + fs->settle_time = 0; } static inline void init_dma(struct dbdma_cmd *cp, int cmd, @@ -451,18 +453,21 @@ } ++cp; out_le16(&cp->command, DBDMA_STOP); + out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS); + in_8(&sw->error); + out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS); + if (CURRENT->cmd == WRITE) + out_8(&sw->control_bis, WRITE_SECTORS); + in_8(&sw->intr); out_le32(&dr->control, (RUN << 16) | RUN); - out_8(&sw->control_bis, - (CURRENT->cmd == WRITE? WRITE_SECTORS: 0) | DO_ACTION); /* enable intr when transfer complete */ - out_8(&sw->intr_enable, ERROR_INTR | TRANSFER_DONE); + out_8(&sw->intr_enable, TRANSFER_DONE); + out_8(&sw->control_bis, DO_ACTION); set_timeout(fs, 2*HZ, xfer_timeout); /* enable timeout */ } static void act(struct floppy_state *fs) { - volatile struct swim3 *sw = fs->swim3; - for (;;) { switch (fs->state) { case idle: @@ -495,20 +500,10 @@ return; case settling: - /* wait for SEEK_COMPLETE to become true */ - swim3_select(fs, SEEK_COMPLETE); - udelay(10); - out_8(&sw->intr_enable, ERROR_INTR | DATA_CHANGED); - in_8(&sw->intr); /* clear DATA_CHANGED */ - if (in_8(&sw->status) & DATA) { - /* seek_complete is not yet true */ - set_timeout(fs, HZ/2, seek_timeout); - return; - } - out_8(&sw->intr_enable, 0); - in_8(&sw->intr); - fs->state = locating; - break; + /* check for SEEK_COMPLETE after 30ms */ + fs->settle_time = (HZ + 32) / 33; + set_timeout(fs, fs->settle_time, settle_timeout); + return; case do_transfer: if (fs->cur_cyl != fs->req_cyl) { @@ -540,7 +535,7 @@ volatile struct swim3 *sw = fs->swim3; fs->timeout_pending = 0; - out_8(&sw->control_bic, DO_ACTION); + out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS); out_8(&sw->select, RELAX); out_8(&sw->intr_enable, 0); fs->cur_cyl = -1; @@ -560,20 +555,34 @@ volatile struct swim3 *sw = fs->swim3; fs->timeout_pending = 0; - if (fs->state == settling) { - printk(KERN_ERR "swim3: MSI sel=%x ctrl=%x stat=%x intr=%x ie=%x\n", - sw->select, sw->control, sw->status, sw->intr, sw->intr_enable); - } out_8(&sw->control_bic, DO_SEEK); out_8(&sw->select, RELAX); out_8(&sw->intr_enable, 0); - if (fs->state == settling && swim3_readbit(fs, SEEK_COMPLETE)) { - /* printk(KERN_DEBUG "swim3: missed settling interrupt\n"); */ + printk(KERN_ERR "swim3: seek timeout\n"); + end_request(0); + fs->state = idle; + start_request(fs); +} + +static void settle_timeout(unsigned long data) +{ + struct floppy_state *fs = (struct floppy_state *) data; + volatile struct swim3 *sw = fs->swim3; + + fs->timeout_pending = 0; + if (swim3_readbit(fs, SEEK_COMPLETE)) { + out_8(&sw->select, RELAX); fs->state = locating; act(fs); return; } - printk(KERN_ERR "swim3: seek timeout\n"); + out_8(&sw->select, RELAX); + if (fs->settle_time < 2*HZ) { + ++fs->settle_time; + set_timeout(fs, 1, settle_timeout); + return; + } + printk(KERN_ERR "swim3: seek settle timeout\n"); end_request(0); fs->state = idle; start_request(fs); @@ -586,9 +595,13 @@ struct dbdma_regs *dr = fs->dma; struct dbdma_cmd *cp = fs->dma_cmd; unsigned long s; + int n; fs->timeout_pending = 0; st_le32(&dr->control, RUN << 16); + /* We must wait a bit for dbdma to stop */ + for (n = 0; (in_le32(&dr->status) & ACTIVE) && n < 1000; n++) + udelay(1); out_8(&sw->intr_enable, 0); out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION); out_8(&sw->select, RELAX); @@ -616,18 +629,15 @@ struct dbdma_regs *dr; struct dbdma_cmd *cp; - err = in_8(&sw->error); intr = in_8(&sw->intr); -#if 0 - printk("swim3 intr state=%d intr=%x err=%x\n", fs->state, intr, err); -#endif + err = (intr & ERROR_INTR)? in_8(&sw->error): 0; if ((intr & ERROR_INTR) && fs->state != do_transfer) printk(KERN_ERR "swim3_interrupt, state=%d, cmd=%x, intr=%x, err=%x\n", fs->state, CURRENT->cmd, intr, err); switch (fs->state) { case locating: if (intr & SEEN_SECTOR) { - out_8(&sw->control_bic, DO_ACTION); + out_8(&sw->control_bic, DO_ACTION | WRITE_SECTORS); out_8(&sw->select, RELAX); out_8(&sw->intr_enable, 0); del_timer(&fs->timeout); @@ -677,19 +687,33 @@ case do_transfer: if ((intr & (ERROR_INTR | TRANSFER_DONE)) == 0) break; - dr = fs->dma; - cp = fs->dma_cmd; - /* We must wait a bit for dbdma to complete */ - for (n=0; (in_le32(&dr->status) & ACTIVE) && n < 1000; n++) - udelay(10); - DBDMA_DO_STOP(dr); out_8(&sw->intr_enable, 0); out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION); out_8(&sw->select, RELAX); del_timer(&fs->timeout); fs->timeout_pending = 0; + dr = fs->dma; + cp = fs->dma_cmd; if (CURRENT->cmd == WRITE) ++cp; + /* + * Check that the main data transfer has finished. + * On writing, the swim3 sometimes doesn't use + * up all the bytes of the postamble, so we can still + * see DMA active here. That doesn't matter as long + * as all the sector data has been transferred. + */ + if ((intr & ERROR_INTR) == 0 && cp->xfer_status == 0) { + /* wait a little while for DMA to complete */ + for (n = 0; n < 100; ++n) { + if (cp->xfer_status != 0) + break; + udelay(1); + barrier(); + } + } + /* turn off DMA */ + out_le32(&dr->control, (RUN | PAUSE) << 16); stat = ld_le16(&cp->xfer_status); resid = ld_le16(&cp->res_count); if (intr & ERROR_INTR) { @@ -796,16 +820,19 @@ if (err) return err; swim3_action(fs, EJECT); - for (n = 2*HZ; n > 0; --n) { - if (swim3_readbit(fs, RELAX)) - break; + for (n = 20; n > 0; --n) { if (signal_pending(current)) { err = -EINTR; break; } + swim3_select(fs, RELAX); current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); + if (swim3_readbit(fs, DISK_IN) == 0) + break; } + swim3_select(fs, RELAX); + udelay(150); fs->ejected = 1; release_drive(fs); return err; @@ -865,29 +892,31 @@ if (fs->ref_count == 0) { if (fs->media_bay && check_media_bay(fs->media_bay, MB_FD)) return -ENXIO; - out_8(&sw->mode, 0x95); - out_8(&sw->control_bic, 0xff); out_8(&sw->setup, S_IBM_DRIVE | S_FCLK_DIV2); + out_8(&sw->control_bic, 0xff); + out_8(&sw->mode, 0x95); udelay(10); out_8(&sw->intr_enable, 0); out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE); swim3_action(fs, MOTOR_ON); fs->write_prot = -1; fs->cur_cyl = -1; - for (n = HZ; n > 0; --n) { - if (swim3_readbit(fs, SEEK_COMPLETE)) + for (n = 0; n < 2 * HZ; ++n) { + if (n >= HZ/30 && swim3_readbit(fs, SEEK_COMPLETE)) break; if (signal_pending(current)) { err = -EINTR; break; } + swim3_select(fs, RELAX); current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); } if (err == 0 && (swim3_readbit(fs, SEEK_COMPLETE) == 0 || swim3_readbit(fs, DISK_IN) == 0)) err = -ENXIO; - swim3_action(fs, 9); + swim3_action(fs, SETMFM); + swim3_select(fs, RELAX); } else if (fs->ref_count == -1 || filp->f_flags & O_EXCL) return -EBUSY; @@ -910,6 +939,7 @@ if (fs->ref_count == 0) { swim3_action(fs, MOTOR_OFF); out_8(&sw->control_bic, DRIVE_ENABLE | INTR_ENABLE); + swim3_select(fs, RELAX); } return err; } @@ -936,6 +966,7 @@ if (fs->ref_count > 0 && --fs->ref_count == 0) { swim3_action(fs, MOTOR_OFF); out_8(&sw->control_bic, 0xff); + swim3_select(fs, RELAX); } return 0; } @@ -970,15 +1001,17 @@ sw = fs->swim3; grab_drive(fs, revalidating, 0); out_8(&sw->intr_enable, 0); - out_8(&sw->control_bis, DRIVE_ENABLE | INTR_ENABLE); - swim3_action(fs, MOTOR_ON); + out_8(&sw->control_bis, DRIVE_ENABLE); + swim3_action(fs, MOTOR_ON); /* necessary? */ fs->write_prot = -1; fs->cur_cyl = -1; + mdelay(1); for (n = HZ; n > 0; --n) { if (swim3_readbit(fs, SEEK_COMPLETE)) break; if (signal_pending(current)) break; + swim3_select(fs, RELAX); current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); } @@ -988,8 +1021,9 @@ swim3_action(fs, MOTOR_OFF); else { fs->ejected = 0; - swim3_action(fs, 9); + swim3_action(fs, SETMFM); } + swim3_select(fs, RELAX); release_drive(fs); return ret; diff -uNr linux-2.4.21/drivers/char/Config.in linux-2.4.21-ben2/drivers/char/Config.in --- linux-2.4.21/drivers/char/Config.in 2003-06-13 16:51:32.000000000 +0200 +++ linux-2.4.21-ben2/drivers/char/Config.in 2003-06-27 15:41:26.000000000 +0200 @@ -161,6 +161,9 @@ if [ "$CONFIG_PPC64" ] ; then bool 'pSeries Hypervisor Virtual Console support' CONFIG_HVC_CONSOLE fi +if [ "$CONFIG_ALL_PPC" = "y" ]; then + tristate 'Total Impact briQ front panel driver' CONFIG_BRIQ_PANEL +fi source drivers/i2c/Config.in @@ -309,6 +312,7 @@ if [ "$CONFIG_IA64" = "y" ]; then bool ' HP ZX1 AGP support' CONFIG_AGP_HP_ZX1 fi + dep_bool ' Apple UniNorth support' CONFIG_AGP_UNINORTH $CONFIG_ALL_PPC fi bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM diff -uNr linux-2.4.21/drivers/char/Makefile linux-2.4.21-ben2/drivers/char/Makefile --- linux-2.4.21/drivers/char/Makefile 2003-06-13 16:51:32.000000000 +0200 +++ linux-2.4.21-ben2/drivers/char/Makefile 2003-06-27 15:41:25.000000000 +0200 @@ -248,6 +248,7 @@ obj-$(CONFIG_INTEL_RNG) += i810_rng.o obj-$(CONFIG_AMD_RNG) += amd768_rng.o obj-$(CONFIG_AMD_PM768) += amd76x_pm.o +obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o obj-$(CONFIG_ITE_GPIO) += ite_gpio.o obj-$(CONFIG_AU1000_GPIO) += au1000_gpio.o diff -uNr linux-2.4.21/drivers/char/agp/agpgart_be.c linux-2.4.21-ben2/drivers/char/agp/agpgart_be.c --- linux-2.4.21/drivers/char/agp/agpgart_be.c 2003-06-13 16:51:32.000000000 +0200 +++ linux-2.4.21-ben2/drivers/char/agp/agpgart_be.c 2003-06-27 15:41:08.000000000 +0200 @@ -44,6 +44,10 @@ #include #include +#ifdef CONFIG_AGP_UNINORTH +#include +#endif + #include #include "agp.h" @@ -71,7 +75,7 @@ { #if defined(__i386__) || defined(__x86_64__) asm volatile ("wbinvd":::"memory"); -#elif defined(__alpha__) || defined(__ia64__) || defined(__sparc__) +#elif defined(__alpha__) || defined(__ia64__) || defined(__sparc__) || defined(__powerpc__) /* ??? I wonder if we'll really need to flush caches, or if the core logic can manage to keep the system coherent. The ARM speaks only of using `cflush' to get things in memory in @@ -4365,6 +4369,405 @@ #endif /* CONFIG_AGP_HP_ZX1 */ +#ifdef CONFIG_AGP_UNINORTH + +static int uninorth_fetch_size(void) +{ + int i; + u32 temp; + aper_size_info_32 *values; + + pci_read_config_dword(agp_bridge.dev, UNI_N_CFG_GART_BASE, &temp); + temp &= ~(0xfffff000); + values = A_SIZE_32(agp_bridge.aperture_sizes); + + for (i = 0; i < agp_bridge.num_aperture_sizes; i++) { + if (temp == values[i].size_value) { + agp_bridge.previous_size = + agp_bridge.current_size = (void *) (values + i); + agp_bridge.aperture_size_idx = i; + return values[i].size; + } + } + + agp_bridge.previous_size = + agp_bridge.current_size = (void *) (values + 1); + agp_bridge.aperture_size_idx = 1; + return values[1].size; + + return 0; +} + +static void uninorth_tlbflush(agp_memory * mem) +{ + pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL, + UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL); + pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL, + UNI_N_CFG_GART_ENABLE); + pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL, + UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_2xRESET); + pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL, + UNI_N_CFG_GART_ENABLE); +} + +static void uninorth_cleanup(void) +{ + pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL, + UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL); + pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL, + 0); + pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL, + UNI_N_CFG_GART_2xRESET); + pci_write_config_dword(agp_bridge.dev, UNI_N_CFG_GART_CTRL, + 0); +} + +static int uninorth_configure(void) +{ + aper_size_info_32 *current_size; + + current_size = A_SIZE_32(agp_bridge.current_size); + + printk("agp: configuring for size idx: %d\n", current_size->size_value); + + /* aperture size and gatt addr */ + pci_write_config_dword(agp_bridge.dev, + UNI_N_CFG_GART_BASE, + (agp_bridge.gatt_bus_addr & 0xfffff000) + | current_size->size_value); + + /* HACK ALERT + * UniNorth seem to be buggy enough not to handle properly when + * the AGP aperture isn't mapped at bus physical address 0 + */ + agp_bridge.gart_bus_addr = 0; + pci_write_config_dword(agp_bridge.dev, + UNI_N_CFG_AGP_BASE, agp_bridge.gart_bus_addr); + + return 0; +} + +static unsigned long uninorth_mask_memory(unsigned long addr, int type) +{ + return addr;/* | agp_bridge.masks[0].mask;*/ +} + +static int uninorth_insert_memory(agp_memory * mem, + off_t pg_start, int type) +{ + int i, j, num_entries; + void *temp; + + temp = agp_bridge.current_size; + num_entries = A_SIZE_32(temp)->num_entries; + + if (type != 0 || mem->type != 0) { + /* The generic routines know nothing of memory types */ + return -EINVAL; + } + if ((pg_start + mem->page_count) > num_entries) { + return -EINVAL; + } + j = pg_start; + + while (j < (pg_start + mem->page_count)) { + if (!PGE_EMPTY(agp_bridge.gatt_table[j])) { + return -EBUSY; + } + j++; + } + + if (mem->is_flushed == FALSE) { + CACHE_FLUSH(); + mem->is_flushed = TRUE; + } + for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { + agp_bridge.gatt_table[j] = cpu_to_le32((mem->memory[i] & 0xfffff000) | 0x00000001UL); + flush_dcache_range(__va(mem->memory[i]), __va(mem->memory[i])+0x1000); + } + (void)in_le32((volatile u32*)&agp_bridge.gatt_table[pg_start]); + mb(); + flush_dcache_range((unsigned long)&agp_bridge.gatt_table[pg_start], + (unsigned long)&agp_bridge.gatt_table[pg_start + mem->page_count]); + + agp_bridge.tlb_flush(mem); + return 0; +} + +static void uninorth_agp_enable(u32 mode) +{ + struct pci_dev *device = NULL; + u32 command, scratch, cap_id; + u8 cap_ptr; + + pci_read_config_dword(agp_bridge.dev, + agp_bridge.capndx + 4, + &command); + + /* + * PASS1: go throu all devices that claim to be + * AGP devices and collect their data. + */ + + while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, + device)) != NULL) { + pci_read_config_dword(device, 0x04, &scratch); + + if (!(scratch & 0x00100000)) + continue; + + pci_read_config_byte(device, 0x34, &cap_ptr); + + if (cap_ptr != 0x00) { + do { + pci_read_config_dword(device, + cap_ptr, &cap_id); + + if ((cap_id & 0xff) != 0x02) + cap_ptr = (cap_id >> 8) & 0xff; + } + while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00)); + } + if (cap_ptr != 0x00) { + /* + * Ok, here we have a AGP device. Disable impossible + * settings, and adjust the readqueue to the minimum. + */ + + pci_read_config_dword(device, cap_ptr + 4, &scratch); + + /* adjust RQ depth */ + command = + ((command & ~0xff000000) | + min_t(u32, (mode & 0xff000000), + min_t(u32, (command & 0xff000000), + (scratch & 0xff000000)))); + + /* disable SBA if it's not supported */ + if (!((command & 0x00000200) && + (scratch & 0x00000200) && + (mode & 0x00000200))) + command &= ~0x00000200; + + /* disable FW if it's not supported */ + if (!((command & 0x00000010) && + (scratch & 0x00000010) && + (mode & 0x00000010))) + command &= ~0x00000010; + + if (!((command & 4) && + (scratch & 4) && + (mode & 4))) + command &= ~0x00000004; + + if (!((command & 2) && + (scratch & 2) && + (mode & 2))) + command &= ~0x00000002; + + if (!((command & 1) && + (scratch & 1) && + (mode & 1))) + command &= ~0x00000001; + } + } + /* + * PASS2: Figure out the 4X/2X/1X setting and enable the + * target (our motherboard chipset). + */ + + if (command & 4) { + command &= ~3; /* 4X */ + } + if (command & 2) { + command &= ~5; /* 2X */ + } + if (command & 1) { + command &= ~6; /* 1X */ + } + command |= 0x00000100; + + uninorth_tlbflush(NULL); + + do { + pci_write_config_dword(agp_bridge.dev, + agp_bridge.capndx + 8, + command); + pci_read_config_dword(agp_bridge.dev, + agp_bridge.capndx + 8, + &scratch); + } while((scratch & 0x100) == 0); + + /* + * PASS3: Go throu all AGP devices and update the + * command registers. + */ + + while ((device = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, + device)) != NULL) { + pci_read_config_dword(device, 0x04, &scratch); + + if (!(scratch & 0x00100000)) + continue; + + pci_read_config_byte(device, 0x34, &cap_ptr); + + if (cap_ptr != 0x00) { + do { + pci_read_config_dword(device, + cap_ptr, &cap_id); + + if ((cap_id & 0xff) != 0x02) + cap_ptr = (cap_id >> 8) & 0xff; + } + while (((cap_id & 0xff) != 0x02) && (cap_ptr != 0x00)); + } + if (cap_ptr != 0x00) + pci_write_config_dword(device, cap_ptr + 8, command); + } + + uninorth_tlbflush(NULL); +} + +static int uninorth_create_gatt_table(void) +{ + char *table; + char *table_end; + int size; + int page_order; + int num_entries; + int i; + void *temp; + struct page *page; + + /* The generic routines can't handle 2 level gatt's */ + if (agp_bridge.size_type == LVL2_APER_SIZE) { + return -EINVAL; + } + + table = NULL; + i = agp_bridge.aperture_size_idx; + temp = agp_bridge.current_size; + size = page_order = num_entries = 0; + + do { + size = A_SIZE_32(temp)->size; + page_order = A_SIZE_32(temp)->page_order; + num_entries = A_SIZE_32(temp)->num_entries; + + table = (char *) __get_free_pages(GFP_KERNEL, page_order); + + if (table == NULL) { + i++; + agp_bridge.current_size = A_IDX32(); + } else { + agp_bridge.aperture_size_idx = i; + } + } while ((table == NULL) && + (i < agp_bridge.num_aperture_sizes)); + + if (table == NULL) { + return -ENOMEM; + } + table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1); + + for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) + SetPageReserved(page); + + agp_bridge.gatt_table_real = (unsigned long *) table; + agp_bridge.gatt_table = (unsigned long *)table; + agp_bridge.gatt_bus_addr = virt_to_phys(table); + + for (i = 0; i < num_entries; i++) { + agp_bridge.gatt_table[i] = + (unsigned long) agp_bridge.scratch_page; + } + + flush_dcache_range((unsigned long)table, (unsigned long)table_end); + + return 0; +} + +static int uninorth_free_gatt_table(void) +{ + int page_order; + char *table, *table_end; + void *temp; + struct page *page; + + temp = agp_bridge.current_size; + page_order = A_SIZE_32(temp)->page_order; + + /* Do not worry about freeing memory, because if this is + * called, then all agp memory is deallocated and removed + * from the table. + */ + + table = (char *) agp_bridge.gatt_table_real; + table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1); + + for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) + ClearPageReserved(page); + + free_pages((unsigned long) agp_bridge.gatt_table_real, page_order); + + return 0; +} + + +/* Setup function */ +static gatt_mask uninorth_masks[] = +{ + {0x00000000, 0} +}; + +static aper_size_info_32 uninorth_sizes[7] = +{ +#if 0 /* Not sure uninorth supports that high aperture sizes */ + {256, 65536, 6, 64}, + {128, 32768, 5, 32}, + {64, 16384, 4, 16}, +#endif + {32, 8192, 3, 8}, + {16, 4096, 2, 4}, + {8, 2048, 1, 2}, + {4, 1024, 0, 1} +}; + +static int __init uninorth_setup (struct pci_dev *pdev) +{ + agp_bridge.masks = uninorth_masks; + agp_bridge.aperture_sizes = (void *)uninorth_sizes; + agp_bridge.size_type = U32_APER_SIZE; + agp_bridge.num_aperture_sizes = 4; //7; + agp_bridge.dev_private_data = NULL; + agp_bridge.needs_scratch_page = FALSE; + agp_bridge.configure = uninorth_configure; + agp_bridge.fetch_size = uninorth_fetch_size; + agp_bridge.cleanup = uninorth_cleanup; + agp_bridge.tlb_flush = uninorth_tlbflush; + agp_bridge.mask_memory = uninorth_mask_memory; + agp_bridge.agp_enable = uninorth_agp_enable; + agp_bridge.cache_flush = global_cache_flush; + agp_bridge.create_gatt_table = uninorth_create_gatt_table; + agp_bridge.free_gatt_table = uninorth_free_gatt_table; + agp_bridge.insert_memory = uninorth_insert_memory; + agp_bridge.remove_memory = agp_generic_remove_memory; + agp_bridge.alloc_by_type = agp_generic_alloc_by_type; + agp_bridge.free_by_type = agp_generic_free_by_type; + agp_bridge.agp_alloc_page = agp_generic_alloc_page; + agp_bridge.agp_destroy_page = agp_generic_destroy_page; + agp_bridge.suspend = agp_generic_suspend; + agp_bridge.resume = agp_generic_resume; + agp_bridge.cant_use_aperture = 1; + + return 0; + + (void) pdev; /* unused */ +} + +#endif /* CONFIG_AGP_UNINORTH */ + /* per-chipset initialization data. * note -- all chipsets for a single vendor MUST be grouped together */ @@ -4711,6 +5114,33 @@ hp_zx1_setup }, #endif +#ifdef CONFIG_AGP_UNINORTH + { PCI_DEVICE_ID_APPLE_UNI_N_AGP, + PCI_VENDOR_ID_APPLE, + APPLE_UNINORTH, + "Apple", + "UniNorth", + uninorth_setup }, + { PCI_DEVICE_ID_APPLE_UNI_N_AGP_P, + PCI_VENDOR_ID_APPLE, + APPLE_UNINORTH, + "Apple", + "UniNorth/Pangea", + uninorth_setup }, + { PCI_DEVICE_ID_APPLE_UNI_N_AGP15, + PCI_VENDOR_ID_APPLE, + APPLE_UNINORTH, + "Apple", + "UniNorth 1.5", + uninorth_setup }, + { PCI_DEVICE_ID_APPLE_UNI_N_AGP2, + PCI_VENDOR_ID_APPLE, + APPLE_UNINORTH, + "Apple", + "UniNorth 2", + uninorth_setup }, +#endif /* CONFIG_AGP_UNINORTH */ + { 0, }, /* dummy final entry, always present */ }; diff -uNr linux-2.4.21/drivers/char/briq_panel.c linux-2.4.21-ben2/drivers/char/briq_panel.c --- linux-2.4.21/drivers/char/briq_panel.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/drivers/char/briq_panel.c 2003-06-27 15:41:16.000000000 +0200 @@ -0,0 +1,251 @@ +/* + * Drivers for the Total Impact PPC based computer "BRIQ" + * by Dr. Karsten Jeppesen + * + * + * 010407 Coding started + * + * 04/20/2002 1.1 Adapted to 2.4, small cleanups + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define TOTALIMPACT_VFD_MINOR 156 +#define VFD_IOPORT 0x0390 +#define LED_IOPORT 0x0398 +#define TI_VER "1.1 (04/20/2002)" +#define TI_MSG0 "Loading Linux" + +static int vfd_is_open; +static unsigned char vfd[40]; +static int vfd_cursor; +static unsigned char ledpb, led; + + +static void UpdateVFD( void ) +{ + int i; + outb(0x02, VFD_IOPORT); /* cursor home */ + for (i=0; i<20; i++) outb(vfd[i], VFD_IOPORT + 1); + outb(0xc0, VFD_IOPORT); /* cursor to next line */ + for (i=20; i<40; i++) outb(vfd[i], VFD_IOPORT + 1); + +} + +static void SetLED( char state) +{ + if ( state == 'R' ) led = 0x01; + else if ( state == 'G' ) led = 0x02; + else if ( state == 'Y' ) led = 0x03; + else if ( state == 'X' ) led = 0x00; + outb(led, LED_IOPORT); +} + +static int do_open(struct inode *ino, struct file *filep) +{ + if (vfd_is_open) return -EBUSY; + MOD_INC_USE_COUNT; + vfd_is_open = 1; + return(0); +} + +static int do_release(struct inode *ino, struct file *filep) +{ + if (!vfd_is_open) return -ENODEV; + MOD_DEC_USE_COUNT; + vfd_is_open = 0; + return(0); +} + + +static ssize_t do_read(struct file *file, char *buf, size_t count, + loff_t *ppos) +{ + unsigned short c; + unsigned char cp; + + /* Can't seek (pread) on this device */ + if (ppos != &file->f_pos) return -ESPIPE; + if (!vfd_is_open) return -ENODEV; + c = (inb( LED_IOPORT ) & 0x000c) | (ledpb & 0x0003); + SetLED(' '); + if ((!(ledpb & 0x0004)) && (c & 0x0004)) + { /* upper button released */ + cp = ' '; + ledpb = c; + if (copy_to_user(buf, &cp, 1)) return -EFAULT; + return(1); + } + else if ((!(ledpb & 0x0008)) && (c & 0x0008)) + { /* lower button released */ + cp = '\r'; + ledpb = c; + if (copy_to_user(buf, &cp, 1)) return -EFAULT; + return(1); + } else + { + ledpb = c; + return(0); + } +} + + +static void ScrollVFD( void ) +{ + int i; + for (i=0; i<20; i++) + { + vfd[i] = vfd[i+20]; + vfd[i+20] = ' '; + } + vfd_cursor = 20; +} + + +static ssize_t do_write(struct file *file, const char *buf, size_t len, + loff_t *ppos) +{ + size_t indx = len; + int i, esc=0; + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) return -ESPIPE; + if (!vfd_is_open) return -EBUSY; + for (;;) + { + if (!indx) break; + if (esc) + { + SetLED(*buf); + esc = 0; + } + else if (*buf == 27) + { + esc = 1; + } + else if (*buf == 12) + { /* do a form feed */ + for (i=0; i<40; i++) vfd[i] = ' '; + vfd_cursor = 0; + } + else if (*buf == 10) + { + if (vfd_cursor < 20) vfd_cursor = 20; + else if (vfd_cursor < 40) vfd_cursor = 40; + else if (vfd_cursor < 60) vfd_cursor = 60; + if (vfd_cursor > 59) ScrollVFD(); + } + else + { + /* just a character */ + if (vfd_cursor > 39) ScrollVFD(); + vfd[vfd_cursor++] = *buf; + } + indx--; + buf++; + } + UpdateVFD(); + return len; +} + + +static struct file_operations vfd_fops = { + read: do_read, /* Read */ + write: do_write, /* Write */ + open: do_open, /* Open */ + release: do_release, /* Release */ +}; + + +static struct miscdevice ti_vfd_miscdev = { + TOTALIMPACT_VFD_MINOR, + "vfd", + &vfd_fops +}; + + +static int __init briq_panel_init(void) +{ + struct device_node *root = find_path_device("/"); + char *machine; + int i; + + machine = get_property(root, "model", NULL); + if (!machine || strncmp(machine, "TotalImpact,BRIQ-1", 18) != 0) + return -ENODEV; + + printk(KERN_INFO "ti_briq: v%s Dr. Karsten Jeppesen (kj@totalimpact.com)\n", TI_VER); + + if (!request_region( VFD_IOPORT, 4, "BRIQ Front Panel")) + return -EBUSY; + if (!request_region( LED_IOPORT, 2, "BRIQ Front Panel")) { + release_region(VFD_IOPORT, 4); + return -EBUSY; + } + ledpb = inb( LED_IOPORT ) & 0x000c; + + if (misc_register(&ti_vfd_miscdev) < 0) { + release_region(VFD_IOPORT, 4); + release_region(LED_IOPORT, 2); + return -EBUSY; + } + + outb(0x38, VFD_IOPORT); /* Function set */ + outb(0x01, VFD_IOPORT); /* Clear display */ + outb(0x0c, VFD_IOPORT); /* Display on */ + outb(0x06, VFD_IOPORT); /* Entry normal */ + for (i=0; i<40; i++) vfd[i]=' '; +#ifndef MODULE + vfd[0] = 'L'; + vfd[1] = 'o'; + vfd[2] = 'a'; + vfd[3] = 'd'; + vfd[4] = 'i'; + vfd[5] = 'n'; + vfd[6] = 'g'; + vfd[7] = ' '; + vfd[8] = '.'; + vfd[9] = '.'; + vfd[10] = '.'; +#endif /* !MODULE */ + UpdateVFD(); + + return 0; +} + + +static void __exit briq_panel_exit(void) +{ + misc_deregister(&ti_vfd_miscdev); + release_region(VFD_IOPORT, 4); + release_region(LED_IOPORT, 2); +} + + +module_init(briq_panel_init); +module_exit(briq_panel_exit); + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Karsten Jeppesen "); +MODULE_DESCRIPTION("Driver for the Total Impact briQ front panel"); +EXPORT_NO_SYMBOLS; diff -uNr linux-2.4.21/drivers/char/defkeymap.c linux-2.4.21-ben2/drivers/char/defkeymap.c --- linux-2.4.21/drivers/char/defkeymap.c 1999-10-07 19:17:09.000000000 +0200 +++ linux-2.4.21-ben2/drivers/char/defkeymap.c 2003-06-27 15:41:18.000000000 +0200 @@ -1,3 +1,4 @@ + /* Do not edit this file! It was automatically generated by */ /* loadkeys --mktable defkeymap.map > defkeymap.c */ @@ -37,7 +38,7 @@ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03e, 0xf10a, 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603, 0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116, 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, @@ -56,7 +57,7 @@ 0xf912, 0xf913, 0xf30b, 0xf90e, 0xf90f, 0xf910, 0xf30a, 0xf90b, 0xf90c, 0xf90d, 0xf90a, 0xf310, 0xf206, 0xf200, 0xf07c, 0xf516, 0xf517, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603, 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, @@ -94,7 +95,7 @@ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603, 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116, 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, @@ -132,7 +133,7 @@ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301, 0xf302, 0xf303, 0xf300, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf50a, 0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, - 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603, + 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603, 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c, 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, @@ -147,6 +148,7 @@ unsigned int keymap_count = 7; + /* * Philosophy: most people do not define more strings, but they who do * often want quite a lot of string space. So, we statically allocate @@ -184,6 +186,7 @@ '\033', '[', 'P', 0, }; + char *funcbufptr = func_buf; int funcbufsize = sizeof(func_buf); int funcbufleft = 0; /* space left */ diff -uNr linux-2.4.21/drivers/char/drm/drmP.h linux-2.4.21-ben2/drivers/char/drm/drmP.h --- linux-2.4.21/drivers/char/drm/drmP.h 2002-11-29 00:53:12.000000000 +0100 +++ linux-2.4.21-ben2/drivers/char/drm/drmP.h 2003-06-27 15:41:08.000000000 +0200 @@ -324,6 +324,15 @@ DRM(ioremapfree)( (map)->handle, (map)->size ); \ } while (0) +#define DRM_IOREMAPAGP(map, dev) \ + (map)->handle = DRM(ioremap_agp)( (map)->offset, (map)->size, (dev) ) + +#define DRM_IOREMAPAGPFREE(map) \ + do { \ + if ( (map)->handle && (map)->size ) \ + DRM(ioremap_agp_free)( (map)->handle, (map)->size ); \ + } while (0) + #define DRM_FIND_MAP(_map, _o) \ do { \ struct list_head *_list; \ @@ -758,6 +767,9 @@ extern void *DRM(ioremap)(unsigned long offset, unsigned long size); extern void DRM(ioremapfree)(void *pt, unsigned long size); +extern void *DRM(ioremap_agp)(unsigned long offset, unsigned long size, drm_device_t *dev); +extern void DRM(ioremap_agp_free)(void *pt, unsigned long size); + #if __REALLY_HAVE_AGP extern agp_memory *DRM(alloc_agp)(int pages, u32 type); extern int DRM(free_agp)(agp_memory *handle, int pages); diff -uNr linux-2.4.21/drivers/char/drm/drm_memory.h linux-2.4.21-ben2/drivers/char/drm/drm_memory.h --- linux-2.4.21/drivers/char/drm/drm_memory.h 2002-11-29 00:53:12.000000000 +0100 +++ linux-2.4.21-ben2/drivers/char/drm/drm_memory.h 2003-06-27 15:41:11.000000000 +0200 @@ -313,6 +313,108 @@ return pt; } +/* PPC specific routine used by ioremap_agp, to be replaced by some + * more generic implementation + */ +extern int map_page(unsigned long va, unsigned long pa, int flags); + +void *DRM(ioremap_agp)(unsigned long offset, unsigned long size, drm_device_t *dev) +{ + void *pt; + struct vm_struct *area; + struct drm_agp_mem *agpmem; + unsigned int flags = _PAGE_NO_CACHE|_PAGE_KERNEL|_PAGE_PRESENT|_PAGE_RW|_PAGE_DIRTY; + int err, i; + + printk("drm: ioremap_agp, offset: 0x%08lx, size: 0x%08lx\n", offset, size); + +#if __REALLY_HAVE_AGP + if (!size) { + DRM_MEM_ERROR(DRM_MEM_MAPPINGS, + "Mapping 0 bytes at 0x%08lx\n", offset); + return NULL; + } + + if (!dev->agp || !dev->agp->cant_use_aperture) + return DRM(ioremap)(offset, size); + + /* XXX This has to be changed into something more generic + * this implementation is really only valid on PPC + */ + area = get_vm_area(size, VM_IOREMAP); + if (area == 0) { + spin_lock(&DRM(mem_lock)); + ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; + spin_unlock(&DRM(mem_lock)); + printk("->NULL\n"); + return NULL; + } + pt = (void *)VMALLOC_VMADDR(area->addr); + err = 0; + for (i = 0; i < size && err == 0; i += PAGE_SIZE) { + unsigned long baddr = offset + i; + unsigned long index; + + /* + * It's AGP memory - find the real physical page to map + */ + for(agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next) { + if (agpmem->bound <= baddr && + agpmem->bound + agpmem->pages * PAGE_SIZE > baddr) + break; + } + if (!agpmem) { + printk("drm: not matching AGP page in ioremap_agp\n"); + err = 1; + break; + } + index = (baddr - agpmem->bound) >> PAGE_SHIFT; + get_page(virt_to_page(__va(agpmem->memory->memory[index]))); + err = map_page(((unsigned long)pt)+i, agpmem->memory->memory[index], flags); + } + if (err) { + vfree((void *)pt); + spin_lock(&DRM(mem_lock)); + ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; + spin_unlock(&DRM(mem_lock)); + printk("->NULL\n"); + return NULL; + } + + spin_lock(&DRM(mem_lock)); + ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count; + DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size; + spin_unlock(&DRM(mem_lock)); + printk("->pt=0x%p\n", pt); + return pt; +#else + return NULL; +#endif +} + +void DRM(ioremap_agp_free)(void *pt, unsigned long size) +{ + int alloc_count; + int free_count; + + if (!pt) + DRM_MEM_ERROR(DRM_MEM_MAPPINGS, + "Attempt to free NULL pointer\n"); + else + vfree(pt); + + spin_lock(&DRM(mem_lock)); + DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += size; + free_count = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count; + alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count; + spin_unlock(&DRM(mem_lock)); + if (free_count > alloc_count) { + DRM_MEM_ERROR(DRM_MEM_MAPPINGS, + "Excess frees: %d frees, %d allocs\n", + free_count, alloc_count); + } +} + void DRM(ioremapfree)(void *pt, unsigned long size) { int alloc_count; diff -uNr linux-2.4.21/drivers/char/drm/drm_vm.h linux-2.4.21-ben2/drivers/char/drm/drm_vm.h --- linux-2.4.21/drivers/char/drm/drm_vm.h 2003-06-13 16:51:32.000000000 +0200 +++ linux-2.4.21-ben2/drivers/char/drm/drm_vm.h 2003-06-27 15:41:51.000000000 +0200 @@ -379,7 +379,13 @@ if ( !priv->authenticated ) return -EACCES; - if (!VM_OFFSET(vma)) return DRM(mmap_dma)(filp, vma); + /* We check for "dma". On Apple's UniNorth, it's valid to have + * the AGP mapped at physical address 0 + * --BenH. + */ + if (!VM_OFFSET(vma) && (!dev->agp || + dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE)) + return DRM(mmap_dma)(filp, vma); /* A sequential search of a linked list is fine here because: 1) there will only be @@ -419,16 +425,22 @@ switch (map->type) { case _DRM_AGP: -#if defined(__alpha__) - /* - * On Alpha we can't talk to bus dma address from the - * CPU, so for memory of type DRM_AGP, we'll deal with - * sorting out the real physical pages and mappings - * in nopage() - */ - vma->vm_ops = &DRM(vm_ops); - break; + if (!dev->agp) + return -ENODEV; + if (dev->agp->cant_use_aperture) { + /* + * On Alpha we can't talk to bus dma address from the + * CPU, so for memory of type DRM_AGP, we'll deal with + * sorting out the real physical pages and mappings + * in nopage() + */ +#if defined(__powerpc__) + pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; #endif + vma->vm_flags |= VM_IO; + vma->vm_ops = &DRM(vm_ops); + break; + } /* fall through to _DRM_FRAME_BUFFER... */ case _DRM_FRAME_BUFFER: case _DRM_REGISTERS: diff -uNr linux-2.4.21/drivers/char/drm/r128_cce.c linux-2.4.21-ben2/drivers/char/drm/r128_cce.c --- linux-2.4.21/drivers/char/drm/r128_cce.c 2002-11-29 00:53:12.000000000 +0100 +++ linux-2.4.21-ben2/drivers/char/drm/r128_cce.c 2003-06-27 15:41:04.000000000 +0200 @@ -37,6 +37,10 @@ #define R128_FIFO_DEBUG 0 +#if __REALLY_HAVE_AGP && defined(CONFIG_ALL_PPC) +extern unsigned long agp_special_page; +#endif + /* CCE microcode (from ATI) */ static u32 r128_cce_microcode[] = { @@ -340,6 +344,14 @@ SET_RING_HEAD( &dev_priv->ring, 0 ); if ( !dev_priv->is_pci ) { +#if __REALLY_HAVE_AGP && defined(CONFIG_ALL_PPC) + if (_machine == _MACH_Pmac) { + dev_priv->ring.head = (__volatile__ u32 *) agp_special_page; + SET_RING_HEAD( &dev_priv->ring, 0 ); + R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR, + __pa( dev_priv->ring.head ) ); + } else +#endif R128_WRITE( R128_PM4_BUFFER_DL_RPTR_ADDR, dev_priv->ring_rptr->offset ); } else { @@ -549,9 +561,9 @@ init->sarea_priv_offset); if ( !dev_priv->is_pci ) { - DRM_IOREMAP( dev_priv->cce_ring ); - DRM_IOREMAP( dev_priv->ring_rptr ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAPAGP( dev_priv->cce_ring, dev ); + DRM_IOREMAPAGP( dev_priv->ring_rptr, dev ); + DRM_IOREMAPAGP( dev_priv->buffers, dev ); if(!dev_priv->cce_ring->handle || !dev_priv->ring_rptr->handle || !dev_priv->buffers->handle) { @@ -623,10 +635,11 @@ drm_r128_private_t *dev_priv = dev->dev_private; if ( !dev_priv->is_pci ) { - DRM_IOREMAPFREE( dev_priv->cce_ring ); - DRM_IOREMAPFREE( dev_priv->ring_rptr ); - DRM_IOREMAPFREE( dev_priv->buffers ); - } else { + DRM_IOREMAPAGPFREE( dev_priv->cce_ring ); + DRM_IOREMAPAGPFREE( dev_priv->ring_rptr ); + DRM_IOREMAPAGPFREE( dev_priv->buffers ); + } + else { if (!DRM(ati_pcigart_cleanup)( dev, dev_priv->phys_pci_gart, dev_priv->bus_pci_gart )) diff -uNr linux-2.4.21/drivers/char/drm/r128_drv.h linux-2.4.21-ben2/drivers/char/drm/r128_drv.h --- linux-2.4.21/drivers/char/drm/r128_drv.h 2002-11-29 00:53:12.000000000 +0100 +++ linux-2.4.21-ben2/drivers/char/drm/r128_drv.h 2003-06-27 15:41:35.000000000 +0200 @@ -34,8 +34,13 @@ #ifndef __R128_DRV_H__ #define __R128_DRV_H__ +#ifdef __powerpc__ +#define GET_RING_HEAD( ring ) in_le32((volatile u32 *)(ring)->head) +#define SET_RING_HEAD( ring, val ) out_le32((volatile u32 *)(ring)->head, (val) ) +#else #define GET_RING_HEAD( ring ) le32_to_cpu( *(ring)->head ) #define SET_RING_HEAD( ring, val ) *(ring)->head = cpu_to_le32( val ) +#endif typedef struct drm_r128_freelist { unsigned int age; @@ -397,6 +402,9 @@ wmb(); \ R128_DEREF(reg) = val; \ } while (0) +#elif defined (__powerpc__) +#define R128_READ(reg) in_le32( (volatile u32 *)R128_ADDR( reg ) ) +#define R128_WRITE(reg,val) out_le32( (volatile u32 *)R128_ADDR( reg ), (val) ) #else #define R128_READ(reg) le32_to_cpu( R128_DEREF( reg ) ) #define R128_WRITE(reg,val) \ @@ -418,6 +426,9 @@ wmb(); \ R128_DEREF8(reg) = val; \ } while (0) +#elif defined (__powerpc__) +#define R128_READ8(reg) in_8( (volatile u8 *)R128_ADDR(reg) ) +#define R128_WRITE8(reg,val) out_8( (volatile u8 *)R128_ADDR(reg), val ) #else #define R128_READ8(reg) R128_DEREF8( reg ) #define R128_WRITE8(reg,val) do { R128_DEREF8( reg ) = val; } while (0) @@ -493,8 +504,11 @@ * Ring control */ +#ifdef __powerpc__ +#define r128_flush_write_combine() (void)in_le32(ring) +#else #define r128_flush_write_combine() mb() - +#endif #define R128_VERBOSE 0 diff -uNr linux-2.4.21/drivers/char/drm/radeon_cp.c linux-2.4.21-ben2/drivers/char/drm/radeon_cp.c --- linux-2.4.21/drivers/char/drm/radeon_cp.c 2002-11-29 00:53:12.000000000 +0100 +++ linux-2.4.21-ben2/drivers/char/drm/radeon_cp.c 2003-06-27 15:41:30.000000000 +0200 @@ -37,12 +37,15 @@ #define RADEON_FIFO_DEBUG 0 -#if defined(__alpha__) +#if defined(__alpha__) || defined(__powerpc__) # define PCIGART_ENABLED #else # undef PCIGART_ENABLED #endif +#if __REALLY_HAVE_AGP && defined(CONFIG_ALL_PPC) +extern unsigned long agp_special_page; +#endif /* CP microcode (from ATI) */ static u32 radeon_cp_microcode[][2] = { @@ -313,7 +316,7 @@ return RADEON_READ(RADEON_CLOCK_CNTL_DATA); } -#if RADEON_FIFO_DEBUG +#if 1 /* RADEON_FIFO_DEBUG */ static void radeon_status( drm_radeon_private_t *dev_priv ) { printk( "%s:\n", __FUNCTION__ ); @@ -400,7 +403,8 @@ udelay( 1 ); } -#if RADEON_FIFO_DEBUG +#if 1 /* RADEON_FIFO_DEBUG */ + printk("wait_for_idle timeout\n"); DRM_ERROR( "failed!\n" ); radeon_status( dev_priv ); #endif @@ -611,6 +615,14 @@ dev_priv->ring.tail = cur_read_ptr; if ( !dev_priv->is_pci ) { +#if __REALLY_HAVE_AGP && defined(CONFIG_ALL_PPC) + if (_machine == _MACH_Pmac) { + dev_priv->ring.head = (__volatile__ u32 *) agp_special_page; + *dev_priv->ring.head = cur_read_ptr; + RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, + __pa( dev_priv->ring.head ) ); + } else +#endif RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, dev_priv->ring_rptr->offset ); } else { @@ -835,9 +847,9 @@ init->sarea_priv_offset); if ( !dev_priv->is_pci ) { - DRM_IOREMAP( dev_priv->cp_ring ); - DRM_IOREMAP( dev_priv->ring_rptr ); - DRM_IOREMAP( dev_priv->buffers ); + DRM_IOREMAPAGP( dev_priv->cp_ring, dev ); + DRM_IOREMAPAGP( dev_priv->ring_rptr, dev ); + DRM_IOREMAPAGP( dev_priv->buffers, dev ); if(!dev_priv->cp_ring->handle || !dev_priv->ring_rptr->handle || !dev_priv->buffers->handle) { @@ -982,9 +994,9 @@ drm_radeon_private_t *dev_priv = dev->dev_private; if ( !dev_priv->is_pci ) { - DRM_IOREMAPFREE( dev_priv->cp_ring ); - DRM_IOREMAPFREE( dev_priv->ring_rptr ); - DRM_IOREMAPFREE( dev_priv->buffers ); + DRM_IOREMAPAGPFREE( dev_priv->cp_ring ); + DRM_IOREMAPAGPFREE( dev_priv->ring_rptr ); + DRM_IOREMAPAGPFREE( dev_priv->buffers ); } else { if (!DRM(ati_pcigart_cleanup)( dev, dev_priv->phys_pci_gart, @@ -1351,14 +1363,15 @@ int i; for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { - radeon_update_ring_snapshot( ring ); + radeon_update_ring_snapshot( dev_priv, ring ); if ( ring->space > n ) return 0; udelay( 1 ); } /* FIXME: This return value is ignored in the BEGIN_RING macro! */ -#if RADEON_FIFO_DEBUG +#if 1 /* RADEON_FIFO_DEBUG */ + printk("wait ring timeout\n"); radeon_status( dev_priv ); DRM_ERROR( "failed!\n" ); #endif diff -uNr linux-2.4.21/drivers/char/drm/radeon_drv.h linux-2.4.21-ben2/drivers/char/drm/radeon_drv.h --- linux-2.4.21/drivers/char/drm/radeon_drv.h 2002-11-29 00:53:12.000000000 +0100 +++ linux-2.4.21-ben2/drivers/char/drm/radeon_drv.h 2003-06-27 15:41:07.000000000 +0200 @@ -31,6 +31,14 @@ #ifndef __RADEON_DRV_H__ #define __RADEON_DRV_H__ +#if defined(__powerpc__) +#define GET_RING_HEAD(ring) in_le32((volatile u32 *)(ring)->head) +#define SET_RING_HEAD(ring,val) out_le32((volatile u32 *)(ring)->head, (val)) +#else +#define GET_RING_HEAD(ring) le32_to_cpu(*(ring)->head) +#define SET_RING_HEAD(ring,val) *(ring)->head = cpu_to_le32(val) +#endif + typedef struct drm_radeon_freelist { unsigned int age; drm_buf_t *buf; @@ -150,12 +158,7 @@ extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n ); static inline void -radeon_update_ring_snapshot( drm_radeon_ring_buffer_t *ring ) -{ - ring->space = (*(volatile int *)ring->head - ring->tail) * sizeof(u32); - if ( ring->space <= 0 ) - ring->space += ring->size; -} +radeon_update_ring_snapshot( drm_radeon_private_t *dev_priv, drm_radeon_ring_buffer_t *ring ); extern int radeon_do_cp_idle( drm_radeon_private_t *dev_priv ); extern int radeon_do_cleanup_cp( drm_device_t *dev ); @@ -539,6 +542,9 @@ wmb(); \ RADEON_DEREF(reg) = val; \ } while (0) +#elif defined(__powerpc__) +#define RADEON_READ(reg) in_le32((volatile u32 *)RADEON_ADDR(reg)) +#define RADEON_WRITE(reg,val) out_le32((volatile u32 *)RADEON_ADDR(reg), (val)) #else #define RADEON_READ(reg) RADEON_DEREF( reg ) #define RADEON_WRITE(reg, val) do { RADEON_DEREF( reg ) = val; } while (0) @@ -557,6 +563,9 @@ wmb(); \ RADEON_DEREF8( reg ) = val; \ } while (0) +#elif defined(__powerpc__) +#define RADEON_READ8(reg) in_8((volatile u8 *)RADEON_ADDR(reg)) +#define RADEON_WRITE8(reg,val) out_8((volatile u8 *)RADEON_ADDR(reg), (val)) #else #define RADEON_READ8(reg) RADEON_DEREF8( reg ) #define RADEON_WRITE8(reg, val) do { RADEON_DEREF8( reg ) = val; } while (0) @@ -652,7 +661,7 @@ drm_radeon_ring_buffer_t *ring = &dev_priv->ring; int i; \ if ( ring->space < ring->high_mark ) { \ for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) { \ - radeon_update_ring_snapshot( ring ); \ + radeon_update_ring_snapshot( dev_priv, ring ); \ if ( ring->space >= ring->high_mark ) \ goto __ring_space_done; \ udelay( 1 ); \ @@ -694,12 +703,28 @@ * Ring control */ +#if defined(__powerpc__) +#define radeon_flush_write_combine() do { mb(); (void)in_le32(ring); mb(); } while(0) +#else #define radeon_flush_write_combine() mb() - +#endif #define RADEON_VERBOSE 0 +#define RADEON_DEBUG +#ifdef RADEON_DEBUG +#define RING_LOCALS int write; unsigned int mask; volatile u32 *ring; int dbg; +#define DEBUG_INIT(n) dbg = n +#define DEBUG_INC() do { if (dbg <= 0) printk("Argh 1 ! (%s:%d)\n", __FILE__, __LINE__); \ + dbg--; } while(0) +#define DEBUG_END() do { if (dbg != 0) printk("Argh 2/%d ! (%s:%d)\n", dbg, __FILE__, __LINE__); \ + dbg--; } while(0) +#else #define RING_LOCALS int write; unsigned int mask; volatile u32 *ring; +#define DEBUG_INIT() +#define DEBUG_INC() +#define DEBUG_END() +#endif #define BEGIN_RING( n ) do { \ if ( RADEON_VERBOSE ) { \ @@ -713,6 +738,7 @@ ring = dev_priv->ring.start; \ write = dev_priv->ring.tail; \ mask = dev_priv->ring.tail_mask; \ + DEBUG_INIT(n); \ } while (0) #define ADVANCE_RING() do { \ @@ -720,6 +746,7 @@ DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \ write, dev_priv->ring.tail ); \ } \ + DEBUG_END(); \ radeon_flush_write_combine(); \ dev_priv->ring.tail = write; \ RADEON_WRITE( RADEON_CP_RB_WPTR, write ); \ @@ -730,10 +757,20 @@ DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \ (unsigned int)(x), write ); \ } \ - ring[write++] = (x); \ + DEBUG_INC(); \ + ring[write++] = cpu_to_le32(x); \ write &= mask; \ } while (0) #define RADEON_PERFORMANCE_BOXES 0 +static inline void +radeon_update_ring_snapshot( drm_radeon_private_t *dev_priv, drm_radeon_ring_buffer_t *ring ) +{ +// ring->space = (GET_RING_HEAD(ring) - ring->tail) * sizeof(u32); + ring->space = (RADEON_READ(0x710) - ring->tail) * sizeof(u32); + if ( ring->space <= 0 ) + ring->space += ring->size; +} + #endif /* __RADEON_DRV_H__ */ diff -uNr linux-2.4.21/drivers/char/drm/radeon_state.c linux-2.4.21-ben2/drivers/char/drm/radeon_state.c --- linux-2.4.21/drivers/char/drm/radeon_state.c 2002-11-29 00:53:12.000000000 +0100 +++ linux-2.4.21-ben2/drivers/char/drm/radeon_state.c 2003-06-27 15:41:26.000000000 +0200 @@ -849,7 +849,7 @@ u32 *data = (u32 *) ((char *)dev_priv->buffers->handle + buf->offset + start); - data[dwords++] = RADEON_CP_PACKET2; + data[dwords++] = cpu_to_le32(RADEON_CP_PACKET2); } buf_priv->dispatched = 1; @@ -913,18 +913,22 @@ data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset + start); - data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 ); + data[0] = cpu_to_le32(CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 )); - data[1] = offset; - data[2] = RADEON_MAX_VB_VERTS; - data[3] = format; - data[4] = (prim | RADEON_PRIM_WALK_IND | + data[1] = cpu_to_le32(offset); + data[2] = cpu_to_le32(RADEON_MAX_VB_VERTS); + data[3] = cpu_to_le32(format); + data[4] = cpu_to_le32((prim | RADEON_PRIM_WALK_IND | RADEON_COLOR_ORDER_RGBA | RADEON_VTX_FMT_RADEON_MODE | - (count << RADEON_NUM_VERTICES_SHIFT) ); + (count << RADEON_NUM_VERTICES_SHIFT) )); if ( count & 0x1 ) { +#ifdef __LITTLE_ENDIAN data[dwords-1] &= 0x0000ffff; +#else + data[dwords-1] &= 0xffff0000; +#endif } do { @@ -1067,22 +1071,22 @@ */ buffer = (u32 *)((char *)dev_priv->buffers->handle + buf->offset); - buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 ); - buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | + buffer[0] = cpu_to_le32(CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 )); + buffer[1] = cpu_to_le32((RADEON_GMC_DST_PITCH_OFFSET_CNTL | RADEON_GMC_BRUSH_NONE | (format << 8) | RADEON_GMC_SRC_DATATYPE_COLOR | RADEON_ROP3_S | RADEON_DP_SRC_SOURCE_HOST_DATA | RADEON_GMC_CLR_CMP_CNTL_DIS | - RADEON_GMC_WR_MSK_DIS); + RADEON_GMC_WR_MSK_DIS)); - buffer[2] = (tex->pitch << 22) | (tex->offset >> 10); - buffer[3] = 0xffffffff; - buffer[4] = 0xffffffff; - buffer[5] = (y << 16) | image->x; - buffer[6] = (height << 16) | image->width; - buffer[7] = dwords; + buffer[2] = cpu_to_le32((tex->pitch << 22) | (tex->offset >> 10)); + buffer[3] = cpu_to_le32(0xffffffff); + buffer[4] = cpu_to_le32(0xffffffff); + buffer[5] = cpu_to_le32((y << 16) | image->x); + buffer[6] = cpu_to_le32((height << 16) | image->width); + buffer[7] = cpu_to_le32(dwords); buffer += 8; diff -uNr linux-2.4.21/drivers/i2c/i2c-keywest.c linux-2.4.21-ben2/drivers/i2c/i2c-keywest.c --- linux-2.4.21/drivers/i2c/i2c-keywest.c 2002-11-29 00:53:13.000000000 +0100 +++ linux-2.4.21-ben2/drivers/i2c/i2c-keywest.c 2003-06-27 15:41:06.000000000 +0200 @@ -256,6 +256,7 @@ len = 1; buffer = &data->byte; iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; + //iface->cur_mode |= KW_I2C_MODE_COMBINED; break; case I2C_SMBUS_WORD_DATA: len = 2; @@ -267,6 +268,7 @@ len = data->block[0]; buffer = &data->block[1]; iface->cur_mode |= KW_I2C_MODE_STANDARDSUB; + //iface->cur_mode |= KW_I2C_MODE_COMBINED; break; default: return -1; diff -uNr linux-2.4.21/drivers/ide/Config.in linux-2.4.21-ben2/drivers/ide/Config.in --- linux-2.4.21/drivers/ide/Config.in 2003-06-13 16:51:33.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ide/Config.in 2003-06-27 15:41:06.000000000 +0200 @@ -86,6 +86,9 @@ dep_bool ' Probe internal Kauai ATA/100 first' CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST $CONFIG_BLK_DEV_IDE_PMAC dep_bool ' PowerMac IDE DMA support' CONFIG_BLK_DEV_IDEDMA_PMAC $CONFIG_BLK_DEV_IDE_PMAC dep_bool ' Use DMA by default' CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO $CONFIG_BLK_DEV_IDEDMA_PMAC + if [ "$CONFIG_ADB_PMU" = "y" ]; then + bool ' Blink laptop LED on activity' CONFIG_PMU_HD_BLINK + fi if [ "$CONFIG_BLK_DEV_IDE_PMAC" = "y" ]; then define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PMAC fi diff -uNr linux-2.4.21/drivers/ide/arm/rapide.c linux-2.4.21-ben2/drivers/ide/arm/rapide.c --- linux-2.4.21/drivers/ide/arm/rapide.c 2003-06-13 16:51:33.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ide/arm/rapide.c 2003-06-27 15:41:06.000000000 +0200 @@ -40,6 +40,7 @@ } hw.io_ports[IDE_CONTROL_OFFSET] = port + 0x206; hw.irq = ec->irq; + hw.chipset = ide_generic; return ide_register_hw(&hw, NULL); } diff -uNr linux-2.4.21/drivers/ide/ide-disk.c linux-2.4.21-ben2/drivers/ide/ide-disk.c --- linux-2.4.21/drivers/ide/ide-disk.c 2003-06-13 16:51:33.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ide/ide-disk.c 2003-06-27 15:41:07.000000000 +0200 @@ -1161,13 +1161,17 @@ { struct hd_driveid *id = drive->id; unsigned long capacity = drive->cyl * drive->head * drive->sect; - unsigned long set_max = idedisk_read_native_max_address(drive); + unsigned long set_max = 0; unsigned long long capacity_2 = capacity; unsigned long long set_max_ext; drive->capacity48 = 0; drive->select.b.lba = 0; + /* That stupid compact flash doesn't like the command */ + if (!drive->is_flash) + set_max = idedisk_read_native_max_address(drive); + (void) idedisk_supports_host_protected_area(drive); if (id->cfs_enable_2 & 0x0400) { @@ -1566,7 +1570,7 @@ static int set_lba_addressing (ide_drive_t *drive, int arg) { - return (probe_lba_addressing(drive, arg)); + return probe_lba_addressing(drive, arg); } static void idedisk_add_settings(ide_drive_t *drive) @@ -1644,13 +1648,20 @@ break; } -#if 1 (void) probe_lba_addressing(drive, 1); -#else - /* if using 48-bit addressing bump the request size up */ - if (probe_lba_addressing(drive, 1)) - blk_queue_max_sectors(&drive->queue, 2048); -#endif + + if (drive->addressing == 1) { + int max_s = 2048, i, off = drive->select.b.unit << PARTN_BITS; + ide_hwif_t *hwif = HWIF(drive); + + if (max_s > hwif->rqsize) + max_s = hwif->rqsize; + + for (i = 0; i < (1 << PARTN_BITS); i++) + max_sectors[hwif->major][off + i] = max_s; + + printk("%s: max request size: %dKiB\n", drive->name, max_s / 2); + } /* Extract geometry if we did not already have one for the drive */ if (!drive->cyl || !drive->head || !drive->sect) { diff -uNr linux-2.4.21/drivers/ide/ide-dma.c linux-2.4.21-ben2/drivers/ide/ide-dma.c --- linux-2.4.21/drivers/ide/ide-dma.c 2003-06-13 16:51:33.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ide/ide-dma.c 2003-06-27 15:41:09.000000000 +0200 @@ -257,6 +257,8 @@ if (hwif->sg_dma_active) BUG(); + hwif->sg_dma_direction = ddir; + bh = rq->bh; do { int contig = 0; @@ -299,7 +301,6 @@ if(nents == 0) BUG(); - hwif->sg_dma_direction = ddir; return pci_map_sg(hwif->pci_dev, sg, nents, ddir); } diff -uNr linux-2.4.21/drivers/ide/ide-probe.c linux-2.4.21-ben2/drivers/ide/ide-probe.c --- linux-2.4.21/drivers/ide/ide-probe.c 2003-06-13 16:51:33.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ide/ide-probe.c 2003-06-27 15:41:02.000000000 +0200 @@ -768,6 +768,7 @@ #ifdef CONFIG_BLK_DEV_IDE if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) { extern void probe_cmos_for_drives(ide_hwif_t *); + probe_cmos_for_drives(hwif); } #endif @@ -971,6 +972,12 @@ q->queuedata = HWGROUP(drive); blk_init_queue(q, do_ide_request); + + /* + * enable led activity for disk drives only + */ + if (drive->media == ide_disk && HWIF(drive)->led_act) + blk_queue_activity_fn(&drive->queue, HWIF(drive)->led_act, drive); } #undef __IRQ_HELL_SPIN @@ -1163,6 +1170,9 @@ units = MAX_DRIVES; + if (!hwif->rqsize) + hwif->rqsize = hwif->addressing ? 128 : 65536; + minors = units * (1<major] = max_sect; max_readahead[hwif->major] = max_ra; for (unit = 0; unit < minors; ++unit) { + int max_s = 128; + *bs++ = BLOCK_SIZE; - /* - * IDE can do up to 128K per request == 256 - */ - *max_sect++ = ((hwif->rqsize) ? hwif->rqsize : 128); + + if (max_s > hwif->rqsize) + max_s = hwif->rqsize; + + *max_sect++ = max_s; *max_ra++ = vm_max_readahead; } diff -uNr linux-2.4.21/drivers/ide/ppc/pmac.c linux-2.4.21-ben2/drivers/ide/ppc/pmac.c --- linux-2.4.21/drivers/ide/ppc/pmac.c 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ide/ppc/pmac.c 2003-06-27 15:41:03.000000000 +0200 @@ -38,10 +38,8 @@ #include #include #include -#ifdef CONFIG_PMAC_PBOOK #include #include -#endif #include "ide_modes.h" #include "ide-timing.h" @@ -357,6 +355,89 @@ }; #endif /* CONFIG_PMAC_PBOOK */ +#ifdef CONFIG_PMU_HD_BLINK + +/* Set to 50ms */ +#define PMU_HD_BLINK_TIME (HZ/20) + +static struct adb_request pmu_blink_on, pmu_blink_off; +static spinlock_t pmu_blink_lock; +static unsigned long pmu_blink_stoptime; +static int pmu_blink_ledstate; +static struct timer_list pmu_blink_timer; + +static void +pmu_hd_blink_timeout(unsigned long data) +{ + unsigned long flags; + + spin_lock_irqsave(&pmu_blink_lock, flags); + + /* We may have been triggered again in a racy way, check + * that we really want to switch it off + */ + if (time_after(pmu_blink_stoptime, jiffies)) + goto done; + + /* Previous req. not complete, try 50ms more */ + if (pmu_blink_off.complete == 0) + mod_timer(&pmu_blink_timer, jiffies + PMU_HD_BLINK_TIME); + else if (pmu_blink_ledstate) { + pmu_request(&pmu_blink_off, NULL, 4, 0xee, 4, 0, 0); + pmu_blink_ledstate = 0; + } +done: + spin_unlock_irqrestore(&pmu_blink_lock, flags); +} + +static void +pmu_hd_kick_blink(void *data, int rw) +{ + unsigned long flags; + + pmu_blink_stoptime = jiffies + PMU_HD_BLINK_TIME; + wmb(); + mod_timer(&pmu_blink_timer, pmu_blink_stoptime); + if (pmu_blink_ledstate == 1) + return; + spin_lock_irqsave(&pmu_blink_lock, flags); + if (pmu_blink_on.complete && !pmu_blink_ledstate) { + pmu_request(&pmu_blink_on, NULL, 4, 0xee, 4, 0, 1); + pmu_blink_ledstate = 1; + } + spin_unlock_irqrestore(&pmu_blink_lock, flags); +} + +static int +pmu_hd_blink_init(void) +{ + struct device_node *dt; + const char *model; + + if (pmu_get_model() != PMU_KEYLARGO_BASED) + return 0; + + dt = find_devices("device-tree"); + if (dt == NULL) + return 0; + model = (const char *)get_property(dt, "model", NULL); + if (model == NULL) + return 0; + if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 && + strncmp(model, "iBook", strlen("iBook")) != 0) + return 0; + + pmu_blink_on.complete = 1; + pmu_blink_off.complete = 1; + spin_lock_init(&pmu_blink_lock); + init_timer(&pmu_blink_timer); + pmu_blink_timer.function = pmu_hd_blink_timeout; + + return 1; +} + +#endif /* CONFIG_PMU_HD_BLINK */ + /* * N.B. this can't be an initfunc, because the media-bay task can * call ide_[un]register at any time. @@ -945,9 +1026,12 @@ unsigned long base, regbase; int irq; ide_hwif_t *hwif; - +#ifdef CONFIG_PMU_HD_BLINK + int has_blink; +#endif if (_machine != _MACH_Pmac) return; + pp = &atas; rp = &removables; p = find_devices("ATA"); @@ -957,6 +1041,14 @@ p = find_type_devices("ide"); if (p == NULL) p = find_type_devices("ata"); + + if (p == NULL) + return; + +#ifdef CONFIG_PMU_HD_BLINK + has_blink = pmu_hd_blink_init(); +#endif /* CONFIG_PMU_HD_BLINK */ + /* Move removable devices such as the media-bay CDROM on the PB3400 to the end of the list. */ for (; p != NULL; p = nextp) { @@ -1163,6 +1255,11 @@ hwif->selectproc = pmac_ide_selectproc; hwif->speedproc = pmac_ide_tune_chipset; +#ifdef CONFIG_PMU_HD_BLINK + if (has_blink) + hwif->led_act = pmu_hd_kick_blink; +#endif /* CONFIG_PMU_HD_BLINK */ + printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s\n", i, model_name[pmif->kind], pmif->aapl_bus_id, in_bay ? " (mediabay)" : ""); diff -uNr linux-2.4.21/drivers/ide/setup-pci.c linux-2.4.21-ben2/drivers/ide/setup-pci.c --- linux-2.4.21/drivers/ide/setup-pci.c 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ide/setup-pci.c 2003-06-27 15:41:25.000000000 +0200 @@ -51,7 +51,8 @@ { int h; ide_hwif_t *hwif; - + int reserved = ide_reserved_hwifs(); + /* * Look for a hwif with matching io_base specified using * parameters to ide_setup(). @@ -90,18 +91,18 @@ */ if (bootable) { for (h = 0; h < MAX_HWIFS; ++h) { - hwif = &ide_hwifs[h]; + hwif = ide_hwifs + h; if (hwif->chipset == ide_unknown) return hwif; /* pick an unused entry */ } } else { - for (h = 2; h < MAX_HWIFS; ++h) { + for (h = reserved; h < MAX_HWIFS; ++h) { hwif = ide_hwifs + h; if (hwif->chipset == ide_unknown) return hwif; /* pick an unused entry */ } } - for (h = 0; h < 2; ++h) { + for (h = 0; h < reserved; ++h) { hwif = ide_hwifs + h; if (hwif->chipset == ide_unknown) return hwif; /* pick an unused entry */ diff -uNr linux-2.4.21/drivers/ieee1394/Config.in linux-2.4.21-ben2/drivers/ieee1394/Config.in --- linux-2.4.21/drivers/ieee1394/Config.in 2002-08-03 02:39:44.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ieee1394/Config.in 2003-06-27 15:41:06.000000000 +0200 @@ -40,6 +40,7 @@ fi bool 'Excessive debugging output' CONFIG_IEEE1394_VERBOSEDEBUG + bool "OUI Database built-in" CONFIG_IEEE1394_OUI_DB fi endmenu fi diff -uNr linux-2.4.21/drivers/ieee1394/Makefile linux-2.4.21-ben2/drivers/ieee1394/Makefile --- linux-2.4.21/drivers/ieee1394/Makefile 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ieee1394/Makefile 2003-06-27 15:41:24.000000000 +0200 @@ -8,7 +8,7 @@ list-multi := ieee1394.o ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \ - highlevel.o csr.o nodemgr.o dma.o iso.o + highlevel.o csr.o nodemgr.o oui.o dma.o iso.o obj-$(CONFIG_IEEE1394) += ieee1394.o obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o @@ -25,3 +25,7 @@ ieee1394.o: $(ieee1394-objs) $(LD) $(LDFLAGS) -r -o $@ $(ieee1394-objs) + +oui.o: oui.c +oui.c: oui.db oui2c.sh + $(CONFIG_SHELL) oui2c.sh < oui.db > $@ diff -uNr linux-2.4.21/drivers/ieee1394/dv1394.c linux-2.4.21-ben2/drivers/ieee1394/dv1394.c --- linux-2.4.21/drivers/ieee1394/dv1394.c 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ieee1394/dv1394.c 2003-06-27 15:41:25.000000000 +0200 @@ -114,7 +114,7 @@ #include "ieee1394.h" #include "ieee1394_types.h" -#include "ieee1394_hotplug.h" +#include "nodemgr.h" #include "hosts.h" #include "ieee1394_core.h" #include "highlevel.h" diff -uNr linux-2.4.21/drivers/ieee1394/highlevel.c linux-2.4.21-ben2/drivers/ieee1394/highlevel.c --- linux-2.4.21/drivers/ieee1394/highlevel.c 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ieee1394/highlevel.c 2003-06-27 15:41:19.000000000 +0200 @@ -205,6 +205,29 @@ } +struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl, unsigned long key) +{ + struct list_head *lh; + struct hl_host_info *hi; + struct hpsb_host *host = NULL; + + if (!hl) + return NULL; + + read_lock(&hl->host_info_lock); + list_for_each (lh, &hl->host_info_list) { + hi = list_entry(lh, struct hl_host_info, list); + if (hi->key == key) { + host = hi->host; + break; + } + } + read_unlock(&hl->host_info_lock); + + return host; +} + + void hpsb_register_highlevel(struct hpsb_highlevel *hl) { struct list_head *lh; diff -uNr linux-2.4.21/drivers/ieee1394/highlevel.h linux-2.4.21-ben2/drivers/ieee1394/highlevel.h --- linux-2.4.21/drivers/ieee1394/highlevel.h 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ieee1394/highlevel.h 2003-06-27 15:41:06.000000000 +0200 @@ -155,19 +155,28 @@ /* Retrieve a hostinfo pointer bound to this driver/host */ void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host); + /* Allocate a hostinfo pointer of data_size bound to this driver/host */ void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, size_t data_size); + /* Free and remove the hostinfo pointer bound to this driver/host */ void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host); + /* Set an alternate lookup key for the hostinfo bound to this driver/host */ void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host, unsigned long key); + /* Retrieve the alternate lookup key for the hostinfo bound to this driver/host */ unsigned long hpsb_get_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host); -/* Retrive a hostinfo pointer bound to this driver using its alternate key */ + +/* Retrieve a hostinfo pointer bound to this driver using its alternate key */ void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key); + /* Set the hostinfo pointer to something useful. Usually follows a call to * hpsb_create_hostinfo, where the size is 0. */ int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host, void *data); +/* Retrieve hpsb_host using a highlevel handle and a key */ +struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl, unsigned long key); + #endif /* IEEE1394_HIGHLEVEL_H */ diff -uNr linux-2.4.21/drivers/ieee1394/ieee1394_core.c linux-2.4.21-ben2/drivers/ieee1394/ieee1394_core.c --- linux-2.4.21/drivers/ieee1394/ieee1394_core.c 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ieee1394/ieee1394_core.c 2003-06-27 15:41:09.000000000 +0200 @@ -41,7 +41,6 @@ #include "ieee1394_transactions.h" #include "csr.h" #include "nodemgr.h" -#include "ieee1394_hotplug.h" #include "dma.h" #include "iso.h" @@ -1297,6 +1296,7 @@ EXPORT_SYMBOL(hpsb_listen_channel); EXPORT_SYMBOL(hpsb_unlisten_channel); EXPORT_SYMBOL(hpsb_get_hostinfo); +EXPORT_SYMBOL(hpsb_get_host_bykey); EXPORT_SYMBOL(hpsb_create_hostinfo); EXPORT_SYMBOL(hpsb_destroy_hostinfo); EXPORT_SYMBOL(hpsb_set_hostinfo_key); diff -uNr linux-2.4.21/drivers/ieee1394/ieee1394_hotplug.h linux-2.4.21-ben2/drivers/ieee1394/ieee1394_hotplug.h --- linux-2.4.21/drivers/ieee1394/ieee1394_hotplug.h 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ieee1394/ieee1394_hotplug.h 2003-06-27 15:41:10.000000000 +0200 @@ -1,8 +1,7 @@ #ifndef _IEEE1394_HOTPLUG_H #define _IEEE1394_HOTPLUG_H -#include "ieee1394_core.h" -#include "nodemgr.h" +#include #define IEEE1394_MATCH_VENDOR_ID 0x0001 #define IEEE1394_MATCH_MODEL_ID 0x0002 @@ -26,57 +25,4 @@ void *driver_data; }; -struct hpsb_protocol_driver { - /* The name of the driver, e.g. SBP2 or IP1394 */ - const char *name; - - /* - * The device id table describing the protocols and/or devices - * supported by this driver. This is used by the nodemgr to - * decide if a driver could support a given node, but the - * probe function below can implement further protocol - * dependent or vendor dependent checking. - */ - struct ieee1394_device_id *id_table; - - /* - * The probe function is called when a device is added to the - * bus and the nodemgr finds a matching entry in the drivers - * device id table or when registering this driver and a - * previously unhandled device can be handled. The driver may - * decline to handle the device based on further investigation - * of the device (or whatever reason) in which case a negative - * error code should be returned, otherwise 0 should be - * returned. The driver may use the driver_data field in the - * unit directory to store per device driver specific data. - */ - int (*probe)(struct unit_directory *ud); - - /* - * The disconnect function is called when a device is removed - * from the bus or if it wasn't possible to read the guid - * after the last bus reset. - */ - void (*disconnect)(struct unit_directory *ud); - - /* - * The update function is called when the node has just - * survived a bus reset, i.e. it is still present on the bus. - * However, it may be necessary to reestablish the connection - * or login into the node again, depending on the protocol. - */ - void (*update)(struct unit_directory *ud); - - /* Driver in list of all registered drivers */ - struct list_head list; - - /* The list of unit directories managed by this driver */ - struct list_head unit_directories; -}; - -int hpsb_register_protocol(struct hpsb_protocol_driver *driver); -void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver); - -void hpsb_release_unit_directory(struct unit_directory *ud); - #endif /* _IEEE1394_HOTPLUG_H */ diff -uNr linux-2.4.21/drivers/ieee1394/ieee1394_types.h linux-2.4.21-ben2/drivers/ieee1394/ieee1394_types.h --- linux-2.4.21/drivers/ieee1394/ieee1394_types.h 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ieee1394/ieee1394_types.h 2003-06-27 15:41:32.000000000 +0200 @@ -19,6 +19,15 @@ #define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif +#ifndef BITS_TO_LONGS /* < 2.4.21-pre6 */ +#define BITS_TO_LONGS(bits) \ + (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) +#define DECLARE_BITMAP(name,bits) \ + unsigned long name[BITS_TO_LONGS(bits)] +#define CLEAR_BITMAP(name,bits) \ + memset(name, 0, BITS_TO_LONGS(bits)*sizeof(unsigned long)) +#endif + /* Transaction Label handling */ struct hpsb_tlabel_pool { diff -uNr linux-2.4.21/drivers/ieee1394/iso.c linux-2.4.21-ben2/drivers/ieee1394/iso.c --- linux-2.4.21/drivers/ieee1394/iso.c 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ieee1394/iso.c 2003-06-27 15:41:05.000000000 +0200 @@ -32,7 +32,6 @@ } dma_region_free(&iso->data_buf); - kfree(iso->infos); kfree(iso); } @@ -70,14 +69,11 @@ /* allocate and write the struct hpsb_iso */ - iso = kmalloc(sizeof(*iso), SLAB_KERNEL); + iso = kmalloc(sizeof(*iso) + buf_packets * sizeof(struct hpsb_iso_packet_info), GFP_KERNEL); if(!iso) return NULL; - /* allocate ringbuffer of packet descriptors */ - iso->infos = kmalloc(buf_packets * sizeof(struct hpsb_iso_packet_info), SLAB_KERNEL); - if(!iso->infos) - return NULL; + iso->infos = (struct hpsb_iso_packet_info *)(iso + 1); iso->type = type; iso->host = host; diff -uNr linux-2.4.21/drivers/ieee1394/iso.h linux-2.4.21-ben2/drivers/ieee1394/iso.h --- linux-2.4.21/drivers/ieee1394/iso.h 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ieee1394/iso.h 2003-06-27 15:41:05.000000000 +0200 @@ -79,9 +79,6 @@ /* size of data_buf, in bytes (always a multiple of PAGE_SIZE) */ unsigned int buf_size; - /* ringbuffer of packet descriptors in regular kernel memory */ - struct hpsb_iso_packet_info *infos; - /* # of packets in the ringbuffer */ unsigned int buf_packets; @@ -118,6 +115,11 @@ /* cycle at which next packet will be transmitted, -1 if not known */ int xmit_cycle; + + /* ringbuffer of packet descriptors in regular kernel memory + * XXX Keep this last, since we use over-allocated memory from + * this entry to fill this field. */ + struct hpsb_iso_packet_info *infos; }; /* functions available to high-level drivers (e.g. raw1394) */ diff -uNr linux-2.4.21/drivers/ieee1394/nodemgr.c linux-2.4.21-ben2/drivers/ieee1394/nodemgr.c --- linux-2.4.21/drivers/ieee1394/nodemgr.c 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ieee1394/nodemgr.c 2003-06-27 15:41:06.000000000 +0200 @@ -23,9 +23,9 @@ #include "ieee1394_types.h" #include "ieee1394.h" +#include "nodemgr.h" #include "hosts.h" #include "ieee1394_transactions.h" -#include "ieee1394_hotplug.h" #include "highlevel.h" #include "csr.h" #include "nodemgr.h" @@ -92,15 +92,26 @@ #ifdef CONFIG_PROC_FS -#define PUTF(fmt, args...) out += sprintf(out, fmt, ## args) +#define PUTF(fmt, args...) \ +do { \ + len += sprintf(page + len, fmt, ## args); \ + pos = begin + len; \ + if (pos < off) { \ + len = 0; \ + begin = pos; \ + } \ + if (pos > off + count) \ + goto done_proc; \ +} while (0) + static int raw1394_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { struct list_head *lh; struct node_entry *ne; - int len; - char *out = page; + off_t begin = 0, pos = 0; + int len = 0; if (down_interruptible(&nodemgr_serialize)) return -EINTR; @@ -180,18 +191,18 @@ } +done_proc: up(&nodemgr_serialize); - len = out - page; - len -= off; - if (len < count) { + *start = page + (off - begin); + len -= (off - begin); + if (len > count) + len = count; + else { *eof = 1; if (len <= 0) return 0; - } else - len = count; - - *start = page + off; + } return len; } diff -uNr linux-2.4.21/drivers/ieee1394/nodemgr.h linux-2.4.21-ben2/drivers/ieee1394/nodemgr.h --- linux-2.4.21/drivers/ieee1394/nodemgr.h 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ieee1394/nodemgr.h 2003-06-27 15:41:34.000000000 +0200 @@ -20,6 +20,9 @@ #ifndef _IEEE1394_NODEMGR_H #define _IEEE1394_NODEMGR_H +#include "ieee1394_core.h" +#include "ieee1394_hotplug.h" + #define CONFIG_ROM_BUS_INFO_LENGTH(q) ((q) >> 24) #define CONFIG_ROM_BUS_CRC_LENGTH(q) (((q) >> 16) & 0xff) #define CONFIG_ROM_BUS_CRC(q) ((q) & 0xffff) @@ -152,6 +155,58 @@ quadlet_t quadlets[0]; }; +struct hpsb_protocol_driver { + /* The name of the driver, e.g. SBP2 or IP1394 */ + const char *name; + + /* + * The device id table describing the protocols and/or devices + * supported by this driver. This is used by the nodemgr to + * decide if a driver could support a given node, but the + * probe function below can implement further protocol + * dependent or vendor dependent checking. + */ + struct ieee1394_device_id *id_table; + + /* + * The probe function is called when a device is added to the + * bus and the nodemgr finds a matching entry in the drivers + * device id table or when registering this driver and a + * previously unhandled device can be handled. The driver may + * decline to handle the device based on further investigation + * of the device (or whatever reason) in which case a negative + * error code should be returned, otherwise 0 should be + * returned. The driver may use the driver_data field in the + * unit directory to store per device driver specific data. + */ + int (*probe)(struct unit_directory *ud); + + /* + * The disconnect function is called when a device is removed + * from the bus or if it wasn't possible to read the guid + * after the last bus reset. + */ + void (*disconnect)(struct unit_directory *ud); + + /* + * The update function is called when the node has just + * survived a bus reset, i.e. it is still present on the bus. + * However, it may be necessary to reestablish the connection + * or login into the node again, depending on the protocol. + */ + void (*update)(struct unit_directory *ud); + + /* Driver in list of all registered drivers */ + struct list_head list; + + /* The list of unit directories managed by this driver */ + struct list_head unit_directories; +}; + +int hpsb_register_protocol(struct hpsb_protocol_driver *driver); +void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver); +void hpsb_release_unit_directory(struct unit_directory *ud); + static inline int hpsb_node_entry_valid(struct node_entry *ne) { return ne->generation == get_hpsb_generation(ne->host); diff -uNr linux-2.4.21/drivers/ieee1394/ohci1394.c linux-2.4.21-ben2/drivers/ieee1394/ohci1394.c --- linux-2.4.21/drivers/ieee1394/ohci1394.c 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ieee1394/ohci1394.c 2003-06-27 15:41:25.000000000 +0200 @@ -164,7 +164,7 @@ printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args) static char version[] __devinitdata = - "$Rev: 896 $ Ben Collins "; + "$Rev: 928 $ Ben Collins "; /* Module Parameters */ MODULE_PARM(phys_dma,"i"); @@ -623,8 +623,10 @@ u32 cycleTimer; int idx = d->prg_ind; - DBGMSG(ohci->id, "Inserting packet for node %d, tlabel=%d, tcode=0x%x, speed=%d", - packet->node_id, packet->tlabel, packet->tcode, packet->speed_code); + DBGMSG(ohci->id, "Inserting packet for node " NODE_BUS_FMT + ", tlabel=%d, tcode=0x%x, speed=%d", + NODE_BUS_ARGS(packet->node_id), packet->tlabel, + packet->tcode, packet->speed_code); d->prg_cpu[idx]->begin.address = 0; d->prg_cpu[idx]->begin.branchAddress = 0; @@ -1514,6 +1516,7 @@ so disable branch and enable interrupt */ next->branchAddress = 0; next->control |= cpu_to_le32(3 << 20); + next->status = cpu_to_le32(recv->buf_stride); /* link prev to next */ prev->branchAddress = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog, @@ -2451,7 +2454,7 @@ reg_write(ohci,OHCI1394_PhyReqFilterLoSet, 0x00000000); } - DBGMSG(ohci->id, "PhyReqFilter=%08x%08x\n", + DBGMSG(ohci->id, "PhyReqFilter=%08x%08x", reg_read(ohci,OHCI1394_PhyReqFilterHiSet), reg_read(ohci,OHCI1394_PhyReqFilterLoSet)); @@ -2699,19 +2702,29 @@ #ifdef OHCI1394_DEBUG if (datasize) - DBGMSG(ohci->id, - "Packet sent to node %d tcode=0x%X tLabel=" - "0x%02X ack=0x%X spd=%d dataLength=%d ctx=%d", - (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1]) - >>16)&0x3f, - (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0]) - >>4)&0xf, - (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0]) - >>10)&0x3f, - status&0x1f, (status>>5)&0x3, - le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3]) - >>16, - d->ctx); + if(((le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf) == 0xa) + DBGMSG(ohci->id, + "Stream packet sent to channel %d tcode=0x%X " + "ack=0x%X spd=%d dataLength=%d ctx=%d", + (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>8)&0x3f, + (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf, + status&0x1f, (status>>5)&0x3, + le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])>>16, + d->ctx); + else + DBGMSG(ohci->id, + "Packet sent to node %d tcode=0x%X tLabel=" + "%d ack=0x%X spd=%d dataLength=%d ctx=%d", + (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1]) + >>16)&0x3f, + (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0]) + >>4)&0xf, + (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0]) + >>10)&0x3f, + status&0x1f, (status>>5)&0x3, + le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3]) + >>16, + d->ctx); else DBGMSG(ohci->id, "Packet sent to node %d tcode=0x%X tLabel=" diff -uNr linux-2.4.21/drivers/ieee1394/oui.db linux-2.4.21-ben2/drivers/ieee1394/oui.db --- linux-2.4.21/drivers/ieee1394/oui.db 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/drivers/ieee1394/oui.db 2003-06-27 15:41:24.000000000 +0200 @@ -0,0 +1,4931 @@ +000000 XEROX CORPORATION +000001 XEROX CORPORATION +000002 XEROX CORPORATION +000003 XEROX CORPORATION +000004 XEROX CORPORATION +000005 XEROX CORPORATION +000006 XEROX CORPORATION +000007 XEROX CORPORATION +000008 XEROX CORPORATION +000009 XEROX CORPORATION +00000A OMRON TATEISI ELECTRONICS CO. +00000B MATRIX CORPORATION +00000C CISCO SYSTEMS, INC. +00000D FIBRONICS LTD. +00000E FUJITSU LIMITED +00000F NEXT, INC. +000010 SYTEK INC. +000011 NORMEREL SYSTEMES +000012 INFORMATION TECHNOLOGY LIMITED +000013 CAMEX +000014 NETRONIX +000015 DATAPOINT CORPORATION +000016 DU PONT PIXEL SYSTEMS . +000017 TEKELEC +000018 WEBSTER COMPUTER CORPORATION +000019 APPLIED DYNAMICS INTERNATIONAL +00001A ADVANCED MICRO DEVICES +00001B NOVELL INC. +00001C BELL TECHNOLOGIES +00001D CABLETRON SYSTEMS, INC. +00001E TELSIST INDUSTRIA ELECTRONICA +00001F Telco Systems, Inc. +000020 DATAINDUSTRIER DIAB AB +000021 SUREMAN COMP. & COMMUN. CORP. +000022 VISUAL TECHNOLOGY INC. +000023 ABB INDUSTRIAL SYSTEMS AB +000024 CONNECT AS +000025 RAMTEK CORP. +000026 SHA-KEN CO., LTD. +000027 JAPAN RADIO COMPANY +000028 PRODIGY SYSTEMS CORPORATION +000029 IMC NETWORKS CORP. +00002A TRW - SEDD/INP +00002B CRISP AUTOMATION, INC +00002C AUTOTOTE LIMITED +00002D CHROMATICS INC +00002E SOCIETE EVIRA +00002F TIMEPLEX INC. +000030 VG LABORATORY SYSTEMS LTD +000031 QPSX COMMUNICATIONS PTY LTD +000032 Marconi plc +000033 EGAN MACHINERY COMPANY +000034 NETWORK RESOURCES CORPORATION +000035 SPECTRAGRAPHICS CORPORATION +000036 ATARI CORPORATION +000037 OXFORD METRICS LIMITED +000038 CSS LABS +000039 TOSHIBA CORPORATION +00003A CHYRON CORPORATION +00003B i Controls, Inc. +00003C AUSPEX SYSTEMS INC. +00003D UNISYS +00003E SIMPACT +00003F SYNTREX, INC. +000040 APPLICON, INC. +000041 ICE CORPORATION +000042 METIER MANAGEMENT SYSTEMS LTD. +000043 MICRO TECHNOLOGY +000044 CASTELLE CORPORATION +000045 FORD AEROSPACE & COMM. CORP. +000046 OLIVETTI NORTH AMERICA +000047 NICOLET INSTRUMENTS CORP. +000048 SEIKO EPSON CORPORATION +000049 APRICOT COMPUTERS, LTD +00004A ADC CODENOLL TECHNOLOGY CORP. +00004B ICL DATA OY +00004C NEC CORPORATION +00004D DCI CORPORATION +00004E AMPEX CORPORATION +00004F LOGICRAFT, INC. +000050 RADISYS CORPORATION +000051 HOB ELECTRONIC GMBH & CO. KG +000052 Intrusion.com, Inc. +000053 COMPUCORP +000054 MODICON, INC. +000055 COMMISSARIAT A L`ENERGIE ATOM. +000056 DR. B. STRUCK +000057 SCITEX CORPORATION LTD. +000058 RACORE COMPUTER PRODUCTS INC. +000059 HELLIGE GMBH +00005A SysKonnect GmbH +00005B ELTEC ELEKTRONIK AG +00005C TELEMATICS INTERNATIONAL INC. +00005D CS TELECOM +00005E USC INFORMATION SCIENCES INST +00005F SUMITOMO ELECTRIC IND., LTD. +000060 KONTRON ELEKTRONIK GMBH +000061 GATEWAY COMMUNICATIONS +000062 BULL HN INFORMATION SYSTEMS +000063 DR.ING.SEUFERT GMBH +000064 YOKOGAWA DIGITAL COMPUTER CORP +000065 NETWORK ASSOCIATES, INC. +000066 TALARIS SYSTEMS, INC. +000067 SOFT * RITE, INC. +000068 ROSEMOUNT CONTROLS +000069 CONCORD COMMUNICATIONS INC +00006A COMPUTER CONSOLES INC. +00006B SILICON GRAPHICS INC./MIPS +00006D CRAY COMMUNICATIONS, LTD. +00006E ARTISOFT, INC. +00006F MADGE NETWORKS LTD. +000070 HCL LIMITED +000071 ADRA SYSTEMS INC. +000072 MINIWARE TECHNOLOGY +000073 SIECOR CORPORATION +000074 RICOH COMPANY LTD. +000075 Nortel Networks +000076 ABEKAS VIDEO SYSTEM +000077 INTERPHASE CORPORATION +000078 LABTAM LIMITED +000079 NETWORTH INCORPORATED +00007A DANA COMPUTER INC. +00007B RESEARCH MACHINES +00007C AMPERE INCORPORATED +00007D SUN MICROSYSTEMS, INC. +00007E CLUSTRIX CORPORATION +00007F LINOTYPE-HELL AG +000080 CRAY COMMUNICATIONS A/S +000081 BAY NETWORKS +000082 LECTRA SYSTEMES SA +000083 TADPOLE TECHNOLOGY PLC +000084 SUPERNET +000085 CANON INC. +000086 MEGAHERTZ CORPORATION +000087 HITACHI, LTD. +000088 COMPUTER NETWORK TECH. CORP. +000089 CAYMAN SYSTEMS INC. +00008A DATAHOUSE INFORMATION SYSTEMS +00008B INFOTRON +00008C ALLOY COMPUTER PRODUCTS, INC. +00008D VERDIX CORPORATION +00008E SOLBOURNE COMPUTER, INC. +00008F RAYTHEON COMPANY +000090 MICROCOM +000091 ANRITSU CORPORATION +000092 COGENT DATA TECHNOLOGIES +000093 PROTEON INC. +000094 ASANTE TECHNOLOGIES +000095 SONY TEKTRONIX CORP. +000096 MARCONI ELECTRONICS LTD. +000097 EPOCH SYSTEMS +000098 CROSSCOMM CORPORATION +000099 MTX, INC. +00009A RC COMPUTER A/S +00009B INFORMATION INTERNATIONAL, INC +00009C ROLM MIL-SPEC COMPUTERS +00009D LOCUS COMPUTING CORPORATION +00009E MARLI S.A. +00009F AMERISTAR TECHNOLOGIES INC. +0000A0 TOKYO SANYO ELECTRIC CO. LTD. +0000A1 MARQUETTE ELECTRIC CO. +0000A2 BAY NETWORKS +0000A3 NETWORK APPLICATION TECHNOLOGY +0000A4 ACORN COMPUTERS LIMITED +0000A5 COMPATIBLE SYSTEMS CORP. +0000A6 NETWORK GENERAL CORPORATION +0000A7 NETWORK COMPUTING DEVICES INC. +0000A8 STRATUS COMPUTER INC. +0000A9 NETWORK SYSTEMS CORP. +0000AA XEROX CORPORATION +0000AB LOGIC MODELING CORPORATION +0000AC CONWARE COMPUTER CONSULTING +0000AD BRUKER INSTRUMENTS INC. +0000AE DASSAULT ELECTRONIQUE +0000AF NUCLEAR DATA INSTRUMENTATION +0000B0 RND-RAD NETWORK DEVICES +0000B1 ALPHA MICROSYSTEMS INC. +0000B2 TELEVIDEO SYSTEMS, INC. +0000B3 CIMLINC INCORPORATED +0000B4 EDIMAX COMPUTER COMPANY +0000B5 DATABILITY SOFTWARE SYS. INC. +0000B6 MICRO-MATIC RESEARCH +0000B7 DOVE COMPUTER CORPORATION +0000B8 SEIKOSHA CO., LTD. +0000B9 MCDONNELL DOUGLAS COMPUTER SYS +0000BA SIIG, INC. +0000BB TRI-DATA +0000BC ALLEN-BRADLEY CO. INC. +0000BD MITSUBISHI CABLE COMPANY +0000BE THE NTI GROUP +0000BF SYMMETRIC COMPUTER SYSTEMS +0000C0 WESTERN DIGITAL CORPORATION +0000C1 Madge Networks Ltd. +0000C2 INFORMATION PRESENTATION TECH. +0000C3 HARRIS CORP COMPUTER SYS DIV +0000C4 WATERS DIV. OF MILLIPORE +0000C5 FARALLON COMPUTING/NETOPIA +0000C6 EON SYSTEMS +0000C7 ARIX CORPORATION +0000C8 ALTOS COMPUTER SYSTEMS +0000C9 EMULEX CORPORATION +0000CA APPLITEK +0000CB COMPU-SHACK ELECTRONIC GMBH +0000CC DENSAN CO., LTD. +0000CD Centrecom Systems, Ltd. +0000CE MEGADATA CORP. +0000CF HAYES MICROCOMPUTER PRODUCTS +0000D0 DEVELCON ELECTRONICS LTD. +0000D1 ADAPTEC INCORPORATED +0000D2 SBE, INC. +0000D3 WANG LABORATORIES INC. +0000D4 PURE DATA LTD. +0000D5 MICROGNOSIS INTERNATIONAL +0000D6 PUNCH LINE HOLDING +0000D7 DARTMOUTH COLLEGE +0000D8 NOVELL, INC. +0000D9 NIPPON TELEGRAPH & TELEPHONE +0000DA ATEX +0000DB BRITISH TELECOMMUNICATIONS PLC +0000DC HAYES MICROCOMPUTER PRODUCTS +0000DD TCL INCORPORATED +0000DE CETIA +0000DF BELL & HOWELL PUB SYS DIV +0000E0 QUADRAM CORP. +0000E1 GRID SYSTEMS +0000E2 ACER TECHNOLOGIES CORP. +0000E3 INTEGRATED MICRO PRODUCTS LTD +0000E4 IN2 GROUPE INTERTECHNIQUE +0000E5 SIGMEX LTD. +0000E6 APTOR PRODUITS DE COMM INDUST +0000E7 STAR GATE TECHNOLOGIES +0000E8 ACCTON TECHNOLOGY CORP. +0000E9 ISICAD, INC. +0000EA UPNOD AB +0000EB MATSUSHITA COMM. IND. CO. LTD. +0000EC MICROPROCESS +0000ED APRIL +0000EE NETWORK DESIGNERS, LTD. +0000EF KTI +0000F0 SAMSUNG ELECTRONICS CO., LTD. +0000F1 MAGNA COMPUTER CORPORATION +0000F2 SPIDER COMMUNICATIONS +0000F3 GANDALF DATA LIMITED +0000F4 ALLIED TELESYN INTERNATIONAL +0000F5 DIAMOND SALES LIMITED +0000F6 APPLIED MICROSYSTEMS CORP. +0000F7 YOUTH KEEP ENTERPRISE CO LTD +0000F8 DIGITAL EQUIPMENT CORPORATION +0000F9 QUOTRON SYSTEMS INC. +0000FA MICROSAGE COMPUTER SYSTEMS INC +0000FB RECHNER ZUR KOMMUNIKATION +0000FC MEIKO +0000FD HIGH LEVEL HARDWARE +0000FE ANNAPOLIS MICRO SYSTEMS +0000FF CAMTEC ELECTRONICS LTD. +000100 EQUIP'TRANS +000102 3COM CORPORATION +000103 3COM CORPORATION +000104 DVICO Co., Ltd. +000105 BECKHOFF GmbH +000106 Tews Datentechnik GmbH +000107 Leiser GmbH +000108 AVLAB Technology, Inc. +000109 Nagano Japan Radio Co., Ltd. +00010A CIS TECHNOLOGY INC. +00010B Space CyberLink, Inc. +00010C System Talks Inc. +00010D CORECO, INC. +00010E Bri-Link Technologies Co., Ltd +00010F Nishan Systems, Inc. +000110 Gotham Networks +000111 iDigm Inc. +000112 Shark Multimedia Inc. +000113 OLYMPUS OPTICAL CO., LTD. +000114 KANDA TSUSHIN KOGYO CO., LTD. +000115 EXTRATECH CORPORATION +000116 Netspect Technologies, Inc. +000117 CANAL + +000118 EZ Digital Co., Ltd. +000119 Action Controls Pty. Ltd. +00011A EEH DataLink GmbH +00011B Unizone Technologies, Inc. +00011C Universal Talkware Corporation +00011D Centillium Communications +00011E Precidia Technologies, Inc. +00011F RC Networks, Inc. +000120 OSCILLOQUARTZ S.A. +000121 RapidStream Inc. +000122 Trend Communications, Ltd. +000123 DIGITAL ELECTRONICS CORP. +000124 Acer Incorporated +000125 YAESU MUSEN CO., LTD. +000126 PAC Labs +000127 The OPEN Group Limited +000128 EnjoyWeb, Inc. +000129 DFI Inc. +00012A Telematica Sistems Inteligente +00012B TELENET Co., Ltd. +00012C Aravox Technologies, Inc. +00012D Komodo Technology +00012E PC Partner Ltd. +00012F Twinhead International Corp +000130 Extreme Networks +000131 Detection Systems, Inc. +000132 Dranetz - BMI +000133 KYOWA Electronic Instruments C +000134 SIG Positec Systems AG +000135 KDC Corp. +000136 CyberTAN Technology, Inc. +000137 IT Farm Corporation +000138 XAVi Technologies Corp. +000139 Point Multimedia Systems +00013A SHELCAD COMMUNICATIONS, LTD. +00013B BNA SYSTEMS +00013C TIW SYSTEMS +00013D RiscStation Ltd. +00013E Ascom Tateco AB +00013F Neighbor World Co., Ltd. +000140 Sendtek Corporation +000141 CABLE PRINT +000142 Cisco Systems, Inc. +000143 Cisco Systems, Inc. +000144 Cereva Networks, Inc. +000145 WINSYSTEMS, INC. +000146 Tesco Controls, Inc. +000147 Zhone Technologies +000148 X-traWeb Inc. +000149 T.D.T. Transfer Data Test GmbH +00014A SONY COMPUTER SCIENCE LABS., I +00014B Ennovate Networks, Inc. +00014C Berkeley Process Control +00014D Shin Kin Enterprises Co., Ltd +00014E WIN Enterprises, Inc. +00014F LUMINOUS Networks, Inc. +000150 GILAT COMMUNICATIONS, LTD. +000151 Ensemble Communications +000152 CHROMATEK INC. +000153 ARCHTEK TELECOM CORPORATION +000154 G3M Corporation +000155 Promise Technology, Inc. +000156 FIREWIREDIRECT.COM, INC. +000157 SYSWAVE CO., LTD +000158 Electro Industries/Gauge Tech +000159 S1 Corporation +00015A Digital Video Broadcasting +00015B ITALTEL S.p.A/RF-UP-I +00015C CADANT INC. +00015D Pirus Networks +00015E BEST TECHNOLOGY CO., LTD. +00015F DIGITAL DESIGN GmbH +000160 ELMEX Co., LTD. +000161 Meta Machine Technology +000162 Cygnet Technologies, Inc. +000163 Cisco Systems, Inc. +000164 Cisco Systems, Inc. +000165 AirSwitch Corporation +000166 TC GROUP A/S +000167 HIOKI E.E. CORPORATION +000168 VITANA CORPORATION +000169 Celestix Networks Pte Ltd. +00016A ALITEC +00016B LightChip, Inc. +00016C FOXCONN +00016D Triton Network Systems +00016E Conklin Corporation +00016F HAITAI ELECTRONICS CO., LTD. +000170 ESE Embedded System Engineer'g +000171 Allied Data Technologies +000172 TechnoLand Co., LTD. +000173 JNI Corporation +000174 CyberOptics Corporation +000175 Radiant Communications Corp. +000176 Orient Silver Enterprises +000177 EDSL +000178 MARGI Systems, Inc. +000179 WIRELESS TECHNOLOGY, INC. +00017A Chengdu Maipu Electric Industrial Co., Ltd. +00017B Heidelberger Druckmaschinen AG +00017C AG-E GmbH +00017D ThermoQuest +00017E ADTEK System Science Co., Ltd. +00017F Experience Music Project +000180 AOpen, Inc. +000181 Nortel Networks +000182 DICA TECHNOLOGIES AG +000183 ANITE TELECOMS +000184 SIEB & MEYER AG +000185 Aloka Co., Ltd. +000186 DISCH GmbH +000187 i2SE GmbH +000188 LXCO Technologies ag +000189 Refraction Technology, Inc. +00018A ROI COMPUTER AG +00018B NetLinks Co., Ltd. +00018C Mega Vision +00018D AudeSi Technologies +00018E Logitec Corporation +00018F Kenetec, Inc. +000190 SMK-M +000191 SYRED Data Systems +000192 Texas Digital Systems +000193 Hanbyul Telecom Co., Ltd. +000194 Capital Equipment Corporation +000195 Sena Technologies, Inc. +000196 Cisco Systems, Inc. +000197 Cisco Systems, Inc. +000198 Darim Vision +000199 HeiSei Electronics +00019A LEUNIG GmbH +00019B Kyoto Microcomputer Co., Ltd. +00019C JDS Uniphase Inc. +00019D E-Control Systems, Inc. +00019E ESS Technology, Inc. +00019F Phonex Broadband +0001A0 Infinilink Corporation +0001A1 Mag-Tek, Inc. +0001A2 Logical Co., Ltd. +0001A3 GENESYS LOGIC, INC. +0001A4 Microlink Corporation +0001A5 Nextcomm, Inc. +0001A6 Scientific-Atlanta Arcodan A/S +0001A7 UNEX TECHNOLOGY CORPORATION +0001A8 Welltech Computer Co., Ltd. +0001A9 BMW AG +0001AA Airspan Communications, Ltd. +0001AB Main Street Networks +0001AC Sitara Networks, Inc. +0001AD Coach Master International d.b.a. CMI Worldwide, Inc. +0001AE Trex Enterprises +0001AF Motorola Computer Group +0001B0 Fulltek Technology Co., Ltd. +0001B1 General Bandwidth +0001B2 Digital Processing Systems, Inc. +0001B3 Precision Electronic Manufacturing +0001B4 Wayport, Inc. +0001B5 Turin Networks, Inc. +0001B6 SAEJIN T&M Co., Ltd. +0001B7 Centos, Inc. +0001B8 Netsensity, Inc. +0001B9 SKF Condition Monitoring +0001BA IC-Net, Inc. +0001BB Frequentis +0001BC Brains Corporation +0001BD Peterson Electro-Musical Products, Inc. +0001BE Gigalink Co., Ltd. +0001BF Teleforce Co., Ltd. +0001C0 CompuLab, Ltd. +0001C1 Exbit Technology +0001C2 ARK Research Corp. +0001C3 Acromag, Inc. +0001C4 NeoWave, Inc. +0001C5 Simpler Networks +0001C6 Quarry Technologies +0001C7 Cisco Systems, Inc. +0001C8 THOMAS CONRAD CORP. +0001C8 CONRAD CORP. +0001C9 Cisco Systems, Inc. +0001CA Geocast Network Systems, Inc. +0001CB NetGame, Ltd. +0001CC Japan Total Design Communication Co., Ltd. +0001CD ARtem +0001CE Custom Micro Products, Ltd. +0001CF Alpha Data Parallel Systems, Ltd. +0001D0 VitalPoint, Inc. +0001D1 CoNet Communications, Inc. +0001D2 MacPower Peripherals, Ltd. +0001D3 PAXCOMM, Inc. +0001D4 Leisure Time, Inc. +0001D5 HAEDONG INFO & COMM CO., LTD +0001D6 MAN Roland Druckmaschinen AG +0001D7 F5 Networks, Inc. +0001D8 Teltronics, Inc. +0001D9 Sigma, Inc. +0001DA WINCOMM Corporation +0001DB Freecom Technologies GmbH +0001DC Activetelco +0001DD Avail Networks +0001DE Trango Systems, Inc. +0001DF ISDN Communications, Ltd. +0001E0 Fast Systems, Inc. +0001E1 Kinpo Electronics, Inc. +0001E2 Ando Electric Corporation +0001E3 Siemens AG +0001E4 Sitera, Inc. +0001E5 Supernet, Inc. +0001E6 Hewlett-Packard Company +0001E7 Hewlett-Packard Company +0001E8 Force10 Networks, Inc. +0001E9 Litton Marine Systems B.V. +0001EA Cirilium Corp. +0001EB C-COM Corporation +0001EC Ericsson Group +0001ED SETA Corp. +0001EE Comtrol Europe, Ltd. +0001EF Camtel Technology Corp. +0001F0 Tridium, Inc. +0001F1 Innovative Concepts, Inc. +0001F3 QPS, Inc. +0001F4 Enterasys Networks +0001F5 ERIM S.A. +0001F6 Association of Musical Electronics Industry +0001F7 Image Display Systems, Inc. +0001F8 Adherent Systems, Ltd. +0001F9 TeraGlobal Communications Corp. +0001FA HOROSCAS +0001FB DoTop Technology, Inc. +0001FC Keyence Corporation +0001FD Digital Voice Systems, Inc. +0001FE DIGITAL EQUIPMENT CORPORATION +0001FF Data Direct Networks, Inc. +000200 Net & Sys Co., Ltd. +000201 IFM Electronic gmbh +000202 Amino Communications, Ltd. +000203 Woonsang Telecom, Inc. +000204 Bodmann Industries Elektronik GmbH +000205 Hitachi Denshi, Ltd. +000206 Telital R&D Denmark A/S +000208 Unify Networks, Inc. +000209 Shenzhen SED Information Technology Co., Ltd. +00020A Gefran Spa +00020B Native Networks, Inc. +00020C Metro-Optix +00020D Micronpc.com +00020E Laurel Networks, Inc. +00020F AATR +000210 Fenecom +000211 Nature Worldwide Technology Corp. +000212 SierraCom +000213 S.D.E.L. +000214 DTVRO +000215 Cotas Computer Technology A/B +000216 Cisco Systems, Inc. +000217 Cisco Systems, Inc. +000218 Advanced Scientific Corp +000219 Paralon Technologies +00021A Zuma Networks +00021B Kollmorgen-Servotronix +00021C Network Elements, Inc. +00021D Data General Communication Ltd. +00021E SIMTEL S.R.L. +00021F Aculab PLC +000220 Canon Aptex, Inc. +000221 DSP Application, Ltd. +000222 Chromisys, Inc. +000223 ClickTV +000224 Lantern Communications, Inc. +000225 Certus Technology, Inc. +000226 XESystems, Inc. +000227 ESD GmbH +000228 Necsom, Ltd. +000229 Adtec Corporation +00022A Asound Electronic +00022B Tamura Electric Works, Ltd. +00022C ABB Bomem, Inc. +00022D Agere Systems +00022E TEAC Corp. R& D +00022F P-Cube, Ltd. +000230 Intersoft Electronics +000231 Ingersoll-Rand +000232 Avision, Inc. +000233 Mantra Communications, Inc. +000234 Imperial Technology, Inc. +000235 Paragon Networks International +000236 INIT GmbH +000237 Cosmo Research Corp. +000238 Serome Technology, Inc. +000239 Visicom +00023A ZSK Stickmaschinen GmbH +00023B Redback Networks +00023C Creative Technology, Ltd. +00023D NuSpeed, Inc. +00023E Selta Telematica S.p.a +00023F Compal Electronics, Inc. +000240 Seedek Co., Ltd. +000241 Amer.com +000242 Videoframe Systems +000243 Raysis Co., Ltd. +000244 SURECOM Technology Co. +000245 Lampus Co, Ltd. +000246 All-Win Tech Co., Ltd. +000247 Great Dragon Information Technology (Group) Co., Ltd. +000248 Pila GmbH & Co. +000249 Aviv Infocom Co, Ltd. +00024A Cisco Systems, Inc. +00024B Cisco Systems, Inc. +00024C SiByte, Inc. +00024D Mannesman Dematic Colby Pty. Ltd. +00024E Datacard Group +00024F IPM Datacom S.R.L. +000250 Geyser Networks, Inc. +000251 Soma Networks +000252 Carrier Corporation +000253 Televideo, Inc. +000254 WorldGate +000255 IBM Corporation +000256 Alpha Processor, Inc. +000257 Microcom Corp. +000258 Flying Packets Communications +000259 Tsann Kuen China (Shanghai)Enterprise Co., Ltd. IT Group +00025A Catena Networks +00025B Cambridge Silicon Radio +00025C SCI Systems (Kunshan) Co., Ltd. +00025E High Technology Ltd +00025F Nortel Networks +000260 Accordion Networks, Inc. +000261 i3 Micro Technology AB +000262 Soyo Group Soyo Com Tech Co., Ltd +000263 UPS Manufacturing SRL +000264 AudioRamp.com +000265 Virditech Co. Ltd. +000266 Thermalogic Corporation +000267 NODE RUNNER, INC. +000268 Harris Government Communications +000269 Nadatel Co., Ltd +00026A Cocess Telecom Co., Ltd. +00026B BCM Computers Co., Ltd. +00026C Philips CFT +00026D Adept Telecom +00026E NeGeN Access, Inc. +00026F Senao International Co., Ltd. +000270 Crewave Co., Ltd. +000271 Vpacket Communications +000272 CC&C Technologies, Inc. +000273 Coriolis Networks +000274 Tommy Technologies Corp. +000275 SMART Technologies, Inc. +000276 Primax Electronics Ltd. +000277 Cash Systemes Industrie +000278 Samsung Electro-Mechanics Co., Ltd. +000279 Control Applications, Ltd. +00027A IOI Technology Corporation +00027B Amplify Net, Inc. +00027C Trilithic, Inc. +00027D Cisco Systems, Inc. +00027E Cisco Systems, Inc. +00027F ask-technologies.com +000280 Mu Net, Inc. +000281 Red-M (Communications) Ltd. +000282 ViaClix, Inc. +000283 Spectrum Controls, Inc. +000284 Alstom T&D P&C +000285 Riverstone Networks +000286 Occam Networks +000287 Adapcom +000288 GLOBAL VILLAGE COMMUNICATION +000289 DNE Technologies +00028A Ambit Microsystems Corporation +00028B VDSL Systems OY +00028C Micrel-Synergy Semiconductor +00028D Movita Technologies, Inc. +00028E Rapid 5 Networks, Inc. +00028F Globetek, Inc. +000290 Woorigisool, Inc. +000291 Open Network Co., Ltd. +000292 Logic Innovations, Inc. +000293 Solid Data Systems +000294 Tokyo Sokushin Co., Ltd. +000295 IP.Access Limited +000296 Lectron Co,. Ltd. +000297 C-COR.net +000298 Broadframe Corporation +000299 Apex, Inc. +00029A Storage Apps +00029B Kreatel Communications AB +00029D Merix Corp. +00029E Information Equipment Co., Ltd. +00029F L-3 Communication Aviation Recorders +0002A0 Flatstack Ltd. +0002A1 World Wide Packets +0002A2 Hilscher GmbH +0002A3 ABB Power Automation +0002A4 AddPac Technology Co., Ltd. +0002A5 Compaq Computer Corporation +0002A6 Effinet Systems Co., Ltd. +0002A7 Vivace Networks +0002A8 Air Link Technology +0002A9 RACOM, s.r.o. +0002AA PLcom Co., Ltd. +0002AB CTC Union Technologies Co., Ltd. +0002AC 3PAR data +0002AD Asahi Optical Co., Ltd. +0002AE Scannex Electronics Ltd. +0002AF TeleCruz Technology, Inc. +0002B0 Hokubu Communication & Industrial Co., Ltd. +0002B1 Anritsu, Ltd. +0002B2 Cablevision +0002B3 Intel Corporation +0002B4 DAPHNE +0002B5 Avnet, Inc. +0002B6 Acrosser Technology Co., Ltd. +0002B7 Watanabe Electric Industry Co., Ltd. +0002B8 WHI KONSULT AB +0002B9 Cisco Systems, Inc. +0002BA Cisco Systems, Inc. +0002BB Continuous Computing +0002BC LVL 7 Systems, Inc. +0002BD Bionet Co., Ltd. +0002BE Totsu Engineering, Inc. +0002BF dotRocket, Inc. +0002C0 Bencent Tzeng Industry Co., Ltd. +0002C1 Innovative Electronic Designs, Inc. +0002C2 Net Vision Telecom +0002C3 Arelnet Ltd. +0002C4 Vector International BUBA +0002C5 Evertz Microsystems Ltd. +0002C6 Data Track Technology PLC +0002C7 ALPS ELECTRIC Co., Ltd. +0002C8 Technocom Communications Technology (pte) Ltd +0002C9 Mellanox Technologies +0002CA EndPoints, Inc. +0002CB TriState Ltd. +0002CC M.C.C.I +0002CD TeleDream, Inc. +0002CE FoxJet, Inc. +0002CF ZyGate Communications, Inc. +0002D0 Comdial Corporation +0002D1 Vivotek, Inc. +0002D2 Workstation AG +0002D3 NetBotz, Inc. +0002D4 PDA Peripherals, Inc. +0002D5 ACR +0002D6 NICE Systems +0002D7 EMPEG Ltd +0002D8 BRECIS Communications Corporation +0002D9 Reliable Controls +0002DA ExiO Communications, Inc. +0002DB NETSEC +0002DC Fujitsu General Limited +0002DD Bromax Communications, Ltd. +0002DE Astrodesign, Inc. +0002DF Net Com Systems, Inc. +0002E0 ETAS GmbH +0002E1 Integrated Network Corporation +0002E2 NDC Infared Engineering +0002E3 LITE-ON Communications, Inc. +0002E4 JC HYUN Systems, Inc. +0002E5 Timeware Ltd. +0002E6 Gould Instrument Systems, Inc. +0002E7 CAB GmbH & Co KG +0002E8 E.D.&A. +0002E9 CS Systemes De Securite - C3S +0002EA Videonics, Inc. +0002EB Easent Communications +0002EC Maschoff Design Engineering +0002ED DXO Telecom Co., Ltd. +0002EE Nokia Danmark A/S +0002EF CCC Network Systems Group Ltd. +0002F0 AME Optimedia Technology Co., Ltd. +0002F1 Pinetron Co., Ltd. +0002F2 eDevice, Inc. +0002F3 Media Serve Co., Ltd. +0002F4 PCTEL, Inc. +0002F5 VIVE Synergies, Inc. +0002F6 Equipe Communications +0002F7 ARM +0002F8 SEAKR Engineering, Inc. +0002F9 Mimos Semiconductor SDN BHD +0002FA DX Antenna Co., Ltd. +0002FB Baumuller Aulugen-Systemtechnik GmbH +0002FC Cisco Systems, Inc. +0002FD Cisco Systems, Inc. +0002FE Viditec, Inc. +0002FF Handan Broad InfoCom +000300 NetContinuum, Inc. +000301 Avantas Networks Corporation +000302 Oasys Telecom, Inc. +000303 JAMA Electronics Co., Ltd. +000304 Pacific Broadband Communications +000305 Smart Network Devices GmbH +000306 Fusion In Tech Co., Ltd. +000307 Secure Works, Inc. +000308 AM Communications, Inc. +000309 Texcel Technology PLC +00030A Argus Technologies +00030B Hunter Technology, Inc. +00030C Telesoft Technologies Ltd. +00030D Uniwill Computer Corp. +00030E Core Communications Co., Ltd. +00030F Legend Digital China Ltd. +000310 Link Evolution Corp. +000311 Micro Technology Co., Ltd. +000312 TR-Systemtechnik GmbH +000313 Access Media SPA +000314 Teleware Network Systems +000315 Cidco Incorporated +000316 Nobell Communications, Inc. +000317 Merlin Systems, Inc. +000318 Cyras Systems, Inc. +000319 Infineon AG +00031A Beijing Broad Telecom Ltd., China +00031B Cellvision Systems, Inc. +00031C Svenska Hardvarufabriken AB +00031D Taiwan Commate Computer, Inc. +00031E Optranet, Inc. +00031F Condev Ltd. +000320 Xpeed, Inc. +000321 Reco Research Co., Ltd. +000322 IDIS Co., Ltd. +000323 Cornet Technology, Inc. +000324 Tottori SANYO Electric Co., Ltd. +000325 Arima Computer Corp. +000326 Iwasaki Information Systems Co., Ltd. +000327 ACT'L +000328 Mace Group, Inc. +000329 F3, Inc. +00032A UniData Communication Systems, Inc. +00032B GAI Datenfunksysteme GmbH +00032C ABB Industrie AG +00032D IBASE Technology, Inc. +00032E Scope Information Management, Ltd. +00032F Global Sun Technology, Inc. +000330 Imagenics, Co., Ltd. +000331 Cisco Systems, Inc. +000332 Cisco Systems, Inc. +000333 Digitel Co., Ltd. +000334 Newport Electronics +000335 Mirae Technology +000336 Zetes Technologies +000337 Vaone, Inc. +000338 Oak Technology +000339 Eurologic Systems, Ltd. +00033A Silicon Wave, Inc. +00033B TAMI Tech Co., Ltd. +00033C Daiden Co., Ltd. +00033D ILSHin Lab +00033E Tateyama System Laboratory Co., Ltd. +00033F BigBand Networks, Ltd. +000340 Floware Wireless Systems, Ltd. +000341 Axon Digital Design +000342 Nortel Networks +000343 Martin Professional A/S +000344 Tietech.Co., Ltd. +000345 Routrek Networks Corporation +000346 Hitachi Kokusai Electric, Inc. +000347 Intel Corporation +000348 Norscan Instruments, Ltd. +000349 Vidicode Datacommunicatie B.V. +00034A RIAS Corporation +00034B Nortel Networks +00034C Shanghai DigiVision Technology Co., Ltd. +00034D Chiaro Networks, Ltd. +00034E Pos Data Company, Ltd. +00034F Sur-Gard Security +000350 BTICINO SPA +000351 Diebold, Inc. +000352 Colubris Networks +000353 Mitac, Inc. +000354 Fiber Logic Communications +000355 TeraBeam Internet Systems +000356 Wincor Nixdorf GmbH & Co KG +000357 Intervoice-Brite, Inc. +000358 iCable System Co., Ltd. +000359 DigitalSis +00035A Phototron Limited +00035B BridgeWave Communications +00035C Saint Song Corp. +00035D Bosung Hi-Net Co., Ltd. +00035E Metropolitan Area Networks, Inc. +00035F Schuehle Mess - und. Kontrollsysteme +000360 PAC Interactive Technology, Inc. +000361 Widcomm, Inc. +000362 Vodtel Communications, Inc. +000363 Miraesys Co., Ltd. +000364 Scenix Semiconductor, Inc. +000365 Kira Information & Communications, Ltd. +000366 ASM Pacific Technology +000367 Jasmine Networks, Inc. +000368 Embedone Co., Ltd. +000369 Nippon Antenna Co., Ltd. +00036A Mainnet, Ltd. +00036B Cisco Systems, Inc. +00036C Cisco Systems, Inc. +00036D Runtop, Inc. +00036E Nicon Systems (Pty) Limited +00036F Telsey SPA +000370 NXTV, Inc. +000371 Acomz Networks Corp. +000372 ULAN +000373 Aselsan A.S +000374 Hunter Watertech +000375 NetMedia, Inc. +000376 Graphtec Technology, Inc. +000377 Gigabit Wireless +000378 HUMAX Co., Ltd. +000379 Proscend Communications, Inc. +00037A Taiyo Yuden Co., Ltd. +00037B IDEC IZUMI Corporation +00037C Coax Media +00037D Stellcom +00037E PORTech Communications, Inc. +00037F Atheros Communications, Inc. +000381 Ingenico International +000382 A-One Co., Ltd. +000383 Metera Networks, Inc. +000384 AETA +000385 Actelis Networks, Inc. +000386 Ho Net, Inc. +000387 Blaze Network Products +000388 Fastfame Technology Co., Ltd. +000389 Plantronics +00038A America Online, Inc. +00038B PLUS-ONE I&T, Inc. +00038C Total Impact +00038D PCS Revenue Control Systems, Inc. +00038E Atoga Systems, Inc. +00038F Weinschel Corporation +000390 Digital Video Communications, Inc. +000392 Hyundai Teletek Co., Ltd. +000393 Apple Computer, Inc. +000394 Connect One +000395 California Amplifier +000396 EZ Cast Co., Ltd. +000397 Watchfront Electronics +000398 WISI +000399 Dongju Informations & Communications Co., Ltd. +00039A nSine, Ltd. +00039B NetChip Technology, Inc. +00039C OptiMight Communications, Inc. +00039D Acer Communications & Multimedia, Inc. +00039E Tera System Co., Ltd. +00039F Cisco Systems, Inc. +0003A0 Cisco Systems, Inc. +0003A1 HIPER Information & Communication, Inc. +0003A2 Catapult Communications +0003A3 MAVIX, Ltd. +0003A4 Data Storage and Information Management +0003A5 Medea Corporation +0003A7 Unixtar Technology, Inc. +0003A8 IDOT Computers, Inc. +0003A9 AXCENT Media AG +0003AA Watlow +0003AB Bridge Information Systems +0003AC Fronius Schweissmaschinen +0003AD Emerson Energy Systems AB +0003AE Allied Advanced Manufacturing Pte, Ltd. +0003AF Paragea Communications +0003B0 Xsense Technology Corp. +0003B1 Abbott Laboratories HPD +0003B2 Radware +0003B3 IA Link Systems Co., Ltd. +0003B4 Macrotek International Corp. +0003B5 Entra Technology Co. +0003B6 QSI Corporation +0003B7 ZACCESS Systems +0003B8 NetKit Solutions, LLC +0003B9 Hualong Telecom Co., Ltd. +0003BA Sun Microsystems +0003BB Signal Communications Limited +0003BC COT GmbH +0003BD OmniCluster Technologies, Inc. +0003BE Netility +0003BF Centerpoint Broadband Technologies, Inc. +0003C0 RFTNC Co., Ltd. +0003C1 Packet Dynamics Ltd +0003C2 Solphone K.K. +0003C3 Micronik Multimedia +0003C4 Tomra Systems ASA +0003C5 Mobotix AG +0003C6 ICUE Systems, Inc. +0003C7 hopf Elektronik GmbH +0003C8 CML Emergency Services +0003C9 TECOM Co., Ltd. +0003CA MTS Systems Corp. +0003CB Nippon Systems Development Co., Ltd. +0003CC Momentum Computer, Inc. +0003CD Clovertech, Inc. +0003CE ETEN Technologies, Inc. +0003CF Muxcom, Inc. +0003D0 KOANKEISO Co., Ltd. +0003D1 Takaya Corporation +0003D2 Crossbeam Systems, Inc. +0003D3 Internet Energy Systems, Inc. +0003D4 Alloptic, Inc. +0003D5 Advanced Communications Co., Ltd. +0003D6 RADVision, Ltd. +0003D7 NextNet Wireless, Inc. +0003D8 iMPath Networks, Inc. +0003D9 Secheron SA +0003DA Takamisawa Cybernetics Co., Ltd. +0003DB Apogee Electronics Corp. +0003DC Lexar Media, Inc. +0003DD Comark Corp. +0003DE OTC Wireless +0003DF Desana Systems +0003E0 RadioFrame Networks, Inc. +0003E1 Winmate Communication, Inc. +0003E2 Comspace Corporation +0003E3 Cisco Systems, Inc. +0003E4 Cisco Systems, Inc. +0003E5 Hermstedt SG +0003E6 Entone Technologies, Inc. +0003E7 Logostek Co. Ltd. +0003E8 Wavelength Digital Limited +0003E9 Akara Canada, Inc. +0003EA Mega System Technologies, Inc. +0003EB Atrica +0003EC ICG Research, Inc. +0003ED Shinkawa Electric Co., Ltd. +0003EE MKNet Corporation +0003EF Oneline AG +0003F0 Redfern Broadband Networks +0003F1 Cicada Semiconductor, Inc. +0003F2 Seneca Networks +0003F3 Dazzle Multimedia, Inc. +0003F4 NetBurner +0003F5 Chip2Chip +0003F6 Allegro Networks, Inc. +0003F7 Plast-Control GmbH +0003F8 SanCastle Technologies, Inc. +0003F9 Pleiades Communications, Inc. +0003FA TiMetra Networks +0003FB Toko Seiki Company, Ltd. +0003FC Intertex Data AB +0003FD Cisco Systems, Inc. +0003FE Cisco Systems, Inc. +0003FF Connectix +000400 LEXMARK INTERNATIONAL, INC. +000401 Osaki Electric Co., Ltd. +000402 Nexsan Technologies, Ltd. +000403 Nexsi Corporation +000404 Makino Milling Machine Co., Ltd. +000405 ACN Technologies +000406 Fa. Metabox AG +000407 Topcon Positioning Systems, Inc. +000408 Sanko Electronics Co., Ltd. +000409 Cratos Networks +00040A Sage Systems +00040B 3com Europe Ltd. +00040C KANNO Work's Ltd. +00040D Avaya, Inc. +00040E AVM GmbH +00040F Asus Network Technologies, Inc. +000410 Spinnaker Networks, Inc. +000411 Inkra Networks, Inc. +000412 WaveSmith Networks, Inc. +000413 SNOM Technology AG +000414 Umezawa Musen Denki Co., Ltd. +000415 Rasteme Systems Co., Ltd. +000416 Parks S/A Comunicacoes Digitais +000417 ELAU AG +000418 Teltronic S.A.U. +000419 Fibercycle Networks, Inc. +00041A ines GmbH +00041B Digital Interfaces Ltd. +00041C ipDialog, Inc. +00041D Corega of America +00041E Shikoku Instrumentation Co., Ltd. +00041F Sony Computer Entertainment, Inc. +000420 Slim Devices, Inc. +000421 Ocular Networks +000422 Gordon Kapes, Inc. +000423 Intel Corporation +000424 TMC s.r.l. +000425 Atmel Corporation +000426 Autosys +000427 Cisco Systems, Inc. +000428 Cisco Systems, Inc. +000429 Pixord Corporation +00042A Wireless Networks, Inc. +00042B IT Access Co., Ltd. +00042C Minet, Inc. +00042D Sarian Systems, Ltd. +00042E Netous Technologies, Ltd. +00042F International Communications Products, Inc. +000430 Netgem +000431 Play Industries +000432 Voyetra Turtle Beach, Inc. +000433 Cyberboard A/S +000434 Accelent Systems, Inc. +000435 Comptek International, Inc. +000436 ELANsat Technologies, Inc. +000437 Powin Information Technology, Inc. +000438 Nortel Networks +000439 Rosco Entertainment Technology, Inc. +00043A Intelligent Telecommunications, Inc. +00043B Lava Computer Mfg., Inc. +00043C SONOS Co., Ltd. +00043D INDEL AG +00043E Telencomm +00043F Electronic Systems Technology, Inc. +000440 cyberPIXIE, Inc. +000441 Half Dome Systems, Inc. +000442 NACT +000443 Agilent Technologies, Inc. +000444 Wireless Home +000445 LMS Skalar Instruments GmbH +000446 CYZENTECH Co., Ltd. +000447 Acrowave Systems Co., Ltd. +000448 Polaroid Professional Imaging +000449 Mapletree Networks +00044A iPolicy Networks, Inc. +00044B NVIDIA +00044C JENOPTIK +00044D Cisco Systems, Inc. +00044E Cisco Systems, Inc. +00044F Leukhardt Systemelektronik GmbH +000450 DMD Computers SRL +000451 Medrad, Inc. +000452 RocketLogix, Inc. +000453 Yotta Yotta, Inc. +000454 Quadriga UK +000455 ANTARA.net +000456 PipingHot Networks +000457 Universal Access Technology, Inc. +000458 Fusion X Co., Ltd. +000459 Veristar Corporation +00045A The Linksys Group, Inc. +00045B Techsan Electronics Co., Ltd. +00045C Mobiwave Pte Ltd +00045D BEKA Elektronik +00045E Poly Trax Information Technology AG +00045F Evalue Technology, Inc. +000460 Knilink Technology, Inc. +000461 EPOX Computer Co., Ltd. +000462 DAKOS Data & Communication Co., Ltd. +000463 Philips Communication Security & Imaging +000464 Fantasma Networks, Inc. +000465 ist isdn support tecknik GmbH +000466 ARMITEL Co. +000467 Wuhan Research Institute +000468 Vivity, Inc. +000469 Innocom, Inc. +00046A Navini Networks +00046B Palm Wireless, Inc. +00046C Cyber Technology Co., Ltd. +00046D Cisco Systems, Inc. +00046E Cisco Systems, Inc. +00046F Digitel S/A Industria Eletronica +000470 ipUnplugged AB +000471 IPrad +000472 Telelynx, Inc. +000473 Photonex Corporation +000474 LEGRAND +000475 3 Com Corporation +000476 3 Com Corporation +000477 e-Appliance Corp. +000478 G. Star Technology Corporation +000479 Radius Co., Ltd. +00047A AXXESSIT ASA +00047B Schlumberger +00047C Skidata AG +00047D Pelco +00047E NKF Electronics +00047F Chr. Mayr GmbH & Co. KG +000480 Foundry Networks, Inc. +000481 Econolite Control Products, Inc. +000482 MediaLogic Corp. +000483 Deltron Technology, Inc. +000484 Amann GmbH +000485 PicoLight +000486 ITTC, University of Kansas +000487 Cogency Semiconductor, Inc. +000488 Eurotherm Action Incorporated. +000489 YAFO Networks, Inc. +00048A Temia Vertriebs GmbH +00048B Poscon Corporation +00048C Nayna Networks, Inc. +00048D Tone Commander Systems, Inc. +00048E Ohm Tech Labs, Inc. +00048F TD Systems Corp. +000490 Optical Access +000491 Technovision, Inc. +000492 Hive Internet, Ltd. +000493 Tsinghua Unisplendour Co., Ltd. +000494 Breezecom, Ltd. +000495 Tejas Networks +000496 Extreme Networks +000497 MacroSystem Digital Video AG +000499 Chino Corporation +00049A Cisco Systems, Inc. +00049B Cisco Systems, Inc. +00049C Surgient Networks, Inc. +00049D Ipanema Technologies +00049E Wirelink Co., Ltd. +00049F Metrowerks +0004A0 Verity Instruments, Inc. +0004A1 Pathway Connectivity +0004A2 L.S.I. Japan Co., Ltd. +0004A3 Microchip Technology, Inc. +0004A4 NetEnabled, Inc. +0004A5 Barco Projection Systems NV +0004A6 SAF Tehnika Ltd. +0004A7 FabiaTech Corporation +0004A8 Broadmax Technologies, Inc. +0004A9 SandStream Technologies, Inc. +0004AA Jetstream Communications +0004AB Comverse Network Systems, Inc. +0004AC IBM CORP. +0004AD Malibu Networks +0004AE Liquid Metronics +0004AF Digital Fountain, Inc. +0004B0 ELESIGN Co., Ltd. +0004B1 Signal Technology, Inc. +0004B2 ESSEGI SRL +0004B3 Videotek, Inc. +0004B4 CIAC +0004B5 Equitrac Corporation +0004B6 Tellumat (Pty) Ltd. +0004B7 AMB i.t. Holding +0004B8 Kumahira Co., Ltd. +0004B9 S.I. Soubou, Inc. +0004BA KDD Media Will Corporation +0004BB Bardac Corporation +0004BC Giantec, Inc. +0004BD Motorola BCS +0004BE OptXCon, Inc. +0004BF Versa Logic Corp. +0004C0 Cisco Systems, Inc. +0004C1 Cisco Systems, Inc. +0004C2 Magnipix, Inc. +0004C3 CASTOR Informatique +0004C4 Allen & Health +0004C5 ASE Technologies, USA +0004C6 Yamaha Motor Co., Ltd. +0004C7 NetMount +0004C8 LIBA Maschinefabrik GmbH +0004C9 Micro Electron Co., Ltd. +0004CA FreeMs Corp. +0004CB Tdsoft Communication, Ltd. +0004CC Peek Traffic BV. +0004CD Informedia Research Group +0004CE Patria Ailon +0004CF Seagate Technology +0004D0 Softlink s.r.o. +0004D1 Drew Technologies, Inc. +0004D2 Adcon Telemetry AG +0004D3 Toyokeiki Co., Ltd. +0004D4 Proview Electronics Co., Ltd. +0004D5 Hitachi Communication Systems, Inc. +0004D6 Takagi Industrial Co., Ltd. +0004D7 Omitec Instrumentation Ltd. +0004D8 IPWireless, Inc. +0004D9 Titan Electronics, Inc. +0004DA Relax Technology, Inc. +0004DB Tellus Group Corp. +0004DC Nortel Networks +0004DD Cisco Systems, Inc. +0004DE Cisco Systems, Inc. +0004DF Teracom Telematica Ltda. +0004E0 Procket Networks +0004E1 Infinior Microsystems +0004E2 SMC Networks, Inc. +0004E3 Accton Technology Corp. +0004E4 Daeryung Ind., Inc. +0004E5 Glonet Systems, Inc. +0004E6 Banyan Network Private Limited +0004E7 Lightpointe Communications, Inc +0004E8 IER, Inc. +0004E9 Infiniswitch Corporation +0004EA Hewlett-Packard Company +0004EB Paxonet Communications, Inc. +0004EC Memobox SA +0004ED Billion Electric Co., Ltd. +0004EE Lincoln Electric Company +0004EF Polestar Corp. +0004F0 International Computers, Ltd +0004F1 WhereNet +0004F2 Circa Communications, Ltd. +0004F3 FS FORTH-SYSTEME GmbH +0004F4 Infinite Electronics Inc. +0004F5 SnowShore Networks, Inc. +0004F6 Amphus +0004F7 Omega Band, Inc. +0004F8 QUALICABLE TV Industria E Com., Ltda +0004F9 Xtera Communications, Inc. +0004FA MIST Inc. +0004FB Commtech, Inc. +0004FC Stratus Computer (DE), Inc. +0004FD Japan Control Engineering Co., Ltd. +0004FE Pelago Networks +0004FF Acronet Co., Ltd. +000500 Cisco Systems, Inc. +000501 Cisco Systems, Inc. +000502 APPLE COMPUTER +000503 ICONAG +000504 Naray Information & Communication Enterprise +000505 Systems Integration Solutions, Inc. +000506 Reddo Networks AB +000507 Fine Appliance Corp. +000508 Inetcam, Inc. +000509 AVOC Nishimura Ltd. +00050A ICS Spa +00050B SICOM Systems, Inc. +00050C Network Photonics, Inc. +00050D Midstream Technologies, Inc. +00050E 3ware, Inc. +00050F Tanaka S/S Ltd. +000510 Infinite Shanghai Communication Terminals Ltd. +000511 Complementaty Technologies Ltd +000512 MeshNetworks, Inc. +000513 VTLinx Multimedia Systems, Inc. +000514 KDT Systems Co., Ltd. +000515 Nuark Co., Ltd. +000516 SMART Modular Technologies +000517 Shellcomm, Inc. +000518 Jupiters Technology +000519 Siemens Building Technologies AG, +00051A 3Com Europe Ltd. +00051B Magic Control Technology Corporation +00051C Xnet Technology Corp. +00051D Airocon, Inc. +00051E Rhapsody Networks +00051F Taijin Media Co., Ltd. +000520 Smartronix, Inc. +000521 Control Microsystems +000522 LEA*D Corporation, Inc. +000523 AVL List GmbH +000524 BTL System (HK) Limited +000525 Puretek Industrial Co., Ltd. +000526 IPAS GmbH +000527 SJ Tek Co. Ltd +000528 New Focus, Inc. +000529 Shanghai Broadan Communication Technology Co., Ltd +00052A Ikegami Tsushinki Co., Ltd. +00052B HORIBA, Ltd. +00052C Supreme Magic Corporation +00052D Zoltrix International Limited +00052E Cinta Networks +00052F Leviton Voice and Data +000530 Andiamo Systems, Inc. +000531 Cisco Systems, Inc. +000532 Cisco Systems, Inc. +000533 Sanera Systems, Inc. +000534 Northstar Engineering Ltd. +000535 Chip PC Ltd. +000536 Danam Communications, Inc. +000537 Nets Technology Co., Ltd. +000538 Merilus, Inc. +000539 A Brand New World in Sweden AB +00053A Willowglen Services Pte Ltd +00053B Harbour Networks Ltd., Co. Beijing +00053C Xircom +00053D Agere Systems +00053E KID Systeme GmbH +00053F VisionTek, Inc. +000540 FAST Corporation +000541 Advanced Systems Co., Ltd. +000542 Otari, Inc. +000543 IQ Wireless GmbH +000544 Valley Technologies, Inc. +000545 Internet Photonics +000546 KDD Network Systems Co., Ltd. +000547 Starent Networks +000548 Disco Corporation +000549 Salira Optical Network Systems +00054A Ario Data Networks, Inc. +00054B Micro Innovation AG +00054C RF Innovations Pty Ltd +00054D Brans Technologies, Inc. +00054E Philips Components +000550 Digi-Tech Communications Limited +000551 F & S Elektronik Systeme GmbH +000552 Xycotec Computer GmbH +000553 DVC Company, Inc. +000554 Rangestar Wireless +000555 Japan Cash Machine Co., Ltd. +000556 360 Systems +000557 Agile TV Corporation +000558 Synchronous, Inc. +000559 Intracom S.A. +00055A Power Dsine Ltd. +00055B Charles Industries, Ltd. +00055C Kowa Company, Ltd. +00055D D-Link Systems, Inc. +00055E Cisco Systems, Inc. +00055F Cisco Systems, Inc. +000560 LEADER COMM.CO., LTD +000561 nac Image Technology, Inc. +000562 Digital View Limited +000563 J-Works, Inc. +000564 Tsinghua Bitway Co., Ltd. +000565 Tailyn Communication Company Ltd. +000566 Secui.com Corporation +000567 Etymonic Design, Inc. +000568 Piltofish Networks AB +000569 VMWARE, Inc. +00056B C.P. Technology Co., Ltd. +00056C Hung Chang Co., Ltd. +00056D Pacific Corporation +00056E National Enhance Technology, Inc. +00056F Innomedia Technologies Pvt. Ltd. +000570 Baydel Ltd. +000571 Seiwa Electronics Co. +000572 Deonet Co., Ltd. +000573 Cisco Systems, Inc. +000574 Cisco Systems, Inc. +000575 CDS-Electronics BV +000576 NSM Technology Ltd. +000577 SM Information & Communication +000579 Universal Control Solution Corp. +00057A Hatteras Networks +00057B Chung Nam Electronic Co., Ltd. +00057C RCO Security AB +00057D Sun Communications, Inc. +00057E Eckelmann Steuerungstechnik GmbH +00057F Acqis Technology +000580 Fibrolan Ltd. +000581 Snell & Wilcox Ltd. +000582 ClearCube Technology +000583 ImageCom Limited +000584 AbsoluteValue Systems, Inc. +000585 Juniper Networks, Inc. +000586 Lucent Technologies +000587 Locus, Incorporated +000588 Sensoria Corp. +000589 National Datacomputer +00058A Netcom Co., Ltd. +00058B IPmental, Inc. +00058C Opentech Inc. +00058D Lynx Photonic Networks, Inc. +00058E Ahead Communications System GmbH +00058F CLCsoft co. +000590 Ascom Business Systems +000591 Active Silicon Ltd. +000592 Pultex Corp. +000593 Grammar Engine Inc. +000594 IXXAT Automation GmbH +000595 Alesis Corporation +000596 Genotech Co., Ltd. +000597 Eagle Traffic Control Systems +000598 CRONOS S.r.l. +000599 PEI Electronics, Inc. +00059A Cisco Systems, Inc. +00059B Cisco Systems, Inc. +00059C Kleinknecht GmbH, Ing. Buero +00059D Daniel Computing Systems, Inc. +00059E Zinwell Corporation +00059F Yotta Networks, Inc. +0005A0 MOBILINE Kft. +0005A1 Zenocom +0005A2 CELOX Networks +0005A3 QEI, Inc. +0005A4 Lucid Voice Ltd. +0005A5 KOTT +0005A6 Extron Electronics +0005A7 Hyperchip, Inc. +0005A8 WYLE ELECTRONICS +0005A9 Princeton Networks, Inc. +0005AA Moore Industries Int. +0005AB Cyber Fone, Inc. +0005AC Northern Digital, Inc. +0005AD Topspin Communications, Inc. +0005AE Mediaport USA +0005AF InnoScan Computing A/S +0005B0 Korea Computer Technology Co., Ltd. +0005B1 ASB Technology BV +0005B2 Medison Co., Ltd. +0005B3 Asahi-Engineering Co., Ltd. +0005B4 Aceex Corporation +0005B5 Broadcom Technologies +0005B6 INSYS Microelectronics GmbH +0005B7 Arbor Technology Corp. +0005B8 Electronic Design Associates, Inc. +0005B9 Airvana, Inc. +0005BA Area Netwoeks, Inc. +0005BC Resorsys Ltd. +0005BD ROAX BV +0005BE Kongsberg Seatex AS +0005BF JustEzy Technology, Inc. +0005C0 Digital Network Alacarte Co., Ltd. +0005C1 A-Kyung Motion, Inc. +0005C2 Digital Archway, Inc. +0005C3 Pacific Instruments, Inc. +0005C4 Telect, Inc. +0005C5 Flaga HF +0005C6 Triz Communications +0005C7 I/F-COM A/S +0005C8 VERYTECH +0005C9 LG Innotek +0005CA Hitron Technology, Inc. +0005CB ROIS Technologies, Inc. +0005CC Sumtel Communications, Inc. +0005CD Nippon Columbia +0005CE Prolink Microsystems Corporation +0005CF Thunder River Technologies, Inc. +0005D0 Solinet Systems +0005D1 Metavector Technologies +0005D2 DAP Technologies +0005D3 CAC, Inc. +0005D4 FutureSmart Networks, Inc. +0005D5 Speedcom Wireless +0005D6 Titan Wireless +0005D7 Vista Imaging, Inc. +0005D8 Arescom, Inc. +0005D9 Techno Valley, Inc. +0005DA Apex Automationstechnik +0005DB Nentec GmbH +0005DC Cisco Systems, Inc. +0005DD Cisco Systems, Inc. +0005DE Gi Fone Korea, Inc. +0005DF Electronic Innovation, Inc. +0005E0 Empirix Corp. +0005E1 Trellis Photonics, Ltd. +0005E2 Creativ Network Technologies +0005E3 LightSand Communications, Inc. +0005E4 Red Lion Controls L.P. +0005E5 Renishaw PLC +0005E6 Egenera, Inc. +0005E7 Netrake +0005E8 TurboWave, Inc. +0005E9 Unicess Networks, Inc. +0005EA Viewcast Corporation +0005EB Blue Ridge Networks, Inc. +0005EC Mosaic Systems Inc. +0005ED Technikum Joanneaum GmbH +0005EE BEWATOR Group +0005EF ADOIR Digital Technology +0005F0 SATEC +0005F1 VRcom, Inc. +0005F2 Power R, Inc. +0005F3 Weboyn +0005F4 SystemBase Co., Ltd. +0005F5 OYO Geospace Corp. +0005F6 Young Chang Co. Ltd. +0005F7 Analog Devices, Inc. +0005F8 Real Time Access, Inc. +0005F9 Diva Systems +0005FA IPOptical, Inc. +0005FB Sharegate +0005FC Schenck Pegasus Corp. +0005FD PacketLight Networks Ltd. +0005FE Traficon N.V. +0005FF SNS Solutions, Inc. +000600 Tokyo Electronic Industry Co., Ltd. +000601 Otanikeiki Co., Ltd. +000602 Cirkitech Electronics Co. +000603 Baker Hughes +000604 @Track Communications, Inc. +000605 Inncom International, Inc. +000606 RapidWan, Inc. +000607 Omni-Directional Control Technology Inc. +000608 At-Sky SAS +000609 Crossport Systems +00060A Blue2space.com +00060B Paceline Systems Corporation +00060C Melco Industries, Inc. +00060D Wave7 Optics +00060E IGSYS Systems, Inc. +00060F Narad Networks Inc +000610 Abeona Networks Inc +000611 Zeus Wireless, Inc. +000612 Accusys, Inc. +000613 Kawasaki Steel Corporation +000614 Prism Holdings +000615 Kimoto Electric Co., Ltd. +000616 Tel Net Co., Ltd. +000617 Redswitch Inc. +000618 DigiPower Manufacturing Inc. +000619 Connection Technology Systems +00061A Zetari Inc. +00061B Portable Systems, IBM Japan Co, Ltd +00061C Hoshino Metal Industries, Ltd. +00061D MIP Telecom, Inc. +00061E Maxan Systems +00061F Vision Components GmbH +000620 Serial System Ltd. +000621 Hinox, Co., Ltd. +000622 Chung Fu Chen Yeh Enterprise Corp. +000623 MGE UPS Systems France +000624 Gentner Communications +000625 The Linksys Group, Inc. +000626 MWE GmbH +000627 Uniwide Technologies, Inc. +000628 Cisco Systems, Inc. +000629 IBM CORPORATION +00062A Cisco Systems, Inc. +00062B INTRASERVER TECHNOLOGY +00062C Network Robots, Inc. +00062D TouchStar Technologies, L.L.C. +00062E Aristos Logic Corp. +00062F Pivotech Systems Inc. +000630 Adtranz Sweden +000631 Optical Solutions, Inc. +000632 Mesco Engineering GmbH +000633 Heimann Biometric Systems GmbH +000634 GTE Airfone Inc. +000635 PacketAir Networks, Inc. +000636 Jedai Broadband Networks +000637 Toptrend-Meta Information (ShenZhen) Inc. +000638 Sungjin C&C Co., Ltd. +000639 Newtec +00063A Dura Micro, Inc. +00063B Lineo Canada Corp. +00063C NMI Electronics Ltd +00063D Microwave Data Systems Inc. +00063E Opthos Inc. +00063F Everex Communications Inc. +000640 White Rock Networks +000641 ITCN +000642 Genetel Systems Inc. +000643 SONO Computer Co., Ltd. +000644 NEIX Inc. +000645 Meisei Electric Co. Ltd. +000646 ShenZhen XunBao Network Technology Co Ltd +000647 Etrali S.A. +000648 Seedsware, Inc. +000649 Quante +00064A Honeywell Co., Ltd. (KOREA) +00064B Alexon Co., Ltd. +00064C Invicta Networks, Inc. +00064D Sencore +00064E Broad Net Technology Inc. +00064F PRO-NETS Technology Corporation +000650 Tiburon Networks, Inc. +000651 Aspen Networks Inc. +000652 Cisco Systems, Inc. +000653 Cisco Systems, Inc. +000654 Maxxio Technologies +000655 Yipee, Inc. +000656 Tactel AB +000657 Market Central, Inc. +000658 Helmut Fischer GmbH & Co. KG +000659 EAL (Apeldoorn) B.V. +00065A Strix Systems +00065B Dell Computer Corp. +00065C Malachite Technologies, Inc. +00065D Heidelberg Web Systems +00065E Photuris, Inc. +00065F ECI Telecom - NGTS Ltd. +000660 NADEX Co., Ltd. +000661 NIA Home Technologies Corp. +000662 MBM Technology Ltd. +000663 Human Technology Co., Ltd. +000664 Fostex Corporation +000665 Summy Gikem, Inc. +000666 Roving Networks +000667 Tripp Lite +000668 Vicon Industries Inc. +000669 Datasound Laboratories Ltd +00066A InfiniCon Systems, Inc. +00066B Sysmex Corporation +00066C Robinson Corporation +00066D Compuprint S.P.A. +00066E Delta Electronics, Inc. +00066F Korea Data Systems +000670 Upponetti Oy +000671 Softing AG +000672 Netezza +000673 Optelecom, Inc. +000674 Spectrum Control, Inc. +000675 Banderacom, Inc. +000676 Novra Technologies, Inc. +000677 SICK AG +000678 Marantz Japan, Inc. +000679 Konami Corporation +00067A JMP Systems +00067B Toplink C&C Corporation +00067C CISCO SYSTEMS, INC. +00067D Takasago Ltd. +0006C1 CISCO SYSTEMS, INC. +000701 RACAL-DATACOM +000800 MULTITECH SYSTEMS, INC. +0008C7 COMPAQ COMPUTER CORPORATION +000A27 Apple Computer, Inc. +001000 CABLE TELEVISION +001001 MCK COMMUNICATIONS +001002 ACTIA +001003 IMATRON, INC. +001004 THE BRANTLEY COILE COMPANY,INC +001005 UEC COMMERCIAL +001006 RACAL RECORDERS LTD. +001007 CISCO SYSTEMS, INC. +001008 VIENNA SYSTEMS CORPORATION +001009 HORO QUARTZ +00100A WILLIAMS COMMUNICATIONS GROUP +00100B CISCO SYSTEMS, INC. +00100C ITO CO., LTD. +00100D CISCO SYSTEMS, INC. +00100E MICRO LINEAR COPORATION +00100F INDUSTRIAL CPU SYSTEMS +001010 INITIO CORPORATION +001011 CISCO SYSTEMS, INC. +001012 PROCESSOR SYSTEMS (I) PVT LTD +001013 INDUSTRIAL COMPUTER SOURCE +001014 CISCO SYSTEMS, INC. +001015 OOMON INC. +001016 T.SQWARE +001017 MICOS GMBH +001018 BROADCOM CORPORATION +001019 SIRONA DENTAL SYSTEMS +00101A PICTURETEL CORP. +00101B CORNET TECHNOLOGY, INC. +00101C OHM TECHNOLOGIES INTL, LLC +00101D WINBOND ELECTRONICS CORP. +00101E MATSUSHITA ELECTRONIC +00101F CISCO SYSTEMS, INC. +001020 WELCH ALLYN, DATA COLLECTION +001021 ENCANTO NETWORKS, INC. +001022 SATCOM MEDIA CORPORATION +001023 FLOWWISE NETWORKS, INC. +001024 NAGOYA ELECTRIC WORKS CO., LTD +001025 GRAYHILL INC. +001026 ACCELERATED NETWORKS, INC. +001027 L-3 COMMUNICATIONS EAST +001028 COMPUTER TECHNICA, INC. +001029 CISCO SYSTEMS, INC. +00102A ZF MICROSYSTEMS, INC. +00102B UMAX DATA SYSTEMS, INC. +00102C Lasat Networks A/S +00102D HITACHI SOFTWARE ENGINEERING +00102E NETWORK SYSTEMS & TECHNOLOGIES +00102F CISCO SYSTEMS, INC. +001030 WI-LAN, INC. +001031 OBJECTIVE COMMUNICATIONS, INC. +001032 ALTA TECHNOLOGY +001033 ACCESSLAN COMMUNICATIONS, INC. +001034 GNP COMPUTERS +001035 ELITEGROUP COMPUTER +001036 INTER-TEL INTEGRATED SYSTEMS +001037 CYQ'VE TECHNOLOGY CO., LTD. +001038 MICRO RESEARCH INSTITUTE, INC. +001039 VECTRON SYSTEMS GMBH +00103A DIAMOND NETWORK TECH +00103B HIPPI NETWORKING FORUM +00103C IC ENSEMBLE, INC. +00103D PHASECOM, LTD. +00103E NETSCHOOLS CORPORATION +00103F TOLLGRADE COMMUNICATIONS, INC. +001040 INTERMEC CORPORATION +001041 BRISTOL BABCOCK, INC. +001042 ALACRITECH +001043 A2 CORPORATION +001044 INNOLABS CORPORATION +001045 Nortel Networks +001046 ALCORN MCBRIDE INC. +001047 ECHO ELETRIC CO. LTD. +001048 HTRC AUTOMATION, INC. +001049 SHORELINE TELEWORKS, INC. +00104A THE PARVUC CORPORATION +00104B 3COM CORPORATION +00104C COMPUTER ACCESS TECHNOLOGY +00104D SURTEC INDUSTRIES, INC. +00104E CEOLOGIC +00104F STORAGE TECHNOLOGY CORPORATION +001050 RION CO., LTD. +001051 CMICRO CORPORATION +001052 METTLER-TOLEDO (ALBSTADT) GMBH +001053 COMPUTER TECHNOLOGY CORP. +001054 CISCO SYSTEMS, INC. +001055 FUJITSU MICROELECTRONICS, INC. +001056 SODICK CO., LTD. +001057 Rebel.com, Inc. +001058 ARROWPOINT COMMUNICATIONS,INC. +001059 DIABLO RESEARCH CO. LLC +00105A 3COM CORPORATION +00105B NET INSIGHT AB +00105C QUANTUM DESIGNS (H.K.) LTD. +00105D DRAGER, BUSINESS UNIT +00105E HEKIMIAN LABORATORIES, INC. +00105F IN-SNEC +001060 BILLIONTON SYSTEMS, INC. +001061 HOSTLINK CORP. +001062 NX SERVER, ILNC. +001063 STARGUIDE DIGITAL NETWORKS +001064 DIGITAL EQUIPMENT CORP. +001065 RADYNE CORPORATION +001066 ADVANCED CONTROL SYSTEMS, INC. +001067 REDBACK NETWORKS, INC. +001068 COMOS TELECOM +001069 HELIOSS COMMUNICATIONS, INC. +00106A DIGITAL MICROWAVE CORPORATION +00106B SONUS NETWORKS, INC. +00106C INFRATEC PLUS GMBH +00106D INTEGRITY COMMUNICATIONS, INC. +00106E TADIRAN COM. LTD. +00106F TRENTON TECHNOLOGY INC. +001070 CARADON TREND LTD. +001071 ADVANET INC. +001072 GVN TECHNOLOGIES, INC. +001073 TECHNOBOX, INC. +001074 ATEN INTERNATIONAL CO., LTD. +001075 Maxtor Corporation +001076 EUREM GMBH +001077 SAF DRIVE SYSTEMS, LTD. +001078 NUERA COMMUNICATIONS, INC. +001079 CISCO SYSTEMS, INC. +00107A AMBICOM, INC. +00107B CISCO SYSTEMS, INC. +00107C P-COM, INC. +00107D AURORA COMMUNICATIONS, LTD. +00107E BACHMANN ELECTRONIC GMBH +00107F CRESTRON ELECTRONICS, INC. +001080 METAWAVE COMMUNICATIONS +001081 DPS, INC. +001082 JNA TELECOMMUNICATIONS LIMITED +001083 HEWLETT-PACKARD COMPANY +001084 K-BOT COMMUNICATIONS +001085 POLARIS COMMUNICATIONS, INC. +001086 ATTO TECHNOLOGY, INC. +001087 Xstreamis PLC +001088 AMERICAN NETWORKS INC. +001089 WEBSONIC +00108A TERALOGIC, INC. +00108B LASERANIMATION SOLLINGER GMBH +00108C FUJITSU TELECOMMUNICATIONS +00108D JOHNSON CONTROLS, INC. +00108E HUGH SYMONS CONCEPT +00108F RAPTOR SYSTEMS +001090 CIMETRICS, INC. +001091 NO WIRES NEEDED BV +001092 NETCORE INC. +001093 CMS COMPUTERS, LTD. +001094 ADTECH, INC. +001095 THOMSON CONSUMER ELECTRONICS +001096 TRACEWELL SYSTEMS, INC. +001097 WINNET METROPOLITAN +001098 STARNET TECHNOLOGIES, INC. +001099 INNOMEDIA, INC. +00109A NETLINE +00109B VIXEL CORPORATION +00109C M-SYSTEM CO., LTD. +00109D CLARINET SYSTEMS, INC. +00109E AWARE, INC. +00109F PAVO, INC. +0010A0 INNOVEX TECHNOLOGIES, INC. +0010A1 KENDIN SEMICONDUCTOR, INC. +0010A2 TNS +0010A3 OMNITRONIX, INC. +0010A4 XIRCOM +0010A5 OXFORD INSTRUMENTS +0010A6 CISCO SYSTEMS, INC. +0010A7 UNEX TECHNOLOGY CORPORATION +0010A8 RELIANCE COMPUTER CORP. +0010A9 ADHOC TECHNOLOGIES +0010AA MEDIA4, INC. +0010AB KOITO INDUSTRIES, LTD. +0010AC IMCI TECHNOLOGIES +0010AD SOFTRONICS USB, INC. +0010AE SHINKO ELECTRIC INDUSTRIES CO. +0010AF TAC SYSTEMS, INC. +0010B0 MERIDIAN TECHNOLOGY CORP. +0010B1 FOR-A CO., LTD. +0010B2 COACTIVE AESTHETICS +0010B3 NOKIA MULTIMEDIA TERMINALS +0010B4 ATMOSPHERE NETWORKS +0010B5 ACCTON TECHNOLOGY CORPORATION +0010B6 ENTRATA COMMUNICATIONS CORP. +0010B7 COYOTE TECHNOLOGIES, LLC +0010B8 ISHIGAKI COMPUTER SYSTEM CO. +0010B9 MAXTOR CORP. +0010BA MARTINHO-DAVIS SYSTEMS, INC. +0010BB DATA & INFORMATION TECHNOLOGY +0010BC Nortel Networks +0010BD THE TELECOMMUNICATION +0010BE TELEXIS CORP. +0010BF INTER AIR WIRELESS +0010C0 ARMA, INC. +0010C1 OI ELECTRIC CO., LTD. +0010C2 WILLNET, INC. +0010C3 CSI-CONTROL SYSTEMS +0010C4 MEDIA LINKS CO., LTD. +0010C5 PROTOCOL TECHNOLOGIES, INC. +0010C6 USI +0010C7 DATA TRANSMISSION NETWORK +0010C8 COMMUNICATIONS ELECTRONICS +0010C9 MITSUBISHI ELECTRONICS +0010CA INTEGRAL ACCESS +0010CB FACIT K.K. +0010CC CLP COMPUTER LOGISTIK +0010CD INTERFACE CONCEPT +0010CE VOLAMP, LTD. +0010CF FIBERLANE COMMUNICATIONS +0010D0 WITCOM, LTD. +0010D1 Top Layer Networks, Inc. +0010D2 NITTO TSUSHINKI CO., LTD +0010D3 GRIPS ELECTRONIC GMBH +0010D4 STORAGE COMPUTER CORPORATION +0010D5 IMASDE CANARIAS, S.A. +0010D6 ITT A/CD +0010D7 ARGOSY RESEARCH INC. +0010D8 CALISTA +0010D9 IBM JAPAN, FUJISAWA MT+D +0010DA MOTION ENGINEERING, INC. +0010DB NETSCREEN TECHNOLOGIES, INC. +0010DC MICRO-STAR INTERNATIONAL +0010DD ENABLE SEMICONDUCTOR, INC. +0010DE INTERNATIONAL DATACASTING +0010DF RISE COMPUTER INC. +0010E0 COBALT MICROSERVER, INC. +0010E1 S.I. TECH, INC. +0010E2 ARRAYCOMM, INC. +0010E3 COMPAQ COMPUTER CORPORATION +0010E4 NSI CORPORATION +0010E5 SOLECTRON TEXAS +0010E6 APPLIED INTELLIGENT +0010E7 BREEZECOM +0010E8 TELOCITY, INCORPORATED +0010E9 RAIDTEC LTD. +0010EA ADEPT TECHNOLOGY +0010EB SELSIUS SYSTEMS, ILNC. +0010EC RPCG, LLC +0010ED SUNDANCE TECHNOLOGY, INC. +0010EE CTI PRODUCTS, INC. +0010EF DB NETWORKS, INC. +0010F0 RITTAL-WERK RUDOLF LOH +0010F1 I-O CORPORATION +0010F2 ANTEC +0010F3 NEXCOM INTERNATIONAL CO., LTD. +0010F4 VERTICAL NETWORKS, INC. +0010F5 AMHERST SYSTEMS, INC. +0010F6 CISCO SYSTEMS, INC. +0010F7 IRIICHI TECHNOLOGIES +0010F8 KENWOOD TMI CORPORATION +0010F9 UNIQUE SYSTEMS, INC. +0010FA ZAYANTE, INC. +0010FB ZIDA TECHNOLOGIES LIMITED +0010FC BROADBAND NETWORKS, INC. +0010FD COCOM A/S +0010FE DIGITAL EQUIPMENT CORPORATION +0010FF CISCO SYSTEMS, INC. +001C7C PERQ SYSTEMS CORPORATION +002000 LEXMARK INTERNATIONAL, INC. +002001 DSP SOLUTIONS, INC. +002002 SERITECH ENTERPRISE CO., LTD. +002003 PIXEL POWER LTD. +002004 YAMATAKE-HONEYWELL CO., LTD. +002005 SIMPLE TECHNOLOGY +002006 GARRETT COMMUNICATIONS, INC. +002007 SFA, INC. +002008 CABLE & COMPUTER TECHNOLOGY +002009 PACKARD BELL ELEC., INC. +00200A SOURCE-COMM CORP. +00200B OCTAGON SYSTEMS CORP. +00200C ADASTRA SYSTEMS CORP. +00200D CARL ZEISS +00200E SATELLITE TECHNOLOGY MGMT, INC +00200F TANBAC CO., LTD. +002010 JEOL SYSTEM TECHNOLOGY CO. LTD +002011 CANOPUS CO., LTD. +002012 CAMTRONICS MEDICAL SYSTEMS +002013 DIVERSIFIED TECHNOLOGY, INC. +002014 GLOBAL VIEW CO., LTD. +002015 ACTIS COMPUTER SA +002016 SHOWA ELECTRIC WIRE & CABLE CO +002017 ORBOTECH +002018 CIS TECHNOLOGY INC. +002019 OHLER GMBH +00201A N-BASE SWITCH COMMUNICATIONS +00201B NORTHERN TELECOM/NETWORK +00201C EXCEL, INC. +00201D KATANA PRODUCTS +00201E NETQUEST CORPORATION +00201F BEST POWER TECHNOLOGY, INC. +002020 MEGATRON COMPUTER INDUSTRIES +002021 ALGORITHMS SOFTWARE PVT. LTD. +002022 TEKNIQUE, INC. +002023 T.C. TECHNOLOGIES PTY. LTD +002024 PACIFIC COMMUNICATION SCIENCES +002025 CONTROL TECHNOLOGY, INC. +002026 AMKLY SYSTEMS, INC. +002027 MING FORTUNE INDUSTRY CO., LTD +002028 WEST EGG SYSTEMS, INC. +002029 TELEPROCESSING PRODUCTS, INC. +00202A N.V. DZINE +00202B ADVANCED TELECOMMUNICATIONS +00202C WELLTRONIX CO., LTD. +00202D TAIYO CORPORATION +00202E DAYSTAR DIGITAL +00202F ZETA COMMUNICATIONS, LTD. +002030 ANALOG & DIGITAL SYSTEMS +002031 ERTEC GMBH +002032 ALCATEL TAISEL +002033 SYNAPSE TECHNOLOGIES, INC. +002034 ROTEC INDUSTRIEAUTOMATION GMBH +002035 IBM CORPORATION +002036 BMC SOFTWARE +002037 SEAGATE TECHNOLOGY +002038 VME MICROSYSTEMS INTERNATIONAL +002039 SCINETS +00203A DIGITAL BI0METRICS INC. +00203B WISDM LTD. +00203C EUROTIME AB +00203D NOVAR ELECTRONICS CORPORATION +00203E LOGICAN TECHNOLOGIES, INC. +00203F JUKI CORPORATION +002040 Motorola Broadband Communications Sector +002041 DATA NET +002042 DATAMETRICS CORP. +002043 NEURON COMPANY LIMITED +002044 GENITECH PTY LTD +002045 ION Networks, Inc. +002046 CIPRICO, INC. +002047 STEINBRECHER CORP. +002048 Marconi Communications +002049 COMTRON, INC. +00204A PRONET GMBH +00204B AUTOCOMPUTER CO., LTD. +00204C MITRON COMPUTER PTE LTD. +00204D INOVIS GMBH +00204E NETWORK SECURITY SYSTEMS, INC. +00204F DEUTSCHE AEROSPACE AG +002050 KOREA COMPUTER INC. +002051 PHOENIX DATA COMMUNUNICATIONS +002052 RAGULA SYSTEMS +002053 HUNTSVILLE MICROSYSTEMS, INC. +002054 EASTERN RESEARCH, INC. +002055 ALTECH CO., LTD. +002056 NEOPRODUCTS +002057 TITZE DATENTECHNIK GMBH +002058 ALLIED SIGNAL INC. +002059 MIRO COMPUTER PRODUCTS AG +00205A COMPUTER IDENTICS +00205B SKYLINE TECHNOLOGY +00205C INTERNET SYSTEMS/ FLORIDA INC. +00205D NANOMATIC OY +00205E CASTLE ROCK, INC. +00205F GAMMADATA COMPUTER GMBH +002060 ALCATEL ITALIA S.P.A. +002061 DYNATECH COMMUNICATIONS, INC. +002062 SCORPION LOGIC, LTD. +002063 WIPRO INFOTECH LTD. +002064 PROTEC MICROSYSTEMS, INC. +002065 SUPERNET NETWORKING INC. +002066 GENERAL MAGIC, INC. +002068 ISDYNE +002069 ISDN SYSTEMS CORPORATION +00206A OSAKA COMPUTER CORP. +00206B MINOLTA CO., LTD. +00206C EVERGREEN TECHNOLOGY CORP. +00206D DATA RACE, INC. +00206E XACT, INC. +00206F FLOWPOINT CORPORATION +002070 HYNET, LTD. +002071 IBR GMBH +002072 WORKLINK INNOVATIONS +002073 FUSION SYSTEMS CORPORATION +002074 SUNGWOON SYSTEMS +002075 MOTOROLA COMMUNICATION ISRAEL +002076 REUDO CORPORATION +002077 KARDIOS SYSTEMS CORP. +002078 RUNTOP, INC. +002079 MIKRON GMBH +00207A WISE COMMUNICATIONS, INC. +00207B LEVEL ONE COMMUNICATIONS +00207C AUTEC GMBH +00207D ADVANCED COMPUTER APPLICATIONS +00207E FINECOM CO., LTD. +00207F KYOEI SANGYO CO., LTD. +002080 SYNERGY (UK) LTD. +002081 TITAN ELECTRONICS +002082 ONEAC CORPORATION +002083 PRESTICOM INCORPORATED +002084 OCE PRINTING SYSTEMS, GMBH +002085 EXIDE ELECTRONICS +002086 MICROTECH ELECTRONICS LIMITED +002087 MEMOTEC COMMUNICATIONS CORP. +002088 GLOBAL VILLAGE COMMUNICATION +002089 T3PLUS NETWORKING, INC. +00208A SONIX COMMUNICATIONS, LTD. +00208B LAPIS TECHNOLOGIES, INC. +00208C GALAXY NETWORKS, INC. +00208D CMD TECHNOLOGY +00208E CHEVIN SOFTWARE ENG. LTD. +00208F ECI TELECOM LTD. +002090 ADVANCED COMPRESSION +002091 J125, NATIONAL SECURITY AGENCY +002092 CHESS ENGINEERING B.V. +002093 LANDINGS TECHNOLOGY CORP. +002094 CUBIX CORPORATION +002095 RIVA ELECTRONICS +002096 SIEBE ENVIRONMENTAL CONTROLS +002097 APPLIED SIGNAL TECHNOLOGY +002098 HECTRONIC AB +002099 BON ELECTRIC CO., LTD. +00209A THE 3DO COMPANY +00209B ERSAT ELECTRONIC GMBH +00209C PRIMARY ACCESS CORP. +00209D LIPPERT AUTOMATIONSTECHNIK +00209E BROWN'S OPERATING SYSTEM +00209F MERCURY COMPUTER SYSTEMS, INC. +0020A0 OA LABORATORY CO., LTD. +0020A1 DOVATRON +0020A2 GALCOM NETWORKING LTD. +0020A3 DIVICOM INC. +0020A4 MULTIPOINT NETWORKS +0020A5 API ENGINEERING +0020A6 PROXIM, INC. +0020A7 PAIRGAIN TECHNOLOGIES, INC. +0020A8 SAST TECHNOLOGY CORP. +0020A9 WHITE HORSE INDUSTRIAL +0020AA DIGIMEDIA VISION LTD. +0020AB MICRO INDUSTRIES CORP. +0020AC INTERFLEX DATENSYSTEME GMBH +0020AD LINQ SYSTEMS +0020AE ORNET DATA COMMUNICATION TECH. +0020AF 3COM CORPORATION +0020B0 GATEWAY DEVICES, INC. +0020B1 COMTECH RESEARCH INC. +0020B2 GKD GESELLSCHAFT FUR +0020B3 SCLTEC COMMUNICATIONS SYSTEMS +0020B4 TERMA ELEKTRONIK AS +0020B5 YASKAWA ELECTRIC CORPORATION +0020B6 AGILE NETWORKS, INC. +0020B7 NAMAQUA COMPUTERWARE +0020B8 PRIME OPTION, INC. +0020B9 METRICOM, INC. +0020BA CENTER FOR HIGH PERFORMANCE +0020BB ZAX CORPORATION +0020BC JTEC PTY LTD. +0020BD NIOBRARA R & D CORPORATION +0020BE LAN ACCESS CORP. +0020BF AEHR TEST SYSTEMS +0020C0 PULSE ELECTRONICS, INC. +0020C1 TAIKO ELECTRIC WORKS, LTD. +0020C2 TEXAS MEMORY SYSTEMS, INC. +0020C3 COUNTER SOLUTIONS LTD. +0020C4 INET,INC. +0020C5 EAGLE TECHNOLOGY +0020C6 NECTEC +0020C7 AKAI Professional M.I. Corp. +0020C8 LARSCOM INCORPORATED +0020C9 VICTRON BV +0020CA DIGITAL OCEAN +0020CB PRETEC ELECTRONICS CORP. +0020CC DIGITAL SERVICES, LTD. +0020CD HYBRID NETWORKS, INC. +0020CE LOGICAL DESIGN GROUP, INC. +0020CF TEST & MEASUREMENT SYSTEMS INC +0020D0 VERSALYNX CORPORATION +0020D1 MICROCOMPUTER SYSTEMS (M) SDN. +0020D2 RAD DATA COMMUNICATIONS, LTD. +0020D3 OST (OUEST STANDARD TELEMATIQU +0020D4 CABLETRON - ZEITTNET INC. +0020D5 VIPA GMBH +0020D6 BREEZECOM +0020D7 JAPAN MINICOMPUTER SYSTEMS CO. +0020D8 NETWAVE TECHNOLOGIES, INC. +0020D9 PANASONIC TECHNOLOGIES, INC./ +0020DA XYLAN CORPORATION +0020DB XNET TECHNOLOGY, INC. +0020DC DENSITRON TAIWAN LTD. +0020DD AWA LTD. +0020DE JAPAN DIGITAL LABORAT'Y CO.LTD +0020DF KYOSAN ELECTRIC MFG. CO., LTD. +0020E0 PREMAX ELECTRONICS, INC. +0020E1 ALAMAR ELECTRONICS +0020E2 INFORMATION RESOURCE +0020E3 MCD KENCOM CORPORATION +0020E4 HSING TECH ENTERPRISE CO., LTD +0020E5 APEX DATA, INC. +0020E6 LIDKOPING MACHINE TOOLS AB +0020E7 B&W NUCLEAR SERVICE COMPANY +0020E8 DATATREK CORPORATION +0020E9 DANTEL +0020EA EFFICIENT NETWORKS, INC. +0020EB CINCINNATI MICROWAVE, INC. +0020EC TECHWARE SYSTEMS CORP. +0020ED GIGA-BYTE TECHNOLOGY CO., LTD. +0020EE GTECH CORPORATION +0020EF USC CORPORATION +0020F0 UNIVERSAL MICROELECTRONICS CO. +0020F1 ALTOS INDIA LIMITED +0020F2 SUN MICROSYSTEMS, INC. +0020F3 RAYNET CORPORATION +0020F4 SPECTRIX CORPORATION +0020F5 PANDATEL AG +0020F6 NET TEK AND KARLNET, INC. +0020F7 CYBERDATA +0020F8 CARRERA COMPUTERS, INC. +0020F9 PARALINK NETWORKS, INC. +0020FA GDE SYSTEMS, INC. +0020FB OCTEL COMMUNICATIONS CORP. +0020FC MATROX +0020FD ITV TECHNOLOGIES, INC. +0020FE TOPWARE INC. / GRAND COMPUTER +0020FF SYMMETRICAL TECHNOLOGIES +003000 ALLWELL TECHNOLOGY CORP. +003001 SMP +003002 Expand Networks +003003 Phasys Ltd. +003004 LEADTEK RESEARCH INC. +003005 Fujitsu Siemens Computers +003006 SUPERPOWER COMPUTER +003007 OPTI, INC. +003008 AVIO DIGITAL, INC. +003009 Tachion Networks, Inc. +00300A AZTECH SYSTEMS LTD. +00300B mPHASE Technologies, Inc. +00300C CONGRUENCY, LTD. +00300D MMC Technology, Inc. +00300E Klotz Digital AG +00300F IMT - Information Management T +003010 VISIONETICS INTERNATIONAL +003011 HMS FIELDBUS SYSTEMS AB +003012 DIGITAL ENGINEERING LTD. +003013 NEC Corporation +003014 DIVIO, INC. +003015 CP CLARE CORP. +003016 ISHIDA CO., LTD. +003017 TERASTACK LTD. +003018 Jetway Information Co., Ltd. +003019 CISCO SYSTEMS, INC. +00301A SMARTBRIDGES PTE. LTD. +00301B SHUTTLE, INC. +00301C ALTVATER AIRDATA SYSTEMS +00301D SKYSTREAM, INC. +00301E 3COM Europe Ltd. +00301F OPTICAL NETWORKS, INC. +003020 TSI, Inc.. +003021 HSING TECH. ENTERPRISE CO.,LTD +003022 Fong Kai Industrial Co., Ltd. +003023 COGENT COMPUTER SYSTEMS, INC. +003024 CISCO SYSTEMS, INC. +003025 CHECKOUT COMPUTER SYSTEMS, LTD +003026 HEITEL +003027 KERBANGO, INC. +003028 FASE Saldatura srl +003029 OPICOM +00302A SOUTHERN INFORMATION +00302B INALP NETWORKS, INC. +00302C SYLANTRO SYSTEMS CORPORATION +00302D QUANTUM BRIDGE COMMUNICATIONS +00302E Hoft & Wessel AG +00302F Smiths Industries +003030 HARMONIX CORPORATION +003031 LIGHTWAVE COMMUNICATIONS, INC. +003032 MAGICRAM, INC. +003033 ORIENT TELECOM CO., LTD. +003036 RMP ELEKTRONIKSYSTEME GMBH +003037 Packard Bell Nec Services +003038 XCP, INC. +003039 SOFTBOOK PRESS +00303A MAATEL +00303B PowerCom Technology +00303C ONNTO CORP. +00303D IVA CORPORATION +00303E Radcom Ltd. +00303F TurboComm Tech Inc. +003040 CISCO SYSTEMS, INC. +003041 SAEJIN T & M CO., LTD. +003042 DeTeWe-Deutsche Telephonwerke +003043 IDREAM TECHNOLOGIES, PTE. LTD. +003044 Portsmith LLC +003045 Village Networks, Inc. (VNI) +003046 Controlled Electronic Manageme +003047 NISSEI ELECTRIC CO., LTD. +003048 Supermicro Computer, Inc. +003049 BRYANT TECHNOLOGY, LTD. +00304A FRAUNHOFER INSTITUTE IMS +00304B ORBACOM SYSTEMS, INC. +00304C APPIAN COMMUNICATIONS, INC. +00304D ESI +00304E BUSTEC PRODUCTION LTD. +00304F PLANET Technology Corporation +003050 Versa Technology +003051 ORBIT AVIONIC & COMMUNICATION +003052 ELASTIC NETWORKS +003053 Basler AG +003054 CASTLENET TECHNOLOGY, INC. +003055 Hitachi Semiconductor America, +003056 Beck IPC GmbH +003057 E-Tel Corporation +003058 API MOTION +003059 DIGITAL-LOGIC AG +00305A TELGEN CORPORATION +00305B MODULE DEPARTMENT +00305C SMAR Laboratories Corp. +00305D DIGITRA SYSTEMS, INC. +00305E Abelko Innovation +00305F IMACON APS +003060 STARMATIX, INC. +003061 MobyTEL +003062 PATH 1 NETWORK TECHNOL'S INC. +003063 SANTERA SYSTEMS, INC. +003064 ADLINK TECHNOLOGY, INC. +003065 APPLE COMPUTER, INC. +003066 DIGITAL WIRELESS CORPORATION +003067 BIOSTAR MICROTECH INT'L CORP. +003068 CYBERNETICS TECH. CO., LTD. +003069 IMPACCT TECHNOLOGY CORP. +00306A PENTA MEDIA CO., LTD. +00306B CMOS SYSTEMS, INC. +00306C Hitex Holding GmbH +00306D LUCENT TECHNOLOGIES +00306E HEWLETT PACKARD +00306F SEYEON TECH. CO., LTD. +003070 1Net Corporation +003071 Cisco Systems, Inc. +003072 INTELLIBYTE INC. +003073 International Microsystems, In +003074 EQUIINET LTD. +003075 ADTECH +003076 Akamba Corporation +003077 ONPREM NETWORKS +003078 Cisco Systems, Inc. +003079 CQOS, INC. +00307A Advanced Technology & Systems +00307B Cisco Systems, Inc. +00307C ADID SA +00307D GRE AMERICA, INC. +00307E Redflex Communication Systems +00307F IRLAN LTD. +003080 CISCO SYSTEMS, INC. +003081 ALTOS C&C +003082 TAIHAN ELECTRIC WIRE CO., LTD. +003083 Ivron Systems +003084 ALLIED TELESYN INTERNAIONAL +003085 CISCO SYSTEMS, INC. +003086 Transistor Devices, Inc. +003087 VEGA GRIESHABER KG +003088 Siara Systems, Inc. +003089 Spectrapoint Wireless, LLC +00308A NICOTRA SISTEMI S.P.A +00308B Brix Networks +00308C ADVANCED DIGITAL INFORMATION +00308D PINNACLE SYSTEMS, INC. +00308E CROSS MATCH TECHNOLOGIES, INC. +00308F MICRILOR, Inc. +003090 CYRA TECHNOLOGIES, INC. +003091 TAIWAN FIRST LINE ELEC. CORP. +003092 ModuNORM GmbH +003093 SONNET TECHNOLOGIES, INC. +003094 Cisco Systems, Inc. +003095 Procomp Informatics, Ltd. +003096 CISCO SYSTEMS, INC. +003097 EXOMATIC AB +003098 Global Converging Technologies +003099 BOENIG UND KALLENBACH OHG +00309A ASTRO TERRA CORP. +00309B Smartware +00309C Timing Applications, Inc. +00309D Nimble Microsystems, Inc. +00309E WORKBIT CORPORATION. +00309F AMBER NETWORKS +0030A0 TYCO SUBMARINE SYSTEMS, LTD. +0030A1 OPTI TECH CO., LTD. +0030A2 Lightner Engineering +0030A3 CISCO SYSTEMS, INC. +0030A4 Woodwind Communications System +0030A5 ACTIVE POWER +0030A6 VIANET TECHNOLOGIES, LTD. +0030A7 SCHWEITZER ENGINEERING +0030A8 OL'E COMMUNICATIONS, INC. +0030A9 Netiverse, Inc. +0030AA AXUS MICROSYSTEMS, INC. +0030AB DELTA NETWORKS, INC. +0030AC Systeme Lauer GmbH & Co., Ltd. +0030AD SHANGHAI COMMUNICATION +0030AE Times N System, Inc. +0030AF Honeywell Reqelsysteme GmbH +0030B0 Convergenet Technologies +0030B1 GOC GESELLSCHAFT FUR OPTISCHE +0030B2 WESCAM - HEALDSBURG +0030B3 San Valley Systems, Inc. +0030B4 INTERSIL CORP. +0030B5 Tadiran Microwave Networks +0030B6 CISCO SYSTEMS, INC. +0030B7 Teletrol Systems, Inc. +0030B8 RiverDelta Networks +0030B9 ECTEL +0030BA AC&T SYSTEM CO., LTD. +0030BB CacheFlow, Inc. +0030BC Optronic AG +0030BD BELKIN COMPONENTS +0030BE City-Net Technology, Inc. +0030BF MULTIDATA GMBH +0030C0 Lara Technology, Inc. +0030C1 HEWLETT-PACKARD +0030C2 COMONE +0030C3 FLUECKIGER ELEKTRONIK AG +0030C4 Niigata Canotec Co., Inc. +0030C5 CADENCE DESIGN SYSTEMS +0030C6 CONTROL SOLUTIONS, INC. +0030C7 MACROMATE CORP. +0030C8 GAD LINE, LTD. +0030C9 LuxN, N +0030CA Discovery Com +0030CB OMNI FLOW COMPUTERS, INC. +0030CC Tenor Networks, Inc. +0030CD CONEXANT SYSTEMS, INC. +0030CE Zaffire +0030CF TWO TECHNOLOGIES, INC. +0030D1 INOVA CORPORATION +0030D2 WIN TECHNOLOGIES, CO., LTD. +0030D3 Agilent Technologies +0030D4 COMTIER +0030D5 DResearch GmbH +0030D6 MSC VERTRIEBS GMBH +0030D7 Innovative Systems, L.L.C. +0030D8 SITEK +0030D9 DATACORE SOFTWARE CORP. +0030DA COMTREND CO. +0030DB Mindready Solutions, Inc. +0030DC RIGHTECH CORPORATION +0030DD INDIGITA CORPORATION +0030DE WAGO Kontakttechnik GmbH +0030DF KB/TEL TELECOMUNICACIONES +0030E0 OXFORD SEMICONDUCTOR LTD. +0030E1 ACROTRON SYSTEMS, INC. +0030E2 GARNET SYSTEMS CO., LTD. +0030E3 SEDONA NETWORKS CORP. +0030E4 CHIYODA SYSTEM RIKEN +0030E5 Amper Datos S.A. +0030E6 SIEMENS MEDICAL SYSTEMS +0030E7 CNF MOBILE SOLUTIONS, INC. +0030E8 ENSIM CORP. +0030E9 GMA COMMUNICATION MANUFACT'G +0030EA TeraForce Technology Corporation +0030EB TURBONET COMMUNICATIONS, INC. +0030EC BORGARDT +0030ED Expert Magnetics Corp. +0030EE DSG Technology, Inc. +0030EF NEON TECHNOLOGY, INC. +0030F0 Uniform Industrial Corp. +0030F1 Accton Technology Corp. +0030F2 CISCO SYSTEMS, INC. +0030F3 At Work Computers +0030F4 STARDOT TECHNOLOGIES +0030F5 Wild Lab. Ltd. +0030F6 SECURELOGIX CORPORATION +0030F7 RAMIX INC. +0030F8 Dynapro Systems, Inc. +0030F9 Sollae Systems Co., Ltd. +0030FA TELICA, INC. +0030FB AZS Technology AG +0030FC Terawave Communications, Inc. +0030FD INTEGRATED SYSTEMS DESIGN +0030FE DSA GmbH +0030FF DATAFAB SYSTEMS, INC. +004000 PCI COMPONENTES DA AMZONIA LTD +004001 ZYXEL COMMUNICATIONS, INC. +004002 PERLE SYSTEMS LIMITED +004003 WESTINGHOUSE PROCESS CONTROL +004004 ICM CO. LTD. +004005 ANI COMMUNICATIONS INC. +004006 SAMPO TECHNOLOGY CORPORATION +004007 TELMAT INFORMATIQUE +004008 A PLUS INFO CORPORATION +004009 TACHIBANA TECTRON CO., LTD. +00400A PIVOTAL TECHNOLOGIES, INC. +00400B CISCO SYSTEMS, INC. +00400C GENERAL MICRO SYSTEMS, INC. +00400D LANNET DATA COMMUNICATIONS,LTD +00400E MEMOTEC COMMUNICATIONS, INC. +00400F DATACOM TECHNOLOGIES +004010 SONIC SYSTEMS, INC. +004011 ANDOVER CONTROLS CORPORATION +004012 WINDATA, INC. +004013 NTT DATA COMM. SYSTEMS CORP. +004014 COMSOFT GMBH +004015 ASCOM INFRASYS AG +004016 HADAX ELECTRONICS, INC. +004017 XCD INC. +004018 ADOBE SYSTEMS, INC. +004019 AEON SYSTEMS, INC. +00401A FUJI ELECTRIC CO., LTD. +00401B PRINTER SYSTEMS CORP. +00401C AST RESEARCH, INC. +00401D INVISIBLE SOFTWARE, INC. +00401E ICC +00401F COLORGRAPH LTD +004020 PINACL COMMUNICATION +004021 RASTER GRAPHICS +004022 KLEVER COMPUTERS, INC. +004023 LOGIC CORPORATION +004024 COMPAC INC. +004025 MOLECULAR DYNAMICS +004026 MELCO, INC. +004027 SMC MASSACHUSETTS, INC. +004028 NETCOMM LIMITED +004029 COMPEX +00402A CANOGA-PERKINS +00402B TRIGEM COMPUTER, INC. +00402C ISIS DISTRIBUTED SYSTEMS, INC. +00402D HARRIS ADACOM CORPORATION +00402E PRECISION SOFTWARE, INC. +00402F XLNT DESIGNS INC. +004030 GK COMPUTER +004031 KOKUSAI ELECTRIC CO., LTD +004032 DIGITAL COMMUNICATIONS +004033 ADDTRON TECHNOLOGY CO., LTD. +004034 BUSTEK CORPORATION +004035 OPCOM +004036 TRIBE COMPUTER WORKS, INC. +004037 SEA-ILAN, INC. +004038 TALENT ELECTRIC INCORPORATED +004039 OPTEC DAIICHI DENKO CO., LTD. +00403A IMPACT TECHNOLOGIES +00403B SYNERJET INTERNATIONAL CORP. +00403C FORKS, INC. +00403D TERADATA +00403E RASTER OPS CORPORATION +00403F SSANGYONG COMPUTER SYSTEMS +004040 RING ACCESS, INC. +004041 FUJIKURA LTD. +004042 N.A.T. GMBH +004043 NOKIA TELECOMMUNICATIONS +004044 QNIX COMPUTER CO., LTD. +004045 TWINHEAD CORPORATION +004046 UDC RESEARCH LIMITED +004047 WIND RIVER SYSTEMS +004048 SMD INFORMATICA S.A. +004049 TEGIMENTA AG +00404A WEST AUSTRALIAN DEPARTMENT +00404B MAPLE COMPUTER SYSTEMS +00404C HYPERTEC PTY LTD. +00404D TELECOMMUNICATIONS TECHNIQUES +00404E FLUENT, INC. +00404F SPACE & NAVAL WARFARE SYSTEMS +004050 IRONICS, INCORPORATED +004051 GRACILIS, INC. +004052 STAR TECHNOLOGIES, INC. +004053 AMPRO COMPUTERS +004054 CONNECTION MACHINES SERVICES +004055 METRONIX GMBH +004056 MCM JAPAN LTD. +004057 LOCKHEED - SANDERS +004058 KRONOS, INC. +004059 YOSHIDA KOGYO K. K. +00405A GOLDSTAR INFORMATION & COMM. +00405B FUNASSET LIMITED +00405C FUTURE SYSTEMS, INC. +00405D STAR-TEK, INC. +00405E NORTH HILLS ISRAEL +00405F AFE COMPUTERS LTD. +004060 COMENDEC LTD +004061 DATATECH ENTERPRISES CO., LTD. +004062 E-SYSTEMS, INC./GARLAND DIV. +004063 VIA TECHNOLOGIES, INC. +004064 KLA INSTRUMENTS CORPORATION +004065 GTE SPACENET +004066 HITACHI CABLE, LTD. +004067 OMNIBYTE CORPORATION +004068 EXTENDED SYSTEMS +004069 LEMCOM SYSTEMS, INC. +00406A KENTEK INFORMATION SYSTEMS,INC +00406B SYSGEN +00406C COPERNIQUE +00406D LANCO, INC. +00406E COROLLARY, INC. +00406F SYNC RESEARCH INC. +004070 INTERWARE CO., LTD. +004071 ATM COMPUTER GMBH +004072 APPLIED INNOVATION, INC. +004073 BASS ASSOCIATES +004074 CABLE AND WIRELESS +004075 M-TRADE (UK) LTD +004076 Sun Conversion Technologies +004077 MAXTON TECHNOLOGY CORPORATION +004078 WEARNES AUTOMATION PTE LTD +004079 JUKO MANUFACTURE COMPANY, LTD. +00407A SOCIETE D'EXPLOITATION DU CNIT +00407B SCIENTIFIC ATLANTA +00407C QUME CORPORATION +00407D EXTENSION TECHNOLOGY CORP. +00407E EVERGREEN SYSTEMS, INC. +00407F AGEMA INFRARED SYSTEMS AB +004080 ATHENIX CORPORATION +004081 MANNESMANN SCANGRAPHIC GMBH +004082 LABORATORY EQUIPMENT CORP. +004083 TDA INDUSTRIA DE PRODUTOS +004084 HONEYWELL INC. +004085 SAAB INSTRUMENTS AB +004086 MICHELS & KLEBERHOFF COMPUTER +004087 UBITREX CORPORATION +004088 MOBIUS TECHNOLOGIES, INC. +004089 MEIDENSHA CORPORATION +00408A TPS TELEPROCESSING SYS. GMBH +00408B RAYLAN CORPORATION +00408C AXIS COMMUNICATIONS AB +00408D THE GOODYEAR TIRE & RUBBER CO. +00408E DIGILOG, INC. +00408F WM-DATA MINFO AB +004090 ANSEL COMMUNICATIONS +004091 PROCOMP INDUSTRIA ELETRONICA +004092 ASP COMPUTER PRODUCTS, INC. +004093 PAXDATA NETWORKS LTD. +004094 SHOGRAPHICS, INC. +004095 R.P.T. INTERGROUPS INT'L LTD. +004096 Aironet Wireless Communication +004097 DATEX DIVISION OF +004098 DRESSLER GMBH & CO. +004099 NEWGEN SYSTEMS CORP. +00409A NETWORK EXPRESS, INC. +00409B HAL COMPUTER SYSTEMS INC. +00409C TRANSWARE +00409D DIGIBOARD, INC. +00409E CONCURRENT TECHNOLOGIES LTD. +00409F LANCAST/CASAT TECHNOLOGY, INC. +0040A0 GOLDSTAR CO., LTD. +0040A1 ERGO COMPUTING +0040A2 KINGSTAR TECHNOLOGY INC. +0040A3 MICROUNITY SYSTEMS ENGINEERING +0040A4 ROSE ELECTRONICS +0040A5 CLINICOMP INTL. +0040A6 Cray, Inc. +0040A7 ITAUTEC PHILCO S.A. +0040A8 IMF INTERNATIONAL LTD. +0040A9 DATACOM INC. +0040AA VALMET AUTOMATION INC. +0040AB ROLAND DG CORPORATION +0040AC SUPER WORKSTATION, INC. +0040AD SMA REGELSYSTEME GMBH +0040AE DELTA CONTROLS, INC. +0040AF DIGITAL PRODUCTS, INC. +0040B0 BYTEX CORPORATION, ENGINEERING +0040B1 CODONICS INC. +0040B2 SYSTEMFORSCHUNG +0040B3 PAR MICROSYSTEMS CORPORATION +0040B4 NEXTCOM K.K. +0040B5 VIDEO TECHNOLOGY COMPUTERS LTD +0040B6 COMPUTERM CORPORATION +0040B7 STEALTH COMPUTER SYSTEMS +0040B8 IDEA ASSOCIATES +0040B9 MACQ ELECTRONIQUE SA +0040BA ALLIANT COMPUTER SYSTEMS CORP. +0040BB GOLDSTAR CABLE CO., LTD. +0040BC ALGORITHMICS LTD. +0040BD STARLIGHT NETWORKS, INC. +0040BE BOEING DEFENSE & SPACE +0040BF CHANNEL SYSTEMS INTERN'L INC. +0040C0 VISTA CONTROLS CORPORATION +0040C1 BIZERBA-WERKE WILHEIM KRAUT +0040C2 APPLIED COMPUTING DEVICES +0040C3 FISCHER AND PORTER CO. +0040C4 KINKEI SYSTEM CORPORATION +0040C5 MICOM COMMUNICATIONS INC. +0040C6 FIBERNET RESEARCH, INC. +0040C7 RUBY TECH CORPORATION +0040C8 MILAN TECHNOLOGY CORPORATION +0040C9 NCUBE +0040CA FIRST INTERNAT'L COMPUTER, INC +0040CB LANWAN TECHNOLOGIES +0040CC SILCOM MANUF'G TECHNOLOGY INC. +0040CD TERA MICROSYSTEMS, INC. +0040CE NET-SOURCE, INC. +0040CF STRAWBERRY TREE, INC. +0040D0 MITAC INTERNATIONAL CORP. +0040D1 FUKUDA DENSHI CO., LTD. +0040D2 PAGINE CORPORATION +0040D3 KIMPSION INTERNATIONAL CORP. +0040D4 GAGE TALKER CORP. +0040D5 SARTORIUS AG +0040D6 LOCAMATION B.V. +0040D7 STUDIO GEN INC. +0040D8 OCEAN OFFICE AUTOMATION LTD. +0040D9 AMERICAN MEGATRENDS INC. +0040DA TELSPEC LTD +0040DB ADVANCED TECHNICAL SOLUTIONS +0040DC TRITEC ELECTRONIC GMBH +0040DD HONG TECHNOLOGIES +0040DE ELETTRONICA SAN GIORGIO +0040DF DIGALOG SYSTEMS, INC. +0040E0 ATOMWIDE LTD. +0040E1 MARNER INTERNATIONAL, INC. +0040E2 MESA RIDGE TECHNOLOGIES, INC. +0040E3 QUIN SYSTEMS LTD +0040E4 E-M TECHNOLOGY, INC. +0040E5 SYBUS CORPORATION +0040E6 C.A.E.N. +0040E7 ARNOS INSTRUMENTS & COMPUTER +0040E8 CHARLES RIVER DATA SYSTEMS,INC +0040E9 ACCORD SYSTEMS, INC. +0040EA PLAIN TREE SYSTEMS INC +0040EB MARTIN MARIETTA CORPORATION +0040EC MIKASA SYSTEM ENGINEERING +0040ED NETWORK CONTROLS INT'NATL INC. +0040EE OPTIMEM +0040EF HYPERCOM, INC. +0040F0 MICRO SYSTEMS, INC. +0040F1 CHUO ELECTRONICS CO., LTD. +0040F2 JANICH & KLASS COMPUTERTECHNIK +0040F3 NETCOR +0040F4 CAMEO COMMUNICATIONS, INC. +0040F5 OEM ENGINES +0040F6 KATRON COMPUTERS INC. +0040F7 POLAROID MEDICAL IMAGING SYS. +0040F8 SYSTEMHAUS DISCOM +0040F9 COMBINET +0040FA MICROBOARDS, INC. +0040FB CASCADE COMMUNICATIONS CORP. +0040FC IBR COMPUTER TECHNIK GMBH +0040FD LXE +0040FE SYMPLEX COMMUNICATIONS +0040FF TELEBIT CORPORATION +005000 NEXO COMMUNICATIONS, INC. +005001 YAMASHITA SYSTEMS CORP. +005002 OMNISEC AG +005003 GRETAG MACBETH AG +005004 3COM CORPORATION +005006 TAC AB +005007 SIEMENS TELECOMMUNICATION +005008 TIVA MICROCOMPUTER CORP. (TMC) +005009 PHILIPS BROADBAND NETWORKS +00500A IRIS TECHNOLOGIES, INC. +00500B CISCO SYSTEMS, INC. +00500C ETEK LABS, INC. +00500D SATORI ELECTORIC CO., LTD. +00500E CHROMATIS NETWORKS,INC. +00500F CISCO SYSTEMS, INC. +005010 NOVANET LEARNING, INC. +005012 CBL - GMBH +005013 Chaparral Technologies, Inc. +005014 CISCO SYSTEMS, INC. +005015 BRIGHT STAR ENGINEERING +005016 SST/WOODHEAD INDUSTRIES +005017 RSR S.R.L. +005018 ADVANCED MULTIMEDIA INTERNET +005019 SPRING TIDE NETWORKS, INC. +00501A UISIQN +00501B ABL CANADA, INC. +00501C JATOM SYSTEMS, INC. +00501E MIRANDA TECHNOLOGIES, INC. +00501F MRG SYSTEMS, LTD. +005020 MEDIASTAR CO., LTD. +005021 EIS INTERNATIONAL, INC. +005022 ZONET TECHNOLOGY, INC. +005023 PG DESIGN ELECTRONICS, INC. +005024 NAVIC SYSTEMS, INC. +005026 COSYSTEMS, INC. +005027 GENICOM CORPORATION +005028 AVAL COMMUNICATIONS +005029 1394 PRINTER WORKING GROUP +00502A CISCO SYSTEMS, INC. +00502B GENRAD LTD. +00502C SOYO COMPUTER, INC. +00502D ACCEL, INC. +00502E CAMBEX CORPORATION +00502F TOLLBRIDGE TECHNOLOGIES, INC. +005030 FUTURE PLUS SYSTEMS +005031 AEROFLEX LABORATORIES, INC. +005032 PICAZO COMMUNICATIONS, INC. +005033 MAYAN NETWORKS +005036 NETCAM, LTD. +005037 KOGA ELECTRONICS CO. +005038 DAIN TELECOM CO., LTD. +005039 MARINER NETWORKS +00503A DATONG ELECTRONICS LTD. +00503B MEDIAFIRE CORPORATION +00503C TSINGHUA NOVEL ELECTRONICS +00503E CISCO SYSTEMS, INC. +00503F ANCHOR GAMES +005040 EMWARE, INC. +005041 CTX OPTO ELECTRONIC CORP. +005042 SCI MANUFACTURING +005043 MARVELL SEMICONDUCTOR, INC. +005044 ASACA CORPORATION +005045 RIOWORKS SOLUTIONS, INC. +005046 MENICX INTERNATIONAL CO., LTD. +005048 INFOLIBRIA +005049 ELLACOYA NETWORKS, INC. +00504A ELTECO A.S. +00504B BARCONET N.V. +00504C GALIL MOTION CONTROL, INC. +00504D TOKYO ELECTRON DEVICE LTD. +00504E SIERRA MONITOR CORP. +00504F OLENCOM ELECTRONICS +005050 CISCO SYSTEMS, INC. +005051 IWATSU ELECTRIC CO., LTD. +005052 TIARA NETWORKS, INC. +005053 CISCO SYSTEMS, INC. +005054 CISCO SYSTEMS, INC. +005055 DOMS A/S +005056 VMWARE, INC. +005057 BROADBAND ACCESS SYSTEMS +005058 VEGASTREAM LIMITED +005059 SUITE TECHNOLOGY SYSTEMS +00505A NETWORK ALCHEMY, INC. +00505B KAWASAKI LSI U.S.A., INC. +00505C TUNDO CORPORATION +00505E DIGITEK MICROLOGIC S.A. +00505F BRAND INNOVATORS +005060 TANDBERG TELECOM AS +005062 KOUWELL ELECTRONICS CORP. ** +005063 OY COMSEL SYSTEM AB +005064 CAE ELECTRONICS +005065 DENSEI-LAMBAD Co., Ltd. +005066 ATECOM GMBH ADVANCED +005067 AEROCOMM, INC. +005068 ELECTRONIC INDUSTRIES +005069 PIXSTREAM INCORPORATED +00506A EDEVA, INC. +00506B SPX-ATEG +00506C G & L BEIJER ELECTRONICS AB +00506D VIDEOJET SYSTEMS +00506E CORDER ENGINEERING CORPORATION +00506F G-CONNECT +005070 CHAINTECH COMPUTER CO., LTD. +005071 AIWA CO., LTD. +005072 CORVIS CORPORATION +005073 CISCO SYSTEMS, INC. +005074 ADVANCED HI-TECH CORP. +005075 KESTREL SOLUTIONS +005076 IBM +005077 PROLIFIC TECHNOLOGY, INC. +005078 MEGATON HOUSE, LTD. +00507A XPEED, INC. +00507B MERLOT COMMUNICATIONS +00507C VIDEOCON AG +00507D IFP +00507E NEWER TECHNOLOGY +00507F DRAYTEK CORP. +005080 CISCO SYSTEMS, INC. +005081 MURATA MACHINERY, LTD. +005082 FORESSON CORPORATION +005083 GILBARCO, INC. +005084 ATL PRODUCTS +005086 TELKOM SA, LTD. +005087 TERASAKI ELECTRIC CO., LTD. +005088 AMANO CORPORATION +005089 SAFETY MANAGEMENT SYSTEMS +00508B COMPAQ COMPUTER CORPORATION +00508C RSI SYSTEMS +00508D ABIT COMPUTER CORPORATION +00508E OPTIMATION, INC. +00508F ASITA TECHNOLOGIES INT'L LTD. +005090 DCTRI +005091 NETACCESS, INC. +005092 RIGAKU INDUSTRIAL CORPORATION +005093 BOEING +005094 PACE MICRO TECHNOLOGY PLC +005095 PERACOM NETWORKS +005096 SALIX TECHNOLOGIES, INC. +005097 MMC-EMBEDDED +005098 GLOBALOOP, LTD. +005099 3COM EUROPE, LTD. +00509A TAG ELECTRONIC SYSTEMS +00509B SWITCHCORE AB +00509C BETA RESEARCH +00509D THE INDUSTREE B.V. +00509E LES TECHNOLOGIES +00509F HORIZON COMPUTER +0050A0 DELTA COMPUTER SYSTEMS, INC. +0050A1 CARLO GAVAZZI, INC. +0050A2 CISCO SYSTEMS, INC. +0050A3 TRANSMEDIA COMMUNICATIONS, INC +0050A4 IO TECH, INC. +0050A5 CAPITOL BUSINESS SYSTEMS, LTD. +0050A6 OPTRONICS +0050A7 CISCO SYSTEMS, INC. +0050A8 OPENCON SYSTEMS, INC. +0050A9 MOLDAT WIRELESS TECHNOLGIES +0050AA KONICA CORPORATION +0050AB NALTEC, INC. +0050AC MAPLE COMPUTER CORPORATION +0050AD COMMUNIQUE WIRELESS CORP. +0050AE IWAKI ELECTRONICS CO., LTD. +0050AF INTERGON, INC. +0050B0 TECHNOLOGY ATLANTA CORPORATION +0050B1 GIDDINGS & LEWIS +0050B2 BRODEL AUTOMATION +0050B3 VOICEBOARD CORPORATION +0050B4 SATCHWELL CONTROL SYSTEMS, LTD +0050B5 FICHET-BAUCHE +0050B6 GOOD WAY IND. CO., LTD. +0050B7 BOSER TECHNOLOGY CO., LTD. +0050B8 INOVA COMPUTERS GMBH & CO. KG +0050B9 XITRON TECHNOLOGIES, INC. +0050BA D-LINK +0050BB CMS TECHNOLOGIES +0050BC HAMMER STORAGE SOLUTIONS +0050BD CISCO SYSTEMS, INC. +0050BE FAST MULTIMEDIA AG +0050BF MOTOTECH INC. +0050C0 GATAN, INC. +0050C1 GEMFLEX NETWORKS, LTD. +0050C2 IEEE REGISTRATION AUTHORITY +0050C4 IMD +0050C5 ADS TECHNOLOGIES, INC. +0050C6 LOOP TELECOMMUNICATION +0050C8 ADDONICS COMMUNICATIONS, INC. +0050C9 MASPRO DENKOH CORP. +0050CA NET TO NET TECHNOLOGIES +0050CB JETTER +0050CC XYRATEX +0050CD DIGIANSWER A/S +0050CE LG INTERNATIONAL CORP. +0050CF VANLINK COMMUNICATION +0050D0 MINERVA SYSTEMS +0050D1 CISCO SYSTEMS, INC. +0050D2 BAE Systems Canada, Inc. +0050D3 DIGITAL AUDIO +0050D4 JOOHONG INFORMATION & +0050D5 AD SYSTEMS CORP. +0050D6 ATLAS COPCO TOOLS AB +0050D7 TELSTRAT +0050D8 UNICORN COMPUTER CORP. +0050D9 ENGETRON-ENGENHARIA ELETRONICA +0050DA 3COM CORPORATION +0050DB CONTEMPORARY CONTROL +0050DC TAS TELEFONBAU A. SCHWABE +0050DD SERRA SOLDADURA, S.A. +0050DE SIGNUM SYSTEMS CORP. +0050DF AIRFIBER, INC. +0050E1 NS TECH ELECTRONICS SDN BHD +0050E2 CISCO SYSTEMS, INC. +0050E3 TELEGATE +0050E4 APPLE COMPUTER, INC. +0050E6 HAKUSAN CORPORATION +0050E7 PARADISE INNOVATIONS (ASIA) +0050E8 NOMADIX INC. +0050EA XEL COMMUNICTIONS, INC. +0050EB ALPHA-TOP CORPORATION +0050EC OLICOM A/S +0050ED ANDA NETWORKS +0050EE TEK DIGITEL CORPORATION +0050EF SPE SYSTEMHAUS GMBH +0050F0 CISCO SYSTEMS, INC. +0050F1 LIBIT SIGNAL PROCESSING, LTD. +0050F2 MICROSOFT CORP. +0050F3 GLOBAL NET INFORMATION CO.,LTD +0050F4 SIGMATEK GMBH & CO. KG +0050F6 PAN-INTERNATIONAL +0050F7 VENTURE MANUFACTURING +0050F8 ENTREGA TECHNOLOGIES, INC. +0050FA OXTEL, LTD. +0050FB VSK ELECTRONICS +0050FC EDIMAX TECHNOLOGY CO., LTD. +0050FD ISIONCOMM CO., LTD. +0050FE PCTVNET ASA +0050FF HAKKO ELECTRONICS CO., LTD. +006000 XYCOM INC. +006001 INNOSYS, INC. +006002 SCREEN SUBTITLING SYSTEMS, LTD +006003 TERAOKA WEIGH SYSTEM PTE, LTD. +006004 COMPUTADORES MODULARES SA +006005 FEEDBACK DATA LTD. +006006 SOTEC CO., LTD +006007 ACRES GAMING, INC. +006008 3COM CORPORATION +006009 CISCO SYSTEMS, INC. +00600A SORD COMPUTER CORPORATION +00600B LOGWARE GMBH +00600C APPLIED DATA SYSTEMS, INC. +00600D MICRODESIGN GMBH +00600E WAVENET INTERNATIONAL, INC. +00600F WESTELL, INC. +006010 NETWORK MACHINES, INC. +006011 CRYSTAL SEMICONDUCTOR CORP. +006012 POWER COMPUTING CORPORATION +006013 NETSTAL MASCHINEN AG +006014 EDEC CO., LTD. +006015 NET2NET CORPORATION +006016 CLARIION +006017 TOKIMEC INC. +006018 STELLAR ONE CORPORATION +006019 BOEHRINGER MANNHEIM CORP. +00601A KEITHLEY INSTRUMENTS +00601B MESA ELECTRONICS +00601C TELXON CORPORATION +00601D LUCENT TECHNOLOGIES +00601E SOFTLAB, INC. +00601F STALLION TECHNOLOGIES +006020 PIVOTAL NETWORKING, INC. +006021 DSC CORPORATION +006022 VICOM SYSTEMS, INC. +006023 PERICOM SEMICONDUCTOR CORP. +006024 GRADIENT TECHNOLOGIES, INC. +006025 ACTIVE IMAGING PLC +006026 VIKING COMPONENTS, INC. +006027 Superior Modular Products +006028 MACROVISION CORPORATION +006029 CARY PERIPHERALS INC. +00602A SYMICRON COMPUTER +00602B PEAK AUDIO +00602C LINX DATA TERMINALS, INC. +00602D ALERTON TECHNOLOGIES, INC. +00602E CYCLADES CORPORATION +00602F CISCO SYSTEMS, INC. +006030 VILLAGE TRONIC +006031 HRK SYSTEMS +006032 I-CUBE, INC. +006033 ACUITY IMAGING, INC. +006034 ROBERT BOSCH GMBH +006035 DALLAS SEMICONDUCTOR, INC. +006036 AUSTRIAN RESEARCH CENTER +006037 PHILIPS SEMICONDUCTORS +006038 Nortel Networks +006039 SANCOM TECHNOLOGY, INC. +00603A QUICK CONTROLS LTD. +00603B AMTEC SPA +00603C HAGIWARA SYS-COM CO., LTD. +00603D 3CX +00603E CISCO SYSTEMS, INC. +00603F PATAPSCO DESIGNS +006040 NETRO CORP. +006041 Yokogawa Electric Corporation +006042 TKS (USA), INC. +006043 COMSOFT SYSTEMS, INC. +006044 LITTON/POLY-SCIENTIFIC +006045 PATHLIGHT TECHNOLOGIES +006046 VMETRO, INC. +006047 CISCO SYSTEMS, INC. +006048 EMC CORPORATION +006049 VINA TECHNOLOGIES +00604A SAIC IDEAS GROUP +00604B BIODATA GMBH +00604C SAT +00604D MMC NETWORKS, INC. +00604E CYCLE COMPUTER CORPORATION, INC. +00604F SUZUKI MFG. CO., LTD. +006050 INTERNIX INC. +006051 QUALITY SEMICONDUCTOR +006052 PERIPHERALS ENTERPRISE CO., L. +006053 TOYODA MACHINE WORKS, LTD. +006054 CONTROLWARE GMBH +006055 CORNELL UNIVERSITY +006056 NETWORK TOOLS, INC. +006057 MURATA MANUFACTURING CO., LTD. +006058 COPPER MOUNTAIN +006059 TECHNICAL COMMUNICATIONS CORP. +00605A CELCORE, INC. +00605B INTRASERVER TECHNOLOGY INC. +00605C CISCO SYSTEMS, INC. +00605D SCANIVALVE CORP. +00605E LIBERTY TECHNOLOGY NETWORKING +00605F NIPPON UNISOFT CORPORATION +006060 DAWNING TECHNOLOGIES, INC. +006061 WHISTLE COMMUNICATIONS CORP. +006062 TELESYNC, INC. +006063 PSION DACOM PLC. +006064 NETCOMM LIMITED +006065 BERNECKER & RAINER +006066 LACROIX TECHNOLGIE +006067 ACER NETXUS INC. +006068 EICON TECHNOLOGY CORPORATION +006069 BROCADE COMMUNICATIONS SYSTEMS +00606A MITSUBISHI WIRELESS COMM. INC. +00606B AICHI ELECTRONICS CO.,LTD. +00606C ARESCOM +00606D DIGITAL EQUIPMENT CORP. +00606E DAVICOM SEMICONDUCTOR, INC. +00606F CLARION CORPORATION OF AMERICA +006070 CISCO SYSTEMS, INC. +006071 MIDAS LAB, INC. +006072 VXL INSTRUMENTS, LIMITED +006073 REDCREEK COMMUNICATIONS, INC. +006074 QSC AUDIO PRODUCTS +006075 PENTEK, INC. +006076 SCHLUMBERGER TECHNOLOGIES +006077 PRISA NETWORKS +006078 POWER MEASUREMENT LTD. +006079 WAVEPHORE NETWORKS, INC. +00607A DVS GMBH +00607B FORE SYSTEMS, INC. +00607C WAVEACCESS, LTD. +00607D SENTIENT NETWORKS INC. +00607E GIGALABS, INC. +00607F AURORA TECHNOLOGIES, INC. +006080 MICROTRONIX DATACOM LTD. +006081 TV/COM INTERNATIONAL +006082 NOVALINK TECHNOLOGIES, INC. +006083 CISCO SYSTEMS, INC. +006084 DIGITAL VIDEO +006085 STORAGE CONCEPTS +006086 LOGIC REPLACEMENT TECH. LTD. +006087 KANSAI ELECTRIC CO., LTD. +006088 WHITE MOUNTAIN DSP, INC. +006089 XATA +00608A CITADEL COMPUTER +00608B CONFERTECH INTERNATIONAL +00608C 3COM CORPORATION +00608D UNIPULSE CORP. +00608E HE ELECTRONICS, TECHNOLOGIE & +00608F TEKRAM TECHNOLOGY CO., LTD. +006090 ABLE COMMUNICATIONS, INC. +006091 FIRST PACIFIC NETWORKS, INC. +006092 MICRO/SYS, INC. +006093 VARIAN +006094 IBM CORP. +006095 ACCU-TIME SYSTEMS, INC. +006096 T.S. MICROTECH INC. +006097 3COM CORPORATION +006098 HT COMMUNICATIONS +006099 LAN MEDIA CORPORATION +00609A NJK TECHNO CO. +00609B ASTRO-MED, INC. +00609C PERKIN-ELMER CORPORATION +00609D PMI FOOD EQUIPMENT GROUP +00609E X3 - INFORMATION TECHNOLOGY +00609F PHAST CORPORATION +0060A0 SWITCHED NETWORK +0060A1 VPNET +0060A2 NIHON UNISYS LIMITED CO. +0060A3 CONTINUUM TECHNOLOGY CORP. +0060A4 GRINAKER SYSTEM TECHNOLOGIES +0060A5 PERFORMANCE TELECOM CORP. +0060A6 PARTICLE MEASURING SYSTEMS +0060A7 MICROSENS GMBH & CO. KG +0060A8 TIDOMAT AB +0060A9 GESYTEC MBH +0060AA INTELLIGENT DEVICES INC. (IDI) +0060AB LARSCOM INCORPORATED +0060AC RESILIENCE CORPORATION +0060AD MEGACHIPS CORPORATION +0060AE TRIO INFORMATION SYSTEMS AB +0060AF PACIFIC MICRO DATA, INC. +0060B0 HEWLETT-PACKARD CO. +0060B1 INPUT/OUTPUT, INC. +0060B2 PROCESS CONTROL CORP. +0060B3 Z-COM, INC. +0060B4 GLENAYRE R&D INC. +0060B5 KEBA GMBH +0060B6 LAND COMPUTER CO., LTD. +0060B7 CHANNELMATIC, INC. +0060B8 CORELIS INC. +0060B9 NITSUKO CORPORATION +0060BA SAHARA NETWORKS, INC. +0060BB CABLETRON - NETLINK, INC. +0060BC KEUNYOUNG ELECTRONICS & +0060BD HUBBELL-PULSECOM +0060BE WEBTRONICS +0060BF MACRAIGOR SYSTEMS, INC. +0060C0 NERA AS +0060C1 WAVESPAN CORPORATION +0060C2 MPL AG +0060C3 NETVISION CORPORATION +0060C4 SOLITON SYSTEMS K.K. +0060C5 ANCOT CORP. +0060C6 DCS AG +0060C7 AMATI COMMUNICATIONS CORP. +0060C8 KUKA WELDING SYSTEMS & ROBOTS +0060C9 CONTROLNET, INC. +0060CA HARMONIC SYSTEMS INCORPORATED +0060CB HITACHI ZOSEN CORPORATION +0060CC EMTRAK, INCORPORATED +0060CD VIDEOSERVER, INC. +0060CE ACCLAIM COMMUNICATIONS +0060CF ALTEON NETWORKS, INC. +0060D0 SNMP RESEARCH INCORPORATED +0060D1 CASCADE COMMUNICATIONS +0060D2 LUCENT TECHNOLOGIES TAIWAN +0060D3 AT&T +0060D4 ELDAT COMMUNICATION LTD. +0060D5 MIYACHI TECHNOS CORP. +0060D6 NOVATEL WIRELESS TECHNOLOGIES +0060D7 ECOLE POLYTECHNIQUE FEDERALE +0060D8 ELMIC SYSTEMS, INC. +0060D9 TRANSYS NETWORKS INC. +0060DA JBM ELECTRONICS CO. +0060DB NTP ELEKTRONIK A/S +0060DC TOYO COMMUNICATION EQUIPMENT +0060DD MYRICOM, INC. +0060DE KAYSER-THREDE GMBH +0060DF INRANGE TECHNOLOGIES CORP. +0060E0 AXIOM TECHNOLOGY CO., LTD. +0060E1 ORCKIT COMMUNICATIONS LTD. +0060E2 QUEST ENGINEERING & DEV. +0060E3 ARBIN INSTRUMENTS +0060E4 COMPUSERVE, INC. +0060E5 FUJI AUTOMATION CO., LTD. +0060E6 SHOMITI SYSTEMS INCORPORATED +0060E7 RANDATA +0060E8 HITACHI COMPUTER PRODUCTS +0060E9 ATOP TECHNOLOGIES, INC. +0060EA STREAMLOGIC +0060EB FOURTHTRACK SYSTEMS +0060EC HERMARY OPTO ELECTRONICS INC. +0060ED RICARDO TEST AUTOMATION LTD. +0060EE APOLLO +0060EF FLYTECH TECHNOLOGY CO., LTD. +0060F0 JOHNSON & JOHNSON MEDICAL, INC +0060F1 EXP COMPUTER, INC. +0060F2 LASERGRAPHICS, INC. +0060F3 NETCOM SYSTEMS, INC. +0060F4 ADVANCED COMPUTER SOLUTIONS, +0060F5 ICON WEST, INC. +0060F6 NEXTEST COMMUNICATION +0060F7 DATAFUSION SYSTEMS +0060F8 LORAN INTERNATIONAL TECHN. INC +0060F9 DIAMOND LANE COMMUNICATIONS +0060FA EDUCATIONAL TECHNOLOGY +0060FB PACKETEER, INC. +0060FC CONSERVATION THROUGH +0060FD NETICS, INC. +0060FE LYNX SYSTEM DEVELOPERS, INC. +0060FF QUVIS, INC. +0070B0 M/A-COM INC. COMPANIES +0070B3 DATA RECALL LTD. +008000 MULTITECH SYSTEMS, INC. +008001 PERIPHONICS CORPORATION +008002 SATELCOM (UK) LTD +008003 HYTEC ELECTRONICS LTD. +008004 ANTLOW COMMUNICATIONS, LTD. +008005 CACTUS COMPUTER INC. +008006 COMPUADD CORPORATION +008007 DLOG NC-SYSTEME +008008 DYNATECH COMPUTER SYSTEMS +008009 JUPITER SYSTEMS, INC. +00800A JAPAN COMPUTER CORP. +00800B CSK CORPORATION +00800C VIDECOM LIMITED +00800D VOSSWINKEL F.U. +00800E ATLANTIX CORPORATION +00800F STANDARD MICROSYSTEMS +008010 COMMODORE INTERNATIONAL +008011 DIGITAL SYSTEMS INT'L. INC. +008012 INTEGRATED MEASUREMENT SYSTEMS +008013 THOMAS-CONRAD CORPORATION +008014 ESPRIT SYSTEMS +008015 SEIKO SYSTEMS, INC. +008016 WANDEL AND GOLTERMANN +008017 PFU LIMITED +008018 KOBE STEEL, LTD. +008019 DAYNA COMMUNICATIONS, INC. +00801A BELL ATLANTIC +00801B KODIAK TECHNOLOGY +00801C NEWPORT SYSTEMS SOLUTIONS +00801D INTEGRATED INFERENCE MACHINES +00801E XINETRON, INC. +00801F KRUPP ATLAS ELECTRONIK GMBH +008020 NETWORK PRODUCTS +008021 NEWBRIDGE RESEARCH CORP. +008022 SCAN-OPTICS +008023 INTEGRATED BUSINESS NETWORKS +008024 KALPANA, INC. +008025 STOLLMANN GMBH +008026 NETWORK PRODUCTS CORPORATION +008027 ADAPTIVE SYSTEMS, INC. +008028 TRADPOST (HK) LTD +008029 EAGLE TECHNOLOGY, INC. +00802A TEST SYSTEMS & SIMULATIONS INC +00802B INTEGRATED MARKETING CO +00802C THE SAGE GROUP PLC +00802D XYLOGICS INC +00802E CASTLE ROCK COMPUTING +00802F NATIONAL INSTRUMENTS CORP. +008030 NEXUS ELECTRONICS +008031 BASYS, CORP. +008032 ACCESS CO., LTD. +008033 FORMATION, INC. +008034 SMT GOUPIL +008035 TECHNOLOGY WORKS, INC. +008036 REFLEX MANUFACTURING SYSTEMS +008037 Ericsson Group +008038 DATA RESEARCH & APPLICATIONS +008039 ALCATEL STC AUSTRALIA +00803A VARITYPER, INC. +00803B APT COMMUNICATIONS, INC. +00803C TVS ELECTRONICS LTD +00803D SURIGIKEN CO., LTD. +00803E SYNERNETICS +00803F TATUNG COMPANY +008040 JOHN FLUKE MANUFACTURING CO. +008041 VEB KOMBINAT ROBOTRON +008042 FORCE COMPUTERS +008043 NETWORLD, INC. +008044 SYSTECH COMPUTER CORP. +008045 MATSUSHITA ELECTRIC IND. CO +008046 UNIVERSITY OF TORONTO +008047 IN-NET CORP. +008048 COMPEX INCORPORATED +008049 NISSIN ELECTRIC CO., LTD. +00804A PRO-LOG +00804B EAGLE TECHNOLOGIES PTY.LTD. +00804C CONTEC CO., LTD. +00804D CYCLONE MICROSYSTEMS, INC. +00804E APEX COMPUTER COMPANY +00804F DAIKIN INDUSTRIES, LTD. +008050 ZIATECH CORPORATION +008051 FIBERMUX +008052 TECHNICALLY ELITE CONCEPTS +008053 INTELLICOM, INC. +008054 FRONTIER TECHNOLOGIES CORP. +008055 FERMILAB +008056 SPHINX ELEKTRONIK GMBH +008057 ADSOFT, LTD. +008058 PRINTER SYSTEMS CORPORATION +008059 STANLEY ELECTRIC CO., LTD +00805A TULIP COMPUTERS INTERNAT'L B.V +00805B CONDOR SYSTEMS, INC. +00805C AGILIS CORPORATION +00805D CANSTAR +00805E LSI LOGIC CORPORATION +00805F COMPAQ COMPUTER CORPORATION +008060 NETWORK INTERFACE CORPORATION +008061 LITTON SYSTEMS, INC. +008062 INTERFACE CO. +008063 RICHARD HIRSCHMANN GMBH & CO. +008064 WYSE TECHNOLOGY +008065 CYBERGRAPHIC SYSTEMS PTY LTD. +008066 ARCOM CONTROL SYSTEMS, LTD. +008067 SQUARE D COMPANY +008068 YAMATECH SCIENTIFIC LTD. +008069 COMPUTONE SYSTEMS +00806A ERI (EMPAC RESEARCH INC.) +00806B SCHMID TELECOMMUNICATION +00806C CEGELEC PROJECTS LTD +00806D CENTURY SYSTEMS CORP. +00806E NIPPON STEEL CORPORATION +00806F ONELAN LTD. +008070 COMPUTADORAS MICRON +008071 SAI TECHNOLOGY +008072 MICROPLEX SYSTEMS LTD. +008073 DWB ASSOCIATES +008074 FISHER CONTROLS +008075 PARSYTEC GMBH +008076 MCNC +008077 BROTHER INDUSTRIES, LTD. +008078 PRACTICAL PERIPHERALS, INC. +008079 MICROBUS DESIGNS LTD. +00807A AITECH SYSTEMS LTD. +00807B ARTEL COMMUNICATIONS CORP. +00807C FIBERCOM, INC. +00807D EQUINOX SYSTEMS INC. +00807E SOUTHERN PACIFIC LTD. +00807F DY-4 INCORPORATED +008080 DATAMEDIA CORPORATION +008081 KENDALL SQUARE RESEARCH CORP. +008082 PEP MODULAR COMPUTERS GMBH +008083 AMDAHL +008084 THE CLOUD INC. +008085 H-THREE SYSTEMS CORPORATION +008086 COMPUTER GENERATION INC. +008087 OKI ELECTRIC INDUSTRY CO., LTD +008088 VICTOR COMPANY OF JAPAN, LTD. +008089 TECNETICS (PTY) LTD. +00808A SUMMIT MICROSYSTEMS CORP. +00808B DACOLL LIMITED +00808C NetScout Systems, Inc. +00808D WESTCOAST TECHNOLOGY B.V. +00808E RADSTONE TECHNOLOGY +00808F C. ITOH ELECTRONICS, INC. +008090 MICROTEK INTERNATIONAL, INC. +008091 TOKYO ELECTRIC CO.,LTD +008092 JAPAN COMPUTER INDUSTRY, INC. +008093 XYRON CORPORATION +008094 ALFA LAVAL AUTOMATION AB +008095 BASIC MERTON HANDELSGES.M.B.H. +008096 HUMAN DESIGNED SYSTEMS, INC. +008097 CENTRALP AUTOMATISMES +008098 TDK CORPORATION +008099 KLOCKNER MOELLER IPC +00809A NOVUS NETWORKS LTD +00809B JUSTSYSTEM CORPORATION +00809C LUXCOM, INC. +00809D Commscraft Ltd. +00809E DATUS GMBH +00809F ALCATEL BUSINESS SYSTEMS +0080A0 EDISA HEWLETT PACKARD S/A +0080A1 MICROTEST, INC. +0080A2 CREATIVE ELECTRONIC SYSTEMS +0080A3 LANTRONIX +0080A4 LIBERTY ELECTRONICS +0080A5 SPEED INTERNATIONAL +0080A6 REPUBLIC TECHNOLOGY, INC. +0080A7 MEASUREX CORP. +0080A8 VITACOM CORPORATION +0080A9 CLEARPOINT RESEARCH +0080AA MAXPEED +0080AB DUKANE NETWORK INTEGRATION +0080AC IMLOGIX, DIVISION OF GENESYS +0080AD CNET TECHNOLOGY, INC. +0080AE HUGHES NETWORK SYSTEMS +0080AF ALLUMER CO., LTD. +0080B0 ADVANCED INFORMATION +0080B1 SOFTCOM A/S +0080B2 NETWORK EQUIPMENT TECHNOLOGIES +0080B3 AVAL DATA CORPORATION +0080B4 SOPHIA SYSTEMS +0080B5 UNITED NETWORKS INC. +0080B6 THEMIS COMPUTER +0080B7 STELLAR COMPUTER +0080B8 BUG, INCORPORATED +0080B9 ARCHE TECHNOLIGIES INC. +0080BA SPECIALIX (ASIA) PTE, LTD +0080BB HUGHES LAN SYSTEMS +0080BC HITACHI ENGINEERING CO., LTD +0080BD THE FURUKAWA ELECTRIC CO., LTD +0080BE ARIES RESEARCH +0080BF TAKAOKA ELECTRIC MFG. CO. LTD. +0080C0 PENRIL DATACOMM +0080C1 LANEX CORPORATION +0080C2 IEEE 802 COMMITTEE +0080C3 BICC INFORMATION SYSTEMS & SVC +0080C4 DOCUMENT TECHNOLOGIES, INC. +0080C5 NOVELLCO DE MEXICO +0080C6 NATIONAL DATACOMM CORPORATION +0080C7 XIRCOM +0080C8 D-LINK SYSTEMS, INC. +0080C9 ALBERTA MICROELECTRONIC CENTRE +0080CA NETCOM RESEARCH INCORPORATED +0080CB FALCO DATA PRODUCTS +0080CC MICROWAVE BYPASS SYSTEMS +0080CD MICRONICS COMPUTER, INC. +0080CE BROADCAST TELEVISION SYSTEMS +0080CF EMBEDDED PERFORMANCE INC. +0080D0 COMPUTER PERIPHERALS, INC. +0080D1 KIMTRON CORPORATION +0080D2 SHINNIHONDENKO CO., LTD. +0080D3 SHIVA CORP. +0080D4 CHASE RESEARCH LTD. +0080D5 CADRE TECHNOLOGIES +0080D6 NUVOTECH, INC. +0080D7 FANTUM ENGINEERING, INC. +0080D8 NETWORK PERIPHERALS INC. +0080D9 EMK ELEKTRONIK +0080DA BRUEL & KJAER +0080DB GRAPHON CORPORATION +0080DC PICKER INTERNATIONAL +0080DD GMX INC/GIMIX +0080DE GIPSI S.A. +0080DF ADC CODENOLL TECHNOLOGY CORP. +0080E0 XTP SYSTEMS, INC. +0080E1 STMICROELECTRONICS +0080E2 T.D.I. CO., LTD. +0080E3 CORAL NETWORK CORPORATION +0080E4 NORTHWEST DIGITAL SYSTEMS, INC +0080E5 MYLEX CORPORATION +0080E6 PEER NETWORKS, INC. +0080E7 LYNWOOD SCIENTIFIC DEV. LTD. +0080E8 CUMULUS CORPORATIION +0080E9 MADGE NETWORKS +0080EA ADVA Optical Networking Ltd. +0080EB COMPCONTROL B.V. +0080EC SUPERCOMPUTING SOLUTIONS, INC. +0080ED IQ TECHNOLOGIES, INC. +0080EE THOMSON CSF +0080EF RATIONAL +0080F0 KYUSHU MATSUSHITA ELECTRIC CO. +0080F1 OPUS SYSTEMS +0080F2 RAYCOM SYSTEMS INC +0080F3 SUN ELECTRONICS CORP. +0080F4 TELEMECANIQUE ELECTRIQUE +0080F5 QUANTEL LTD +0080F6 SYNERGY MICROSYSTEMS +0080F7 ZENITH ELECTRONICS +0080F8 MIZAR, INC. +0080F9 HEURIKON CORPORATION +0080FA RWT GMBH +0080FB BVM LIMITED +0080FC AVATAR CORPORATION +0080FD EXSCEED CORPRATION +0080FE AZURE TECHNOLOGIES, INC. +0080FF SOC. DE TELEINFORMATIQUE RTC +009000 DIAMOND MULTIMEDIA +009001 NISHIMU ELCTRONICS INDUSTRIES +009002 ALLGON AB +009003 APLIO +009004 3COM EUROPE LTD. +009005 PROTECH SYSTEMS CO., LTD. +009006 HAMAMATSU PHOTONICS K.K. +009007 DOMEX TECHNOLOGY CORP. +009008 HAN A SYSTEMS, INC. +009009 i Controls, Inc. +00900A PROTON ELECTRONIC INDUSTRIAL +00900B LANNER ELECTRONICS, INC. +00900C CISCO SYSTEMS, INC. +00900D OVERLAND DATA INC. +00900E HANDLINK TECHNOLOGIES, INC. +00900F KAWASAKI HEAVY INDUSTRIES, LTD +009010 SIMULATION LABORATORIES, INC. +009011 WAVTRACE, INC. +009012 GLOBESPAN SEMICONDUCTOR, INC. +009013 SAMSAN CORP. +009014 ROTORK INSTRUMENTS, LTD. +009015 CENTIGRAM COMMUNICATIONS CORP. +009016 ZAC +009017 ZYPCOM, INC. +009018 ITO ELECTRIC INDUSTRY CO, LTD. +009019 HERMES ELECTRONICS CO., LTD. +00901A UNISPHERE SOLUTIONS +00901B DIGITAL CONTROLS +00901C MPS SOFTWARE GMBH +00901D PEC (NZ) LTD. +00901E SELESTA INGEGNE RIA S.P.A. +00901F ADTEC PRODUCTIONS, INC. +009020 PHILIPS ANALYTICAL X-RAY B.V. +009021 CISCO SYSTEMS, INC. +009022 IVEX +009023 ZILOG INC. +009024 PIPELINKS, INC. +009025 VISION SYSTEMS LTD. PTY +009026 ADVANCED SWITCHING +009027 INTEL CORPORATION +009028 NIPPON SIGNAL CO., LTD. +009029 CRYPTO AG +00902A COMMUNICATION DEVICES, INC. +00902B CISCO SYSTEMS, INC. +00902C DATA & CONTROL EQUIPMENT LTD. +00902D DATA ELECTRONICS +00902E NAMCO LIMITED +00902F NETCORE SYSTEMS, INC. +009030 HONEYWELL-DATING +009031 MYSTICOM, LTD. +009032 PELCOMBE GROUP LTD. +009033 INNOVAPHONE GMBH +009034 IMAGIC, INC. +009035 ALPHA TELECOM, INC. +009036 ENS, INC. +009037 ACUCOMM, INC. +009038 FOUNTAIN TECHNOLOGIES, INC. +009039 SHASTA NETWORKS +00903A NIHON MEDIA TOOL INC. +00903B TRIEMS RESEARCH LAB, INC. +00903C ATLANTIC NETWORK SYSTEMS +00903D BIOPAC SYSTEMS, INC. +00903E N.V. PHILIPS INDUSTRIAL +00903F AZTEC RADIOMEDIA +009040 CASTLE NETWORKS, INC. +009041 APPLIED DIGITAL ACCESS +009042 ECCS +009043 NICHIBEI DENSHI CO., LTD. +009044 ASSURED DIGITAL, INC. +009045 MARIPOSA TECHNOLOGY +009046 DEXDYNE, LTD. +009047 GIGA FAST E. LTD. +009048 ZEAL CORPORATION +009049 ENTRIDIA CORPORATION +00904A CONCUR SYSTEM TECHNOLOGIES +00904B GEMTEK TECHNOLOGY CO., LTD. +00904C EPIGRAM, INC. +00904D SPEC S.A. +00904E DELEM BV +00904F ABB POWER T&D COMPANY, INC. +009050 TELESTE OY +009051 ULTIMATE TECHNOLOGY CORP. +009052 SELCOM ELETTRONICA S.R.L. +009053 DAEWOO ELECTRONICS CO., LTD. +009054 INNOVATIVE SEMICONDUCTORS, INC +009055 PARKER HANNIFIN CORPORATION +009056 TELESTREAM, INC. +009057 AANETCOM, INC. +009058 ULTRA ELECTRONICS LTD. +009059 TELECOM DEVICE K.K. +00905A DEARBORN GROUP, INC. +00905B RAYMOND AND LAE ENGINEERING +00905C EDMI +00905D NETCOM SICHERHEITSTECHNIK GMBH +00905E RAULAND-BORG CORPORATION +00905F CISCO SYSTEMS, INC. +009060 SYSTEM CREATE CORP. +009061 PACIFIC RESEARCH & ENGINEERING +009062 ICP VORTEX COMPUTERSYSTEME +009063 COHERENT COMMUNICATIONS +009064 THOMSON BROADCAST SYSTEMS +009065 FINISAR CORPORATION +009066 Troika Networks, Inc. +009067 WALKABOUT COMPUTERS, INC. +009068 DVT CORP. +009069 JUNIPER NETWORKS, INC. +00906A TURNSTONE SYSTEMS, INC. +00906B APPLIED RESOURCES, INC. +00906C GWT GLOBAL WEIGHING +00906D CISCO SYSTEMS, INC. +00906E PRAXON, INC. +00906F CISCO SYSTEMS, INC. +009070 NEO NETWORKS, INC. +009071 BADGER TECHNOLOGY, INC. +009072 SIMRAD AS +009073 GAIO TECHNOLOGY +009074 ARGON NETWORKS, INC. +009075 NEC DO BRASIL S.A. +009076 FMT AIRCRAFT GATE SUPPORT +009077 ADVANCED FIBRE COMMUNICATIONS +009078 MER TELEMANAGEMENT +009079 CLEARONE INC. +00907A SPECTRALINK CORP. +00907B E-TECH, INC. +00907C DIGITALCAST, INC. +00907D HOME WIRELESS NETWORKS +00907E VETRONIX CORP. +00907F WATCHGUARD TECHNOLOGIES, INC. +009080 NOT LIMITED, INC. +009081 ALOHA NETWORKS, INC. +009082 FORCE INSTITUTE +009083 TURBO COMMUNICATION, INC. +009084 ATECH SYSTEM +009085 GOLDEN ENTERPRISES, INC. +009086 CISCO SYSTEMS, INC. +009087 ITIS +009088 BAXALL SECURITY LTD. +009089 SOFTCOM MICROSYSTEMS, INC. +00908A BAYLY COMMUNICATIONS, INC. +00908B CELL COMPUTING, INC. +00908C ETREND ELECTRONICS, INC. +00908D VICKERS ELECTRONICS SYSTEMS +00908E Nortel Networks Broadband Access +00908F AUDIOCODES LTD. +009090 I-BUS +009091 DIGITALSCAPE, INC. +009092 CISCO SYSTEMS, INC. +009093 NANAO CORPORATION +009094 OSPREY TECHNOLOGIES, INC. +009095 UNIVERSAL AVIONICS +009096 ASKEY COMPUTER CORP. +009097 SYCAMORE NETWORKS +009098 SBC DESIGNS, INC. +009099 ALLIED TELESIS,K.K. +00909A ONE WORLD SYSTEMS, INC. +00909B MARKPOINT AB +00909C COMBOX, LTD. +00909D GSE SYSTEMS, INC. +00909E DELPHI ENGINEERING GROUP +00909F DIGI-DATA CORPORATION +0090A0 8X8 INC. +0090A1 FLYING PIG SYSTEMS, LTD. +0090A2 CYBERTAN TECHNOLOGY, INC. +0090A3 MEDIALINCS CO., LTD. +0090A4 ALTIGA NETWORKS +0090A5 SPECTRA LOGIC +0090A6 CISCO SYSTEMS, INC. +0090A7 CLIENTEC CORPORATION +0090A8 NINETILES NETWORKS LTD. +0090A9 WESTERN DIGITAL +0090AA INDIGO ACTIVE VISION +0090AB CISCO SYSTEMS, INC. +0090AC OPTIVISION, INC. +0090AD ASPECT ELECTRONICS, INC. +0090AE ITALTEL SPA +0090AF J. MORITA MFG. CORP. +0090B0 VADEM +0090B1 CISCO SYSTEMS, INC. +0090B2 AVICI SYSTEMS INC. +0090B3 AGRANAT SYSTEMS +0090B4 WILLOWBROOK TECHNOLOGIES +0090B5 NIKON CORPORATION +0090B6 FIBEX SYSTEMS +0090B7 DIGITAL LIGHTWAVE, INC. +0090B8 ROHDE & SCHWARZ GMBH & CO. KG +0090B9 BERAN INSTRUMENTS LTD. +0090BA VALID NETWORKS, INC. +0090BB TAINET COMMUNICATION SYSTEM +0090BC TELEMANN CO., LTD. +0090BD OMNIA COMMUNICATIONS, INC. +0090BE IBC/INTEGRATED BUSINESS +0090BF CISCO SYSTEMS, INC. +0090C0 K.J. LAW ENGINEERS, INC. +0090C1 EDA INDUSTRIES +0090C2 JK MICROSYSTEMS, INC. +0090C3 TOPIC SEMICONDUCTOR CORP. +0090C4 JAVELIN SYSTEMS, INC. +0090C5 INTERNET MAGIC, INC. +0090C6 OPTIM SYSTEMS, INC. +0090C7 ICOM INC. +0090C8 WAVERIDER COMMUNICATIONS +0090C9 PRODUCTIVITY ENHANCEMENT +0090CA ACCORD VIDEO +0090CB WIRELESS ONLINE, INC. +0090CC PLANEX COMMUNICATIONS, INC. +0090CD ENT-EMPRESA NACIONAL +0090CE TETRA GMBH +0090CF NORTEL +0090D0 ALCATEL BELL +0090D1 LEICHU ENTERPRISE CO., LTD. +0090D2 ARTEL VIDEO SYSTEMS +0090D3 GIESECKE & DEVRIENT GMBH +0090D4 BINDVIEW DEVELOPMENT CORP. +0090D5 EUPHONIX, INC. +0090D6 CRYSTAL GROUP +0090D7 NETBOOST CORP. +0090D8 WHITECROSS SYSTEMS +0090D9 CISCO SYSTEMS, INC. +0090DA DYNARC, INC. +0090DB NEXT LEVEL COMMUNICATIONS +0090DC TECO INFORMATION SYSTEMS +0090DD THE MIHARU COMMUNICATIONS +0090DE CARDKEY SYSTEMS, INC. +0090DF MITSUBISHI CHEMICAL +0090E0 SYSTRAN CORP. +0090E1 TELENA S.P.A. +0090E2 DISTRIBUTED PROCESSING +0090E3 AVEX ELECTRONICS INC. +0090E4 NEC AMERICA, INC. +0090E5 TEKNEMA, INC. +0090E6 ACER LABORATORIES, INC. +0090E7 HORSCH ELEKTRONIK AG +0090E8 MOXA TECHNOLOGIES CORP., LTD. +0090E9 JANZ COMPUTER AG +0090EA ALPHA TECHNOLOGIES, INC. +0090EB SENTRY TELECOM SYSTEMS +0090EC PYRESCOM +0090ED CENTRAL SYSTEM RESEARCH +0090EE PERSONAL COMMUNICATIONS +0090EF INTEGRIX, INC. +0090F0 HARMONIC LIGHTWAVES, LTD. +0090F1 DOT HILL SYSTEMS CORPORATION +0090F2 CISCO SYSTEMS, INC. +0090F3 ASPECT COMMUNICATIONS +0090F4 LIGHTNING INSTRUMENTATION +0090F5 CLEVO CO. +0090F6 ESCALATE NETWORKS, INC. +0090F7 NBASE COMMUNICATIONS LTD. +0090F8 MEDIATRIX TELECOM +0090F9 LEITCH +0090FA GIGANET, INC. +0090FB PORTWELL, INC. +0090FC NETWORK COMPUTING DEVICES +0090FD COPPERCOM, INC. +0090FE ELECOM CO., LTD. (LANEED DIV. +0090FF TELLUS TECHNOLOGY INC. +009D8E CARDIAC RECORDERS, INC. +00A000 CENTILLION NETWORKS, INC. +00A001 WATKINS-JOHNSON COMPANY +00A002 LEEDS & NORTHRUP AUSTRALIA +00A003 STAEFA CONTROL SYSTEM +00A004 NETPOWER, INC. +00A005 DANIEL INSTRUMENTS, LTD. +00A006 IMAGE DATA PROCESSING +00A007 APEXX TECHNOLOGY, INC. +00A008 NETCORP +00A009 WHITETREE NETWORK +00A00A R.D.C. COMMUNICATION +00A00B COMPUTEX CO., LTD. +00A00C KINGMAX TECHNOLOGY, INC. +00A00D THE PANDA PROJECT +00A00E VISUAL NETWORKS, INC. +00A00F Broadband Technologies +00A010 SYSLOGIC DATENTECHNIK AG +00A011 MUTOH INDUSTRIES LTD. +00A012 B.A.T.M. ADVANCED TECHNOLOGIES +00A013 TELTREND LTD. +00A014 CSIR +00A015 WYLE +00A016 MICROPOLIS CORP. +00A017 J B M CORPORATION +00A018 CREATIVE CONTROLLERS, INC. +00A019 NEBULA CONSULTANTS, INC. +00A01A BINAR ELEKTRONIK AB +00A01B PREMISYS COMMUNICATIONS, INC. +00A01C NASCENT NETWORKS CORPORATION +00A01D SIXNET +00A01E EST CORPORATION +00A01F TRICORD SYSTEMS, INC. +00A020 CITICORP/TTI +00A021 GENERAL DYNAMICS- +00A022 CENTRE FOR DEVELOPMENT OF +00A023 APPLIED CREATIVE TECHNOLOGY, +00A024 3COM CORPORATION +00A025 REDCOM LABS INC. +00A026 TELDAT, S.A. +00A027 FIREPOWER SYSTEMS, INC. +00A028 CONNER PERIPHERALS +00A029 COULTER CORPORATION +00A02A TRANCELL SYSTEMS +00A02B TRANSITIONS RESEARCH CORP. +00A02C INTERWAVE COMMUNICATIONS +00A02D 1394 Trade Association +00A02E BRAND COMMUNICATIONS, LTD. +00A02F PIRELLI CAVI +00A030 CAPTOR NV/SA +00A031 HAZELTINE CORPORATION, MS 1-17 +00A032 GES SINGAPORE PTE. LTD. +00A033 IMC MESS-SYSTEME GMBH +00A034 AXEL +00A035 CYLINK CORPORATION +00A036 APPLIED NETWORK TECHNOLOGY +00A037 DATASCOPE CORPORATION +00A038 EMAIL ELECTRONICS +00A039 ROSS TECHNOLOGY, INC. +00A03A KUBOTEK CORPORATION +00A03B TOSHIN ELECTRIC CO., LTD. +00A03C EG&G NUCLEAR INSTRUMENTS +00A03D OPTO - 22 +00A03E ATM FORUM +00A03F COMPUTER SOCIETY MICROPROCES'R +00A040 APPLE COMPUTER +00A041 LEYBOLD-INFICON +00A042 SPUR PRODUCTS CORP. +00A043 AMERICAN TECHNOLOGY LABS, INC. +00A044 NTT INTELLIGENT TECHNOLOGY +00A045 PHOENIX CONTACT GMBH & CO. +00A046 SCITEX CORP. LTD. +00A047 INTEGRATED FITNESS CORP. +00A048 QUESTECH, LTD. +00A049 DIGITECH INDUSTRIES, INC. +00A04A NISSHIN ELECTRIC CO., LTD. +00A04B TFL LAN INC. +00A04C INNOVATIVE SYSTEMS & TECH. INC +00A04D EDA INSTRUMENTS, INC. +00A04E VOELKER TECHNOLOGIES, INC. +00A04F AMERITEC CORP. +00A050 CYPRESS SEMICONDUCTOR +00A051 ANGIA COMMUNICATIONS. INC. +00A052 STANILITE ELECTRONICS PTY. LTD +00A053 COMPACT DEVICES, INC. +00A055 LINKTECH, INC. +00A056 MICROPROSS +00A057 ELSA AG +00A058 GLORY, LTD. +00A059 HAMILTON HALLMARK +00A05A KOFAX IMAGE PRODUCTS +00A05B MARQUIP, INC. +00A05C INVENTORY CONVERSION, INC./ +00A05D CS COMPUTER SYSTEME GMBH +00A05E MYRIAD LOGIC INC. +00A05F BTG ENGINEERING BV +00A060 ACER PERIPHERALS, INC. +00A061 PURITAN BENNETT +00A062 AES PRODATA +00A063 JRL SYSTEMS, INC. +00A064 KVB/ANALECT +00A065 NEXLAND, INC. +00A066 ISA CO., LTD. +00A067 NETWORK SERVICES GROUP +00A068 BHP LIMITED +00A069 TrueTime +00A06A VERILINK CORP. +00A06B DMS DORSCH MIKROSYSTEM GMBH +00A06C SHINDENGEN ELECTRIC MFG. +00A06D MANNESMANN TALLY CORPORATION +00A06E AUSTRON, INC. +00A06F THE APPCON GROUP, INC. +00A070 COASTCOM +00A071 VIDEO LOTTERY TECHNOLOGIES,INC +00A072 OVATION SYSTEMS LTD. +00A073 COM21, INC. +00A074 PERCEPTION TECHNOLOGY +00A075 MICRON TECHNOLOGY, INC. +00A076 CARDWARE LAB, INC. +00A077 FUJITSU NEXION, INC. +00A078 Marconi Communications +00A079 ALPS ELECTRIC (USA), INC. +00A07A ADVANCED PERIPHERALS +00A07B DAWN COMPUTER INCORPORATION +00A07C TONYANG NYLON CO., LTD. +00A07D SEEQ TECHNOLOGY, INC. +00A07E AVID TECHNOLOGY, INC. +00A07F GSM-SYNTEL, LTD. +00A080 ANTARES MICROSYSTEMS +00A081 ALCATEL DATA NETWORKS +00A082 NKT ELEKTRONIK A/S +00A083 ASIMMPHONY TURKEY +00A084 DATAPLEX PTY. LTD. +00A086 AMBER WAVE SYSTEMS, INC. +00A087 MITEL SEMICONDUCTOR, LTD. +00A088 ESSENTIAL COMMUNICATIONS +00A089 XPOINT TECHNOLOGIES, INC. +00A08A BROOKTROUT TECHNOLOGY, INC. +00A08B ASTON ELECTRONIC DESIGNS LTD. +00A08C MULTIMEDIA LANS, INC. +00A08D JACOMO CORPORATION +00A08E Nokia Internet Communications +00A08F DESKNET SYSTEMS, INC. +00A090 TIMESTEP CORPORATION +00A091 APPLICOM INTERNATIONAL +00A092 H. BOLLMANN MANUFACTURERS, LTD +00A093 B/E AEROSPACE +00A094 COMSAT CORPORATION +00A095 ACACIA NETWORKS, INC. +00A096 MITSUMI ELECTRIC CO., LTD. +00A097 JC INFORMATION SYSTEMS +00A098 NETWORK APPLIANCE CORP. +00A099 K-NET LTD. +00A09A NIHON KOHDEN AMERICA +00A09B QPSX COMMUNICATIONS, LTD. +00A09C XYPLEX, INC. +00A09D JOHNATHON FREEMAN TECHNOLOGIES +00A09E ICTV +00A09F COMMVISION CORP. +00A0A0 COMPACT DATA, LTD. +00A0A1 EPIC DATA INC. +00A0A2 DIGICOM S.P.A. +00A0A3 RELIABLE POWER METERS +00A0A4 MICROS SYSTEMS, INC. +00A0A5 TEKNOR MICROSYSTEME, INC. +00A0A6 M.I. SYSTEMS, K.K. +00A0A7 VORAX CORPORATION +00A0A8 RENEX CORPORATION +00A0A9 GN NETTEST (CANADA) INC. +00A0AA SPACELABS MEDICAL +00A0AB NETCS INFORMATIONSTECHNIK GMBH +00A0AC GILAT SATELLITE NETWORKS, LTD. +00A0AD MARCONI SPA +00A0AE NUCOM SYSTEMS, INC. +00A0AF WMS INDUSTRIES +00A0B0 I-O DATA DEVICE, INC. +00A0B1 FIRST VIRTUAL CORPORATION +00A0B2 SHIMA SEIKI +00A0B3 ZYKRONIX +00A0B4 TEXAS MICROSYSTEMS, INC. +00A0B5 3H TECHNOLOGY +00A0B6 SANRITZ AUTOMATION CO., LTD. +00A0B7 CORDANT, INC. +00A0B8 SYMBIOS LOGIC INC. +00A0B9 EAGLE TECHNOLOGY, INC. +00A0BA PATTON ELECTRONICS CO. +00A0BB HILAN GMBH +00A0BC VIASAT, INCORPORATED +00A0BD I-TECH CORP. +00A0BE INTEGRATED CIRCUIT SYSTEMS,INC +00A0BF WIRELESS DATA GROUP MOTOROLA +00A0C0 DIGITAL LINK CORP. +00A0C1 ORTIVUS MEDICAL AB +00A0C2 R.A. SYSTEMS CO., LTD. +00A0C3 UNICOMPUTER GMBH +00A0C4 CRISTIE ELECTRONICS LTD. +00A0C5 ZYXEL COMMUNICATION +00A0C6 QUALCOMM INCORPORATED +00A0C7 TADIRAN TELECOMMUNICATIONS +00A0C8 ADTRAN INC. +00A0C9 INTEL CORPORATION - HF1-06 +00A0CA FUJITSU DENSO LTD. +00A0CB ARK TELECOMMUNICATIONS, INC. +00A0CC LITE-ON COMMUNICATIONS, INC. +00A0CD DR. JOHANNES HEIDENHAIN GMBH +00A0CE ASTROCOM CORPORATION +00A0CF SOTAS, INC. +00A0D0 TEN X TECHNOLOGY, INC. +00A0D1 INVENTEC CORPORATION +00A0D2 ALLIED TELESIS INTERNATIONAL +00A0D3 INSTEM COMPUTER SYSTEMS, LTD. +00A0D4 RADIOLAN, INC. +00A0D5 SIERRA WIRELESS INC. +00A0D6 SBE, INC. +00A0D7 KASTEN CHASE APPLIED RESEARCH +00A0D8 SPECTRA - TEK +00A0D9 CONVEX COMPUTER CORPORATION +00A0DA INTEGRATED SYSTEMS +00A0DB FISHER & PAYKEL PRODUCTION +00A0DC O.N. ELECTRONIC CO., LTD. +00A0DD AZONIX CORPORATION +00A0DE YAMAHA CORPORATION +00A0DF STS TECHNOLOGIES, INC. +00A0E0 TENNYSON TECHNOLOGIES PTY LTD +00A0E1 WESTPORT RESEARCH +00A0E2 KEISOKU GIKEN CORP. +00A0E3 XKL SYSTEMS CORP. +00A0E4 OPTIQUEST +00A0E5 NHC COMMUNICATIONS +00A0E6 DIALOGIC CORPORATION +00A0E7 CENTRAL DATA CORPORATION +00A0E8 REUTERS HOLDINGS PLC +00A0E9 ELECTRONIC RETAILING SYSTEMS +00A0EA ETHERCOM CORP. +00A0EB FASTCOMM COMMUNICATIONS CORP. +00A0EC TRANSMITTON LTD. +00A0ED PRI AUTOMATION +00A0EE NASHOBA NETWORKS +00A0EF LUCIDATA LTD. +00A0F0 TORONTO MICROELECTRONICS INC. +00A0F1 MTI +00A0F2 INFOTEK COMMUNICATIONS, INC. +00A0F3 STAUBLI +00A0F4 GE +00A0F5 RADGUARD LTD. +00A0F6 AUTOGAS SYSTEMS, INC. +00A0F7 V.I COMPUTER CORP. +00A0F8 SYMBOL TECHNOLOGIES, INC. +00A0F9 BINTEC COMMUNICATIONS GMBH +00A0FA Marconi Communication GmbH +00A0FB TORAY ENGINEERING CO., LTD. +00A0FC IMAGE SCIENCES, INC. +00A0FD SCITEX DIGITAL PRINTING, INC. +00A0FE BOSTON TECHNOLOGY, INC. +00A0FF TELLABS OPERATIONS, INC. +00AA00 INTEL CORPORATION +00AA01 INTEL CORPORATION +00AA02 INTEL CORPORATION +00AA3C OLIVETTI TELECOM SPA (OLTECO) +00B009 Grass Valley Group +00B017 InfoGear Technology Corp. +00B019 Casi-Rusco +00B01C Westport Technologies +00B01E Rantic Labs, Inc. +00B02A ORSYS GmbH +00B02D ViaGate Technologies, Inc. +00B03B HiQ Networks +00B048 Marconi Communications Inc. +00B04A Cisco Systems, Inc. +00B052 Intellon Corporation +00B064 Cisco Systems, Inc. +00B069 Honewell Oy +00B06D Jones Futurex Inc. +00B080 Mannesmann Ipulsys B.V. +00B086 LocSoft Limited +00B08E Cisco Systems, Inc. +00B091 Transmeta Corp. +00B094 Alaris, Inc. +00B09A Morrow Technologies Corp. +00B09D Point Grey Research Inc. +00B0AC SIAE-Microelettronica S.p.A. +00B0AE Symmetricom +00B0B3 Xstreamis PLC +00B0C2 Cisco Systems, Inc. +00B0C7 Tellabs Operations, Inc. +00B0CE TECHNOLOGY RESCUE +00B0D0 Dell Computer Corp. +00B0DB Nextcell, Inc. +00B0DF Reliable Data Technology, Inc. +00B0E7 British Federal Ltd. +00B0EC EACEM +00B0EE Ajile Systems, Inc. +00B0F0 CALY NETWORKS +00B0F5 NetWorth Technologies, Inc. +00BB01 OCTOTHORPE CORP. +00BBF0 UNGERMANN-BASS INC. +00C000 LANOPTICS, LTD. +00C001 DIATEK PATIENT MANAGMENT +00C002 SERCOMM CORPORATION +00C003 GLOBALNET COMMUNICATIONS +00C004 JAPAN BUSINESS COMPUTER CO.LTD +00C005 LIVINGSTON ENTERPRISES, INC. +00C006 NIPPON AVIONICS CO., LTD. +00C007 PINNACLE DATA SYSTEMS, INC. +00C008 SECO SRL +00C009 KT TECHNOLOGY (S) PTE LTD +00C00A MICRO CRAFT +00C00B NORCONTROL A.S. +00C00C RELIA TECHNOLGIES +00C00D ADVANCED LOGIC RESEARCH, INC. +00C00E PSITECH, INC. +00C00F QUANTUM SOFTWARE SYSTEMS LTD. +00C010 HIRAKAWA HEWTECH CORP. +00C011 INTERACTIVE COMPUTING DEVICES +00C012 NETSPAN CORPORATION +00C013 NETRIX +00C014 TELEMATICS CALABASAS INT'L,INC +00C015 NEW MEDIA CORPORATION +00C016 ELECTRONIC THEATRE CONTROLS +00C017 FORTE NETWORKS +00C018 LANART CORPORATION +00C019 LEAP TECHNOLOGY, INC. +00C01A COROMETRICS MEDICAL SYSTEMS +00C01B SOCKET COMMUNICATIONS, INC. +00C01C INTERLINK COMMUNICATIONS LTD. +00C01D GRAND JUNCTION NETWORKS, INC. +00C01E LA FRANCAISE DES JEUX +00C01F S.E.R.C.E.L. +00C020 ARCO ELECTRONIC, CONTROL LTD. +00C021 NETEXPRESS +00C022 LASERMASTER TECHNOLOGIES, INC. +00C023 TUTANKHAMON ELECTRONICS +00C024 EDEN SISTEMAS DE COMPUTACAO SA +00C025 DATAPRODUCTS CORPORATION +00C026 LANS TECHNOLOGY CO., LTD. +00C027 CIPHER SYSTEMS, INC. +00C028 JASCO CORPORATION +00C029 KABEL RHEYDT AG +00C02A OHKURA ELECTRIC CO., LTD. +00C02B GERLOFF GESELLSCHAFT FUR +00C02C CENTRUM COMMUNICATIONS, INC. +00C02D FUJI PHOTO FILM CO., LTD. +00C02E NETWIZ +00C02F OKUMA CORPORATION +00C030 INTEGRATED ENGINEERING B. V. +00C031 DESIGN RESEARCH SYSTEMS, INC. +00C032 I-CUBED LIMITED +00C033 TELEBIT COMMUNICATIONS APS +00C034 TRANSACTION NETWORK +00C035 QUINTAR COMPANY +00C036 RAYTECH ELECTRONIC CORP. +00C037 DYNATEM +00C038 RASTER IMAGE PROCESSING SYSTEM +00C039 TDK SEMICONDUCTOR CORPORATION +00C03A MEN-MIKRO ELEKTRONIK GMBH +00C03B MULTIACCESS COMPUTING CORP. +00C03C TOWER TECH S.R.L. +00C03D WIESEMANN & THEIS GMBH +00C03E FA. GEBR. HELLER GMBH +00C03F STORES AUTOMATED SYSTEMS, INC. +00C040 ECCI +00C041 DIGITAL TRANSMISSION SYSTEMS +00C042 DATALUX CORP. +00C043 STRATACOM +00C044 EMCOM CORPORATION +00C045 ISOLATION SYSTEMS, LTD. +00C046 KEMITRON LTD. +00C047 UNIMICRO SYSTEMS, INC. +00C048 BAY TECHNICAL ASSOCIATES +00C049 U.S. ROBOTICS, INC. +00C04A GROUP 2000 AG +00C04B CREATIVE MICROSYSTEMS +00C04C DEPARTMENT OF FOREIGN AFFAIRS +00C04D MITEC, INC. +00C04E COMTROL CORPORATION +00C04F DELL COMPUTER CORPORATION +00C050 TOYO DENKI SEIZO K.K. +00C051 ADVANCED INTEGRATION RESEARCH +00C052 BURR-BROWN +00C053 DAVOX CORPORATION +00C054 NETWORK PERIPHERALS, LTD. +00C055 MODULAR COMPUTING TECHNOLOGIES +00C056 SOMELEC +00C057 MYCO ELECTRONICS +00C058 DATAEXPERT CORP. +00C059 NIPPON DENSO CO., LTD. +00C05A SEMAPHORE COMMUNICATIONS CORP. +00C05B NETWORKS NORTHWEST, INC. +00C05C ELONEX PLC +00C05D L&N TECHNOLOGIES +00C05E VARI-LITE, INC. +00C05F FINE-PAL COMPANY LIMITED +00C060 ID SCANDINAVIA AS +00C061 SOLECTEK CORPORATION +00C062 IMPULSE TECHNOLOGY +00C063 MORNING STAR TECHNOLOGIES, INC +00C064 GENERAL DATACOMM IND. INC. +00C065 SCOPE COMMUNICATIONS, INC. +00C066 DOCUPOINT, INC. +00C067 UNITED BARCODE INDUSTRIES +00C068 PHILIP DRAKE ELECTRONICS LTD. +00C069 ADAPTIVE BROADBAND CORPORATION +00C06A ZAHNER-ELEKTRIK GMBH & CO. KG +00C06B OSI PLUS CORPORATION +00C06C SVEC COMPUTER CORP. +00C06D BOCA RESEARCH, INC. +00C06E HAFT TECHNOLOGY, INC. +00C06F KOMATSU LTD. +00C070 SECTRA SECURE-TRANSMISSION AB +00C071 AREANEX COMMUNICATIONS, INC. +00C072 KNX LTD. +00C073 XEDIA CORPORATION +00C074 TOYODA AUTOMATIC LOOM +00C075 XANTE CORPORATION +00C076 I-DATA INTERNATIONAL A-S +00C077 DAEWOO TELECOM LTD. +00C078 COMPUTER SYSTEMS ENGINEERING +00C079 FONSYS CO.,LTD. +00C07A PRIVA B.V. +00C07B ASCEND COMMUNICATIONS, INC. +00C07C HIGHTECH INFORMATION +00C07D RISC DEVELOPMENTS LTD. +00C07E KUBOTA CORPORATION ELECTRONIC +00C07F NUPON COMPUTING CORP. +00C080 NETSTAR, INC. +00C081 METRODATA LTD. +00C082 MOORE PRODUCTS CO. +00C083 TRACE MOUNTAIN PRODUCTS, INC. +00C084 DATA LINK CORP. LTD. +00C085 ELECTRONICS FOR IMAGING, INC. +00C086 THE LYNK CORPORATION +00C087 UUNET TECHNOLOGIES, INC. +00C088 EKF ELEKTRONIK GMBH +00C089 TELINDUS DISTRIBUTION +00C08A LAUTERBACH DATENTECHNIK GMBH +00C08B RISQ MODULAR SYSTEMS, INC. +00C08C PERFORMANCE TECHNOLOGIES, INC. +00C08D TRONIX PRODUCT DEVELOPMENT +00C08E NETWORK INFORMATION TECHNOLOGY +00C08F MATSUSHITA ELECTRIC WORKS, LTD +00C090 PRAIM S.R.L. +00C091 JABIL CIRCUIT, INC. +00C092 MENNEN MEDICAL INC. +00C093 ALTA RESEARCH CORP. +00C094 VMX INC. +00C095 ZNYX +00C096 TAMURA CORPORATION +00C097 ARCHIPEL SA +00C098 CHUNTEX ELECTRONIC CO., LTD. +00C099 YOSHIKI INDUSTRIAL CO.,LTD. +00C09A PHOTONICS CORPORATION +00C09B RELIANCE COMM/TEC, R-TEC +00C09C TOA ELECTRONIC LTD. +00C09D DISTRIBUTED SYSTEMS INT'L, INC +00C09E CACHE COMPUTERS, INC. +00C09F QUANTA COMPUTER, INC. +00C0A0 ADVANCE MICRO RESEARCH, INC. +00C0A1 TOKYO DENSHI SEKEI CO. +00C0A2 INTERMEDIUM A/S +00C0A3 DUAL ENTERPRISES CORPORATION +00C0A4 UNIGRAF OY +00C0A5 DICKENS DATA SYSTEMS +00C0A6 EXICOM AUSTRALIA PTY. LTD +00C0A7 SEEL LTD. +00C0A8 GVC CORPORATION +00C0A9 BARRON MCCANN LTD. +00C0AA SILICON VALLEY COMPUTER +00C0AB Telco Systems, Inc. +00C0AC GAMBIT COMPUTER COMMUNICATIONS +00C0AD MARBEN COMMUNICATION SYSTEMS +00C0AE TOWERCOM CO. INC. DBA PC HOUSE +00C0AF TEKLOGIX INC. +00C0B0 GCC TECHNOLOGIES,INC. +00C0B1 GENIUS NET CO. +00C0B2 NORAND CORPORATION +00C0B3 COMSTAT DATACOMM CORPORATION +00C0B4 MYSON TECHNOLOGY, INC. +00C0B5 CORPORATE NETWORK SYSTEMS,INC. +00C0B6 MERIDIAN DATA, INC. +00C0B7 AMERICAN POWER CONVERSION CORP +00C0B8 FRASER'S HILL LTD. +00C0B9 FUNK SOFTWARE, INC. +00C0BA NETVANTAGE +00C0BB FORVAL CREATIVE, INC. +00C0BC TELECOM AUSTRALIA/CSSC +00C0BD INEX TECHNOLOGIES, INC. +00C0BE ALCATEL - SEL +00C0BF TECHNOLOGY CONCEPTS, LTD. +00C0C0 SHORE MICROSYSTEMS, INC. +00C0C1 QUAD/GRAPHICS, INC. +00C0C2 INFINITE NETWORKS LTD. +00C0C3 ACUSON COMPUTED SONOGRAPHY +00C0C4 COMPUTER OPERATIONAL +00C0C5 SID INFORMATICA +00C0C6 PERSONAL MEDIA CORP. +00C0C7 SPARKTRUM MICROSYSTEMS, INC. +00C0C8 MICRO BYTE PTY. LTD. +00C0C9 ELSAG BAILEY PROCESS +00C0CA ALFA, INC. +00C0CB CONTROL TECHNOLOGY CORPORATION +00C0CC TELESCIENCES CO SYSTEMS, INC. +00C0CD COMELTA, S.A. +00C0CE CEI SYSTEMS & ENGINEERING PTE +00C0CF IMATRAN VOIMA OY +00C0D0 RATOC SYSTEM INC. +00C0D1 COMTREE TECHNOLOGY CORPORATION +00C0D2 SYNTELLECT, INC. +00C0D3 OLYMPUS IMAGE SYSTEMS, INC. +00C0D4 AXON NETWORKS, INC. +00C0D5 QUANCOM ELECTRONIC GMBH +00C0D6 J1 SYSTEMS, INC. +00C0D7 TAIWAN TRADING CENTER DBA +00C0D8 UNIVERSAL DATA SYSTEMS +00C0D9 QUINTE NETWORK CONFIDENTIALITY +00C0DA NICE SYSTEMS LTD. +00C0DB IPC CORPORATION (PTE) LTD. +00C0DC EOS TECHNOLOGIES, INC. +00C0DD QLogic Corporation +00C0DE ZCOMM, INC. +00C0DF KYE SYSTEMS CORP. +00C0E0 DSC COMMUNICATION CORP. +00C0E1 SONIC SOLUTIONS +00C0E2 CALCOMP, INC. +00C0E3 OSITECH COMMUNICATIONS, INC. +00C0E4 SIEMENS BUILDING +00C0E5 GESPAC, S.A. +00C0E6 Verilink Corporation +00C0E7 FIBERDATA AB +00C0E8 PLEXCOM, INC. +00C0E9 OAK SOLUTIONS, LTD. +00C0EA ARRAY TECHNOLOGY LTD. +00C0EB SEH COMPUTERTECHNIK GMBH +00C0EC DAUPHIN TECHNOLOGY +00C0ED US ARMY ELECTRONIC +00C0EE KYOCERA CORPORATION +00C0EF ABIT CORPORATION +00C0F0 KINGSTON TECHNOLOGY CORP. +00C0F1 SHINKO ELECTRIC CO., LTD. +00C0F2 TRANSITION NETWORKS +00C0F3 NETWORK COMMUNICATIONS CORP. +00C0F4 INTERLINK SYSTEM CO., LTD. +00C0F5 METACOMP, INC. +00C0F6 CELAN TECHNOLOGY INC. +00C0F7 ENGAGE COMMUNICATION, INC. +00C0F8 ABOUT COMPUTING INC. +00C0F9 HARRIS AND JEFFRIES, INC. +00C0FA CANARY COMMUNICATIONS, INC. +00C0FB ADVANCED TECHNOLOGY LABS +00C0FC ELASTIC REALITY, INC. +00C0FD PROSUM +00C0FE APTEC COMPUTER SYSTEMS, INC. +00C0FF DOT HILL SYSTEMS CORPORATION +00CBBD Cambridge Broadband Ltd. +00CF1C COMMUNICATION MACHINERY CORP. +00D000 FERRAN SCIENTIFIC, INC. +00D001 VST TECHNOLOGIES, INC. +00D002 DITECH CORPORATION +00D003 COMDA ENTERPRISES CORP. +00D004 PENTACOM LTD. +00D005 ZHS ZEITMANAGEMENTSYSTEME +00D006 CISCO SYSTEMS, INC. +00D007 MIC ASSOCIATES, INC. +00D008 MACTELL CORPORATION +00D009 HSING TECH. ENTERPRISE CO. LTD +00D00A LANACCESS TELECOM S.A. +00D00B RHK TECHNOLOGY, INC. +00D00C SNIJDER MICRO SYSTEMS +00D00D MICROMERITICS INSTRUMENT +00D00E PLURIS, INC. +00D00F SPEECH DESIGN GMBH +00D010 CONVERGENT NETWORKS, INC. +00D011 PRISM VIDEO, INC. +00D012 GATEWORKS CORP. +00D013 PRIMEX AEROSPACE COMPANY +00D014 ROOT, INC. +00D015 UNIVEX MICROTECHNOLOGY CORP. +00D016 SCM MICROSYSTEMS, INC. +00D017 SYNTECH INFORMATION CO., LTD. +00D018 QWES. COM, INC. +00D019 DAINIPPON SCREEN CORPORATE +00D01A URMET SUD S.P.A. +00D01B MIMAKI ENGINEERING CO., LTD. +00D01C SBS TECHNOLOGIES, +00D01D FURUNO ELECTRIC CO., LTD. +00D01E PINGTEL CORP. +00D01F CTAM PTY. LTD. +00D020 AIM SYSTEM, INC. +00D021 REGENT ELECTRONICS CORP. +00D022 INCREDIBLE TECHNOLOGIES, INC. +00D023 INFORTREND TECHNOLOGY, INC. +00D024 Cognex Corporation +00D025 XROSSTECH, INC. +00D026 HIRSCHMANN AUSTRIA GMBH +00D027 APPLIED AUTOMATION, INC. +00D028 OMNEON VIDEO NETWORKS +00D029 WAKEFERN FOOD CORPORATION +00D02A FLEXION SYSTEMS +00D02B JETCELL, INC. +00D02C CAMPBELL SCIENTIFIC, INC. +00D02D ADEMCO +00D02E COMMUNICATION AUTOMATION CORP. +00D02F VLSI TECHNOLOGY INC. +00D030 SAFETRAN SYSTEMS CORP. +00D031 INDUSTRIAL LOGIC CORPORATION +00D032 YANO ELECTRIC CO., LTD. +00D033 DALIAN DAXIAN NETWORK +00D034 ORMEC SYSTEMS CORP. +00D035 BEHAVIOR TECH. COMPUTER CORP. +00D036 TECHNOLOGY ATLANTA CORP. +00D037 PHILIPS-DVS-LO BDR +00D038 FIVEMERE, LTD. +00D039 UTILICOM, INC. +00D03A ZONEWORX, INC. +00D03B VISION PRODUCTS PTY. LTD. +00D03C Vieo, Inc. +00D03E ROCKETCHIPS, INC. +00D03F AMERICAN COMMUNICATION +00D040 SYSMATE CO., LTD. +00D041 AMIGO TECHNOLOGY CO., LTD. +00D042 MAHLO GMBH & CO. UG +00D043 ZONAL RETAIL DATA SYSTEMS +00D044 ALIDIAN NETWORKS, INC. +00D045 KVASER AB +00D046 DOLBY LABORATORIES, INC. +00D047 XN TECHNOLOGIES +00D048 ECTON, INC. +00D049 IMPRESSTEK CO., LTD. +00D04A PRESENCE TECHNOLOGY GMBH +00D04B LA CIE GROUP S.A. +00D04C EUROTEL TELECOM LTD. +00D04D DIV OF RESEARCH & STATISTICS +00D04E LOGIBAG +00D04F BITRONICS, INC. +00D050 ISKRATEL +00D051 O2 MICRO, INC. +00D052 ASCEND COMMUNICATIONS, INC. +00D053 CONNECTED SYSTEMS +00D054 SAS INSTITUTE INC. +00D055 KATHREIN-WERKE KG +00D056 SOMAT CORPORATION +00D057 ULTRAK, INC. +00D058 CISCO SYSTEMS, INC. +00D059 AMBIT MICROSYSTEMS CORP. +00D05A SYMBIONICS, LTD. +00D05B ACROLOOP MOTION CONTROL +00D05C TECHNOTREND SYSTEMTECHNIK GMBH +00D05D INTELLIWORXX, INC. +00D05E STRATABEAM TECHNOLOGY, INC. +00D05F VALCOM, INC. +00D060 PANASONIC EUROPEAN +00D061 TREMON ENTERPRISES CO., LTD. +00D062 DIGIGRAM +00D063 CISCO SYSTEMS, INC. +00D064 MULTITEL +00D065 TOKO ELECTRIC +00D066 WINTRISS ENGINEERING CORP. +00D067 CAMPIO COMMUNICATIONS +00D068 IWILL CORPORATION +00D069 TECHNOLOGIC SYSTEMS +00D06A LINKUP SYSTEMS CORPORATION +00D06B SR TELECOM INC. +00D06C SHAREWAVE, INC. +00D06D ACRISON, INC. +00D06E TRENDVIEW RECORDERS LTD. +00D06F KMC CONTROLS +00D070 LONG WELL ELECTRONICS CORP. +00D071 ECHELON CORP. +00D072 BROADLOGIC +00D073 ACN ADVANCED COMMUNICATIONS +00D074 TAQUA SYSTEMS, INC. +00D075 ALARIS MEDICAL SYSTEMS, INC. +00D076 MERRILL LYNCH & CO., INC. +00D077 LUCENT TECHNOLOGIES +00D078 ELTEX OF SWEDEN AB +00D079 CISCO SYSTEMS, INC. +00D07A AMAQUEST COMPUTER CORP. +00D07B COMCAM INTERNATIONAL LTD. +00D07C KOYO ELECTRONICS INC. CO.,LTD. +00D07D COSINE COMMUNICATIONS +00D07E KEYCORP LTD. +00D07F STRATEGY & TECHNOLOGY, LIMITED +00D080 EXABYTE CORPORATION +00D081 REAL TIME DEVICES USA, INC. +00D082 IOWAVE INC. +00D083 INVERTEX, INC. +00D084 NEXCOMM SYSTEMS, INC. +00D085 OTIS ELEVATOR COMPANY +00D086 FOVEON, INC. +00D087 MICROFIRST INC. +00D088 MAINSAIL NETWORKS, INC. +00D089 DYNACOLOR, INC. +00D08A PHOTRON USA +00D08B ADVA Limited +00D08C GENOA TECHNOLOGY, INC. +00D08D PHOENIX GROUP, INC. +00D08E NVISION INC. +00D08F ARDENT TECHNOLOGIES, INC. +00D090 CISCO SYSTEMS, INC. +00D091 SMARTSAN SYSTEMS, INC. +00D092 GLENAYRE WESTERN MULTIPLEX +00D093 TQ - COMPONENTS GMBH +00D094 TIMELINE VISTA, INC. +00D095 XYLAN CORPORATION +00D096 3COM EUROPE LTD. +00D097 CISCO SYSTEMS, INC. +00D098 IPS AUTOMATION +00D099 ELCARD OY +00D09A FILANET CORPORATION +00D09B SPECTEL LTD. +00D09C KAPADIA COMMUNICATIONS +00D09D VERIS INDUSTRIES +00D09E 2WIRE, INC. +00D09F NOVTEK TEST SYSTEMS +00D0A0 MIPS DENMARK +00D0A1 OSKAR VIERLING GMBH + CO. KG +00D0A2 INTEGRATED DEVICE +00D0A3 VOCAL DATA, INC. +00D0A4 ALANTRO COMMUNICATIONS +00D0A5 AMERICAN ARIUM +00D0A6 LANBIRD TECHNOLOGY CO., LTD. +00D0A7 TOKYO SOKKI KENKYUJO CO., LTD. +00D0A8 NETWORK ENGINES, INC. +00D0A9 SHINANO KENSHI CO., LTD. +00D0AA CHASE COMMUNICATIONS +00D0AB DELTAKABEL TELECOM CV +00D0AC GRAYSON WIRELESS +00D0AD TL INDUSTRIES +00D0AE ORESIS COMMUNICATIONS, INC. +00D0AF CUTLER-HAMMER, INC. +00D0B0 BITSWITCH LTD. +00D0B1 OMEGA ELECTRONICS SA +00D0B2 XIOTECH CORPORATION +00D0B3 DRS FLIGHT SAFETY AND +00D0B4 KATSUJIMA CO., LTD. +00D0B5 DOTCOM +00D0B6 CRESCENT NETWORKS, INC. +00D0B7 INTEL CORPOTATION +00D0B8 IOMEGA CORP. +00D0B9 MICROTEK INTERNATIONAL, INC. +00D0BA CISCO SYSTEMS, INC. +00D0BB CISCO SYSTEMS, INC. +00D0BC CISCO SYSTEMS, INC. +00D0BD SICAN GMBH +00D0BE EMUTEC INC. +00D0BF PIVOTAL TECHNOLOGIES +00D0C0 CISCO SYSTEMS, INC. +00D0C1 HARMONIC DATA SYSTEMS, LTD. +00D0C2 BALTHAZAR TECHNOLOGY AB +00D0C3 VIVID TECHNOLOGY PTE, LTD. +00D0C4 TERATECH CORPORATION +00D0C5 COMPUTATIONAL SYSTEMS, INC. +00D0C6 THOMAS & BETTS CORP. +00D0C7 PATHWAY, INC. +00D0C8 I/O CONSULTING A/S +00D0C9 ADVANTECH CO., LTD. +00D0CA INTRINSYC SOFTWARE INC. +00D0CB DASAN CO., LTD. +00D0CC TECHNOLOGIES LYRE INC. +00D0CD ATAN TECHNOLOGY INC. +00D0CE ASYST ELECTRONIC +00D0CF MORETON BAY +00D0D0 ZHONGXING TELECOM LTD. +00D0D1 SIROCCO SYSTEMS, INC. +00D0D2 EPILOG CORPORATION +00D0D3 CISCO SYSTEMS, INC. +00D0D4 V-BITS, INC. +00D0D5 GRUNDIG AG +00D0D6 AETHRA TELECOMUNICAZIONI +00D0D7 B2C2, INC. +00D0D8 3Com Corporation +00D0D9 DEDICATED MICROCOMPUTERS +00D0DA TAICOM DATA SYSTEMS CO., LTD. +00D0DB MCQUAY INTERNATIONAL +00D0DC MODULAR MINING SYSTEMS, INC. +00D0DD SUNRISE TELECOM, INC. +00D0DE PHILIPS MULTIMEDIA NETWORK +00D0DF KUZUMI ELECTRONICS, INC. +00D0E0 DOOIN ELECTRONICS CO. +00D0E1 AVIONITEK ISRAEL INC. +00D0E2 MRT MICRO, INC. +00D0E3 ELE-CHEM ENGINEERING CO., LTD. +00D0E4 CISCO SYSTEMS, INC. +00D0E5 SOLIDUM SYSTEMS CORP. +00D0E6 IBOND INC. +00D0E7 VCON TELECOMMUNICATION LTD. +00D0E8 MAC SYSTEM CO., LTD. +00D0E9 ADVANTAGE CENTURY +00D0EA NEXTONE COMMUNICATIONS, INC. +00D0EB LIGHTERA NETWORKS, INC. +00D0EC NAKAYO TELECOMMUNICATIONS, INC +00D0ED XIOX +00D0EE DICTAPHONE CORPORATION +00D0EF IGT +00D0F0 CONVISION TECHNOLOGY GMBH +00D0F1 SEGA ENTERPRISES, LTD. +00D0F2 MONTEREY NETWORKS +00D0F3 SOLARI DI UDINE SPA +00D0F4 CARINTHIAN TECH INSTITUTE +00D0F5 ORANGE MICRO, INC. +00D0F6 NORTHCHURCH COMMUNICATIONS INC +00D0F7 NEXT NETS CORPORATION +00D0F8 FUJIAN STAR TERMINAL +00D0F9 ACUTE COMMUNICATIONS CORP. +00D0FA RACAL GUARDATA +00D0FB TEK MICROSYSTEMS, INCORPORATED +00D0FC GRANITE MICROSYSTEMS +00D0FD OPTIMA TELE.COM, INC. +00D0FE ASTRAL POINT +00D0FF CISCO SYSTEMS, INC. +00DD00 UNGERMANN-BASS INC. +00DD01 UNGERMANN-BASS INC. +00DD02 UNGERMANN-BASS INC. +00DD03 UNGERMANN-BASS INC. +00DD04 UNGERMANN-BASS INC. +00DD05 UNGERMANN-BASS INC. +00DD06 UNGERMANN-BASS INC. +00DD07 UNGERMANN-BASS INC. +00DD08 UNGERMANN-BASS INC. +00DD09 UNGERMANN-BASS INC. +00DD0A UNGERMANN-BASS INC. +00DD0B UNGERMANN-BASS INC. +00DD0C UNGERMANN-BASS INC. +00DD0D UNGERMANN-BASS INC. +00DD0E UNGERMANN-BASS INC. +00DD0F UNGERMANN-BASS INC. +00E000 FUJITSU, LTD +00E001 STRAND LIGHTING LIMITED +00E002 CROSSROADS SYSTEMS, INC. +00E003 NOKIA WIRELESS BUSINESS COMMUN +00E004 PMC-SIERRA, INC. +00E005 TECHNICAL CORP. +00E006 SILICON INTEGRATED SYS. CORP. +00E007 NETWORK ALCHEMY LTD. +00E008 AMAZING CONTROLS! INC. +00E009 MARATHON TECHNOLOGIES CORP. +00E00A DIBA, INC. +00E00B ROOFTOP COMMUNICATIONS CORP. +00E00C MOTOROLA +00E00D RADIANT SYSTEMS +00E00E AVALON IMAGING SYSTEMS, INC. +00E00F SHANGHAI BAUD DATA +00E010 HESS SB-AUTOMATENBAU GMBH +00E011 UNIDEN SAN DIEGO +00E012 PLUTO TECHNOLOGIES +00E013 EASTERN ELECTRONIC CO., LTD. +00E014 CISCO SYSTEMS, INC. +00E015 HEIWA CORPORATION +00E016 RAPID CITY COMMUNICATIONS +00E017 EXXACT GMBH +00E018 ASUSTEK COMPUTER INC. +00E019 ING. GIORDANO ELETTRONICA +00E01A COMTEC SYSTEMS. CO., LTD. +00E01B SPHERE COMMUNICATIONS, INC. +00E01C MOBILITY ELECTRONICSY +00E01D WEBTV NETWORKS, INC. +00E01E CISCO SYSTEMS, INC. +00E01F AVIDIA SYSTEMS, INC. +00E020 TECNOMEN OY +00E021 FREEGATE CORP. +00E022 MEDIALIGHT INC. +00E023 TELRAD +00E024 GADZOOX NETWORKS +00E025 DIT CO., LTD. +00E026 EASTMAN KODAK CO. +00E027 DUX, INC. +00E028 APTIX CORPORATION +00E029 STANDARD MICROSYSTEMS CORP. +00E02A TANDBERG TELEVISION AS +00E02B EXTREME NETWORKS +00E02C AST COMPUTER +00E02D INNOMEDIALOGIC, INC. +00E02E SPC ELECTRONICS CORPORATION +00E02F MCNS HOLDINGS, L.P. +00E030 MELITA INTERNATIONAL CORP. +00E031 HAGIWARA ELECTRIC CO., LTD. +00E032 MISYS FINANCIAL SYSTEMS, LTD. +00E033 E.E.P.D. GMBH +00E034 CISCO SYSTEMS, INC. +00E035 LOUGHBOROUGH SOUND IMAGES, PLC +00E036 PIONEER CORPORATION +00E037 CENTURY CORPORATION +00E038 PROXIMA CORPORATION +00E039 PARADYNE CORP. +00E03A CABLETRON SYSTEMS, INC. +00E03B PROMINET CORPORATION +00E03C ADVANSYS +00E03D FOCON ELECTRONIC SYSTEMS A/S +00E03E ALFATECH, INC. +00E03F JATON CORPORATION +00E040 DESKSTATION TECHNOLOGY, INC. +00E041 CSPI +00E042 PACOM DATA LTD. +00E043 VITALCOM +00E044 LSICS CORPORATION +00E045 TOUCHWAVE, INC. +00E046 BENTLY NEVADA CORP. +00E047 INFOCUS SYSTEMS +00E048 SDL COMMUNICATIONS, INC. +00E049 MICROWI ELECTRONIC GMBH +00E04A ENHANCED MESSAGING SYSTEMS,INC +00E04B JUMP INDUSTRIELLE +00E04C REALTEK SEMICONDUCTOR CORP. +00E04D INTERNET INITIATIVE JAPAN, INC +00E04E SANYO DENKI CO., LTD. +00E04F CISCO SYSTEMS, INC. +00E050 EXECUTONE INFORMATION +00E051 TALX CORPORATION +00E052 FOUNDRY NETWORKS, INC. +00E053 CELLPORT LABS, INC. +00E054 KODAI HITEC CO., LTD. +00E055 INGENIERIA ELECTRONICA +00E056 HOLONTECH CORPORATION +00E057 HAN MICROTELECOM. CO., LTD. +00E058 PHASE ONE DENMARK A/S +00E059 CONTROLLED ENVIRONMENTS, LTD. +00E05A GALEA NETWORK SECURITY +00E05B WEST END SYSTEMS CORP. +00E05C MATSUSHITA KOTOBUKI +00E05D UNITEC CO., LTD. +00E05E JAPAN AVIATION ELECTRONICS +00E05F E-NET, INC. +00E060 SHERWOOD +00E061 EDGEPOINT NETWORKS, INC. +00E062 HOST ENGINEERING +00E063 CABLETRON - YAGO SYSTEMS, INC. +00E064 SAMSUNG ELECTRONICS +00E065 OPTICAL ACCESS INTERNATIONAL +00E066 PROMAX SYSTEMS, INC. +00E067 EAC AUTOMATION-CONSULTING GMBH +00E068 MERRIMAC SYSTEMS INC. +00E069 JAYCOR NETWORKS, INC. +00E06A KAPSCH AG +00E06B W&G SPECIAL PRODUCTS +00E06C BALTIMORE TECHNOLOGIES, LTD. +00E06D COMPUWARE CORPORATION +00E06E FAR SYSTEMS SPA +00E06F TERAYON CORP. +00E070 DH TECHNOLOGY +00E071 EPIS MICROCOMPUTER +00E072 LYNK +00E073 NATIONAL AMUSEMENT +00E074 TIERNAN COMMUNICATIONS, INC. +00E075 ATLAS COMPUTER EQUIPMENT, INC. +00E076 DEVELOPMENT CONCEPTS, INC. +00E077 WEBGEAR, INC. +00E078 BERKELEY NETWORKS +00E079 A.T.N.R. +00E07A MIKRODIDAKT AB +00E07B BAY NETWORKS +00E07C METTLER-TOLEDO, INC. +00E07D NETRONIX, INC. +00E07E WALT DISNEY IMAGINEERING +00E07F LOGISTISTEM SRL +00E080 CONTROL RESOURCES CORPORATION +00E081 TYAN COMPUTER CORP. +00E082 ANERMA +00E083 JATO TECHNOLOGIES, INC. +00E084 COMPULITE R&D +00E085 GLOBAL MAINTECH, INC. +00E086 CYBEX COMPUTER PRODUCTS +00E087 LECROY +00E088 LTX CORPORATION +00E089 ION Networks, Inc. +00E08A GEC AVERY, LTD. +00E08B QLOGIC CORP. +00E08C NEOPARADIGM LABS, INC. +00E08D PRESSURE SYSTEMS, INC. +00E08E UTSTARCOM +00E08F CISCO SYSTEMS, INC. +00E090 BECKMAN LAB. AUTOMATION DIV. +00E091 LG ELECTRONICS, INC. +00E092 ADMTEK INCORPORATED +00E093 ACKFIN NETWORKS +00E094 OSAI SRL +00E095 ADVANCED-VISION TECHNOLGIES +00E096 SHIMADZU CORPORATION +00E097 CARRIER ACCESS CORPORATION +00E098 ABOCOM SYSTEMS, INC. +00E099 SAMSON AG +00E09A POSITRON INDUSTRIES, INC. +00E09B ENGAGE NETWORKS, INC. +00E09C MII +00E09D SARNOFF CORPORATION +00E09E QUANTUM CORPORATION +00E09F PIXEL VISION +00E0A0 WILTRON CO. +00E0A1 HIMA PAUL HILDEBRANDT +00E0A2 MICROSLATE INC. +00E0A3 CISCO SYSTEMS, INC. +00E0A4 ESAOTE S.P.A. +00E0A5 COMCORE SEMICONDUCTOR, INC. +00E0A6 TELOGY NETWORKS, INC. +00E0A7 IPC INFORMATION SYSTEMS, INC. +00E0A8 SAT GMBH&CO +00E0A9 FUNAI ELECTRIC CO., LTD. +00E0AA ELECTROSONIC LTD. +00E0AB DIMAT S.A. +00E0AC MIDSCO, INC. +00E0AD EES TECHNOLOGY, LTD. +00E0AE XAQTI CORPORATION +00E0AF GENERAL DYNAMICS INFORMATION +00E0B0 CISCO SYSTEMS, INC. +00E0B1 PACKET ENGINES, INC. +00E0B2 TELMAX COMMUNICATIONS CORP. +00E0B3 ETHERWAN SYSTEMS, INC. +00E0B4 TECHNO SCOPE CO., LTD. +00E0B5 ARDENT COMMUNICATIONS CORP. +00E0B6 Entrada Networks +00E0B7 PI GROUP, LTD. +00E0B8 GATEWAY 2000 +00E0B9 BYAS SYSTEMS +00E0BA BERGHOF AUTOMATIONSTECHNIK +00E0BB NBX CORPORATION +00E0BC SYMON COMMUNICATIONS, INC. +00E0BD INTERFACE SYSTEMS, INC. +00E0BE GENROCO INTERNATIONAL, INC. +00E0BF TORRENT NETWORKING +00E0C0 SEIWA ERECTRIC MFG. CO., LTD. +00E0C1 MEMOREX TELEX JAPAN, LTD. +00E0C2 NECSY SPA +00E0C3 SAKAI SYSTEM DEVELOPMENT CORP. +00E0C4 HORNER ELECTRIC, INC. +00E0C5 BCOM ELECTRONICS INC. +00E0C6 LINK2IT, L.L.C. +00E0C7 EUROTECH SRL +00E0C8 VIRTUAL ACCESS, LTD. +00E0C9 AUTOMATEDLOGIC CORPORATION +00E0CA BEST DATA PRODUCTS +00E0CB RESON, INC. +00E0CC HERO SYSTEMS, LTD. +00E0CD SENSIS CORPORATION +00E0CE ARN +00E0CF INTEGRATED DEVICE +00E0D0 NETSPEED, INC. +00E0D1 TELSIS LIMITED +00E0D2 VERSANET COMMUNICATIONS, INC. +00E0D3 DATENTECHNIK GMBH +00E0D4 EXCELLENT COMPUTER +00E0D5 ARCXEL TECHNOLOGIES, INC. +00E0D6 COMPUTER & COMMUNICATION +00E0D7 SUNSHINE ELECTRONICS, INC. +00E0D8 LANBIT COMPUTER, INC. +00E0D9 TAZMO CO., LTD. +00E0DA ASSURED ACCESS +00E0DB VIAVIDEO COMMUNICATIONS +00E0DC NEXWARE CORP. +00E0DD ZENITH ELECTRONICS CORPORATION +00E0DE DATAX NV +00E0DF KE KOMMUNIKATIONS-ELECTRONIK +00E0E0 SI ELECTRONICS, LTD. +00E0E1 G2 NETWORKS, ILNC. +00E0E2 INNOVA CORP. +00E0E3 SK-ELEKTRONIK GMBH +00E0E4 FANUC ROBOTICS NORTH AMERICA, +00E0E5 CINCO NETWORKS, INC. +00E0E6 INCAA DATACOM B.V. +00E0E7 RAYTHEON E-SYSTEMS, INC. +00E0E8 GRETACODER DATA SYSTEMS AG +00E0E9 DATA LABS, INC. +00E0EA INNOVAT COMMUNICATIONS, INC. +00E0EB DIGICOM SYSTEMS, INCORPORATED +00E0EC CELESTICA INC. +00E0ED SILICOM, LTD. +00E0EE MAREL HF +00E0EF DIONEX +00E0F0 ABLER TECHNOLOGY, INC. +00E0F1 THAT CORPORATION +00E0F2 ARLOTTO COMNET, INC. +00E0F3 WEBSPRINT COMMUNICATIONS, INC. +00E0F4 INSIDE TECHNOLOGY A/S +00E0F5 TELES AG +00E0F6 DECISION EUROPE +00E0F7 CISCO SYSTEMS, INC. +00E0F8 DIANA CONTROL AB +00E0F9 CISCO SYSTEMS, INC. +00E0FA TRL TECHNOLOGY, LTD. +00E0FB LEIGHTRONIX, INC. +00E0FC HUAWEI TECHNOLOGIES CO., LTD. +00E0FD A-TREND TECHNOLOGY CO., LTD. +00E0FE CISCO SYSTEMS, INC. +00E0FF SECURITY DYNAMICS TECHNOLOGIES +00E6D3 NIXDORF COMPUTER CORP. +020701 RACAL-DATACOM +021C7C PERQ SYSTEMS CORPORATION +026086 LOGIC REPLACEMENT TECH. LTD. +02608C 3COM CORPORATION +027001 RACAL-DATACOM +0270B0 M/A-COM INC. COMPANIES +0270B3 DATA RECALL LTD +029D8E CARDIAC RECORDERS INC. +02AA3C OLIVETTI TELECOMM SPA (OLTECO) +02BB01 OCTOTHORPE CORP. +02C08C 3COM CORPORATION +02CF1C COMMUNICATION MACHINERY CORP. +02E6D3 NIXDORF COMPUTER CORPORATION +040AE0 XMIT AG COMPUTER NETWORKS +04E0C4 TRIUMPH-ADLER AG +080001 COMPUTERVISION CORPORATION +080002 BRIDGE COMMUNICATIONS INC. +080003 ADVANCED COMPUTER COMM. +080004 CROMEMCO INCORPORATED +080005 SYMBOLICS INC. +080006 SIEMENS AG +080007 APPLE COMPUTER INC. +080008 BOLT BERANEK AND NEWMAN INC. +080009 HEWLETT PACKARD +08000A NESTAR SYSTEMS INCORPORATED +08000B UNISYS CORPORATION +08000C MIKLYN DEVELOPMENT CO. +08000D INTERNATIONAL COMPUTERS LTD. +08000E NCR CORPORATION +08000F MITEL CORPORATION +080011 TEKTRONIX INC. +080012 BELL ATLANTIC INTEGRATED SYST. +080013 EXXON +080014 EXCELAN +080015 STC BUSINESS SYSTEMS +080016 BARRISTER INFO SYS CORP +080017 NATIONAL SEMICONDUCTOR +080018 PIRELLI FOCOM NETWORKS +080019 GENERAL ELECTRIC CORPORATION +08001A TIARA/ 10NET +08001B DATA GENERAL +08001C KDD-KOKUSAI DEBNSIN DENWA CO. +08001D ABLE COMMUNICATIONS INC. +08001E APOLLO COMPUTER INC. +08001F SHARP CORPORATION +080020 SUN MICROSYSTEMS INC. +080021 3M COMPANY +080022 NBI INC. +080023 MATSUHITA GRAPHIC COMM SYS INC +080024 10NET COMMUNICATIONS/DCA +080025 CONTROL DATA +080026 NORSK DATA A.S. +080027 CADMUS COMPUTER SYSTEMS +080028 TEXAS INSTRUMENTS +080029 MEGATEK CORPORATION +08002A MOSAIC TECHNOLOGIES INC. +08002B DIGITAL EQUIPMENT CORPORATION +08002C BRITTON LEE INC. +08002D LAN-TEC INC. +08002E METAPHOR COMPUTER SYSTEMS +08002F PRIME COMPUTER INC. +080030 NETWORK RESEARCH CORPORATION +080030 CERN +080030 ROYAL MELBOURNE INST OF TECH +080031 LITTLE MACHINES INC. +080032 TIGAN INCORPORATED +080033 BAUSCH & LOMB +080034 FILENET CORPORATION +080035 MICROFIVE CORPORATION +080036 INTERGRAPH CORPORATION +080037 FUJI-XEROX CO. LTD. +080038 CII HONEYWELL BULL +080039 SPIDER SYSTEMS LIMITED +08003A ORCATECH INC. +08003B TORUS SYSTEMS LIMITED +08003C SCHLUMBERGER WELL SERVICES +08003D CADNETIX CORPORATIONS +08003E CODEX CORPORATION +08003F FRED KOSCHARA ENTERPRISES +080040 FERRANTI COMPUTER SYS. LIMITED +080041 RACAL-MILGO INFORMATION SYS.. +080042 JAPAN MACNICS CORP. +080043 PIXEL COMPUTER INC. +080044 DAVID SYSTEMS INC. +080045 CONCURRENT COMPUTER CORP. +080046 SONY CORPORATION LTD. +080047 SEQUENT COMPUTER SYSTEMS INC. +080048 EUROTHERM GAUGING SYSTEMS +080049 UNIVATION +08004A BANYAN SYSTEMS INC. +08004B PLANNING RESEARCH CORP. +08004C HYDRA COMPUTER SYSTEMS INC. +08004D CORVUS SYSTEMS INC. +08004E 3COM EUROPE LTD. +08004F CYGNET SYSTEMS +080050 DAISY SYSTEMS CORP. +080051 EXPERDATA +080052 INSYSTEC +080053 MIDDLE EAST TECH. UNIVERSITY +080055 STANFORD TELECOMM. INC. +080056 STANFORD LINEAR ACCEL. CENTER +080057 EVANS & SUTHERLAND +080058 SYSTEMS CONCEPTS +080059 A/S MYCRON +08005A IBM CORPORATION +08005B VTA TECHNOLOGIES INC. +08005C FOUR PHASE SYSTEMS +08005D GOULD INC. +08005E COUNTERPOINT COMPUTER INC. +08005F SABER TECHNOLOGY CORP. +080060 INDUSTRIAL NETWORKING INC. +080061 JAROGATE LTD. +080062 GENERAL DYNAMICS +080063 PLESSEY +080064 AUTOPHON AG +080065 GENRAD INC. +080066 AGFA CORPORATION +080067 COMDESIGN +080068 RIDGE COMPUTERS +080069 SILICON GRAPHICS INC. +08006A ATT BELL LABORATORIES +08006B ACCEL TECHNOLOGIES INC. +08006C SUNTEK TECHNOLOGY INT'L +08006D WHITECHAPEL COMPUTER WORKS +08006E MASSCOMP +08006F PHILIPS APELDOORN B.V. +080070 MITSUBISHI ELECTRIC CORP. +080071 MATRA (DSIE) +080072 XEROX CORP UNIV GRANT PROGRAM +080073 TECMAR INC. +080074 CASIO COMPUTER CO. LTD. +080075 DANSK DATA ELECTRONIK +080076 PC LAN TECHNOLOGIES +080077 TSL COMMUNICATIONS LTD. +080078 ACCELL CORPORATION +080079 THE DROID WORKS +08007A INDATA +08007B SANYO ELECTRIC CO. LTD. +08007C VITALINK COMMUNICATIONS CORP. +08007E AMALGAMATED WIRELESS(AUS) LTD +08007F CARNEGIE-MELLON UNIVERSITY +080080 AES DATA INC. +080081 ,ASTECH INC. +080082 VERITAS SOFTWARE +080083 SEIKO INSTRUM. AND ELECTRONICS +080084 TOMEN ELECTRONICS CORP. +080085 ELXSI +080086 IMAGEN CORPORATION +080087 XYPLEX +080088 MCDATA CORPORATION +080089 KINETICS +08008A PERFORMANCE TECHNOLOGY +08008B PYRAMID TECHNOLOGY CORP. +08008C NETWORK RESEARCH CORPORATION +08008D XYVISION INC. +08008E TANDEM COMPUTERS +08008F CHIPCOM CORPORATION +080090 SONOMA SYSTEMS +08BBCC AK-NORD EDV VERTRIEBSGES. MBH +10005A IBM CORPORATION +1000E8 NATIONAL SEMICONDUCTOR +800010 ATT BELL LABORATORIES +A06A00 Verilink Corporation +AA0000 DIGITAL EQUIPMENT CORPORATION +AA0001 DIGITAL EQUIPMENT CORPORATION +AA0002 DIGITAL EQUIPMENT CORPORATION +AA0003 DIGITAL EQUIPMENT CORPORATION +AA0004 DIGITAL EQUIPMENT CORPORATION diff -uNr linux-2.4.21/drivers/ieee1394/oui2c.sh linux-2.4.21-ben2/drivers/ieee1394/oui2c.sh --- linux-2.4.21/drivers/ieee1394/oui2c.sh 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/drivers/ieee1394/oui2c.sh 2003-06-27 15:41:08.000000000 +0200 @@ -0,0 +1,23 @@ +#!/bin/sh + +cat < + +#ifdef CONFIG_IEEE1394_OUI_DB +struct oui_list_struct { + int oui; + char *name; +} oui_list[] = { +EOF + +while read oui name; do + echo " { 0x$oui, \"$name\" }," +done + +cat < + * * 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 @@ -27,283 +29,17 @@ * driver. It also registers as a SCSI lower-level driver in order to accept * SCSI commands for transport using SBP-2. * - * - * Driver Loading: - * - * Currently, the SBP-2 driver is supported only as a module. Because the - * Linux SCSI stack is not Plug-N-Play aware, module load order is - * important. Assuming the SCSI core drivers are either built into the - * kernel or already loaded as modules, you should load the IEEE-1394 modules - * in the following order: - * - * ieee1394 (e.g. insmod ieee1394) - * ohci1394 (e.g. insmod ohci1394) - * sbp2 (e.g. insmod sbp2) - * - * The SBP-2 driver will attempt to discover any attached SBP-2 devices when first - * loaded, or after any IEEE-1394 bus reset (e.g. a hot-plug). It will then print - * out a debug message indicating if it was able to discover a SBP-2 device. - * - * Currently, the SBP-2 driver will catch any attached SBP-2 devices during the - * initial scsi bus scan (when the driver is first loaded). To add or remove - * SBP-2 devices "after" this initial scan (i.e. if you plug-in or un-plug a - * device after the SBP-2 driver is loaded), you must either use the scsi procfs - * add-single-device, remove-single-device, or a shell script such as - * rescan-scsi-bus.sh. - * * The easiest way to add/detect new SBP-2 devices is to run the shell script - * rescan-scsi-bus.sh (or re-load the SBP-2 driver). This script may be - * found at: + * rescan-scsi-bus.sh. This script may be found at: * http://www.garloff.de/kurt/linux/rescan-scsi-bus.sh * - * As an alternative, you may manually add/remove SBP-2 devices via the procfs with - * add-single-device or remove-single-device , where: - * = host (starting at zero for first SCSI adapter) - * = bus (normally zero) - * = target (starting at zero for first SBP-2 device) - * = lun (normally zero) - * - * e.g. To manually add/detect a new SBP-2 device - * echo "scsi add-single-device 0 0 0 0" > /proc/scsi/scsi - * - * e.g. To manually remove a SBP-2 device after it's been unplugged - * echo "scsi remove-single-device 0 0 0 0" > /proc/scsi/scsi - * - * e.g. To check to see which SBP-2/SCSI devices are currently registered - * cat /proc/scsi/scsi - * - * After scanning for new SCSI devices (above), you may access any attached - * SBP-2 storage devices as if they were SCSI devices (e.g. mount /dev/sda1, - * fdisk, mkfs, etc.). - * - * - * Module Load Options: - * - * sbp2_max_speed - Force max speed allowed - * (2 = 400mb, 1 = 200mb, 0 = 100mb. default = 2) - * sbp2_serialize_io - Serialize all I/O coming down from the scsi drivers - * (0 = deserialized, 1 = serialized, default = 0) - * sbp2_max_sectors, - Change max sectors per I/O supported (default = 255) - * sbp2_exclusive_login - Set to zero if you'd like to allow multiple hosts the ability - * to log in at the same time. Sbp2 device must support this, - * and you must know what you're doing (default = 1) - * - * (e.g. insmod sbp2 sbp2_serialize_io = 1) - * - * - * Current Support: - * - * The SBP-2 driver is still in an early state, but supports a variety of devices. - * I have read/written many gigabytes of data from/to SBP-2 drives, and have seen - * performance of more than 25 MBytes/s on individual drives (limit of the media - * transfer rate). - * - * - * Following are a sampling of devices that have been tested successfully: - * - * - Western Digital IEEE-1394 hard drives - * - Maxtor IEEE-1394 hard drives - * - VST (SmartDisk) IEEE-1394 hard drives and Zip drives (several flavors) - * - LaCie IEEE-1394 hard drives (several flavors) - * - QPS IEEE-1394 CD-RW/DVD drives and hard drives - * - BusLink IEEE-1394 hard drives - * - Iomega IEEE-1394 Zip/Jazz/Peerless drives - * - ClubMac IEEE-1394 hard drives - * - FirePower IEEE-1394 hard drives - * - EzQuest IEEE-1394 hard drives and CD-RW drives - * - Castlewood/ADS IEEE-1394 ORB drives - * - Evergreen IEEE-1394 hard drives and CD-RW drives - * - Addonics IEEE-1394 CD-RW drives - * - Bellstor IEEE-1394 hard drives and CD-RW drives - * - APDrives IEEE-1394 hard drives - * - Fujitsu IEEE-1394 MO drives - * - Sony IEEE-1394 CD-RW drives - * - Epson IEEE-1394 scanners - * - ADS IEEE-1394 memory stick and compact flash readers - * - SBP-2 bridge-based devices (LSI, Oxford Semiconductor, Indigita bridges) - * - Various other standard IEEE-1394 hard drives and enclosures - * - * - * Performance Issues: - * - * - Make sure you are "not" running fat/fat32 on your attached SBP-2 drives. You'll - * get much better performance formatting the drive ext2 (but you will lose the - * ability to easily move the drive between Windows/Linux). - * + * You may access any attached SBP-2 storage devices as if they were SCSI + * devices (e.g. mount /dev/sda1, fdisk, mkfs, etc.). * * Current Issues: * * - Error Handling: SCSI aborts and bus reset requests are handled somewhat * but the code needs additional debugging. - * - * - Module: The SBP-2 driver is currently only supported as a module. It would not take - * much work to allow it to be compiled into the kernel, but you'd have to - * add some init code to the kernel to support this... and modules are much - * more flexible anyway. ;-) - * - * - Hot-plugging: Interaction with the SCSI stack and support for hot-plugging could - * stand some improvement. - * - * - * History: - * - * 07/25/00 - Initial revision (JSG) - * 08/11/00 - Following changes/bug fixes were made (JSG): - * * Bug fix to SCSI procfs code (still needs to be synched with 2.4 kernel). - * * Bug fix where request sense commands were actually sent on the bus. - * * Changed bus reset/abort code to deal with devices that spin up quite - * slowly (which result in SCSI time-outs). - * * "More" properly pull information from device's config rom, for enumeration - * of SBP-2 devices, and determining SBP-2 register offsets. - * * Change Simplified Direct Access Device type to Direct Access Device type in - * returned inquiry data, in order to make the SCSI stack happy. - * * Modified driver to register with the SCSI stack "before" enumerating any attached - * SBP-2 devices. This means that you'll have to use procfs scsi-add-device or - * some sort of script to discover new SBP-2 devices. - * * Minor re-write of some code and other minor changes. - * 08/28/00 - Following changes/bug fixes were made (JSG): - * * Bug fixes to scatter/gather support (case of one s/g element) - * * Updated direction table for scsi commands (mostly DVD commands) - * * Retries when trying to detect SBP-2 devices (for slow devices) - * * Slightly better error handling (previously none) when commands time-out. - * * Misc. other bug fixes and code reorganization. - * 09/13/00 - Following changes/bug fixes were made (JSG) - * * Moved detection/enumeration code to a kernel thread which is woken up when IEEE-1394 - * bus resets occur. - * * Added code to handle bus resets and hot-plugging while devices are mounted, but full - * hot-plug support is not quite there yet. - * * Now use speed map to determine speed and max payload sizes for ORBs - * * Clean-up of code and reorganization - * 09/19/00 - Added better hot-plug support and other minor changes (JSG) - * 10/15/00 - Fixes for latest 2.4.0 test kernel, minor fix for hot-plug race. (JSG) - * 12/03/00 - Created pool of request packet structures for use in sending out sbp2 command - * and agent reset requests. This removes the kmallocs/kfrees in the critical I/O paths, - * and also deals with some subtle race conditions related to allocating and freeing - * packets. (JSG) - * 12/09/00 - Improved the sbp2 device detection by actually reading the root and unit - * directory (khk@khk.net) - * 12/23/00 - Following changes/enhancements were made (JSG) - * * Only do SCSI to RBC command conversion for Direct Access and Simplified - * Direct Access Devices (this is pulled from the config rom root directory). - * This is needed because doing the conversion for all device types broke the - * Epson scanner. Still looking for a better way of determining when to convert - * commands (for RBC devices). Thanks to khk for helping on this! - * * Added ability to "emulate" physical dma support, for host adapters such as TILynx. - * * Determine max payload and speed by also looking at the host adapter's max_rec field. - * 01/19/01 - Added checks to sbp2 login and made the login time-out longer. Also fixed a compile - * problem for 2.4.0. (JSG) - * 01/24/01 - Fixed problem when individual s/g elements are 64KB or larger. Needed to break - * up these larger elements, since the sbp2 page table element size is only 16 bits. (JSG) - * 01/29/01 - Minor byteswap fix for login response (used for reconnect and log out). - * 03/07/01 - Following changes/enhancements were made (JSG) - * * Changes to allow us to catch the initial scsi bus scan (for detecting sbp2 - * devices when first loading sbp2.o). To disable this, un-define - * SBP2_SUPPORT_INITIAL_BUS_SCAN. - * * Temporary fix to deal with many sbp2 devices that do not support individual - * transfers of greater than 128KB in size. - * * Mode sense conversion from 6 byte to 10 byte versions for CDRW/DVD devices. (Mark Burton) - * * Define allowing support for goofy sbp2 devices that do not support mode - * sense command at all, allowing them to be mounted rw (such as 1394 memory - * stick and compact flash readers). Define SBP2_MODE_SENSE_WRITE_PROTECT_HACK - * if you need this fix. - * 03/29/01 - Major performance enhancements and misc. other changes. Thanks to Daniel Berlin for many of - * changes and suggestions for change: - * * Now use sbp2 doorbell and link commands on the fly (instead of serializing requests) - * * Removed all bit fields in an attempt to run on PPC machines (still needs a little more work) - * * Added large request break-up/linking support for sbp2 chipsets that do not support transfers - * greater than 128KB in size. - * * Bumped up max commands per lun to two, and max total outstanding commands to eight. - * 04/03/01 - Minor clean-up. Write orb pointer directly if no outstanding commands (saves one 1394 bus - * transaction). Added module load options (bus scan, mode sense hack, max speed, serialize_io, - * no_large_transfers). Better bus reset handling while I/O pending. Set serialize_io to 1 by - * default (debugging of deserialized I/O in progress). - * 04/04/01 - Added workaround for PPC Pismo firewire chipset. See #define below. (Daniel Berlin) - * 04/20/01 - Minor clean-up. Allocate more orb structures when running with sbp2 target chipsets with - * 128KB max transfer limit. - * 06/16/01 - Converted DMA interfaces to pci_dma - Ben Collins - * - * - * 11/17/01 - Various bugfixes/cleanups: - * * Remember to logout of device in sbp2_disconnect. - * * If we fail to reconnect to a device after bus reset - * remember to release unit directory, so the ieee1394 - * knows we no longer manage it. - * * Unregister scsi hosts in sbp2_remove_host when a - * hpsb_host goes away. - * * Remove stupid hack in sbp2_remove_host. - * * Switched to "manual" module initialization - * (i.e. not scsi_module.c) and moved sbp2_cleanup - * moved sbp2scsi_release to sbp2_module_ext. The - * release function is called once pr. registered - * scsi host, but sbp2_cleanup should only be called - * upon module unload. Moved much initialization - * from sbp2scsi_detect to sbp2_module_init. - * Kristian Hogsberg - * 01/06/02 - Misc bug fixes/enhancements: (JSG) - * * Enable use_new_eh_code for scsi stuff. - * * Do not write all ones for NULL ORB high/low fields, but - * rather leave reserved areas zeroed (per SBP2 spec). - * * Use newer scsi transfer direction passed down instead of our - * direction table. - * * Bumped login time-out to 20 seconds, as some devices are slow. - * * Fixed a couple scsi unregister bugs on module unload - * 01/13/02 - Fixed compatibility with certain SBP2 devices, such as Iomega - * 1394 devices (Peerless, Jazz). Also a bit of clean-up of the - * driver, thanks to H.J.Lu (hjl@lucon.org). Removed mode_sense_hack - * module load option, as it's been fixed in the 2.4 scsi stack. - * 02/10/02 - Added support for max_sectors, minor fix for inquiry command, make - * up sbp2 device type from inquiry response data if not part of - * device's 1394 unit directory. (JSG) - * 02/18/02 - Code clean-up and enhancements: (JSG) - * * Finish cleaning out hacked code for dealing with broken sbp2 devices - * which do not support requests of 128KB or greater. Now use - * max_sectors scsi host entry to limit transfer sizes. - * * Change status fifo address from a single address to a set of addresses, - * with each sbp2 device having its own status fifo address. This makes - * it easier to match the status write to the sbp2 device instance. - * * Minor change to use lun when logging into sbp2 devices. First step in - * supporting multi-lun devices such as CD/DVD changer devices. - * * Added a new module load option for setting max sectors. For use by folk - * who'd like to bump up the max scsi transfer size supported. - * * Enabled deserialized operation by default, allowing for better performance, - * particularily when running with multiple sbp2 devices. For debugging, - * you may enable serialization through use of the sbp2_serialize_io module - * load option (e.g. insmod sbp2 sbp2_serialize_io=1). - * 02/20/02 - Added a couple additional module load options. - * Needed to bump down max commands per lun because of the !%@&*^# QPS CDRW - * drive I have, which doesn't seem to get along with other sbp2 devices - * (or handle linked commands well). - * 04/21/02 - Added some additional debug capabilities: - * * Able to handle phys dma requests directly, if host controller has phys - * dma disabled (e.g. insmod ohci1394 phys_dma=0). Undefine CONFIG_IEEE1394_SBP2_PHYS_DMA - * if you'd like to disable sbp2 driver from registering for phys address range. - * * New packet dump debug define (CONFIG_IEEE1394_SBP2_PACKET_DUMP) which allows - * dumping of all sbp2 related packets sent and received. Especially effective - * when phys dma is disabled on ohci controller (e.g. insmod ohci1394 phys_dma=0). - * * Added new sbp2 module load option (sbp2_exclusive_login) for allowing - * non-exclusive login to sbp2 device, for special multi-host applications. - * 04/23/02 - Fix for Sony CD-ROM drives. Only send fetch agent reset to sbp2 device if it - * returns the dead bit in status. Thanks to Chandan (chandan@toad.net) for this one. - * 04/27/02 - Fix sbp2 login problem on SMP systems, enable real spinlocks by default. (JSG) - * 06/09/02 - Don't force 36-bute SCSI inquiry, but leave in a define for badly behaved devices. (JSG) - * 02/04/03 - Fixed a SMP deadlock (don't hold sbp2_command_lock while calling sbp2scsi_complete_command). - * Also save/restore irq flags in sbp2scsi_complete_command - Sancho Dauskardt - * - */ - - -/* - * Includes */ #include @@ -343,15 +79,15 @@ #include "ieee1394.h" #include "ieee1394_types.h" #include "ieee1394_core.h" +#include "nodemgr.h" #include "hosts.h" #include "nodemgr.h" #include "highlevel.h" #include "ieee1394_transactions.h" -#include "ieee1394_hotplug.h" #include "sbp2.h" static char version[] __devinitdata = - "$Rev: 906 $ James Goodwin "; + "$Rev: 931 $ Ben Collins "; /* * Module load parameter definitions @@ -489,6 +225,13 @@ #define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args) +/* If you get the linux-2.4 scsi_{add,remove}_single_device patch, you can + * enable this define to make use of it. This provides better hotplug + * support. The mentioned patch is not part of the kernel proper though, + * because it is considered somewhat of a hack. */ +//#define SBP2_USE_SCSI_ADDREM_HACK + + /* * Globals */ @@ -504,7 +247,6 @@ static struct hpsb_highlevel sbp2_highlevel = { .name = SBP2_DEVICE_NAME, - .add_host = sbp2_add_host, .remove_host = sbp2_remove_host, }; @@ -815,22 +557,22 @@ /* Free our DMA's */ static void sbp2util_free_command_dma(struct sbp2_command_info *command) { - struct sbp2scsi_host_info *hi; + struct hpsb_host *host; - hi = hpsb_get_hostinfo_bykey(&sbp2_highlevel, + host = hpsb_get_host_bykey(&sbp2_highlevel, (unsigned long)command->Current_SCpnt->device->host->hostt); - if (!hi) { - printk(KERN_ERR "%s: hi == NULL\n", __FUNCTION__); + if (!host) { + printk(KERN_ERR "%s: host == NULL\n", __FUNCTION__); return; } if (command->cmd_dma) { if (command->dma_type == CMD_DMA_SINGLE) { - pci_unmap_single(hi->host->pdev, command->cmd_dma, + pci_unmap_single(host->pdev, command->cmd_dma, command->dma_size, command->dma_dir); SBP2_DMA_FREE("single bulk"); } else if (command->dma_type == CMD_DMA_PAGE) { - pci_unmap_page(hi->host->pdev, command->cmd_dma, + pci_unmap_page(host->pdev, command->cmd_dma, command->dma_size, command->dma_dir); SBP2_DMA_FREE("single page"); } /* XXX: Check for CMD_DMA_NONE bug */ @@ -839,7 +581,7 @@ } if (command->sge_buffer) { - pci_unmap_sg(hi->host->pdev, command->sge_buffer, + pci_unmap_sg(host->pdev, command->sge_buffer, command->dma_size, command->dma_dir); SBP2_DMA_FREE("scatter list"); command->sge_buffer = NULL; @@ -873,7 +615,7 @@ static int sbp2scsi_detect(Scsi_Host_Template *tpnt) { struct Scsi_Host *scsi_host; - struct sbp2scsi_host_info *hi = hpsb_get_hostinfo_bykey(&sbp2_highlevel, (unsigned long)tpnt); + struct hpsb_host *host = hpsb_get_host_bykey(&sbp2_highlevel, (unsigned long)tpnt); SBP2_DEBUG("sbp2scsi_detect"); @@ -881,7 +623,7 @@ if (!(scsi_host = scsi_register(tpnt, 0))) return 0; - scsi_set_pci_device(scsi_host, hi->host->pdev); + scsi_set_pci_device(scsi_host, host->pdev); tpnt->present = 1; @@ -893,80 +635,104 @@ struct sbp2scsi_host_info *hi; SBP2_DEBUG("sbp2_probe"); - hi = hpsb_get_hostinfo(&sbp2_highlevel, ud->ne->host); + hi = sbp2_add_host(ud->ne->host); + + if (!hi) + return -1; - return sbp2_start_device(hi, ud); + return sbp2_start_ud(hi, ud); } static void sbp2_disconnect(struct unit_directory *ud) { - struct scsi_id_instance_data *scsi_id = ud->driver_data; + struct scsi_id_group *scsi_group = ud->driver_data; + struct list_head *lh, *next; + struct scsi_id_instance_data *scsi_id; SBP2_DEBUG("sbp2_disconnect"); - if (scsi_id) { - sbp2_logout_device(scsi_id); - sbp2_remove_device(scsi_id); + list_for_each_safe (lh, next, &scsi_group->scsi_id_list) { + scsi_id = list_entry(lh, struct scsi_id_instance_data, list); + if (scsi_id) { + sbp2_logout_device(scsi_id); + sbp2_remove_device(scsi_id); + } } + + kfree(scsi_group); } static void sbp2_update(struct unit_directory *ud) { struct sbp2scsi_host_info *hi; - struct scsi_id_instance_data *scsi_id = ud->driver_data; + struct scsi_id_group *scsi_group = ud->driver_data; + struct list_head *lh, *next; + struct scsi_id_instance_data *scsi_id; unsigned long flags; SBP2_DEBUG("sbp2_update"); hi = hpsb_get_hostinfo(&sbp2_highlevel, ud->ne->host); - if (sbp2_reconnect_device(scsi_id)) { - - /* - * Ok, reconnect has failed. Perhaps we didn't - * reconnect fast enough. Try doing a regular login. - */ - if (sbp2_login_device(scsi_id)) { - /* Login failed too, just remove the device. */ - SBP2_ERR("sbp2_reconnect_device failed!"); - sbp2_remove_device(scsi_id); - hpsb_release_unit_directory(ud); - return; + list_for_each_safe (lh, next, &scsi_group->scsi_id_list) { + scsi_id = list_entry(lh, struct scsi_id_instance_data, list); + + if (sbp2_reconnect_device(scsi_id)) { + /* + * Ok, reconnect has failed. Perhaps we didn't + * reconnect fast enough. Try doing a regular login. + */ + if (sbp2_login_device(scsi_id)) { + /* Login failed too, just remove the device. */ + SBP2_ERR("sbp2_reconnect_device failed!"); + sbp2_remove_device(scsi_id); + continue; + } } - } - /* Set max retries to something large on the device. */ - sbp2_set_busy_timeout(scsi_id); + /* Set max retries to something large on the device. */ + sbp2_set_busy_timeout(scsi_id); - /* Do a SBP-2 fetch agent reset. */ - sbp2_agent_reset(scsi_id, 0); + /* Do a SBP-2 fetch agent reset. */ + sbp2_agent_reset(scsi_id, 0); - /* Get the max speed and packet size that we can use. */ - sbp2_max_speed_and_size(scsi_id); + /* Get the max speed and packet size that we can use. */ + sbp2_max_speed_and_size(scsi_id); - /* Complete any pending commands with busy (so they get - * retried) and remove them from our queue - */ - spin_lock_irqsave(&hi->sbp2_command_lock, flags); - sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); - spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); + /* Complete any pending commands with busy (so they get + * retried) and remove them from our queue + */ + spin_lock_irqsave(&hi->sbp2_command_lock, flags); + sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); + spin_unlock_irqrestore(&hi->sbp2_command_lock, flags); + } + + if (list_empty(&scsi_group->scsi_id_list)) { + hpsb_release_unit_directory(ud); + kfree(scsi_group); + } } /* * We go ahead and allocate some memory for our host info structure, and * init some structures. */ -static void sbp2_add_host(struct hpsb_host *host) +static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host) { struct sbp2scsi_host_info *hi; SBP2_DEBUG("sbp2_add_host"); + /* Check for existing hostinfo */ + hi = hpsb_get_hostinfo(&sbp2_highlevel, host); + if (hi) + return hi; + /* Allocate some memory for our host info structure */ hi = hpsb_create_hostinfo(&sbp2_highlevel, host, sizeof(*hi)); if (hi == NULL) { SBP2_ERR("out of memory in sbp2_add_host"); - return; + return NULL; } /* Initialize some host stuff */ @@ -981,7 +747,7 @@ if (SCSI_REGISTER_HOST(&hi->sht)) { SBP2_ERR("Failed to register scsi template for ieee1394 host"); hpsb_destroy_hostinfo(&sbp2_highlevel, host); - return; + return NULL; } for (hi->scsi_host = scsi_hostlist; hi->scsi_host; hi->scsi_host = hi->scsi_host->next) @@ -992,12 +758,12 @@ SBP2_ERR("Failed to register scsi host for ieee1394 host"); SCSI_UNREGISTER_HOST(&hi->sht); hpsb_destroy_hostinfo(&sbp2_highlevel, host); - return; + return NULL; } hi->scsi_host->max_id = SBP2SCSI_MAX_SCSI_IDS; - return; + return hi; } @@ -1014,34 +780,61 @@ if (hi) SCSI_UNREGISTER_HOST(&hi->sht); - else - SBP2_ERR("attempt to remove unknown host %p", host); } +static int sbp2_start_ud(struct sbp2scsi_host_info *hi, struct unit_directory *ud) +{ + struct scsi_id_instance_data *scsi_id; + struct scsi_id_group *scsi_group; + struct list_head *lh, *next; + + SBP2_DEBUG("sbp2_start_ud"); + + scsi_group = kmalloc(sizeof(*scsi_group), GFP_KERNEL); + if (!scsi_group) { + SBP2_ERR ("Could not allocate memory for scsi_group"); + return -ENOMEM; + } + + INIT_LIST_HEAD(&scsi_group->scsi_id_list); + ud->driver_data = scsi_group; + sbp2_parse_unit_directory(scsi_group, ud); + + list_for_each_safe (lh, next, &scsi_group->scsi_id_list) { + scsi_id = list_entry(lh, struct scsi_id_instance_data, list); + + scsi_id->ne = ud->ne; + scsi_id->hi = hi; + scsi_id->speed_code = SPEED_100; + scsi_id->max_payload_size = hpsb_speedto_maxrec[SPEED_100]; + atomic_set(&scsi_id->sbp2_login_complete, 0); + INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse); + INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed); + scsi_id->sbp2_command_orb_lock = SPIN_LOCK_UNLOCKED; + + sbp2_start_device(scsi_id); + } + + /* Check to see if any of our devices survived the ordeal */ + if (list_empty(&scsi_group->scsi_id_list)) { + kfree(scsi_group); + return -ENODEV; + } + + return 0; +} + + /* * This function is where we first pull the node unique ids, and then * allocate memory and register a SBP-2 device. */ -static int sbp2_start_device(struct sbp2scsi_host_info *hi, struct unit_directory *ud) +static int sbp2_start_device(struct scsi_id_instance_data *scsi_id) { - struct scsi_id_instance_data *scsi_id = NULL; - struct node_entry *ne; + struct sbp2scsi_host_info *hi = scsi_id->hi; int i; SBP2_DEBUG("sbp2_start_device"); - ne = ud->ne; - - /* - * This really is a "new" device plugged in. Let's allocate memory - * for our scsi id instance data. - */ - scsi_id = (struct scsi_id_instance_data *)kmalloc(sizeof(struct scsi_id_instance_data), - GFP_KERNEL); - if (!scsi_id) - goto alloc_fail_first; - memset(scsi_id, 0, sizeof(struct scsi_id_instance_data)); - - scsi_id->hi = hi; /* Login FIFO DMA */ scsi_id->login_response = @@ -1130,7 +923,9 @@ } kfree(scsi_id); -alloc_fail_first: + + list_del(&scsi_id->list); + SBP2_ERR ("Could not allocate memory for scsi_id"); return -ENOMEM; @@ -1138,31 +933,6 @@ SBP2_DMA_ALLOC("consistent DMA region for login ORB"); /* - * Initialize some of the fields in this structure - */ - scsi_id->ne = ne; - scsi_id->ud = ud; - scsi_id->speed_code = SPEED_100; - scsi_id->max_payload_size = hpsb_speedto_maxrec[SPEED_100]; - ud->driver_data = scsi_id; - - atomic_set(&scsi_id->sbp2_login_complete, 0); - - /* - * Initialize structures needed for the command orb pool. - */ - INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse); - INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed); - scsi_id->sbp2_command_orb_lock = SPIN_LOCK_UNLOCKED; - - /* - * Make sure that we've gotten ahold of the sbp2 management agent - * address. Also figure out the command set being used (SCSI or - * RBC). - */ - sbp2_parse_unit_directory(scsi_id); - - /* * Find an empty spot to stick our scsi id instance data. */ for (i = 0; i < hi->scsi_host->max_id; i++) { @@ -1216,6 +986,12 @@ */ sbp2_max_speed_and_size(scsi_id); +#ifdef SBP2_USE_SCSI_ADDREM_HACK + /* Try to hook ourselves into the SCSI subsystem */ + if (scsi_add_single_device(hi->scsi_host, 0, scsi_id->id, 0)) + SBP2_INFO("Unable to connect SBP-2 device into the SCSI subsystem"); +#endif + return 0; } @@ -1286,6 +1062,8 @@ SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->id); + list_del(&scsi_id->list); + kfree(scsi_id); } @@ -1362,6 +1140,8 @@ scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1); if (scsi_id->sbp2_device_type_and_lun != SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) { scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun); + SBP2_DEBUG("sbp2_query_logins: set lun to %d", + ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun)); } SBP2_DEBUG("sbp2_query_logins: lun_misc initialized"); @@ -1474,6 +1254,8 @@ /* Set the lun if we were able to pull it from the device's unit directory */ if (scsi_id->sbp2_device_type_and_lun != SBP2_DEVICE_TYPE_LUN_UNINITIALIZED) { scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun); + SBP2_DEBUG("sbp2_query_logins: set lun to %d", + ORB_SET_LUN(scsi_id->sbp2_device_type_and_lun)); } SBP2_DEBUG("sbp2_login_device: lun_misc initialized"); @@ -1514,7 +1296,8 @@ atomic_set(&scsi_id->sbp2_login_complete, 0); - SBP2_DEBUG("sbp2_login_device: prepared to write"); + SBP2_DEBUG("sbp2_login_device: prepared to write to %08x", + (unsigned int)scsi_id->sbp2_management_agent_addr); hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8); SBP2_DEBUG("sbp2_login_device: written"); @@ -1625,8 +1408,14 @@ SBP2_INFO("Logged out of SBP-2 device"); - return(0); +#ifdef SBP2_USE_SCSI_ADDREM_HACK + /* Now that we are logged out of the SBP-2 device, lets + * try to un-hook ourselves from the SCSI subsystem */ + if (scsi_remove_single_device(hi->scsi_host, 0, scsi_id->id, 0)) + SBP2_INFO("Unable to disconnect SBP-2 device from the SCSI subsystem"); +#endif + return 0; } /* @@ -1745,50 +1534,50 @@ * directory. Used to determine things like sbp2 management agent offset, * and command set used (SCSI or RBC). */ -static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id) +static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group, + struct unit_directory *ud) { - struct unit_directory *ud; + struct scsi_id_instance_data *scsi_id; + struct list_head *lh; + u64 management_agent_addr; + u32 command_set_spec_id, command_set, unit_characteristics, + firmware_revision, workarounds; int i; SBP2_DEBUG("sbp2_parse_unit_directory"); - /* Initialize some fields, in case an entry does not exist */ - scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED; - scsi_id->sbp2_management_agent_addr = 0x0; - scsi_id->sbp2_command_set_spec_id = 0x0; - scsi_id->sbp2_command_set = 0x0; - scsi_id->sbp2_unit_characteristics = 0x0; - scsi_id->sbp2_firmware_revision = 0x0; - - ud = scsi_id->ud; + management_agent_addr = 0x0; + command_set_spec_id = 0x0; + command_set = 0x0; + unit_characteristics = 0x0; + firmware_revision = 0x0; /* Handle different fields in the unit directory, based on keys */ for (i = 0; i < ud->length; i++) { switch (CONFIG_ROM_KEY(ud->quadlets[i])) { case SBP2_CSR_OFFSET_KEY: /* Save off the management agent address */ - scsi_id->sbp2_management_agent_addr = + management_agent_addr = CSR_REGISTER_BASE + (CONFIG_ROM_VALUE(ud->quadlets[i]) << 2); SBP2_DEBUG("sbp2_management_agent_addr = %x", - (unsigned int) scsi_id->sbp2_management_agent_addr); + (unsigned int) management_agent_addr); break; case SBP2_COMMAND_SET_SPEC_ID_KEY: /* Command spec organization */ - scsi_id->sbp2_command_set_spec_id + command_set_spec_id = CONFIG_ROM_VALUE(ud->quadlets[i]); SBP2_DEBUG("sbp2_command_set_spec_id = %x", - (unsigned int) scsi_id->sbp2_command_set_spec_id); + (unsigned int) command_set_spec_id); break; case SBP2_COMMAND_SET_KEY: /* Command set used by sbp2 device */ - scsi_id->sbp2_command_set - = CONFIG_ROM_VALUE(ud->quadlets[i]); + command_set = CONFIG_ROM_VALUE(ud->quadlets[i]); SBP2_DEBUG("sbp2_command_set = %x", - (unsigned int) scsi_id->sbp2_command_set); + (unsigned int) command_set); break; case SBP2_UNIT_CHARACTERISTICS_KEY: @@ -1796,10 +1585,10 @@ * Unit characterisitcs (orb related stuff * that I'm not yet paying attention to) */ - scsi_id->sbp2_unit_characteristics + unit_characteristics = CONFIG_ROM_VALUE(ud->quadlets[i]); SBP2_DEBUG("sbp2_unit_characteristics = %x", - (unsigned int) scsi_id->sbp2_unit_characteristics); + (unsigned int) unit_characteristics); break; case SBP2_DEVICE_TYPE_AND_LUN_KEY: @@ -1807,21 +1596,29 @@ * Device type and lun (used for * detemining type of sbp2 device) */ + scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL); + if (!scsi_id) { + SBP2_ERR("Out of memory adding scsi_id, not all LUN's will be added"); + break; + } + memset(scsi_id, 0, sizeof(*scsi_id)); + scsi_id->sbp2_device_type_and_lun = CONFIG_ROM_VALUE(ud->quadlets[i]); SBP2_DEBUG("sbp2_device_type_and_lun = %x", (unsigned int) scsi_id->sbp2_device_type_and_lun); + list_add_tail(&scsi_id->list, &scsi_group->scsi_id_list); break; case SBP2_FIRMWARE_REVISION_KEY: /* Firmware revision */ - scsi_id->sbp2_firmware_revision + firmware_revision = CONFIG_ROM_VALUE(ud->quadlets[i]); if (sbp2_force_inquiry_hack) SBP2_INFO("sbp2_firmware_revision = %x", - (unsigned int) scsi_id->sbp2_firmware_revision); + (unsigned int) firmware_revision); else SBP2_DEBUG("sbp2_firmware_revision = %x", - (unsigned int) scsi_id->sbp2_firmware_revision); + (unsigned int) firmware_revision); break; default: @@ -1831,7 +1628,7 @@ /* This is the start of our broken device checking. We try to hack * around oddities and known defects. */ - scsi_id->workarounds = 0x0; + workarounds = 0x0; /* If the vendor id is 0xa0b8 (Symbios vendor id), then we have a * bridge with 128KB max transfer size limitation. For sanity, we @@ -1842,28 +1639,54 @@ * host gets initialized. That way we can down-force the * sbp2_max_sectors to account for it. That is not currently * possible. */ - if ((scsi_id->sbp2_firmware_revision & 0xffff00) == + if ((firmware_revision & 0xffff00) == SBP2_128KB_BROKEN_FIRMWARE && (sbp2_max_sectors * 512) > (128 * 1024)) { SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB max transfer size.", - NODE_BUS_ARGS(scsi_id->ne->nodeid)); + NODE_BUS_ARGS(ud->ne->nodeid)); SBP2_WARN("WARNING: Current sbp2_max_sectors setting is larger than 128KB (%d sectors)!", sbp2_max_sectors); - scsi_id->workarounds |= SBP2_BREAKAGE_128K_MAX_TRANSFER; + workarounds |= SBP2_BREAKAGE_128K_MAX_TRANSFER; } /* Check for a blacklisted set of devices that require us to force * a 36 byte host inquiry. This can be overriden as a module param * (to force all hosts). */ for (i = 0; i < NUM_BROKEN_INQUIRY_DEVS; i++) { - if ((scsi_id->sbp2_firmware_revision & 0xffff00) == + if ((firmware_revision & 0xffff00) == sbp2_broken_inquiry_list[i]) { SBP2_WARN("Node " NODE_BUS_FMT ": Using 36byte inquiry workaround", - NODE_BUS_ARGS(scsi_id->ne->nodeid)); - scsi_id->workarounds |= SBP2_BREAKAGE_INQUIRY_HACK; + NODE_BUS_ARGS(ud->ne->nodeid)); + workarounds |= SBP2_BREAKAGE_INQUIRY_HACK; break; /* No need to continue. */ } } + + /* If our list is empty, add a base scsi_id (happens in a normal + * case where there is no logical_unit_number entry */ + if (list_empty(&scsi_group->scsi_id_list)) { + scsi_id = kmalloc(sizeof(*scsi_id), GFP_KERNEL); + if (!scsi_id) { + SBP2_ERR("Out of memory adding scsi_id"); + return; + } + memset(scsi_id, 0, sizeof(*scsi_id)); + + scsi_id->sbp2_device_type_and_lun = SBP2_DEVICE_TYPE_LUN_UNINITIALIZED; + list_add_tail(&scsi_id->list, &scsi_group->scsi_id_list); + } + + /* Update the generic fields in all the LUN's */ + list_for_each (lh, &scsi_group->scsi_id_list) { + scsi_id = list_entry(lh, struct scsi_id_instance_data, list); + + scsi_id->sbp2_management_agent_addr = management_agent_addr; + scsi_id->sbp2_command_set_spec_id = command_set_spec_id; + scsi_id->sbp2_command_set = command_set; + scsi_id->sbp2_unit_characteristics = unit_characteristics; + scsi_id->sbp2_firmware_revision = firmware_revision; + scsi_id->workarounds = workarounds; + } } /* @@ -3053,27 +2876,27 @@ int length, int hostno, int inout) { Scsi_Device *scd; - struct Scsi_Host *host; - struct sbp2scsi_host_info *hi; + struct Scsi_Host *scsi_host; + struct hpsb_host *host; char *pos = buffer; /* if someone is sending us data, just throw it away */ if (inout) return length; - for (host = scsi_hostlist; host; host = host->next) - if (host->host_no == hostno) + for (scsi_host = scsi_hostlist; scsi_host; scsi_host = scsi_host->next) + if (scsi_host->host_no == hostno) break; - if (!host) /* if we couldn't find it, we return an error */ + if (!scsi_host) /* if we couldn't find it, we return an error */ return -ESRCH; - hi = hpsb_get_hostinfo_bykey(&sbp2_highlevel, (unsigned long)host->hostt); - if (!hi) /* shouldn't happen, but... */ + host = hpsb_get_host_bykey(&sbp2_highlevel, (unsigned long)scsi_host->hostt); + if (!host) /* shouldn't happen, but... */ return -ESRCH; SPRINTF("Host scsi%d : SBP-2 IEEE-1394 (%s)\n", hostno, - hi->host->driver->name); + host->driver->name); SPRINTF("Driver version : %s\n", version); SPRINTF("\nModule options :\n"); @@ -3082,9 +2905,9 @@ SPRINTF(" serialize_io : %s\n", sbp2_serialize_io ? "yes" : "no"); SPRINTF(" exclusive_login : %s\n", sbp2_exclusive_login ? "yes" : "no"); - SPRINTF("\nAttached devices : %s\n", host->host_queue ? "" : "none"); + SPRINTF("\nAttached devices : %s\n", scsi_host->host_queue ? "" : "none"); - for (scd = host->host_queue; scd; scd = scd->next) { + for (scd = scsi_host->host_queue; scd; scd = scd->next) { int i; SPRINTF(" [Channel: %02d, Id: %02d, Lun: %02d] ", scd->channel, @@ -3117,7 +2940,7 @@ } -MODULE_AUTHOR("James Goodwin "); +MODULE_AUTHOR("Ben Collins "); MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver"); MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME); MODULE_LICENSE("GPL"); diff -uNr linux-2.4.21/drivers/ieee1394/sbp2.h linux-2.4.21-ben2/drivers/ieee1394/sbp2.h --- linux-2.4.21/drivers/ieee1394/sbp2.h 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ieee1394/sbp2.h 2003-06-27 15:41:23.000000000 +0200 @@ -388,7 +388,6 @@ /* * Values pulled from the device's unit directory */ - struct unit_directory *ud; u32 sbp2_command_set_spec_id; u32 sbp2_command_set; u32 sbp2_unit_characteristics; @@ -407,6 +406,8 @@ struct list_head sbp2_command_orb_inuse; struct list_head sbp2_command_orb_completed; + struct list_head list; + /* Node entry, as retrieved from NodeMgr entries */ struct node_entry *ne; @@ -417,6 +418,13 @@ u32 workarounds; }; + +/* Describes a per-ud scsi_id group */ +struct scsi_id_group { + struct list_head scsi_id_list; +}; + + /* * Sbp2 host data structure (one per sbp2 host) */ @@ -461,14 +469,15 @@ /* * IEEE-1394 core driver related prototypes */ -static void sbp2_add_host(struct hpsb_host *host); +static struct sbp2scsi_host_info *sbp2_add_host(struct hpsb_host *host); static void sbp2_remove_host(struct hpsb_host *host); static int sbp2_probe(struct unit_directory *ud); static void sbp2_disconnect(struct unit_directory *ud); static void sbp2_update(struct unit_directory *ud); -static int sbp2_start_device(struct sbp2scsi_host_info *hi, - struct unit_directory *ud); +static int sbp2_start_ud(struct sbp2scsi_host_info *hi, + struct unit_directory *ud); +static int sbp2_start_device(struct scsi_id_instance_data *scsi_id); static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id); #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA @@ -502,7 +511,8 @@ static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data); static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd); static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, Scsi_Cmnd *SCpnt); -static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id); +static void sbp2_parse_unit_directory(struct scsi_id_group *scsi_group, + struct unit_directory *ud); static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id); static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id); diff -uNr linux-2.4.21/drivers/ieee1394/video1394.c linux-2.4.21-ben2/drivers/ieee1394/video1394.c --- linux-2.4.21/drivers/ieee1394/video1394.c 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/ieee1394/video1394.c 2003-06-27 15:41:51.000000000 +0200 @@ -46,7 +46,7 @@ #include "ieee1394.h" #include "ieee1394_types.h" -#include "ieee1394_hotplug.h" +#include "nodemgr.h" #include "hosts.h" #include "ieee1394_core.h" #include "highlevel.h" @@ -1007,6 +1007,8 @@ struct video1394_queue_variable qv; struct dma_iso_ctx *d; + qv.packet_sizes = NULL; + if(copy_from_user(&v, (void *)arg, sizeof(v))) return -EFAULT; @@ -1019,12 +1021,22 @@ } if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) { + unsigned int *psizes; + int buf_size = d->nb_cmd * sizeof(unsigned int); + if (copy_from_user(&qv, (void *)arg, sizeof(qv))) return -EFAULT; - if (!access_ok(VERIFY_READ, qv.packet_sizes, - d->nb_cmd * sizeof(unsigned int))) { + + psizes = kmalloc(buf_size, GFP_KERNEL); + if (!psizes) + return -ENOMEM; + + if (copy_from_user(psizes, qv.packet_sizes, buf_size)) { + kfree(psizes); return -EFAULT; } + + qv.packet_sizes = psizes; } spin_lock_irqsave(&d->lock,flags); @@ -1033,6 +1045,8 @@ PRINT(KERN_ERR, ohci->id, "Buffer %d is already used",v.buffer); spin_unlock_irqrestore(&d->lock,flags); + if (qv.packet_sizes) + kfree(qv.packet_sizes); return -EFAULT; } @@ -1086,6 +1100,10 @@ reg_write(ohci, d->ctrlSet, 0x1000); } } + + if (qv.packet_sizes) + kfree(qv.packet_sizes); + return 0; } diff -uNr linux-2.4.21/drivers/macintosh/Makefile linux-2.4.21-ben2/drivers/macintosh/Makefile --- linux-2.4.21/drivers/macintosh/Makefile 2002-11-29 00:53:13.000000000 +0100 +++ linux-2.4.21-ben2/drivers/macintosh/Makefile 2003-06-27 15:41:51.000000000 +0200 @@ -35,6 +35,8 @@ obj-$(CONFIG_INPUT_ADBHID) += adbhid.o obj-$(CONFIG_PPC_RTC) += rtc.o obj-$(CONFIG_ANSLCD) += ans-lcd.o +#obj-$(CONFIG_I2C) += therm_pismo.o +#obj-$(CONFIG_I2C) += therm_albooks.o obj-$(CONFIG_ADB_PMU) += via-pmu.o obj-$(CONFIG_ADB_CUDA) += via-cuda.o diff -uNr linux-2.4.21/drivers/macintosh/adb.c linux-2.4.21-ben2/drivers/macintosh/adb.c --- linux-2.4.21/drivers/macintosh/adb.c 2002-11-29 00:53:13.000000000 +0100 +++ linux-2.4.21-ben2/drivers/macintosh/adb.c 2003-06-27 15:41:25.000000000 +0200 @@ -252,6 +252,10 @@ { adb_probe_task_pid = kernel_thread(adb_probe_task, NULL, SIGCHLD | CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + if (adb_probe_task_pid < 0) { + adb_probe_task_pid = 0; + printk(KERN_ERR "adb: failed to create probe task !\n"); + } } int @@ -592,7 +596,6 @@ return (*original_address != 0); } - /* * /dev/adb device driver. */ @@ -636,6 +639,27 @@ spin_unlock_irqrestore(&state->lock, flags); } +static int +do_adb_query(struct adb_request *req) +{ + int ret = -EINVAL; + + switch(req->data[1]) + { + case ADB_QUERY_GETDEVINFO: + if (req->nbytes < 3) + break; + req->reply[0] = adb_handler[req->data[2]].original_address; + req->reply[1] = adb_handler[req->data[2]].handler_id; + req->complete = 1; + req->reply_len = 2; + adb_write_done(req); + ret = 0; + break; + } + return ret; +} + static int adb_open(struct inode *inode, struct file *file) { struct adbdev_state *state; @@ -655,6 +679,7 @@ return 0; } +/* FIXME: Should wait completion, dequeue & delete pending requests */ static int adb_release(struct inode *inode, struct file *file) { struct adbdev_state *state = file->private_data; @@ -772,9 +797,17 @@ /* If a probe is in progress or we are sleeping, wait for it to complete */ down(&adb_probe_mutex); + /* Queries are special requests sent to the ADB driver itself */ + if (req->data[0] == ADB_QUERY) { + if (count > 1) + ret = do_adb_query(req); + else + ret = -EINVAL; + up(&adb_probe_mutex); + } /* Special case for ADB_BUSRESET request, all others are sent to the controller */ - if ((req->data[0] == ADB_PACKET)&&(count > 1) + else if ((req->data[0] == ADB_PACKET)&&(count > 1) &&(req->data[1] == ADB_BUSRESET)) { ret = do_adb_reset_bus(); up(&adb_probe_mutex); diff -uNr linux-2.4.21/drivers/macintosh/adbhid.c linux-2.4.21-ben2/drivers/macintosh/adbhid.c --- linux-2.4.21/drivers/macintosh/adbhid.c 2002-08-03 02:39:44.000000000 +0200 +++ linux-2.4.21-ben2/drivers/macintosh/adbhid.c 2003-06-27 15:41:25.000000000 +0200 @@ -42,6 +42,10 @@ #include #include #include + +#include +#include + #ifdef CONFIG_PMAC_BACKLIGHT #include #endif @@ -65,7 +69,7 @@ 0, 83, 0, 55, 0, 78, 0, 69, 0, 0, 0, 98, 96, 0, 74, 0, 0,117, 82, 79, 80, 81, 75, 76, 77, 71, 0, 72, 73,183,181,124, 63, 64, 65, 61, 66, 67,191, 87,190, 99, 0, 70, 0, 68,101, 88, - 0,119,110,102,104,111, 62,107, 60,109, 59, 54,100, 97,116,116 + 0,119,110,102,104,111, 62,107, 60,109, 59, 54,100, 97,126,116 }; struct adbhid { @@ -154,6 +158,15 @@ return; case 0x3f: /* ignore Powerbook Fn key */ return; + case 0x7e: /* Power key on PBook 3400 needs remapping */ + switch(pmac_call_feature(PMAC_FTR_GET_MB_INFO, + NULL, PMAC_MB_INFO_MODEL, 0)) { + case PMAC_TYPE_COMET: + case PMAC_TYPE_HOOPER: + case PMAC_TYPE_KANGA: + keycode = 0x7f; + } + break; } if (adbhid[id]->keycode[keycode]) @@ -306,13 +319,12 @@ case 0xa: /* brightness decrease */ #ifdef CONFIG_PMAC_BACKLIGHT if (!disable_kernel_backlight) { - if (!down || backlight < 0) - break; - if (backlight > BACKLIGHT_OFF) - set_backlight_level(backlight-1); - else - set_backlight_level(BACKLIGHT_OFF); - break; + if (down && backlight >= 0) { + if (backlight > BACKLIGHT_OFF) + set_backlight_level(backlight-1); + else + set_backlight_level(BACKLIGHT_OFF); + } } #endif /* CONFIG_PMAC_BACKLIGHT */ input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSDOWN, down); @@ -320,13 +332,12 @@ case 0x9: /* brightness increase */ #ifdef CONFIG_PMAC_BACKLIGHT if (!disable_kernel_backlight) { - if (!down || backlight < 0) - break; - if (backlight < BACKLIGHT_MAX) - set_backlight_level(backlight+1); - else - set_backlight_level(BACKLIGHT_MAX); - break; + if (down && backlight >= 0) { + if (backlight < BACKLIGHT_MAX) + set_backlight_level(backlight+1); + else + set_backlight_level(BACKLIGHT_MAX); + } } #endif /* CONFIG_PMAC_BACKLIGHT */ input_report_key(&adbhid[id]->input, KEY_BRIGHTNESSUP, down); diff -uNr linux-2.4.21/drivers/macintosh/apm_emu.c linux-2.4.21-ben2/drivers/macintosh/apm_emu.c --- linux-2.4.21/drivers/macintosh/apm_emu.c 2002-11-29 00:53:13.000000000 +0100 +++ linux-2.4.21-ben2/drivers/macintosh/apm_emu.c 2003-06-27 15:41:09.000000000 +0200 @@ -436,40 +436,40 @@ int percentage = -1; int time_units = -1; int real_count = 0; - int charge = -1; - int current = 0; int i; char * p = buf; char charging = 0; + long charge = -1; + long current = 0; + unsigned long btype = 0; ac_line_status = ((pmu_power_flags & PMU_PWR_AC_PRESENT) != 0); for (i=0; i 0) { battery_status = 0x03; battery_flag = 0x08; } else if (percentage <= APM_CRITICAL) { @@ -516,6 +516,7 @@ static int __init apm_emu_init(void) { struct proc_dir_entry *apm_proc; + int retval; if (sys_ctrler != SYS_CTRLER_PMU) { printk(KERN_INFO "apm_emu: Requires a machine with a PMU.\n"); @@ -523,10 +524,18 @@ } apm_proc = create_proc_info_entry("apm", 0, NULL, apm_emu_get_info); - if (apm_proc) - SET_MODULE_OWNER(apm_proc); + if (!apm_proc) { + printk(KERN_ERR "apm_emu: create_proc_info_entry failed.\n"); + return -ENOENT; + } + SET_MODULE_OWNER(apm_proc); - misc_register(&apm_device); + retval = misc_register(&apm_device); + if (retval < 0) { + printk(KERN_ERR "apm_emu: misc_register failed\n"); + remove_proc_entry("apm", NULL); + return retval; + } pmu_register_sleep_notifier(&apm_sleep_notifier); diff -uNr linux-2.4.21/drivers/macintosh/macio-adb.c linux-2.4.21-ben2/drivers/macintosh/macio-adb.c --- linux-2.4.21/drivers/macintosh/macio-adb.c 2002-11-29 00:53:13.000000000 +0100 +++ linux-2.4.21-ben2/drivers/macintosh/macio-adb.c 2003-06-27 15:41:21.000000000 +0200 @@ -218,7 +218,6 @@ out_8(&adb->ctrl.r, DTB + CRE); } else { out_8(&adb->ctrl.r, DTB); - req->complete = 1; current_req = req->next; complete = 1; if (current_req) @@ -238,7 +237,6 @@ for (i = 0; i < req->reply_len; ++i) req->reply[i] = in_8(&adb->data[i].r); } - req->complete = 1; current_req = req->next; complete = 1; if (current_req) @@ -255,8 +253,16 @@ out_8(&adb->intr.r, 0); } spin_unlock(&macio_lock); - if (complete && req && req->done) - (*req->done)(req); + if (complete && req) { + void (*done)(struct adb_request *) = req->done; + mb(); + req->complete = 1; + /* Here, we assume that if the request has a done member, the + * struct request will survive to setting req->complete to 1 + */ + if (done) + (*done)(req); + } if (ibuf_len) adb_input(ibuf, ibuf_len, regs, autopoll); } diff -uNr linux-2.4.21/drivers/macintosh/macserial.c linux-2.4.21-ben2/drivers/macintosh/macserial.c --- linux-2.4.21/drivers/macintosh/macserial.c 2002-08-03 02:39:44.000000000 +0200 +++ linux-2.4.21-ben2/drivers/macintosh/macserial.c 2003-06-27 15:41:19.000000000 +0200 @@ -1134,6 +1134,8 @@ */ static void shutdown(struct mac_serial * info) { + unsigned long flags; + OPNDBG("Shutting down serial port %d (irq %d)....\n", info->line, info->irq); @@ -1142,6 +1144,8 @@ return; } + save_flags(flags); cli(); /* Disable interrupts */ + if (info->has_dma) { del_timer(&info->poll_dma_timer); dbdma_reset(info->tx_dma); @@ -1151,6 +1155,8 @@ } disable_irq(info->irq); + restore_flags(flags); + info->pendregs[1] = info->curregs[1] = 0; write_zsreg(info->zs_channel, 1, 0); /* no interrupts */ @@ -1980,6 +1986,7 @@ return; } info->flags |= ZILOG_CLOSING; + restore_flags(flags); /* * Save the termios structure, since this port may have * separate termios for callout and dialin. @@ -1994,11 +2001,8 @@ */ OPNDBG("waiting end of Tx... (timeout:%d)\n", info->closing_wait); tty->closing = 1; - if (info->closing_wait != ZILOG_CLOSING_WAIT_NONE) { - restore_flags(flags); + if (info->closing_wait != ZILOG_CLOSING_WAIT_NONE) tty_wait_until_sent(tty, info->closing_wait); - save_flags(flags); cli(); - } /* * At this point we stop accepting input. To do this, we @@ -2017,15 +2021,10 @@ * has completely drained. */ OPNDBG("waiting end of Rx...\n"); - restore_flags(flags); rs_wait_until_sent(tty, info->timeout); - save_flags(flags); cli(); } shutdown(info); - /* restore flags now since shutdown() will have disabled this port's - specific irqs */ - restore_flags(flags); if (tty->driver.flush_buffer) tty->driver.flush_buffer(tty); @@ -2880,7 +2879,7 @@ static int __init serial_console_setup(struct console *co, char *options) { struct mac_serial *info; - int baud = 38400; + int baud = 57600; /*38400;*/ int bits = 8; int parity = 'n'; int cflag = CREAD | HUPCL | CLOCAL; diff -uNr linux-2.4.21/drivers/macintosh/mediabay.c linux-2.4.21-ben2/drivers/macintosh/mediabay.c --- linux-2.4.21/drivers/macintosh/mediabay.c 2002-02-25 20:37:58.000000000 +0100 +++ linux-2.4.21-ben2/drivers/macintosh/mediabay.c 2003-06-27 15:41:23.000000000 +0200 @@ -756,7 +756,7 @@ struct media_bay_info* bay = &media_bays[n]; if (!np->parent || np->n_addrs == 0 || !request_OF_resource(np, 0, NULL)) { np = np->next; - printk(KERN_ERR "media-bay: Can't request IO resource !\n"); + printk(KERN_ERR "mediabay: Can't request IO resource !\n"); continue; } bay->mb_type = mb_ohare; @@ -771,7 +771,7 @@ bay->mb_type = mb_ohare; bay->ops = &ohare_mb_ops; } else { - printk(KERN_ERR "mediabay: Unknown bay type !\n"); + printk(KERN_ERR "media-bay: Unknown bay type !\n"); np = np->next; continue; } @@ -782,7 +782,7 @@ MB_BIS(bay, KEYLARGO_MBCR, KL_MBCR_MB0_ENABLE); #ifdef MB_USE_INTERRUPTS if (np->n_intrs == 0) { - printk(KERN_ERR "media bay %d has no irq\n",n); + printk(KERN_ERR "media-bay %d has no irq\n",n); np = np->next; continue; } @@ -823,8 +823,9 @@ pmu_register_sleep_notifier(&mb_sleep_notifier); #endif /* CONFIG_PMAC_PBOOK */ - kernel_thread(media_bay_task, NULL, - CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + if (kernel_thread(media_bay_task, NULL, + CLONE_FS | CLONE_FILES | CLONE_SIGHAND) < 0) + printk(KERN_ERR "media-bay: Cannot create polling thread !\n"); } } diff -uNr linux-2.4.21/drivers/macintosh/therm_pismo.c linux-2.4.21-ben2/drivers/macintosh/therm_pismo.c --- linux-2.4.21/drivers/macintosh/therm_pismo.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/drivers/macintosh/therm_pismo.c 2003-06-27 15:41:10.000000000 +0200 @@ -0,0 +1,269 @@ +/* + * Device driver for the i2c thermostat found on some laptops + * + * Copyright (C) 2001 Benjamin Herrenschmidt + * + * Actually, there are 2 DS1775R1 on uninorth I2C busses + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG + +#define I2C_THERMOSTAT_ADDR 0x49 +#define I2C_THERMOSTAT_ADDR2 0x48 +#define MAX_THERMOSTATS 4 + + +MODULE_AUTHOR("Benjamin Herrenschmidt "); +MODULE_DESCRIPTION("Driver for DS1775 thermostat on Apple laptops"); +MODULE_LICENSE("GPL"); +EXPORT_NO_SYMBOLS; + +struct temp_range +{ + u8 high; /* Start the fan */ + u8 low; /* Stop the fan */ +}; + +struct apple_thermal_info { + u8 id; /* Implementation ID */ + u8 fan_count; /* Number of fans */ + u8 thermostat_count; /* Number of thermostats */ + u8 unused[5]; + struct temp_range ranges[4]; /* Temperature ranges (may be [])*/ +}; + +struct thermostat { + struct i2c_client clt; + int th_num; + // more to come ? +}; + +static struct apple_thermal_info *thinfo; +static struct thermostat* thermostats[MAX_THERMOSTATS]; +static int therm_count; + +static int attach_thermostat(struct i2c_adapter *adapter); +static int detach_thermostat(struct i2c_client *client); + +/* What is this supposed to be ? registered ? I hate + * magic numbers like that ... + */ +#define I2C_DRIVERID_THERMOSTAT (0xDEAD) + +static struct i2c_driver thermostat_driver = { + name: "Apple Thermostat", + id: I2C_DRIVERID_THERMOSTAT, + flags: I2C_DF_NOTIFY, + attach_adapter: &attach_thermostat, + detach_client: &detach_thermostat, + command: NULL, + inc_use: NULL, + dec_use: NULL +}; + +static int +write_reg(struct thermostat* th, int reg, u8* data, int len) +{ + u8 tmp[5]; + int rc; + + if (len > 4) + return -EINVAL; + tmp[0] = reg; + memcpy(&tmp[1], data, len); + rc = i2c_master_send(&th->clt, (const char *)tmp, len+1); + if (rc < 0) + return rc; + if (rc != (len+1)) + return -ENODEV; + return 0; +} + +static int +read_reg(struct thermostat* th, int reg, u8* data, int len) +{ + u8 reg_addr; + int rc; + + reg_addr = (u8)reg; + rc = i2c_master_send(&th->clt, ®_addr, 1); + if (rc < 0) + return rc; + if (rc != 1) + return -ENODEV; + rc = i2c_master_recv(&th->clt, (char *)data, len); + if (rc < 0) + return rc; + if (rc != len) + return -ENODEV; + return 0; +} + +static int +attach_one_thermostat(struct i2c_adapter *adapter, int addr, int num) +{ + struct thermostat* th; + int rc; + u16 t, tlo, thi; + u8 config; + + if (therm_count >= MAX_THERMOSTATS) { + printk(KERN_WARNING "Skipped thermostat %d (%s:%x), max count reached !\n", + num, adapter->name, addr); + return -ENODEV; + } + + th = (struct thermostat *)kmalloc(sizeof(struct thermostat), GFP_KERNEL); + if (!th) + return -ENOMEM; + th->clt.addr = addr; + th->clt.adapter = adapter; + th->clt.driver = &thermostat_driver; + th->clt.flags = 0; + th->clt.data = (void *)therm_count; + th->th_num = num; + strcpy(th->clt.name, "thermostat"); + + rc = read_reg(th, 1, &config, 1); + if (rc < 0) { + printk(KERN_ERR "Thermostat %d (%s:%x) failed to read config !\n", + num, adapter->name, addr); + kfree(th); + return -ENODEV; + } + printk(KERN_INFO "Thermostat %d (%s:%x), config: %02x\n", + num, adapter->name, addr, config); + + rc = read_reg(th, 0, (u8 *)&t, 2); + if (rc < 0) { + printk(KERN_ERR "Thermostat %d (%s:%x) failed to read temp !\n", + num, adapter->name, addr); + kfree(th); + return -ENODEV; + } + printk(KERN_INFO "Thermostat %d (%s:%x), temp: %04x (about: %d degree C)\n", + num, adapter->name, addr, t, t>>8); + + thermostats[therm_count++] = th; + + if (i2c_attach_client(&th->clt)) { + printk(KERN_ERR "Thermostat %d (%s:%x), failed to attach client !\n", + num, adapter->name, addr); + thermostats[--therm_count] = NULL; + kfree(th); + return -ENODEV; + } + + tlo = thi = 0; + rc = read_reg(th, 2, (u8 *)&tlo, 2); + if (rc < 0) { + printk(KERN_WARNING "Thermostat %d (%s:%x) failed to read low threshold !\n", + num, adapter->name, addr); + } + rc = read_reg(th, 3, (u8 *)&thi, 2); + if (rc < 0) { + printk(KERN_WARNING "Thermostat %d (%s:%x) failed to read high threshold !\n", + num, adapter->name, addr); + } + printk(KERN_INFO "Thermostat %d (%s:%x), tl: %04x (%d degree C), th: %04x (%d degree C)\n", + num, adapter->name, addr, tlo, tlo>>8, thi, thi>>8); + return 0; +} + +static int +attach_thermostat(struct i2c_adapter *adapter) +{ + unsigned long bus_no; + int rc; + + if (strncmp(adapter->name, "uni-n", 5)) + return 0; + bus_no = simple_strtoul(adapter->name + 6, NULL, 10); + rc = attach_one_thermostat(adapter, I2C_THERMOSTAT_ADDR, bus_no); + if (!rc && thinfo->thermostat_count > 2) + attach_one_thermostat(adapter, I2C_THERMOSTAT_ADDR2, bus_no+2); + + return rc; +} + +static int +detach_thermostat(struct i2c_client *client) +{ + int index = (int)client->data; + struct thermostat* th; + + if (index >= MAX_THERMOSTATS || !thermostats[index]) { + printk(KERN_ERR "Invalid client in deatch_thermostat()\n"); + return -ENODEV; + } + th = thermostats[index]; + i2c_detach_client(&th->clt); + thermostats[index] = NULL; + + kfree(th); + + return 0; +} + +static int __init +thermostat_init(void) +{ + struct device_node* np; + + if (!machine_is_compatible("PowerBook3,1")) + return -ENODEV; + + np = find_devices("power-mgt"); + if (!np) + return -ENODEV; + thinfo = (struct apple_thermal_info *)get_property(np, "thermal-info", NULL); + if (!thinfo) + return -ENODEV; + +#ifdef DEBUG + printk(KERN_DEBUG " Thermal Infos found :\n"); + printk(KERN_DEBUG " implementation id : %d\n", thinfo->id); + printk(KERN_DEBUG " fan_count : %d\n", thinfo->fan_count); + printk(KERN_DEBUG " thermostat_count : %d\n", thinfo->thermostat_count); + printk(KERN_DEBUG " ranges[0] : %d,%d\n", + thinfo->ranges[0].high, thinfo->ranges[0].low); + printk(KERN_DEBUG " ranges[1] : %d,%d\n", + thinfo->ranges[1].high, thinfo->ranges[1].low); + printk(KERN_DEBUG " ranges[2] : %d,%d\n", + thinfo->ranges[2].high, thinfo->ranges[2].low); + printk(KERN_DEBUG " ranges[3] : %d,%d\n", + thinfo->ranges[3].high, thinfo->ranges[3].low); +#endif + /* Check against titaniums & ibooks.... */ + if (thinfo->id != 1 && thinfo->id != 2) { + printk(KERN_ERR "thermostat: design id %d unknown !\n", thinfo->id); + return -ENODEV; + } + + return i2c_add_driver(&thermostat_driver); +} + +static void __exit +thermostat_exit(void) +{ + i2c_del_driver(&thermostat_driver); +} + +module_init(thermostat_init); +module_exit(thermostat_exit); diff -uNr linux-2.4.21/drivers/macintosh/via-cuda.c linux-2.4.21-ben2/drivers/macintosh/via-cuda.c --- linux-2.4.21/drivers/macintosh/via-cuda.c 2002-11-29 00:53:13.000000000 +0100 +++ linux-2.4.21-ben2/drivers/macintosh/via-cuda.c 2003-06-27 15:41:04.000000000 +0200 @@ -37,7 +37,6 @@ #ifdef CONFIG_MAC #define CUDA_IRQ IRQ_MAC_ADB #define __openfirmware -#define eieio() #else #define CUDA_IRQ vias->intrs[0].line #endif @@ -175,8 +174,8 @@ /* for us by the main VIA driver in arch/m68k/mac/via.c */ #ifndef CONFIG_MAC - via[IFR] = 0x7f; eieio(); /* clear interrupts by writing 1s */ - via[IER] = IER_SET|SR_INT; eieio(); /* enable interrupt from SR */ + out_8(&via[IFR], 0x7f); /* clear interrupts by writing 1s */ + out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */ #endif /* enable autopoll */ @@ -244,7 +243,8 @@ #endif /* CONFIG_ADB */ #define WAIT_FOR(cond, what) \ - do { \ + do { \ + int x; \ for (x = 1000; !(cond); --x) { \ if (x == 0) { \ printk("Timeout waiting for " what "\n"); \ @@ -257,40 +257,40 @@ static int cuda_init_via() { - int x; - - via[DIRB] = (via[DIRB] | TACK | TIP) & ~TREQ; /* TACK & TIP out */ - via[B] |= TACK | TIP; /* negate them */ - via[ACR] = (via[ACR] & ~SR_CTRL) | SR_EXT; /* SR data in */ - eieio(); - x = via[SR]; eieio(); /* clear any left-over data */ + out_8(&via[DIRB], (in_8(&via[DIRB]) | TACK | TIP) & ~TREQ); /* TACK & TIP out */ + out_8(&via[B], in_8(&via[B]) | TACK | TIP); /* negate them */ + out_8(&via[ACR] ,(in_8(&via[ACR]) & ~SR_CTRL) | SR_EXT); /* SR data in */ + (void)in_8(&via[SR]); /* clear any left-over data */ #ifndef CONFIG_MAC - via[IER] = 0x7f; eieio(); /* disable interrupts from VIA */ + out_8(&via[IER], 0x7f); /* disable interrupts from VIA */ + (void)in_8(&via[IER]); #endif - eieio(); /* delay 4ms and then clear any pending interrupt */ mdelay(4); - x = via[SR]; eieio(); + (void)in_8(&via[SR]); + out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); /* sync with the CUDA - assert TACK without TIP */ - via[B] &= ~TACK; eieio(); + out_8(&via[B], in_8(&via[B]) & ~TACK); /* wait for the CUDA to assert TREQ in response */ - WAIT_FOR((via[B] & TREQ) == 0, "CUDA response to sync"); + WAIT_FOR((in_8(&via[B]) & TREQ) == 0, "CUDA response to sync"); /* wait for the interrupt and then clear it */ - WAIT_FOR(via[IFR] & SR_INT, "CUDA response to sync (2)"); - x = via[SR]; eieio(); + WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (2)"); + (void)in_8(&via[SR]); + out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); /* finish the sync by negating TACK */ - via[B] |= TACK; eieio(); + out_8(&via[B], in_8(&via[B]) | TACK); /* wait for the CUDA to negate TREQ and the corresponding interrupt */ - WAIT_FOR(via[B] & TREQ, "CUDA response to sync (3)"); - WAIT_FOR(via[IFR] & SR_INT, "CUDA response to sync (4)"); - x = via[SR]; eieio(); - via[B] |= TIP; eieio(); /* should be unnecessary */ + WAIT_FOR(in_8(&via[B]) & TREQ, "CUDA response to sync (3)"); + WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (4)"); + (void)in_8(&via[SR]); + out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); + out_8(&via[B], in_8(&via[B]) | TIP); /* should be unnecessary */ return 0; } @@ -413,55 +413,59 @@ req = current_req; if (req == 0) return; - if ((via[B] & TREQ) == 0) + if ((in_8(&via[B]) & TREQ) == 0) return; /* a byte is coming in from the CUDA */ /* set the shift register to shift out and send a byte */ - via[ACR] |= SR_OUT; eieio(); - via[SR] = req->data[0]; eieio(); - via[B] &= ~TIP; + out_8(&via[ACR], in_8(&via[ACR]) | SR_OUT); + out_8(&via[SR], req->data[0]); + out_8(&via[B], in_8(&via[B]) & ~TIP); cuda_state = sent_first_byte; } void cuda_poll() { - if (via[IFR] & SR_INT) { - unsigned long flags; + unsigned long flags; - /* cuda_interrupt only takes a normal lock, we disable - * interrupts here to avoid re-entering and thus deadlocking. - * An option would be to disable only the IRQ source with - * disable_irq(), would that work on m68k ? --BenH - */ - local_irq_save(flags); - cuda_interrupt(0, 0, 0); - local_irq_restore(flags); - } + /* cuda_interrupt only takes a normal lock, we disable + * interrupts here to avoid re-entering and thus deadlocking. + * An option would be to disable only the IRQ source with + * disable_irq(), would that work on m68k ? --BenH + */ + local_irq_save(flags); + cuda_interrupt(0, 0, 0); + local_irq_restore(flags); } static void cuda_interrupt(int irq, void *arg, struct pt_regs *regs) { - int x, status; + int status; struct adb_request *req = NULL; unsigned char ibuf[16]; int ibuf_len = 0; int complete = 0; + unsigned char virq; - if ((via[IFR] & SR_INT) == 0) - return; - spin_lock(&cuda_lock); - status = (~via[B] & (TIP|TREQ)) | (via[ACR] & SR_OUT); eieio(); + + virq = in_8(&via[IFR]) & 0x7f; + out_8(&via[IFR], virq); + if ((virq & SR_INT) == 0) { + spin_unlock(&cuda_lock); + return; + } + + status = (~in_8(&via[B]) & (TIP|TREQ)) | (in_8(&via[ACR]) & SR_OUT); /* printk("cuda_interrupt: state=%d status=%x\n", cuda_state, status); */ switch (cuda_state) { case idle: /* CUDA has sent us the first byte of data - unsolicited */ if (status != TREQ) printk("cuda: state=idle, status=%x\n", status); - x = via[SR]; eieio(); - via[B] &= ~TIP; eieio(); + (void)in_8(&via[SR]); + out_8(&via[B], in_8(&via[B]) & ~TIP); cuda_state = reading; reply_ptr = cuda_rbuf; reading_reply = 0; @@ -471,8 +475,8 @@ /* CUDA has sent us the first byte of data of a reply */ if (status != TREQ) printk("cuda: state=awaiting_reply, status=%x\n", status); - x = via[SR]; eieio(); - via[B] &= ~TIP; eieio(); + (void)in_8(&via[SR]); + out_8(&via[B], in_8(&via[B]) & ~TIP); cuda_state = reading; reply_ptr = current_req->reply; reading_reply = 1; @@ -481,16 +485,16 @@ case sent_first_byte: if (status == TREQ + TIP + SR_OUT) { /* collision */ - via[ACR] &= ~SR_OUT; eieio(); - x = via[SR]; eieio(); - via[B] |= TIP | TACK; eieio(); + out_8(&via[ACR], in_8(&via[ACR]) & ~SR_OUT); + (void)in_8(&via[SR]); + out_8(&via[B], in_8(&via[B]) | TIP | TACK); cuda_state = idle; } else { /* assert status == TIP + SR_OUT */ if (status != TIP + SR_OUT) printk("cuda: state=sent_first_byte status=%x\n", status); - via[SR] = current_req->data[1]; eieio(); - via[B] ^= TACK; eieio(); + out_8(&via[SR], current_req->data[1]); + out_8(&via[B], in_8(&via[B]) ^ TACK); data_index = 2; cuda_state = sending; } @@ -499,9 +503,9 @@ case sending: req = current_req; if (data_index >= req->nbytes) { - via[ACR] &= ~SR_OUT; eieio(); - x = via[SR]; eieio(); - via[B] |= TACK | TIP; eieio(); + out_8(&via[ACR], in_8(&via[ACR]) & ~SR_OUT); + (void)in_8(&via[SR]); + out_8(&via[B], in_8(&via[B]) | TACK | TIP); req->sent = 1; if (req->reply_expected) { cuda_state = awaiting_reply; @@ -513,27 +517,27 @@ cuda_start(); } } else { - via[SR] = req->data[data_index++]; eieio(); - via[B] ^= TACK; eieio(); + out_8(&via[SR], req->data[data_index++]); + out_8(&via[B], in_8(&via[B]) ^ TACK); } break; case reading: - *reply_ptr++ = via[SR]; eieio(); + *reply_ptr++ = in_8(&via[SR]); if (status == TIP) { /* that's all folks */ - via[B] |= TACK | TIP; eieio(); + out_8(&via[B], in_8(&via[B]) | TACK | TIP); cuda_state = read_done; } else { /* assert status == TIP | TREQ */ if (status != TIP + TREQ) printk("cuda: state=reading status=%x\n", status); - via[B] ^= TACK; eieio(); + out_8(&via[B], in_8(&via[B]) ^ TACK); } break; case read_done: - x = via[SR]; eieio(); + (void)in_8(&via[SR]); if (reading_reply) { req = current_req; req->reply_len = reply_ptr - req->reply; @@ -548,7 +552,6 @@ memmove(req->reply, req->reply + 2, req->reply_len); } } - req->complete = 1; current_req = req->next; complete = 1; } else { @@ -563,7 +566,7 @@ memcpy(ibuf, cuda_rbuf, ibuf_len); } if (status == TREQ) { - via[B] &= ~TIP; eieio(); + out_8(&via[B], in_8(&via[B]) & ~TIP); cuda_state = reading; reply_ptr = cuda_rbuf; reading_reply = 0; @@ -577,8 +580,16 @@ printk("cuda_interrupt: unknown cuda_state %d?\n", cuda_state); } spin_unlock(&cuda_lock); - if (complete && req && req->done) - (*req->done)(req); + if (complete && req) { + void (*done)(struct adb_request *) = req->done; + mb(); + req->complete = 1; + /* Here, we assume that if the request has a done member, the + * struct request will survive to setting req->complete to 1 + */ + if (done) + (*done)(req); + } if (ibuf_len) cuda_input(ibuf, ibuf_len, regs); } diff -uNr linux-2.4.21/drivers/macintosh/via-pmu.c linux-2.4.21-ben2/drivers/macintosh/via-pmu.c --- linux-2.4.21/drivers/macintosh/via-pmu.c 2002-11-29 00:53:13.000000000 +0100 +++ linux-2.4.21-ben2/drivers/macintosh/via-pmu.c 2003-06-27 15:41:32.000000000 +0200 @@ -345,11 +345,6 @@ } else pmu_kind = PMU_UNKNOWN; -#ifdef CONFIG_PMAC_PBOOK - if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0) - can_sleep = 1; -#endif /* CONFIG_PMAC_PBOOK */ - via = (volatile unsigned char *) ioremap(vias->addrs->address, 0x2000); out_8(&via[IER], IER_CLR | 0x7f); /* disable all intrs */ @@ -410,6 +405,8 @@ bright_req_3.complete = 1; #ifdef CONFIG_PMAC_PBOOK batt_req.complete = 1; + if (pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,0,-1) >= 0) + can_sleep = 1; #endif if (request_irq(vias->intrs[0].line, via_pmu_interrupt, 0, "VIA-PMU", @@ -436,12 +433,20 @@ #ifdef CONFIG_PMAC_PBOOK if (machine_is_compatible("AAPL,3400/2400") || - machine_is_compatible("AAPL,3500")) + machine_is_compatible("AAPL,3500")) { + int mb = pmac_call_feature(PMAC_FTR_GET_MB_INFO, + NULL, PMAC_MB_INFO_MODEL, 0); pmu_battery_count = 1; - else if (machine_is_compatible("AAPL,PowerBook1998") || - machine_is_compatible("PowerBook1,1")) + if (mb == PMAC_TYPE_COMET) + pmu_batteries[0].flags |= PMU_BATT_TYPE_COMET; + else + pmu_batteries[0].flags |= PMU_BATT_TYPE_HOOPER; + } else if (machine_is_compatible("AAPL,PowerBook1998") || + machine_is_compatible("PowerBook1,1")) { pmu_battery_count = 2; - else { + pmu_batteries[0].flags |= PMU_BATT_TYPE_SMART; + pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART; + } else { struct device_node* prim = find_devices("power-mgt"); u32 *prim_info = NULL; if (prim) @@ -449,6 +454,9 @@ if (prim_info) { /* Other stuffs here yet unknown */ pmu_battery_count = (prim_info[6] >> 16) & 0xff; + pmu_batteries[0].flags |= PMU_BATT_TYPE_SMART; + if (pmu_battery_count > 1) + pmu_batteries[1].flags |= PMU_BATT_TYPE_SMART; } } #endif /* CONFIG_PMAC_PBOOK */ @@ -558,148 +566,12 @@ #ifdef CONFIG_PMAC_PBOOK -/* - * WARNING ! This code probably needs some debugging... -- BenH. +/* This new version of the code for 2400/3400/3500 powerbooks + * is inspired from the implementation in gkrellm-pmu */ -#ifdef NEW_OHARE_CODE -static void __pmac -done_battery_state_ohare(struct adb_request* req) -{ - unsigned int bat_flags = 0; - int current = 0; - unsigned int capa, max, voltage, time; - int lrange[] = { 0, 275, 850, 1680, 2325, - 2765, 3160, 3500, 3830, 4115, - 4360, 4585, 4795, 4990, 5170, - 5340, 5510, 5710, 5930, 6150, - 6370, 6500 - }; - - if (req->reply[0] & 0x01) - pmu_power_flags |= PMU_PWR_AC_PRESENT; - else - pmu_power_flags &= ~PMU_PWR_AC_PRESENT; - - if (req->reply[0] & 0x04) { - int vb, i, j, k, charge, pcharge; - bat_flags |= PMU_BATT_PRESENT; - vb = (req->reply[1] << 8) | req->reply[2]; - voltage = ((vb * 2650) + 726650)/100; - vb *= 100; - current = req->reply[5]; - if ((req->reply[0] & 0x01) == 0 && (current > 200)) - vb += (current - 200) * 15; - else if (req->reply[0] & 0x02) - vb = (vb - 2000); - i = (33000 - vb) / 10; - j = i - (i % 100); - k = j/100; - if (k <= 0) - charge = 0; - else if (k >= 21) - charge = 650000; - else - charge = (lrange[k + 1] - lrange[k]) * (i - j) + (lrange[k] * 100); - charge = (1000 - charge / 650) / 10; - if (req->reply[0] & 0x40) { - pcharge = (req->reply[6] << 8) + req->reply[7]; - if (pcharge > 6500) - pcharge = 6500; - pcharge *= 100; - pcharge = (1000 - pcharge / 650) / 10; - if (pcharge < charge) - charge = pcharge; - } - capa = charge; - max = 100; - time = (charge * 16440) / current; - current = -current; - - } else - capa = max = current = voltage = time = 0; - - if (req->reply[0] & 0x02) - bat_flags |= PMU_BATT_CHARGING; - - pmu_batteries[pmu_cur_battery].flags = bat_flags; - pmu_batteries[pmu_cur_battery].charge = capa; - pmu_batteries[pmu_cur_battery].max_charge = max; - pmu_batteries[pmu_cur_battery].current = current; - pmu_batteries[pmu_cur_battery].voltage = voltage; - pmu_batteries[pmu_cur_battery].time_remaining = time; -} -#else /* NEW_OHARE_CODE */ static void __pmac done_battery_state_ohare(struct adb_request* req) { - unsigned int bat_flags = 0; - int current = 0; - unsigned int capa, max, voltage, time; - int lrange[] = { 0, 275, 850, 1680, 2325, - 2765, 3160, 3500, 3830, 4115, - 4360, 4585, 4795, 4990, 5170, - 5340, 5510, 5710, 5930, 6150, - 6370, 6500 - }; - - if (req->reply[0] & 0x01) - pmu_power_flags |= PMU_PWR_AC_PRESENT; - else - pmu_power_flags &= ~PMU_PWR_AC_PRESENT; - - if (req->reply[0] & 0x04) { - int vb, i, j, charge, pcharge; - bat_flags |= PMU_BATT_PRESENT; - vb = (req->reply[1] << 8) | req->reply[2]; - voltage = ((vb * 2650) + 726650)/100; - current = *((signed char *)&req->reply[5]); - if ((req->reply[0] & 0x01) == 0 && (current > 200)) - vb += (current - 200) * 15; - else if (req->reply[0] & 0x02) - vb = (vb - 10) * 100; - i = (33000 - vb) / 10; - j = i - (i % 100); - if (j <= 0) - charge = 0; - else if (j >= 21) - charge = 650000; - else - charge = (lrange[j + 1] - lrange[j]) * (i - j) + (lrange[j] * 100); - charge = (1000 - charge / 650) / 10; - if (req->reply[0] & 0x40) { - pcharge = (req->reply[6] << 8) + req->reply[7]; - if (pcharge > 6500) - pcharge = 6500; - pcharge *= 100; - pcharge = (1000 - pcharge / 650) / 10; - if (pcharge < charge) - charge = pcharge; - } - capa = charge; - max = 100; - time = (charge * 274) / current; - current = -current; - - } else - capa = max = current = voltage = time = 0; - - if ((req->reply[0] & 0x02) && (current > 0)) - bat_flags |= PMU_BATT_CHARGING; - if (req->reply[0] & 0x04) /* CHECK THIS ONE */ - bat_flags |= PMU_BATT_PRESENT; - - pmu_batteries[pmu_cur_battery].flags = bat_flags; - pmu_batteries[pmu_cur_battery].charge = capa; - pmu_batteries[pmu_cur_battery].max_charge = max; - pmu_batteries[pmu_cur_battery].current = current; - pmu_batteries[pmu_cur_battery].voltage = voltage; - pmu_batteries[pmu_cur_battery].time_remaining = time; -} -#endif /* NEW_OHARE_CODE */ - - static void __pmac -done_battery_state_comet(struct adb_request* req) -{ /* format: * [0] : flags * 0x01 : AC indicator @@ -718,57 +590,62 @@ * [6][7] : pcharge * --tkoba */ + unsigned int bat_flags = PMU_BATT_TYPE_HOOPER; + long pcharge, charge, vb, vmax, lmax; + long vmax_charging, vmax_charged; + long current, voltage, time, max; + int mb = pmac_call_feature(PMAC_FTR_GET_MB_INFO, + NULL, PMAC_MB_INFO_MODEL, 0); - unsigned int bat_flags = 0; - int current = 0; - unsigned int max = 100; - unsigned int charge, voltage, time; - int lrange[] = { 0, 600, 750, 900, 1000, 1080, - 1180, 1250, 1300, 1340, 1360, - 1390, 1420, 1440, 1470, 1490, - 1520, 1550, 1580, 1610, 1650, - 1700 - }; - if (req->reply[0] & 0x01) pmu_power_flags |= PMU_PWR_AC_PRESENT; else pmu_power_flags &= ~PMU_PWR_AC_PRESENT; + + if (mb == PMAC_TYPE_COMET) { + vmax_charged = 189; + vmax_charging = 213; + lmax = 6500; + } else { + vmax_charged = 330; + vmax_charging = 330; + lmax = 6500; + } + vmax = vmax_charged; - if (req->reply[0] & 0x04) { /* battery exist */ - int vb, i; + /* If battery installed */ + if (req->reply[0] & 0x04) { bat_flags |= PMU_BATT_PRESENT; + if (req->reply[0] & 0x02) + bat_flags |= PMU_BATT_CHARGING; vb = (req->reply[1] << 8) | req->reply[2]; - voltage = ((vb * 2650) + 726650)/100; - vb *= 10; + voltage = (vb * 265 + 72665) / 10; current = req->reply[5]; - if ((req->reply[0] & 0x01) == 0 && (current > 200)) - vb += ((current - 200) * 3); /* vb = 500<->1800 */ - else if (req->reply[0] & 0x02) - vb = ((vb - 800) * 1700/13)/100; /* in charging vb = 1300<->2130 */ - - if (req->reply[0] & 0x20) { /* full charged */ - charge = max; - } else { - if (lrange[21] < vb) - charge = max; - else { - if (vb < lrange[1]) - charge = 0; - else { - for (i=21; vb < lrange[i]; --i); - charge = (i * 100)/21; - } - } - if (charge > max) charge = max; + if ((req->reply[0] & 0x01) == 0) { + if (current > 200) + vb += ((current - 200) * 15)/100; + } else if (req->reply[0] & 0x02) { + vb = (vb * 97) / 100; + vmax = vmax_charging; } - time = (charge * 72); + charge = (100 * vb) / vmax; + if (req->reply[0] & 0x40) { + pcharge = (req->reply[6] << 8) + req->reply[7]; + if (pcharge > lmax) + pcharge = lmax; + pcharge *= 100; + pcharge = 100 - pcharge / lmax; + if (pcharge < charge) + charge = pcharge; + } + if (current > 0) + time = (charge * 16440) / current; + else + time = 0; + max = 100; current = -current; } else - max = current = voltage = time = 0; - - if (req->reply[0] & 0x02) - bat_flags |= PMU_BATT_CHARGING; + charge = max = current = voltage = time = 0; pmu_batteries[pmu_cur_battery].flags = bat_flags; pmu_batteries[pmu_cur_battery].charge = charge; @@ -800,7 +677,7 @@ * [8][9] : voltage */ - unsigned int bat_flags = 0; + unsigned int bat_flags = PMU_BATT_TYPE_SMART; int current; unsigned int capa, max, voltage; @@ -858,17 +735,10 @@ { if (!batt_req.complete) return; - if (pmu_kind == PMU_OHARE_BASED) { - int mb = pmac_call_feature(PMAC_FTR_GET_MB_INFO, - NULL, PMAC_MB_INFO_MODEL, 0); - - if (mb == PMAC_TYPE_COMET) - pmu_request(&batt_req, done_battery_state_comet, - 1, PMU_BATTERY_STATE); - else - pmu_request(&batt_req, done_battery_state_ohare, - 1, PMU_BATTERY_STATE); - } else + if (pmu_kind == PMU_OHARE_BASED) + pmu_request(&batt_req, done_battery_state_ohare, + 1, PMU_BATTERY_STATE); + else pmu_request(&batt_req, done_battery_state_smart, 2, PMU_SMART_BATTERY_STATE, pmu_cur_battery+1); } @@ -1220,9 +1090,14 @@ static inline void pmu_done(struct adb_request *req) { + void (*done)(struct adb_request *) = req->done; + mb(); req->complete = 1; - if (req->done) - (*req->done)(req); + /* Here, we assume that if the request has a done member, the + * struct request will survive to setting req->complete to 1 + */ + if (done) + (*done)(req); } static void __openfirmware @@ -1557,7 +1432,8 @@ wait_for_ack(); send_byte(PMU_INT_ACK); adb_int_pending = 0; -no_free_slot: +no_free_slot: + ; } else if (current_req) pmu_start(); } @@ -1714,6 +1590,259 @@ return via != 0; } +struct pmu_i2c_hdr { + u8 bus; + u8 mode; + u8 bus2; + u8 address; + u8 sub_addr; + u8 comb_addr; + u8 count; +}; + +int +pmu_i2c_combined_read(int bus, int addr, int subaddr, u8* data, int len) +{ + struct adb_request req; + struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; + int retry; + int rc; + + for (retry=0; retry<16; retry++) { + memset(&req, 0, sizeof(req)); + + hdr->bus = bus; + hdr->address = addr & 0xfe; + hdr->mode = PMU_I2C_MODE_COMBINED; + hdr->bus2 = 0; + hdr->sub_addr = subaddr; + hdr->comb_addr = addr | 1; + hdr->count = len; + + req.nbytes = sizeof(struct pmu_i2c_hdr) + 1; + req.reply_expected = 0; + req.reply_len = 0; + req.data[0] = PMU_I2C_CMD; + req.reply[0] = 0xff; + rc = pmu_queue_request(&req); + if (rc) + return rc; + while(!req.complete) + pmu_poll(); + if (req.reply[0] == PMU_I2C_STATUS_OK) + break; + mdelay(15); + } + if (req.reply[0] != PMU_I2C_STATUS_OK) + return -1; + + for (retry=0; retry<16; retry++) { + memset(&req, 0, sizeof(req)); + + mdelay(15); + + hdr->bus = PMU_I2C_BUS_STATUS; + req.reply[0] = 0xff; + + req.nbytes = 2; + req.reply_expected = 0; + req.reply_len = 0; + req.data[0] = PMU_I2C_CMD; + rc = pmu_queue_request(&req); + if (rc) + return rc; + while(!req.complete) + pmu_poll(); + if (req.reply[0] == PMU_I2C_STATUS_DATAREAD) { + memcpy(data, &req.reply[1], req.reply_len - 1); + return req.reply_len - 1; + } + } + return -1; +} + +int +pmu_i2c_stdsub_write(int bus, int addr, int subaddr, u8* data, int len) +{ + struct adb_request req; + struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; + int retry; + int rc; + + for (retry=0; retry<16; retry++) { + memset(&req, 0, sizeof(req)); + + hdr->bus = bus; + hdr->address = addr & 0xfe; + hdr->mode = PMU_I2C_MODE_STDSUB; + hdr->bus2 = 0; + hdr->sub_addr = subaddr; + hdr->comb_addr = addr & 0xfe; + hdr->count = len; + + req.data[0] = PMU_I2C_CMD; + memcpy(&req.data[sizeof(struct pmu_i2c_hdr) + 1], data, len); + req.nbytes = sizeof(struct pmu_i2c_hdr) + len + 1; + req.reply_expected = 0; + req.reply_len = 0; + req.reply[0] = 0xff; + rc = pmu_queue_request(&req); + if (rc) + return rc; + while(!req.complete) + pmu_poll(); + if (req.reply[0] == PMU_I2C_STATUS_OK) + break; + mdelay(15); + } + if (req.reply[0] != PMU_I2C_STATUS_OK) + return -1; + + for (retry=0; retry<16; retry++) { + memset(&req, 0, sizeof(req)); + + mdelay(15); + + hdr->bus = PMU_I2C_BUS_STATUS; + req.reply[0] = 0xff; + + req.nbytes = 2; + req.reply_expected = 0; + req.reply_len = 0; + req.data[0] = PMU_I2C_CMD; + rc = pmu_queue_request(&req); + if (rc) + return rc; + while(!req.complete) + pmu_poll(); + if (req.reply[0] == PMU_I2C_STATUS_OK) + return len; + } + return -1; +} + +int +pmu_i2c_simple_read(int bus, int addr, u8* data, int len) +{ + struct adb_request req; + struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; + int retry; + int rc; + + for (retry=0; retry<16; retry++) { + memset(&req, 0, sizeof(req)); + + hdr->bus = bus; + hdr->address = addr | 1; + hdr->mode = PMU_I2C_MODE_SIMPLE; + hdr->bus2 = 0; + hdr->sub_addr = 0; + hdr->comb_addr = 0; + hdr->count = len; + + req.data[0] = PMU_I2C_CMD; + req.nbytes = sizeof(struct pmu_i2c_hdr) + 1; + req.reply_expected = 0; + req.reply_len = 0; + req.reply[0] = 0xff; + rc = pmu_queue_request(&req); + if (rc) + return rc; + while(!req.complete) + pmu_poll(); + if (req.reply[0] == PMU_I2C_STATUS_OK) + break; + mdelay(15); + } + if (req.reply[0] != PMU_I2C_STATUS_OK) + return -1; + + for (retry=0; retry<16; retry++) { + memset(&req, 0, sizeof(req)); + + mdelay(15); + + hdr->bus = PMU_I2C_BUS_STATUS; + req.reply[0] = 0xff; + + req.nbytes = 2; + req.reply_expected = 0; + req.reply_len = 0; + req.data[0] = PMU_I2C_CMD; + rc = pmu_queue_request(&req); + if (rc) + return rc; + while(!req.complete) + pmu_poll(); + if (req.reply[0] == PMU_I2C_STATUS_DATAREAD) { + memcpy(data, &req.reply[1], req.reply_len - 1); + return req.reply_len - 1; + } + } + return -1; +} + +int +pmu_i2c_simple_write(int bus, int addr, u8* data, int len) +{ + struct adb_request req; + struct pmu_i2c_hdr *hdr = (struct pmu_i2c_hdr *)&req.data[1]; + int retry; + int rc; + + for (retry=0; retry<16; retry++) { + memset(&req, 0, sizeof(req)); + + hdr->bus = bus; + hdr->address = addr & 0xfe; + hdr->mode = PMU_I2C_MODE_SIMPLE; + hdr->bus2 = 0; + hdr->sub_addr = 0; + hdr->comb_addr = 0; + hdr->count = len; + + req.data[0] = PMU_I2C_CMD; + memcpy(&req.data[sizeof(struct pmu_i2c_hdr) + 1], data, len); + req.nbytes = sizeof(struct pmu_i2c_hdr) + len + 1; + req.reply_expected = 0; + req.reply_len = 0; + req.reply[0] = 0xff; + rc = pmu_queue_request(&req); + if (rc) + return rc; + while(!req.complete) + pmu_poll(); + if (req.reply[0] == PMU_I2C_STATUS_OK) + break; + mdelay(15); + } + if (req.reply[0] != PMU_I2C_STATUS_OK) + return -1; + + for (retry=0; retry<16; retry++) { + memset(&req, 0, sizeof(req)); + + mdelay(15); + + hdr->bus = PMU_I2C_BUS_STATUS; + req.reply[0] = 0xff; + + req.nbytes = 2; + req.reply_expected = 0; + req.reply_len = 0; + req.data[0] = PMU_I2C_CMD; + rc = pmu_queue_request(&req); + if (rc) + return rc; + while(!req.complete) + pmu_poll(); + if (req.reply[0] == PMU_I2C_STATUS_OK) + return len; + } + return -1; +} + + #if defined(DEBUG_SLEEP) || defined(DEBUG_FREQ) /* N.B. This doesn't work on the 3400 */ void @@ -2794,6 +2923,10 @@ EXPORT_SYMBOL(pmu_poll); EXPORT_SYMBOL(pmu_suspend); EXPORT_SYMBOL(pmu_resume); +EXPORT_SYMBOL(pmu_i2c_combined_read); +EXPORT_SYMBOL(pmu_i2c_stdsub_write); +EXPORT_SYMBOL(pmu_i2c_simple_read); +EXPORT_SYMBOL(pmu_i2c_simple_write); #ifdef CONFIG_PMAC_PBOOK EXPORT_SYMBOL(pmu_register_sleep_notifier); EXPORT_SYMBOL(pmu_unregister_sleep_notifier); diff -uNr linux-2.4.21/drivers/net/Makefile linux-2.4.21-ben2/drivers/net/Makefile --- linux-2.4.21/drivers/net/Makefile 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/Makefile 2003-06-27 15:41:09.000000000 +0200 @@ -17,7 +17,7 @@ export-objs := 8390.o arlan.o aironet4500_core.o aironet4500_card.o \ ppp_async.o ppp_generic.o slhc.o pppox.o auto_irq.o \ - net_init.o mii.o + net_init.o mii.o sungem_phy.o list-multi := rcpci.o rcpci-objs := rcpci45.o rclanmtl.o @@ -59,7 +59,7 @@ obj-$(CONFIG_SUNQE) += sunqe.o obj-$(CONFIG_SUNBMAC) += sunbmac.o obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o -obj-$(CONFIG_SUNGEM) += sungem.o +obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o obj-$(CONFIG_MACE) += mace.o obj-$(CONFIG_BMAC) += bmac.o diff -uNr linux-2.4.21/drivers/net/bmac.c linux-2.4.21-ben2/drivers/net/bmac.c --- linux-2.4.21/drivers/net/bmac.c 2003-06-13 16:51:34.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/bmac.c 2003-06-27 15:41:07.000000000 +0200 @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -67,7 +69,6 @@ volatile struct dbdma_cmd *tx_cmds; /* xmit dma command list */ volatile struct dbdma_cmd *rx_cmds; /* recv dma command list */ struct device_node *node; - int is_bmac_plus; struct sk_buff *rx_bufs[N_RX_RING]; int rx_fill; int rx_empty; @@ -80,6 +81,8 @@ int timeout_active; int sleeping; int opened; + int is_bmac_plus; + u32 device_id; unsigned short hash_use_count[64]; unsigned short hash_table_mask[4]; struct net_device *next_bmac; @@ -153,6 +156,7 @@ static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev); static struct net_device_stats *bmac_stats(struct net_device *dev); static void bmac_set_multicast(struct net_device *dev); +static int bmac_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); static void bmac_reset_and_enable(struct net_device *dev); static void bmac_start_chip(struct net_device *dev); static void bmac_init_chip(struct net_device *dev); @@ -1053,7 +1057,7 @@ { struct dev_mc_list *dmi = dev->mc_list; char *addrs; - int i, j, bit, byte; + int i; unsigned short rx_cfg; u32 crc; @@ -1189,7 +1193,7 @@ read_srom(struct net_device *dev, unsigned int addr, unsigned int addr_len) { unsigned short data, val; - int i; + unsigned int i; /* send out the address we want to read from */ for (i = 0; i < addr_len; i++) { @@ -1303,6 +1307,7 @@ struct bmac_data *bp; unsigned char *addr; struct net_device *dev; + u32 *deviceid; if (bmac->n_addrs != 3 || bmac->n_intrs != 3) { printk(KERN_ERR "can't use BMAC %s: need 3 addrs and 3 intrs\n", @@ -1356,6 +1361,10 @@ goto err_out; dev->irq = bmac->intrs[0].line; + deviceid = (u32 *)get_property(bmac, "device-id", NULL); + if (deviceid) + bp->device_id = *deviceid; + bmac_enable_and_reset_chip(dev); bmwrite(dev, INTDISABLE, DisableAll); @@ -1378,6 +1387,7 @@ dev->get_stats = bmac_stats; dev->set_multicast_list = bmac_set_multicast; dev->set_mac_address = bmac_set_address; + dev->do_ioctl = bmac_do_ioctl; bmac_get_station_address(dev, addr); if (bmac_verify_checksum(dev) != 0) @@ -1451,6 +1461,56 @@ kfree(dev); } +static int bmac_ethtool_ioctl(struct net_device *dev, void *useraddr) +{ + struct bmac_data *bp = (struct bmac_data *) dev->priv; + u32 ethcmd; + + if (get_user(ethcmd, (u32 *)useraddr)) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; + strcpy (info.driver, "bmac"); + info.version[0] = '\0'; + snprintf(info.fw_version, 31, "chip id %x", bp->device_id); + if (copy_to_user (useraddr, &info, sizeof (info))) + return -EFAULT; + return 0; + } + + case ETHTOOL_GSET: + case ETHTOOL_SSET: + case ETHTOOL_NWAY_RST: + case ETHTOOL_GLINK: + case ETHTOOL_GMSGLVL: + case ETHTOOL_SMSGLVL: + default: + ; + } + + return -EOPNOTSUPP; +} + +static int bmac_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + switch(cmd) { + case SIOCETHTOOL: + return bmac_ethtool_ioctl(dev, (void *) ifr->ifr_data); + + case SIOCGMIIPHY: + case SIOCDEVPRIVATE: + case SIOCGMIIREG: + case SIOCDEVPRIVATE+1: + case SIOCSMIIREG: + case SIOCDEVPRIVATE+2: + default: + ; + } + return -EOPNOTSUPP; +} + static int bmac_open(struct net_device *dev) { struct bmac_data *bp = (struct bmac_data *) dev->priv; diff -uNr linux-2.4.21/drivers/net/gmac.c linux-2.4.21-ben2/drivers/net/gmac.c --- linux-2.4.21/drivers/net/gmac.c 2002-11-29 00:53:13.000000000 +0100 +++ linux-2.4.21-ben2/drivers/net/gmac.c 2003-06-27 15:41:09.000000000 +0200 @@ -1622,6 +1622,7 @@ gm->of_node = gmac; if (!request_OF_resource(gmac, 0, " (gmac)")) { printk(KERN_ERR "GMAC: can't request IO resource !\n"); + gm->of_node = NULL; goto out_unreg; } dev->base_addr = gmac->addrs[0].address; diff -uNr linux-2.4.21/drivers/net/irda/irda-usb.c linux-2.4.21-ben2/drivers/net/irda/irda-usb.c --- linux-2.4.21/drivers/net/irda/irda-usb.c 2002-11-29 00:53:13.000000000 +0100 +++ linux-2.4.21-ben2/drivers/net/irda/irda-usb.c 2003-06-27 15:41:10.000000000 +0200 @@ -1392,6 +1392,9 @@ WARNING("usb-irda: bad class_descriptor type\n"); } else { + le16_to_cpus (&(desc->wBaudRate)); + le16_to_cpus (&(desc->bcdSpecRevision)); + #ifdef IU_DUMP_CLASS_DESC irda_usb_dump_class_desc(desc); #endif /* IU_DUMP_CLASS_DESC */ diff -uNr linux-2.4.21/drivers/net/mace.c linux-2.4.21-ben2/drivers/net/mace.c --- linux-2.4.21/drivers/net/mace.c 2002-08-03 02:39:44.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/mace.c 2003-06-27 15:41:20.000000000 +0200 @@ -1,8 +1,12 @@ /* * Network device driver for the MACE ethernet controller on * Apple Powermacs. Assumes it's under a DBDMA controller. + * + * MACE is beleived to be an AMD 79C940 * * Copyright (C) 1996 Paul Mackerras. + * + * TODO: Use a spinlock for smp safety (backport 2.5 version ?) */ #include @@ -16,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -82,7 +88,10 @@ static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev); static struct net_device_stats *mace_stats(struct net_device *dev); static void mace_set_multicast(struct net_device *dev); +static int mace_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); +static int mace_ethtool_ioctl(struct net_device *dev, void *useraddr); static void mace_reset(struct net_device *dev); +static void mace_restart(struct net_device *dev); static int mace_set_address(struct net_device *dev, void *addr); static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs); @@ -226,6 +235,7 @@ dev->get_stats = mace_stats; dev->set_multicast_list = mace_set_multicast; dev->set_mac_address = mace_set_address; + dev->do_ioctl = mace_do_ioctl; ether_setup(dev); @@ -362,6 +372,90 @@ return 0; } +static int mace_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + switch(cmd) { + case SIOCETHTOOL: + return mace_ethtool_ioctl(dev, (void *) ifr->ifr_data); + + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */ + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCDEVPRIVATE+1: /* for binary compat, remove in 2.5 */ + case SIOCSMIIREG: /* Write MII PHY register. */ + case SIOCDEVPRIVATE+2: /* for binary compat, remove in 2.5 */ + default: + return -EOPNOTSUPP; + } +} + +static int mace_ethtool_ioctl(struct net_device *dev, void *useraddr) +{ + struct mace_data *mp = (struct mace_data *) dev->priv; + u32 ethcmd; + + if (get_user(ethcmd, (u32 *)useraddr)) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info = { .cmd = ETHTOOL_GDRVINFO }; + struct mace_data *mp = dev->priv; + strcpy (info.driver, "mace"); + info.version[0] = '\0'; + snprintf(info.fw_version, 31, "chip revision %d.%d", mp->chipid >> 8, mp->chipid & 0xff); + if (copy_to_user (useraddr, &info, sizeof (info))) + return -EFAULT; + return 0; + } + case ETHTOOL_GSET: { + struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET }; + + cmd.supported = SUPPORTED_10baseT_Half | + SUPPORTED_AUI | + SUPPORTED_MII; + cmd.advertising = SUPPORTED_10baseT_Half; + cmd.port = mp->port_aaui ? PORT_AUI : PORT_MII; + cmd.speed = SPEED_10; + if (copy_to_user(useraddr, &cmd, sizeof(cmd))) + return -EFAULT; + return 0; + } + case ETHTOOL_SSET: { + struct ethtool_cmd cmd; + + if (copy_from_user(&cmd, useraddr, sizeof(cmd))) + return -EFAULT; + + if (cmd.autoneg != AUTONEG_DISABLE) + return -EINVAL; + if (cmd.speed != SPEED_10) + return -EINVAL; + if ((cmd.port == PORT_AUI) != mp->port_aaui) { + int aaui = (cmd.port == PORT_AUI); + unsigned long flags; + + printk("%s: switching port to: %s\n", + dev->name, aaui ? "AAUI" : "MII"); + mp->port_aaui = aaui; + save_flags(flags); + cli(); + mace_restart(dev); + restore_flags(flags); + } + return 0; + } + case ETHTOOL_NWAY_RST: + case ETHTOOL_GLINK: + case ETHTOOL_GMSGLVL: + case ETHTOOL_SMSGLVL: + default: + break; + } + + return -EOPNOTSUPP; +} + static int mace_open(struct net_device *dev) { struct mace_data *mp = (struct mace_data *) dev->priv; @@ -473,10 +567,7 @@ static inline void mace_set_timeout(struct net_device *dev) { struct mace_data *mp = (struct mace_data *) dev->priv; - unsigned long flags; - save_flags(flags); - cli(); if (mp->timeout_active) del_timer(&mp->tx_timeout); mp->tx_timeout.expires = jiffies + TX_TIMEOUT; @@ -484,7 +575,6 @@ mp->tx_timeout.data = (unsigned long) dev; add_timer(&mp->tx_timeout); mp->timeout_active = 1; - restore_flags(flags); } static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev) @@ -763,31 +853,17 @@ } } -static void mace_tx_timeout(unsigned long data) +static void mace_restart(struct net_device *dev) { - struct net_device *dev = (struct net_device *) data; struct mace_data *mp = (struct mace_data *) dev->priv; volatile struct mace *mb = mp->mace; volatile struct dbdma_regs *td = mp->tx_dma; volatile struct dbdma_regs *rd = mp->rx_dma; volatile struct dbdma_cmd *cp; - unsigned long flags; int i; - save_flags(flags); - cli(); - mp->timeout_active = 0; - if (mp->tx_active == 0 && !mp->tx_bad_runt) - goto out; - - /* update various counters */ - mace_handle_misc_intrs(mp, in_8(&mb->ir)); - - cp = mp->tx_cmds + NCMDS_TX * mp->tx_empty; - /* turn off both tx and rx and reset the chip */ out_8(&mb->maccc, 0); - printk(KERN_ERR "mace: transmit timeout - resetting\n"); dbdma_reset(td); mace_reset(dev); @@ -825,7 +901,29 @@ /* turn it back on */ out_8(&mb->imr, RCVINT); out_8(&mb->maccc, mp->maccc); +} + +static void mace_tx_timeout(unsigned long data) +{ + struct net_device *dev = (struct net_device *) data; + struct mace_data *mp = (struct mace_data *) dev->priv; + volatile struct mace *mb = mp->mace; + unsigned long flags; + + save_flags(flags); + cli(); + mp->timeout_active = 0; + if (mp->tx_active == 0 && !mp->tx_bad_runt) + goto out; + + /* update various counters */ + mace_handle_misc_intrs(mp, in_8(&mb->ir)); + + printk(KERN_ERR "mace: transmit timeout - resetting\n"); + /* Kick chip */ + mace_restart(dev); + out: restore_flags(flags); } diff -uNr linux-2.4.21/drivers/net/ne2k-pci.c linux-2.4.21-ben2/drivers/net/ne2k-pci.c --- linux-2.4.21/drivers/net/ne2k-pci.c 2002-08-03 02:39:44.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/ne2k-pci.c 2003-06-27 15:41:07.000000000 +0200 @@ -69,8 +69,6 @@ #if defined(__powerpc__) #define inl_le(addr) le32_to_cpu(inl(addr)) #define inw_le(addr) le16_to_cpu(inw(addr)) -#define insl insl_ns -#define outsl outsl_ns #endif #define PFX DRV_NAME ": " diff -uNr linux-2.4.21/drivers/net/pcnet32.c linux-2.4.21-ben2/drivers/net/pcnet32.c --- linux-2.4.21/drivers/net/pcnet32.c 2003-06-13 16:51:35.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/pcnet32.c 2003-06-27 15:41:24.000000000 +0200 @@ -569,7 +569,7 @@ break; case 0x2625: chipname = "PCnet/FAST III 79C973"; /* PCI */ - fdx = 1; mii = 1; + fdx = 1; mii = 1; fset = 1; break; case 0x2626: chipname = "PCnet/Home 79C978"; /* PCI */ @@ -612,6 +612,7 @@ if(fset) { + printk(KERN_INFO PFX "Activating Tx error recovery on %s\n", chipname); a->write_bcr(ioaddr, 18, (a->read_bcr(ioaddr, 18) | 0x0800)); a->write_csr(ioaddr, 80, (a->read_csr(ioaddr, 80) & 0x0C00) | 0x0c00); dxsuflo = 1; diff -uNr linux-2.4.21/drivers/net/sungem.c linux-2.4.21-ben2/drivers/net/sungem.c --- linux-2.4.21/drivers/net/sungem.c 2002-08-03 02:39:44.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/sungem.c 2003-06-27 15:41:20.000000000 +0200 @@ -10,10 +10,6 @@ * - Get rid of all those nasty mdelay's and replace them * with schedule_timeout. * - Implement WOL - * - Currently, forced Gb mode is only supported on bcm54xx - * PHY for which I use the SPD2 bit of the control register. - * On m1011 PHY, I can't force as I don't have the specs, but - * I can at least detect gigabit with autoneg. */ #include @@ -63,12 +59,20 @@ #include #endif +#include "sungem_phy.h" #include "sungem.h" +/* Stripping FCS is causing problems, disabled for now */ +#undef STRIP_FCS + #define DEFAULT_MSG (NETIF_MSG_DRV | \ NETIF_MSG_PROBE | \ NETIF_MSG_LINK) +#define ADVERTISE_MASK (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \ + SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \ + SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full) + #define DRV_NAME "sungem" #define DRV_VERSION "0.97" #define DRV_RELDATE "3/20/02" @@ -83,21 +87,14 @@ MODULE_PARM(gem_debug, "i"); MODULE_PARM_DESC(gem_debug, "bitmapped message enable number"); -MODULE_PARM(link_mode, "i"); -MODULE_PARM_DESC(link_mode, "default link mode"); +MODULE_PARM(forced_speed, "i"); +MODULE_PARM(forced_duplex, "i"); +MODULE_PARM_DESC(forced_speed, "force link speed (10,100,1000)"); +MODULE_PARM_DESC(forced_duplex, "force link duplex (0: half, 1: full)"); int gem_debug = -1; -static int link_mode; - -static u16 link_modes[] __devinitdata = { - BMCR_ANENABLE, /* 0 : autoneg */ - 0, /* 1 : 10bt half duplex */ - BMCR_SPEED100, /* 2 : 100bt half duplex */ - BMCR_SPD2, /* bcm54xx only */ /* 3 : 1000bt half duplex */ - BMCR_FULLDPLX, /* 4 : 10bt full duplex */ - BMCR_SPEED100|BMCR_FULLDPLX, /* 5 : 100bt full duplex */ - BMCR_SPD2|BMCR_FULLDPLX /* 6 : 1000bt full duplex */ -}; +static int forced_speed = -1; +static int forced_duplex = -1; #define GEM_MODULE_NAME "gem" #define PFX GEM_MODULE_NAME ": " @@ -119,12 +116,14 @@ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_GMACP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_GMAC2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, {0, } }; MODULE_DEVICE_TABLE(pci, gem_pci_tbl); -static u16 __phy_read(struct gem *gp, int reg, int phy_addr) +static u16 __phy_read(struct gem *gp, int phy_addr, int reg) { u32 cmd; int limit = 10000; @@ -150,12 +149,18 @@ return cmd & MIF_FRAME_DATA; } +static inline int _phy_read(struct net_device *dev, int mii_id, int reg) +{ + struct gem *gp = dev->priv; + return __phy_read(gp, mii_id, reg); +} + static inline u16 phy_read(struct gem *gp, int reg) { - return __phy_read(gp, reg, gp->mii_phy_addr); + return __phy_read(gp, gp->mii_phy_addr, reg); } -static void __phy_write(struct gem *gp, int reg, u16 val, int phy_addr) +static void __phy_write(struct gem *gp, int phy_addr, int reg, u16 val) { u32 cmd; int limit = 10000; @@ -177,9 +182,15 @@ } } +static inline void _phy_write(struct net_device *dev, int mii_id, int reg, int val) +{ + struct gem *gp = dev->priv; + __phy_write(gp, mii_id, reg, val & 0xffff); +} + static inline void phy_write(struct gem *gp, int reg, u16 val) { - __phy_write(gp, reg, val, gp->mii_phy_addr); + __phy_write(gp, gp->mii_phy_addr, reg, val); } static void gem_handle_mif_event(struct gem *gp, u32 reg_val, u32 changed_bits) @@ -228,10 +239,11 @@ if (pcs_miistat & PCS_MIISTAT_LS) { printk(KERN_INFO "%s: PCS link is now up.\n", dev->name); + netif_carrier_on(gp->dev); } else { printk(KERN_INFO "%s: PCS link is now down.\n", dev->name); - + netif_carrier_off(gp->dev); /* If this happens and the link timer is not running, * reset so we re-negotiate. */ @@ -359,6 +371,7 @@ rxd->status_word = cpu_to_le64(RXDCTRL_FRESH(gp)); } + mb(); gp->rx_new = gp->rx_old = 0; /* Now we must reprogram the rest of RX unit. */ @@ -667,6 +680,7 @@ count = 0; } } + mb(); if (kick >= 0) writel(kick, gp->regs + RXDMA_KICK); } @@ -936,6 +950,7 @@ if (netif_msg_tx_queued(gp)) printk(KERN_DEBUG "%s: tx queued, slot %d, skblen %d\n", dev->name, entry, skb->len); + mb(); writel(gp->tx_new, gp->regs + TXDMA_KICK); spin_unlock_irq(&gp->lock); @@ -1003,7 +1018,7 @@ } while (val & (GREG_SWRST_TXRST | GREG_SWRST_RXRST)); if (limit <= 0) - printk(KERN_ERR "gem: SW reset is ghetto.\n"); + printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name); } /* Must be invoked under gp->lock. */ @@ -1030,136 +1045,118 @@ } -/* Link modes of the BCM5400 PHY */ -static int phy_BCM5400_link_table[8][3] = { - { 0, 0, 0 }, /* No link */ - { 0, 0, 0 }, /* 10BT Half Duplex */ - { 1, 0, 0 }, /* 10BT Full Duplex */ - { 0, 1, 0 }, /* 100BT Half Duplex */ - { 0, 1, 0 }, /* 100BT Half Duplex */ - { 1, 1, 0 }, /* 100BT Full Duplex*/ - { 1, 0, 1 }, /* 1000BT */ - { 1, 0, 1 }, /* 1000BT */ -}; /* Must be invoked under gp->lock. */ +// XXX dbl check what that function should do when called on PCS PHY static void gem_begin_auto_negotiation(struct gem *gp, struct ethtool_cmd *ep) { - u16 ctl; + u32 advertise, features; + int autoneg; + int speed; + int duplex; + + if (gp->phy_type != phy_mii_mdio0 && + gp->phy_type != phy_mii_mdio1) + goto non_mii; + + /* Setup advertise */ + if (found_mii_phy(gp)) + features = gp->phy_mii.def->features; + else + features = 0; + + advertise = features & ADVERTISE_MASK; + if (gp->phy_mii.advertising != 0) + advertise &= gp->phy_mii.advertising; + + autoneg = gp->want_autoneg; + speed = gp->phy_mii.speed; + duplex = gp->phy_mii.duplex; /* Setup link parameters */ if (!ep) goto start_aneg; if (ep->autoneg == AUTONEG_ENABLE) { - /* TODO: parse ep->advertising */ - gp->link_advertise |= (ADVERTISE_10HALF | ADVERTISE_10FULL); - gp->link_advertise |= (ADVERTISE_100HALF | ADVERTISE_100FULL); - /* Can I advertise gigabit here ? I'd need BCM PHY docs... */ - gp->link_cntl = BMCR_ANENABLE; + advertise = ep->advertising; + autoneg = 1; } else { - gp->link_cntl = 0; - if (ep->speed == SPEED_100) - gp->link_cntl |= BMCR_SPEED100; - else if (ep->speed == SPEED_1000 && gp->gigabit_capable) - /* Hrm... check if this is right... */ - gp->link_cntl |= BMCR_SPD2; - if (ep->duplex == DUPLEX_FULL) - gp->link_cntl |= BMCR_FULLDPLX; + autoneg = 0; + speed = ep->speed; + duplex = ep->duplex; } start_aneg: - if (!gp->hw_running) + /* Sanitize settings based on PHY capabilities */ + if ((features & SUPPORTED_Autoneg) == 0) + autoneg = 0; + if (speed == SPEED_1000 && + !(features & (SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full))) + speed = SPEED_100; + if (speed == SPEED_100 && + !(features & (SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full))) + speed = SPEED_10; + if (duplex == DUPLEX_FULL && + !(features & (SUPPORTED_1000baseT_Full | + SUPPORTED_100baseT_Full | + SUPPORTED_10baseT_Full))) + duplex = DUPLEX_HALF; + if (speed == 0) + speed = SPEED_10; + + /* If HW is down, we don't try to actually setup the PHY, we + * just store the settings + */ + if (!gp->hw_running) { + gp->phy_mii.autoneg = gp->want_autoneg = autoneg; + gp->phy_mii.speed = speed; + gp->phy_mii.duplex = duplex; return; + } /* Configure PHY & start aneg */ - ctl = phy_read(gp, MII_BMCR); - ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE); - ctl |= gp->link_cntl; - if (ctl & BMCR_ANENABLE) { - ctl |= BMCR_ANRESTART; + gp->want_autoneg = autoneg; + if (autoneg) { + if (found_mii_phy(gp)) + gp->phy_mii.def->ops->setup_aneg(&gp->phy_mii, advertise); gp->lstate = link_aneg; } else { + if (found_mii_phy(gp)) + gp->phy_mii.def->ops->setup_forced(&gp->phy_mii, speed, duplex); gp->lstate = link_force_ok; } - phy_write(gp, MII_BMCR, ctl); +non_mii: gp->timer_ticks = 0; mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10)); } -/* Must be invoked under gp->lock. */ -static void gem_read_mii_link_mode(struct gem *gp, int *fd, int *spd, int *pause) -{ - u32 val; - - *fd = 0; - *spd = 10; - *pause = 0; - - if (gp->phy_mod == phymod_bcm5400 || - gp->phy_mod == phymod_bcm5401 || - gp->phy_mod == phymod_bcm5411) { - int link_mode; - - val = phy_read(gp, MII_BCM5400_AUXSTATUS); - link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >> - MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT); - *fd = phy_BCM5400_link_table[link_mode][0]; - *spd = phy_BCM5400_link_table[link_mode][2] ? - 1000 : - (phy_BCM5400_link_table[link_mode][1] ? 100 : 10); - val = phy_read(gp, MII_LPA); - if (val & LPA_PAUSE) - *pause = 1; - } else { - val = phy_read(gp, MII_LPA); - - if (val & (LPA_10FULL | LPA_100FULL)) - *fd = 1; - if (val & (LPA_100FULL | LPA_100HALF)) - *spd = 100; - - if (gp->phy_mod == phymod_m1011) { - val = phy_read(gp, 0x0a); - if (val & 0xc00) - *spd = 1000; - if (val & 0x800) - *fd = 1; - } - } -} - /* A link-up condition has occurred, initialize and enable the * rest of the chip. * * Must be invoked under gp->lock. */ -static void gem_set_link_modes(struct gem *gp) +static int gem_set_link_modes(struct gem *gp) { u32 val; int full_duplex, speed, pause; full_duplex = 0; - speed = 10; + speed = SPEED_10; pause = 0; - if (gp->phy_type == phy_mii_mdio0 || - gp->phy_type == phy_mii_mdio1) { - val = phy_read(gp, MII_BMCR); - if (val & BMCR_ANENABLE) - gem_read_mii_link_mode(gp, &full_duplex, &speed, &pause); - else { - if (val & BMCR_FULLDPLX) - full_duplex = 1; - if (val & BMCR_SPEED100) - speed = 100; - } - } else { + if (found_mii_phy(gp)) { + if (gp->phy_mii.def->ops->read_link(&gp->phy_mii)) + return 1; + full_duplex = (gp->phy_mii.duplex == DUPLEX_FULL); + speed = gp->phy_mii.speed; + pause = gp->phy_mii.pause; + } else if (gp->phy_type == phy_serialink || + gp->phy_type == phy_serdes) { u32 pcs_lpa = readl(gp->regs + PCS_MIILP); if (pcs_lpa & PCS_MIIADV_FD) full_duplex = 1; - speed = 1000; + speed = SPEED_1000; } if (netif_msg_link(gp)) @@ -1183,7 +1180,7 @@ val |= MAC_XIFCFG_FLED; } - if (speed == 1000) + if (speed == SPEED_1000) val |= (MAC_XIFCFG_GMII); writel(val, gp->regs + MAC_XIFCFG); @@ -1191,7 +1188,7 @@ /* If gigabit and half-duplex, enable carrier extension * mode. Else, disable it. */ - if (speed == 1000 && !full_duplex) { + if (speed == SPEED_1000 && !full_duplex) { val = readl(gp->regs + MAC_TXCFG); writel(val | MAC_TXCFG_TCE, gp->regs + MAC_TXCFG); @@ -1239,50 +1236,51 @@ writel(val, gp->regs + MAC_MCCFG); gem_start_dma(gp); + + return 0; } /* Must be invoked under gp->lock. */ static int gem_mdio_link_not_up(struct gem *gp) { - u16 val; - - if (gp->lstate == link_force_ret) { + switch (gp->lstate) { + case link_force_ret: if (netif_msg_link(gp)) printk(KERN_INFO "%s: Autoneg failed again, keeping" " forced mode\n", gp->dev->name); - phy_write(gp, MII_BMCR, gp->link_fcntl); + gp->phy_mii.def->ops->setup_forced(&gp->phy_mii, + gp->last_forced_speed, DUPLEX_HALF); gp->timer_ticks = 5; gp->lstate = link_force_ok; - } else if (gp->lstate == link_aneg) { - val = phy_read(gp, MII_BMCR); - + return 0; + case link_aneg: if (netif_msg_link(gp)) printk(KERN_INFO "%s: switching to forced 100bt\n", gp->dev->name); /* Try forced modes. */ - val &= ~(BMCR_ANRESTART | BMCR_ANENABLE); - val &= ~(BMCR_FULLDPLX); - val |= BMCR_SPEED100; - phy_write(gp, MII_BMCR, val); + gp->phy_mii.def->ops->setup_forced(&gp->phy_mii, SPEED_100, + DUPLEX_HALF); gp->timer_ticks = 5; gp->lstate = link_force_try; - } else { + return 0; + case link_force_try: /* Downgrade from 100 to 10 Mbps if necessary. * If already at 10Mbps, warn user about the * situation every 10 ticks. */ - val = phy_read(gp, MII_BMCR); - if (val & BMCR_SPEED100) { - val &= ~BMCR_SPEED100; - phy_write(gp, MII_BMCR, val); + if (gp->phy_mii.speed == SPEED_100) { + gp->phy_mii.def->ops->setup_forced(&gp->phy_mii, SPEED_10, + DUPLEX_HALF); gp->timer_ticks = 5; if (netif_msg_link(gp)) printk(KERN_INFO "%s: switching to forced 10bt\n", gp->dev->name); + return 0; } else return 1; + default: + return 0; } - return 0; } static void gem_init_rings(struct gem *); @@ -1322,7 +1320,8 @@ static void gem_link_timer(unsigned long data) { struct gem *gp = (struct gem *) data; - + int restart_aneg = 0; + if (!gp->hw_running) return; @@ -1334,62 +1333,8 @@ if (gp->reset_task_pending) goto restart; - if (gp->phy_type == phy_mii_mdio0 || - gp->phy_type == phy_mii_mdio1) { - u16 val = phy_read(gp, MII_BMSR); - u16 cntl = phy_read(gp, MII_BMCR); - int up; - - /* When using autoneg, we really wait for ANEGCOMPLETE or we may - * get a "transcient" incorrect link state - */ - if (cntl & BMCR_ANENABLE) - up = (val & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS); - else - up = (val & BMSR_LSTATUS) != 0; - if (up) { - /* Ok, here we got a link. If we had it due to a forced - * fallback, and we were configured for autoneg, we do - * retry a short autoneg pass. If you know your hub is - * broken, use ethtool ;) - */ - if (gp->lstate == link_force_try && (gp->link_cntl & BMCR_ANENABLE)) { - gp->lstate = link_force_ret; - gp->link_fcntl = phy_read(gp, MII_BMCR); - gp->timer_ticks = 5; - if (netif_msg_link(gp)) - printk(KERN_INFO "%s: Got link after fallback, retrying" - " autoneg once...\n", gp->dev->name); - phy_write(gp, MII_BMCR, - gp->link_fcntl | BMCR_ANENABLE | BMCR_ANRESTART); - } else if (gp->lstate != link_up) { - gp->lstate = link_up; - if (gp->opened) - gem_set_link_modes(gp); - } - } else { - int restart = 0; - - /* If the link was previously up, we restart the - * whole process - */ - if (gp->lstate == link_up) { - gp->lstate = link_down; - if (netif_msg_link(gp)) - printk(KERN_INFO "%s: Link down\n", - gp->dev->name); - gp->reset_task_pending = 2; - schedule_task(&gp->reset_task); - restart = 1; - } else if (++gp->timer_ticks > 10) - restart = gem_mdio_link_not_up(gp); - - if (restart) { - gem_begin_auto_negotiation(gp, NULL); - goto out_unlock; - } - } - } else { + if (gp->phy_type == phy_serialink || + gp->phy_type == phy_serdes) { u32 val = readl(gp->regs + PCS_MIISTAT); if (!(val & PCS_MIISTAT_LS)) @@ -1397,11 +1342,56 @@ if ((val & PCS_MIISTAT_LS) != 0) { gp->lstate = link_up; + netif_carrier_on(gp->dev); if (gp->opened) - gem_set_link_modes(gp); + (void)gem_set_link_modes(gp); } + goto restart; + } + if (found_mii_phy(gp) && gp->phy_mii.def->ops->poll_link(&gp->phy_mii)) { + /* Ok, here we got a link. If we had it due to a forced + * fallback, and we were configured for autoneg, we do + * retry a short autoneg pass. If you know your hub is + * broken, use ethtool ;) + */ + if (gp->lstate == link_force_try && gp->want_autoneg) { + gp->lstate = link_force_ret; + gp->last_forced_speed = gp->phy_mii.speed; + gp->timer_ticks = 5; + if (netif_msg_link(gp)) + printk(KERN_INFO "%s: Got link after fallback, retrying" + " autoneg once...\n", gp->dev->name); + gp->phy_mii.def->ops->setup_aneg(&gp->phy_mii, gp->phy_mii.advertising); + } else if (gp->lstate != link_up) { + gp->lstate = link_up; + netif_carrier_on(gp->dev); + if (gp->opened && gem_set_link_modes(gp)) + restart_aneg = 1; + } + } else { + /* If the link was previously up, we restart the + * whole process + */ + if (gp->lstate == link_up) { + gp->lstate = link_down; + if (netif_msg_link(gp)) + printk(KERN_INFO "%s: Link down\n", + gp->dev->name); + netif_carrier_off(gp->dev); + gp->reset_task_pending = 2; + schedule_task(&gp->reset_task); + restart_aneg = 1; + } else if (++gp->timer_ticks > 10) { + if (found_mii_phy(gp)) + restart_aneg = gem_mdio_link_not_up(gp); + else + restart_aneg = 1; + } + } + if (restart_aneg) { + gem_begin_auto_negotiation(gp, NULL); + goto out_unlock; } - restart: mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10)); out_unlock: @@ -1501,153 +1491,14 @@ txd->control_word = 0; txd->buffer = 0; } -} - -/* Must be invoked under gp->lock. */ -static int gem_reset_one_mii_phy(struct gem *gp, int phy_addr) -{ - u16 val; - int limit = 10000; - - val = __phy_read(gp, MII_BMCR, phy_addr); - val &= ~BMCR_ISOLATE; - val |= BMCR_RESET; - __phy_write(gp, MII_BMCR, val, phy_addr); - - udelay(100); - - while (limit--) { - val = __phy_read(gp, MII_BMCR, phy_addr); - if ((val & BMCR_RESET) == 0) - break; - udelay(10); - } - if ((val & BMCR_ISOLATE) && limit > 0) - __phy_write(gp, MII_BMCR, val & ~BMCR_ISOLATE, phy_addr); - - return (limit <= 0); -} - -/* Must be invoked under gp->lock. */ -static void gem_init_bcm5201_phy(struct gem *gp) -{ - u16 data; - - data = phy_read(gp, MII_BCM5201_MULTIPHY); - data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE; - phy_write(gp, MII_BCM5201_MULTIPHY, data); -} - -/* Must be invoked under gp->lock. */ -static void gem_init_bcm5400_phy(struct gem *gp) -{ - u16 data; - - /* Configure for gigabit full duplex */ - data = phy_read(gp, MII_BCM5400_AUXCONTROL); - data |= MII_BCM5400_AUXCONTROL_PWR10BASET; - phy_write(gp, MII_BCM5400_AUXCONTROL, data); - - data = phy_read(gp, MII_BCM5400_GB_CONTROL); - data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP; - phy_write(gp, MII_BCM5400_GB_CONTROL, data); - - mdelay(10); - - /* Reset and configure cascaded 10/100 PHY */ - gem_reset_one_mii_phy(gp, 0x1f); - - data = __phy_read(gp, MII_BCM5201_MULTIPHY, 0x1f); - data |= MII_BCM5201_MULTIPHY_SERIALMODE; - __phy_write(gp, MII_BCM5201_MULTIPHY, data, 0x1f); - - data = phy_read(gp, MII_BCM5400_AUXCONTROL); - data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET; - phy_write(gp, MII_BCM5400_AUXCONTROL, data); -} - -/* Must be invoked under gp->lock. */ -static void gem_init_bcm5401_phy(struct gem *gp) -{ - u16 data; - int rev; - - rev = phy_read(gp, MII_PHYSID2) & 0x000f; - if (rev == 0 || rev == 3) { - /* Some revisions of 5401 appear to need this - * initialisation sequence to disable, according - * to OF, "tap power management" - * - * WARNING ! OF and Darwin don't agree on the - * register addresses. OF seem to interpret the - * register numbers below as decimal - * - * Note: This should (and does) match tg3_init_5401phy_dsp - * in the tg3.c driver. -DaveM - */ - phy_write(gp, 0x18, 0x0c20); - phy_write(gp, 0x17, 0x0012); - phy_write(gp, 0x15, 0x1804); - phy_write(gp, 0x17, 0x0013); - phy_write(gp, 0x15, 0x1204); - phy_write(gp, 0x17, 0x8006); - phy_write(gp, 0x15, 0x0132); - phy_write(gp, 0x17, 0x8006); - phy_write(gp, 0x15, 0x0232); - phy_write(gp, 0x17, 0x201f); - phy_write(gp, 0x15, 0x0a20); - } - - /* Configure for gigabit full duplex */ - data = phy_read(gp, MII_BCM5400_GB_CONTROL); - data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP; - phy_write(gp, MII_BCM5400_GB_CONTROL, data); - - mdelay(1); - - /* Reset and configure cascaded 10/100 PHY */ - gem_reset_one_mii_phy(gp, 0x1f); - - data = __phy_read(gp, MII_BCM5201_MULTIPHY, 0x1f); - data |= MII_BCM5201_MULTIPHY_SERIALMODE; - __phy_write(gp, MII_BCM5201_MULTIPHY, data, 0x1f); -} - -/* Must be invoked under gp->lock. */ -static void gem_init_bcm5411_phy(struct gem *gp) -{ - u16 data; - - /* Here's some more Apple black magic to setup - * some voltage stuffs. - */ - phy_write(gp, 0x1c, 0x8c23); - phy_write(gp, 0x1c, 0x8ca3); - phy_write(gp, 0x1c, 0x8c23); - - /* Here, Apple seems to want to reset it, do - * it as well - */ - phy_write(gp, MII_BMCR, BMCR_RESET); - - /* Start autoneg */ - phy_write(gp, MII_BMCR, - (BMCR_ANENABLE | BMCR_FULLDPLX | - BMCR_ANRESTART | BMCR_SPD2)); - - data = phy_read(gp, MII_BCM5400_GB_CONTROL); - data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP; - phy_write(gp, MII_BCM5400_GB_CONTROL, data); + mb(); } /* Must be invoked under gp->lock. */ static void gem_init_phy(struct gem *gp) { u32 mifcfg; - - if (!gp->wake_on_lan && gp->phy_mod == phymod_bcm5201) - phy_write(gp, MII_BCM5201_INTERRUPT, 0); - + /* Revert MIF CFG setting done on stop_phy */ mifcfg = readl(gp->regs + MIF_CFG); mifcfg &= ~MIF_CFG_BBMODE; @@ -1655,19 +1506,37 @@ #ifdef CONFIG_ALL_PPC if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) { - int i; + int i, j; + /* Those delay sucks, the HW seem to love them though, I'll + * serisouly consider breaking some locks here to be able + * to schedule instead + */ pmac_call_feature(PMAC_FTR_GMAC_PHY_RESET, gp->of_node, 0, 0); - for (i = 0; i < 32; i++) { - gp->mii_phy_addr = i; - if (phy_read(gp, MII_BMCR) != 0xffff) + mdelay(10); + for (j = 0; j < 3; j++) { + /* Some PHYs used by apple have problem getting back to us, + * we _know_ it's actually at addr 0, that's a hack, but + * it helps to do that reset now. I suspect some motherboards + * don't wire the PHY reset line properly, thus the PHY doesn't + * come back with the above pmac_call_feature. + */ + gp->mii_phy_addr = 0; + phy_write(gp, MII_BMCR, BMCR_RESET); + /* We should probably break some locks here and schedule... */ + mdelay(10); + for (i = 0; i < 32; i++) { + gp->mii_phy_addr = i; + if (phy_read(gp, MII_BMCR) != 0xffff) + break; + } + if (i == 32) { + printk(KERN_WARNING "%s: GMAC PHY not responding !\n", + gp->dev->name); + gp->mii_phy_addr = 0; + } else break; } - if (i == 32) { - printk(KERN_WARNING "%s: GMAC PHY not responding !\n", - gp->dev->name); - return; - } } #endif /* CONFIG_ALL_PPC */ @@ -1690,79 +1559,12 @@ if (gp->phy_type == phy_mii_mdio0 || gp->phy_type == phy_mii_mdio1) { - u32 phy_id; - u16 val; - - /* Take PHY out of isloate mode and reset it. */ - gem_reset_one_mii_phy(gp, gp->mii_phy_addr); - - phy_id = (phy_read(gp, MII_PHYSID1) << 16 | phy_read(gp, MII_PHYSID2)) - & 0xfffffff0; - printk(KERN_INFO "%s: MII PHY ID: %x ", gp->dev->name, phy_id); - switch(phy_id) { - case 0x406210: - gp->phy_mod = phymod_bcm5201; - gem_init_bcm5201_phy(gp); - printk("BCM 5201\n"); - break; - - case 0x4061e0: - printk("BCM 5221\n"); - gp->phy_mod = phymod_bcm5221; - break; - - case 0x206040: - printk("BCM 5400\n"); - gp->phy_mod = phymod_bcm5400; - gem_init_bcm5400_phy(gp); - gp->gigabit_capable = 1; - break; - - case 0x206050: - printk("BCM 5401\n"); - gp->phy_mod = phymod_bcm5401; - gem_init_bcm5401_phy(gp); - gp->gigabit_capable = 1; - break; - - case 0x206070: - printk("BCM 5411\n"); - gp->phy_mod = phymod_bcm5411; - gem_init_bcm5411_phy(gp); - gp->gigabit_capable = 1; - break; - case 0x1410c60: - printk("M1011 (Marvel ?)\n"); - gp->phy_mod = phymod_m1011; - gp->gigabit_capable = 1; - break; - - case 0x18074c0: - printk("Lucent\n"); - gp->phy_mod = phymod_generic; - break; - - case 0x437420: - printk("Enable Semiconductor\n"); - gp->phy_mod = phymod_generic; - break; - - default: - printk("Unknown (Using generic mode)\n"); - gp->phy_mod = phymod_generic; - break; - }; + // XXX check for errors + mii_phy_probe(&gp->phy_mii, gp->mii_phy_addr); - /* Init advertisement and enable autonegotiation. */ - val = phy_read(gp, MII_BMCR); - val &= ~BMCR_ANENABLE; - phy_write(gp, MII_BMCR, val); - udelay(10); - - phy_write(gp, MII_ADVERTISE, - phy_read(gp, MII_ADVERTISE) | - (ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL)); + /* Init PHY */ + if (gp->phy_mii.def && gp->phy_mii.def->ops->init) + gp->phy_mii.def->ops->init(&gp->phy_mii); } else { u32 val; int limit; @@ -1819,13 +1621,7 @@ else val |= PCS_SCTRL_LOOP; writel(val, gp->regs + PCS_SCTRL); - gp->gigabit_capable = 1; } - - /* BMCR_SPD2 is a broadcom 54xx specific thing afaik */ - if (gp->phy_mod != phymod_bcm5400 && gp->phy_mod != phymod_bcm5401 && - gp->phy_mod != phymod_bcm5411) - gp->link_cntl &= ~BMCR_SPD2; } /* Must be invoked under gp->lock. */ @@ -1914,9 +1710,7 @@ { unsigned char *e = &gp->dev->dev_addr[0]; - if (gp->pdev->vendor == PCI_VENDOR_ID_SUN && - gp->pdev->device == PCI_DEVICE_ID_SUN_GEM) - writel(0x1bf0, gp->regs + MAC_SNDPAUSE); + writel(0x1bf0, gp->regs + MAC_SNDPAUSE); writel(0x00, gp->regs + MAC_IPG0); writel(0x08, gp->regs + MAC_IPG1); @@ -1953,7 +1747,9 @@ writel(0, gp->regs + MAC_AF0MSK); gp->mac_rx_cfg = gem_setup_multicast(gp); - +#ifdef STRIP_FCS + gp->mac_rx_cfg |= MAC_RXCFG_SFCS; +#endif writel(0, gp->regs + MAC_NCOLL); writel(0, gp->regs + MAC_FASUCC); writel(0, gp->regs + MAC_ECOLL); @@ -2129,12 +1925,15 @@ /* Default aneg parameters */ gp->timer_ticks = 0; gp->lstate = link_down; + netif_carrier_off(gp->dev); /* Can I advertise gigabit here ? I'd need BCM PHY docs... */ gem_begin_auto_negotiation(gp, NULL); } else { - if (gp->lstate == link_up) + if (gp->lstate == link_up) { + netif_carrier_on(gp->dev); gem_set_link_modes(gp); + } } } @@ -2184,9 +1983,6 @@ { u32 mifcfg; - if (!gp->wake_on_lan && gp->phy_mod == phymod_bcm5201) - phy_write(gp, MII_BCM5201_INTERRUPT, 0); - /* Make sure we aren't polling PHY status change. We * don't currently use that feature though */ @@ -2194,9 +1990,6 @@ mifcfg &= ~MIF_CFG_POLL; writel(mifcfg, gp->regs + MIF_CFG); - /* Here's a strange hack used by both MacOS 9 and X */ - phy_write(gp, MII_LPA, phy_read(gp, MII_LPA)); - if (gp->wake_on_lan) { /* Setup wake-on-lan */ } else @@ -2210,21 +2003,12 @@ gem_stop(gp); writel(MAC_TXRST_CMD, gp->regs + MAC_TXRST); writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST); - if (gp->phy_mod == phymod_bcm5400 || gp->phy_mod == phymod_bcm5401 || - gp->phy_mod == phymod_bcm5411) { -#if 0 /* Commented out in Darwin... someone has those dawn docs ? */ - phy_write(gp, MII_BMCR, BMCR_PDOWN); -#endif - } else if (gp->phy_mod == phymod_bcm5201 || gp->phy_mod == phymod_bcm5221) { -#if 0 /* Commented out in Darwin... someone has those dawn docs ? */ - u16 val = phy_read(gp, MII_BCM5201_AUXMODE2) - phy_write(gp, MII_BCM5201_AUXMODE2, - val & ~MII_BCM5201_AUXMODE2_LOWPOWER); -#endif - phy_write(gp, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE); - } else if (gp->phy_mod == phymod_m1011) - phy_write(gp, MII_BMCR, BMCR_PDOWN); + } + if (found_mii_phy(gp) && gp->phy_mii.def->ops->suspend) + gp->phy_mii.def->ops->suspend(&gp->phy_mii, 0 /* wake on lan options */); + + if (!gp->wake_on_lan) { /* According to Apple, we must set the MDIO pins to this begnign * state or we may 1) eat more current, 2) damage some PHYs */ @@ -2526,7 +2310,11 @@ netif_stop_queue(dev); rxcfg = readl(gp->regs + MAC_RXCFG); - gp->mac_rx_cfg = rxcfg_new = gem_setup_multicast(gp); + rxcfg_new = gem_setup_multicast(gp); +#ifdef STRIP_FCS + rxcfg_new |= MAC_RXCFG_SFCS; +#endif + gp->mac_rx_cfg = rxcfg_new; writel(rxcfg & ~MAC_RXCFG_ENAB, gp->regs + MAC_RXCFG); while (readl(gp->regs + MAC_RXCFG) & MAC_RXCFG_ENAB) { @@ -2551,8 +2339,6 @@ static int gem_ethtool_ioctl(struct net_device *dev, void *ep_user) { struct gem *gp = dev->priv; - u16 bmcr; - int full_duplex, speed, pause; struct ethtool_cmd ecmd; if (copy_from_user(&ecmd, ep_user, sizeof(ecmd))) @@ -2560,7 +2346,7 @@ switch(ecmd.cmd) { case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = { cmd: ETHTOOL_GDRVINFO }; + struct ethtool_drvinfo info = { .cmd = ETHTOOL_GDRVINFO }; strncpy(info.driver, DRV_NAME, ETHTOOL_BUSINFO_LEN); strncpy(info.version, DRV_VERSION, ETHTOOL_BUSINFO_LEN); @@ -2575,41 +2361,36 @@ } case ETHTOOL_GSET: - ecmd.supported = + if (gp->phy_type == phy_mii_mdio0 || + gp->phy_type == phy_mii_mdio1) { + if (gp->phy_mii.def) + ecmd.supported = gp->phy_mii.def->features; + else + ecmd.supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full; + + /* XXX hardcoded stuff for now */ + ecmd.port = PORT_MII; + ecmd.transceiver = XCVR_EXTERNAL; + ecmd.phy_address = 0; /* XXX fixed PHYAD */ + + /* Return current PHY settings */ + spin_lock_irq(&gp->lock); + ecmd.autoneg = gp->want_autoneg; + ecmd.speed = gp->phy_mii.speed; + ecmd.duplex = gp->phy_mii.duplex; + ecmd.advertising = gp->phy_mii.advertising; + /* If we started with a forced mode, we don't have a default + * advertise set, we need to return something sensible so + * userland can re-enable autoneg properly */ + if (ecmd.advertising == 0) + ecmd.advertising = ecmd.supported; + spin_unlock_irq(&gp->lock); + } else { // XXX PCS ? + ecmd.supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | - SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII); - - if (gp->gigabit_capable) - ecmd.supported |= - (SUPPORTED_1000baseT_Half | - SUPPORTED_1000baseT_Full); - - /* XXX hardcoded stuff for now */ - ecmd.port = PORT_MII; - ecmd.transceiver = XCVR_EXTERNAL; - ecmd.phy_address = 0; /* XXX fixed PHYAD */ - - /* Record PHY settings if HW is on. */ - spin_lock_irq(&gp->lock); - if (gp->hw_running) { - bmcr = phy_read(gp, MII_BMCR); - gem_read_mii_link_mode(gp, &full_duplex, &speed, &pause); - } else - bmcr = 0; - spin_unlock_irq(&gp->lock); - if (bmcr & BMCR_ANENABLE) { - ecmd.autoneg = AUTONEG_ENABLE; - ecmd.speed = speed == 10 ? SPEED_10 : (speed == 1000 ? SPEED_1000 : SPEED_100); - ecmd.duplex = full_duplex ? DUPLEX_FULL : DUPLEX_HALF; - } else { - ecmd.autoneg = AUTONEG_DISABLE; - ecmd.speed = - (bmcr & BMCR_SPEED100) ? - SPEED_100 : SPEED_10; - ecmd.duplex = - (bmcr & BMCR_FULLDPLX) ? - DUPLEX_FULL : DUPLEX_HALF; + SUPPORTED_Autoneg); + ecmd.advertising = ecmd.supported; } if (copy_to_user(ep_user, &ecmd, sizeof(ecmd))) return -EFAULT; @@ -2624,13 +2405,18 @@ ecmd.autoneg != AUTONEG_DISABLE) return -EINVAL; + if (ecmd.autoneg == AUTONEG_ENABLE && + ecmd.advertising == 0) + return -EINVAL; + if (ecmd.autoneg == AUTONEG_DISABLE && - ((ecmd.speed != SPEED_100 && + ((ecmd.speed != SPEED_1000 && + ecmd.speed != SPEED_100 && ecmd.speed != SPEED_10) || (ecmd.duplex != DUPLEX_HALF && ecmd.duplex != DUPLEX_FULL))) return -EINVAL; - + /* Apply settings and restart link process. */ spin_lock_irq(&gp->lock); gem_begin_auto_negotiation(gp, &ecmd); @@ -2639,7 +2425,7 @@ return 0; case ETHTOOL_NWAY_RST: - if ((gp->link_cntl & BMCR_ANENABLE) == 0) + if (!gp->want_autoneg) return -EINVAL; /* Restart link process. */ @@ -2655,7 +2441,7 @@ /* get link status */ case ETHTOOL_GLINK: { - struct ethtool_value edata = { cmd: ETHTOOL_GLINK }; + struct ethtool_value edata = { .cmd = ETHTOOL_GLINK }; edata.data = (gp->lstate == link_up); if (copy_to_user(ep_user, &edata, sizeof(edata))) @@ -2665,7 +2451,7 @@ /* get message-level */ case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = { cmd: ETHTOOL_GMSGLVL }; + struct ethtool_value edata = { .cmd = ETHTOOL_GMSGLVL }; edata.data = gp->msg_enable; if (copy_to_user(ep_user, &edata, sizeof(edata))) @@ -2743,15 +2529,21 @@ /* Fallthrough... */ case SIOCGMIIREG: /* Read MII PHY register. */ - data->val_out = __phy_read(gp, data->reg_num & 0x1f, data->phy_id & 0x1f); - rc = 0; + if (!gp->hw_running) + rc = -EIO; + else { + data->val_out = __phy_read(gp, data->phy_id & 0x1f, data->reg_num & 0x1f); + rc = 0; + } break; case SIOCSMIIREG: /* Write MII PHY register. */ - if (!capable(CAP_NET_ADMIN)) { + if (!capable(CAP_NET_ADMIN)) rc = -EPERM; - } else { - __phy_write(gp, data->reg_num & 0x1f, data->val_in, data->phy_id & 0x1f); + else if (!gp->hw_running) + rc = -EIO; + else { + __phy_write(gp, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in); rc = 0; } break; @@ -2897,7 +2689,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); @@ -2953,13 +2745,9 @@ INIT_TQUEUE(&gp->pm_task, gem_pm_task, gp); INIT_TQUEUE(&gp->reset_task, gem_reset_task, gp); - /* Default link parameters */ - if (link_mode >= 0 && link_mode <= 6) - gp->link_cntl = link_modes[link_mode]; - else - gp->link_cntl = BMCR_ANENABLE; gp->lstate = link_down; gp->timer_ticks = 0; + netif_carrier_off(dev); gp->regs = (unsigned long) ioremap(gemreg_base, gemreg_len); if (gp->regs == 0UL) { @@ -2980,15 +2768,33 @@ gem_stop(gp); spin_unlock_irq(&gp->lock); + /* Fill up the mii_phy structure (even if we won't use it) */ + gp->phy_mii.dev = dev; + gp->phy_mii.mdio_read = _phy_read; + gp->phy_mii.mdio_write = _phy_write; + + /* Default link parameters */ + if (forced_speed != -1 && + forced_speed != SPEED_10 && + forced_speed != SPEED_100 && + forced_speed != SPEED_1000) { + forced_speed = -1; + printk(KERN_WARNING "forced_speed argument invalid, reverting to autoneg\n"); + } + if (forced_speed < SPEED_10) + gp->want_autoneg = 1; + else { + gp->want_autoneg = 0; + gp->phy_mii.speed = forced_speed; + if (forced_duplex > 0) + gp->phy_mii.duplex = DUPLEX_FULL; + else + gp->phy_mii.duplex = DUPLEX_HALF; + } + if (gem_check_invariants(gp)) goto err_out_iounmap; - spin_lock_irq(&gp->lock); - gp->hw_running = 1; - gem_init_phy(gp); - gem_begin_auto_negotiation(gp, NULL); - spin_unlock_irq(&gp->lock); - /* It is guarenteed that the returned buffer will be at least * PAGE_SIZE aligned. */ @@ -3015,12 +2821,23 @@ printk(KERN_INFO "%s: Sun GEM (PCI) 10/100/1000BaseT Ethernet ", dev->name); - for (i = 0; i < 6; i++) printk("%2.2x%c", dev->dev_addr[i], i == 5 ? ' ' : ':'); printk("\n"); + /* Detect & init PHY, start autoneg */ + spin_lock_irq(&gp->lock); + gp->hw_running = 1; + gem_init_phy(gp); + gem_begin_auto_negotiation(gp, NULL); + spin_unlock_irq(&gp->lock); + + if (gp->phy_type == phy_mii_mdio0 || + gp->phy_type == phy_mii_mdio1) + printk(KERN_INFO "%s: Found %s PHY\n", dev->name, + gp->phy_mii.def ? gp->phy_mii.def->name : "no"); + pci_set_drvdata(pdev, dev); dev->open = gem_open; diff -uNr linux-2.4.21/drivers/net/sungem.h linux-2.4.21-ben2/drivers/net/sungem.h --- linux-2.4.21/drivers/net/sungem.h 2002-08-03 02:39:44.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/sungem.h 2003-06-27 15:41:08.000000000 +0200 @@ -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) | \ @@ -936,16 +936,6 @@ phy_serdes, }; -enum gem_phy_model { - phymod_generic, - phymod_bcm5201, - phymod_bcm5221, - phymod_bcm5400, - phymod_bcm5401, - phymod_bcm5411, - phymod_m1011, -}; - enum link_state { link_down = 0, /* No link, will retry */ link_aneg, /* Autoneg in progress */ @@ -980,21 +970,20 @@ struct net_device_stats net_stats; enum gem_phy_type phy_type; - enum gem_phy_model phy_mod; + struct mii_phy phy_mii; + int tx_fifo_sz; int rx_fifo_sz; int rx_pause_off; int rx_pause_on; int mii_phy_addr; - int gigabit_capable; u32 mac_rx_cfg; u32 swrst_base; /* Autoneg & PHY control */ - int link_cntl; - int link_advertise; - int link_fcntl; + int want_autoneg; + int last_forced_speed; enum link_state lstate; struct timer_list link_timer; int timer_ticks; @@ -1014,6 +1003,9 @@ #endif }; +#define found_mii_phy(gp) ((gp->phy_type == phy_mii_mdio0 || gp->phy_type == phy_mii_mdio1) \ + && gp->phy_mii.def && gp->phy_mii.def->ops) + #define ALIGNED_RX_SKB_ADDR(addr) \ ((((unsigned long)(addr) + (64UL - 1UL)) & ~(64UL - 1UL)) - (unsigned long)(addr)) static __inline__ struct sk_buff *gem_alloc_skb(int size, int gfp_flags) diff -uNr linux-2.4.21/drivers/net/sungem_phy.c linux-2.4.21-ben2/drivers/net/sungem_phy.c --- linux-2.4.21/drivers/net/sungem_phy.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/drivers/net/sungem_phy.c 2003-06-27 15:41:50.000000000 +0200 @@ -0,0 +1,838 @@ +/* + * PHY drivers for the sungem ethernet driver. + * + * This file could be shared with other drivers. + * + * (c) 2002, Benjamin Herrenscmidt (benh@kernel.crashing.org) + * + * TODO: + * - Implement WOL + * - Add support for PHYs that provide an IRQ line + * - Eventually moved the entire polling state machine in + * there (out of the eth driver), so that it can easily be + * skipped on PHYs that implement it in hardware. + * - On LXT971 & BCM5201, Apple uses some chip specific regs + * to read the link status. Figure out why and if it makes + * sense to do the same (magic aneg ?) + * - Apple has some additional power management code for some + * Broadcom PHYs that they "hide" from the OpenSource version + * of darwin, still need to reverse engineer that + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sungem_phy.h" + +/* Link modes of the BCM5400 PHY */ +static int phy_BCM5400_link_table[8][3] = { + { 0, 0, 0 }, /* No link */ + { 0, 0, 0 }, /* 10BT Half Duplex */ + { 1, 0, 0 }, /* 10BT Full Duplex */ + { 0, 1, 0 }, /* 100BT Half Duplex */ + { 0, 1, 0 }, /* 100BT Half Duplex */ + { 1, 1, 0 }, /* 100BT Full Duplex*/ + { 1, 0, 1 }, /* 1000BT */ + { 1, 0, 1 }, /* 1000BT */ +}; + +static inline int __phy_read(struct mii_phy* phy, int id, int reg) +{ + return phy->mdio_read(phy->dev, id, reg); +} + +static inline void __phy_write(struct mii_phy* phy, int id, int reg, int val) +{ + phy->mdio_write(phy->dev, id, reg, val); +} + +static inline int phy_read(struct mii_phy* phy, int reg) +{ + return phy->mdio_read(phy->dev, phy->mii_id, reg); +} + +static inline void phy_write(struct mii_phy* phy, int reg, int val) +{ + phy->mdio_write(phy->dev, phy->mii_id, reg, val); +} + +static int reset_one_mii_phy(struct mii_phy* phy, int phy_id) +{ + u16 val; + int limit = 10000; + + val = __phy_read(phy, phy_id, MII_BMCR); + val &= ~BMCR_ISOLATE; + val |= BMCR_RESET; + __phy_write(phy, phy_id, MII_BMCR, val); + + udelay(100); + + while (limit--) { + val = __phy_read(phy, phy_id, MII_BMCR); + if ((val & BMCR_RESET) == 0) + break; + udelay(10); + } + if ((val & BMCR_ISOLATE) && limit > 0) + __phy_write(phy, phy_id, MII_BMCR, val & ~BMCR_ISOLATE); + + return (limit <= 0); +} + +static int bcm5201_init(struct mii_phy* phy) +{ + u16 data; + + data = phy_read(phy, MII_BCM5201_MULTIPHY); + data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE; + phy_write(phy, MII_BCM5201_MULTIPHY, data); + + return 0; +} + +static int bcm5201_suspend(struct mii_phy* phy, int wol_options) +{ + if (!wol_options) + phy_write(phy, MII_BCM5201_INTERRUPT, 0); + + /* Here's a strange hack used by both MacOS 9 and X */ + phy_write(phy, MII_LPA, phy_read(phy, MII_LPA)); + + if (!wol_options) { +#if 0 /* Commented out in Darwin... someone has those dawn docs ? */ + u16 val = phy_read(phy, MII_BCM5201_AUXMODE2) + phy_write(phy, MII_BCM5201_AUXMODE2, + val & ~MII_BCM5201_AUXMODE2_LOWPOWER); +#endif + phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE); + } + + return 0; +} + +static int bcm5221_init(struct mii_phy* phy) +{ + u16 data; + + data = phy_read(phy, MII_BCM5221_TEST); + phy_write(phy, MII_BCM5221_TEST, + data | MII_BCM5221_TEST_ENABLE_SHADOWS); + + data = phy_read(phy, MII_BCM5221_SHDOW_AUX_STAT2); + phy_write(phy, MII_BCM5221_SHDOW_AUX_STAT2, + data | MII_BCM5221_SHDOW_AUX_STAT2_APD); + + data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4); + phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4, + data | MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR); + + data = phy_read(phy, MII_BCM5221_TEST); + phy_write(phy, MII_BCM5221_TEST, + data & ~MII_BCM5221_TEST_ENABLE_SHADOWS); + + return 0; +} + +static int bcm5400_init(struct mii_phy* phy) +{ + u16 data; + + /* Configure for gigabit full duplex */ + data = phy_read(phy, MII_BCM5400_AUXCONTROL); + data |= MII_BCM5400_AUXCONTROL_PWR10BASET; + phy_write(phy, MII_BCM5400_AUXCONTROL, data); + + data = phy_read(phy, MII_BCM5400_GB_CONTROL); + data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP; + phy_write(phy, MII_BCM5400_GB_CONTROL, data); + + mdelay(10); + + /* Reset and configure cascaded 10/100 PHY */ + (void)reset_one_mii_phy(phy, 0x1f); + + data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY); + data |= MII_BCM5201_MULTIPHY_SERIALMODE; + __phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data); + + data = phy_read(phy, MII_BCM5400_AUXCONTROL); + data &= ~MII_BCM5400_AUXCONTROL_PWR10BASET; + phy_write(phy, MII_BCM5400_AUXCONTROL, data); + + return 0; +} + +static int bcm5400_suspend(struct mii_phy* phy, int wol_options) +{ +#if 0 /* Commented out in Darwin... someone has those dawn docs ? */ + phy_write(phy, MII_BMCR, BMCR_PDOWN); +#endif + return 0; +} + +static int bcm5401_init(struct mii_phy* phy) +{ + u16 data; + int rev; + + rev = phy_read(phy, MII_PHYSID2) & 0x000f; + if (rev == 0 || rev == 3) { + /* Some revisions of 5401 appear to need this + * initialisation sequence to disable, according + * to OF, "tap power management" + * + * WARNING ! OF and Darwin don't agree on the + * register addresses. OF seem to interpret the + * register numbers below as decimal + * + * Note: This should (and does) match tg3_init_5401phy_dsp + * in the tg3.c driver. -DaveM + */ + phy_write(phy, 0x18, 0x0c20); + phy_write(phy, 0x17, 0x0012); + phy_write(phy, 0x15, 0x1804); + phy_write(phy, 0x17, 0x0013); + phy_write(phy, 0x15, 0x1204); + phy_write(phy, 0x17, 0x8006); + phy_write(phy, 0x15, 0x0132); + phy_write(phy, 0x17, 0x8006); + phy_write(phy, 0x15, 0x0232); + phy_write(phy, 0x17, 0x201f); + phy_write(phy, 0x15, 0x0a20); + } + + /* Configure for gigabit full duplex */ + data = phy_read(phy, MII_BCM5400_GB_CONTROL); + data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP; + phy_write(phy, MII_BCM5400_GB_CONTROL, data); + + mdelay(10); + + /* Reset and configure cascaded 10/100 PHY */ + (void)reset_one_mii_phy(phy, 0x1f); + + data = __phy_read(phy, 0x1f, MII_BCM5201_MULTIPHY); + data |= MII_BCM5201_MULTIPHY_SERIALMODE; + __phy_write(phy, 0x1f, MII_BCM5201_MULTIPHY, data); + + return 0; +} + +static int bcm5401_suspend(struct mii_phy* phy, int wol_options) +{ +#if 0 /* Commented out in Darwin... someone has those dawn docs ? */ + phy_write(phy, MII_BMCR, BMCR_PDOWN); +#endif + return 0; +} + +static int bcm5411_init(struct mii_phy* phy) +{ + u16 data; + + /* Here's some more Apple black magic to setup + * some voltage stuffs. + */ + phy_write(phy, 0x1c, 0x8c23); + phy_write(phy, 0x1c, 0x8ca3); + phy_write(phy, 0x1c, 0x8c23); + + /* Here, Apple seems to want to reset it, do + * it as well + */ + phy_write(phy, MII_BMCR, BMCR_RESET); + phy_write(phy, MII_BMCR, 0x1340); + + data = phy_read(phy, MII_BCM5400_GB_CONTROL); + data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP; + phy_write(phy, MII_BCM5400_GB_CONTROL, data); + + mdelay(10); + + /* Reset and configure cascaded 10/100 PHY */ + (void)reset_one_mii_phy(phy, 0x1f); + + return 0; +} + +static int bcm5411_suspend(struct mii_phy* phy, int wol_options) +{ + phy_write(phy, MII_BMCR, BMCR_PDOWN); + + return 0; +} + +static int bcm5421_init(struct mii_phy* phy) +{ + u16 data; + int rev; + + rev = phy_read(phy, MII_PHYSID2) & 0x000f; + if (rev == 0) { + /* This is borrowed from MacOS + */ + phy_write(phy, 0x18, 0x1007); + data = phy_read(phy, 0x18); + phy_write(phy, 0x18, data | 0x0400); + phy_write(phy, 0x18, 0x0007); + data = phy_read(phy, 0x18); + phy_write(phy, 0x18, data | 0x0800); + phy_write(phy, 0x17, 0x000a); + data = phy_read(phy, 0x15); + phy_write(phy, 0x15, data | 0x0200); + } +#if 0 + /* This has to be verified before I enable it */ + /* Enable automatic low-power */ + phy_write(phy, 0x1c, 0x9002); + phy_write(phy, 0x1c, 0xa821); + phy_write(phy, 0x1c, 0x941d); +#endif + return 0; +} + +static int bcm54xx_setup_aneg(struct mii_phy *phy, u32 advertise) +{ + u16 ctl, adv; + + phy->autoneg = 1; + phy->speed = SPEED_10; + phy->duplex = DUPLEX_HALF; + phy->pause = 0; + phy->advertising = advertise; + + /* Setup standard advertise */ + adv = phy_read(phy, MII_ADVERTISE); + adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4); + if (advertise & ADVERTISED_10baseT_Half) + adv |= ADVERTISE_10HALF; + if (advertise & ADVERTISED_10baseT_Full) + adv |= ADVERTISE_10FULL; + if (advertise & ADVERTISED_100baseT_Half) + adv |= ADVERTISE_100HALF; + if (advertise & ADVERTISED_100baseT_Full) + adv |= ADVERTISE_100FULL; + phy_write(phy, MII_ADVERTISE, adv); + + /* Setup 1000BT advertise */ + adv = phy_read(phy, MII_1000BASETCONTROL); + adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP|MII_1000BASETCONTROL_HALFDUPLEXCAP); + if (advertise & SUPPORTED_1000baseT_Half) + adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP; + if (advertise & SUPPORTED_1000baseT_Full) + adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP; + phy_write(phy, MII_1000BASETCONTROL, adv); + + /* Start/Restart aneg */ + ctl = phy_read(phy, MII_BMCR); + ctl |= (BMCR_ANENABLE | BMCR_ANRESTART); + phy_write(phy, MII_BMCR, ctl); + + return 0; +} + +static int bcm54xx_setup_forced(struct mii_phy *phy, int speed, int fd) +{ + u16 ctl; + + phy->autoneg = 0; + phy->speed = speed; + phy->duplex = fd; + phy->pause = 0; + + ctl = phy_read(phy, MII_BMCR); + ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE); + + /* First reset the PHY */ + phy_write(phy, MII_BMCR, ctl | BMCR_RESET); + + /* Select speed & duplex */ + switch(speed) { + case SPEED_10: + break; + case SPEED_100: + ctl |= BMCR_SPEED100; + break; + case SPEED_1000: + ctl |= BMCR_SPD2; + } + if (fd == DUPLEX_FULL) + ctl |= BMCR_FULLDPLX; + + // XXX Should we set the sungem to GII now on 1000BT ? + + phy_write(phy, MII_BMCR, ctl); + + return 0; +} + +static int bcm54xx_read_link(struct mii_phy *phy) +{ + int link_mode; + u16 val; + + if (phy->autoneg) { + val = phy_read(phy, MII_BCM5400_AUXSTATUS); + link_mode = ((val & MII_BCM5400_AUXSTATUS_LINKMODE_MASK) >> + MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT); + phy->duplex = phy_BCM5400_link_table[link_mode][0] ? DUPLEX_FULL : DUPLEX_HALF; + phy->speed = phy_BCM5400_link_table[link_mode][2] ? + SPEED_1000 : + (phy_BCM5400_link_table[link_mode][1] ? SPEED_100 : SPEED_10); + val = phy_read(phy, MII_LPA); + phy->pause = ((val & LPA_PAUSE) != 0); + } + /* On non-aneg, we assume what we put in BMCR is the speed, + * though magic-aneg shouldn't prevent this case from occurring + */ + + return 0; +} + +static int marvell_setup_aneg(struct mii_phy *phy, u32 advertise) +{ + u16 ctl, adv; + + phy->autoneg = 1; + phy->speed = SPEED_10; + phy->duplex = DUPLEX_HALF; + phy->pause = 0; + phy->advertising = advertise; + + /* Setup standard advertise */ + adv = phy_read(phy, MII_ADVERTISE); + adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4); + if (advertise & ADVERTISED_10baseT_Half) + adv |= ADVERTISE_10HALF; + if (advertise & ADVERTISED_10baseT_Full) + adv |= ADVERTISE_10FULL; + if (advertise & ADVERTISED_100baseT_Half) + adv |= ADVERTISE_100HALF; + if (advertise & ADVERTISED_100baseT_Full) + adv |= ADVERTISE_100FULL; + phy_write(phy, MII_ADVERTISE, adv); + + /* Setup 1000BT advertise & enable crossover detect + * XXX How do we advertise 1000BT ? Darwin source is + * confusing here, they read from specific control and + * write to control... Someone has specs for those + * beasts ? + */ + adv = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL); + adv |= MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX; + adv &= ~(MII_1000BASETCONTROL_FULLDUPLEXCAP | + MII_1000BASETCONTROL_HALFDUPLEXCAP); + if (advertise & SUPPORTED_1000baseT_Half) + adv |= MII_1000BASETCONTROL_HALFDUPLEXCAP; + if (advertise & SUPPORTED_1000baseT_Full) + adv |= MII_1000BASETCONTROL_FULLDUPLEXCAP; + phy_write(phy, MII_1000BASETCONTROL, adv); + + /* Start/Restart aneg */ + ctl = phy_read(phy, MII_BMCR); + ctl |= (BMCR_ANENABLE | BMCR_ANRESTART); + phy_write(phy, MII_BMCR, ctl); + + return 0; +} + +static int marvell_setup_forced(struct mii_phy *phy, int speed, int fd) +{ + u16 ctl, ctl2; + + phy->autoneg = 0; + phy->speed = speed; + phy->duplex = fd; + phy->pause = 0; + + ctl = phy_read(phy, MII_BMCR); + ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_SPD2|BMCR_ANENABLE); + ctl |= BMCR_RESET; + + /* Select speed & duplex */ + switch(speed) { + case SPEED_10: + break; + case SPEED_100: + ctl |= BMCR_SPEED100; + break; + /* I'm not sure about the one below, again, Darwin source is + * quite confusing and I lack chip specs + */ + case SPEED_1000: + ctl |= BMCR_SPD2; + } + if (fd == DUPLEX_FULL) + ctl |= BMCR_FULLDPLX; + + /* Disable crossover. Again, the way Apple does it is strange, + * though I don't assume they are wrong ;) + */ + ctl2 = phy_read(phy, MII_M1011_PHY_SPEC_CONTROL); + ctl2 &= ~(MII_M1011_PHY_SPEC_CONTROL_MANUAL_MDIX | + MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX | + MII_1000BASETCONTROL_FULLDUPLEXCAP | + MII_1000BASETCONTROL_HALFDUPLEXCAP); + if (speed == SPEED_1000) + ctl2 |= (fd == DUPLEX_FULL) ? + MII_1000BASETCONTROL_FULLDUPLEXCAP : + MII_1000BASETCONTROL_HALFDUPLEXCAP; + phy_write(phy, MII_1000BASETCONTROL, ctl2); + + // XXX Should we set the sungem to GII now on 1000BT ? + + phy_write(phy, MII_BMCR, ctl); + + return 0; +} + +static int marvell_read_link(struct mii_phy *phy) +{ + u16 status; + + if (phy->autoneg) { + status = phy_read(phy, MII_M1011_PHY_SPEC_STATUS); + if ((status & MII_M1011_PHY_SPEC_STATUS_RESOLVED) == 0) + return -EAGAIN; + if (status & MII_M1011_PHY_SPEC_STATUS_1000) + phy->speed = SPEED_1000; + else if (status & MII_M1011_PHY_SPEC_STATUS_100) + phy->speed = SPEED_100; + else + phy->speed = SPEED_10; + if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX) + phy->duplex = DUPLEX_FULL; + else + phy->duplex = DUPLEX_HALF; + phy->pause = 0; /* XXX Check against spec ! */ + } + /* On non-aneg, we assume what we put in BMCR is the speed, + * though magic-aneg shouldn't prevent this case from occurring + */ + + return 0; +} + +static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise) +{ + u16 ctl, adv; + + phy->autoneg = 1; + phy->speed = SPEED_10; + phy->duplex = DUPLEX_HALF; + phy->pause = 0; + phy->advertising = advertise; + + /* Setup standard advertise */ + adv = phy_read(phy, MII_ADVERTISE); + adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4); + if (advertise & ADVERTISED_10baseT_Half) + adv |= ADVERTISE_10HALF; + if (advertise & ADVERTISED_10baseT_Full) + adv |= ADVERTISE_10FULL; + if (advertise & ADVERTISED_100baseT_Half) + adv |= ADVERTISE_100HALF; + if (advertise & ADVERTISED_100baseT_Full) + adv |= ADVERTISE_100FULL; + phy_write(phy, MII_ADVERTISE, adv); + + /* Start/Restart aneg */ + ctl = phy_read(phy, MII_BMCR); + ctl |= (BMCR_ANENABLE | BMCR_ANRESTART); + phy_write(phy, MII_BMCR, ctl); + + return 0; +} + +static int genmii_setup_forced(struct mii_phy *phy, int speed, int fd) +{ + u16 ctl; + + phy->autoneg = 0; + phy->speed = speed; + phy->duplex = fd; + phy->pause = 0; + + ctl = phy_read(phy, MII_BMCR); + ctl &= ~(BMCR_FULLDPLX|BMCR_SPEED100|BMCR_ANENABLE); + + /* First reset the PHY */ + phy_write(phy, MII_BMCR, ctl | BMCR_RESET); + + /* Select speed & duplex */ + switch(speed) { + case SPEED_10: + break; + case SPEED_100: + ctl |= BMCR_SPEED100; + break; + case SPEED_1000: + default: + return -EINVAL; + } + if (fd == DUPLEX_FULL) + ctl |= BMCR_FULLDPLX; + phy_write(phy, MII_BMCR, ctl); + + return 0; +} + +static int genmii_poll_link(struct mii_phy *phy) +{ + u16 status; + + (void)phy_read(phy, MII_BMSR); + status = phy_read(phy, MII_BMSR); + if ((status & BMSR_LSTATUS) == 0) + return 0; + if (phy->autoneg && !(status & BMSR_ANEGCOMPLETE)) + return 0; + return 1; +} + +static int genmii_read_link(struct mii_phy *phy) +{ + u16 lpa; + + if (phy->autoneg) { + lpa = phy_read(phy, MII_LPA); + + if (lpa & (LPA_10FULL | LPA_100FULL)) + phy->duplex = DUPLEX_FULL; + else + phy->duplex = DUPLEX_HALF; + if (lpa & (LPA_100FULL | LPA_100HALF)) + phy->speed = SPEED_100; + else + phy->speed = SPEED_10; + phy->pause = 0; + } + /* On non-aneg, we assume what we put in BMCR is the speed, + * though magic-aneg shouldn't prevent this case from occurring + */ + + return 0; +} + + +#define MII_BASIC_FEATURES (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \ + SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \ + SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII) +#define MII_GBIT_FEATURES (MII_BASIC_FEATURES | \ + SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full) + +/* Broadcom BCM 5201 */ +static struct mii_phy_ops bcm5201_phy_ops = { + init: bcm5201_init, + suspend: bcm5201_suspend, + setup_aneg: genmii_setup_aneg, + setup_forced: genmii_setup_forced, + poll_link: genmii_poll_link, + read_link: genmii_read_link, +}; + +static struct mii_phy_def bcm5201_phy_def = { + phy_id: 0x00406210, + phy_id_mask: 0xfffffff0, + name: "BCM5201", + features: MII_BASIC_FEATURES, + magic_aneg: 0, + ops: &bcm5201_phy_ops +}; + +/* Broadcom BCM 5221 */ +static struct mii_phy_ops bcm5221_phy_ops = { + suspend: bcm5201_suspend, + init: bcm5221_init, + setup_aneg: genmii_setup_aneg, + setup_forced: genmii_setup_forced, + poll_link: genmii_poll_link, + read_link: genmii_read_link, +}; + +static struct mii_phy_def bcm5221_phy_def = { + phy_id: 0x004061e0, + phy_id_mask: 0xfffffff0, + name: "BCM5221", + features: MII_BASIC_FEATURES, + magic_aneg: 0, + ops: &bcm5221_phy_ops +}; + +/* Broadcom BCM 5400 */ +static struct mii_phy_ops bcm5400_phy_ops = { + init: bcm5400_init, + suspend: bcm5400_suspend, + setup_aneg: bcm54xx_setup_aneg, + setup_forced: bcm54xx_setup_forced, + poll_link: genmii_poll_link, + read_link: bcm54xx_read_link, +}; + +static struct mii_phy_def bcm5400_phy_def = { + phy_id: 0x00206040, + phy_id_mask: 0xfffffff0, + name: "BCM5400", + features: MII_GBIT_FEATURES, + magic_aneg: 1, + ops: &bcm5400_phy_ops +}; + +/* Broadcom BCM 5401 */ +static struct mii_phy_ops bcm5401_phy_ops = { + init: bcm5401_init, + suspend: bcm5401_suspend, + setup_aneg: bcm54xx_setup_aneg, + setup_forced: bcm54xx_setup_forced, + poll_link: genmii_poll_link, + read_link: bcm54xx_read_link, +}; + +static struct mii_phy_def bcm5401_phy_def = { + phy_id: 0x00206050, + phy_id_mask: 0xfffffff0, + name: "BCM5401", + features: MII_GBIT_FEATURES, + magic_aneg: 1, + ops: &bcm5401_phy_ops +}; + +/* Broadcom BCM 5411 */ +static struct mii_phy_ops bcm5411_phy_ops = { + init: bcm5411_init, + suspend: bcm5411_suspend, + setup_aneg: bcm54xx_setup_aneg, + setup_forced: bcm54xx_setup_forced, + poll_link: genmii_poll_link, + read_link: bcm54xx_read_link, +}; + +static struct mii_phy_def bcm5411_phy_def = { + phy_id: 0x00206070, + phy_id_mask: 0xfffffff0, + name: "BCM5411", + features: MII_GBIT_FEATURES, + magic_aneg: 1, + ops: &bcm5411_phy_ops +}; + +/* Broadcom BCM 5421 */ +static struct mii_phy_ops bcm5421_phy_ops = { + init: bcm5421_init, + suspend: bcm5411_suspend, + setup_aneg: bcm54xx_setup_aneg, + setup_forced: bcm54xx_setup_forced, + poll_link: genmii_poll_link, + read_link: bcm54xx_read_link, +}; + +static struct mii_phy_def bcm5421_phy_def = { + phy_id: 0x002060e0, + phy_id_mask: 0xfffffff0, + name: "BCM5421", + features: MII_GBIT_FEATURES, + magic_aneg: 1, + ops: &bcm5421_phy_ops +}; + +/* Marvell 88E1101 (Apple seem to deal with 2 different revs, + * I masked out the 8 last bits to get both, but some specs + * would be useful here) --BenH. + */ +static struct mii_phy_ops marvell_phy_ops = { + setup_aneg: marvell_setup_aneg, + setup_forced: marvell_setup_forced, + poll_link: genmii_poll_link, + read_link: marvell_read_link +}; + +static struct mii_phy_def marvell_phy_def = { + phy_id: 0x01410c00, + phy_id_mask: 0xffffff00, + name: "Marvell 88E1101", + features: MII_GBIT_FEATURES, + magic_aneg: 1, + ops: &marvell_phy_ops +}; + +/* Generic implementation for most 10/100 PHYs */ +static struct mii_phy_ops generic_phy_ops = { + setup_aneg: genmii_setup_aneg, + setup_forced: genmii_setup_forced, + poll_link: genmii_poll_link, + read_link: genmii_read_link +}; + +static struct mii_phy_def genmii_phy_def = { + phy_id: 0x00000000, + phy_id_mask: 0x00000000, + name: "Generic MII", + features: MII_BASIC_FEATURES, + magic_aneg: 0, + ops: &generic_phy_ops +}; + +static struct mii_phy_def* mii_phy_table[] = { + &bcm5201_phy_def, + &bcm5221_phy_def, + &bcm5400_phy_def, + &bcm5401_phy_def, + &bcm5411_phy_def, + &bcm5421_phy_def, + &marvell_phy_def, + &genmii_phy_def, + NULL +}; + +int mii_phy_probe(struct mii_phy *phy, int mii_id) +{ + int rc; + u32 id; + struct mii_phy_def* def; + int i; + + /* We do not reset the mii_phy structure as the driver + * may re-probe the PHY regulary + */ + phy->mii_id = mii_id; + + /* Take PHY out of isloate mode and reset it. */ + rc = reset_one_mii_phy(phy, mii_id); + if (rc) + goto fail; + + /* Read ID and find matching entry */ + id = (phy_read(phy, MII_PHYSID1) << 16 | phy_read(phy, MII_PHYSID2)) + & 0xfffffff0; + for (i=0; (def = mii_phy_table[i]) != NULL; i++) + if ((id & def->phy_id_mask) == def->phy_id) + break; + /* Should never be NULL (we have a generic entry), but... */ + if (def == NULL) + goto fail; + + phy->def = def; + + return 0; +fail: + phy->speed = 0; + phy->duplex = 0; + phy->pause = 0; + phy->advertising = 0; + return -ENODEV; +} + +EXPORT_SYMBOL(mii_phy_probe); +MODULE_LICENSE("GPL"); + diff -uNr linux-2.4.21/drivers/net/sungem_phy.h linux-2.4.21-ben2/drivers/net/sungem_phy.h --- linux-2.4.21/drivers/net/sungem_phy.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/drivers/net/sungem_phy.h 2003-06-27 15:41:09.000000000 +0200 @@ -0,0 +1,116 @@ +#ifndef __SUNGEM_PHY_H__ +#define __SUNGEM_PHY_H__ + +struct mii_phy; + +/* Operations supported by any kind of PHY */ +struct mii_phy_ops +{ + int (*init)(struct mii_phy *phy); + int (*suspend)(struct mii_phy *phy, int wol_options); + int (*setup_aneg)(struct mii_phy *phy, u32 advertise); + int (*setup_forced)(struct mii_phy *phy, int speed, int fd); + int (*poll_link)(struct mii_phy *phy); + int (*read_link)(struct mii_phy *phy); +}; + +/* Structure used to statically define an mii/gii based PHY */ +struct mii_phy_def +{ + u32 phy_id; /* Concatenated ID1 << 16 | ID2 */ + u32 phy_id_mask; /* Significant bits */ + u32 features; /* Ethtool SUPPORTED_* defines */ + int magic_aneg; /* Autoneg does all speed test for us */ + const char* name; + const struct mii_phy_ops* ops; +}; + +/* An instance of a PHY, partially borrowed from mii_if_info */ +struct mii_phy +{ + struct mii_phy_def* def; + int advertising; + int mii_id; + + /* 1: autoneg enabled, 0: disabled */ + int autoneg; + + /* forced speed & duplex (no autoneg) + * partner speed & duplex & pause (autoneg) + */ + int speed; + int duplex; + int pause; + + /* Provided by host chip */ + struct net_device* dev; + int (*mdio_read) (struct net_device *dev, int mii_id, int reg); + void (*mdio_write) (struct net_device *dev, int mii_id, int reg, int val); +}; + +/* Pass in a struct mii_phy with dev, mdio_read and mdio_write + * filled, the remaining fields will be filled on return + */ +extern int mii_phy_probe(struct mii_phy *phy, int mii_id); + + +/* MII definitions missing from mii.h */ + +#define BMCR_SPD2 0x0040 /* Gigabit enable (bcm54xx) */ +#define LPA_PAUSE 0x0400 + +/* More PHY registers (model specific) */ + +/* MII BCM5201 MULTIPHY interrupt register */ +#define MII_BCM5201_INTERRUPT 0x1A +#define MII_BCM5201_INTERRUPT_INTENABLE 0x4000 + +#define MII_BCM5201_AUXMODE2 0x1B +#define MII_BCM5201_AUXMODE2_LOWPOWER 0x0008 + +#define MII_BCM5201_MULTIPHY 0x1E + +/* MII BCM5201 MULTIPHY register bits */ +#define MII_BCM5201_MULTIPHY_SERIALMODE 0x0002 +#define MII_BCM5201_MULTIPHY_SUPERISOLATE 0x0008 + +/* MII BCM5221 Additional registers */ +#define MII_BCM5221_TEST 0x1f +#define MII_BCM5221_TEST_ENABLE_SHADOWS 0x0080 +#define MII_BCM5221_SHDOW_AUX_STAT2 0x1b +#define MII_BCM5221_SHDOW_AUX_STAT2_APD 0x0020 +#define MII_BCM5221_SHDOW_AUX_MODE4 0x1a +#define MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR 0x0004 + +/* MII BCM5400 1000-BASET Control register */ +#define MII_BCM5400_GB_CONTROL 0x09 +#define MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP 0x0200 + +/* MII BCM5400 AUXCONTROL register */ +#define MII_BCM5400_AUXCONTROL 0x18 +#define MII_BCM5400_AUXCONTROL_PWR10BASET 0x0004 + +/* MII BCM5400 AUXSTATUS register */ +#define MII_BCM5400_AUXSTATUS 0x19 +#define MII_BCM5400_AUXSTATUS_LINKMODE_MASK 0x0700 +#define MII_BCM5400_AUXSTATUS_LINKMODE_SHIFT 8 + +/* 1000BT control (Marvell & BCM54xx at least) */ +#define MII_1000BASETCONTROL 0x09 +#define MII_1000BASETCONTROL_FULLDUPLEXCAP 0x0200 +#define MII_1000BASETCONTROL_HALFDUPLEXCAP 0x0100 + +/* Marvell 88E1011 PHY control */ +#define MII_M1011_PHY_SPEC_CONTROL 0x10 +#define MII_M1011_PHY_SPEC_CONTROL_MANUAL_MDIX 0x20 +#define MII_M1011_PHY_SPEC_CONTROL_AUTO_MDIX 0x40 + +/* Marvell 88E1011 PHY status */ +#define MII_M1011_PHY_SPEC_STATUS 0x11 +#define MII_M1011_PHY_SPEC_STATUS_1000 0x8000 +#define MII_M1011_PHY_SPEC_STATUS_100 0x4000 +#define MII_M1011_PHY_SPEC_STATUS_SPD_MASK 0xc000 +#define MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX 0x2000 +#define MII_M1011_PHY_SPEC_STATUS_RESOLVED 0x0800 + +#endif /* __SUNGEM_PHY_H__ */ diff -uNr linux-2.4.21/drivers/net/tg3.c linux-2.4.21-ben2/drivers/net/tg3.c --- linux-2.4.21/drivers/net/tg3.c 2003-06-13 16:51:35.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/tg3.c 2003-06-27 15:41:01.000000000 +0200 @@ -149,6 +149,8 @@ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, { 0, } }; diff -uNr linux-2.4.21/drivers/net/tulip/tulip_core.c linux-2.4.21-ben2/drivers/net/tulip/tulip_core.c --- linux-2.4.21/drivers/net/tulip/tulip_core.c 2003-06-13 16:51:35.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/tulip/tulip_core.c 2003-06-27 15:41:06.000000000 +0200 @@ -473,6 +473,15 @@ } else tulip_select_media(dev, 1); + /* check for Apple 100BaseTX card and disable loops */ + if ((dev->dev_addr[0] == 0x00) && + (dev->dev_addr[1] == 0x05) && + (dev->dev_addr[2] == 0x02) && + (tp->chip_id == DC21140)) { + outl(0x10f, ioaddr + CSR12); + outl(0x03, ioaddr + CSR12); + } + /* Start the chip's Tx to process setup frame. */ tulip_stop_rxtx(tp); barrier(); diff -uNr linux-2.4.21/drivers/net/wireless/Config.in linux-2.4.21-ben2/drivers/net/wireless/Config.in --- linux-2.4.21/drivers/net/wireless/Config.in 2002-11-29 00:53:14.000000000 +0100 +++ linux-2.4.21-ben2/drivers/net/wireless/Config.in 2003-06-27 15:41:09.000000000 +0200 @@ -15,6 +15,7 @@ if [ "$CONFIG_PCI" = "y" ]; then dep_tristate ' Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.) (EXPERIMENTAL)' CONFIG_PLX_HERMES $CONFIG_HERMES $CONFIG_EXPERIMENTAL dep_tristate ' Prism 2.5 PCI 802.11b adaptor support (EXPERIMENTAL)' CONFIG_PCI_HERMES $CONFIG_HERMES $CONFIG_EXPERIMENTAL + dep_tristate ' Prism II devices connected via a TMD7160 (EXPERIMENTAL)' CONFIG_TMD_HERMES $CONFIG_HERMES $CONFIG_EXPERIMENTAL fi # If Pcmcia is compiled in, offer Pcmcia cards... diff -uNr linux-2.4.21/drivers/net/wireless/Makefile linux-2.4.21-ben2/drivers/net/wireless/Makefile --- linux-2.4.21/drivers/net/wireless/Makefile 2002-08-03 02:39:44.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/wireless/Makefile 2003-06-27 15:41:01.000000000 +0200 @@ -19,6 +19,7 @@ obj-$(CONFIG_APPLE_AIRPORT) += airport.o obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o +obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o obj-$(CONFIG_AIRO) += airo.o obj-$(CONFIG_AIRO_CS) += airo_cs.o airo.o diff -uNr linux-2.4.21/drivers/net/wireless/airport.c linux-2.4.21-ben2/drivers/net/wireless/airport.c --- linux-2.4.21/drivers/net/wireless/airport.c 2003-06-13 16:51:35.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/wireless/airport.c 2003-06-27 15:41:32.000000000 +0200 @@ -1,4 +1,4 @@ -/* airport.c 0.13b +/* airport.c 0.13d * * A driver for "Hermes" chipset based Apple Airport wireless * card. @@ -95,7 +95,7 @@ netif_device_detach(dev); - priv->hw_unavailable = 1; + priv->hw_unavailable++; orinoco_unlock(priv, &flags); @@ -121,14 +121,15 @@ netif_device_attach(dev); - if (priv->open) { + priv->hw_unavailable--; + + if (priv->open && (! priv->hw_unavailable)) { err = __orinoco_up(dev); if (err) printk(KERN_ERR "%s: Error %d restarting card on PBOOK_WAKE\n", dev->name, err); } - priv->hw_unavailable = 0; spin_unlock_irqrestore(&priv->lock, flags); @@ -140,8 +141,21 @@ static int airport_hard_reset(struct orinoco_private *priv) { + /* It would be nice to power cycle the Airport for a real hard + * reset, but for some reason although it appears to + * re-initialize properly, it falls in a screaming heap + * shortly afterwards. */ +#if 0 + struct net_device *dev = priv->ndev; struct airport *card = priv->card; + /* Vitally important. If we don't do this it seems we get an + * interrupt somewhere during the power cycle, since + * hw_unavailable is already set it doesn't get ACKed, we get + * into an interrupt loop and the the PMU decides to turn us + * off. */ + disable_irq(dev->irq); + pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, card->node, 0, 0); current->state = TASK_UNINTERRUPTIBLE; schedule_timeout(HZ); @@ -149,6 +163,10 @@ current->state = TASK_UNINTERRUPTIBLE; schedule_timeout(HZ); + enable_irq(dev->irq); + schedule_timeout(HZ); +#endif + return 0; } @@ -209,7 +227,7 @@ /* Reset it before we get the interrupt */ hermes_init(hw); - if (request_irq(dev->irq, orinoco_interrupt, 0, "Airport", (void *)priv)) { + if (request_irq(dev->irq, orinoco_interrupt, 0, "Airport", dev)) { printk(KERN_ERR "airport: Couldn't get IRQ %d\n", dev->irq); goto failed; } @@ -251,7 +269,7 @@ card->ndev_registered = 0; if (card->irq_requested) - free_irq(dev->irq, priv); + free_irq(dev->irq, dev); card->irq_requested = 0; if (card->vaddr) @@ -269,11 +287,10 @@ kfree(dev); } /* airport_detach */ -static char version[] __initdata = "airport.c 0.13b (Benjamin Herrenschmidt )"; +static char version[] __initdata = "airport.c 0.13d (Benjamin Herrenschmidt )"; MODULE_AUTHOR("Benjamin Herrenschmidt "); MODULE_DESCRIPTION("Driver for the Apple Airport wireless card."); MODULE_LICENSE("Dual MPL/GPL"); -EXPORT_NO_SYMBOLS; static int __init init_airport(void) @@ -282,15 +299,11 @@ printk(KERN_DEBUG "%s\n", version); - MOD_INC_USE_COUNT; - /* Lookup card in device tree */ airport_node = find_devices("radio"); if (airport_node && !strcmp(airport_node->parent->name, "mac-io")) airport_dev = airport_attach(airport_node); - MOD_DEC_USE_COUNT; - return airport_dev ? 0 : -ENODEV; } diff -uNr linux-2.4.21/drivers/net/wireless/hermes.c linux-2.4.21-ben2/drivers/net/wireless/hermes.c --- linux-2.4.21/drivers/net/wireless/hermes.c 2003-06-13 16:51:35.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/wireless/hermes.c 2003-06-27 15:41:05.000000000 +0200 @@ -544,4 +544,9 @@ return 0; } +static void __exit exit_hermes(void) +{ +} + module_init(init_hermes); +module_exit(exit_hermes); diff -uNr linux-2.4.21/drivers/net/wireless/hermes.h linux-2.4.21-ben2/drivers/net/wireless/hermes.h --- linux-2.4.21/drivers/net/wireless/hermes.h 2003-06-13 16:51:35.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/wireless/hermes.h 2003-06-27 15:41:20.000000000 +0200 @@ -250,7 +250,6 @@ u16 scanreason; /* ??? */ struct hermes_scan_apinfo aps[35]; /* Scan result */ } __attribute__ ((packed)); - #define HERMES_LINKSTATUS_NOT_CONNECTED (0x0000) #define HERMES_LINKSTATUS_CONNECTED (0x0001) #define HERMES_LINKSTATUS_DISCONNECTED (0x0002) @@ -368,7 +367,7 @@ if (hw->io_space) { insw(hw->iobase + off, buf, count); } else { - int i; + unsigned i; u16 *p; /* This needs to *not* byteswap (like insw()) but @@ -388,7 +387,7 @@ if (hw->io_space) { outsw(hw->iobase + off, buf, count); } else { - int i; + unsigned i; const u16 *p; /* This needs to *not* byteswap (like outsw()) but @@ -401,6 +400,21 @@ } } +static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count) +{ + unsigned i; + + off = off << hw->reg_spacing;; + + if (hw->io_space) { + for (i = 0; i < count; i++) + outw(0, hw->iobase + off); + } else { + for (i = 0; i < count; i++) + writew(0, hw->iobase + off); + } +} + #define HERMES_READ_RECORD(hw, bap, rid, buf) \ (hermes_read_ltv((hw),(bap),(rid), sizeof(*buf), NULL, (buf))) #define HERMES_WRITE_RECORD(hw, bap, rid, buf) \ diff -uNr linux-2.4.21/drivers/net/wireless/orinoco.c linux-2.4.21-ben2/drivers/net/wireless/orinoco.c --- linux-2.4.21/drivers/net/wireless/orinoco.c 2003-06-13 16:51:35.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/wireless/orinoco.c 2003-06-27 15:41:49.000000000 +0200 @@ -1,4 +1,4 @@ -/* orinoco.c 0.13b - (formerly known as dldwd_cs.c and orinoco_cs.c) +/* orinoco.c 0.13d - (formerly known as dldwd_cs.c and orinoco_cs.c) * * A driver for Hermes or Prism 2 chipset based PCMCIA wireless * adaptors, with Lucent/Agere, Intersil or Symbol firmware. @@ -345,11 +345,45 @@ * we are connected (avoids cofusing the firmware), and only * give LINKSTATUS printk()s if the status has changed. * + * v0.13b -> v0.13c - 11 Mar 2003 - David Gibson + * o Cleanup: use dev instead of priv in various places. + * o Bug fix: Don't ReleaseConfiguration on RESET_PHYSICAL event + * if we're in the middle of a (driver initiated) hard reset. + * o Bug fix: ETH_ZLEN is supposed to include the header + * (Dionysus Blazakis & Manish Karir) + * o Convert to using workqueues instead of taskqueues (and + * backwards compatibility macros for pre 2.5.41 kernels). + * o Drop redundant (I think...) MOD_{INC,DEC}_USE_COUNT in + * airport.c + * o New orinoco_tmd.c init module from Joerg Dorchain for + * TMD7160 based PCI to PCMCIA bridges (similar to + * orinoco_plx.c). + * + * v0.13c -> v0.13d - 22 Apr 2003 - David Gibson + * o Make hw_unavailable a counter, rather than just a flag, this + * is necessary to avoid some races (such as a card being + * removed in the middle of orinoco_reset(). + * o Restore Release/RequestConfiguration in the PCMCIA event handler + * when dealing with a driver initiated hard reset. This is + * necessary to prevent hangs due to a spurious interrupt while + * the reset is in progress. + * o Clear the 802.11 header when transmitting, even though we + * don't use it. This fixes a long standing bug on some + * firmwares, which seem to get confused if that isn't done. + * o Be less eager to de-encapsulate SNAP frames, only do so if + * the OUI is 00:00:00 or 00:00:f8, leave others alone. The old + * behaviour broke CDP (Cisco Discovery Protocol). + * o Use dev instead of priv for free_irq() as well as + * request_irq() (oops). + * o Attempt to reset rather than giving up if we get too many + * IRQs. + * o Changed semantics of __orinoco_down() so it can be called + * safely with hw_unavailable set. It also now clears the + * linkstatus (since we're going to have to reassociate). + * * TODO - * o New wireless extensions API (patch from Moustafa * Youssef, updated by Jim Carter). - * o Fix PCMCIA hard resets with pcmcia-cs. * o Handle de-encapsulation within network layer, provide 802.11 * headers (patch from Thomas 'Dent' Mirlacher) * o Fix possible races in SPY handling. @@ -373,7 +407,7 @@ * flag after taking the lock, and if it is set, give up on whatever * they are doing and drop the lock again. The orinoco_lock() * function handles this (it unlocks and returns -EBUSY if - * hw_unavailable is true). */ + * hw_unavailable is non-zero). */ #include @@ -522,7 +556,7 @@ /* Hardware control routines */ -static int __orinoco_program_rids(struct orinoco_private *priv); +static int __orinoco_program_rids(struct net_device *dev); static int __orinoco_hw_set_bitrate(struct orinoco_private *priv); static int __orinoco_hw_setup_wep(struct orinoco_private *priv); @@ -535,14 +569,14 @@ static void __orinoco_set_multicast_list(struct net_device *dev); /* Interrupt handling routines */ -static void __orinoco_ev_tick(struct orinoco_private *priv, hermes_t *hw); -static void __orinoco_ev_wterr(struct orinoco_private *priv, hermes_t *hw); -static void __orinoco_ev_infdrop(struct orinoco_private *priv, hermes_t *hw); -static void __orinoco_ev_info(struct orinoco_private *priv, hermes_t *hw); -static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw); -static void __orinoco_ev_txexc(struct orinoco_private *priv, hermes_t *hw); -static void __orinoco_ev_tx(struct orinoco_private *priv, hermes_t *hw); -static void __orinoco_ev_alloc(struct orinoco_private *priv, hermes_t *hw); +static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw); +static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw); +static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw); +static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw); +static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw); +static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw); +static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw); +static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw); /* ioctl() routines */ static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq); @@ -577,7 +611,7 @@ struct hermes *hw = &priv->hw; int err; - err = __orinoco_program_rids(priv); + err = __orinoco_program_rids(dev); if (err) { printk(KERN_ERR "%s: Error %d configuring card\n", dev->name, err); @@ -606,14 +640,25 @@ netif_stop_queue(dev); - err = hermes_disable_port(hw, 0); - if (err) { - printk(KERN_ERR "%s: Error %d disabling MAC port\n", - dev->name, err); - return err; + if (! priv->hw_unavailable) { + if (! priv->broken_disableport) { + err = hermes_disable_port(hw, 0); + if (err) { + /* Some firmwares (e.g. Intersil 1.3.x) seem + * to have problems disabling the port, oh + * well, too bad. */ + printk(KERN_WARNING "%s: Error %d disabling MAC port\n", + dev->name, err); + priv->broken_disableport = 1; + } + } + hermes_set_irqmask(hw, 0); + hermes_write_regn(hw, EVACK, 0xffff); } - hermes_set_irqmask(hw, 0); - hermes_write_regn(hw, EVACK, 0xffff); + + /* firmware will have to reassociate */ + priv->last_linkstatus = 0xffff; + priv->connected = 0; return 0; } @@ -656,38 +701,38 @@ if (err) return err; - priv->open = 1; - err = __orinoco_up(dev); + if (! err) + priv->open = 1; + orinoco_unlock(priv, &flags); return err; } -static int orinoco_stop(struct net_device *dev) +int orinoco_stop(struct net_device *dev) { struct orinoco_private *priv = dev->priv; int err = 0; /* We mustn't use orinoco_lock() here, because we need to be - able to close the interface, even if hw_unavailable is set + able to close the interface even if hw_unavailable is set (e.g. as we're released after a PC Card removal) */ spin_lock_irq(&priv->lock); priv->open = 0; - if (! priv->hw_unavailable) - err = __orinoco_down(dev); + err = __orinoco_down(dev); spin_unlock_irq(&priv->lock); return err; } -static int __orinoco_program_rids(struct orinoco_private *priv) +static int __orinoco_program_rids(struct net_device *dev) { - struct net_device *dev = priv->ndev; + struct orinoco_private *priv = dev->priv; hermes_t *hw = &priv->hw; int err; struct hermes_idstring idbuf; @@ -873,51 +918,84 @@ } /* xyzzy */ -static int orinoco_reconfigure(struct orinoco_private *priv) +static int orinoco_reconfigure(struct net_device *dev) { + struct orinoco_private *priv = dev->priv; struct hermes *hw = &priv->hw; unsigned long flags; int err = 0; - orinoco_lock(priv, &flags); + if (priv->broken_disableport) { + schedule_work(&priv->reset_work); + return 0; + } + err = orinoco_lock(priv, &flags); + if (err) + return err; + + err = hermes_disable_port(hw, 0); if (err) { - printk(KERN_ERR "%s: Unable to disable port in orinco_reconfigure()\n", - priv->ndev->name); + printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n", + dev->name); + priv->broken_disableport = 1; goto out; } - err = __orinoco_program_rids(priv); - if (err) + err = __orinoco_program_rids(dev); + if (err) { + printk(KERN_WARNING "%s: Unable to reconfigure card\n", + dev->name); goto out; + } err = hermes_enable_port(hw, 0); if (err) { - printk(KERN_ERR "%s: Unable to enable port in orinco_reconfigure()\n", - priv->ndev->name); + printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n", + dev->name); goto out; } out: + if (err) { + printk(KERN_WARNING "%s: Resetting instead...\n", dev->name); + schedule_work(&priv->reset_work); + err = 0; + } + orinoco_unlock(priv, &flags); return err; } /* This must be called from user context, without locks held - use - * schedule_task() */ + * schedule_work() */ static void orinoco_reset(struct net_device *dev) { struct orinoco_private *priv = dev->priv; + struct hermes *hw = &priv->hw; int err; unsigned long flags; err = orinoco_lock(priv, &flags); if (err) + /* When the hardware becomes available again, whatever + * detects that is responsible for re-initializing + * it. So no need for anything further*/ return; - priv->hw_unavailable = 1; + netif_stop_queue(dev); + + /* Shut off interrupts. Depending on what state the hardware + * is in, this might not work, but we'll try anyway */ + hermes_set_irqmask(hw, 0); + hermes_write_regn(hw, EVACK, 0xffff); + + priv->hw_unavailable++; + priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */ + priv->connected = 0; + orinoco_unlock(priv, &flags); if (priv->hard_reset) @@ -936,18 +1014,22 @@ return; } - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irq(&priv->lock); /* This has to be called from user context */ - priv->hw_unavailable = 0; + priv->hw_unavailable--; - err = __orinoco_up(dev); - if (err) { - printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n", - dev->name, err); - } else - dev->trans_start = jiffies; + /* priv->open or priv->hw_unavailable might have changed while + * we dropped the lock */ + if (priv->open && (! priv->hw_unavailable)) { + err = __orinoco_up(dev); + if (err) { + printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n", + dev->name, err); + } else + dev->trans_start = jiffies; + } - orinoco_unlock(priv, &flags); + spin_unlock_irq(&priv->lock); return; } @@ -979,10 +1061,18 @@ } } +/* Does the frame have a SNAP header indicating it should be + * de-encapsulated to Ethernet-II? */ static inline int -is_snap(struct header_struct *hdr) +is_ethersnap(struct header_struct *hdr) { - return (hdr->dsap == 0xAA) && (hdr->ssap == 0xAA) && (hdr->ctrl == 0x3); + /* We de-encapsulate all packets which, a) have SNAP headers + * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header + * and where b) the OUI of the SNAP header is 00:00:00 or + * 00:00:f8 - we need both because different APs appear to use + * different OUIs for some reason */ + return (memcmp(&hdr->dsap, &encaps_hdr, 5) == 0) + && ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) ); } static void @@ -1140,7 +1230,8 @@ return 0; } -static int orinoco_hw_get_bssid(struct orinoco_private *priv, char buf[ETH_ALEN]) +static int orinoco_hw_get_bssid(struct orinoco_private *priv, + char buf[ETH_ALEN]) { hermes_t *hw = &priv->hw; int err = 0; @@ -1159,7 +1250,7 @@ } static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, - char buf[IW_ESSID_MAX_SIZE+1]) + char buf[IW_ESSID_MAX_SIZE+1]) { hermes_t *hw = &priv->hw; int err = 0; @@ -1236,9 +1327,8 @@ } if ( (channel < 1) || (channel > NUM_CHANNELS) ) { - struct net_device *dev = priv->ndev; - - printk(KERN_WARNING "%s: Channel out of range (%d)!\n", dev->name, channel); + printk(KERN_WARNING "%s: Channel out of range (%d)!\n", + priv->ndev->name, channel); err = -EBUSY; goto out; @@ -1253,8 +1343,8 @@ return err ? err : freq; } -static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrates, - s32 *rates, int max) +static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, + int *numrates, s32 *rates, int max) { hermes_t *hw = &priv->hw; struct hermes_idstring list; @@ -1354,9 +1444,9 @@ */ void orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - struct orinoco_private *priv = (struct orinoco_private *) dev_id; + struct net_device *dev = (struct net_device *)dev_id; + struct orinoco_private *priv = dev->priv; hermes_t *hw = &priv->hw; - struct net_device *dev = priv->ndev; int count = MAX_IRQLOOPS_PER_IRQ; u16 evstat, events; /* These are used to detect a runaway interrupt situation */ @@ -1380,11 +1470,11 @@ while (events && count--) { if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) { - printk(KERN_CRIT "%s: IRQ handler is looping too \ -much! Shutting down.\n", - dev->name); - /* Perform an emergency shutdown */ + printk(KERN_WARNING "%s: IRQ handler is looping too " + "much! Resetting.\n", dev->name); + /* Disable interrupts for now */ hermes_set_irqmask(hw, 0); + schedule_work(&priv->reset_work); break; } @@ -1395,21 +1485,21 @@ } if (events & HERMES_EV_TICK) - __orinoco_ev_tick(priv, hw); + __orinoco_ev_tick(dev, hw); if (events & HERMES_EV_WTERR) - __orinoco_ev_wterr(priv, hw); + __orinoco_ev_wterr(dev, hw); if (events & HERMES_EV_INFDROP) - __orinoco_ev_infdrop(priv, hw); + __orinoco_ev_infdrop(dev, hw); if (events & HERMES_EV_INFO) - __orinoco_ev_info(priv, hw); + __orinoco_ev_info(dev, hw); if (events & HERMES_EV_RX) - __orinoco_ev_rx(priv, hw); + __orinoco_ev_rx(dev, hw); if (events & HERMES_EV_TXEXC) - __orinoco_ev_txexc(priv, hw); + __orinoco_ev_txexc(dev, hw); if (events & HERMES_EV_TX) - __orinoco_ev_tx(priv, hw); + __orinoco_ev_tx(dev, hw); if (events & HERMES_EV_ALLOC) - __orinoco_ev_alloc(priv, hw); + __orinoco_ev_alloc(dev, hw); hermes_write_regn(hw, EVACK, events); @@ -1420,22 +1510,22 @@ orinoco_unlock(priv, &flags); } -static void __orinoco_ev_tick(struct orinoco_private *priv, hermes_t *hw) +static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw) { - printk(KERN_DEBUG "%s: TICK\n", priv->ndev->name); + printk(KERN_DEBUG "%s: TICK\n", dev->name); } -static void __orinoco_ev_wterr(struct orinoco_private *priv, hermes_t *hw) +static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw) { /* This seems to happen a fair bit under load, but ignoring it seems to work fine...*/ printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n", - priv->ndev->name); + dev->name); } -static void __orinoco_ev_infdrop(struct orinoco_private *priv, hermes_t *hw) +static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw) { - printk(KERN_WARNING "%s: Information frame lost.\n", priv->ndev->name); + printk(KERN_WARNING "%s: Information frame lost.\n", dev->name); } static void print_linkstatus(struct net_device *dev, u16 status) @@ -1472,9 +1562,9 @@ dev->name, s, status); } -static void __orinoco_ev_info(struct orinoco_private *priv, hermes_t *hw) +static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) { - struct net_device *dev = priv->ndev; + struct orinoco_private *priv = dev->priv; u16 infofid; struct { u16 len; @@ -1573,9 +1663,9 @@ } } -static void __orinoco_ev_rx(struct orinoco_private *priv, hermes_t *hw) +static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) { - struct net_device *dev = priv->ndev; + struct orinoco_private *priv = dev->priv; struct net_device_stats *stats = &priv->stats; struct iw_statistics *wstats = &priv->wstats; struct sk_buff *skb = NULL; @@ -1664,7 +1754,7 @@ * So, check ourselves */ if(((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) || ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) || - is_snap(&hdr)) { + is_ethersnap(&hdr)) { /* These indicate a SNAP within 802.2 LLC within 802.11 frame which we'll need to de-encapsulate to the original EthernetII frame. */ @@ -1726,9 +1816,9 @@ return; } -static void __orinoco_ev_txexc(struct orinoco_private *priv, hermes_t *hw) +static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) { - struct net_device *dev = priv->ndev; + struct orinoco_private *priv = dev->priv; struct net_device_stats *stats = &priv->stats; u16 fid = hermes_read_regn(hw, TXCOMPLFID); struct hermes_tx_descriptor desc; @@ -1752,8 +1842,9 @@ hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); } -static void __orinoco_ev_tx(struct orinoco_private *priv, hermes_t *hw) +static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw) { + struct orinoco_private *priv = dev->priv; struct net_device_stats *stats = &priv->stats; stats->tx_packets++; @@ -1761,9 +1852,10 @@ hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); } -static void __orinoco_ev_alloc(struct orinoco_private *priv, hermes_t *hw) +static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw) { - struct net_device *dev = priv->ndev; + struct orinoco_private *priv = dev->priv; + u16 fid = hermes_read_regn(hw, ALLOCFID); if (fid != priv->txfid) { @@ -1945,7 +2037,7 @@ TRACE_ENTER(dev->name); - /* No need to lock, the resetting flag is already set in + /* No need to lock, the hw_unavailable flag is already set in * alloc_orinocodev() */ priv->nicbuf_size = IEEE802_11_FRAME_LEN + ETH_HLEN; @@ -2081,8 +2173,6 @@ priv->wep_on = 0; priv->tx_key = 0; - priv->hw_unavailable = 0; - err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); if (err == -EIO) { /* Try workaround for old Symbol firmware bug */ @@ -2102,6 +2192,12 @@ goto out; } + /* Make the hardware available, as long as it hasn't been + * removed elsewhere (e.g. by PCMCIA hot unplug) */ + spin_lock_irq(&priv->lock); + priv->hw_unavailable--; + spin_unlock_irq(&priv->lock); + printk(KERN_DEBUG "%s: ready\n", dev->name); out: @@ -2267,7 +2363,7 @@ /* Length of the packet body */ /* FIXME: what if the skb is smaller than this? */ - len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN); + len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN); eh = (struct ethhdr *)skb->data; @@ -2281,6 +2377,12 @@ goto fail; } + /* Clear the 802.11 header and data length fields - some + * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused + * if this isn't done. */ + hermes_clear_words(hw, HERMES_DATA0, + HERMES_802_3_OFFSET - HERMES_802_11_OFFSET); + /* Encapsulate Ethernet-II frames */ if (ntohs(eh->h_proto) > 1500) { /* Ethernet-II frame */ struct header_struct hdr; @@ -2362,7 +2464,7 @@ stats->tx_errors++; - schedule_task(&priv->timeout_task); + schedule_work(&priv->reset_work); } static int @@ -2532,7 +2634,7 @@ } err = orinoco_hw_get_bitratelist(priv, &numrates, - range.bitrate, IW_MAX_BITRATES); + range.bitrate, IW_MAX_BITRATES); if (err) return err; range.num_bitrates = numrates; @@ -3128,7 +3230,7 @@ rrq->value = 5500000; else rrq->value = val * 1000000; - break; + break; case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */ case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */ for (i = 0; i < BITRATE_TABLE_SIZE; i++) @@ -3754,7 +3856,7 @@ printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name); - schedule_task(&priv->timeout_task); + schedule_work(&priv->reset_work); break; case SIOCIWFIRSTPRIV + 0x2: /* set_port3 */ @@ -3839,7 +3941,7 @@ } if (! err && changed && netif_running(dev)) { - err = orinoco_reconfigure(priv); + err = orinoco_reconfigure(dev); } TRACE_EXIT(dev->name); @@ -3924,7 +4026,7 @@ DEBUG_REC(PRIID,WORDS), DEBUG_REC(PRISUPRANGE,WORDS), DEBUG_REC(CFIACTRANGES,WORDS), - DEBUG_REC(NICSERNUM,WORDS), + DEBUG_REC(NICSERNUM,XSTRING), DEBUG_REC(NICID,WORDS), DEBUG_REC(MFISUPRANGE,WORDS), DEBUG_REC(CFISUPRANGE,WORDS), @@ -4062,7 +4164,7 @@ priv->hw_unavailable = 1; /* orinoco_init() must clear this * before anything else touches the * hardware */ - INIT_TQUEUE(&priv->timeout_task, (void (*)(void *))orinoco_reset, dev); + INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev); priv->last_linkstatus = 0xffff; priv->connected = 0; @@ -4079,13 +4181,14 @@ EXPORT_SYMBOL(__orinoco_up); EXPORT_SYMBOL(__orinoco_down); +EXPORT_SYMBOL(orinoco_stop); EXPORT_SYMBOL(orinoco_reinit_firmware); EXPORT_SYMBOL(orinoco_interrupt); /* Can't be declared "const" or the whole __initdata section will * become const */ -static char version[] __initdata = "orinoco.c 0.13b (David Gibson and others)"; +static char version[] __initdata = "orinoco.c 0.13d (David Gibson and others)"; static int __init init_orinoco(void) { diff -uNr linux-2.4.21/drivers/net/wireless/orinoco.h linux-2.4.21-ben2/drivers/net/wireless/orinoco.h --- linux-2.4.21/drivers/net/wireless/orinoco.h 2003-06-13 16:51:35.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/wireless/orinoco.h 2003-06-27 15:41:03.000000000 +0200 @@ -11,9 +11,20 @@ #include #include #include -#include +#include #include "hermes.h" +/* Workqueue / task queue backwards compatibility stuff */ + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41) +#include +#else +#include +#define work_struct tq_struct +#define INIT_WORK INIT_TQUEUE +#define schedule_work schedule_task +#endif + /* To enable debug messages */ //#define ORINOCO_DEBUG 3 @@ -42,7 +53,7 @@ /* Synchronisation stuff */ spinlock_t lock; int hw_unavailable; - struct tq_struct timeout_task; + struct work_struct reset_work; /* driver state */ int open; @@ -72,6 +83,7 @@ int has_sensitivity; int nicbuf_size; u16 channel_mask; + int broken_disableport; /* Configuration paramaters */ u32 iw_mode; @@ -111,8 +123,8 @@ int (*hard_reset)(struct orinoco_private *)); extern int __orinoco_up(struct net_device *dev); extern int __orinoco_down(struct net_device *dev); -int orinoco_reinit_firmware(struct net_device *dev); - +extern int orinoco_stop(struct net_device *dev); +extern int orinoco_reinit_firmware(struct net_device *dev); extern void orinoco_interrupt(int irq, void * dev_id, struct pt_regs *regs); /********************************************************************/ diff -uNr linux-2.4.21/drivers/net/wireless/orinoco_cs.c linux-2.4.21-ben2/drivers/net/wireless/orinoco_cs.c --- linux-2.4.21/drivers/net/wireless/orinoco_cs.c 2003-06-13 16:51:35.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/wireless/orinoco_cs.c 2003-06-27 15:41:06.000000000 +0200 @@ -1,4 +1,4 @@ -/* orinoco_cs.c 0.13b - (formerly known as dldwd_cs.c) +/* orinoco_cs.c 0.13d - (formerly known as dldwd_cs.c) * * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/ @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -38,7 +37,6 @@ #include #include #include -#include #include "orinoco.h" @@ -269,19 +267,12 @@ return; } - /* - If the device is currently configured and active, we won't - actually delete it yet. Instead, it is marked so that when - the release() function is called, that will trigger a proper - detach(). - */ if (link->state & DEV_CONFIG) { -#ifdef PCMCIA_DEBUG - printk(KERN_DEBUG "orinoco_cs: detach postponed, '%s' " - "still locked\n", link->dev->dev_name); -#endif - link->state |= DEV_STALE_LINK; - return; + orinoco_cs_release((u_long)link); + if (link->state & DEV_CONFIG) { + link->state |= DEV_STALE_LINK; + return; + } } /* Break the link with Card Services */ @@ -472,7 +463,7 @@ link->irq.IRQInfo2 |= 1 << irq_list[i]; link->irq.Handler = orinoco_interrupt; - link->irq.Instance = priv; + link->irq.Instance = dev; CS_CHECK(RequestIRQ, link->handle, &link->irq); } @@ -549,18 +540,13 @@ dev_link_t *link = (dev_link_t *) arg; struct net_device *dev = link->priv; struct orinoco_private *priv = dev->priv; + unsigned long flags; - /* - If the device is currently in use, we won't release until it - is actually closed, because until then, we can't be sure that - no one will try to access the device or its data structures. - */ - if (priv->open) { - DEBUG(0, "orinoco_cs: release postponed, '%s' still open\n", - link->dev->dev_name); - link->state |= DEV_STALE_CONFIG; - return; - } + /* We're committed to taking the device away now, so mark the + * hardware as unavailable */ + spin_lock_irqsave(&priv->lock, flags); + priv->hw_unavailable++; + spin_unlock_irqrestore(&priv->lock, flags); /* Don't bother checking to see if these succeed or not */ CardServices(ReleaseConfiguration, link->handle); @@ -593,14 +579,9 @@ orinoco_lock(priv, &flags); netif_device_detach(dev); - priv->hw_unavailable = 1; + priv->hw_unavailable++; orinoco_unlock(priv, &flags); - -/* if (link->open) */ -/* orinoco_cs_stop(dev); */ - - mod_timer(&link->release, jiffies + HZ / 20); } break; @@ -619,13 +600,8 @@ a better way, short of rewriting the PCMCIA layer to not suck :-( */ if (! test_bit(0, &card->hard_reset_in_progress)) { - err = orinoco_lock(priv, &flags); - if (err) { - printk(KERN_ERR "%s: hw_unavailable on SUSPEND/RESET_PHYSICAL\n", - dev->name); - break; - } - + spin_lock_irqsave(&priv->lock, flags); + err = __orinoco_down(dev); if (err) printk(KERN_WARNING "%s: %s: Error %d downing interface\n", @@ -634,9 +610,9 @@ err); netif_device_detach(dev); - priv->hw_unavailable = 1; - - orinoco_unlock(priv, &flags); + priv->hw_unavailable++; + + spin_unlock_irqrestore(&priv->lock, flags); } CardServices(ReleaseConfiguration, link->handle); @@ -653,10 +629,6 @@ CardServices(RequestConfiguration, link->handle, &link->conf); - /* If we're only getting these events because - of the ResetCard in the hard reset, we - don't need to do anything - orinoco_reset() - will handle reinitialization. */ if (! test_bit(0, &card->hard_reset_in_progress)) { err = orinoco_reinit_firmware(dev); if (err) { @@ -668,9 +640,9 @@ spin_lock_irqsave(&priv->lock, flags); netif_device_attach(dev); - priv->hw_unavailable = 0; + priv->hw_unavailable--; - if (priv->open) { + if (priv->open && ! priv->hw_unavailable) { err = __orinoco_up(dev); if (err) printk(KERN_ERR "%s: Error %d restarting card\n", @@ -678,7 +650,7 @@ } - orinoco_unlock(priv, &flags); + spin_unlock_irqrestore(&priv->lock, flags); } } break; @@ -693,7 +665,7 @@ /* Can't be declared "const" or the whole __initdata section will * become const */ -static char version[] __initdata = "orinoco_cs.c 0.13b (David Gibson and others)"; +static char version[] __initdata = "orinoco_cs.c 0.13d (David Gibson and others)"; static int __init init_orinoco_cs(void) @@ -722,7 +694,6 @@ if (dev_list) DEBUG(0, "orinoco_cs: Removing leftover devices.\n"); while (dev_list != NULL) { - del_timer(&dev_list->release); if (dev_list->state & DEV_CONFIG) orinoco_cs_release((u_long) dev_list); orinoco_cs_detach(dev_list); diff -uNr linux-2.4.21/drivers/net/wireless/orinoco_pci.c linux-2.4.21-ben2/drivers/net/wireless/orinoco_pci.c --- linux-2.4.21/drivers/net/wireless/orinoco_pci.c 2003-06-13 16:51:35.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/wireless/orinoco_pci.c 2003-06-27 15:41:24.000000000 +0200 @@ -1,4 +1,4 @@ -/* orinoco_pci.c 0.13b +/* orinoco_pci.c 0.13d * * Driver for Prism II devices that have a direct PCI interface * (i.e., not in a Pcmcia or PLX bridge) @@ -143,8 +143,6 @@ unsigned long timeout; u16 reg; - TRACE_ENTER(priv->ndev->name); - /* Assert the reset until the card notice */ hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK); printk(KERN_NOTICE "Reset done"); @@ -181,8 +179,6 @@ } printk(KERN_NOTICE "pci_cor : reg = 0x%X - %lX - %lX\n", reg, timeout, jiffies); - TRACE_EXIT(priv->ndev->name); - return 0; } @@ -232,7 +228,7 @@ hermes_struct_init(&(priv->hw), dev->base_addr, HERMES_MEM, HERMES_32BIT_REGSPACING); pci_set_drvdata(pdev, dev); - err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name, priv); + err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name, dev); if (err) { printk(KERN_ERR "orinoco_pci: Error allocating IRQ %d.\n", pdev->irq); err = -EBUSY; @@ -264,7 +260,7 @@ unregister_netdev(dev); if (dev->irq) - free_irq(dev->irq, priv); + free_irq(dev->irq, dev); kfree(dev); } @@ -286,7 +282,7 @@ unregister_netdev(dev); if (dev->irq) - free_irq(dev->irq, priv); + free_irq(dev->irq, dev); if (priv->hw.iobase) iounmap((unsigned char *) priv->hw.iobase); @@ -321,7 +317,7 @@ netif_device_detach(dev); - priv->hw_unavailable = 1; + priv->hw_unavailable++; orinoco_unlock(priv, &flags); @@ -348,15 +344,15 @@ netif_device_attach(dev); - if (priv->open) { + priv->hw_unavailable--; + + if (priv->open && (! priv->hw_unavailable)) { err = __orinoco_up(dev); if (err) printk(KERN_ERR "%s: Error %d restarting card on orinoco_pci_resume()\n", dev->name, err); } - priv->hw_unavailable = 0; - spin_unlock_irqrestore(&priv->lock, flags); return 0; @@ -378,7 +374,7 @@ .resume = orinoco_pci_resume, }; -static char version[] __initdata = "orinoco_pci.c 0.13b (David Gibson & Jean Tourrilhes )"; +static char version[] __initdata = "orinoco_pci.c 0.13d (David Gibson & Jean Tourrilhes )"; MODULE_AUTHOR("David Gibson "); MODULE_DESCRIPTION("Driver for wireless LAN cards using direct PCI interface"); MODULE_LICENSE("Dual MPL/GPL"); diff -uNr linux-2.4.21/drivers/net/wireless/orinoco_plx.c linux-2.4.21-ben2/drivers/net/wireless/orinoco_plx.c --- linux-2.4.21/drivers/net/wireless/orinoco_plx.c 2003-06-13 16:51:35.000000000 +0200 +++ linux-2.4.21-ben2/drivers/net/wireless/orinoco_plx.c 2003-06-27 15:41:04.000000000 +0200 @@ -1,4 +1,4 @@ -/* orinoco_plx.c 0.13b +/* orinoco_plx.c 0.13d * * Driver for Prism II devices which would usually be driven by orinoco_cs, * but are connected to the PCI bus by a PLX9052. @@ -243,7 +243,7 @@ HERMES_IO, HERMES_16BIT_REGSPACING); pci_set_drvdata(pdev, dev); - err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name, priv); + err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name, dev); if (err) { printk(KERN_ERR "orinoco_plx: Error allocating IRQ %d.\n", pdev->irq); err = -EBUSY; @@ -266,7 +266,7 @@ unregister_netdev(dev); if (dev->irq) - free_irq(dev->irq, priv); + free_irq(dev->irq, dev); kfree(priv); } @@ -285,7 +285,6 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - struct orinoco_private *priv = dev->priv; if (! dev) BUG(); @@ -293,7 +292,7 @@ unregister_netdev(dev); if (dev->irq) - free_irq(dev->irq, priv); + free_irq(dev->irq, dev); pci_set_drvdata(pdev, NULL); @@ -334,7 +333,7 @@ .resume = 0, }; -static char version[] __initdata = "orinoco_plx.c 0.13b (Daniel Barlow , David Gibson )"; +static char version[] __initdata = "orinoco_plx.c 0.13d (Daniel Barlow , David Gibson )"; MODULE_AUTHOR("Daniel Barlow "); MODULE_DESCRIPTION("Driver for wireless LAN cards using the PLX9052 PCI bridge"); #ifdef MODULE_LICENSE diff -uNr linux-2.4.21/drivers/net/wireless/orinoco_tmd.c linux-2.4.21-ben2/drivers/net/wireless/orinoco_tmd.c --- linux-2.4.21/drivers/net/wireless/orinoco_tmd.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/drivers/net/wireless/orinoco_tmd.c 2003-06-27 15:41:06.000000000 +0200 @@ -0,0 +1,240 @@ +/* orinoco_tmd.c 0.01 + * + * Driver for Prism II devices which would usually be driven by orinoco_cs, + * but are connected to the PCI bus by a TMD7160. + * + * Copyright (C) 2003 Joerg Dorchain + * based heavily upon orinoco_plx.c Copyright (C) 2001 Daniel Barlow + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License version 2 (the "GPL"), in + * which case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use your + * version of this file under the MPL, indicate your decision by + * deleting the provisions above and replace them with the notice and + * other provisions required by the GPL. If you do not delete the + * provisions above, a recipient may use your version of this file + * under either the MPL or the GPL. + + * Caution: this is experimental and probably buggy. For success and + * failure reports for different cards and adaptors, see + * orinoco_tmd_pci_id_table near the end of the file. If you have a + * card we don't have the PCI id for, and looks like it should work, + * drop me mail with the id and "it works"/"it doesn't work". + * + * Note: if everything gets detected fine but it doesn't actually send + * or receive packets, your first port of call should probably be to + * try newer firmware in the card. Especially if you're doing Ad-Hoc + * modes + * + * The actual driving is done by orinoco.c, this is just resource + * allocation stuff. + * + * This driver is modeled after the orinoco_plx driver. The main + * difference is that the TMD chip has only IO port ranges and no + * memory space, i.e. no access to the CIS. Compared to the PLX chip, + * the io range functionalities are exchanged. + * + * Pheecom sells cards with the TMD chip as "ASIC version" + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "hermes.h" +#include "orinoco.h" + +static char dev_info[] = "orinoco_tmd"; + +#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA | COR_FUNC_ENA) /* Enable PC card with level triggered irqs and irq requests */ + + +static int orinoco_tmd_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int err = 0; + u32 reg, addr; + struct orinoco_private *priv = NULL; + unsigned long pccard_ioaddr = 0; + unsigned long pccard_iolen = 0; + struct net_device *dev = NULL; + int netdev_registered = 0; + + err = pci_enable_device(pdev); + if (err) + return -EIO; + + printk(KERN_DEBUG "TMD setup\n"); + pccard_ioaddr = pci_resource_start(pdev, 2); + pccard_iolen = pci_resource_len(pdev, 2); + if (! request_region(pccard_ioaddr, pccard_iolen, dev_info)) { + printk(KERN_ERR "orinoco_tmd: I/O resource at 0x%lx len 0x%lx busy\n", + pccard_ioaddr, pccard_iolen); + pccard_ioaddr = 0; + err = -EBUSY; + goto fail; + } + addr = pci_resource_start(pdev, 1); + outb(COR_VALUE, addr); + mdelay(1); + reg = inb(addr); + if (reg != COR_VALUE) { + printk(KERN_ERR "orinoco_tmd: Error setting TMD COR values %x should be %x\n", reg, COR_VALUE); + err = -EIO; + goto fail; + } + + dev = alloc_orinocodev(0, NULL); + if (! dev) { + err = -ENOMEM; + goto fail; + } + + priv = dev->priv; + dev->base_addr = pccard_ioaddr; + SET_MODULE_OWNER(dev); + + printk(KERN_DEBUG + "Detected Orinoco/Prism2 TMD device at %s irq:%d, io addr:0x%lx\n", + pdev->slot_name, pdev->irq, pccard_ioaddr); + + hermes_struct_init(&(priv->hw), dev->base_addr, + HERMES_IO, HERMES_16BIT_REGSPACING); + pci_set_drvdata(pdev, dev); + + err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, dev->name, + dev); + if (err) { + printk(KERN_ERR "orinoco_tmd: Error allocating IRQ %d.\n", + pdev->irq); + err = -EBUSY; + goto fail; + } + dev->irq = pdev->irq; + + err = register_netdev(dev); + if (err) + goto fail; + netdev_registered = 1; + + return 0; /* succeeded */ + + fail: + printk(KERN_DEBUG "orinoco_tmd: init_one(), FAIL!\n"); + + if (priv) { + if (dev->irq) + free_irq(dev->irq, dev); + + kfree(priv); + } + + if (pccard_ioaddr) + release_region(pccard_ioaddr, pccard_iolen); + + pci_disable_device(pdev); + + return err; +} + +static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + + if (! dev) + BUG(); + + unregister_netdev(dev); + + if (dev->irq) + free_irq(dev->irq, dev); + + pci_set_drvdata(pdev, NULL); + + kfree(dev); + + release_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); + + pci_disable_device(pdev); +} + + +static struct pci_device_id orinoco_tmd_pci_id_table[] __devinitdata = { + {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */ + {0,}, +}; + +MODULE_DEVICE_TABLE(pci, orinoco_tmd_pci_id_table); + +static struct pci_driver orinoco_tmd_driver = { + .name = "orinoco_tmd", + .id_table = orinoco_tmd_pci_id_table, + .probe = orinoco_tmd_init_one, + .remove = __devexit_p(orinoco_tmd_remove_one), + .suspend = 0, + .resume = 0, +}; + +static char version[] __initdata = "orinoco_tmd.c 0.01 (Joerg Dorchain )"; +MODULE_AUTHOR("Joerg Dorchain "); +MODULE_DESCRIPTION("Driver for wireless LAN cards using the TMD7160 PCI bridge"); +#ifdef MODULE_LICENSE +MODULE_LICENSE("Dual MPL/GPL"); +#endif + +static int __init orinoco_tmd_init(void) +{ + printk(KERN_DEBUG "%s\n", version); + return pci_module_init(&orinoco_tmd_driver); +} + +extern void __exit orinoco_tmd_exit(void) +{ + pci_unregister_driver(&orinoco_tmd_driver); + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(HZ); +} + +module_init(orinoco_tmd_init); +module_exit(orinoco_tmd_exit); + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff -uNr linux-2.4.21/drivers/pci/pci.c linux-2.4.21-ben2/drivers/pci/pci.c --- linux-2.4.21/drivers/pci/pci.c 2003-06-13 16:51:35.000000000 +0200 +++ linux-2.4.21-ben2/drivers/pci/pci.c 2003-06-27 15:41:19.000000000 +0200 @@ -28,7 +28,7 @@ #include #include /* isa_dma_bridge_buggy */ -#undef DEBUG +#define DEBUG #ifdef DEBUG #define DBG(x...) printk(x) @@ -1059,16 +1059,23 @@ unsigned int pos, reg, next; u32 l, sz; struct resource *res; + int is_kl = (dev->device == 0x22 && dev->vendor == 0x106b); + if (is_kl) + howmany = 1; for(pos=0; posresource[pos]; res->name = dev->name; reg = PCI_BASE_ADDRESS_0 + (pos << 2); pci_read_config_dword(dev, reg, &l); - pci_write_config_dword(dev, reg, ~0); - pci_read_config_dword(dev, reg, &sz); - pci_write_config_dword(dev, reg, l); + if (is_kl) + sz = 0x00080000; + else { + pci_write_config_dword(dev, reg, ~0); + pci_read_config_dword(dev, reg, &sz); + pci_write_config_dword(dev, reg, l); + } if (!sz || sz == 0xffffffff) continue; if (l == 0xffffffff) @@ -1309,7 +1316,7 @@ if (!pass) return max; pci_read_config_word(dev, PCI_COMMAND, &cr); - pci_write_config_word(dev, PCI_COMMAND, 0x0000); + //pci_write_config_word(dev, PCI_COMMAND, 0x0000); pci_write_config_word(dev, PCI_STATUS, 0xffff); child = pci_add_new_bus(bus, dev, ++max); diff -uNr linux-2.4.21/drivers/sound/dmasound/Config.in linux-2.4.21-ben2/drivers/sound/dmasound/Config.in --- linux-2.4.21/drivers/sound/dmasound/Config.in 2002-02-25 20:38:04.000000000 +0100 +++ linux-2.4.21-ben2/drivers/sound/dmasound/Config.in 2003-06-27 15:41:08.000000000 +0200 @@ -27,13 +27,27 @@ fi # the new dmasound_pmac driver needs access to the i2c bus +# and nvram. if [ "$CONFIG_DMASOUND_PMAC" = "y" ] ; then - define_tristate CONFIG_I2C y - define_tristate CONFIG_I2C_KEYWEST y + if [ "$CONFIG_I2C" != "y" ]; then + define_tristate CONFIG_I2C y + fi + if [ "$CONFIG_I2C_KEYWEST" != "y" ]; then + define_tristate CONFIG_I2C_KEYWEST y + fi + if [ "$CONFIG_NVRAM" != "y" -a "$CONFIG_NVRAM" != "m" ]; then + define_tristate CONFIG_NVRAM y + fi else if [ "$CONFIG_DMASOUND_PMAC" = "m" ] ; then - define_tristate CONFIG_I2C m - define_tristate CONFIG_I2C_KEYWEST m + if [ "$CONFIG_I2C" != "y" -a "$CONFIG_I2C" != "m" ]; then + define_tristate CONFIG_I2C m + fi + if [ "$CONFIG_I2C_KEYWEST" != "y" -a "$CONFIG_I2C_KEYWEST" != "m" ]; then + define_tristate CONFIG_I2C_KEYWEST m + fi + if [ "$CONFIG_NVRAM" != "y" -a "$CONFIG_NVRAM" != "m" ]; then + define_tristate CONFIG_NVRAM y + fi fi fi - diff -uNr linux-2.4.21/drivers/sound/dmasound/Makefile linux-2.4.21-ben2/drivers/sound/dmasound/Makefile --- linux-2.4.21/drivers/sound/dmasound/Makefile 2002-02-25 20:38:04.000000000 +0100 +++ linux-2.4.21-ben2/drivers/sound/dmasound/Makefile 2003-06-27 15:41:25.000000000 +0200 @@ -13,7 +13,8 @@ list-multi := dmasound_pmac.o -dmasound_pmac-objs := dmasound_awacs.o trans_16.o tas3001c.o dac3550a.o +dmasound_pmac-objs := dmasound_awacs.o trans_16.o dac3550a.o tas_common.o \ + tas3001c.o tas3001c_tables.o tas3004.o tas3004_tables.o obj-$(CONFIG_DMASOUND) += dmasound_core.o obj-$(CONFIG_DMASOUND_ATARI) += dmasound_atari.o diff -uNr linux-2.4.21/drivers/sound/dmasound/awacs_defs.h linux-2.4.21-ben2/drivers/sound/dmasound/awacs_defs.h --- linux-2.4.21/drivers/sound/dmasound/awacs_defs.h 2002-02-25 20:38:04.000000000 +0100 +++ linux-2.4.21-ben2/drivers/sound/dmasound/awacs_defs.h 2003-06-27 15:41:50.000000000 +0200 @@ -168,8 +168,9 @@ #define RATE_LOW 1 /* HIGH = 48kHz, etc; LOW = 44.1kHz, etc. */ - +/*******************/ /* Burgundy values */ +/*******************/ #define MASK_ADDR_BURGUNDY_INPSEL21 (0x11 << 12) #define MASK_ADDR_BURGUNDY_INPSEL3 (0x12 << 12) @@ -232,4 +233,19 @@ #define DEF_BURGUNDY_ATTENLINEOUT (0xCC) #define DEF_BURGUNDY_ATTENHP (0xCC) +/*********************/ +/* i2s layout values */ +/*********************/ + +#define I2S_REG_INT_CTL 0x00 +#define I2S_REG_SERIAL_FORMAT 0x10 +#define I2S_REG_CODEC_MSG_OUT 0x20 +#define I2S_REG_CODEC_MSG_IN 0x30 +#define I2S_REG_FRAME_COUNT 0x40 +#define I2S_REG_FRAME_MATCH 0x50 +#define I2S_REG_DATAWORD_SIZES 0x60 +#define I2S_REG_PEAKLEVEL_SEL 0x70 +#define I2S_REG_PEAKLEVEL_IN0 0x80 +#define I2S_REG_PEAKLEVEL_IN1 0x90 + #endif /* _AWACS_DEFS_H_ */ diff -uNr linux-2.4.21/drivers/sound/dmasound/dmasound_awacs.c linux-2.4.21-ben2/drivers/sound/dmasound/dmasound_awacs.c --- linux-2.4.21/drivers/sound/dmasound/dmasound_awacs.c 2002-08-03 02:39:44.000000000 +0200 +++ linux-2.4.21-ben2/drivers/sound/dmasound/dmasound_awacs.c 2003-06-27 15:41:51.000000000 +0200 @@ -45,7 +45,14 @@ * 01/02/2002 [0.7] - BenH * - all sort of minor bits went in since the latest update, I * bumped the version number for that reason -*/ + * + * 07/26/2002 [0.8] - BenH + * - More minor bits since last changelog (I should be more careful + * with those) + * - Support for snapper & better tumbler integration by Toby Sargeant + * - Headphone detect for scremer by Julien Blache + * - More tumbler fixed by Andreas Schwab + */ /* GENERAL FIXME/TODO: check that the assumptions about what is written to mac-io is valid for DACA & Tumbler. @@ -88,10 +95,14 @@ #include "awacs_defs.h" #include "dmasound.h" +#include "tas3001c.h" +#include "tas3004.h" +#include "tas_common.h" #define DMASOUND_AWACS_REVISION 0 #define DMASOUND_AWACS_EDITION 7 +#define AWACS_SNAPPER 110 /* fake revision # for snapper */ #define AWACS_BURGUNDY 100 /* fake revision # for burgundy */ #define AWACS_TUMBLER 90 /* fake revision # for tumbler */ #define AWACS_DACA 80 /* fake revision # for daca (ibook) */ @@ -102,11 +113,13 @@ */ static int awacs_irq, awacs_tx_irq, awacs_rx_irq; static volatile struct awacs_regs *awacs; +static volatile u32 *i2s; static volatile struct dbdma_regs *awacs_txdma, *awacs_rxdma; static int awacs_rate_index; static int awacs_subframe; static int awacs_spkr_vol; static struct device_node* awacs_node; +static struct device_node* i2s_node; static char awacs_name[64]; static int awacs_revision; @@ -163,6 +176,8 @@ static int cd_lev = 0x6363 ; /* 99 % */ static int line_lev = 0 ; +static int hdp_connected = 0; + /* * Stuff for outputting a beep. The values range from -327 to +327 * so we can multiply by an amplitude in the range 0..100 to get a @@ -293,19 +308,6 @@ extern int daca_enter_sleep(void); extern int daca_leave_sleep(void); -extern int tas_init(void); -extern int tas_cleanup(void); -extern int tumbler_set_volume(uint left_vol, uint right_vol); -extern void tumbler_get_volume(uint * left_vol, uint *right_vol); -extern void tumbler_set_treble(int treble); -extern void tumbler_get_treble(int *treble); -extern void tumbler_set_bass(int bass); -extern void tumbler_get_bass(int *bass); -extern void tumbler_set_pcm_lvl(int pcm_lvl); -extern void tumbler_get_pcm_lvl(int *pcm_lvl); -extern int tumbler_enter_sleep(void); -extern int tumbler_leave_sleep(void); - #define TRY_LOCK() \ if ((rc = down_interruptible(&dmasound_sem)) != 0) \ return rc; @@ -332,7 +334,7 @@ } -/*** AE - TUMBLER START *********************************************************/ +/*** AE - TUMBLER / SNAPPER START ************************************************/ int gpio_audio_reset, gpio_audio_reset_pol; @@ -394,17 +396,22 @@ return ((pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio_addr, 0) & 0x02) !=0); } +/* + * Headphone interrupt via GPIO (Tumbler, Snapper, DACA) + */ static void headphone_intr(int irq, void *devid, struct pt_regs *regs) { if (read_audio_gpio(gpio_headphone_detect) == gpio_headphone_detect_pol) { printk(KERN_INFO "Audio jack plugged, muting speakers.\n"); - write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol); write_audio_gpio(gpio_headphone_mute, !gpio_headphone_mute_pol); + write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol); + tas_output_device_change(sound_device_id,TAS_OUTPUT_HEADPHONES,0); } else { printk(KERN_INFO "Audio jack unplugged, enabling speakers.\n"); write_audio_gpio(gpio_amp_mute, !gpio_amp_mute_pol); write_audio_gpio(gpio_headphone_mute, gpio_headphone_mute_pol); + tas_output_device_change(sound_device_id,TAS_OUTPUT_INTERNAL_SPKR,0); } } @@ -412,7 +419,7 @@ /* Initialize tumbler */ static int -awacs_tumbler_init(void) +tas_dmasound_init(void) { setup_audio_gpio( "audio-hw-reset", @@ -469,15 +476,124 @@ static int -awacs_tumbler_cleanup(void) +tas_dmasound_cleanup(void) { if (gpio_headphone_irq) free_irq(gpio_headphone_irq, 0); return 0; } +/* We don't support 48k yet */ +static int tas_freqs[1] = { 44100 } ; +static int tas_freqs_ok[1] = { 1 } ; -/*** AE - TUMBLER END *********************************************************/ +/* don't know what to do really - just have to leave it where + * OF left things +*/ + +static int +tas_set_frame_rate(void) +{ + if (i2s) { + out_le32(i2s + (I2S_REG_SERIAL_FORMAT >> 2), 0x41190000); + out_le32(i2s + (I2S_REG_DATAWORD_SIZES >> 2), 0x02000200); + } + dmasound.hard.speed = 44100 ; + awacs_rate_index = 0 ; + return 44100 ; +} + +static int +tas_mixer_ioctl(u_int cmd, u_long arg) +{ + int data; + int rc; + + rc=tas_device_ioctl(cmd, arg); + if (rc != -EINVAL) { + return rc; + } + + if ((cmd & ~0xff) == MIXER_WRITE(0) && + tas_supported_mixers() & (1<<(cmd & 0xff))) { + rc = get_user(data, (int *)(arg)); + if (rc<0) return rc; + tas_set_mixer_level(cmd & 0xff, data); + tas_get_mixer_level(cmd & 0xff, &data); + return ioctl_return2((int *)(arg), data); + } + if ((cmd & ~0xff) == MIXER_READ(0) && + tas_supported_mixers() & (1<<(cmd & 0xff))) { + tas_get_mixer_level(cmd & 0xff, &data); + return ioctl_return2((int *)(arg), data); + } + + switch(cmd) { + case SOUND_MIXER_READ_DEVMASK: + data = tas_supported_mixers() | SOUND_MASK_SPEAKER; + rc = IOCTL_OUT(arg, data); + break; + case SOUND_MIXER_READ_STEREODEVS: + data = tas_stereo_mixers(); + rc = IOCTL_OUT(arg, data); + break; + case SOUND_MIXER_READ_CAPS: + rc = IOCTL_OUT(arg, 0); + break; + case SOUND_MIXER_READ_RECMASK: + data = 0; + rc = IOCTL_OUT(arg, data); + break; + case SOUND_MIXER_READ_RECSRC: + data = 0; + rc = IOCTL_OUT(arg, data); + break; + case SOUND_MIXER_WRITE_RECSRC: + IOCTL_IN(arg, data); + data =0; + rc = IOCTL_OUT(arg, data); + break; + case SOUND_MIXER_WRITE_SPEAKER: /* really bell volume */ + IOCTL_IN(arg, data); + beep_vol = data & 0xff; + /* fall through */ + case SOUND_MIXER_READ_SPEAKER: + rc = IOCTL_OUT(arg, (beep_vol<<8) | beep_vol); + break; + case SOUND_MIXER_OUTMASK: + case SOUND_MIXER_OUTSRC: + default: + rc = -EINVAL; + } + + return rc; +} + +static void __init +tas_init_frame_rates(unsigned int *prop, unsigned int l) +{ + int i ; + if (prop) { + for (i=0; i<1; i++) + tas_freqs_ok[i] = 0; + for (l /= sizeof(int); l > 0; --l) { + unsigned int r = *prop++; + /* Apple 'Fixed' format */ + if (r >= 0x10000) + r >>= 16; + for (i = 0; i < 1; ++i) { + if (r == tas_freqs[i]) { + tas_freqs_ok[i] = 1; + break; + } + } + } + } + /* else we assume that all the rates are available */ +} + + +/*** AE - TUMBLER / SNAPPER END ************************************************/ @@ -509,8 +625,10 @@ static int __init PMacIrqInit(void) { - if (request_irq(awacs_irq, pmac_awacs_intr, 0, "Built-in Sound misc", 0) - || request_irq(awacs_tx_irq, pmac_awacs_tx_intr, 0, "Built-in Sound out", 0) + if (awacs) + if (request_irq(awacs_irq, pmac_awacs_intr, 0, "Built-in Sound misc", 0)) + return 0; + if (request_irq(awacs_tx_irq, pmac_awacs_tx_intr, 0, "Built-in Sound out", 0) || request_irq(awacs_rx_irq, pmac_awacs_rx_intr, 0, "Built-in Sound in", 0)) return 0; return 1; @@ -523,23 +641,28 @@ DBDMA_DO_STOP(awacs_txdma); DBDMA_DO_STOP(awacs_rxdma); - /* disable interrupts from awacs interface */ - out_le32(&awacs->control, in_le32(&awacs->control) & 0xfff); - + if (awacs) + /* disable interrupts from awacs interface */ + out_le32(&awacs->control, in_le32(&awacs->control) & 0xfff); + /* Switch off the sound clock */ pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, awacs_node, 0, 0); /* Make sure proper bits are set on pismo & tipb */ - if (machine_is_compatible("PowerBook3,1") || - machine_is_compatible("PowerBook3,2")) { + if ((machine_is_compatible("PowerBook3,1") || + machine_is_compatible("PowerBook3,2")) && awacs) { awacs_reg[1] |= MASK_PAROUT0 | MASK_PAROUT1; awacs_write(MASK_ADDR1 | awacs_reg[1]); wait_ms(200); } - free_irq(awacs_irq, 0); + if (awacs) + free_irq(awacs_irq, 0); free_irq(awacs_tx_irq, 0); free_irq(awacs_rx_irq, 0); - /* all OF versions I've seen use this value */ - iounmap((void *)awacs); + + if (awacs) + iounmap((void *)awacs); + if (i2s) + iounmap((void *)i2s); iounmap((void *)awacs_txdma); iounmap((void *)awacs_rxdma); @@ -555,7 +678,9 @@ kfree(beep_dbdma_cmd_space); if (beep_buf) { kfree(beep_buf); +#ifdef CONFIG_VT kd_mksound = orig_mksound; +#endif } #ifdef CONFIG_PMAC_PBOOK pmu_unregister_sleep_notifier(&awacs_sleep_notifier); @@ -569,26 +694,16 @@ DBDMA_DO_STOP(awacs_txdma); } -static int tumbler_freqs[2] = { 48000, 44100 } ; -static int tumbler_freqs_ok[2] = { 1, 1 } ; - -/* don't know what to do really - just have to leave it where - * OF left things -*/ - -static int tumbler_set_frame_rate(void) -{ - dmasound.hard.speed = 44100 ; - awacs_rate_index = 0 ; - return 44100 ; -} - /* don't know what to do really - just have to leave it where * OF left things */ static int daca_set_frame_rate(void) { + if (i2s) { + out_le32(i2s + (I2S_REG_SERIAL_FORMAT >> 2), 0x41190000); + out_le32(i2s + (I2S_REG_DATAWORD_SIZES >> 2), 0x02000200); + } dmasound.hard.speed = 44100 ; awacs_rate_index = 0 ; return 44100 ; @@ -599,7 +714,8 @@ }; static int awacs_freqs_ok[8] = { 1, 1, 1, 1, 1, 1, 1, 1 }; -static int awacs_set_frame_rate(int desired, int catch_r) +static int +awacs_set_frame_rate(int desired, int catch_r) { int tolerance, i = 8 ; /* @@ -623,13 +739,9 @@ return dmasound.hard.speed; } -static int burgundy_frame_rates = 1 ; -static int burgundy_set_frame_rate(void) +static int +burgundy_set_frame_rate(void) { -#ifdef DEBUG_DMASOUND -if (burgundy_frame_rates > 1) - printk("dmasound_pmac: warning Burgundy had more than one frame rate\n"); -#endif awacs_rate_index = 0 ; awacs_reg[1] = (awacs_reg[1] & ~MASK_SAMPLERATE) ; /* XXX disable error interrupt on burgundy for now */ @@ -637,24 +749,24 @@ return 44100 ; } -static int set_frame_rate(int desired, int catch_r) +static int +set_frame_rate(int desired, int catch_r) { switch (awacs_revision) { case AWACS_BURGUNDY: - dmasound.hard.speed = - burgundy_set_frame_rate(); + dmasound.hard.speed = burgundy_set_frame_rate(); break ; case AWACS_TUMBLER: - dmasound.hard.speed = - tumbler_set_frame_rate(); + case AWACS_SNAPPER: + dmasound.hard.speed = tas_set_frame_rate(); break ; case AWACS_DACA: dmasound.hard.speed = daca_set_frame_rate(); break ; default: - dmasound.hard.speed = - awacs_set_frame_rate(desired, catch_r); + dmasound.hard.speed = awacs_set_frame_rate(desired, + catch_r); break ; } return dmasound.hard.speed ; @@ -704,11 +816,13 @@ dmasound.trans_write = &transAwacsExpand; dmasound.trans_read = &transAwacsNormalRead; - if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE)) - out_le32(&awacs->byteswap, BS_VAL); - else - out_le32(&awacs->byteswap, 0); - + if (awacs) { + if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE)) + out_le32(&awacs->byteswap, BS_VAL); + else + out_le32(&awacs->byteswap, 0); + } + expand_bal = -dmasound.soft.speed; } @@ -793,7 +907,20 @@ static int PMacSetVolume(int volume) { - return awacs_volume_setter(volume, 2, MASK_AMUTE, 6); + printk(KERN_WARNING "Bogus call to PMacSetVolume !\n"); + return 0; +} + +static void awacs_setup_for_beep(int speed) +{ + out_le32(&awacs->control, + (in_le32(&awacs->control) & ~0x1f00) + | ((speed > 0 ? speed : awacs_rate_index) << 8)); + + if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE) && speed == -1) + out_le32(&awacs->byteswap, BS_VAL); + else + out_le32(&awacs->byteswap, 0); } static void __PMacPlay(void) @@ -816,15 +943,8 @@ out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); while ( (in_le32(&awacs_txdma->status) & RUN) && count--) udelay(1); - /* FIXME: check that this is OK for other chip sets */ - out_le32(&awacs->control, - (in_le32(&awacs->control) & ~0x1f00) - | (awacs_rate_index << 8)); - - if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE)) - out_le32(&awacs->byteswap, BS_VAL); - else - out_le32(&awacs->byteswap, 0); + if (awacs) + awacs_setup_for_beep(-1); out_le32(&awacs_txdma->cmdptr, virt_to_bus(&(awacs_tx_cmds[next_frg]))); @@ -925,6 +1045,7 @@ { int i = write_sq.front; int stat; + int i_nowrap = write_sq.front; volatile struct dbdma_cmd *cp; /* != 0 when we are dealing with a DEAD xfer */ static int emergency_in_use = 0 ; @@ -981,6 +1102,7 @@ emergency_in_use = 0 ; /* done that */ --write_sq.count; --write_sq.active; + i_nowrap++; if (++i >= write_sq.max_count) i = 0; } @@ -993,7 +1115,7 @@ } /* if we used some data up then wake the writer to supply some more*/ - if (i != write_sq.front) + if (i_nowrap != write_sq.front) WAKE_UP(write_sq.action_queue); write_sq.front = i; @@ -1090,9 +1212,26 @@ pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs) { int ctrl = in_le32(&awacs->control); + int status = in_le32(&awacs->codec_stat); + int r1; - if (ctrl & MASK_PORTCHG) { - /* do something when headphone is plugged/unplugged? */ + if (ctrl & MASK_PORTCHG) { + /* tested on Screamer, should work on others too */ + if (awacs_revision == AWACS_SCREAMER) { + if (((status & MASK_HDPCONN) >> 3) && (hdp_connected == 0)) { + hdp_connected = 1; + + r1 = awacs_reg[1] | MASK_SPKMUTE; + awacs_reg[1] = r1; + awacs_write(r1 | MASK_ADDR_MUTE); + } else if (((status & MASK_HDPCONN) >> 3 == 0) && (hdp_connected == 1)) { + hdp_connected = 0; + + r1 = awacs_reg[1] & ~MASK_SPKMUTE; + awacs_reg[1] = r1; + awacs_write(r1 | MASK_ADDR_MUTE); + } + } } if (ctrl & MASK_CNTLERR) { int err = (in_le32(&awacs->codec_stat) & MASK_ERRCODE) >> 16; @@ -1108,7 +1247,7 @@ awacs_write(int val) { int count = 300 ; - if (awacs_revision >= AWACS_DACA) + if (awacs_revision >= AWACS_DACA || !awacs) return ; while ((in_le32(&awacs->codec_ctrl) & MASK_NEWECMD) && count--) @@ -1131,14 +1270,8 @@ out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); while ((in_le32(&awacs_txdma->status) & RUN) && count--) udelay(1); - /* FIXME: check this is OK for DACA, Tumbler */ - out_le32(&awacs->control, - (in_le32(&awacs->control) & ~0x1f00) - | (awacs_rate_index << 8)); - if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE)) - out_le32(&awacs->byteswap, BS_VAL); - else - out_le32(&awacs->byteswap, 0); + if (awacs) + awacs_setup_for_beep(-1); beep_playing = 0; } restore_flags(flags); @@ -1233,11 +1366,8 @@ out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16); while ((in_le32(&awacs_txdma->status) & RUN) && count--) udelay(1); /* timeout > 2 samples at lowest rate*/ - /* FIXME: check this is OK on DACA, Tumbler */ - out_le32(&awacs->control, - (in_le32(&awacs->control) & ~0x1f00) - | (beep_speed << 8)); - out_le32(&awacs->byteswap, 0); /* force BE */ + if (awacs) + awacs_setup_for_beep(beep_speed); out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd)); (void)in_le32(&awacs_txdma->status); out_le32(&awacs_txdma->control, RUN | (RUN << 16)); @@ -1263,10 +1393,12 @@ awacs_write(awacs_reg[1] + MASK_ADDR1); awacs_write(awacs_reg[7] + MASK_ADDR7); } - if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE)) - out_le32(&awacs->byteswap, BS_VAL); - else - out_le32(&awacs->byteswap, 0); + if (awacs) { + if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE)) + out_le32(&awacs->byteswap, BS_VAL); + else + out_le32(&awacs->byteswap, 0); + } } #ifdef CONFIG_PMAC_PBOOK @@ -1293,9 +1425,18 @@ /* stop rx - if going - a bit of a daft user... but */ out_le32(&awacs_rxdma->control, (RUN|WAKE|FLUSH << 16)); /* deny interrupts */ + if (awacs) + disable_irq(awacs_irq); + disable_irq(awacs_tx_irq); + disable_irq(awacs_rx_irq); + /* Chip specific sleep code */ switch (awacs_revision) { case AWACS_TUMBLER: - tumbler_enter_sleep(); /* Stub for now */ + case AWACS_SNAPPER: + write_audio_gpio(gpio_headphone_mute, gpio_headphone_mute_pol); + write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol); + tas_enter_sleep(); + write_audio_gpio(gpio_audio_reset, gpio_audio_reset_pol); break ; case AWACS_DACA: daca_enter_sleep(); @@ -1308,17 +1449,14 @@ out_le32(&awacs->control, 0x11) ; break ; } - disable_irq(awacs_irq); - disable_irq(awacs_tx_irq); - disable_irq(awacs_rx_irq); /* Disable sound clock */ pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, awacs_node, 0, 0); /* According to Darwin, we do that after turning off the sound * chip clock. All this will have to be cleaned up once we properly * parse the OF sound-objects */ - if (machine_is_compatible("PowerBook3,1") || - machine_is_compatible("PowerBook3,2")) { + if ((machine_is_compatible("PowerBook3,1") || + machine_is_compatible("PowerBook3,2")) && awacs) { awacs_reg[1] |= MASK_PAROUT0 | MASK_PAROUT1; awacs_write(MASK_ADDR1 | awacs_reg[1]); wait_ms(200); @@ -1327,8 +1465,8 @@ case PBOOK_WAKE: /* Enable sound clock */ pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, awacs_node, 0, 1); - if (machine_is_compatible("PowerBook3,1") || - machine_is_compatible("PowerBook3,2")) { + if ((machine_is_compatible("PowerBook3,1") || + machine_is_compatible("PowerBook3,2")) && awacs) { wait_ms(100); awacs_reg[1] &= ~(MASK_PAROUT0 | MASK_PAROUT1); awacs_write(MASK_ADDR1 | awacs_reg[1]); @@ -1338,8 +1476,15 @@ /* restore settings */ switch (awacs_revision) { case AWACS_TUMBLER: + case AWACS_SNAPPER: + write_audio_gpio(gpio_headphone_mute, gpio_headphone_mute_pol); + write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol); + write_audio_gpio(gpio_audio_reset, gpio_audio_reset_pol); + wait_ms(100); + write_audio_gpio(gpio_audio_reset, !gpio_audio_reset_pol); + wait_ms(150); + tas_leave_sleep(); /* Stub for now */ headphone_intr(0,0,0); - tumbler_leave_sleep(); /* Stub for now */ break; case AWACS_DACA: wait_ms(10); /* Check this !!! */ @@ -1354,17 +1499,20 @@ break ; } /* Recalibrate chip */ - if (awacs_revision == AWACS_SCREAMER) + if (awacs_revision == AWACS_SCREAMER && awacs) awacs_recalibrate(); /* Make sure dma is stopped */ PMacSilence(); - enable_irq(awacs_irq); + if (awacs) + enable_irq(awacs_irq); enable_irq(awacs_tx_irq); enable_irq(awacs_rx_irq); - /* OK, allow ints back again */ - out_le32(&awacs->control, MASK_IEPC - | (awacs_rate_index << 8) | 0x11 - | (awacs_revision < AWACS_DACA ? MASK_IEE: 0)); + if (awacs) { + /* OK, allow ints back again */ + out_le32(&awacs->control, MASK_IEPC + | (awacs_rate_index << 8) | 0x11 + | (awacs_revision < AWACS_DACA ? MASK_IEE: 0)); + } if (macio_base && is_pbook_g3) { /* FIXME: should restore the setup we had...*/ out_8(macio_base + 0x37, 3); @@ -1952,7 +2100,7 @@ case SOUND_MIXER_READ_SPEAKER: data = awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER); data = (((data & 0xf)*100)/16) + ((((data>>4)*100)/16)<<8); - rc = IOCTL_OUT(arg, ~data); + rc = IOCTL_OUT(arg, (~data) & 0x0000ffff); break; case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */ IOCTL_IN(arg, data); @@ -2007,89 +2155,6 @@ return rc; } -static int tumbler_mixer_ioctl(u_int cmd, u_long arg) -{ - int data; - int rc; - - /* We are, we are, we are... Tumbler (and very dumb) */ - /* Ok, we're not THAT dumb anymore, but still pretty dumb :-) */ - - switch(cmd) { - case SOUND_MIXER_READ_DEVMASK: - data = SOUND_MASK_VOLUME | SOUND_MASK_ALTPCM | - SOUND_MASK_BASS | SOUND_MASK_TREBLE | - SOUND_MASK_PCM; - rc = IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_READ_RECMASK: - data = 0; - rc = IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_READ_RECSRC: - data = 0; - rc = IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_WRITE_RECSRC: - IOCTL_IN(arg, data); - data =0; - rc = IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_READ_STEREODEVS: - data = SOUND_MASK_VOLUME | SOUND_MASK_PCM; - rc = IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_READ_CAPS: - rc = IOCTL_OUT(arg, 0); - break; - case SOUND_MIXER_WRITE_BASS: - IOCTL_IN(arg, data); - tumbler_set_bass(data); - /* Fall through */ - case SOUND_MIXER_READ_BASS: - tumbler_get_bass(&data); - rc = IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_WRITE_TREBLE: - IOCTL_IN(arg, data); - tumbler_set_treble(data); - /* Fall through */ - case SOUND_MIXER_READ_TREBLE: - tumbler_get_treble(&data); - rc = IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_WRITE_PCM: - IOCTL_IN(arg, data); - tumbler_set_pcm_lvl(data); - /* Fall through */ - case SOUND_MIXER_READ_PCM: - tumbler_get_pcm_lvl(&data); - IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - tumbler_set_volume(data, data); - /* Fall through */ - case SOUND_MIXER_READ_VOLUME: - tumbler_get_volume(& data, &data); - rc = IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */ - IOCTL_IN(arg, data); - beep_vol = data & 0xff; - /* fall through */ - case SOUND_MIXER_READ_ALTPCM: - rc = IOCTL_OUT(arg, beep_vol); - break; - case SOUND_MIXER_OUTMASK: - case SOUND_MIXER_OUTSRC: - default: - rc = -EINVAL; - } - - return rc; -} - static int daca_mixer_ioctl(u_int cmd, u_long arg) { int data; @@ -2154,7 +2219,8 @@ rc = daca_mixer_ioctl(cmd, arg); break; case AWACS_TUMBLER: - rc = tumbler_mixer_ioctl(cmd, arg); + case AWACS_SNAPPER: + rc = tas_mixer_ioctl(cmd, arg); break ; default: /* ;-)) */ rc = awacs_mixer_ioctl(cmd, arg); @@ -2171,7 +2237,9 @@ case AWACS_TUMBLER: printk("AE-Init tumbler mixer\n"); break ; - + case AWACS_SNAPPER: + printk("AE-Init snapper mixer\n"); + break ; case AWACS_DACA: case AWACS_BURGUNDY: break ; /* don't know yet */ @@ -2362,12 +2430,12 @@ len += sprintf(b,"44100 ") ; break ; case AWACS_TUMBLER: - for (i=0; i<2; i++){ - if (tumbler_freqs_ok[i]) - len += sprintf(b+len,"%d ", tumbler_freqs[i]) ; + case AWACS_SNAPPER: + for (i=0; i<1; i++){ + if (tas_freqs_ok[i]) + len += sprintf(b+len,"%d ", tas_freqs[i]) ; } break ; - case AWACS_AWACS: case AWACS_SCREAMER: default: @@ -2469,8 +2537,8 @@ code that looks for chip properties knows how to go about it. */ -static struct device_node -__init *get_snd_io_node(void) +static struct device_node* __init +get_snd_io_node(void) { struct device_node *np = NULL; @@ -2491,7 +2559,7 @@ * this seems to be what iBooks (& Tumbler) have. */ if (np == NULL) - np = find_devices("i2s-a"); + np = i2s_node = find_devices("i2s-a"); /* if we didn't find this - perhaps we are on an early model * which _only_ has an 'awacs' node @@ -2511,8 +2579,8 @@ we have to deduce the info other ways for these. */ -static struct device_node -__init *get_snd_info_node(struct device_node *io) +static struct device_node* __init +get_snd_info_node(struct device_node *io) { struct device_node *info; @@ -2526,8 +2594,8 @@ /* Find out what type of codec we have. */ -static int -__init get_codec_type(struct device_node *info) +static int __init +get_codec_type(struct device_node *info) { /* already set if pre-davbus model and info will be NULL */ int codec = awacs_revision ; @@ -2544,14 +2612,16 @@ codec = AWACS_DACA; if (device_is_compatible(info, "tumbler")) codec = AWACS_TUMBLER; + if (device_is_compatible(info, "snapper")) + codec = AWACS_SNAPPER; } return codec ; } /* find out what type, if any, of expansion card we have */ -static void -__init get_expansion_type(void) +static void __init +get_expansion_type(void) { if (find_devices("perch") != NULL) has_perch = 1; @@ -2569,8 +2639,8 @@ * Set dmasound.mach.max_dsp_rate on the basis of these routines. */ -static void -__init init_awacs_frame_rates(unsigned int *prop, unsigned int l) +static void __init +awacs_init_frame_rates(unsigned int *prop, unsigned int l) { int i ; if (prop) { @@ -2592,31 +2662,8 @@ /* else we assume that all the rates are available */ } -static void -__init init_tumbler_frame_rates(unsigned int *prop, unsigned int l) -{ - int i ; - if (prop) { - for (i=0; i<2; i++) - tumbler_freqs_ok[i] = 0; - for (l /= sizeof(int); l > 0; --l) { - unsigned int r = *prop++; - /* Apple 'Fixed' format */ - if (r >= 0x10000) - r >>= 16; - for (i = 0; i < 2; ++i) { - if (r == tumbler_freqs[i]) { - tumbler_freqs_ok[i] = 1; - break; - } - } - } - } - /* else we assume that all the rates are available */ -} - -static void -__init init_burgundy_frame_rates(unsigned int *prop, unsigned int l) +static void __init +burgundy_init_frame_rates(unsigned int *prop, unsigned int l) { int temp[9] ; int i = 0 ; @@ -2641,8 +2688,8 @@ #endif } -static void -__init init_daca_frame_rates(unsigned int *prop, unsigned int l) +static void __init +daca_init_frame_rates(unsigned int *prop, unsigned int l) { int temp[9] ; int i = 0 ; @@ -2668,21 +2715,22 @@ #endif } -static void -__init init_frame_rates(unsigned int *prop, unsigned int l) +static void __init +init_frame_rates(unsigned int *prop, unsigned int l) { - switch (awacs_revision){ + switch (awacs_revision) { case AWACS_TUMBLER: - init_tumbler_frame_rates(prop, l); + case AWACS_SNAPPER: + tas_init_frame_rates(prop, l); break ; case AWACS_DACA: - init_daca_frame_rates(prop, l); + daca_init_frame_rates(prop, l); break ; case AWACS_BURGUNDY: - init_burgundy_frame_rates(prop, l); + burgundy_init_frame_rates(prop, l); break ; - default: /* ;-))) */ - init_awacs_frame_rates(prop, l); + default: + awacs_init_frame_rates(prop, l); break ; } } @@ -2690,11 +2738,11 @@ /* find things/machines that can't do mac-io byteswap */ -static void -__init set_hw_byteswap(struct device_node *io) +static void __init +set_hw_byteswap(struct device_node *io) { struct device_node *mio ; - unsigned int *p, kl = 0 ; + unsigned int kl = 0 ; /* if seems that Keylargo can't byte-swap */ @@ -2741,9 +2789,11 @@ if( beep_dbdma_cmd_space ) kfree(beep_dbdma_cmd_space) ; return -ENOMEM ; } +#ifdef CONFIG_VT /* OK, we should be safe to claim the mksound vector now */ orig_mksound = kd_mksound; kd_mksound = awacs_mksound; +#endif return 0 ; } @@ -2839,23 +2889,26 @@ } /* all OF versions I've seen use this value */ - awacs = (volatile struct awacs_regs *) - ioremap(io->addrs[0].address, 0x1000); + if (i2s_node) + i2s = (u32 *)ioremap(io->addrs[0].address, 0x1000); + else + awacs = (volatile struct awacs_regs *) + ioremap(io->addrs[0].address, 0x1000); awacs_txdma = (volatile struct dbdma_regs *) ioremap(io->addrs[1].address, 0x100); awacs_rxdma = (volatile struct dbdma_regs *) ioremap(io->addrs[2].address, 0x100); -#ifdef CONFIG_PMAC_PBOOK /* first of all make sure that the chip is powered up....*/ pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, io, 0, 1); - if (awacs_revision == AWACS_SCREAMER) + if (awacs_revision == AWACS_SCREAMER && awacs) awacs_recalibrate(); -#endif + awacs_irq = io->intrs[0].line; awacs_tx_irq = io->intrs[1].line; awacs_rx_irq = io->intrs[2].line; + /* Hack for legacy crap that will be killed someday */ awacs_node = io; /* if we have an awacs or screamer - probe the chip to make @@ -2906,8 +2959,9 @@ /* if it's there use it to set up frame rates */ init_frame_rates(prop, l) ; } - - out_le32(&awacs->control, 0x11); /* set everything quiesent */ + + if (awacs) + out_le32(&awacs->control, 0x11); /* set everything quiesent */ set_hw_byteswap(io) ; /* figure out if the h/w can do it */ @@ -2942,9 +2996,20 @@ #ifdef CONFIG_KMOD request_module("i2c-keywest"); #endif /* CONFIG_KMOD */ - awacs_tumbler_init(); - tas_init(); + tas_register_driver(&tas3001c_hooks); + tas_init(I2C_DRIVERID_TAS3001C, I2C_DRIVERNAME_TAS3001C); + tas_dmasound_init(); + tas_post_init(); break ; + case AWACS_SNAPPER: +#ifdef CONFIG_KMOD + request_module("i2c-keywest"); +#endif /* CONFIG_KMOD */ + tas_register_driver(&tas3004_hooks); + tas_init(I2C_DRIVERID_TAS3004,I2C_DRIVERNAME_TAS3004); + tas_dmasound_init(); + tas_post_init(); + break; case AWACS_DACA: #ifdef CONFIG_KMOD request_module("i2c-keywest"); @@ -3028,11 +3093,15 @@ dmasound.mach.hardware_afmts = AFMT_S16_BE ; /* shut out chips that do output only. - may need to extend this to machines which have no inputs - even tho' - they use screamer - IIRC one of the powerbooks is like this. - */ + * may need to extend this to machines which have no inputs - even tho' + * they use screamer - IIRC one of the powerbooks is like this. + * + * FIXME: Actually, some TUMBLER and SNAPPER do have inputs... + */ - if (awacs_revision != AWACS_TUMBLER && awacs_revision != AWACS_DACA) { + if (awacs_revision != AWACS_TUMBLER && + awacs_revision != AWACS_SNAPPER && + awacs_revision != AWACS_DACA) { dmasound.mach.capabilities = DSP_CAP_DUPLEX ; dmasound.mach.record = PMacRecord ; } @@ -3050,6 +3119,9 @@ case AWACS_TUMBLER: sprintf(awacs_name, "PowerMac Tumbler ") ; break ; + case AWACS_SNAPPER: + sprintf(awacs_name, "PowerMac Snapper ") ; + break ; case AWACS_SCREAMER: sprintf(awacs_name, "PowerMac Screamer ") ; break ; @@ -3066,7 +3138,8 @@ { switch (awacs_revision) { case AWACS_TUMBLER: - awacs_tumbler_cleanup(); + case AWACS_SNAPPER: + tas_dmasound_cleanup(); tas_cleanup(); break ; case AWACS_DACA: @@ -3081,3 +3154,10 @@ module_init(dmasound_awacs_init); module_exit(dmasound_awacs_cleanup); +/* + * Local Variables: + * tab-width: 8 + * indent-tabs-mode: t + * c-basic-offset: 8 + * End: + */ diff -uNr linux-2.4.21/drivers/sound/dmasound/tas3001c.c linux-2.4.21-ben2/drivers/sound/dmasound/tas3001c.c --- linux-2.4.21/drivers/sound/dmasound/tas3001c.c 2002-02-25 20:38:05.000000000 +0100 +++ linux-2.4.21-ben2/drivers/sound/dmasound/tas3001c.c 2003-06-27 15:41:06.000000000 +0200 @@ -1,38 +1,17 @@ /* - * Driver for the i2c/i2s based TA3001C sound chip used - * on some Apple hardware. Also known as "tumbler". + * Driver for the i2c/i2s based TA3004 sound chip used + * on some Apple hardware. Also known as "snapper". * - * 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. - * - * Modified by Christopher C. Chimelis : + * Tobias Sargeant + * Based upon, tas3001c.c by Christopher C. Chimelis : * * TODO: * ----- - * * Enable DRC since the TiBook speakers are less than good * * Enable control over input line 2 (is this connected?) - * * Play with the dual six-stage cascading biquad filtering to see how - * we can use it to our advantage (currently not implemented) - * * Reorganise driver a bit to make it cleaner and easier to work with - * (read: use the header file more :-P) - * * Implement sleep support - * - * Version 0.4: - * ------------ - * * Balance control finally works (can someone document OSS better please?) - * * Moved to a struct for common values referenced in the driver - * * Put stubs in for sleep/wake-up support for now. This will take some - * experimentation to make sure that the timing is right, since the - * TAS hardware requires specific timing while enabling low-power mode. - * I may cheat for now and just reset the chip on wake-up, but I'd rather - * not if I don't have to. - * - * Version 0.3: - * ------------ - * * Fixed volume control - * * Added bass and treble control - * * Added PCM line level control (mixer 1 in the TAS manual) + * * Implement sleep support (at least mute everything and + * * set gains to minimum during sleep) + * * Look into some of Darwin's tweaks regarding the mute + * * lines (delays & different behaviour on some HW) * */ @@ -45,403 +24,854 @@ #include #include #include +#include #include #include #include #include #include "dmasound.h" +#include "tas_common.h" #include "tas3001c.h" -#define I2C_DRIVERID_TAS (0xFEBA) +#include "tas_ioctl.h" -#define TAS_VERSION "0.3" -#define TAS_DATE "20011214" +#define TAS3001C_BIQUAD_FILTER_COUNT 6 +#define TAS3001C_BIQUAD_CHANNEL_COUNT 2 -#define TAS_SETTING_MAX 100 +#define VOL_DEFAULT (100 * 4 / 5) +#define INPUT_DEFAULT (100 * 4 / 5) +#define BASS_DEFAULT (100 / 2) +#define TREBLE_DEFAULT (100 / 2) + +struct tas3001c_data_t { + struct tas_data_t super; + int device_id; + int output_id; + int speaker_id; + struct tas_drce_t drce_state; +}; -#define VOL_DEFAULT (((((TAS_SETTING_MAX*4)/5)<<0)<<8) | (((TAS_SETTING_MAX*4)/5)<<0)) -#define INPUT_DEFAULT (((TAS_SETTING_MAX*4)/5)<<0) -#define BASS_DEFAULT ((TAS_SETTING_MAX/2)<<0) -#define TREBLE_DEFAULT ((TAS_SETTING_MAX/2)<<0) -static struct i2c_client * tumbler_client = NULL; +static const union tas_biquad_t +tas3001c_eq_unity={ + buf: { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } +}; -int tumbler_enter_sleep(void); -int tumbler_leave_sleep(void); -static int tas_attach_adapter(struct i2c_adapter *adapter); -static int tas_detect_client(struct i2c_adapter *adapter, int address); -static int tas_detach_client(struct i2c_client *client); +static inline unsigned char db_to_regval(short db) { + int r=0; -/* Unique ID allocation */ -static int tas_id; -static int tas_initialized; + r=(db+0x59a0) / 0x60; -static struct device_node* tas_node; -static u8 tas_i2c_address = 0x34; + if (r < 0x91) return 0x91; + if (r > 0xef) return 0xef; + return r; +} -struct tas_data_t { - uint left_vol; /* left volume */ - uint right_vol; /* right volume */ - uint treble; /* treble */ - uint bass; /* bass */ - uint pcm_level; /* pcm level */ -}; +static inline short quantize_db(short db) { + return db_to_regval(db) * 0x60 - 0x59a0; +} -struct i2c_driver tas_driver = { - name: "TAS3001C driver V 0.3", - id: I2C_DRIVERID_TAS, - flags: I2C_DF_NOTIFY, - attach_adapter: &tas_attach_adapter, - detach_client: &tas_detach_client, - command: NULL, - inc_use: NULL, /* &tas_inc_use, */ - dec_use: NULL /* &tas_dev_use */ -}; -int -tumbler_get_volume(uint * left_vol, uint *right_vol) +static inline int +register_width(enum tas3001c_reg_t r) { - struct tas_data_t *data; + switch(r) { + case TAS3001C_REG_MCR: + case TAS3001C_REG_TREBLE: + case TAS3001C_REG_BASS: + return 1; - if (!tumbler_client) - return -1; + case TAS3001C_REG_DRC: + return 2; - data = (struct tas_data_t *) (tumbler_client->data); - *left_vol = data->left_vol; - *right_vol = data->right_vol; - - return 0; + case TAS3001C_REG_MIXER1: + case TAS3001C_REG_MIXER2: + return 3; + + case TAS3001C_REG_VOLUME: + return 6; + + case TAS3001C_REG_LEFT_BIQUAD0: + case TAS3001C_REG_LEFT_BIQUAD1: + case TAS3001C_REG_LEFT_BIQUAD2: + case TAS3001C_REG_LEFT_BIQUAD3: + case TAS3001C_REG_LEFT_BIQUAD4: + case TAS3001C_REG_LEFT_BIQUAD5: + case TAS3001C_REG_LEFT_BIQUAD6: + + case TAS3001C_REG_RIGHT_BIQUAD0: + case TAS3001C_REG_RIGHT_BIQUAD1: + case TAS3001C_REG_RIGHT_BIQUAD2: + case TAS3001C_REG_RIGHT_BIQUAD3: + case TAS3001C_REG_RIGHT_BIQUAD4: + case TAS3001C_REG_RIGHT_BIQUAD5: + case TAS3001C_REG_RIGHT_BIQUAD6: + return 15; + + default: + return 0; + } } -int -tumbler_set_register(uint reg, uint size, char *block) -{ - if (i2c_smbus_write_block_data(tumbler_client, reg, size, block) < 0) { - printk("tas3001c: I2C write failed \n"); - return -1; +static int +tas3001c_write_register( struct tas3001c_data_t *self, + enum tas3001c_reg_t reg_num, + char *data, + uint write_mode) +{ + if (reg_num==TAS3001C_REG_MCR || + reg_num==TAS3001C_REG_BASS || + reg_num==TAS3001C_REG_TREBLE) { + return tas_write_byte_register(&self->super, + (uint)reg_num, + *data, + write_mode); + } else { + return tas_write_register(&self->super, + (uint)reg_num, + register_width(reg_num), + data, + write_mode); } - return 0; } -int -tumbler_get_pcm_lvl(uint *pcm_lvl) +static int +tas3001c_sync_register( struct tas3001c_data_t *self, + enum tas3001c_reg_t reg_num) { - struct tas_data_t *data; - - if (!tumbler_client) - return -1; + if (reg_num==TAS3001C_REG_MCR || + reg_num==TAS3001C_REG_BASS || + reg_num==TAS3001C_REG_TREBLE) { + return tas_sync_byte_register(&self->super, + (uint)reg_num, + register_width(reg_num)); + } else { + return tas_sync_register(&self->super, + (uint)reg_num, + register_width(reg_num)); + } +} - data = (struct tas_data_t *) (tumbler_client->data); - *pcm_lvl = data->pcm_level; +static int +tas3001c_read_register( struct tas3001c_data_t *self, + enum tas3001c_reg_t reg_num, + char *data, + uint write_mode) +{ + return tas_read_register(&self->super, + (uint)reg_num, + register_width(reg_num), + data); +} + +static inline int +tas3001c_fast_load(struct tas3001c_data_t *self, int fast) +{ + if (fast) + self->super.shadow[TAS3001C_REG_MCR][0] |= 0x80; + else + self->super.shadow[TAS3001C_REG_MCR][0] &= 0x7f; + return tas3001c_sync_register(self,TAS3001C_REG_MCR); +} + +static uint +tas3001c_supported_mixers(struct tas3001c_data_t *self) +{ + return SOUND_MASK_VOLUME | + SOUND_MASK_PCM | + SOUND_MASK_ALTPCM | + SOUND_MASK_TREBLE | + SOUND_MASK_BASS; +} - return 0; +static int +tas3001c_mixer_is_stereo(struct tas3001c_data_t *self,int mixer) +{ + switch(mixer) { + case SOUND_MIXER_VOLUME: + return 1; + default: + return 0; + } } -int -tumbler_get_treble(uint *treble) +static uint +tas3001c_stereo_mixers(struct tas3001c_data_t *self) { - struct tas_data_t *data; + uint r=tas3001c_supported_mixers(self); + uint i; + + for (i=1; idata); - *treble = data->treble; + + *level=self->super.mixer[mixer]; return 0; } -int -tumbler_get_bass(uint *bass) +static int +tas3001c_set_mixer_level(struct tas3001c_data_t *self,int mixer,uint level) { - struct tas_data_t *data; - - if (!tumbler_client) - return -1; + int rc; + tas_shadow_t *shadow; - data = (struct tas_data_t *) (tumbler_client->data); - *bass = data->bass; + uint temp; + uint offset=0; + if (!self) + return -1; + + shadow=self->super.shadow; + + if (!tas3001c_mixer_is_stereo(self,mixer)) + level = tas_mono_to_stereo(level); + + switch(mixer) { + case SOUND_MIXER_VOLUME: + temp = tas3001c_gain.master[level&0xff]; + shadow[TAS3001C_REG_VOLUME][0] = (temp >> 16) & 0xff; + shadow[TAS3001C_REG_VOLUME][1] = (temp >> 8) & 0xff; + shadow[TAS3001C_REG_VOLUME][2] = (temp >> 0) & 0xff; + temp = tas3001c_gain.master[(level>>8)&0xff]; + shadow[TAS3001C_REG_VOLUME][3] = (temp >> 16) & 0xff; + shadow[TAS3001C_REG_VOLUME][4] = (temp >> 8) & 0xff; + shadow[TAS3001C_REG_VOLUME][5] = (temp >> 0) & 0xff; + rc = tas3001c_sync_register(self,TAS3001C_REG_VOLUME); + break; + case SOUND_MIXER_ALTPCM: + /* tas3001c_fast_load(self, 1); */ + level = tas_mono_to_stereo(level); + temp = tas3001c_gain.mixer[level&0xff]; + shadow[TAS3001C_REG_MIXER2][offset+0] = (temp >> 16) & 0xff; + shadow[TAS3001C_REG_MIXER2][offset+1] = (temp >> 8) & 0xff; + shadow[TAS3001C_REG_MIXER2][offset+2] = (temp >> 0) & 0xff; + rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER2); + /* tas3001c_fast_load(self, 0); */ + break; + case SOUND_MIXER_PCM: + /* tas3001c_fast_load(self, 1); */ + level = tas_mono_to_stereo(level); + temp = tas3001c_gain.mixer[level&0xff]; + shadow[TAS3001C_REG_MIXER1][offset+0] = (temp >> 16) & 0xff; + shadow[TAS3001C_REG_MIXER1][offset+1] = (temp >> 8) & 0xff; + shadow[TAS3001C_REG_MIXER1][offset+2] = (temp >> 0) & 0xff; + rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER1); + /* tas3001c_fast_load(self, 0); */ + break; + case SOUND_MIXER_TREBLE: + temp = tas3001c_gain.treble[level&0xff]; + shadow[TAS3001C_REG_TREBLE][0]=temp&0xff; + rc = tas3001c_sync_register(self,TAS3001C_REG_TREBLE); + break; + case SOUND_MIXER_BASS: + temp = tas3001c_gain.bass[level&0xff]; + shadow[TAS3001C_REG_BASS][0]=temp&0xff; + rc = tas3001c_sync_register(self,TAS3001C_REG_BASS); + break; + default: + rc = -1; + break; + } + if (rc < 0) + return rc; + self->super.mixer[mixer]=level; return 0; } -int -tumbler_set_bass(uint bass) +static int +tas3001c_leave_sleep(struct tas3001c_data_t *self) { - uint cur_bass_pers = bass; - char block; - struct tas_data_t *data; + unsigned char mcr = (1<<6)+(2<<4)+(2<<2); - if (!tumbler_client) + if (!self) return -1; - data = (struct tas_data_t *) (tumbler_client->data); + /* Make sure something answers on the i2c bus */ + if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr, + WRITE_NORMAL|FORCE_WRITE) < 0) + return -1; + + tas3001c_fast_load(self, 1); + + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5); + + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5); - bass &= 0xff; - if (bass > TAS_SETTING_MAX) - bass = TAS_SETTING_MAX; - bass = ((bass * 72) / TAS_SETTING_MAX) << 0; - bass = tas_bass_table[bass]; - block = (bass >> 0) & 0xff; + tas3001c_fast_load(self, 0); - if (tumbler_set_register(TAS_SET_BASS, &block) < 0) { - printk("tas3001c: failed to set bass \n"); + (void)tas3001c_sync_register(self,TAS3001C_REG_BASS); + (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE); + (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1); + (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2); + (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME); + + return 0; +} + +static int +tas3001c_enter_sleep(struct tas3001c_data_t *self) +{ + /* Stub for now, but I have the details on low-power mode */ + if (!self) return -1; - } - data->bass = cur_bass_pers; return 0; } -int -tumbler_set_treble(uint treble) +static int +tas3001c_sync_biquad( struct tas3001c_data_t *self, + u_int channel, + u_int filter) { - uint cur_treble_pers = treble; - char block; - struct tas_data_t *data; + enum tas3001c_reg_t reg; - if (!tumbler_client) - return -1; + if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT || + filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL; - data = (struct tas_data_t *) (tumbler_client->data); + reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter; - treble &= 0xff; - if (treble > TAS_SETTING_MAX) - treble = TAS_SETTING_MAX; - treble = ((treble * 72) / TAS_SETTING_MAX) << 0; - treble = tas_treble_table[treble]; - block = (treble >> 0) & 0xff; + return tas3001c_sync_register(self,reg); +} + +static int +tas3001c_write_biquad_shadow( struct tas3001c_data_t *self, + u_int channel, + u_int filter, + const union tas_biquad_t *biquad) +{ + tas_shadow_t *shadow=self->super.shadow; + enum tas3001c_reg_t reg; + + if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT || + filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL; + + reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter; + + SET_4_20(shadow[reg], 0,biquad->coeff.b0); + SET_4_20(shadow[reg], 3,biquad->coeff.b1); + SET_4_20(shadow[reg], 6,biquad->coeff.b2); + SET_4_20(shadow[reg], 9,biquad->coeff.a1); + SET_4_20(shadow[reg],12,biquad->coeff.a2); - if (tumbler_set_register(TAS_SET_TREBLE, &block) < 0) { - printk("tas3001c: failed to set treble \n"); - return -1; - } - data->treble = cur_treble_pers; return 0; } -int -tumbler_set_pcm_lvl(uint pcm_lvl) +static int +tas3001c_write_biquad( struct tas3001c_data_t *self, + u_int channel, + u_int filter, + const union tas_biquad_t *biquad) { - uint pcm_lvl_pers = pcm_lvl; - unsigned char block[3]; - struct tas_data_t *data; + int rc; - if (!tumbler_client) - return -1; + rc=tas3001c_write_biquad_shadow(self, channel, filter, biquad); + if (rc < 0) return rc; - data = (struct tas_data_t *) (tumbler_client->data); + return tas3001c_sync_biquad(self, channel, filter); +} - pcm_lvl &= 0xff; - if (pcm_lvl > TAS_SETTING_MAX) - pcm_lvl = TAS_SETTING_MAX; - pcm_lvl = ((pcm_lvl * 176) / TAS_SETTING_MAX) << 0; +static int +tas3001c_write_biquad_list( struct tas3001c_data_t *self, + u_int filter_count, + u_int flags, + struct tas_biquad_ctrl_t *biquads) +{ + int i; + int rc; - pcm_lvl = tas_input_table[pcm_lvl]; + if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1); - block[0] = (pcm_lvl >> 16) & 0xff; - block[1] = (pcm_lvl >> 8) & 0xff; - block[2] = (pcm_lvl >> 0) & 0xff; + for (i=0; ipcm_level = pcm_lvl_pers; - return 0; + return rc; } -int -tumbler_set_volume(uint left_vol, uint right_vol) +static int +tas3001c_read_biquad( struct tas3001c_data_t *self, + u_int channel, + u_int filter, + union tas_biquad_t *biquad) +{ + tas_shadow_t *shadow=self->super.shadow; + enum tas3001c_reg_t reg; + + if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT || + filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL; + + reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter; + + biquad->coeff.b0=GET_4_20(shadow[reg], 0); + biquad->coeff.b1=GET_4_20(shadow[reg], 3); + biquad->coeff.b2=GET_4_20(shadow[reg], 6); + biquad->coeff.a1=GET_4_20(shadow[reg], 9); + biquad->coeff.a2=GET_4_20(shadow[reg],12); + + return 0; +} + +static int +tas3001c_eq_rw( struct tas3001c_data_t *self, + u_int cmd, + u_long arg) { - uint left_vol_pers = left_vol; - uint right_vol_pers = right_vol; - unsigned char block[6]; - struct tas_data_t *data; + int rc; + struct tas_biquad_ctrl_t biquad; - if (!tumbler_client) - return -1; + if (copy_from_user((void *)&biquad, (const void *)arg, sizeof(struct tas_biquad_ctrl_t))) { + return -EFAULT; + } - data = (struct tas_data_t *) (tumbler_client->data); + if (cmd & SIOC_IN) { + rc=tas3001c_write_biquad(self, biquad.channel, biquad.filter, &biquad.data); + if (rc != 0) return rc; + } - left_vol &= 0xff; - if (left_vol > TAS_SETTING_MAX) - left_vol = TAS_SETTING_MAX; + if (cmd & SIOC_OUT) { + rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data); + if (rc != 0) return rc; + + if (copy_to_user((void *)arg, (const void *)&biquad, sizeof(struct tas_biquad_ctrl_t))) { + return -EFAULT; + } - right_vol = (right_vol >> 8) & 0xff; - if (right_vol > TAS_SETTING_MAX) - right_vol = TAS_SETTING_MAX; + } + return 0; +} - left_vol = ((left_vol * 176) / TAS_SETTING_MAX) << 0; - right_vol = ((right_vol * 176) / TAS_SETTING_MAX) << 0; +static int +tas3001c_eq_list_rw( struct tas3001c_data_t *self, + u_int cmd, + u_long arg) +{ + int rc; + int filter_count; + int flags; + int i,j; + char sync_required[2][6]; + struct tas_biquad_ctrl_t biquad; + + memset(sync_required,0,sizeof(sync_required)); + + if (copy_from_user((void *)&filter_count, + (const void *)arg + offsetof(struct tas_biquad_ctrl_list_t,filter_count), + sizeof(int))) { + return -EFAULT; + } - left_vol = tas_volume_table[left_vol]; - right_vol = tas_volume_table[right_vol]; + if (copy_from_user((void *)&flags, + (const void *)arg + offsetof(struct tas_biquad_ctrl_list_t,flags), + sizeof(int))) { + return -EFAULT; + } - block[0] = (left_vol >> 16) & 0xff; - block[1] = (left_vol >> 8) & 0xff; - block[2] = (left_vol >> 0) & 0xff; + if (cmd & SIOC_IN) { + } - block[3] = (right_vol >> 16) & 0xff; - block[4] = (right_vol >> 8) & 0xff; - block[5] = (right_vol >> 0) & 0xff; + for (i=0; i < filter_count; i++) { + if (copy_from_user((void *)&biquad, + (const void *)arg + offsetof(struct tas_biquad_ctrl_list_t, biquads[i]), + sizeof(struct tas_biquad_ctrl_t))) { + return -EFAULT; + } + + if (cmd & SIOC_IN) { + sync_required[biquad.channel][biquad.filter]=1; + rc=tas3001c_write_biquad_shadow(self, biquad.channel, biquad.filter, &biquad.data); + if (rc != 0) return rc; + } + + if (cmd & SIOC_OUT) { + rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data); + if (rc != 0) return rc; + + if (copy_to_user((void *)arg + offsetof(struct tas_biquad_ctrl_list_t, biquads[i]), + (const void *)&biquad, + sizeof(struct tas_biquad_ctrl_t))) { + return -EFAULT; + } + } + } - if (tumbler_set_register(TAS_SET_VOLUME, block) < 0) { - printk("tas3001c: failed to set volume \n"); - return -1; + if (cmd & SIOC_IN) { + if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1); + for (i=0; i<2; i++) { + for (j=0; j<6; j++) { + if (sync_required[i][j]) { + rc=tas3001c_sync_biquad(self, i, j); + if (rc < 0) return rc; + } + } + } + if (flags & TAS_BIQUAD_FAST_LOAD) { + tas3001c_fast_load(self,0); + /* now we need to set up the mixers again, + because leaving fast mode resets them. */ + (void)tas3001c_sync_register(self,TAS3001C_REG_BASS); + (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE); + (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1); + (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2); + (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME); + } } - data->left_vol = left_vol_pers; - data->right_vol = right_vol_pers; return 0; } -int -tumbler_leave_sleep(void) -{ - /* Stub for now, but I have the details on low-power mode */ - if (!tumbler_client) - return -1; +static int +tas3001c_update_drce( struct tas3001c_data_t *self, + int flags, + struct tas_drce_t *drce) +{ + tas_shadow_t *shadow; + shadow=self->super.shadow; + + shadow[TAS3001C_REG_DRC][1] = 0xc1; + + if (flags & TAS_DRCE_THRESHOLD) { + self->drce_state.threshold=quantize_db(drce->threshold); + shadow[TAS3001C_REG_DRC][2] = db_to_regval(self->drce_state.threshold); + } - return 0; + if (flags & TAS_DRCE_ENABLE) { + self->drce_state.enable = drce->enable; + } + + if (!self->drce_state.enable) { + shadow[TAS3001C_REG_DRC][0] = 0xf0; + } + +#ifdef DEBUG_DRCE + printk("DRCE IOCTL: set [ ENABLE:%x THRESH:%x\n", + self->drce_state.enable, + self->drce_state.threshold); + + printk("DRCE IOCTL: reg [ %02x %02x ]\n", + (unsigned char)shadow[TAS3001C_REG_DRC][0], + (unsigned char)shadow[TAS3001C_REG_DRC][1]); +#endif + + return tas3001c_sync_register(self, TAS3001C_REG_DRC); } -int -tumbler_enter_sleep(void) +static int +tas3001c_drce_rw( struct tas3001c_data_t *self, + u_int cmd, + u_long arg) { - /* Stub for now, but I have the details on low-power mode */ - if (!tumbler_client) - return -1; + int rc; + struct tas_drce_ctrl_t drce_ctrl; + + if (copy_from_user((void *)&drce_ctrl, + (const void *)arg, + sizeof(struct tas_drce_ctrl_t))) { + return -EFAULT; + } + +#ifdef DEBUG_DRCE + printk("DRCE IOCTL: input [ FLAGS:%x ENABLE:%x THRESH:%x\n", + drce_ctrl.flags, + drce_ctrl.data.enable, + drce_ctrl.data.threshold); +#endif + + if (cmd & SIOC_IN) { + rc = tas3001c_update_drce(self, drce_ctrl.flags, &drce_ctrl.data); + if (rc < 0) + return rc; + } + + if (cmd & SIOC_OUT) { + if (drce_ctrl.flags & TAS_DRCE_ENABLE) + drce_ctrl.data.enable = self->drce_state.enable; + + if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) + drce_ctrl.data.threshold = self->drce_state.threshold; + + if (copy_to_user((void *)arg, + (const void *)&drce_ctrl, + sizeof(struct tas_drce_ctrl_t))) { + return -EFAULT; + } + } return 0; } -static int -tas_attach_adapter(struct i2c_adapter *adapter) +static void +tas3001c_update_device_parameters(struct tas3001c_data_t *self) { - if (!strncmp(adapter->name, "mac-io", 6)) - tas_detect_client(adapter, tas_i2c_address); + int i,j; - return 0; + if (!self) return; + + if (self->output_id == TAS_OUTPUT_HEADPHONES) { + tas3001c_fast_load(self, 1); + + for (i=0; idevice_id == self->device_id && + (eq->output_id == 0 || eq->output_id == self->output_id) && + (eq->speaker_id == 0 || eq->speaker_id == self->speaker_id)) { + + tas3001c_update_drce(self, TAS_DRCE_ALL, eq->drce); + tas3001c_write_biquad_list(self, eq->filter_count, TAS_BIQUAD_FAST_LOAD, eq->biquads); + + break; + } + } } -static int -tas_init_client(struct i2c_client * new_client) +static void +tas3001c_device_change_handler(void *self) { - /* Make sure something answers on the i2c bus - */ + if (!self) return; - if (i2c_smbus_write_byte_data(new_client, 1, (1<<6)+(2<<4)+(2<<2)+0) < 0) - return -1; + tas3001c_update_device_parameters((struct tas3001c_data_t *)self); +} + +static struct tq_struct device_change_task; - tumbler_client = new_client; +static int +tas3001c_output_device_change( struct tas3001c_data_t *self, + int device_id, + int output_id, + int speaker_id) +{ + self->device_id=device_id; + self->output_id=output_id; + self->speaker_id=speaker_id; - tumbler_set_volume(VOL_DEFAULT, VOL_DEFAULT); - tumbler_set_pcm_lvl(INPUT_DEFAULT); - tumbler_set_bass(BASS_DEFAULT); - tumbler_set_treble(TREBLE_DEFAULT); + schedule_task(&device_change_task); return 0; } static int -tas_detect_client(struct i2c_adapter *adapter, int address) -{ - int rc = 0; - struct i2c_client *new_client; - struct tas_data_t *data; - const char *client_name = "tas 3001c Digital Equalizer"; - - new_client = kmalloc( - sizeof(struct i2c_client) + sizeof(struct tas_data_t), - GFP_KERNEL); - if (!new_client) { - rc = -ENOMEM; - goto bail; - } +tas3001c_device_ioctl( struct tas3001c_data_t *self, + u_int cmd, + u_long arg) +{ + switch (cmd) { + case TAS_READ_EQ: + case TAS_WRITE_EQ: + return tas3001c_eq_rw(self, cmd, arg); + + case TAS_READ_EQ_LIST: + case TAS_WRITE_EQ_LIST: + return tas3001c_eq_list_rw(self, cmd, arg); - /* This is tricky, but it will set the data to the right value. */ - new_client->data = new_client + 1; - data = (struct tas_data_t *) (new_client->data); + case TAS_READ_EQ_FILTER_COUNT: + put_user(TAS3001C_BIQUAD_FILTER_COUNT, (uint *)(arg)); + return 0; - new_client->addr = address; - new_client->data = data; - new_client->adapter = adapter; - new_client->driver = &tas_driver; - new_client->flags = 0; + case TAS_READ_EQ_CHANNEL_COUNT: + put_user(TAS3001C_BIQUAD_CHANNEL_COUNT, (uint *)(arg)); + return 0; - strcpy(new_client->name,client_name); + case TAS_READ_DRCE: + case TAS_WRITE_DRCE: + return tas3001c_drce_rw(self, cmd, arg); - new_client->id = tas_id++; /* Automatically unique */ + case TAS_READ_DRCE_CAPS: + put_user(TAS_DRCE_ENABLE | TAS_DRCE_THRESHOLD, (uint *)(arg)); + return 0; - if (tas_init_client(new_client)) { - rc = -ENODEV; - goto bail; + case TAS_READ_DRCE_MIN: + case TAS_READ_DRCE_MAX: { + struct tas_drce_ctrl_t drce_ctrl; + + if (copy_from_user((void *)&drce_ctrl, + (const void *)arg, + sizeof(struct tas_drce_ctrl_t))) { + return -EFAULT; + } + + if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) { + if (cmd == TAS_READ_DRCE_MIN) { + drce_ctrl.data.threshold=-36<<8; + } else { + drce_ctrl.data.threshold=-6<<8; + } + } + + if (copy_to_user((void *)arg, + (const void *)&drce_ctrl, + sizeof(struct tas_drce_ctrl_t))) { + return -EFAULT; + } } - - /* Tell the i2c layer a new client has arrived */ - if (i2c_attach_client(new_client)) { - rc = -ENODEV; - goto bail; } -bail: - if (rc && new_client) - kfree(new_client); - return rc; + + return -EINVAL; } static int -tas_detach_client(struct i2c_client *client) +tas3001c_init_mixer(struct tas3001c_data_t *self) { - if (client == tumbler_client) - tumbler_client = NULL; + unsigned char mcr = (1<<6)+(2<<4)+(2<<2); + + /* Make sure something answers on the i2c bus */ + if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr, + WRITE_NORMAL|FORCE_WRITE) < 0) + return -1; + + tas3001c_fast_load(self, 1); + + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD6); + + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD6); + + tas3001c_fast_load(self, 0); + + tas3001c_set_mixer_level(self, SOUND_MIXER_VOLUME, VOL_DEFAULT<<8 | VOL_DEFAULT); + tas3001c_set_mixer_level(self, SOUND_MIXER_PCM, INPUT_DEFAULT<<8 | INPUT_DEFAULT); + tas3001c_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0); - i2c_detach_client(client); - kfree(client); + tas3001c_set_mixer_level(self, SOUND_MIXER_BASS, BASS_DEFAULT); + tas3001c_set_mixer_level(self, SOUND_MIXER_TREBLE, TREBLE_DEFAULT); return 0; } -int -tas_cleanup(void) +static int +tas3001c_uninit_mixer(struct tas3001c_data_t *self) { - if (!tas_initialized) - return -ENODEV; - i2c_del_driver(&tas_driver); - tas_initialized = 0; + tas3001c_set_mixer_level(self, SOUND_MIXER_VOLUME, 0); + tas3001c_set_mixer_level(self, SOUND_MIXER_PCM, 0); + tas3001c_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0); + + tas3001c_set_mixer_level(self, SOUND_MIXER_BASS, 0); + tas3001c_set_mixer_level(self, SOUND_MIXER_TREBLE, 0); return 0; } -int -tas_init(void) +static int +tas3001c_init(struct i2c_client *client) { - int rc; - u32* paddr; - - if (tas_initialized) - return 0; + struct tas3001c_data_t *self; + int i,j; - tas_node = find_devices("deq"); - if (tas_node == NULL) - return -ENODEV; - - printk(KERN_INFO "tas3001c driver version %s (%s)\n",TAS_VERSION,TAS_DATE); - paddr = (u32 *)get_property(tas_node, "i2c-address", NULL); - if (paddr) { - tas_i2c_address = (*paddr) >> 1; - printk(KERN_INFO "using i2c address: 0x%x from device-tree\n", - tas_i2c_address); - } else - printk(KERN_INFO "using i2c address: 0x%x (default)\n", tas_i2c_address); - - if ((rc = i2c_add_driver(&tas_driver))) { - printk("tas3001c: Driver registration failed, module not inserted.\n"); - tas_cleanup(); - return rc; + self = kmalloc(sizeof(struct tas3001c_data_t) + + TAS3001C_REG_MAX * sizeof(tas_shadow_t), + GFP_KERNEL); + if (self == NULL) + return -ENOMEM; + client->data = (void *)self; + self->super.client = client; + self->super.shadow = (tas_shadow_t *)(self+1); + + self->output_id=TAS_OUTPUT_HEADPHONES; + self->device_id=0; + self->speaker_id=0; + + for (i=0; i */ -#ifndef _tas3001c_h_ -#define _tas3001c_h_ +#ifndef _TAS3001C_H_ +#define _TAS3001C_H_ -/* - * Macros that correspond to the registers that we write to - * when setting the various values. - */ -#define TAS_DRC 0x02 /* DRC */ -#define TAS_VOLUME 0x04 /* Volume */ -#define TAS_TREBLE 0x05 /* Treble */ -#define TAS_BASS 0x06 /* Bass */ -#define TAS_MIXER1 0x07 /* PCM line */ -#define TAS_MIXER2 0x08 /* Input (Unk) */ - -/* - * Macros that define various arguments to tas_set_register() - */ -#define TAS_SET_DRC TAS_DRC, 2 -#define TAS_SET_VOLUME TAS_VOLUME, 6 -#define TAS_SET_TREBLE TAS_TREBLE, 1 -#define TAS_SET_BASS TAS_BASS, 1 -#define TAS_SET_MIXER1 TAS_MIXER1, 3 -#define TAS_SET_MIXER2 TAS_MIXER2, 3 +#include +#include "tas_common.h" +#include "tas_eq_prefs.h" /* - * tas_volume_table contains lookup values for the volume settings - * for tumbler. This is straight from the programming manual - * for the chip, however, it's zero-sourced for your shopping pleasure - * (meaning, you'll have to compute the difference between the desired - * dB and the index value of the proper setting. - * - * This table should've been replaced by the formula: - * dB = 20 log(x) - * but, since there's no log() or supporting functions like exp(), - * my implementation of the above won't work. Yeah, I could do it - * the hard way, but this table is just easier :-) - * - * For reference, -70 dB = tas_volume_table[0] + * Macros that correspond to the registers that we write to + * when setting the various values. */ -static unsigned int tas_volume_table[] = { - 0x00000015, 0x00000016, 0x00000017, /* -70.0, -69.5, -69.0 */ - 0x00000019, 0x0000001a, 0x0000001c, /* -68.5, -68.0, -67.5 */ - 0x0000001d, 0x0000001f, 0x00000021, /* -67.0, -66.5, -66.0 */ - 0x00000023, 0x00000025, 0x00000027, /* -65.5, -65.0, -64.5 */ - 0x00000029, 0x0000002c, 0x0000002e, /* -64.0, -63.5, -63.0 */ - 0x00000031, 0x00000034, 0x00000037, /* -62.5, -62.0, -61.5 */ - 0x0000003a, 0x0000003e, 0x00000042, /* -61.0, -60.5, -60.0 */ - 0x00000045, 0x0000004a, 0x0000004e, /* -59.5, -59.0, -58.5 */ - 0x00000053, 0x00000057, 0x0000005d, /* -58.0, -57.5, -57.0 */ - 0x00000062, 0x00000068, 0x0000006e, /* -56.5, -56.0, -55.5 */ - 0x00000075, 0x0000007b, 0x00000083, /* -55.0, -54.5, -54.0 */ - 0x0000008b, 0x00000093, 0x0000009b, /* -53.5, -53.0, -52.5 */ - 0x000000a5, 0x000000ae, 0x000000b9, /* -52.0, -51.5, -51.0 */ - 0x000000c4, 0x000000cf, 0x000000dc, /* -50.5, -50.0, -49.5 */ - 0x000000e9, 0x000000f6, 0x00000105, /* -49.0, -48.5, -48.0 */ - 0x00000114, 0x00000125, 0x00000136, /* -47.5, -47.0, -46.5 */ - 0x00000148, 0x0000015c, 0x00000171, /* -46.0, -45.5, -45.0 */ - 0x00000186, 0x0000019e, 0x000001b6, /* -44.5, -44.0, -43.5 */ - 0x000001d0, 0x000001eb, 0x00000209, /* -43.0, -42.5, -42.0 */ - 0x00000227, 0x00000248, 0x0000026b, /* -41.5, -41.0, -40.5 */ - 0x0000028f, 0x000002b6, 0x000002df, /* -40.0, -39.5, -39.0 */ - 0x0000030b, 0x00000339, 0x0000036a, /* -38.5, -38.0, -37.5 */ - 0x0000039e, 0x000003d5, 0x0000040f, /* -37.0, -36.5, -36.0 */ - 0x0000044c, 0x0000048d, 0x000004d2, /* -35.5, -35.0, -34.5 */ - 0x0000051c, 0x00000569, 0x000005bb, /* -34.0, -33.5, -33.0 */ - 0x00000612, 0x0000066e, 0x000006d0, /* -32.5, -32.0, -31.5 */ - 0x00000737, 0x000007a5, 0x00000818, /* -31.0, -30.5, -30.0 */ - 0x00000893, 0x00000915, 0x0000099f, /* -29.5, -29.0, -28.5 */ - 0x00000a31, 0x00000acc, 0x00000b6f, /* -28.0, -27.5, -27.0 */ - 0x00000c1d, 0x00000cd5, 0x00000d97, /* -26.5, -26.0, -25.5 */ - 0x00000e65, 0x00000f40, 0x00001027, /* -25.0, -24.5, -24.0 */ - 0x0000111c, 0x00001220, 0x00001333, /* -23.5, -23.0, -22.5 */ - 0x00001456, 0x0000158a, 0x000016d1, /* -22.0, -21.5, -21.0 */ - 0x0000182b, 0x0000199a, 0x00001b1e, /* -20.5, -20.0, -19.5 */ - 0x00001cb9, 0x00001e6d, 0x0000203a, /* -19.0, -18.5, -18.0 */ - 0x00002223, 0x00002429, 0x0000264e, /* -17.5, -17.0, -16.5 */ - 0x00002893, 0x00002afa, 0x00002d86, /* -16.0, -15.5, -15.0 */ - 0x00003039, 0x00003314, 0x0000361b, /* -14.5, -14.0, -13.5 */ - 0x00003950, 0x00003cb5, 0x0000404e, /* -13.0, -12.5, -12.0 */ - 0x0000441d, 0x00004827, 0x00004c6d, /* -11.5, -11.0, -10.5 */ - 0x000050f4, 0x000055c0, 0x00005ad5, /* -10.0, -09.5, -09.0 */ - 0x00006037, 0x000065ea, 0x00006bf4, /* -08.5, -08.0, -07.5 */ - 0x0000725a, 0x00007920, 0x0000804e, /* -07.0, -06.5, -06.0 */ - 0x000087e8, 0x00008ff6, 0x0000987d, /* -05.5, -05.0, -04.5 */ - 0x0000a186, 0x0000ab19, 0x0000b53c, /* -04.0, -03.5, -03.0 */ - 0x0000bff9, 0x0000cb59, 0x0000d766, /* -02.5, -02.0, -01.5 */ - 0x0000e429, 0x0000f1ae, 0x00010000, /* -01.0, -00.5, 00.0 */ - 0x00010f2b, 0x00011f3d, 0x00013042, /* +00.5, +01.0, +01.5 */ - 0x00014249, 0x00015562, 0x0001699c, /* +02.0, +02.5, +03.0 */ - 0x00017f09, 0x000195bc, 0x0001adc6, /* +03.5, +04.0, +04.5 */ - 0x0001c73d, 0x0001e237, 0x0001feca, /* +05.0, +05.5, +06.0 */ - 0x00021d0e, 0x00023d1d, 0x00025f12, /* +06.5, +07.0, +07.5 */ - 0x0002830b, 0x0002a925, 0x0002d182, /* +08.0, +08.5, +09.0 */ - 0x0002fc42, 0x0003298b, 0x00035983, /* +09.5, +10.0, +10.5 */ - 0x00038c53, 0x0003c225, 0x0003fb28, /* +11.0, +11.5, +12.0 */ - 0x0004378b, 0x00047783, 0x0004bb44, /* +12.5, +13.0, +13.5 */ - 0x0005030a, 0x00054f10, 0x00059f98, /* +14.0, +14.5, +15.0 */ - 0x0005f4e5, 0x00064f40, 0x0006aef6, /* +15.5, +16.0, +16.5 */ - 0x00071457, 0x00077fbb, 0x0007f17b /* +17.0, +17.5, +18.0 */ -}; +#define TAS3001C_VERSION "0.3" +#define TAS3001C_DATE "20011214" -/* tas_treble_table[] is a lookup table that holds the values to drop into - * the treble setting register on the TAS. Again, there is a formula for - * this one, but we use this instead due to lack of real math functions - * in the kernel. - */ -static char tas_treble_table[] = { - 0x96, 0x95, 0x94, /* -18.0, -17.5, -17.0 */ - 0x93, 0x92, 0x91, /* -16.5, -16.0, -15.5 */ - 0x90, 0x8f, 0x8e, /* -15.0, -14.5, -14.0 */ - 0x8d, 0x8c, 0x8b, /* -13.5, -13.0, -12.5 */ - 0x8a, 0x89, 0x88, /* -12.0, -11.5, -11.0 */ - 0x87, 0x86, 0x85, /* -10.5, -10.0, -09.5 */ - 0x84, 0x83, 0x82, /* -09.0, -08.5, -08.0 */ - 0x81, 0x80, 0x7f, /* -07.5, -07.0, -06.5 */ - 0x7e, 0x7d, 0x7c, /* -06.0, -05.5, -05.0 */ - 0x7b, 0x7a, 0x79, /* -04.5, -04.0, -03.5 */ - 0x78, 0x77, 0x76, /* -03.0, -02.5, -02.0 */ - 0x75, 0x74, 0x73, /* -01.5, -01.0, -00.5 */ - 0x72, 0x71, 0x70, /* 00.0, +00.5, +01.0 */ - 0x6e, 0x6d, 0x6c, /* +01.5, +02.0, +02.5 */ - 0x6b, 0x69, 0x68, /* +03.0, +03.5, +04.0 */ - 0x66, 0x65, 0x63, /* +04.5, +05.0, +05.5 */ - 0x62, 0x60, 0x5e, /* +06.0, +06.5, +07.0 */ - 0x5c, 0x5a, 0x57, /* +07.5, +08.0, +08.5 */ - 0x55, 0x52, 0x4f, /* +09.0, +09.5, +10.0 */ - 0x4c, 0x49, 0x45, /* +10.5, +11.0, +11.5 */ - 0x42, 0x3e, 0x3a, /* +12.0, +12.5, +13.0 */ - 0x36, 0x32, 0x2d, /* +13.5, +14.0, +14.5 */ - 0x28, 0x22, 0x1c, /* +15.0, +15.5, +16.0 */ - 0x16, 0x10, 0x09, /* +16.5, +17.0, +17.5 */ - 0x01 /* +18.0 */ -}; +#define I2C_DRIVERNAME_TAS3001C "TAS3001c driver V " TAS3001C_VERSION +#define I2C_DRIVERID_TAS3001C (I2C_DRIVERID_TAS_BASE+0) -/* tas_bass_table[] is a lookup table that holds the values to drop into - * the bass setting register on the TAS. Again, there is a formula for - * this one, but we use this instead due to lack of real math functions - * in the kernel. - */ -static char tas_bass_table[] = { - 0x86, 0x82, 0x7f, /* -18.0, -17.5, -17.0 */ - 0x7d, 0x7a, 0x78, /* -16.5, -16.0, -15.5 */ - 0x76, 0x74, 0x72, /* -15.0, -14.5, -14.0 */ - 0x70, 0x6e, 0x6d, /* -13.5, -13.0, -12.5 */ - 0x6b, 0x69, 0x66, /* -12.0, -11.5, -11.0 */ - 0x64, 0x61, 0x5f, /* -10.5, -10.0, -09.5 */ - 0x5d, 0x5c, 0x5a, /* -09.0, -08.5, -08.0 */ - 0x59, 0x58, 0x56, /* -07.5, -07.0, -06.5 */ - 0x55, 0x54, 0x53, /* -06.0, -05.5, -05.0 */ - 0x51, 0x4f, 0x4d, /* -04.5, -04.0, -03.5 */ - 0x4b, 0x49, 0x46, /* -03.0, -02.5, -02.0 */ - 0x44, 0x42, 0x40, /* -01.5, -01.0, -00.5 */ - 0x3e, 0x3c, 0x3b, /* 00.0, +00.5, +01.0 */ - 0x39, 0x38, 0x36, /* +01.5, +02.0, +02.5 */ - 0x35, 0x33, 0x31, /* +03.0, +03.5, +04.0 */ - 0x30, 0x2e, 0x2c, /* +04.5, +05.0, +05.5 */ - 0x2b, 0x29, 0x28, /* +06.0, +06.5, +07.0 */ - 0x26, 0x25, 0x23, /* +07.5, +08.0, +08.5 */ - 0x21, 0x1f, 0x1c, /* +09.0, +09.5, +10.0 */ - 0x19, 0x18, 0x17, /* +10.5, +11.0, +11.5 */ - 0x16, 0x14, 0x13, /* +12.0, +12.5, +13.0 */ - 0x12, 0x10, 0x0f, /* +13.5, +14.0, +14.5 */ - 0x0d, 0x0b, 0x0a, /* +15.0, +15.5, +16.0 */ - 0x08, 0x06, 0x03, /* +16.5, +17.0, +17.5 */ - 0x01 /* +18.0 */ -}; +extern struct tas_driver_hooks_t tas3001c_hooks; +extern struct tas_gain_t tas3001c_gain; +extern struct tas_eq_pref_t *tas3001c_eq_prefs[]; + +enum tas3001c_reg_t { + TAS3001C_REG_MCR = 0x01, + TAS3001C_REG_DRC = 0x02, + + TAS3001C_REG_VOLUME = 0x04, + TAS3001C_REG_TREBLE = 0x05, + TAS3001C_REG_BASS = 0x06, + TAS3001C_REG_MIXER1 = 0x07, + TAS3001C_REG_MIXER2 = 0x08, + + TAS3001C_REG_LEFT_BIQUAD0 = 0x0a, + TAS3001C_REG_LEFT_BIQUAD1 = 0x0b, + TAS3001C_REG_LEFT_BIQUAD2 = 0x0c, + TAS3001C_REG_LEFT_BIQUAD3 = 0x0d, + TAS3001C_REG_LEFT_BIQUAD4 = 0x0e, + TAS3001C_REG_LEFT_BIQUAD5 = 0x0f, + TAS3001C_REG_LEFT_BIQUAD6 = 0x10, + + TAS3001C_REG_RIGHT_BIQUAD0 = 0x13, + TAS3001C_REG_RIGHT_BIQUAD1 = 0x14, + TAS3001C_REG_RIGHT_BIQUAD2 = 0x15, + TAS3001C_REG_RIGHT_BIQUAD3 = 0x16, + TAS3001C_REG_RIGHT_BIQUAD4 = 0x17, + TAS3001C_REG_RIGHT_BIQUAD5 = 0x18, + TAS3001C_REG_RIGHT_BIQUAD6 = 0x19, -/* tas_input_table[] is a lookup table that holds the values to drop into - * the setting registers on the TAS for "mixers 1 & 2" (which are the input - * lines). Again, there is a formula for these, but we use this instead - * due to lack of real math functions in the kernel. - */ -static unsigned int tas_input_table[] = { - 0x00014b, 0x00015f, 0x000174, /* -70.0, -69.5, -69.0 */ - 0x00018a, 0x0001a1, 0x0001ba, /* -68.5, -68.0, -67.5 */ - 0x0001d4, 0x0001f0, 0x00020d, /* -67.0, -66.5, -66.0 */ - 0x00022c, 0x00024d, 0x000270, /* -65.5, -65.0, -64.5 */ - 0x000295, 0x0002bc, 0x0002e6, /* -64.0, -63.5, -63.0 */ - 0x000312, 0x000340, 0x000372, /* -62.5, -62.0, -61.5 */ - 0x0003a6, 0x0003dd, 0x000418, /* -61.0, -60.5, -60.0 */ - 0x000456, 0x000498, 0x0004de, /* -59.5, -59.0, -58.5 */ - 0x000528, 0x000576, 0x0005c9, /* -58.0, -57.5, -57.0 */ - 0x000620, 0x00067d, 0x0006e0, /* -56.5, -56.0, -55.5 */ - 0x000748, 0x0007b7, 0x00082c, /* -55.0, -54.5, -54.0 */ - 0x0008a8, 0x00092b, 0x0009b6, /* -53.5, -53.0, -52.5 */ - 0x000a49, 0x000ae5, 0x000b8b, /* -52.0, -51.5, -51.0 */ - 0x000c3a, 0x000cf3, 0x000db8, /* -50.5, -50.0, -49.5 */ - 0x000e88, 0x000f64, 0x00104e, /* -49.0, -48.5, -48.0 */ - 0x001145, 0x00124b, 0x001361, /* -47.5, -47.0, -46.5 */ - 0x001487, 0x0015be, 0x001708, /* -46.0, -45.5, -45.0 */ - 0x001865, 0x0019d8, 0x001b60, /* -44.5, -44.0, -43.5 */ - 0x001cff, 0x001eb7, 0x002089, /* -43.0, -42.5, -42.0 */ - 0x002276, 0x002481, 0x0026ab, /* -41.5, -41.0, -40.5 */ - 0x0028f5, 0x002b63, 0x002df5, /* -40.0, -39.5, -39.0 */ - 0x0030ae, 0x003390, 0x00369e, /* -38.5, -38.0, -37.5 */ - 0x0039db, 0x003d49, 0x0040ea, /* -37.0, -36.5, -36.0 */ - 0x0044c3, 0x0048d6, 0x004d27, /* -35.5, -35.0, -34.5 */ - 0x0051b9, 0x005691, 0x005bb2, /* -34.0, -33.5, -33.0 */ - 0x006121, 0x0066e3, 0x006cfb, /* -32.5, -32.0, -31.5 */ - 0x007370, 0x007a48, 0x008186, /* -31.0, -30.5, -30.0 */ - 0x008933, 0x009154, 0x0099f1, /* -29.5, -29.0, -28.5 */ - 0x00a310, 0x00acba, 0x00b6f6, /* -28.0, -27.5, -27.0 */ - 0x00c1cd, 0x00cd49, 0x00d973, /* -26.5, -26.0, -25.5 */ - 0x00e655, 0x00f3fb, 0x010270, /* -25.0, -24.5, -24.0 */ - 0x0111c0, 0x0121f9, 0x013328, /* -23.5, -23.0, -22.5 */ - 0x01455b, 0x0158a2, 0x016d0e, /* -22.0, -21.5, -21.0 */ - 0x0182af, 0x019999, 0x01b1de, /* -20.5, -20.0, -19.5 */ - 0x01cb94, 0x01e6cf, 0x0203a7, /* -19.0, -18.5, -18.0 */ - 0x022235, 0x024293, 0x0264db, /* -17.5, -17.0, -16.5 */ - 0x02892c, 0x02afa3, 0x02d862, /* -16.0, -15.5, -15.0 */ - 0x03038a, 0x033142, 0x0361af, /* -14.5, -14.0, -13.5 */ - 0x0394fa, 0x03cb50, 0x0404de, /* -13.0, -12.5, -12.0 */ - 0x0441d5, 0x048268, 0x04c6d0, /* -11.5, -11.0, -10.5 */ - 0x050f44, 0x055c04, 0x05ad50, /* -10.0, -09.5, -09.0 */ - 0x06036e, 0x065ea5, 0x06bf44, /* -08.5, -08.0, -07.5 */ - 0x07259d, 0x079207, 0x0804dc, /* -07.0, -06.5, -06.0 */ - 0x087e80, 0x08ff59, 0x0987d5, /* -05.5, -05.0, -04.5 */ - 0x0a1866, 0x0ab189, 0x0b53be, /* -04.0, -03.5, -03.0 */ - 0x0bff91, 0x0cb591, 0x0d765a, /* -02.5, -02.0, -01.5 */ - 0x0e4290, 0x0f1adf, 0x100000, /* -01.0, -00.5, 00.0 */ - 0x10f2b4, 0x11f3c9, 0x13041a, /* +00.5, +01.0, +01.5 */ - 0x14248e, 0x15561a, 0x1699c0, /* +02.0, +02.5, +03.0 */ - 0x17f094, 0x195bb8, 0x1adc61, /* +03.5, +04.0, +04.5 */ - 0x1c73d5, 0x1e236d, 0x1fec98, /* +05.0, +05.5, +06.0 */ - 0x21d0d9, 0x23d1cd, 0x25f125, /* +06.5, +07.0, +07.5 */ - 0x2830af, 0x2a9254, 0x2d1818, /* +08.0, +08.5, +09.0 */ - 0x2fc420, 0x3298b0, 0x35982f, /* +09.5, +10.0, +10.5 */ - 0x38c528, 0x3c224c, 0x3fb278, /* +11.0, +11.5, +12.0 */ - 0x437880, 0x477828, 0x4bb446, /* +12.5, +13.0, +13.5 */ - 0x5030a1, 0x54f106, 0x59f980, /* +14.0, +14.5, +15.0 */ - 0x5f4e52, 0x64f403, 0x6aef5d, /* +15.5, +16.0, +16.5 */ - 0x714575, 0x77fbaa, 0x7f17af /* +17.0, +17.5, +18.0 */ + TAS3001C_REG_MAX = 0x20 }; -#endif /* _tas3001c_h_ */ +#endif /* _TAS3001C_H_ */ diff -uNr linux-2.4.21/drivers/sound/dmasound/tas3001c_tables.c linux-2.4.21-ben2/drivers/sound/dmasound/tas3001c_tables.c --- linux-2.4.21/drivers/sound/dmasound/tas3001c_tables.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/drivers/sound/dmasound/tas3001c_tables.c 2003-06-27 15:41:34.000000000 +0200 @@ -0,0 +1,375 @@ +#include "tas_common.h" +#include "tas_eq_prefs.h" + +static struct tas_drce_t eqp_0e_2_1_drce = { + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -15.33 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_0e_2_1_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } }, + { channel: 0, filter: 1, data: { coeff: { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } }, + { channel: 0, filter: 5, data: { coeff: { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } }, + { channel: 1, filter: 1, data: { coeff: { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } }, + { channel: 1, filter: 5, data: { coeff: { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } }, +}; + +static struct tas_eq_pref_t eqp_0e_2_1 = { + sample_rate: 44100, + device_id: 0x0e, + output_id: TAS_OUTPUT_EXTERNAL_SPKR, + speaker_id: 0x01, + + drce: &eqp_0e_2_1_drce, + + filter_count: 12, + biquads: eqp_0e_2_1_biquads +}; + +/* ======================================================================== */ + +static struct tas_drce_t eqp_10_1_0_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -12.46 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_10_1_0_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0F4A12, 0xE16BDA, 0x0F4A12, 0xE173F0, 0x0E9C3A } } }, + { channel: 0, filter: 1, data: { coeff: { 0x02DD54, 0x05BAA8, 0x02DD54, 0xF8001D, 0x037532 } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0E2FC7, 0xE4D5DC, 0x0D7477, 0xE4D5DC, 0x0BA43F } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0E7899, 0xE67CCA, 0x0D0E93, 0xE67CCA, 0x0B872D } } }, + { channel: 0, filter: 4, data: { coeff: { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } }, + { channel: 0, filter: 5, data: { coeff: { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0F4A12, 0xE16BDA, 0x0F4A12, 0xE173F0, 0x0E9C3A } } }, + { channel: 1, filter: 1, data: { coeff: { 0x02DD54, 0x05BAA8, 0x02DD54, 0xF8001D, 0x037532 } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0E2FC7, 0xE4D5DC, 0x0D7477, 0xE4D5DC, 0x0BA43F } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0E7899, 0xE67CCA, 0x0D0E93, 0xE67CCA, 0x0B872D } } }, + { channel: 1, filter: 4, data: { coeff: { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } }, + { channel: 1, filter: 5, data: { coeff: { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } }, +}; + +static struct tas_eq_pref_t eqp_10_1_0 = { + sample_rate: 44100, + device_id: 0x10, + output_id: TAS_OUTPUT_INTERNAL_SPKR, + speaker_id: 0x00, + + drce: &eqp_10_1_0_drce, + + filter_count: 12, + biquads: eqp_10_1_0_biquads +}; + +/* ======================================================================== */ + +static struct tas_drce_t eqp_15_2_1_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -15.33 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_15_2_1_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } }, + { channel: 0, filter: 1, data: { coeff: { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } }, + { channel: 0, filter: 5, data: { coeff: { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } }, + { channel: 1, filter: 1, data: { coeff: { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } }, + { channel: 1, filter: 5, data: { coeff: { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } }, +}; + +static struct tas_eq_pref_t eqp_15_2_1 = { + sample_rate: 44100, + device_id: 0x15, + output_id: TAS_OUTPUT_EXTERNAL_SPKR, + speaker_id: 0x01, + + drce: &eqp_15_2_1_drce, + + filter_count: 12, + biquads: eqp_15_2_1_biquads +}; + +/* ======================================================================== */ + +static struct tas_drce_t eqp_15_1_0_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: 0.0 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_15_1_0_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0FAD08, 0xE0A5EF, 0x0FAD08, 0xE0A79D, 0x0F5BBE } } }, + { channel: 0, filter: 1, data: { coeff: { 0x04B38D, 0x09671B, 0x04B38D, 0x000F71, 0x02BEC5 } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0FDD32, 0xE0A56F, 0x0F8A69, 0xE0A56F, 0x0F679C } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0FD284, 0xE135FB, 0x0F2161, 0xE135FB, 0x0EF3E5 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x0E81B1, 0xE6283F, 0x0CE49D, 0xE6283F, 0x0B664F } } }, + { channel: 0, filter: 5, data: { coeff: { 0x0F2D62, 0xE98797, 0x0D1E19, 0xE98797, 0x0C4B7B } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0FAD08, 0xE0A5EF, 0x0FAD08, 0xE0A79D, 0x0F5BBE } } }, + { channel: 1, filter: 1, data: { coeff: { 0x04B38D, 0x09671B, 0x04B38D, 0x000F71, 0x02BEC5 } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0FDD32, 0xE0A56F, 0x0F8A69, 0xE0A56F, 0x0F679C } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0FD284, 0xE135FB, 0x0F2161, 0xE135FB, 0x0EF3E5 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x0E81B1, 0xE6283F, 0x0CE49D, 0xE6283F, 0x0B664F } } }, + { channel: 1, filter: 5, data: { coeff: { 0x0F2D62, 0xE98797, 0x0D1E19, 0xE98797, 0x0C4B7B } } }, +}; + +static struct tas_eq_pref_t eqp_15_1_0 = { + sample_rate: 44100, + device_id: 0x15, + output_id: TAS_OUTPUT_INTERNAL_SPKR, + speaker_id: 0x00, + + drce: &eqp_15_1_0_drce, + + filter_count: 12, + biquads: eqp_15_1_0_biquads +}; + +/* ======================================================================== */ + +static struct tas_drce_t eqp_0f_2_1_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -15.33 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_0f_2_1_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } }, + { channel: 0, filter: 1, data: { coeff: { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } }, + { channel: 0, filter: 5, data: { coeff: { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } }, + { channel: 1, filter: 1, data: { coeff: { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } }, + { channel: 1, filter: 5, data: { coeff: { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } }, +}; + +static struct tas_eq_pref_t eqp_0f_2_1 = { + sample_rate: 44100, + device_id: 0x0f, + output_id: TAS_OUTPUT_EXTERNAL_SPKR, + speaker_id: 0x01, + + drce: &eqp_0f_2_1_drce, + + filter_count: 12, + biquads: eqp_0f_2_1_biquads +}; + +/* ======================================================================== */ + +static struct tas_drce_t eqp_0f_1_0_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -15.33 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_0f_1_0_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } }, + { channel: 0, filter: 1, data: { coeff: { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } }, + { channel: 0, filter: 5, data: { coeff: { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } }, + { channel: 1, filter: 1, data: { coeff: { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } }, + { channel: 1, filter: 5, data: { coeff: { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } }, +}; + +static struct tas_eq_pref_t eqp_0f_1_0 = { + sample_rate: 44100, + device_id: 0x0f, + output_id: TAS_OUTPUT_INTERNAL_SPKR, + speaker_id: 0x00, + + drce: &eqp_0f_1_0_drce, + + filter_count: 12, + biquads: eqp_0f_1_0_biquads +}; + +/* ======================================================================== */ + +static uint tas3001c_master_tab[]={ + 0x0, 0x75, 0x9c, 0xbb, + 0xdb, 0xfb, 0x11e, 0x143, + 0x16b, 0x196, 0x1c3, 0x1f5, + 0x229, 0x263, 0x29f, 0x2e1, + 0x328, 0x373, 0x3c5, 0x41b, + 0x478, 0x4dc, 0x547, 0x5b8, + 0x633, 0x6b5, 0x740, 0x7d5, + 0x873, 0x91c, 0x9d2, 0xa92, + 0xb5e, 0xc39, 0xd22, 0xe19, + 0xf20, 0x1037, 0x1161, 0x129e, + 0x13ed, 0x1551, 0x16ca, 0x185d, + 0x1a08, 0x1bcc, 0x1dac, 0x1fa7, + 0x21c1, 0x23fa, 0x2655, 0x28d6, + 0x2b7c, 0x2e4a, 0x3141, 0x3464, + 0x37b4, 0x3b35, 0x3ee9, 0x42d3, + 0x46f6, 0x4b53, 0x4ff0, 0x54ce, + 0x59f2, 0x5f5f, 0x6519, 0x6b24, + 0x7183, 0x783c, 0x7f53, 0x86cc, + 0x8ead, 0x96fa, 0x9fba, 0xa8f2, + 0xb2a7, 0xbce1, 0xc7a5, 0xd2fa, + 0xdee8, 0xeb75, 0xf8aa, 0x1068e, + 0x1152a, 0x12487, 0x134ad, 0x145a5, + 0x1577b, 0x16a37, 0x17df5, 0x192bd, + 0x1a890, 0x1bf7b, 0x1d78d, 0x1f0d1, + 0x20b55, 0x22727, 0x24456, 0x262f2, + 0x2830b +}; + +static uint tas3001c_mixer_tab[]={ + 0x0, 0x748, 0x9be, 0xbaf, + 0xda4, 0xfb1, 0x11de, 0x1431, + 0x16ad, 0x1959, 0x1c37, 0x1f4b, + 0x2298, 0x2628, 0x29fb, 0x2e12, + 0x327d, 0x3734, 0x3c47, 0x41b4, + 0x4787, 0x4dbe, 0x546d, 0x5b86, + 0x632e, 0x6b52, 0x7400, 0x7d54, + 0x873b, 0x91c6, 0x9d1a, 0xa920, + 0xb5e5, 0xc38c, 0xd21b, 0xe18f, + 0xf1f5, 0x1036a, 0x1160f, 0x129d6, + 0x13ed0, 0x1550c, 0x16ca0, 0x185c9, + 0x1a07b, 0x1bcc3, 0x1dab9, 0x1fa75, + 0x21c0f, 0x23fa3, 0x26552, 0x28d64, + 0x2b7c9, 0x2e4a2, 0x31411, 0x3463b, + 0x37b44, 0x3b353, 0x3ee94, 0x42d30, + 0x46f55, 0x4b533, 0x4fefc, 0x54ce5, + 0x59f25, 0x5f5f6, 0x65193, 0x6b23c, + 0x71835, 0x783c3, 0x7f52c, 0x86cc0, + 0x8eacc, 0x96fa5, 0x9fba0, 0xa8f1a, + 0xb2a71, 0xbce0a, 0xc7a4a, 0xd2fa0, + 0xdee7b, 0xeb752, 0xf8a9f, 0x1068e4, + 0x1152a3, 0x12486a, 0x134ac8, 0x145a55, + 0x1577ac, 0x16a370, 0x17df51, 0x192bc2, + 0x1a88f8, 0x1bf7b7, 0x1d78c9, 0x1f0d04, + 0x20b542, 0x227268, 0x244564, 0x262f26, + 0x2830af +}; + +static uint tas3001c_treble_tab[]={ + 0x96, 0x95, 0x95, 0x94, + 0x93, 0x92, 0x92, 0x91, + 0x90, 0x90, 0x8f, 0x8e, + 0x8d, 0x8d, 0x8c, 0x8b, + 0x8a, 0x8a, 0x89, 0x88, + 0x88, 0x87, 0x86, 0x85, + 0x85, 0x84, 0x83, 0x83, + 0x82, 0x81, 0x80, 0x80, + 0x7f, 0x7e, 0x7e, 0x7d, + 0x7c, 0x7b, 0x7b, 0x7a, + 0x79, 0x78, 0x78, 0x77, + 0x76, 0x76, 0x75, 0x74, + 0x73, 0x73, 0x72, 0x71, + 0x71, 0x70, 0x6e, 0x6d, + 0x6d, 0x6c, 0x6b, 0x6a, + 0x69, 0x68, 0x67, 0x66, + 0x65, 0x63, 0x62, 0x62, + 0x60, 0x5f, 0x5d, 0x5c, + 0x5a, 0x58, 0x56, 0x55, + 0x53, 0x51, 0x4f, 0x4c, + 0x4a, 0x48, 0x45, 0x43, + 0x40, 0x3d, 0x3a, 0x37, + 0x35, 0x32, 0x2e, 0x2a, + 0x27, 0x22, 0x1e, 0x1a, + 0x15, 0x11, 0xc, 0x7, + 0x1 +}; + +static uint tas3001c_bass_tab[]={ + 0x86, 0x83, 0x81, 0x7f, + 0x7d, 0x7b, 0x79, 0x78, + 0x76, 0x75, 0x74, 0x72, + 0x71, 0x6f, 0x6e, 0x6d, + 0x6c, 0x6b, 0x69, 0x67, + 0x65, 0x64, 0x61, 0x60, + 0x5e, 0x5d, 0x5c, 0x5b, + 0x5a, 0x59, 0x58, 0x57, + 0x56, 0x55, 0x55, 0x54, + 0x53, 0x52, 0x50, 0x4f, + 0x4d, 0x4c, 0x4b, 0x49, + 0x47, 0x45, 0x44, 0x42, + 0x41, 0x3f, 0x3e, 0x3d, + 0x3c, 0x3b, 0x39, 0x38, + 0x37, 0x36, 0x35, 0x34, + 0x33, 0x31, 0x30, 0x2f, + 0x2e, 0x2c, 0x2b, 0x2b, + 0x29, 0x28, 0x27, 0x26, + 0x25, 0x24, 0x22, 0x21, + 0x20, 0x1e, 0x1c, 0x19, + 0x18, 0x18, 0x17, 0x16, + 0x15, 0x14, 0x13, 0x12, + 0x11, 0x10, 0xf, 0xe, + 0xd, 0xb, 0xa, 0x9, + 0x8, 0x6, 0x4, 0x2, + 0x1 +}; + +struct tas_gain_t tas3001c_gain = { + master: tas3001c_master_tab, + treble: tas3001c_treble_tab, + bass: tas3001c_bass_tab, + mixer: tas3001c_mixer_tab +}; + +struct tas_eq_pref_t *tas3001c_eq_prefs[]={ + &eqp_0e_2_1, + &eqp_10_1_0, + &eqp_15_2_1, + &eqp_15_1_0, + &eqp_0f_2_1, + &eqp_0f_1_0, + NULL +}; diff -uNr linux-2.4.21/drivers/sound/dmasound/tas3004.c linux-2.4.21-ben2/drivers/sound/dmasound/tas3004.c --- linux-2.4.21/drivers/sound/dmasound/tas3004.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/drivers/sound/dmasound/tas3004.c 2003-06-27 15:41:02.000000000 +0200 @@ -0,0 +1,1173 @@ +/* + * Driver for the i2c/i2s based TA3004 sound chip used + * on some Apple hardware. Also known as "snapper". + * + * Tobias Sargeant + * Based upon tas3001c.c by Christopher C. Chimelis : + * + * TODO: + * ----- + * * Enable control over input line 2 (is this connected?) + * * Implement sleep support (at least mute everything and + * * set gains to minimum during sleep) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "dmasound.h" +#include "tas_common.h" +#include "tas3004.h" + +#include "tas_ioctl.h" + +/* #define DEBUG_DRCE */ + +#define TAS3004_BIQUAD_FILTER_COUNT 7 +#define TAS3004_BIQUAD_CHANNEL_COUNT 2 + +#define VOL_DEFAULT (100 * 4 / 5) +#define INPUT_DEFAULT (100 * 4 / 5) +#define BASS_DEFAULT (100 / 2) +#define TREBLE_DEFAULT (100 / 2) + +struct tas3004_data_t { + struct tas_data_t super; + int device_id; + int output_id; + int speaker_id; + struct tas_drce_t drce_state; +}; + +#define MAKE_TIME(sec,usec) (((sec)<<12) + (50000+(usec/10)*(1<<12))/100000) + +#define MAKE_RATIO(i,f) (((i)<<8) + ((500+(f)*(1<<8))/1000)) + + +static const union tas_biquad_t +tas3004_eq_unity={ + buf: { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } +}; + + +static const struct tas_drce_t +tas3004_drce_min={ + enable: 1, + above: { val: MAKE_RATIO(16,0), expand:0 }, + below: { val: MAKE_RATIO(2,0), expand:0 }, + threshold: -0x59a0, + energy: MAKE_TIME(0, 1700), + attack: MAKE_TIME(0, 1700), + decay: MAKE_TIME(0, 1700) +}; + + +static const struct tas_drce_t +tas3004_drce_max={ + enable: 1, + above: { val: MAKE_RATIO(1,500), expand:1 }, + below: { val: MAKE_RATIO(2,0), expand:1 }, + threshold: -0x0, + energy: MAKE_TIME(2,400000), + attack: MAKE_TIME(2,400000), + decay: MAKE_TIME(2,400000) +}; + + +static const unsigned short time_constants[]={ + MAKE_TIME(0, 1700), + MAKE_TIME(0, 3500), + MAKE_TIME(0, 6700), + MAKE_TIME(0, 13000), + MAKE_TIME(0, 26000), + MAKE_TIME(0, 53000), + MAKE_TIME(0,106000), + MAKE_TIME(0,212000), + MAKE_TIME(0,425000), + MAKE_TIME(0,850000), + MAKE_TIME(1,700000), + MAKE_TIME(2,400000), +}; + +static const unsigned short above_threshold_compression_ratio[]={ + MAKE_RATIO( 1, 70), + MAKE_RATIO( 1,140), + MAKE_RATIO( 1,230), + MAKE_RATIO( 1,330), + MAKE_RATIO( 1,450), + MAKE_RATIO( 1,600), + MAKE_RATIO( 1,780), + MAKE_RATIO( 2, 0), + MAKE_RATIO( 2,290), + MAKE_RATIO( 2,670), + MAKE_RATIO( 3,200), + MAKE_RATIO( 4, 0), + MAKE_RATIO( 5,330), + MAKE_RATIO( 8, 0), + MAKE_RATIO(16, 0), +}; + +static const unsigned short above_threshold_expansion_ratio[]={ + MAKE_RATIO(1, 60), + MAKE_RATIO(1,130), + MAKE_RATIO(1,190), + MAKE_RATIO(1,250), + MAKE_RATIO(1,310), + MAKE_RATIO(1,380), + MAKE_RATIO(1,440), + MAKE_RATIO(1,500) +}; + +static const unsigned short below_threshold_compression_ratio[]={ + MAKE_RATIO(1, 70), + MAKE_RATIO(1,140), + MAKE_RATIO(1,230), + MAKE_RATIO(1,330), + MAKE_RATIO(1,450), + MAKE_RATIO(1,600), + MAKE_RATIO(1,780), + MAKE_RATIO(2, 0) +}; + +static const unsigned short below_threshold_expansion_ratio[]={ + MAKE_RATIO(1, 60), + MAKE_RATIO(1,130), + MAKE_RATIO(1,190), + MAKE_RATIO(1,250), + MAKE_RATIO(1,310), + MAKE_RATIO(1,380), + MAKE_RATIO(1,440), + MAKE_RATIO(1,500), + MAKE_RATIO(1,560), + MAKE_RATIO(1,630), + MAKE_RATIO(1,690), + MAKE_RATIO(1,750), + MAKE_RATIO(1,810), + MAKE_RATIO(1,880), + MAKE_RATIO(1,940), + MAKE_RATIO(2, 0) +}; + +static inline int +search( unsigned short val, + const unsigned short *arr, + const int arrsize) { + /* + * This could be a binary search, but for small tables, + * a linear search is likely to be faster + */ + + int i; + + for (i=0; i < arrsize; i++) + if (arr[i] >= val) + goto _1; + return arrsize-1; + _1: + if (i == 0) + return 0; + return (arr[i]-val < val-arr[i-1]) ? i : i-1; +} + +#define SEARCH(a, b) search(a, b, ARRAY_SIZE(b)) + +static inline int +time_index(unsigned short time) { + return SEARCH(time, time_constants); +} + + +static inline int +above_threshold_compression_index(unsigned short ratio) { + return SEARCH(ratio, above_threshold_compression_ratio); +} + + +static inline int +above_threshold_expansion_index(unsigned short ratio) { + return SEARCH(ratio, above_threshold_expansion_ratio); +} + + +static inline int +below_threshold_compression_index(unsigned short ratio) { + return SEARCH(ratio, below_threshold_compression_ratio); +} + + +static inline int +below_threshold_expansion_index(unsigned short ratio) { + return SEARCH(ratio, below_threshold_expansion_ratio); +} + + +static inline unsigned char db_to_regval(short db) { + int r=0; + + r=(db+0x59a0) / 0x60; + + if (r < 0x91) return 0x91; + if (r > 0xef) return 0xef; + return r; +} + + +static inline short quantize_db(short db) { + return db_to_regval(db) * 0x60 - 0x59a0; +} + + +static inline int +register_width(enum tas3004_reg_t r) +{ + switch(r) { + case TAS3004_REG_MCR: + case TAS3004_REG_TREBLE: + case TAS3004_REG_BASS: + case TAS3004_REG_ANALOG_CTRL: + case TAS3004_REG_TEST1: + case TAS3004_REG_TEST2: + case TAS3004_REG_MCR2: + return 1; + + case TAS3004_REG_LEFT_LOUD_BIQUAD_GAIN: + case TAS3004_REG_RIGHT_LOUD_BIQUAD_GAIN: + return 3; + + case TAS3004_REG_DRC: + case TAS3004_REG_VOLUME: + return 6; + + case TAS3004_REG_LEFT_MIXER: + case TAS3004_REG_RIGHT_MIXER: + return 9; + + case TAS3004_REG_TEST: + return 10; + + case TAS3004_REG_LEFT_BIQUAD0: + case TAS3004_REG_LEFT_BIQUAD1: + case TAS3004_REG_LEFT_BIQUAD2: + case TAS3004_REG_LEFT_BIQUAD3: + case TAS3004_REG_LEFT_BIQUAD4: + case TAS3004_REG_LEFT_BIQUAD5: + case TAS3004_REG_LEFT_BIQUAD6: + + case TAS3004_REG_RIGHT_BIQUAD0: + case TAS3004_REG_RIGHT_BIQUAD1: + case TAS3004_REG_RIGHT_BIQUAD2: + case TAS3004_REG_RIGHT_BIQUAD3: + case TAS3004_REG_RIGHT_BIQUAD4: + case TAS3004_REG_RIGHT_BIQUAD5: + case TAS3004_REG_RIGHT_BIQUAD6: + + case TAS3004_REG_LEFT_LOUD_BIQUAD: + case TAS3004_REG_RIGHT_LOUD_BIQUAD: + return 15; + + default: + return 0; + } +} + + +static int +tas3004_write_register( struct tas3004_data_t *self, + enum tas3004_reg_t reg_num, + char *data, + uint write_mode) +{ + if (reg_num==TAS3004_REG_MCR || + reg_num==TAS3004_REG_BASS || + reg_num==TAS3004_REG_TREBLE) { + return tas_write_byte_register(&self->super, + (uint)reg_num, + *data, + write_mode); + } else { + return tas_write_register(&self->super, + (uint)reg_num, + register_width(reg_num), + data, + write_mode); + } +} + + +static int +tas3004_sync_register( struct tas3004_data_t *self, + enum tas3004_reg_t reg_num) +{ + if (reg_num==TAS3004_REG_MCR || + reg_num==TAS3004_REG_BASS || + reg_num==TAS3004_REG_TREBLE) { + return tas_sync_byte_register(&self->super, + (uint)reg_num, + register_width(reg_num)); + } else { + return tas_sync_register(&self->super, + (uint)reg_num, + register_width(reg_num)); + } +} + + +static int +tas3004_read_register( struct tas3004_data_t *self, + enum tas3004_reg_t reg_num, + char *data, + uint write_mode) +{ + return tas_read_register(&self->super, + (uint)reg_num, + register_width(reg_num), + data); +} + + +static inline int +tas3004_fast_load(struct tas3004_data_t *self, int fast) +{ + if (fast) + self->super.shadow[TAS3004_REG_MCR][0] |= 0x80; + else + self->super.shadow[TAS3004_REG_MCR][0] &= 0x7f; + return tas3004_sync_register(self,TAS3004_REG_MCR); +} + + +static uint +tas3004_supported_mixers(struct tas3004_data_t *self) +{ + return SOUND_MASK_VOLUME | + SOUND_MASK_PCM | + SOUND_MASK_ALTPCM | + SOUND_MASK_IMIX | + SOUND_MASK_TREBLE | + SOUND_MASK_BASS; +} + + +static int +tas3004_mixer_is_stereo(struct tas3004_data_t *self, int mixer) +{ + switch(mixer) { + case SOUND_MIXER_VOLUME: + case SOUND_MIXER_PCM: + case SOUND_MIXER_ALTPCM: + case SOUND_MIXER_IMIX: + return 1; + default: + return 0; + } +} + + +static uint +tas3004_stereo_mixers(struct tas3004_data_t *self) +{ + uint r = tas3004_supported_mixers(self); + uint i; + + for (i=1; isuper.mixer[mixer]; + + return 0; +} + + +static int +tas3004_set_mixer_level(struct tas3004_data_t *self, int mixer, uint level) +{ + int rc; + tas_shadow_t *shadow; + uint temp; + uint offset=0; + + if (!self) + return -1; + + shadow = self->super.shadow; + + if (!tas3004_mixer_is_stereo(self,mixer)) + level = tas_mono_to_stereo(level); + switch(mixer) { + case SOUND_MIXER_VOLUME: + temp = tas3004_gain.master[level&0xff]; + SET_4_20(shadow[TAS3004_REG_VOLUME], 0, temp); + temp = tas3004_gain.master[(level>>8)&0xff]; + SET_4_20(shadow[TAS3004_REG_VOLUME], 3, temp); + rc = tas3004_sync_register(self,TAS3004_REG_VOLUME); + break; + case SOUND_MIXER_IMIX: + offset += 3; + case SOUND_MIXER_ALTPCM: + offset += 3; + case SOUND_MIXER_PCM: + /* + * Don't load these in fast mode. The documentation + * says it can be done in either mode, but testing it + * shows that fast mode produces ugly clicking. + */ + /* tas3004_fast_load(self,1); */ + temp = tas3004_gain.mixer[level&0xff]; + SET_4_20(shadow[TAS3004_REG_LEFT_MIXER], offset, temp); + temp = tas3004_gain.mixer[(level>>8)&0xff]; + SET_4_20(shadow[TAS3004_REG_RIGHT_MIXER], offset, temp); + rc = tas3004_sync_register(self,TAS3004_REG_LEFT_MIXER); + if (rc == 0) + rc=tas3004_sync_register(self,TAS3004_REG_RIGHT_MIXER); + /* tas3004_fast_load(self,0); */ + break; + case SOUND_MIXER_TREBLE: + temp = tas3004_gain.treble[level&0xff]; + shadow[TAS3004_REG_TREBLE][0]=temp&0xff; + rc = tas3004_sync_register(self,TAS3004_REG_TREBLE); + break; + case SOUND_MIXER_BASS: + temp = tas3004_gain.bass[level&0xff]; + shadow[TAS3004_REG_BASS][0]=temp&0xff; + rc = tas3004_sync_register(self,TAS3004_REG_BASS); + break; + default: + rc = -1; + break; + } + if (rc < 0) + return rc; + self->super.mixer[mixer] = level; + + return 0; +} + + +static int +tas3004_leave_sleep(struct tas3004_data_t *self) +{ + unsigned char mcr = (1<<6)+(2<<4)+(2<<2); + + if (!self) + return -1; + + /* Make sure something answers on the i2c bus */ + if (tas3004_write_register(self, TAS3004_REG_MCR, &mcr, + WRITE_NORMAL | FORCE_WRITE) < 0) + return -1; + + tas3004_fast_load(self, 1); + + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD0); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD1); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD2); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD3); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD4); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD5); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD6); + + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD0); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD1); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD2); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD3); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD4); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD5); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD6); + + tas3004_fast_load(self, 0); + + (void)tas3004_sync_register(self,TAS3004_REG_VOLUME); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_MIXER); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_MIXER); + (void)tas3004_sync_register(self,TAS3004_REG_TREBLE); + (void)tas3004_sync_register(self,TAS3004_REG_BASS); + + return 0; +} + + +static int +tas3004_enter_sleep(struct tas3004_data_t *self) +{ + if (!self) + return -1; + return 0; +} + + +static int +tas3004_sync_biquad( struct tas3004_data_t *self, + u_int channel, + u_int filter) +{ + enum tas3004_reg_t reg; + + if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT || + filter >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL; + + reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter; + + return tas3004_sync_register(self,reg); +} + + +static int +tas3004_write_biquad_shadow( struct tas3004_data_t *self, + u_int channel, + u_int filter, + const union tas_biquad_t *biquad) +{ + tas_shadow_t *shadow=self->super.shadow; + enum tas3004_reg_t reg; + + if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT || + filter >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL; + + reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter; + + SET_4_20(shadow[reg], 0,biquad->coeff.b0); + SET_4_20(shadow[reg], 3,biquad->coeff.b1); + SET_4_20(shadow[reg], 6,biquad->coeff.b2); + SET_4_20(shadow[reg], 9,biquad->coeff.a1); + SET_4_20(shadow[reg],12,biquad->coeff.a2); + + return 0; +} + + +static int +tas3004_write_biquad( struct tas3004_data_t *self, + u_int channel, + u_int filter, + const union tas_biquad_t *biquad) +{ + int rc; + + rc=tas3004_write_biquad_shadow(self, channel, filter, biquad); + if (rc < 0) return rc; + + return tas3004_sync_biquad(self, channel, filter); +} + + +static int +tas3004_write_biquad_list( struct tas3004_data_t *self, + u_int filter_count, + u_int flags, + struct tas_biquad_ctrl_t *biquads) +{ + int i; + int rc; + + if (flags & TAS_BIQUAD_FAST_LOAD) tas3004_fast_load(self,1); + + for (i=0; isuper.shadow; + enum tas3004_reg_t reg; + + if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT || + filter >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL; + + reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter; + + biquad->coeff.b0=GET_4_20(shadow[reg], 0); + biquad->coeff.b1=GET_4_20(shadow[reg], 3); + biquad->coeff.b2=GET_4_20(shadow[reg], 6); + biquad->coeff.a1=GET_4_20(shadow[reg], 9); + biquad->coeff.a2=GET_4_20(shadow[reg],12); + + return 0; +} + + +static int +tas3004_eq_rw( struct tas3004_data_t *self, + u_int cmd, + u_long arg) +{ + int rc; + struct tas_biquad_ctrl_t biquad; + + if (copy_from_user((void *)&biquad, (const void *)arg, sizeof(struct tas_biquad_ctrl_t))) { + return -EFAULT; + } + + if (cmd & SIOC_IN) { + rc=tas3004_write_biquad(self, biquad.channel, biquad.filter, &biquad.data); + if (rc != 0) return rc; + } + + if (cmd & SIOC_OUT) { + rc=tas3004_read_biquad(self, biquad.channel, biquad.filter, &biquad.data); + if (rc != 0) return rc; + + if (copy_to_user((void *)arg, (const void *)&biquad, sizeof(struct tas_biquad_ctrl_t))) { + return -EFAULT; + } + + } + return 0; +} + + +static int +tas3004_eq_list_rw( struct tas3004_data_t *self, + u_int cmd, + u_long arg) +{ + int rc = 0; + int filter_count; + int flags; + int i,j; + char sync_required[TAS3004_BIQUAD_CHANNEL_COUNT][TAS3004_BIQUAD_FILTER_COUNT]; + struct tas_biquad_ctrl_t biquad; + + memset(sync_required,0,sizeof(sync_required)); + + if (copy_from_user((void *)&filter_count, + (const void *)arg + offsetof(struct tas_biquad_ctrl_list_t,filter_count), + sizeof(int))) { + return -EFAULT; + } + + if (copy_from_user((void *)&flags, + (const void *)arg + offsetof(struct tas_biquad_ctrl_list_t,flags), + sizeof(int))) { + return -EFAULT; + } + + if (cmd & SIOC_IN) { + } + + for (i=0; i < filter_count; i++) { + if (copy_from_user((void *)&biquad, + (const void *)arg + offsetof(struct tas_biquad_ctrl_list_t, biquads[i]), + sizeof(struct tas_biquad_ctrl_t))) { + return -EFAULT; + } + + if (cmd & SIOC_IN) { + sync_required[biquad.channel][biquad.filter]=1; + rc=tas3004_write_biquad_shadow(self, biquad.channel, biquad.filter, &biquad.data); + if (rc != 0) return rc; + } + + if (cmd & SIOC_OUT) { + rc=tas3004_read_biquad(self, biquad.channel, biquad.filter, &biquad.data); + if (rc != 0) return rc; + + if (copy_to_user((void *)arg + offsetof(struct tas_biquad_ctrl_list_t, biquads[i]), + (const void *)&biquad, + sizeof(struct tas_biquad_ctrl_t))) { + return -EFAULT; + } + } + } + + if (cmd & SIOC_IN) { + /* + * This is OK for the tas3004. For the + * tas3001c, going into fast load mode causes + * the treble and bass to be reset to 0dB, and + * volume controls to be muted. + */ + if (flags & TAS_BIQUAD_FAST_LOAD) tas3004_fast_load(self,1); + for (i=0; isuper.shadow; + + if (flags & TAS_DRCE_ABOVE_RATIO) { + self->drce_state.above.expand = drce->above.expand; + if (drce->above.val == (1<<8)) { + self->drce_state.above.val = 1<<8; + shadow[TAS3004_REG_DRC][0] = 0x02; + + } else if (drce->above.expand) { + i=above_threshold_expansion_index(drce->above.val); + self->drce_state.above.val=above_threshold_expansion_ratio[i]; + shadow[TAS3004_REG_DRC][0] = 0x0a + (i<<3); + } else { + i=above_threshold_compression_index(drce->above.val); + self->drce_state.above.val=above_threshold_compression_ratio[i]; + shadow[TAS3004_REG_DRC][0] = 0x08 + (i<<3); + } + } + + if (flags & TAS_DRCE_BELOW_RATIO) { + self->drce_state.below.expand = drce->below.expand; + if (drce->below.val == (1<<8)) { + self->drce_state.below.val = 1<<8; + shadow[TAS3004_REG_DRC][1] = 0x02; + + } else if (drce->below.expand) { + i=below_threshold_expansion_index(drce->below.val); + self->drce_state.below.val=below_threshold_expansion_ratio[i]; + shadow[TAS3004_REG_DRC][1] = 0x08 + (i<<3); + } else { + i=below_threshold_compression_index(drce->below.val); + self->drce_state.below.val=below_threshold_compression_ratio[i]; + shadow[TAS3004_REG_DRC][1] = 0x0a + (i<<3); + } + } + + if (flags & TAS_DRCE_THRESHOLD) { + self->drce_state.threshold=quantize_db(drce->threshold); + shadow[TAS3004_REG_DRC][2] = db_to_regval(self->drce_state.threshold); + } + + if (flags & TAS_DRCE_ENERGY) { + i=time_index(drce->energy); + self->drce_state.energy=time_constants[i]; + shadow[TAS3004_REG_DRC][3] = 0x40 + (i<<4); + } + + if (flags & TAS_DRCE_ATTACK) { + i=time_index(drce->attack); + self->drce_state.attack=time_constants[i]; + shadow[TAS3004_REG_DRC][4] = 0x40 + (i<<4); + } + + if (flags & TAS_DRCE_DECAY) { + i=time_index(drce->decay); + self->drce_state.decay=time_constants[i]; + shadow[TAS3004_REG_DRC][5] = 0x40 + (i<<4); + } + + if (flags & TAS_DRCE_ENABLE) { + self->drce_state.enable = drce->enable; + } + + if (!self->drce_state.enable) { + shadow[TAS3004_REG_DRC][0] |= 0x01; + } + +#ifdef DEBUG_DRCE + printk("DRCE: set [ ENABLE:%x ABOVE:%x/%x BELOW:%x/%x THRESH:%x ENERGY:%x ATTACK:%x DECAY:%x\n", + self->drce_state.enable, + self->drce_state.above.expand,self->drce_state.above.val, + self->drce_state.below.expand,self->drce_state.below.val, + self->drce_state.threshold, + self->drce_state.energy, + self->drce_state.attack, + self->drce_state.decay); + + printk("DRCE: reg [ %02x %02x %02x %02x %02x %02x ]\n", + (unsigned char)shadow[TAS3004_REG_DRC][0], + (unsigned char)shadow[TAS3004_REG_DRC][1], + (unsigned char)shadow[TAS3004_REG_DRC][2], + (unsigned char)shadow[TAS3004_REG_DRC][3], + (unsigned char)shadow[TAS3004_REG_DRC][4], + (unsigned char)shadow[TAS3004_REG_DRC][5]); +#endif + + return tas3004_sync_register(self, TAS3004_REG_DRC); +} + + +static int +tas3004_drce_rw( struct tas3004_data_t *self, + u_int cmd, + u_long arg) +{ + int rc; + struct tas_drce_ctrl_t drce_ctrl; + + if (copy_from_user((void *)&drce_ctrl, + (const void *)arg, + sizeof(struct tas_drce_ctrl_t))) { + return -EFAULT; + } + +#ifdef DEBUG_DRCE + printk("DRCE: input [ FLAGS:%x ENABLE:%x ABOVE:%x/%x BELOW:%x/%x THRESH:%x ENERGY:%x ATTACK:%x DECAY:%x\n", + drce_ctrl.flags, + drce_ctrl.data.enable, + drce_ctrl.data.above.expand,drce_ctrl.data.above.val, + drce_ctrl.data.below.expand,drce_ctrl.data.below.val, + drce_ctrl.data.threshold, + drce_ctrl.data.energy, + drce_ctrl.data.attack, + drce_ctrl.data.decay); +#endif + + if (cmd & SIOC_IN) { + rc = tas3004_update_drce(self, drce_ctrl.flags, &drce_ctrl.data); + if (rc < 0) return rc; + } + + if (cmd & SIOC_OUT) { + if (drce_ctrl.flags & TAS_DRCE_ENABLE) + drce_ctrl.data.enable = self->drce_state.enable; + if (drce_ctrl.flags & TAS_DRCE_ABOVE_RATIO) + drce_ctrl.data.above = self->drce_state.above; + if (drce_ctrl.flags & TAS_DRCE_BELOW_RATIO) + drce_ctrl.data.below = self->drce_state.below; + if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) + drce_ctrl.data.threshold = self->drce_state.threshold; + if (drce_ctrl.flags & TAS_DRCE_ENERGY) + drce_ctrl.data.energy = self->drce_state.energy; + if (drce_ctrl.flags & TAS_DRCE_ATTACK) + drce_ctrl.data.attack = self->drce_state.attack; + if (drce_ctrl.flags & TAS_DRCE_DECAY) + drce_ctrl.data.decay = self->drce_state.decay; + + if (copy_to_user((void *)arg, + (const void *)&drce_ctrl, + sizeof(struct tas_drce_ctrl_t))) { + return -EFAULT; + } + } + + return 0; +} + + +static void +tas3004_update_device_parameters(struct tas3004_data_t *self) +{ + char data; + int i; + + if (!self) return; + + if (self->output_id == TAS_OUTPUT_HEADPHONES) { + /* turn on allPass when headphones are plugged in */ + data = 0x02; + } else { + data = 0x00; + } + + tas3004_write_register(self, TAS3004_REG_MCR2, &data, WRITE_NORMAL | FORCE_WRITE); + + for (i=0; tas3004_eq_prefs[i]; i++) { + struct tas_eq_pref_t *eq = tas3004_eq_prefs[i]; + + if (eq->device_id == self->device_id && + (eq->output_id == 0 || eq->output_id == self->output_id) && + (eq->speaker_id == 0 || eq->speaker_id == self->speaker_id)) { + + tas3004_update_drce(self, TAS_DRCE_ALL, eq->drce); + tas3004_write_biquad_list(self, eq->filter_count, TAS_BIQUAD_FAST_LOAD, eq->biquads); + + break; + } + } +} + +static void +tas3004_device_change_handler(void *self) +{ + if (!self) return; + + tas3004_update_device_parameters((struct tas3004_data_t *)self); +} + +static struct tq_struct device_change_task; + +static int +tas3004_output_device_change( struct tas3004_data_t *self, + int device_id, + int output_id, + int speaker_id) +{ + self->device_id=device_id; + self->output_id=output_id; + self->speaker_id=speaker_id; + + schedule_task(&device_change_task); + + return 0; +} + + +static int +tas3004_device_ioctl( struct tas3004_data_t *self, + u_int cmd, + u_long arg) +{ + switch (cmd) { + case TAS_READ_EQ: + case TAS_WRITE_EQ: + return tas3004_eq_rw(self, cmd, arg); + + case TAS_READ_EQ_LIST: + case TAS_WRITE_EQ_LIST: + return tas3004_eq_list_rw(self, cmd, arg); + + case TAS_READ_EQ_FILTER_COUNT: + put_user(TAS3004_BIQUAD_FILTER_COUNT, (uint *)(arg)); + return 0; + + case TAS_READ_EQ_CHANNEL_COUNT: + put_user(TAS3004_BIQUAD_CHANNEL_COUNT, (uint *)(arg)); + return 0; + + case TAS_READ_DRCE: + case TAS_WRITE_DRCE: + return tas3004_drce_rw(self, cmd, arg); + + case TAS_READ_DRCE_CAPS: + put_user(TAS_DRCE_ENABLE | + TAS_DRCE_ABOVE_RATIO | + TAS_DRCE_BELOW_RATIO | + TAS_DRCE_THRESHOLD | + TAS_DRCE_ENERGY | + TAS_DRCE_ATTACK | + TAS_DRCE_DECAY, + (uint *)(arg)); + return 0; + + case TAS_READ_DRCE_MIN: + case TAS_READ_DRCE_MAX: { + struct tas_drce_ctrl_t drce_ctrl; + const struct tas_drce_t *drce_copy; + + if (copy_from_user((void *)&drce_ctrl, + (const void *)arg, + sizeof(struct tas_drce_ctrl_t))) { + return -EFAULT; + } + + if (cmd == TAS_READ_DRCE_MIN) { + drce_copy=&tas3004_drce_min; + } else { + drce_copy=&tas3004_drce_max; + } + + if (drce_ctrl.flags & TAS_DRCE_ABOVE_RATIO) { + drce_ctrl.data.above=drce_copy->above; + } + if (drce_ctrl.flags & TAS_DRCE_BELOW_RATIO) { + drce_ctrl.data.below=drce_copy->below; + } + if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) { + drce_ctrl.data.threshold=drce_copy->threshold; + } + if (drce_ctrl.flags & TAS_DRCE_ENERGY) { + drce_ctrl.data.energy=drce_copy->energy; + } + if (drce_ctrl.flags & TAS_DRCE_ATTACK) { + drce_ctrl.data.attack=drce_copy->attack; + } + if (drce_ctrl.flags & TAS_DRCE_DECAY) { + drce_ctrl.data.decay=drce_copy->decay; + } + + if (copy_to_user((void *)arg, + (const void *)&drce_ctrl, + sizeof(struct tas_drce_ctrl_t))) { + return -EFAULT; + } + } + } + + return -EINVAL; +} + + +static int +tas3004_init_mixer(struct tas3004_data_t *self) +{ + unsigned char mcr = (1<<6)+(2<<4)+(2<<2); + + /* Make sure something answers on the i2c bus */ + if (tas3004_write_register(self, TAS3004_REG_MCR, &mcr, + WRITE_NORMAL | FORCE_WRITE) < 0) + return -1; + + tas3004_fast_load(self, 1); + + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD0); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD1); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD2); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD3); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD4); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD5); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD6); + + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD0); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD1); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD2); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD3); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD4); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD5); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD6); + + tas3004_sync_register(self, TAS3004_REG_DRC); + + tas3004_sync_register(self, TAS3004_REG_MCR2); + + tas3004_fast_load(self, 0); + + tas3004_set_mixer_level(self, SOUND_MIXER_VOLUME, VOL_DEFAULT<<8 | VOL_DEFAULT); + tas3004_set_mixer_level(self, SOUND_MIXER_PCM, INPUT_DEFAULT<<8 | INPUT_DEFAULT); + tas3004_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0); + tas3004_set_mixer_level(self, SOUND_MIXER_IMIX, 0); + + tas3004_set_mixer_level(self, SOUND_MIXER_BASS, BASS_DEFAULT); + tas3004_set_mixer_level(self, SOUND_MIXER_TREBLE, TREBLE_DEFAULT); + + return 0; +} + + +static int +tas3004_uninit_mixer(struct tas3004_data_t *self) +{ + tas3004_set_mixer_level(self, SOUND_MIXER_VOLUME, 0); + tas3004_set_mixer_level(self, SOUND_MIXER_PCM, 0); + tas3004_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0); + tas3004_set_mixer_level(self, SOUND_MIXER_IMIX, 0); + + tas3004_set_mixer_level(self, SOUND_MIXER_BASS, 0); + tas3004_set_mixer_level(self, SOUND_MIXER_TREBLE, 0); + + return 0; +} + + +static int +tas3004_init(struct i2c_client *client) +{ + char drce_init[]={ 0x69, 0x22, 0x9f, 0xb0, 0x60, 0xa0 }; + char mcr2 = 0; + + struct tas3004_data_t *self; + int i, j; + + self = kmalloc(sizeof(struct tas3004_data_t) + + TAS3004_REG_MAX * sizeof(tas_shadow_t), + GFP_KERNEL); + if (self == NULL) + return -ENOMEM; + + memset(self, + 0, + sizeof(struct tas3004_data_t) + + TAS3004_REG_MAX * sizeof(tas_shadow_t)); + + client->data = (void *)self; + + self->super.client = client; + self->super.shadow = (tas_shadow_t *)(self+1); + + self->output_id=TAS_OUTPUT_HEADPHONES; + self->device_id=0; + self->speaker_id=0; + + for (i=0; i + */ + +#ifndef _TAS3004_H_ +#define _TAS3004_H_ + +#include + +#include "tas_common.h" +#include "tas_eq_prefs.h" + +/* + * Macros that correspond to the registers that we write to + * when setting the various values. + */ + +#define TAS3004_VERSION "0.3" +#define TAS3004_DATE "20011214" + +#define I2C_DRIVERNAME_TAS3004 "TAS3004 driver V " TAS3004_VERSION +#define I2C_DRIVERID_TAS3004 (I2C_DRIVERID_TAS_BASE+1) + +extern struct tas_driver_hooks_t tas3004_hooks; +extern struct tas_gain_t tas3004_gain; +extern struct tas_eq_pref_t *tas3004_eq_prefs[]; + +enum tas3004_reg_t { + TAS3004_REG_MCR = 0x01, + TAS3004_REG_DRC = 0x02, + + TAS3004_REG_VOLUME = 0x04, + TAS3004_REG_TREBLE = 0x05, + TAS3004_REG_BASS = 0x06, + TAS3004_REG_LEFT_MIXER = 0x07, + TAS3004_REG_RIGHT_MIXER = 0x08, + + TAS3004_REG_LEFT_BIQUAD0 = 0x0a, + TAS3004_REG_LEFT_BIQUAD1 = 0x0b, + TAS3004_REG_LEFT_BIQUAD2 = 0x0c, + TAS3004_REG_LEFT_BIQUAD3 = 0x0d, + TAS3004_REG_LEFT_BIQUAD4 = 0x0e, + TAS3004_REG_LEFT_BIQUAD5 = 0x0f, + TAS3004_REG_LEFT_BIQUAD6 = 0x10, + + TAS3004_REG_RIGHT_BIQUAD0 = 0x13, + TAS3004_REG_RIGHT_BIQUAD1 = 0x14, + TAS3004_REG_RIGHT_BIQUAD2 = 0x15, + TAS3004_REG_RIGHT_BIQUAD3 = 0x16, + TAS3004_REG_RIGHT_BIQUAD4 = 0x17, + TAS3004_REG_RIGHT_BIQUAD5 = 0x18, + TAS3004_REG_RIGHT_BIQUAD6 = 0x19, + + TAS3004_REG_LEFT_LOUD_BIQUAD = 0x21, + TAS3004_REG_RIGHT_LOUD_BIQUAD = 0x22, + + TAS3004_REG_LEFT_LOUD_BIQUAD_GAIN = 0x23, + TAS3004_REG_RIGHT_LOUD_BIQUAD_GAIN = 0x24, + + TAS3004_REG_TEST = 0x29, + + TAS3004_REG_ANALOG_CTRL = 0x40, + TAS3004_REG_TEST1 = 0x41, + TAS3004_REG_TEST2 = 0x42, + TAS3004_REG_MCR2 = 0x43, + + TAS3004_REG_MAX = 0x44 +}; + +#endif /* _TAS3004_H_ */ diff -uNr linux-2.4.21/drivers/sound/dmasound/tas3004_tables.c linux-2.4.21-ben2/drivers/sound/dmasound/tas3004_tables.c --- linux-2.4.21/drivers/sound/dmasound/tas3004_tables.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/drivers/sound/dmasound/tas3004_tables.c 2003-06-27 15:41:24.000000000 +0200 @@ -0,0 +1,301 @@ +#include "tas3004.h" +#include "tas_eq_prefs.h" + +static struct tas_drce_t eqp_17_1_0_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -19.12 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_17_1_0_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0fd0d4, 0xe05e56, 0x0fd0d4, 0xe05ee1, 0x0fa234 } } }, + { channel: 0, filter: 1, data: { coeff: { 0x0910d7, 0x088e1a, 0x030651, 0x01dcb1, 0x02c892 } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0ff895, 0xe0970b, 0x0f7f00, 0xe0970b, 0x0f7795 } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0fd1c4, 0xe1ac22, 0x0ec8cf, 0xe1ac22, 0x0e9a94 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x0f7c1c, 0xe3cc03, 0x0df786, 0xe3cc03, 0x0d73a2 } } }, + { channel: 0, filter: 5, data: { coeff: { 0x11fb92, 0xf5a1a0, 0x073cd2, 0xf5a1a0, 0x093865 } } }, + { channel: 0, filter: 6, data: { coeff: { 0x0e17a9, 0x068b6c, 0x08a0e5, 0x068b6c, 0x06b88e } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0fd0d4, 0xe05e56, 0x0fd0d4, 0xe05ee1, 0x0fa234 } } }, + { channel: 1, filter: 1, data: { coeff: { 0x0910d7, 0x088e1a, 0x030651, 0x01dcb1, 0x02c892 } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0ff895, 0xe0970b, 0x0f7f00, 0xe0970b, 0x0f7795 } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0fd1c4, 0xe1ac22, 0x0ec8cf, 0xe1ac22, 0x0e9a94 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x0f7c1c, 0xe3cc03, 0x0df786, 0xe3cc03, 0x0d73a2 } } }, + { channel: 1, filter: 5, data: { coeff: { 0x11fb92, 0xf5a1a0, 0x073cd2, 0xf5a1a0, 0x093865 } } }, + { channel: 1, filter: 6, data: { coeff: { 0x0e17a9, 0x068b6c, 0x08a0e5, 0x068b6c, 0x06b88e } } } +}; + +static struct tas_eq_pref_t eqp_17_1_0 = { + sample_rate: 44100, + device_id: 0x17, + output_id: TAS_OUTPUT_INTERNAL_SPKR, + speaker_id: 0x00, + + drce: &eqp_17_1_0_drce, + + filter_count: 14, + biquads: eqp_17_1_0_biquads +}; + +/* ======================================================================== */ + +static struct tas_drce_t eqp_18_1_0_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -13.14 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_18_1_0_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0f5514, 0xe155d7, 0x0f5514, 0xe15cfa, 0x0eb14b } } }, + { channel: 0, filter: 1, data: { coeff: { 0x06ec33, 0x02abe3, 0x015eef, 0xf764d9, 0x03922d } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0ef5f2, 0xe67d1f, 0x0bcf37, 0xe67d1f, 0x0ac529 } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0db050, 0xe5be4d, 0x0d0c78, 0xe5be4d, 0x0abcc8 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x0f1298, 0xe64ec6, 0x0cc03e, 0xe64ec6, 0x0bd2d7 } } }, + { channel: 0, filter: 5, data: { coeff: { 0x0c641a, 0x06537a, 0x08d155, 0x06537a, 0x053570 } } }, + { channel: 0, filter: 6, data: { coeff: { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0f5514, 0xe155d7, 0x0f5514, 0xe15cfa, 0x0eb14b } } }, + { channel: 1, filter: 1, data: { coeff: { 0x06ec33, 0x02abe3, 0x015eef, 0xf764d9, 0x03922d } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0ef5f2, 0xe67d1f, 0x0bcf37, 0xe67d1f, 0x0ac529 } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0db050, 0xe5be4d, 0x0d0c78, 0xe5be4d, 0x0abcc8 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x0f1298, 0xe64ec6, 0x0cc03e, 0xe64ec6, 0x0bd2d7 } } }, + { channel: 1, filter: 5, data: { coeff: { 0x0c641a, 0x06537a, 0x08d155, 0x06537a, 0x053570 } } }, + { channel: 1, filter: 6, data: { coeff: { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } } +}; + +static struct tas_eq_pref_t eqp_18_1_0 = { + sample_rate: 44100, + device_id: 0x18, + output_id: TAS_OUTPUT_INTERNAL_SPKR, + speaker_id: 0x00, + + drce: &eqp_18_1_0_drce, + + filter_count: 14, + biquads: eqp_18_1_0_biquads +}; + +/* ======================================================================== */ + +static struct tas_drce_t eqp_1a_1_0_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -10.75 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_1a_1_0_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0fb8fd, 0xe08e04, 0x0fb8fd, 0xe08f40, 0x0f7336 } } }, + { channel: 0, filter: 1, data: { coeff: { 0x06371d, 0x0c6e3a, 0x06371d, 0x05bfd3, 0x031ca2 } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0fa1c0, 0xe18692, 0x0f030e, 0xe18692, 0x0ea4ce } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0fe495, 0xe17eff, 0x0f0452, 0xe17eff, 0x0ee8e7 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x100857, 0xe7e71c, 0x0e9599, 0xe7e71c, 0x0e9df1 } } }, + { channel: 0, filter: 5, data: { coeff: { 0x0fb26e, 0x06a82c, 0x0db2b4, 0x06a82c, 0x0d6522 } } }, + { channel: 0, filter: 6, data: { coeff: { 0x11419d, 0xf06cbf, 0x0a4f6e, 0xf06cbf, 0x0b910c } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0fb8fd, 0xe08e04, 0x0fb8fd, 0xe08f40, 0x0f7336 } } }, + { channel: 1, filter: 1, data: { coeff: { 0x06371d, 0x0c6e3a, 0x06371d, 0x05bfd3, 0x031ca2 } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0fa1c0, 0xe18692, 0x0f030e, 0xe18692, 0x0ea4ce } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0fe495, 0xe17eff, 0x0f0452, 0xe17eff, 0x0ee8e7 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x100857, 0xe7e71c, 0x0e9599, 0xe7e71c, 0x0e9df1 } } }, + { channel: 1, filter: 5, data: { coeff: { 0x0fb26e, 0x06a82c, 0x0db2b4, 0x06a82c, 0x0d6522 } } }, + { channel: 1, filter: 6, data: { coeff: { 0x11419d, 0xf06cbf, 0x0a4f6e, 0xf06cbf, 0x0b910c } } } +}; + +static struct tas_eq_pref_t eqp_1a_1_0 = { + sample_rate: 44100, + device_id: 0x1a, + output_id: TAS_OUTPUT_INTERNAL_SPKR, + speaker_id: 0x00, + + drce: &eqp_1a_1_0_drce, + + filter_count: 14, + biquads: eqp_1a_1_0_biquads +}; + +/* ======================================================================== */ + +static struct tas_drce_t eqp_1c_1_0_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -14.34 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_1c_1_0_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0f4f95, 0xe160d4, 0x0f4f95, 0xe1686e, 0x0ea6c5 } } }, + { channel: 0, filter: 1, data: { coeff: { 0x066b92, 0x0290d4, 0x0148a0, 0xf6853f, 0x03bfc7 } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0f57dc, 0xe51c91, 0x0dd1cb, 0xe51c91, 0x0d29a8 } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0df1cb, 0xe4fa84, 0x0d7cdc, 0xe4fa84, 0x0b6ea7 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x0eba36, 0xe6aa48, 0x0b9f52, 0xe6aa48, 0x0a5989 } } }, + { channel: 0, filter: 5, data: { coeff: { 0x0caf02, 0x05ef9d, 0x084beb, 0x05ef9d, 0x04faee } } }, + { channel: 0, filter: 6, data: { coeff: { 0x0fc686, 0xe22947, 0x0e4b5d, 0xe22947, 0x0e11e4 } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0f4f95, 0xe160d4, 0x0f4f95, 0xe1686e, 0x0ea6c5 } } }, + { channel: 1, filter: 1, data: { coeff: { 0x066b92, 0x0290d4, 0x0148a0, 0xf6853f, 0x03bfc7 } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0f57dc, 0xe51c91, 0x0dd1cb, 0xe51c91, 0x0d29a8 } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0df1cb, 0xe4fa84, 0x0d7cdc, 0xe4fa84, 0x0b6ea7 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x0eba36, 0xe6aa48, 0x0b9f52, 0xe6aa48, 0x0a5989 } } }, + { channel: 1, filter: 5, data: { coeff: { 0x0caf02, 0x05ef9d, 0x084beb, 0x05ef9d, 0x04faee } } }, + { channel: 1, filter: 6, data: { coeff: { 0x0fc686, 0xe22947, 0x0e4b5d, 0xe22947, 0x0e11e4 } } } +}; + +static struct tas_eq_pref_t eqp_1c_1_0 = { + sample_rate: 44100, + device_id: 0x1c, + output_id: TAS_OUTPUT_INTERNAL_SPKR, + speaker_id: 0x00, + + drce: &eqp_1c_1_0_drce, + + filter_count: 14, + biquads: eqp_1c_1_0_biquads +}; + +/* ======================================================================== */ + +static uint tas3004_master_tab[]={ + 0x0, 0x75, 0x9c, 0xbb, + 0xdb, 0xfb, 0x11e, 0x143, + 0x16b, 0x196, 0x1c3, 0x1f5, + 0x229, 0x263, 0x29f, 0x2e1, + 0x328, 0x373, 0x3c5, 0x41b, + 0x478, 0x4dc, 0x547, 0x5b8, + 0x633, 0x6b5, 0x740, 0x7d5, + 0x873, 0x91c, 0x9d2, 0xa92, + 0xb5e, 0xc39, 0xd22, 0xe19, + 0xf20, 0x1037, 0x1161, 0x129e, + 0x13ed, 0x1551, 0x16ca, 0x185d, + 0x1a08, 0x1bcc, 0x1dac, 0x1fa7, + 0x21c1, 0x23fa, 0x2655, 0x28d6, + 0x2b7c, 0x2e4a, 0x3141, 0x3464, + 0x37b4, 0x3b35, 0x3ee9, 0x42d3, + 0x46f6, 0x4b53, 0x4ff0, 0x54ce, + 0x59f2, 0x5f5f, 0x6519, 0x6b24, + 0x7183, 0x783c, 0x7f53, 0x86cc, + 0x8ead, 0x96fa, 0x9fba, 0xa8f2, + 0xb2a7, 0xbce1, 0xc7a5, 0xd2fa, + 0xdee8, 0xeb75, 0xf8aa, 0x1068e, + 0x1152a, 0x12487, 0x134ad, 0x145a5, + 0x1577b, 0x16a37, 0x17df5, 0x192bd, + 0x1a890, 0x1bf7b, 0x1d78d, 0x1f0d1, + 0x20b55, 0x22727, 0x24456, 0x262f2, + 0x2830b +}; + +static uint tas3004_mixer_tab[]={ + 0x0, 0x748, 0x9be, 0xbaf, + 0xda4, 0xfb1, 0x11de, 0x1431, + 0x16ad, 0x1959, 0x1c37, 0x1f4b, + 0x2298, 0x2628, 0x29fb, 0x2e12, + 0x327d, 0x3734, 0x3c47, 0x41b4, + 0x4787, 0x4dbe, 0x546d, 0x5b86, + 0x632e, 0x6b52, 0x7400, 0x7d54, + 0x873b, 0x91c6, 0x9d1a, 0xa920, + 0xb5e5, 0xc38c, 0xd21b, 0xe18f, + 0xf1f5, 0x1036a, 0x1160f, 0x129d6, + 0x13ed0, 0x1550c, 0x16ca0, 0x185c9, + 0x1a07b, 0x1bcc3, 0x1dab9, 0x1fa75, + 0x21c0f, 0x23fa3, 0x26552, 0x28d64, + 0x2b7c9, 0x2e4a2, 0x31411, 0x3463b, + 0x37b44, 0x3b353, 0x3ee94, 0x42d30, + 0x46f55, 0x4b533, 0x4fefc, 0x54ce5, + 0x59f25, 0x5f5f6, 0x65193, 0x6b23c, + 0x71835, 0x783c3, 0x7f52c, 0x86cc0, + 0x8eacc, 0x96fa5, 0x9fba0, 0xa8f1a, + 0xb2a71, 0xbce0a, 0xc7a4a, 0xd2fa0, + 0xdee7b, 0xeb752, 0xf8a9f, 0x1068e4, + 0x1152a3, 0x12486a, 0x134ac8, 0x145a55, + 0x1577ac, 0x16a370, 0x17df51, 0x192bc2, + 0x1a88f8, 0x1bf7b7, 0x1d78c9, 0x1f0d04, + 0x20b542, 0x227268, 0x244564, 0x262f26, + 0x2830af +}; + +static uint tas3004_treble_tab[]={ + 0x96, 0x95, 0x95, 0x94, + 0x93, 0x92, 0x92, 0x91, + 0x90, 0x90, 0x8f, 0x8e, + 0x8d, 0x8d, 0x8c, 0x8b, + 0x8a, 0x8a, 0x89, 0x88, + 0x88, 0x87, 0x86, 0x85, + 0x85, 0x84, 0x83, 0x83, + 0x82, 0x81, 0x80, 0x80, + 0x7f, 0x7e, 0x7e, 0x7d, + 0x7c, 0x7b, 0x7b, 0x7a, + 0x79, 0x78, 0x78, 0x77, + 0x76, 0x76, 0x75, 0x74, + 0x73, 0x73, 0x72, 0x71, + 0x71, 0x68, 0x45, 0x5b, + 0x6d, 0x6c, 0x6b, 0x6a, + 0x69, 0x68, 0x67, 0x66, + 0x65, 0x63, 0x62, 0x62, + 0x60, 0x5e, 0x5c, 0x5b, + 0x59, 0x57, 0x55, 0x53, + 0x52, 0x4f, 0x4d, 0x4a, + 0x48, 0x46, 0x43, 0x40, + 0x3d, 0x3a, 0x36, 0x33, + 0x2f, 0x2c, 0x27, 0x23, + 0x1f, 0x1a, 0x15, 0xf, + 0x8, 0x5, 0x2, 0x1, + 0x1 +}; + +static uint tas3004_bass_tab[]={ + 0x96, 0x95, 0x95, 0x94, + 0x93, 0x92, 0x92, 0x91, + 0x90, 0x90, 0x8f, 0x8e, + 0x8d, 0x8d, 0x8c, 0x8b, + 0x8a, 0x8a, 0x89, 0x88, + 0x88, 0x87, 0x86, 0x85, + 0x85, 0x84, 0x83, 0x83, + 0x82, 0x81, 0x80, 0x80, + 0x7f, 0x7e, 0x7e, 0x7d, + 0x7c, 0x7b, 0x7b, 0x7a, + 0x79, 0x78, 0x78, 0x77, + 0x76, 0x76, 0x75, 0x74, + 0x73, 0x73, 0x72, 0x71, + 0x70, 0x6f, 0x6e, 0x6d, + 0x6c, 0x6b, 0x6a, 0x6a, + 0x69, 0x67, 0x66, 0x66, + 0x65, 0x63, 0x62, 0x62, + 0x61, 0x60, 0x5e, 0x5d, + 0x5b, 0x59, 0x57, 0x55, + 0x53, 0x51, 0x4f, 0x4c, + 0x4a, 0x48, 0x46, 0x44, + 0x41, 0x3e, 0x3b, 0x38, + 0x36, 0x33, 0x2f, 0x2b, + 0x28, 0x24, 0x20, 0x1c, + 0x17, 0x12, 0xd, 0x7, + 0x1 +}; + +struct tas_gain_t tas3004_gain={ + master: tas3004_master_tab, + treble: tas3004_treble_tab, + bass: tas3004_bass_tab, + mixer: tas3004_mixer_tab +}; + +struct tas_eq_pref_t *tas3004_eq_prefs[]={ + &eqp_17_1_0, + &eqp_18_1_0, + &eqp_1a_1_0, + &eqp_1c_1_0, + NULL +}; diff -uNr linux-2.4.21/drivers/sound/dmasound/tas_common.c linux-2.4.21-ben2/drivers/sound/dmasound/tas_common.c --- linux-2.4.21/drivers/sound/dmasound/tas_common.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/drivers/sound/dmasound/tas_common.c 2003-06-27 15:41:05.000000000 +0200 @@ -0,0 +1,256 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tas_common.h" + +#define CALL0(proc) \ + do { \ + struct tas_data_t *self; \ + if (!tas_client || driver_hooks == NULL) \ + return -1; \ + self = (struct tas_data_t *)tas_client->data; \ + if (driver_hooks->proc) \ + return driver_hooks->proc(self); \ + else \ + return -EINVAL; \ + } while (0) + +#define CALL(proc,arg...) \ + do { \ + struct tas_data_t *self; \ + if (!tas_client || driver_hooks == NULL) \ + return -1; \ + self = (struct tas_data_t *)tas_client->data; \ + if (driver_hooks->proc) \ + return driver_hooks->proc(self, ## arg); \ + else \ + return -EINVAL; \ + } while (0) + + +static u8 tas_i2c_address = 0x34; +static struct i2c_client * tas_client = NULL; + +static int tas_initialized = 0; +static struct device_node* tas_node = NULL; + +static int tas_attach_adapter(struct i2c_adapter *); +static int tas_detach_client(struct i2c_client *); + +struct i2c_driver tas_driver = { + name: "", + id: 0, + flags: I2C_DF_NOTIFY, + attach_adapter: &tas_attach_adapter, + detach_client: &tas_detach_client, + command: NULL, + inc_use: NULL, + dec_use: NULL +}; + +struct tas_driver_hooks_t *driver_hooks; + +int +tas_register_driver(struct tas_driver_hooks_t *hooks) +{ + driver_hooks = hooks; + return 0; +} + +int +tas_get_mixer_level(int mixer, uint *level) +{ + CALL(get_mixer_level,mixer,level); +} + +int +tas_set_mixer_level(int mixer,uint level) +{ + CALL(set_mixer_level,mixer,level); +} + +int +tas_enter_sleep(void) +{ + CALL0(enter_sleep); +} + +int +tas_leave_sleep(void) +{ + CALL0(leave_sleep); +} + +int +tas_supported_mixers(void) +{ + CALL0(supported_mixers); +} + +int +tas_mixer_is_stereo(int mixer) +{ + CALL(mixer_is_stereo,mixer); +} + +int +tas_stereo_mixers(void) +{ + CALL0(stereo_mixers); +} + +int +tas_output_device_change(int device_id,int layout_id,int speaker_id) +{ + CALL(output_device_change,device_id,layout_id,speaker_id); +} + +int +tas_device_ioctl(u_int cmd, u_long arg) +{ + CALL(device_ioctl,cmd,arg); +} + +int +tas_post_init(void) +{ + CALL0(post_init); +} + +static int +tas_detect_client(struct i2c_adapter *adapter, int address) +{ + int rc = 0; + struct i2c_client *new_client; + struct tas_data_t *data; + const char *client_name = "tas Digital Equalizer"; + + if (driver_hooks == NULL) { + printk(KERN_ERR "tas_detect_client called with no hooks !\n"); + return -ENODEV; + } + + new_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!new_client) { + rc = -ENOMEM; + goto bail; + } + + new_client->data = NULL; + + new_client->addr = address; + new_client->data = data; + new_client->adapter = adapter; + new_client->driver = &tas_driver; + new_client->flags = 0; + + strcpy(new_client->name,client_name); + + new_client->id = 0; /* Only one instance supported */ + + if (driver_hooks->init && driver_hooks->init(new_client)) { + rc = -ENODEV; + goto bail; + } + + /* Tell the i2c layer a new client has arrived */ + if (i2c_attach_client(new_client)) { + if (driver_hooks->uninit) + driver_hooks->uninit((struct tas_data_t *)new_client->data); + rc = -ENODEV; + goto bail; + } + + tas_client = new_client; +bail: + if (rc && new_client) { + tas_client = NULL; + kfree(new_client); + } + return rc; +} + +static int +tas_attach_adapter(struct i2c_adapter *adapter) +{ + if (!strncmp(adapter->name, "mac-io", 6)) + return tas_detect_client(adapter, tas_i2c_address); + return 0; +} + +static int +tas_detach_client(struct i2c_client *client) +{ + if (client == tas_client) { + driver_hooks->uninit((struct tas_data_t *)client->data); + + i2c_detach_client(client); + kfree(client); + } + return 0; +} + +int __init +tas_cleanup(void) +{ + if (!tas_initialized) + return -ENODEV; + i2c_del_driver(&tas_driver); + tas_initialized = 0; + + return 0; +} + +int __init +tas_init(int driver_id, const char *driver_name) +{ + int rc; + u32* paddr; + + if (tas_initialized) + return 0; + + strncpy(tas_driver.name,driver_name,31); + tas_driver.name[31]=0; + tas_driver.id=driver_id; + + tas_node = find_devices("deq"); + if (tas_node == NULL) + return -ENODEV; + + printk(KERN_INFO "tas driver [%s])\n",tas_driver.name); + paddr = (u32 *)get_property(tas_node, "i2c-address", NULL); + if (paddr) { + tas_i2c_address = (*paddr) >> 1; + printk(KERN_INFO "using i2c address: 0x%x from device-tree\n", + tas_i2c_address); + } else + printk(KERN_INFO "using i2c address: 0x%x (default)\n", tas_i2c_address); + + if ((rc = i2c_add_driver(&tas_driver))) { + printk("tas: Driver registration failed, module not inserted.\n"); + tas_cleanup(); + return rc; + } + tas_initialized = 1; + return 0; +} +/* + * Local Variables: + * tab-width: 8 + * indent-tabs-mode: t + * c-basic-offset: 8 + * End: + */ diff -uNr linux-2.4.21/drivers/sound/dmasound/tas_common.h linux-2.4.21-ben2/drivers/sound/dmasound/tas_common.h --- linux-2.4.21/drivers/sound/dmasound/tas_common.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/drivers/sound/dmasound/tas_common.h 2003-06-27 15:41:19.000000000 +0200 @@ -0,0 +1,284 @@ +#ifndef _TAS_COMMON_H_ +#define _TAS_COMMON_H_ + +#include +#include +#include + +#define I2C_DRIVERID_TAS_BASE (0xFEBA) + +#define SET_4_20(shadow, offset, val) \ + do { \ + (shadow)[(offset)+0] = ((val) >> 16) & 0xff; \ + (shadow)[(offset)+1] = ((val) >> 8) & 0xff; \ + (shadow)[(offset)+2] = ((val) >> 0) & 0xff; \ + } while (0) + +#define GET_4_20(shadow, offset) \ + (((u_int)((shadow)[(offset)+0]) << 16) | \ + ((u_int)((shadow)[(offset)+1]) << 8) | \ + ((u_int)((shadow)[(offset)+2]) << 0)) + + +#define TAS_BIQUAD_FAST_LOAD 0x01 + +#define TAS_DRCE_ENABLE 0x01 +#define TAS_DRCE_ABOVE_RATIO 0x02 +#define TAS_DRCE_BELOW_RATIO 0x04 +#define TAS_DRCE_THRESHOLD 0x08 +#define TAS_DRCE_ENERGY 0x10 +#define TAS_DRCE_ATTACK 0x20 +#define TAS_DRCE_DECAY 0x40 + +#define TAS_DRCE_ALL 0x7f + + +#define TAS_OUTPUT_HEADPHONES 0x00 +#define TAS_OUTPUT_INTERNAL_SPKR 0x01 +#define TAS_OUTPUT_EXTERNAL_SPKR 0x02 + + +union tas_biquad_t { + struct { + int b0,b1,b2,a1,a2; + } coeff; + int buf[5]; +}; + +struct tas_biquad_ctrl_t { + u_int channel:4; + u_int filter:4; + + union tas_biquad_t data; +}; + +struct tas_biquad_ctrl_list_t { + int flags; + int filter_count; + struct tas_biquad_ctrl_t biquads[0]; +}; + +struct tas_ratio_t { + unsigned short val; /* 8.8 */ + unsigned short expand; /* 0 = compress, !0 = expand. */ +}; + +struct tas_drce_t { + unsigned short enable; + struct tas_ratio_t above; + struct tas_ratio_t below; + short threshold; /* dB, 8.8 signed */ + unsigned short energy; /* seconds, 4.12 unsigned */ + unsigned short attack; /* seconds, 4.12 unsigned */ + unsigned short decay; /* seconds, 4.12 unsigned */ +}; + +struct tas_drce_ctrl_t { + uint flags; + + struct tas_drce_t data; +}; + +struct tas_gain_t +{ + unsigned int *master; + unsigned int *treble; + unsigned int *bass; + unsigned int *mixer; +}; + +typedef char tas_shadow_t[16]; + +struct tas_data_t +{ + struct i2c_client *client; + tas_shadow_t *shadow; + uint mixer[SOUND_MIXER_NRDEVICES]; +}; + +typedef int (*tas_hook_init_t)(struct i2c_client *); +typedef int (*tas_hook_post_init_t)(struct tas_data_t *); +typedef void (*tas_hook_uninit_t)(struct tas_data_t *); + +typedef int (*tas_hook_get_mixer_level_t)(struct tas_data_t *,int,uint *); +typedef int (*tas_hook_set_mixer_level_t)(struct tas_data_t *,int,uint); + +typedef int (*tas_hook_enter_sleep_t)(struct tas_data_t *); +typedef int (*tas_hook_leave_sleep_t)(struct tas_data_t *); + +typedef int (*tas_hook_supported_mixers_t)(struct tas_data_t *); +typedef int (*tas_hook_mixer_is_stereo_t)(struct tas_data_t *,int); +typedef int (*tas_hook_stereo_mixers_t)(struct tas_data_t *); + +typedef int (*tas_hook_output_device_change_t)(struct tas_data_t *,int,int,int); +typedef int (*tas_hook_device_ioctl_t)(struct tas_data_t *,u_int,u_long); + +struct tas_driver_hooks_t { + /* + * All hardware initialisation must be performed in + * post_init(), as tas_dmasound_init() does a hardware reset. + * + * init() is called before tas_dmasound_init() so that + * ouput_device_change() is always called after i2c driver + * initialisation. The implication is that + * output_device_change() must cope with the fact that it + * may be called before post_init(). + */ + + tas_hook_init_t init; + tas_hook_post_init_t post_init; + tas_hook_uninit_t uninit; + + tas_hook_get_mixer_level_t get_mixer_level; + tas_hook_set_mixer_level_t set_mixer_level; + + tas_hook_enter_sleep_t enter_sleep; + tas_hook_leave_sleep_t leave_sleep; + + tas_hook_supported_mixers_t supported_mixers; + tas_hook_mixer_is_stereo_t mixer_is_stereo; + tas_hook_stereo_mixers_t stereo_mixers; + + tas_hook_output_device_change_t output_device_change; + tas_hook_device_ioctl_t device_ioctl; +}; + +enum tas_write_mode_t { + WRITE_HW = 0x01, + WRITE_SHADOW = 0x02, + WRITE_NORMAL = 0x03, + FORCE_WRITE = 0x04 +}; + +static inline uint +tas_mono_to_stereo(uint mono) +{ + mono &=0xff; + return mono | (mono<<8); +} + +/* + * Todo: make these functions a bit more efficient ! + */ +static inline int +tas_write_register( struct tas_data_t *self, + uint reg_num, + uint reg_width, + char *data, + uint write_mode) +{ + int rc; + + if (reg_width==0 || data==NULL || self==NULL) + return -EINVAL; + if (!(write_mode & FORCE_WRITE) && + !memcmp(data,self->shadow[reg_num],reg_width)) + return 0; + + if (write_mode & WRITE_SHADOW) + memcpy(self->shadow[reg_num],data,reg_width); + if (write_mode & WRITE_HW) { + rc=i2c_smbus_write_block_data(self->client, + reg_num, + reg_width, + data); + if (rc < 0) { + printk("tas: I2C block write failed \n"); + return rc; + } + } + return 0; +} + +static inline int +tas_sync_register( struct tas_data_t *self, + uint reg_num, + uint reg_width) +{ + int rc; + + if (reg_width==0 || self==NULL) + return -EINVAL; + rc=i2c_smbus_write_block_data(self->client, + reg_num, + reg_width, + self->shadow[reg_num]); + if (rc < 0) { + printk("tas: I2C block write failed \n"); + return rc; + } + return 0; +} + +static inline int +tas_write_byte_register( struct tas_data_t *self, + uint reg_num, + char data, + uint write_mode) +{ + if (self==NULL) + return -1; + if (!(write_mode & FORCE_WRITE) && data != self->shadow[reg_num][0]) + return 0; + if (write_mode & WRITE_SHADOW) + self->shadow[reg_num][0]=data; + if (write_mode & WRITE_HW) { + if (i2c_smbus_write_byte_data(self->client, reg_num, data) < 0) { + printk("tas: I2C byte write failed \n"); + return -1; + } + } + return 0; +} + +static inline int +tas_sync_byte_register( struct tas_data_t *self, + uint reg_num, + uint reg_width) +{ + if (reg_width==0 || self==NULL) + return -1; + if (i2c_smbus_write_byte_data( + self->client, reg_num, self->shadow[reg_num][0]) < 0) { + printk("tas: I2C byte write failed \n"); + return -1; + } + return 0; +} + +static inline int +tas_read_register( struct tas_data_t *self, + uint reg_num, + uint reg_width, + char *data) +{ + if (reg_width==0 || data==NULL || self==NULL) + return -1; + memcpy(data,self->shadow[reg_num],reg_width); + return 0; +} + +extern int tas_register_driver(struct tas_driver_hooks_t *hooks); + +extern int tas_get_mixer_level(int mixer,uint *level); +extern int tas_set_mixer_level(int mixer,uint level); +extern int tas_enter_sleep(void); +extern int tas_leave_sleep(void); +extern int tas_supported_mixers(void); +extern int tas_mixer_is_stereo(int mixer); +extern int tas_stereo_mixers(void); +extern int tas_output_device_change(int,int,int); +extern int tas_device_ioctl(u_int, u_long); + +extern int tas_cleanup(void); +extern int tas_init(int driver_id,const char *driver_name); +extern int tas_post_init(void); + +#endif /* _TAS_COMMON_H_ */ +/* + * Local Variables: + * tab-width: 8 + * indent-tabs-mode: t + * c-basic-offset: 8 + * End: + */ diff -uNr linux-2.4.21/drivers/sound/dmasound/tas_eq_prefs.h linux-2.4.21-ben2/drivers/sound/dmasound/tas_eq_prefs.h --- linux-2.4.21/drivers/sound/dmasound/tas_eq_prefs.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/drivers/sound/dmasound/tas_eq_prefs.h 2003-06-27 15:41:13.000000000 +0200 @@ -0,0 +1,24 @@ +#ifndef _TAS_EQ_PREFS_H_ +#define _TAS_EQ_PREFS_H_ + +struct tas_eq_pref_t { + u_int sample_rate; + u_int device_id; + u_int output_id; + u_int speaker_id; + + struct tas_drce_t *drce; + + u_int filter_count; + struct tas_biquad_ctrl_t *biquads; +}; + +#endif /* _TAS_EQ_PREFS_H_ */ + +/* + * Local Variables: + * tab-width: 8 + * indent-tabs-mode: t + * c-basic-offset: 8 + * End: + */ diff -uNr linux-2.4.21/drivers/sound/dmasound/tas_ioctl.h linux-2.4.21-ben2/drivers/sound/dmasound/tas_ioctl.h --- linux-2.4.21/drivers/sound/dmasound/tas_ioctl.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.4.21-ben2/drivers/sound/dmasound/tas_ioctl.h 2003-06-27 15:41:19.000000000 +0200 @@ -0,0 +1,24 @@ +#ifndef _TAS_IOCTL_H_ +#define _TAS_IOCTL_H_ + +#include +#include + + +#define TAS_READ_EQ _SIOR('t',0,struct tas_biquad_ctrl_t) +#define TAS_WRITE_EQ _SIOW('t',0,struct tas_biquad_ctrl_t) + +#define TAS_READ_EQ_LIST _SIOR('t',1,struct tas_biquad_ctrl_t) +#define TAS_WRITE_EQ_LIST _SIOW('t',1,struct tas_biquad_ctrl_t) + +#define TAS_READ_EQ_FILTER_COUNT _SIOR('t',2,int) +#define TAS_READ_EQ_CHANNEL_COUNT _SIOR('t',3,int) + +#define TAS_READ_DRCE _SIOR('t',4,struct tas_drce_ctrl_t) +#define TAS_WRITE_DRCE _SIOW('t',4,struct tas_drce_ctrl_t) + +#define TAS_READ_DRCE_CAPS _SIOR('t',5,int) +#define TAS_READ_DRCE_MIN _SIOR('t',6,int) +#define TAS_READ_DRCE_MAX _SIOR('t',7,int) + +#endif diff -uNr linux-2.4.21/drivers/usb/host/usb-ohci.c linux-2.4.21-ben2/drivers/usb/host/usb-ohci.c --- linux-2.4.21/drivers/usb/host/usb-ohci.c 2003-06-13 16:51:36.000000000 +0200 +++ linux-2.4.21-ben2/drivers/usb/host/usb-ohci.c 2003-06-27 15:41:21.000000000 +0200 @@ -490,12 +490,16 @@ usb_pipeout (urb->pipe) ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - urb->complete (urb); - + if (urb->interval == 0) { + urb_rm_priv (urb); + urb->complete (urb); + break; + } /* implicitly requeued */ - urb->actual_length = 0; - urb->status = -EINPROGRESS; - td_submit_urb (urb); + urb->complete (urb); + urb->actual_length = 0; + urb->status = -EINPROGRESS; + td_submit_urb (urb); break; case PIPE_ISOCHRONOUS: @@ -707,8 +711,10 @@ list_add (&urb->urb_list, entry); /* drive timeouts by SF (messy, but works) */ - writel (OHCI_INTR_SF, &ohci->regs->intrenable); - (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ + if (!ohci->sleeping) { + writel (OHCI_INTR_SF, &ohci->regs->intrenable); + (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ + } } #endif @@ -1003,6 +1009,7 @@ case PIPE_CONTROL: ed->hwNextED = 0; if (ohci->ed_controltail == NULL) { + io_barrier(); writel (ed->dma, &ohci->regs->ed_controlhead); } else { ohci->ed_controltail->hwNextED = cpu_to_le32 (ed->dma); @@ -1011,6 +1018,7 @@ if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && !ohci->ed_rm_list[1] && !ohci->sleeping) { ohci->hc_control |= OHCI_CTRL_CLE; + io_barrier(); writel (ohci->hc_control, &ohci->regs->control); } ohci->ed_controltail = edi; @@ -1019,6 +1027,7 @@ case PIPE_BULK: ed->hwNextED = 0; if (ohci->ed_bulktail == NULL) { + io_barrier(); writel (ed->dma, &ohci->regs->ed_bulkhead); } else { ohci->ed_bulktail->hwNextED = cpu_to_le32 (ed->dma); @@ -1027,6 +1036,7 @@ if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && !ohci->ed_rm_list[1] && !ohci->sleeping) { ohci->hc_control |= OHCI_CTRL_BLE; + io_barrier(); writel (ohci->hc_control, &ohci->regs->control); } ohci->ed_bulktail = edi; @@ -1119,7 +1129,8 @@ if (ed->ed_prev == NULL) { if (!ed->hwNextED) { ohci->hc_control &= ~OHCI_CTRL_CLE; - writel (ohci->hc_control, &ohci->regs->control); + if (!ohci->sleeping) + writel (ohci->hc_control, &ohci->regs->control); } writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_controlhead); } else { @@ -1136,7 +1147,8 @@ if (ed->ed_prev == NULL) { if (!ed->hwNextED) { ohci->hc_control &= ~OHCI_CTRL_BLE; - writel (ohci->hc_control, &ohci->regs->control); + if (!ohci->sleeping) + writel (ohci->hc_control, &ohci->regs->control); } writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_bulkhead); } else { @@ -1265,16 +1277,19 @@ return; ed->hwINFO |= cpu_to_le32 (OHCI_ED_SKIP); + io_barrier(); if (!ohci->disabled) { switch (ed->type) { case PIPE_CONTROL: /* stop control list */ ohci->hc_control &= ~OHCI_CTRL_CLE; - writel (ohci->hc_control, &ohci->regs->control); + if (!ohci->sleeping) + writel (ohci->hc_control, &ohci->regs->control); break; case PIPE_BULK: /* stop bulk list */ ohci->hc_control &= ~OHCI_CTRL_BLE; - writel (ohci->hc_control, &ohci->regs->control); + if (!ohci->sleeping) + writel (ohci->hc_control, &ohci->regs->control); break; } } @@ -1406,7 +1421,7 @@ } if (!ohci->sleeping) { - wmb(); + io_barrier(); writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ } @@ -1435,7 +1450,7 @@ TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1; td_fill (ohci, info, data, 0, urb, cnt++); if (!ohci->sleeping) { - wmb(); + io_barrier(); writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ (void)readl (&ohci->regs->intrdisable); /* PCI posting flush */ } @@ -1543,6 +1558,7 @@ td_list_hc = le32_to_cpup (&ohci->hcca->done_head) & 0xfffffff0; ohci->hcca->done_head = 0; + wmb(); while (td_list_hc) { td_list = dma_to_td (ohci, td_list_hc); @@ -1651,6 +1667,7 @@ /* maybe reenable control and bulk lists */ if (!ohci->disabled) { + io_barrier(); if (ctrl) /* reset control list */ writel (0, &ohci->regs->ed_controlcurrent); if (bulk) /* reset bulk list */ @@ -2311,6 +2328,10 @@ struct ohci_regs * regs = ohci->regs; int ints; + /* Sanity check */ + if (ohci->sleeping) + return; + /* avoid (slow) readl if only WDH happened */ if ((ohci->hcca->done_head != 0) && !(le32_to_cpup (&ohci->hcca->done_head) & 0x01)) { @@ -2617,6 +2638,16 @@ if (pci_enable_device(dev) < 0) return -ENODEV; +#ifdef CONFIG_PMAC_PBOOK + { + struct device_node *of_node; + + /* Re-enable USB PAD & cell clock */ + of_node = pci_device_to_OF_node (dev); + if (of_node) + pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 1); + } +#endif if (!dev->irq) { err("found OHCI device with no IRQ assigned. check BIOS settings!"); pci_disable_device (dev); @@ -2712,6 +2743,12 @@ info ("USB suspend: usb-%s", dev->slot_name); ohci->sleeping = 1; +#ifdef CONFIG_PMAC_PBOOK + if (_machine == _MACH_Pmac) + disable_irq (ohci->irq); + /* else, 2.4 assumes shared irqs -- don't disable */ +#endif + /* First stop processing */ spin_lock_irqsave (&usb_ed_lock, flags); ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE); @@ -2725,11 +2762,6 @@ if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) mdelay (1); -#ifdef CONFIG_PMAC_PBOOK - if (_machine == _MACH_Pmac) - disable_irq (ohci->irq); - /* else, 2.4 assumes shared irqs -- don't disable */ -#endif /* Enable remote wakeup */ writel (readl(&ohci->regs->intrenable) | OHCI_INTR_RD, &ohci->regs->intrenable); diff -uNr linux-2.4.21/drivers/usb/host/usb-ohci.h linux-2.4.21-ben2/drivers/usb/host/usb-ohci.h --- linux-2.4.21/drivers/usb/host/usb-ohci.h 2003-06-13 16:51:36.000000000 +0200 +++ linux-2.4.21-ben2/drivers/usb/host/usb-ohci.h 2003-06-27 15:41:19.000000000 +0200 @@ -58,7 +58,7 @@ dma_addr_t dma; __u32 unused[3]; -} __attribute((aligned(16))); +} __attribute((aligned(32))); typedef struct ed ed_t; @@ -567,7 +567,7 @@ return -ENOMEM; ohci->dev_cache = pci_pool_create ("ohci_dev", ohci->ohci_dev, sizeof (struct ohci_device), - 16 /* byte alignment */, + 32 /* byte alignment */, 0 /* no page-crossing issues */, GFP_KERNEL | OHCI_MEM_FLAGS); if (!ohci->dev_cache) diff -uNr linux-2.4.21/drivers/usb/storage/scsiglue.c linux-2.4.21-ben2/drivers/usb/storage/scsiglue.c --- linux-2.4.21/drivers/usb/storage/scsiglue.c 2003-06-13 16:51:37.000000000 +0200 +++ linux-2.4.21-ben2/drivers/usb/storage/scsiglue.c 2003-06-27 15:41:04.000000000 +0200 @@ -75,16 +75,19 @@ { struct us_data *us; char local_name[32]; - /* Note: this function gets called with io_request_lock spinlock helt! */ + spin_unlock_irq(&io_request_lock); + /* This is not nice at all, but how else are we to get the * data here? */ us = (struct us_data *)sht->proc_dir; /* set up the name of our subdirectory under /proc/scsi/ */ sprintf(local_name, "usb-storage-%d", us->host_number); - sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_ATOMIC); - if (!sht->proc_name) + sht->proc_name = kmalloc (strlen(local_name) + 1, GFP_KERNEL); + if (!sht->proc_name) { + spin_lock_irq(&io_request_lock); return 0; + } strcpy(sht->proc_name, local_name); /* we start with no /proc directory entry */ @@ -95,12 +98,14 @@ if (us->host) { us->host->hostdata[0] = (unsigned long)us; us->host_no = us->host->host_no; + spin_lock_irq(&io_request_lock); return 1; } /* odd... didn't register properly. Abort and free pointers */ kfree(sht->proc_name); sht->proc_name = NULL; + spin_lock_irq(&io_request_lock); return 0; } diff -uNr linux-2.4.21/drivers/video/Config.in linux-2.4.21-ben2/drivers/video/Config.in --- linux-2.4.21/drivers/video/Config.in 2003-06-13 16:51:37.000000000 +0200 +++ linux-2.4.21-ben2/drivers/video/Config.in 2003-06-27 15:41:04.000000000 +0200 @@ -73,7 +73,7 @@ dep_bool ' Apple "valkyrie" display support' CONFIG_FB_VALKYRIE $CONFIG_ALL_PPC bool ' Chips 65550 display support' CONFIG_FB_CT65550 bool ' IMS Twin Turbo display support' CONFIG_FB_IMSTT - bool ' S3 Trio display support' CONFIG_FB_S3TRIO + dep_bool ' S3 Trio display support' CONFIG_FB_S3TRIO $CONFIG_ALL_PPC tristate ' VGA 16-color graphics console' CONFIG_FB_VGA16 fi if [ "$CONFIG_PARISC" = "y" ]; then diff -uNr linux-2.4.21/drivers/video/aty/atyfb.h linux-2.4.21-ben2/drivers/video/aty/atyfb.h --- linux-2.4.21/drivers/video/aty/atyfb.h 2002-11-29 00:53:15.000000000 +0100 +++ linux-2.4.21-ben2/drivers/video/aty/atyfb.h 2003-06-27 15:41:23.000000000 +0200 @@ -124,6 +124,7 @@ #endif } fbcon_cmap; u8 blitter_may_be_busy; + int asleep; #ifdef __sparc__ u8 mmaped; int open; diff -uNr linux-2.4.21/drivers/video/aty/atyfb_base.c linux-2.4.21-ben2/drivers/video/aty/atyfb_base.c --- linux-2.4.21/drivers/video/aty/atyfb_base.c 2002-11-29 00:53:15.000000000 +0100 +++ linux-2.4.21-ben2/drivers/video/aty/atyfb_base.c 2003-06-27 15:41:09.000000000 +0200 @@ -748,6 +748,8 @@ info->current_par = *par; + if (info->asleep) + return; if (info->blitter_may_be_busy) wait_for_idle(info); tmp = aty_ld_8(CRTC_GEN_CNTL + 3, info); @@ -1192,6 +1194,10 @@ return -EINVAL; par->crtc.xoffset = xoffset; par->crtc.yoffset = yoffset; + + if (info->asleep) + return 0; + set_off_pitch(par, info); return 0; } @@ -1660,6 +1666,7 @@ } break; case PBOOK_SLEEP_NOW: + acquire_console_sem(); if (currcon >= 0) fb_display[currcon].dispsw = &fbcon_dummy; if (info->blitter_may_be_busy) @@ -1675,11 +1682,14 @@ /* Blank display and LCD */ atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info); + info->asleep = 1; /* Set chip to "suspend" mode */ result = aty_power_mgmt(1, info); + release_console_sem(); break; case PBOOK_WAKE: + acquire_console_sem(); /* Wakeup chip */ result = aty_power_mgmt(0, info); @@ -1690,6 +1700,7 @@ vfree(info->save_framebuffer); info->save_framebuffer = 0; } + info->asleep = 0; /* Restore display */ if (currcon >= 0) { atyfb_set_dispsw(&fb_display[currcon], @@ -1697,6 +1708,11 @@ info->current_par.accel_flags & FB_ACCELF_TEXT); } atyfbcon_blank(0, (struct fb_info *)info); + /* XXX We may want to re-call atyfb_set_par and make + * sure panning & cursor & palette are correct as we + * skipped any change to these during suspend. + */ + release_console_sem(); break; } } @@ -2720,6 +2736,9 @@ struct fb_info_aty *info = (struct fb_info_aty *)fb; u8 gen_cntl; + if (info->asleep) + return; + #ifdef CONFIG_PMAC_BACKLIGHT if ((_machine == _MACH_Pmac) && blank) set_backlight_enable(0); @@ -2792,23 +2811,25 @@ info->palette[regno].red = red; info->palette[regno].green = green; info->palette[regno].blue = blue; - i = aty_ld_8(DAC_CNTL, info) & 0xfc; - if (M64_HAS(EXTRA_BRIGHT)) - i |= 0x2; /*DAC_CNTL|0x2 turns off the extra brightness for gt*/ - aty_st_8(DAC_CNTL, i, info); - aty_st_8(DAC_MASK, 0xff, info); - scale = (M64_HAS(INTEGRATED) && info->current_par.crtc.bpp == 16) ? 3 : 0; + if (!info->asleep) { + i = aty_ld_8(DAC_CNTL, info) & 0xfc; + if (M64_HAS(EXTRA_BRIGHT)) + i |= 0x2; /*DAC_CNTL|0x2 turns off the extra brightness for gt*/ + aty_st_8(DAC_CNTL, i, info); + aty_st_8(DAC_MASK, 0xff, info); + scale = (M64_HAS(INTEGRATED) && info->current_par.crtc.bpp == 16) ? 3 : 0; #ifdef CONFIG_ATARI - out_8(&info->aty_cmap_regs->windex, regno << scale); - out_8(&info->aty_cmap_regs->lut, red); - out_8(&info->aty_cmap_regs->lut, green); - out_8(&info->aty_cmap_regs->lut, blue); + out_8(&info->aty_cmap_regs->windex, regno << scale); + out_8(&info->aty_cmap_regs->lut, red); + out_8(&info->aty_cmap_regs->lut, green); + out_8(&info->aty_cmap_regs->lut, blue); #else - writeb(regno << scale, &info->aty_cmap_regs->windex); - writeb(red, &info->aty_cmap_regs->lut); - writeb(green, &info->aty_cmap_regs->lut); - writeb(blue, &info->aty_cmap_regs->lut); + writeb(regno << scale, &info->aty_cmap_regs->windex); + writeb(red, &info->aty_cmap_regs->lut); + writeb(green, &info->aty_cmap_regs->lut); + writeb(blue, &info->aty_cmap_regs->lut); #endif + } if (regno < 16) switch (info->current_par.crtc.bpp) { #ifdef FBCON_HAS_CFB16 @@ -2859,6 +2880,9 @@ struct vc_data *conp = p->conp; u32 yres, yoffset, sy, height; + if (info->asleep) + return 0; + yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1; yoffset = fb_display[con].var.yoffset; diff -uNr linux-2.4.21/drivers/video/aty/mach64_cursor.c linux-2.4.21-ben2/drivers/video/aty/mach64_cursor.c --- linux-2.4.21/drivers/video/aty/mach64_cursor.c 2001-10-25 22:53:52.000000000 +0200 +++ linux-2.4.21-ben2/drivers/video/aty/mach64_cursor.c 2003-06-27 15:41:19.000000000 +0200 @@ -54,7 +54,7 @@ const u8 *blue = cursor_color_map; int i; - if (!c) + if (!c || fb->asleep) return; #ifdef __sparc__ @@ -81,7 +81,7 @@ u8 *ram, m, b; int x, y; - if (!c) + if (!c || fb->asleep) return; #ifdef __sparc__ @@ -118,7 +118,7 @@ u16 xoff, yoff; int x, y; - if (!c) + if (!c || fb->asleep) return; #ifdef __sparc__ @@ -297,8 +297,10 @@ c->mask[i][height-1] = (j >= 8) ? 0xff : (0xff << (8 - j)); } - aty_set_cursor_color(fb); - aty_set_cursor_shape(fb); + if (!fb->asleep) { + aty_set_cursor_color(fb); + aty_set_cursor_shape(fb); + } } return 1; } diff -uNr linux-2.4.21/drivers/video/aty128fb.c linux-2.4.21-ben2/drivers/video/aty128fb.c --- linux-2.4.21/drivers/video/aty128fb.c 2003-06-13 16:51:37.000000000 +0200 +++ linux-2.4.21-ben2/drivers/video/aty128fb.c 2003-06-27 15:41:10.000000000 +0200 @@ -55,7 +55,7 @@ #include #include -#ifdef CONFIG_PPC +#ifdef CONFIG_ALL_PPC #include #include #include