From: Marc Fiuczynski <mef@cs.princeton.edu> Date: Mon, 13 Nov 2006 15:58:54 +0000 (+0000) Subject: Initial revision X-Git-Tag: before-fedora-2_6_18-1_2239_FC5-vs2_0_2_2-rc6-merge~5 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=2bc4a4c2110abc597495800841793d38a2e6a0b1;p=linux-2.6.git Initial revision --- diff --git a/Documentation/ABI/README b/Documentation/ABI/README new file mode 100644 index 000000000..9feaf16f1 --- /dev/null +++ b/Documentation/ABI/README @@ -0,0 +1,77 @@ +This directory attempts to document the ABI between the Linux kernel and +userspace, and the relative stability of these interfaces. Due to the +everchanging nature of Linux, and the differing maturity levels, these +interfaces should be used by userspace programs in different ways. + +We have four different levels of ABI stability, as shown by the four +different subdirectories in this location. Interfaces may change levels +of stability according to the rules described below. + +The different levels of stability are: + + stable/ + This directory documents the interfaces that the developer has + defined to be stable. Userspace programs are free to use these + interfaces with no restrictions, and backward compatibility for + them will be guaranteed for at least 2 years. Most interfaces + (like syscalls) are expected to never change and always be + available. + + testing/ + This directory documents interfaces that are felt to be stable, + as the main development of this interface has been completed. + The interface can be changed to add new features, but the + current interface will not break by doing this, unless grave + errors or security problems are found in them. Userspace + programs can start to rely on these interfaces, but they must be + aware of changes that can occur before these interfaces move to + be marked stable. Programs that use these interfaces are + strongly encouraged to add their name to the description of + these interfaces, so that the kernel developers can easily + notify them if any changes occur (see the description of the + layout of the files below for details on how to do this.) + + obsolete/ + This directory documents interfaces that are still remaining in + the kernel, but are marked to be removed at some later point in + time. The description of the interface will document the reason + why it is obsolete and when it can be expected to be removed. + The file Documentation/feature-removal-schedule.txt may describe + some of these interfaces, giving a schedule for when they will + be removed. + + removed/ + This directory contains a list of the old interfaces that have + been removed from the kernel. + +Every file in these directories will contain the following information: + +What: Short description of the interface +Date: Date created +KernelVersion: Kernel version this feature first showed up in. +Contact: Primary contact for this interface (may be a mailing list) +Description: Long description of the interface and how to use it. +Users: All users of this interface who wish to be notified when + it changes. This is very important for interfaces in + the "testing" stage, so that kernel developers can work + with userspace developers to ensure that things do not + break in ways that are unacceptable. It is also + important to get feedback for these interfaces to make + sure they are working in a proper way and do not need to + be changed further. + + +How things move between levels: + +Interfaces in stable may move to obsolete, as long as the proper +notification is given. + +Interfaces may be removed from obsolete and the kernel as long as the +documented amount of time has gone by. + +Interfaces in the testing state can move to the stable state when the +developers feel they are finished. They cannot be removed from the +kernel tree without going through the obsolete state first. + +It's up to the developer to place their interfaces in the category they +wish for it to start out in. diff --git a/Documentation/ABI/obsolete/devfs b/Documentation/ABI/obsolete/devfs new file mode 100644 index 000000000..b8b87399b --- /dev/null +++ b/Documentation/ABI/obsolete/devfs @@ -0,0 +1,13 @@ +What: devfs +Date: July 2005 +Contact: Greg Kroah-Hartman <gregkh@suse.de> +Description: + devfs has been unmaintained for a number of years, has unfixable + races, contains a naming policy within the kernel that is + against the LSB, and can be replaced by using udev. + The files fs/devfs/*, include/linux/devfs_fs*.h will be removed, + along with the the assorted devfs function calls throughout the + kernel tree. + +Users: + diff --git a/Documentation/ABI/stable/syscalls b/Documentation/ABI/stable/syscalls new file mode 100644 index 000000000..c3ae3e7d6 --- /dev/null +++ b/Documentation/ABI/stable/syscalls @@ -0,0 +1,10 @@ +What: The kernel syscall interface +Description: + This interface matches much of the POSIX interface and is based + on it and other Unix based interfaces. It will only be added to + over time, and not have things removed from it. + + Note that this interface is different for every architecture + that Linux supports. Please see the architecture-specific + documentation for details on the syscall numbers that are to be + mapped to each syscall. diff --git a/Documentation/ABI/stable/sysfs-module b/Documentation/ABI/stable/sysfs-module new file mode 100644 index 000000000..75be43118 --- /dev/null +++ b/Documentation/ABI/stable/sysfs-module @@ -0,0 +1,30 @@ +What: /sys/module +Description: + The /sys/module tree consists of the following structure: + + /sys/module/MODULENAME + The name of the module that is in the kernel. This + module name will show up either if the module is built + directly into the kernel, or if it is loaded as a + dyanmic module. + + /sys/module/MODULENAME/parameters + This directory contains individual files that are each + individual parameters of the module that are able to be + changed at runtime. See the individual module + documentation as to the contents of these parameters and + what they accomplish. + + Note: The individual parameter names and values are not + considered stable, only the fact that they will be + placed in this location within sysfs. See the + individual driver documentation for details as to the + stability of the different parameters. + + /sys/module/MODULENAME/refcnt + If the module is able to be unloaded from the kernel, this file + will contain the current reference count of the module. + + Note: If the module is built into the kernel, or if the + CONFIG_MODULE_UNLOAD kernel configuration value is not enabled, + this file will not be present. diff --git a/Documentation/ABI/testing/sysfs-class b/Documentation/ABI/testing/sysfs-class new file mode 100644 index 000000000..4b0cb891e --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class @@ -0,0 +1,16 @@ +What: /sys/class/ +Date: Febuary 2006 +Contact: Greg Kroah-Hartman <gregkh@suse.de> +Description: + The /sys/class directory will consist of a group of + subdirectories describing individual classes of devices + in the kernel. The individual directories will consist + of either subdirectories, or symlinks to other + directories. + + All programs that use this directory tree must be able + to handle both subdirectories or symlinks in order to + work properly. + +Users: + udev <linux-hotplug-devel@lists.sourceforge.net> diff --git a/Documentation/ABI/testing/sysfs-devices b/Documentation/ABI/testing/sysfs-devices new file mode 100644 index 000000000..6a25671ee --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices @@ -0,0 +1,25 @@ +What: /sys/devices +Date: February 2006 +Contact: Greg Kroah-Hartman <gregkh@suse.de> +Description: + The /sys/devices tree contains a snapshot of the + internal state of the kernel device tree. Devices will + be added and removed dynamically as the machine runs, + and between different kernel versions, the layout of the + devices within this tree will change. + + Please do not rely on the format of this tree because of + this. If a program wishes to find different things in + the tree, please use the /sys/class structure and rely + on the symlinks there to point to the proper location + within the /sys/devices tree of the individual devices. + Or rely on the uevent messages to notify programs of + devices being added and removed from this tree to find + the location of those devices. + + Note that sometimes not all devices along the directory + chain will have emitted uevent messages, so userspace + programs must be able to handle such occurrences. + +Users: + udev <linux-hotplug-devel@lists.sourceforge.net> diff --git a/Documentation/DocBook/genericirq.tmpl b/Documentation/DocBook/genericirq.tmpl new file mode 100644 index 000000000..0f4a4b632 --- /dev/null +++ b/Documentation/DocBook/genericirq.tmpl @@ -0,0 +1,474 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> + +<book id="Generic-IRQ-Guide"> + <bookinfo> + <title>Linux generic IRQ handling</title> + + <authorgroup> + <author> + <firstname>Thomas</firstname> + <surname>Gleixner</surname> + <affiliation> + <address> + <email>tglx@linutronix.de</email> + </address> + </affiliation> + </author> + <author> + <firstname>Ingo</firstname> + <surname>Molnar</surname> + <affiliation> + <address> + <email>mingo@elte.hu</email> + </address> + </affiliation> + </author> + </authorgroup> + + <copyright> + <year>2005-2006</year> + <holder>Thomas Gleixner</holder> + </copyright> + <copyright> + <year>2005-2006</year> + <holder>Ingo Molnar</holder> + </copyright> + + <legalnotice> + <para> + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License version 2 as published by the Free Software Foundation. + </para> + + <para> + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + </para> + + <para> + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + </para> + + <para> + For more details see the file COPYING in the source + distribution of Linux. + </para> + </legalnotice> + </bookinfo> + +<toc></toc> + + <chapter id="intro"> + <title>Introduction</title> + <para> + The generic interrupt handling layer is designed to provide a + complete abstraction of interrupt handling for device drivers. + It is able to handle all the different types of interrupt controller + hardware. Device drivers use generic API functions to request, enable, + disable and free interrupts. The drivers do not have to know anything + about interrupt hardware details, so they can be used on different + platforms without code changes. + </para> + <para> + This documentation is provided to developers who want to implement + an interrupt subsystem based for their architecture, with the help + of the generic IRQ handling layer. + </para> + </chapter> + + <chapter id="rationale"> + <title>Rationale</title> + <para> + The original implementation of interrupt handling in Linux is using + the __do_IRQ() super-handler, which is able to deal with every + type of interrupt logic. + </para> + <para> + Originally, Russell King identified different types of handlers to + build a quite universal set for the ARM interrupt handler + implementation in Linux 2.5/2.6. He distinguished between: + <itemizedlist> + <listitem><para>Level type</para></listitem> + <listitem><para>Edge type</para></listitem> + <listitem><para>Simple type</para></listitem> + </itemizedlist> + In the SMP world of the __do_IRQ() super-handler another type + was identified: + <itemizedlist> + <listitem><para>Per CPU type</para></listitem> + </itemizedlist> + </para> + <para> + This split implementation of highlevel IRQ handlers allows us to + optimize the flow of the interrupt handling for each specific + interrupt type. This reduces complexity in that particular codepath + and allows the optimized handling of a given type. + </para> + <para> + The original general IRQ implementation used hw_interrupt_type + structures and their ->ack(), ->end() [etc.] callbacks to + differentiate the flow control in the super-handler. This leads to + a mix of flow logic and lowlevel hardware logic, and it also leads + to unnecessary code duplication: for example in i386, there is a + ioapic_level_irq and a ioapic_edge_irq irq-type which share many + of the lowlevel details but have different flow handling. + </para> + <para> + A more natural abstraction is the clean separation of the + 'irq flow' and the 'chip details'. + </para> + <para> + Analysing a couple of architecture's IRQ subsystem implementations + reveals that most of them can use a generic set of 'irq flow' + methods and only need to add the chip level specific code. + The separation is also valuable for (sub)architectures + which need specific quirks in the irq flow itself but not in the + chip-details - and thus provides a more transparent IRQ subsystem + design. + </para> + <para> + Each interrupt descriptor is assigned its own highlevel flow + handler, which is normally one of the generic + implementations. (This highlevel flow handler implementation also + makes it simple to provide demultiplexing handlers which can be + found in embedded platforms on various architectures.) + </para> + <para> + The separation makes the generic interrupt handling layer more + flexible and extensible. For example, an (sub)architecture can + use a generic irq-flow implementation for 'level type' interrupts + and add a (sub)architecture specific 'edge type' implementation. + </para> + <para> + To make the transition to the new model easier and prevent the + breakage of existing implementations, the __do_IRQ() super-handler + is still available. This leads to a kind of duality for the time + being. Over time the new model should be used in more and more + architectures, as it enables smaller and cleaner IRQ subsystems. + </para> + </chapter> + <chapter id="bugs"> + <title>Known Bugs And Assumptions</title> + <para> + None (knock on wood). + </para> + </chapter> + + <chapter id="Abstraction"> + <title>Abstraction layers</title> + <para> + There are three main levels of abstraction in the interrupt code: + <orderedlist> + <listitem><para>Highlevel driver API</para></listitem> + <listitem><para>Highlevel IRQ flow handlers</para></listitem> + <listitem><para>Chiplevel hardware encapsulation</para></listitem> + </orderedlist> + </para> + <sect1> + <title>Interrupt control flow</title> + <para> + Each interrupt is described by an interrupt descriptor structure + irq_desc. The interrupt is referenced by an 'unsigned int' numeric + value which selects the corresponding interrupt decription structure + in the descriptor structures array. + The descriptor structure contains status information and pointers + to the interrupt flow method and the interrupt chip structure + which are assigned to this interrupt. + </para> + <para> + Whenever an interrupt triggers, the lowlevel arch code calls into + the generic interrupt code by calling desc->handle_irq(). + This highlevel IRQ handling function only uses desc->chip primitives + referenced by the assigned chip descriptor structure. + </para> + </sect1> + <sect1> + <title>Highlevel Driver API</title> + <para> + The highlevel Driver API consists of following functions: + <itemizedlist> + <listitem><para>request_irq()</para></listitem> + <listitem><para>free_irq()</para></listitem> + <listitem><para>disable_irq()</para></listitem> + <listitem><para>enable_irq()</para></listitem> + <listitem><para>disable_irq_nosync() (SMP only)</para></listitem> + <listitem><para>synchronize_irq() (SMP only)</para></listitem> + <listitem><para>set_irq_type()</para></listitem> + <listitem><para>set_irq_wake()</para></listitem> + <listitem><para>set_irq_data()</para></listitem> + <listitem><para>set_irq_chip()</para></listitem> + <listitem><para>set_irq_chip_data()</para></listitem> + </itemizedlist> + See the autogenerated function documentation for details. + </para> + </sect1> + <sect1> + <title>Highlevel IRQ flow handlers</title> + <para> + The generic layer provides a set of pre-defined irq-flow methods: + <itemizedlist> + <listitem><para>handle_level_irq</para></listitem> + <listitem><para>handle_edge_irq</para></listitem> + <listitem><para>handle_simple_irq</para></listitem> + <listitem><para>handle_percpu_irq</para></listitem> + </itemizedlist> + The interrupt flow handlers (either predefined or architecture + specific) are assigned to specific interrupts by the architecture + either during bootup or during device initialization. + </para> + <sect2> + <title>Default flow implementations</title> + <sect3> + <title>Helper functions</title> + <para> + The helper functions call the chip primitives and + are used by the default flow implementations. + The following helper functions are implemented (simplified excerpt): + <programlisting> +default_enable(irq) +{ + desc->chip->unmask(irq); +} + +default_disable(irq) +{ + if (!delay_disable(irq)) + desc->chip->mask(irq); +} + +default_ack(irq) +{ + chip->ack(irq); +} + +default_mask_ack(irq) +{ + if (chip->mask_ack) { + chip->mask_ack(irq); + } else { + chip->mask(irq); + chip->ack(irq); + } +} + +noop(irq) +{ +} + + </programlisting> + </para> + </sect3> + </sect2> + <sect2> + <title>Default flow handler implementations</title> + <sect3> + <title>Default Level IRQ flow handler</title> + <para> + handle_level_irq provides a generic implementation + for level-triggered interrupts. + </para> + <para> + The following control flow is implemented (simplified excerpt): + <programlisting> +desc->chip->start(); +handle_IRQ_event(desc->action); +desc->chip->end(); + </programlisting> + </para> + </sect3> + <sect3> + <title>Default Edge IRQ flow handler</title> + <para> + handle_edge_irq provides a generic implementation + for edge-triggered interrupts. + </para> + <para> + The following control flow is implemented (simplified excerpt): + <programlisting> +if (desc->status & running) { + desc->chip->hold(); + desc->status |= pending | masked; + return; +} +desc->chip->start(); +desc->status |= running; +do { + if (desc->status & masked) + desc->chip->enable(); + desc-status &= ~pending; + handle_IRQ_event(desc->action); +} while (status & pending); +desc-status &= ~running; +desc->chip->end(); + </programlisting> + </para> + </sect3> + <sect3> + <title>Default simple IRQ flow handler</title> + <para> + handle_simple_irq provides a generic implementation + for simple interrupts. + </para> + <para> + Note: The simple flow handler does not call any + handler/chip primitives. + </para> + <para> + The following control flow is implemented (simplified excerpt): + <programlisting> +handle_IRQ_event(desc->action); + </programlisting> + </para> + </sect3> + <sect3> + <title>Default per CPU flow handler</title> + <para> + handle_percpu_irq provides a generic implementation + for per CPU interrupts. + </para> + <para> + Per CPU interrupts are only available on SMP and + the handler provides a simplified version without + locking. + </para> + <para> + The following control flow is implemented (simplified excerpt): + <programlisting> +desc->chip->start(); +handle_IRQ_event(desc->action); +desc->chip->end(); + </programlisting> + </para> + </sect3> + </sect2> + <sect2> + <title>Quirks and optimizations</title> + <para> + The generic functions are intended for 'clean' architectures and chips, + which have no platform-specific IRQ handling quirks. If an architecture + needs to implement quirks on the 'flow' level then it can do so by + overriding the highlevel irq-flow handler. + </para> + </sect2> + <sect2> + <title>Delayed interrupt disable</title> + <para> + This per interrupt selectable feature, which was introduced by Russell + King in the ARM interrupt implementation, does not mask an interrupt + at the hardware level when disable_irq() is called. The interrupt is + kept enabled and is masked in the flow handler when an interrupt event + happens. This prevents losing edge interrupts on hardware which does + not store an edge interrupt event while the interrupt is disabled at + the hardware level. When an interrupt arrives while the IRQ_DISABLED + flag is set, then the interrupt is masked at the hardware level and + the IRQ_PENDING bit is set. When the interrupt is re-enabled by + enable_irq() the pending bit is checked and if it is set, the + interrupt is resent either via hardware or by a software resend + mechanism. (It's necessary to enable CONFIG_HARDIRQS_SW_RESEND when + you want to use the delayed interrupt disable feature and your + hardware is not capable of retriggering an interrupt.) + The delayed interrupt disable can be runtime enabled, per interrupt, + by setting the IRQ_DELAYED_DISABLE flag in the irq_desc status field. + </para> + </sect2> + </sect1> + <sect1> + <title>Chiplevel hardware encapsulation</title> + <para> + The chip level hardware descriptor structure irq_chip + contains all the direct chip relevant functions, which + can be utilized by the irq flow implementations. + <itemizedlist> + <listitem><para>ack()</para></listitem> + <listitem><para>mask_ack() - Optional, recommended for performance</para></listitem> + <listitem><para>mask()</para></listitem> + <listitem><para>unmask()</para></listitem> + <listitem><para>retrigger() - Optional</para></listitem> + <listitem><para>set_type() - Optional</para></listitem> + <listitem><para>set_wake() - Optional</para></listitem> + </itemizedlist> + These primitives are strictly intended to mean what they say: ack means + ACK, masking means masking of an IRQ line, etc. It is up to the flow + handler(s) to use these basic units of lowlevel functionality. + </para> + </sect1> + </chapter> + + <chapter id="doirq"> + <title>__do_IRQ entry point</title> + <para> + The original implementation __do_IRQ() is an alternative entry + point for all types of interrupts. + </para> + <para> + This handler turned out to be not suitable for all + interrupt hardware and was therefore reimplemented with split + functionality for egde/level/simple/percpu interrupts. This is not + only a functional optimization. It also shortens code paths for + interrupts. + </para> + <para> + To make use of the split implementation, replace the call to + __do_IRQ by a call to desc->chip->handle_irq() and associate + the appropriate handler function to desc->chip->handle_irq(). + In most cases the generic handler implementations should + be sufficient. + </para> + </chapter> + + <chapter id="locking"> + <title>Locking on SMP</title> + <para> + The locking of chip registers is up to the architecture that + defines the chip primitives. There is a chip->lock field that can be used + for serialization, but the generic layer does not touch it. The per-irq + structure is protected via desc->lock, by the generic layer. + </para> + </chapter> + <chapter id="structs"> + <title>Structures</title> + <para> + This chapter contains the autogenerated documentation of the structures which are + used in the generic IRQ layer. + </para> +!Iinclude/linux/irq.h + </chapter> + + <chapter id="pubfunctions"> + <title>Public Functions Provided</title> + <para> + This chapter contains the autogenerated documentation of the kernel API functions + which are exported. + </para> +!Ekernel/irq/manage.c +!Ekernel/irq/chip.c + </chapter> + + <chapter id="intfunctions"> + <title>Internal Functions Provided</title> + <para> + This chapter contains the autogenerated documentation of the internal functions. + </para> +!Ikernel/irq/handle.c +!Ikernel/irq/chip.c + </chapter> + + <chapter id="credits"> + <title>Credits</title> + <para> + The following people have contributed to this document: + <orderedlist> + <listitem><para>Thomas Gleixner<email>tglx@linutronix.de</email></para></listitem> + <listitem><para>Ingo Molnar<email>mingo@elte.hu</email></para></listitem> + </orderedlist> + </para> + </chapter> +</book> diff --git a/Documentation/IRQ.txt b/Documentation/IRQ.txt new file mode 100644 index 000000000..1011e7175 --- /dev/null +++ b/Documentation/IRQ.txt @@ -0,0 +1,22 @@ +What is an IRQ? + +An IRQ is an interrupt request from a device. +Currently they can come in over a pin, or over a packet. +Several devices may be connected to the same pin thus +sharing an IRQ. + +An IRQ number is a kernel identifier used to talk about a hardware +interrupt source. Typically this is an index into the global irq_desc +array, but except for what linux/interrupt.h implements the details +are architecture specific. + +An IRQ number is an enumeration of the possible interrupt sources on a +machine. Typically what is enumerated is the number of input pins on +all of the interrupt controller in the system. In the case of ISA +what is enumerated are the 16 input pins on the two i8259 interrupt +controllers. + +Architectures can assign additional meaning to the IRQ numbers, and +are encouraged to in the case where there is any manual configuration +of the hardware involved. The ISA IRQs are a classic example of +assigning this kind of additional meaning. diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist new file mode 100644 index 000000000..a10bfb6ec --- /dev/null +++ b/Documentation/SubmitChecklist @@ -0,0 +1,63 @@ +Linux Kernel patch sumbittal checklist +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Here are some basic things that developers should do if they want to see their +kernel patch submissions accepted more quickly. + +These are all above and beyond the documentation that is provided in +Documentation/SubmittingPatches and elsewhere regarding submitting Linux +kernel patches. + + + +1: Builds cleanly with applicable or modified CONFIG options =y, =m, and + =n. No gcc warnings/errors, no linker warnings/errors. + +2: Passes allnoconfig, allmodconfig + +3: Builds on multiple CPU architectures by using local cross-compile tools + or something like PLM at OSDL. + +4: ppc64 is a good architecture for cross-compilation checking because it + tends to use `unsigned long' for 64-bit quantities. + +5: Matches kernel coding style(!) + +6: Any new or modified CONFIG options don't muck up the config menu. + +7: All new Kconfig options have help text. + +8: Has been carefully reviewed with respect to relevant Kconfig + combinations. This is very hard to get right with testing -- brainpower + pays off here. + +9: Check cleanly with sparse. + +10: Use 'make checkstack' and 'make namespacecheck' and fix any problems + that they find. Note: checkstack does not point out problems explicitly, + but any one function that uses more than 512 bytes on the stack is a + candidate for change. + +11: Include kernel-doc to document global kernel APIs. (Not required for + static functions, but OK there also.) Use 'make htmldocs' or 'make + mandocs' to check the kernel-doc and fix any issues. + +12: Has been tested with CONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT, + CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES, + CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_SPINLOCK_SLEEP all simultaneously + enabled. + +13: Has been build- and runtime tested with and without CONFIG_SMP and + CONFIG_PREEMPT. + +14: If the patch affects IO/Disk, etc: has been tested with and without + CONFIG_LBD. + +15: All codepaths have been exercised with all lockdep features enabled. + +16: All new /proc entries are documented under Documentation/ + +17: All new kernel boot parameters are documented in + Documentation/kernel-parameters.txt. + +18: All new module parameters are documented with MODULE_PARM_DESC() diff --git a/Documentation/accounting/delay-accounting.txt b/Documentation/accounting/delay-accounting.txt new file mode 100644 index 000000000..1443cd71d --- /dev/null +++ b/Documentation/accounting/delay-accounting.txt @@ -0,0 +1,112 @@ +Delay accounting +---------------- + +Tasks encounter delays in execution when they wait +for some kernel resource to become available e.g. a +runnable task may wait for a free CPU to run on. + +The per-task delay accounting functionality measures +the delays experienced by a task while + +a) waiting for a CPU (while being runnable) +b) completion of synchronous block I/O initiated by the task +c) swapping in pages + +and makes these statistics available to userspace through +the taskstats interface. + +Such delays provide feedback for setting a task's cpu priority, +io priority and rss limit values appropriately. Long delays for +important tasks could be a trigger for raising its corresponding priority. + +The functionality, through its use of the taskstats interface, also provides +delay statistics aggregated for all tasks (or threads) belonging to a +thread group (corresponding to a traditional Unix process). This is a commonly +needed aggregation that is more efficiently done by the kernel. + +Userspace utilities, particularly resource management applications, can also +aggregate delay statistics into arbitrary groups. To enable this, delay +statistics of a task are available both during its lifetime as well as on its +exit, ensuring continuous and complete monitoring can be done. + + +Interface +--------- + +Delay accounting uses the taskstats interface which is described +in detail in a separate document in this directory. Taskstats returns a +generic data structure to userspace corresponding to per-pid and per-tgid +statistics. The delay accounting functionality populates specific fields of +this structure. See + include/linux/taskstats.h +for a description of the fields pertaining to delay accounting. +It will generally be in the form of counters returning the cumulative +delay seen for cpu, sync block I/O, swapin etc. + +Taking the difference of two successive readings of a given +counter (say cpu_delay_total) for a task will give the delay +experienced by the task waiting for the corresponding resource +in that interval. + +When a task exits, records containing the per-task statistics +are sent to userspace without requiring a command. If it is the last exiting +task of a thread group, the per-tgid statistics are also sent. More details +are given in the taskstats interface description. + +The getdelays.c userspace utility in this directory allows simple commands to +be run and the corresponding delay statistics to be displayed. It also serves +as an example of using the taskstats interface. + +Usage +----- + +Compile the kernel with + CONFIG_TASK_DELAY_ACCT=y + CONFIG_TASKSTATS=y + +Delay accounting is enabled by default at boot up. +To disable, add + nodelayacct +to the kernel boot options. The rest of the instructions +below assume this has not been done. + +After the system has booted up, use a utility +similar to getdelays.c to access the delays +seen by a given task or a task group (tgid). +The utility also allows a given command to be +executed and the corresponding delays to be +seen. + +General format of the getdelays command + +getdelays [-t tgid] [-p pid] [-c cmd...] + + +Get delays, since system boot, for pid 10 +# ./getdelays -p 10 +(output similar to next case) + +Get sum of delays, since system boot, for all pids with tgid 5 +# ./getdelays -t 5 + + +CPU count real total virtual total delay total + 7876 92005750 100000000 24001500 +IO count delay total + 0 0 +MEM count delay total + 0 0 + +Get delays seen in executing a given simple command +# ./getdelays -c ls / + +bin data1 data3 data5 dev home media opt root srv sys usr +boot data2 data4 data6 etc lib mnt proc sbin subdomain tmp var + + +CPU count real total virtual total delay total + 6 4000250 4000000 0 +IO count delay total + 0 0 +MEM count delay total + 0 0 diff --git a/Documentation/accounting/getdelays.c b/Documentation/accounting/getdelays.c new file mode 100644 index 000000000..795ca3911 --- /dev/null +++ b/Documentation/accounting/getdelays.c @@ -0,0 +1,396 @@ +/* getdelays.c + * + * Utility to get per-pid and per-tgid delay accounting statistics + * Also illustrates usage of the taskstats interface + * + * Copyright (C) Shailabh Nagar, IBM Corp. 2005 + * Copyright (C) Balbir Singh, IBM Corp. 2006 + * Copyright (c) Jay Lan, SGI. 2006 + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <poll.h> +#include <string.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <signal.h> + +#include <linux/genetlink.h> +#include <linux/taskstats.h> + +/* + * Generic macros for dealing with netlink sockets. Might be duplicated + * elsewhere. It is recommended that commercial grade applications use + * libnl or libnetlink and use the interfaces provided by the library + */ +#define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN)) +#define GENLMSG_PAYLOAD(glh) (NLMSG_PAYLOAD(glh, 0) - GENL_HDRLEN) +#define NLA_DATA(na) ((void *)((char*)(na) + NLA_HDRLEN)) +#define NLA_PAYLOAD(len) (len - NLA_HDRLEN) + +#define err(code, fmt, arg...) do { printf(fmt, ##arg); exit(code); } while (0) +int done = 0; +int rcvbufsz=0; + + char name[100]; +int dbg=0, print_delays=0; +__u64 stime, utime; +#define PRINTF(fmt, arg...) { \ + if (dbg) { \ + printf(fmt, ##arg); \ + } \ + } + +/* Maximum size of response requested or message sent */ +#define MAX_MSG_SIZE 256 +/* Maximum number of cpus expected to be specified in a cpumask */ +#define MAX_CPUS 32 +/* Maximum length of pathname to log file */ +#define MAX_FILENAME 256 + +struct msgtemplate { + struct nlmsghdr n; + struct genlmsghdr g; + char buf[MAX_MSG_SIZE]; +}; + +char cpumask[100+6*MAX_CPUS]; + +/* + * Create a raw netlink socket and bind + */ +static int create_nl_socket(int protocol) +{ + int fd; + struct sockaddr_nl local; + + fd = socket(AF_NETLINK, SOCK_RAW, protocol); + if (fd < 0) + return -1; + + if (rcvbufsz) + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, + &rcvbufsz, sizeof(rcvbufsz)) < 0) { + printf("Unable to set socket rcv buf size to %d\n", + rcvbufsz); + return -1; + } + + memset(&local, 0, sizeof(local)); + local.nl_family = AF_NETLINK; + + if (bind(fd, (struct sockaddr *) &local, sizeof(local)) < 0) + goto error; + + return fd; +error: + close(fd); + return -1; +} + + +int send_cmd(int sd, __u16 nlmsg_type, __u32 nlmsg_pid, + __u8 genl_cmd, __u16 nla_type, + void *nla_data, int nla_len) +{ + struct nlattr *na; + struct sockaddr_nl nladdr; + int r, buflen; + char *buf; + + struct msgtemplate msg; + + msg.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN); + msg.n.nlmsg_type = nlmsg_type; + msg.n.nlmsg_flags = NLM_F_REQUEST; + msg.n.nlmsg_seq = 0; + msg.n.nlmsg_pid = nlmsg_pid; + msg.g.cmd = genl_cmd; + msg.g.version = 0x1; + na = (struct nlattr *) GENLMSG_DATA(&msg); + na->nla_type = nla_type; + na->nla_len = nla_len + 1 + NLA_HDRLEN; + memcpy(NLA_DATA(na), nla_data, nla_len); + msg.n.nlmsg_len += NLMSG_ALIGN(na->nla_len); + + buf = (char *) &msg; + buflen = msg.n.nlmsg_len ; + memset(&nladdr, 0, sizeof(nladdr)); + nladdr.nl_family = AF_NETLINK; + while ((r = sendto(sd, buf, buflen, 0, (struct sockaddr *) &nladdr, + sizeof(nladdr))) < buflen) { + if (r > 0) { + buf += r; + buflen -= r; + } else if (errno != EAGAIN) + return -1; + } + return 0; +} + + +/* + * Probe the controller in genetlink to find the family id + * for the TASKSTATS family + */ +int get_family_id(int sd) +{ + struct { + struct nlmsghdr n; + struct genlmsghdr g; + char buf[256]; + } ans; + + int id, rc; + struct nlattr *na; + int rep_len; + + strcpy(name, TASKSTATS_GENL_NAME); + rc = send_cmd(sd, GENL_ID_CTRL, getpid(), CTRL_CMD_GETFAMILY, + CTRL_ATTR_FAMILY_NAME, (void *)name, + strlen(TASKSTATS_GENL_NAME)+1); + + rep_len = recv(sd, &ans, sizeof(ans), 0); + if (ans.n.nlmsg_type == NLMSG_ERROR || + (rep_len < 0) || !NLMSG_OK((&ans.n), rep_len)) + return 0; + + na = (struct nlattr *) GENLMSG_DATA(&ans); + na = (struct nlattr *) ((char *) na + NLA_ALIGN(na->nla_len)); + if (na->nla_type == CTRL_ATTR_FAMILY_ID) { + id = *(__u16 *) NLA_DATA(na); + } + return id; +} + +void print_delayacct(struct taskstats *t) +{ + printf("\n\nCPU %15s%15s%15s%15s\n" + " %15llu%15llu%15llu%15llu\n" + "IO %15s%15s\n" + " %15llu%15llu\n" + "MEM %15s%15s\n" + " %15llu%15llu\n\n", + "count", "real total", "virtual total", "delay total", + t->cpu_count, t->cpu_run_real_total, t->cpu_run_virtual_total, + t->cpu_delay_total, + "count", "delay total", + t->blkio_count, t->blkio_delay_total, + "count", "delay total", t->swapin_count, t->swapin_delay_total); +} + +int main(int argc, char *argv[]) +{ + int c, rc, rep_len, aggr_len, len2, cmd_type; + __u16 id; + __u32 mypid; + + struct nlattr *na; + int nl_sd = -1; + int len = 0; + pid_t tid = 0; + pid_t rtid = 0; + + int fd = 0; + int count = 0; + int write_file = 0; + int maskset = 0; + char logfile[128]; + int loop = 0; + + struct msgtemplate msg; + + while (1) { + c = getopt(argc, argv, "dw:r:m:t:p:v:l"); + if (c < 0) + break; + + switch (c) { + case 'd': + printf("print delayacct stats ON\n"); + print_delays = 1; + break; + case 'w': + strncpy(logfile, optarg, MAX_FILENAME); + printf("write to file %s\n", logfile); + write_file = 1; + break; + case 'r': + rcvbufsz = atoi(optarg); + printf("receive buf size %d\n", rcvbufsz); + if (rcvbufsz < 0) + err(1, "Invalid rcv buf size\n"); + break; + case 'm': + strncpy(cpumask, optarg, sizeof(cpumask)); + maskset = 1; + printf("cpumask %s maskset %d\n", cpumask, maskset); + break; + case 't': + tid = atoi(optarg); + if (!tid) + err(1, "Invalid tgid\n"); + cmd_type = TASKSTATS_CMD_ATTR_TGID; + print_delays = 1; + break; + case 'p': + tid = atoi(optarg); + if (!tid) + err(1, "Invalid pid\n"); + cmd_type = TASKSTATS_CMD_ATTR_PID; + print_delays = 1; + break; + case 'v': + printf("debug on\n"); + dbg = 1; + break; + case 'l': + printf("listen forever\n"); + loop = 1; + break; + default: + printf("Unknown option %d\n", c); + exit(-1); + } + } + + if (write_file) { + fd = open(logfile, O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (fd == -1) { + perror("Cannot open output file\n"); + exit(1); + } + } + + if ((nl_sd = create_nl_socket(NETLINK_GENERIC)) < 0) + err(1, "error creating Netlink socket\n"); + + + mypid = getpid(); + id = get_family_id(nl_sd); + if (!id) { + printf("Error getting family id, errno %d", errno); + goto err; + } + PRINTF("family id %d\n", id); + + if (maskset) { + rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET, + TASKSTATS_CMD_ATTR_REGISTER_CPUMASK, + &cpumask, sizeof(cpumask)); + PRINTF("Sent register cpumask, retval %d\n", rc); + if (rc < 0) { + printf("error sending register cpumask\n"); + goto err; + } + } + + if (tid) { + rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET, + cmd_type, &tid, sizeof(__u32)); + PRINTF("Sent pid/tgid, retval %d\n", rc); + if (rc < 0) { + printf("error sending tid/tgid cmd\n"); + goto done; + } + } + + do { + int i; + + rep_len = recv(nl_sd, &msg, sizeof(msg), 0); + PRINTF("received %d bytes\n", rep_len); + + if (rep_len < 0) { + printf("nonfatal reply error: errno %d\n", errno); + continue; + } + if (msg.n.nlmsg_type == NLMSG_ERROR || + !NLMSG_OK((&msg.n), rep_len)) { + printf("fatal reply error, errno %d\n", errno); + goto done; + } + + PRINTF("nlmsghdr size=%d, nlmsg_len=%d, rep_len=%d\n", + sizeof(struct nlmsghdr), msg.n.nlmsg_len, rep_len); + + + rep_len = GENLMSG_PAYLOAD(&msg.n); + + na = (struct nlattr *) GENLMSG_DATA(&msg); + len = 0; + i = 0; + while (len < rep_len) { + len += NLA_ALIGN(na->nla_len); + switch (na->nla_type) { + case TASKSTATS_TYPE_AGGR_TGID: + /* Fall through */ + case TASKSTATS_TYPE_AGGR_PID: + aggr_len = NLA_PAYLOAD(na->nla_len); + len2 = 0; + /* For nested attributes, na follows */ + na = (struct nlattr *) NLA_DATA(na); + done = 0; + while (len2 < aggr_len) { + switch (na->nla_type) { + case TASKSTATS_TYPE_PID: + rtid = *(int *) NLA_DATA(na); + if (print_delays) + printf("PID\t%d\n", rtid); + break; + case TASKSTATS_TYPE_TGID: + rtid = *(int *) NLA_DATA(na); + if (print_delays) + printf("TGID\t%d\n", rtid); + break; + case TASKSTATS_TYPE_STATS: + count++; + if (print_delays) + print_delayacct((struct taskstats *) NLA_DATA(na)); + if (fd) { + if (write(fd, NLA_DATA(na), na->nla_len) < 0) { + err(1,"write error\n"); + } + } + if (!loop) + goto done; + break; + default: + printf("Unknown nested nla_type %d\n", na->nla_type); + break; + } + len2 += NLA_ALIGN(na->nla_len); + na = (struct nlattr *) ((char *) na + len2); + } + break; + + default: + printf("Unknown nla_type %d\n", na->nla_type); + break; + } + na = (struct nlattr *) (GENLMSG_DATA(&msg) + len); + } + } while (loop); +done: + if (maskset) { + rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET, + TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK, + &cpumask, sizeof(cpumask)); + printf("Sent deregister mask, retval %d\n", rc); + if (rc < 0) + err(rc, "error sending deregister cpumask\n"); + } +err: + close(nl_sd); + if (fd) + close(fd); + return 0; +} diff --git a/Documentation/accounting/taskstats.txt b/Documentation/accounting/taskstats.txt new file mode 100644 index 000000000..92ebf29e9 --- /dev/null +++ b/Documentation/accounting/taskstats.txt @@ -0,0 +1,181 @@ +Per-task statistics interface +----------------------------- + + +Taskstats is a netlink-based interface for sending per-task and +per-process statistics from the kernel to userspace. + +Taskstats was designed for the following benefits: + +- efficiently provide statistics during lifetime of a task and on its exit +- unified interface for multiple accounting subsystems +- extensibility for use by future accounting patches + +Terminology +----------- + +"pid", "tid" and "task" are used interchangeably and refer to the standard +Linux task defined by struct task_struct. per-pid stats are the same as +per-task stats. + +"tgid", "process" and "thread group" are used interchangeably and refer to the +tasks that share an mm_struct i.e. the traditional Unix process. Despite the +use of tgid, there is no special treatment for the task that is thread group +leader - a process is deemed alive as long as it has any task belonging to it. + +Usage +----- + +To get statistics during a task's lifetime, userspace opens a unicast netlink +socket (NETLINK_GENERIC family) and sends commands specifying a pid or a tgid. +The response contains statistics for a task (if pid is specified) or the sum of +statistics for all tasks of the process (if tgid is specified). + +To obtain statistics for tasks which are exiting, the userspace listener +sends a register command and specifies a cpumask. Whenever a task exits on +one of the cpus in the cpumask, its per-pid statistics are sent to the +registered listener. Using cpumasks allows the data received by one listener +to be limited and assists in flow control over the netlink interface and is +explained in more detail below. + +If the exiting task is the last thread exiting its thread group, +an additional record containing the per-tgid stats is also sent to userspace. +The latter contains the sum of per-pid stats for all threads in the thread +group, both past and present. + +getdelays.c is a simple utility demonstrating usage of the taskstats interface +for reporting delay accounting statistics. Users can register cpumasks, +send commands and process responses, listen for per-tid/tgid exit data, +write the data received to a file and do basic flow control by increasing +receive buffer sizes. + +Interface +--------- + +The user-kernel interface is encapsulated in include/linux/taskstats.h + +To avoid this documentation becoming obsolete as the interface evolves, only +an outline of the current version is given. taskstats.h always overrides the +description here. + +struct taskstats is the common accounting structure for both per-pid and +per-tgid data. It is versioned and can be extended by each accounting subsystem +that is added to the kernel. The fields and their semantics are defined in the +taskstats.h file. + +The data exchanged between user and kernel space is a netlink message belonging +to the NETLINK_GENERIC family and using the netlink attributes interface. +The messages are in the format + + +----------+- - -+-------------+-------------------+ + | nlmsghdr | Pad | genlmsghdr | taskstats payload | + +----------+- - -+-------------+-------------------+ + + +The taskstats payload is one of the following three kinds: + +1. Commands: Sent from user to kernel. Commands to get data on +a pid/tgid consist of one attribute, of type TASKSTATS_CMD_ATTR_PID/TGID, +containing a u32 pid or tgid in the attribute payload. The pid/tgid denotes +the task/process for which userspace wants statistics. + +Commands to register/deregister interest in exit data from a set of cpus +consist of one attribute, of type +TASKSTATS_CMD_ATTR_REGISTER/DEREGISTER_CPUMASK and contain a cpumask in the +attribute payload. The cpumask is specified as an ascii string of +comma-separated cpu ranges e.g. to listen to exit data from cpus 1,2,3,5,7,8 +the cpumask would be "1-3,5,7-8". If userspace forgets to deregister interest +in cpus before closing the listening socket, the kernel cleans up its interest +set over time. However, for the sake of efficiency, an explicit deregistration +is advisable. + +2. Response for a command: sent from the kernel in response to a userspace +command. The payload is a series of three attributes of type: + +a) TASKSTATS_TYPE_AGGR_PID/TGID : attribute containing no payload but indicates +a pid/tgid will be followed by some stats. + +b) TASKSTATS_TYPE_PID/TGID: attribute whose payload is the pid/tgid whose stats +is being returned. + +c) TASKSTATS_TYPE_STATS: attribute with a struct taskstsats as payload. The +same structure is used for both per-pid and per-tgid stats. + +3. New message sent by kernel whenever a task exits. The payload consists of a + series of attributes of the following type: + +a) TASKSTATS_TYPE_AGGR_PID: indicates next two attributes will be pid+stats +b) TASKSTATS_TYPE_PID: contains exiting task's pid +c) TASKSTATS_TYPE_STATS: contains the exiting task's per-pid stats +d) TASKSTATS_TYPE_AGGR_TGID: indicates next two attributes will be tgid+stats +e) TASKSTATS_TYPE_TGID: contains tgid of process to which task belongs +f) TASKSTATS_TYPE_STATS: contains the per-tgid stats for exiting task's process + + +per-tgid stats +-------------- + +Taskstats provides per-process stats, in addition to per-task stats, since +resource management is often done at a process granularity and aggregating task +stats in userspace alone is inefficient and potentially inaccurate (due to lack +of atomicity). + +However, maintaining per-process, in addition to per-task stats, within the +kernel has space and time overheads. To address this, the taskstats code +accumalates each exiting task's statistics into a process-wide data structure. +When the last task of a process exits, the process level data accumalated also +gets sent to userspace (along with the per-task data). + +When a user queries to get per-tgid data, the sum of all other live threads in +the group is added up and added to the accumalated total for previously exited +threads of the same thread group. + +Extending taskstats +------------------- + +There are two ways to extend the taskstats interface to export more +per-task/process stats as patches to collect them get added to the kernel +in future: + +1. Adding more fields to the end of the existing struct taskstats. Backward + compatibility is ensured by the version number within the + structure. Userspace will use only the fields of the struct that correspond + to the version its using. + +2. Defining separate statistic structs and using the netlink attributes + interface to return them. Since userspace processes each netlink attribute + independently, it can always ignore attributes whose type it does not + understand (because it is using an older version of the interface). + + +Choosing between 1. and 2. is a matter of trading off flexibility and +overhead. If only a few fields need to be added, then 1. is the preferable +path since the kernel and userspace don't need to incur the overhead of +processing new netlink attributes. But if the new fields expand the existing +struct too much, requiring disparate userspace accounting utilities to +unnecessarily receive large structures whose fields are of no interest, then +extending the attributes structure would be worthwhile. + +Flow control for taskstats +-------------------------- + +When the rate of task exits becomes large, a listener may not be able to keep +up with the kernel's rate of sending per-tid/tgid exit data leading to data +loss. This possibility gets compounded when the taskstats structure gets +extended and the number of cpus grows large. + +To avoid losing statistics, userspace should do one or more of the following: + +- increase the receive buffer sizes for the netlink sockets opened by +listeners to receive exit data. + +- create more listeners and reduce the number of cpus being listened to by +each listener. In the extreme case, there could be one listener for each cpu. +Users may also consider setting the cpu affinity of the listener to the subset +of cpus to which it listens, especially if they are listening to just one cpu. + +Despite these measures, if the userspace receives ENOBUFS error messages +indicated overflow of receive buffers, it should take measures to handle the +loss of data. + +---- diff --git a/Documentation/arm/Samsung-S3C24XX/S3C2412.txt b/Documentation/arm/Samsung-S3C24XX/S3C2412.txt new file mode 100644 index 000000000..cb82a7fc7 --- /dev/null +++ b/Documentation/arm/Samsung-S3C24XX/S3C2412.txt @@ -0,0 +1,120 @@ + S3C2412 ARM Linux Overview + ========================== + +Introduction +------------ + + The S3C2412 is part of the S3C24XX range of ARM9 System-on-Chip CPUs + from Samsung. This part has an ARM926-EJS core, capable of running up + to 266MHz (see data-sheet for more information) + + +Clock +----- + + The core clock code provides a set of clocks to the drivers, and allows + for source selection and a number of other features. + + +Power +----- + + No support for suspend/resume to RAM in the current system. + + +DMA +--- + + No current support for DMA. + + +GPIO +---- + + There is support for setting the GPIO to input/output/special function + and reading or writing to them. + + +UART +---- + + The UART hardware is similar to the S3C2440, and is supported by the + s3c2410 driver in the drivers/serial directory. + + +NAND +---- + + The NAND hardware is similar to the S3C2440, and is supported by the + s3c2410 driver in the drivers/mtd/nand directory. + + +USB Host +-------- + + The USB hardware is similar to the S3C2410, with extended clock source + control. The OHCI portion is supported by the ohci-s3c2410 driver, and + the clock control selection is supported by the core clock code. + + +USB Device +---------- + + No current support in the kernel + + +IRQs +---- + + All the standard, and external interrupt sources are supported. The + extra sub-sources are not yet supported. + + +RTC +--- + + The RTC hardware is similar to the S3C2410, and is supported by the + s3c2410-rtc driver. + + +Watchdog +-------- + + The watchdog harware is the same as the S3C2410, and is supported by + the s3c2410_wdt driver. + + +MMC/SD/SDIO +----------- + + No current support for the MMC/SD/SDIO block. + +IIC +--- + + The IIC hardware is the same as the S3C2410, and is supported by the + i2c-s3c24xx driver. + + +IIS +--- + + No current support for the IIS interface. + + +SPI +--- + + No current support for the SPI interfaces. + + +ATA +--- + + No current support for the on-board ATA block. + + +Document Author +--------------- + +Ben Dooks, (c) 2006 Simtec Electronics diff --git a/Documentation/arm/Samsung-S3C24XX/S3C2413.txt b/Documentation/arm/Samsung-S3C24XX/S3C2413.txt new file mode 100644 index 000000000..ab2a88858 --- /dev/null +++ b/Documentation/arm/Samsung-S3C24XX/S3C2413.txt @@ -0,0 +1,21 @@ + S3C2413 ARM Linux Overview + ========================== + +Introduction +------------ + + The S3C2413 is an extended version of the S3C2412, with an camera + interface and mobile DDR memory support. See the S3C2412 support + documentation for more information. + + +Camera Interface +--------------- + + This block is currently not supported. + + +Document Author +--------------- + +Ben Dooks, (c) 2006 Simtec Electronics diff --git a/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen b/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen new file mode 100644 index 000000000..1e6a23fdf --- /dev/null +++ b/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen @@ -0,0 +1,61 @@ +README on the ADC/Touchscreen Controller +======================================== + +The LH79524 and LH7A404 include a built-in Analog to Digital +controller (ADC) that is used to process input from a touchscreen. +The driver only implements a four-wire touch panel protocol. + +The touchscreen driver is maintenance free except for the pen-down or +touch threshold. Some resistive displays and board combinations may +require tuning of this threshold. The driver exposes some of it's +internal state in the sys filesystem. If the kernel is configured +with it, CONFIG_SYSFS, and sysfs is mounted at /sys, there will be a +directory + + /sys/devices/platform/adc-lh7.0 + +containing these files. + + -r--r--r-- 1 root root 4096 Jan 1 00:00 samples + -rw-r--r-- 1 root root 4096 Jan 1 00:00 threshold + -r--r--r-- 1 root root 4096 Jan 1 00:00 threshold_range + +The threshold is the current touch threshold. It defaults to 750 on +most targets. + + # cat threshold + 750 + +The threshold_range contains the range of valid values for the +threshold. Values outside of this range will be silently ignored. + + # cat threshold_range + 0 1023 + +To change the threshold, write a value to the threshold file. + + # echo 500 > threshold + # cat threshold + 500 + +The samples file contains the most recently sampled values from the +ADC. There are 12. Below are typical of the last sampled values when +the pen has been released. The first two and last two samples are for +detecting whether or not the pen is down. The third through sixth are +X coordinate samples. The seventh through tenth are Y coordinate +samples. + + # cat samples + 1023 1023 0 0 0 0 530 529 530 529 1023 1023 + +To determine a reasonable threshold, press on the touch panel with an +appropriate stylus and read the values from samples. + + # cat samples + 1023 676 92 103 101 102 855 919 922 922 1023 679 + +The first and eleventh samples are discarded. Thus, the important +values are the second and twelfth which are used to determine if the +pen is down. When both are below the threshold, the driver registers +that the pen is down. When either is above the threshold, it +registers then pen is up. diff --git a/Documentation/arm/Sharp-LH/LCDPanels b/Documentation/arm/Sharp-LH/LCDPanels new file mode 100644 index 000000000..fb1b21c2f --- /dev/null +++ b/Documentation/arm/Sharp-LH/LCDPanels @@ -0,0 +1,59 @@ +README on the LCD Panels +======================== + +Configuration options for several LCD panels, available from Logic PD, +are included in the kernel source. This README will help you +understand the configuration data and give you some guidance for +adding support for other panels if you wish. + + +lcd-panels.h +------------ + +There is no way, at present, to detect which panel is attached to the +system at runtime. Thus the kernel configuration is static. The file +arch/arm/mach-ld7a40x/lcd-panels.h (or similar) defines all of the +panel specific parameters. + +It should be possible for this data to be shared among several device +families. The current layout may be insufficiently general, but it is +amenable to improvement. + + +PIXEL_CLOCK +----------- + +The panel data sheets will give a range of acceptable pixel clocks. +The fundamental LCDCLK input frequency is divided down by a PCD +constant in field '.tim2'. It may happen that it is impossible to set +the pixel clock within this range. A clock which is too slow will +tend to flicker. For the highest quality image, set the clock as high +as possible. + + +MARGINS +------- + +These values may be difficult to glean from the panel data sheet. In +the case of the Sharp panels, the upper margin is explicitly called +out as a specific number of lines from the top of the frame. The +other values may not matter as much as the panels tend to +automatically center the image. + + +Sync Sense +---------- + +The sense of the hsync and vsync pulses may be called out in the data +sheet. On one panel, the sense of these pulses determine the height +of the visible region on the panel. Most of the Sharp panels use +negative sense sync pulses set by the TIM2_IHS and TIM2_IVS bits in +'.tim2'. + + +Pel Layout +---------- + +The Sharp color TFT panels are all configured for 16 bit direct color +modes. The amba-lcd driver sets the pel mode to 565 for 5 bits of +each red and blue and 6 bits of green. diff --git a/Documentation/connector/ucon.c b/Documentation/connector/ucon.c new file mode 100644 index 000000000..d738cde2a --- /dev/null +++ b/Documentation/connector/ucon.c @@ -0,0 +1,206 @@ +/* + * ucon.c + * + * Copyright (c) 2004+ Evgeniy Polyakov <johnpol@2ka.mipt.ru> + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <asm/types.h> + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/poll.h> + +#include <linux/netlink.h> +#include <linux/rtnetlink.h> + +#include <arpa/inet.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <time.h> + +#include <linux/connector.h> + +#define DEBUG +#define NETLINK_CONNECTOR 11 + +#ifdef DEBUG +#define ulog(f, a...) fprintf(stdout, f, ##a) +#else +#define ulog(f, a...) do {} while (0) +#endif + +static int need_exit; +static __u32 seq; + +static int netlink_send(int s, struct cn_msg *msg) +{ + struct nlmsghdr *nlh; + unsigned int size; + int err; + char buf[128]; + struct cn_msg *m; + + size = NLMSG_SPACE(sizeof(struct cn_msg) + msg->len); + + nlh = (struct nlmsghdr *)buf; + nlh->nlmsg_seq = seq++; + nlh->nlmsg_pid = getpid(); + nlh->nlmsg_type = NLMSG_DONE; + nlh->nlmsg_len = NLMSG_LENGTH(size - sizeof(*nlh)); + nlh->nlmsg_flags = 0; + + m = NLMSG_DATA(nlh); +#if 0 + ulog("%s: [%08x.%08x] len=%u, seq=%u, ack=%u.\n", + __func__, msg->id.idx, msg->id.val, msg->len, msg->seq, msg->ack); +#endif + memcpy(m, msg, sizeof(*m) + msg->len); + + err = send(s, nlh, size, 0); + if (err == -1) + ulog("Failed to send: %s [%d].\n", + strerror(errno), errno); + + return err; +} + +int main(int argc, char *argv[]) +{ + int s; + char buf[1024]; + int len; + struct nlmsghdr *reply; + struct sockaddr_nl l_local; + struct cn_msg *data; + FILE *out; + time_t tm; + struct pollfd pfd; + + if (argc < 2) + out = stdout; + else { + out = fopen(argv[1], "a+"); + if (!out) { + ulog("Unable to open %s for writing: %s\n", + argv[1], strerror(errno)); + out = stdout; + } + } + + memset(buf, 0, sizeof(buf)); + + s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); + if (s == -1) { + perror("socket"); + return -1; + } + + l_local.nl_family = AF_NETLINK; + l_local.nl_groups = 0x123; /* bitmask of requested groups */ + l_local.nl_pid = 0; + + if (bind(s, (struct sockaddr *)&l_local, sizeof(struct sockaddr_nl)) == -1) { + perror("bind"); + close(s); + return -1; + } + +#if 0 + { + int on = 0x57; /* Additional group number */ + setsockopt(s, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &on, sizeof(on)); + } +#endif + if (0) { + int i, j; + + memset(buf, 0, sizeof(buf)); + + data = (struct cn_msg *)buf; + + data->id.idx = 0x123; + data->id.val = 0x456; + data->seq = seq++; + data->ack = 0; + data->len = 0; + + for (j=0; j<10; ++j) { + for (i=0; i<1000; ++i) { + len = netlink_send(s, data); + } + + ulog("%d messages have been sent to %08x.%08x.\n", i, data->id.idx, data->id.val); + } + + return 0; + } + + + pfd.fd = s; + + while (!need_exit) { + pfd.events = POLLIN; + pfd.revents = 0; + switch (poll(&pfd, 1, -1)) { + case 0: + need_exit = 1; + break; + case -1: + if (errno != EINTR) { + need_exit = 1; + break; + } + continue; + } + if (need_exit) + break; + + memset(buf, 0, sizeof(buf)); + len = recv(s, buf, sizeof(buf), 0); + if (len == -1) { + perror("recv buf"); + close(s); + return -1; + } + reply = (struct nlmsghdr *)buf; + + switch (reply->nlmsg_type) { + case NLMSG_ERROR: + fprintf(out, "Error message received.\n"); + fflush(out); + break; + case NLMSG_DONE: + data = (struct cn_msg *)NLMSG_DATA(reply); + + time(&tm); + fprintf(out, "%.24s : [%x.%x] [%08u.%08u].\n", + ctime(&tm), data->id.idx, data->id.val, data->seq, data->ack); + fflush(out); + break; + default: + break; + } + } + + close(s); + return 0; +} diff --git a/Documentation/console/console.txt b/Documentation/console/console.txt new file mode 100644 index 000000000..d3e174473 --- /dev/null +++ b/Documentation/console/console.txt @@ -0,0 +1,144 @@ +Console Drivers +=============== + +The linux kernel has 2 general types of console drivers. The first type is +assigned by the kernel to all the virtual consoles during the boot process. +This type will be called 'system driver', and only one system driver is allowed +to exist. The system driver is persistent and it can never be unloaded, though +it may become inactive. + +The second type has to be explicitly loaded and unloaded. This will be called +'modular driver' by this document. Multiple modular drivers can coexist at +any time with each driver sharing the console with other drivers including +the system driver. However, modular drivers cannot take over the console +that is currently occupied by another modular driver. (Exception: Drivers that +call take_over_console() will succeed in the takeover regardless of the type +of driver occupying the consoles.) They can only take over the console that is +occupied by the system driver. In the same token, if the modular driver is +released by the console, the system driver will take over. + +Modular drivers, from the programmer's point of view, has to call: + + take_over_console() - load and bind driver to console layer + give_up_console() - unbind and unload driver + +In newer kernels, the following are also available: + + register_con_driver() + unregister_con_driver() + +If sysfs is enabled, the contents of /sys/class/vtconsole can be +examined. This shows the console backends currently registered by the +system which are named vtcon<n> where <n> is an integer fro 0 to 15. Thus: + + ls /sys/class/vtconsole + . .. vtcon0 vtcon1 + +Each directory in /sys/class/vtconsole has 3 files: + + ls /sys/class/vtconsole/vtcon0 + . .. bind name uevent + +What do these files signify? + + 1. bind - this is a read/write file. It shows the status of the driver if + read, or acts to bind or unbind the driver to the virtual consoles + when written to. The possible values are: + + 0 - means the driver is not bound and if echo'ed, commands the driver + to unbind + + 1 - means the driver is bound and if echo'ed, commands the driver to + bind + + 2. name - read-only file. Shows the name of the driver in this format: + + cat /sys/class/vtconsole/vtcon0/name + (S) VGA+ + + '(S)' stands for a (S)ystem driver, ie, it cannot be directly + commanded to bind or unbind + + 'VGA+' is the name of the driver + + cat /sys/class/vtconsole/vtcon1/name + (M) frame buffer device + + In this case, '(M)' stands for a (M)odular driver, one that can be + directly commanded to bind or unbind. + + 3. uevent - ignore this file + +When unbinding, the modular driver is detached first, and then the system +driver takes over the consoles vacated by the driver. Binding, on the other +hand, will bind the driver to the consoles that are currently occupied by a +system driver. + +NOTE1: Binding and binding must be selected in Kconfig. It's under: + +Device Drivers -> Character devices -> Support for binding and unbinding +console drivers + +NOTE2: If any of the virtual consoles are in KD_GRAPHICS mode, then binding or +unbinding will not succeed. An example of an application that sets the console +to KD_GRAPHICS is X. + +How useful is this feature? This is very useful for console driver +developers. By unbinding the driver from the console layer, one can unload the +driver, make changes, recompile, reload and rebind the driver without any need +for rebooting the kernel. For regular users who may want to switch from +framebuffer console to VGA console and vice versa, this feature also makes +this possible. (NOTE NOTE NOTE: Please read fbcon.txt under Documentation/fb +for more details). + +Notes for developers: +===================== + +take_over_console() is now broken up into: + + register_con_driver() + bind_con_driver() - private function + +give_up_console() is a wrapper to unregister_con_driver(), and a driver must +be fully unbound for this call to succeed. con_is_bound() will check if the +driver is bound or not. + +Guidelines for console driver writers: +===================================== + +In order for binding to and unbinding from the console to properly work, +console drivers must follow these guidelines: + +1. All drivers, except system drivers, must call either register_con_driver() + or take_over_console(). register_con_driver() will just add the driver to + the console's internal list. It won't take over the + console. take_over_console(), as it name implies, will also take over (or + bind to) the console. + +2. All resources allocated during con->con_init() must be released in + con->con_deinit(). + +3. All resources allocated in con->con_startup() must be released when the + driver, which was previously bound, becomes unbound. The console layer + does not have a complementary call to con->con_startup() so it's up to the + driver to check when it's legal to release these resources. Calling + con_is_bound() in con->con_deinit() will help. If the call returned + false(), then it's safe to release the resources. This balance has to be + ensured because con->con_startup() can be called again when a request to + rebind the driver to the console arrives. + +4. Upon exit of the driver, ensure that the driver is totally unbound. If the + condition is satisfied, then the driver must call unregister_con_driver() + or give_up_console(). + +5. unregister_con_driver() can also be called on conditions which make it + impossible for the driver to service console requests. This can happen + with the framebuffer console that suddenly lost all of its drivers. + +The current crop of console drivers should still work correctly, but binding +and unbinding them may cause problems. With minimal fixes, these drivers can +be made to work correctly. + +========================== +Antonino Daplas <adaplas@pol.net> + diff --git a/Documentation/fb/imacfb.txt b/Documentation/fb/imacfb.txt new file mode 100644 index 000000000..759028545 --- /dev/null +++ b/Documentation/fb/imacfb.txt @@ -0,0 +1,31 @@ + +What is imacfb? +=============== + +This is a generic EFI platform driver for Intel based Apple computers. +Imacfb is only for EFI booted Intel Macs. + +Supported Hardware +================== + +iMac 17"/20" +Macbook +Macbook Pro 15"/17" +MacMini + +How to use it? +============== + +Imacfb does not have any kind of autodetection of your machine. +You have to add the fillowing kernel parameters in your elilo.conf: + Macbook : + video=imacfb:macbook + MacMini : + video=imacfb:mini + Macbook Pro 15", iMac 17" : + video=imacfb:i17 + Macbook Pro 17", iMac 20" : + video=imacfb:i20 + +-- +Edgar Hucek <gimli@dark-green.com> diff --git a/Documentation/filesystems/caching/backend-api.txt b/Documentation/filesystems/caching/backend-api.txt new file mode 100644 index 000000000..1dd601b50 --- /dev/null +++ b/Documentation/filesystems/caching/backend-api.txt @@ -0,0 +1,357 @@ + ========================== + FS-CACHE CACHE BACKEND API + ========================== + +The FS-Cache system provides an API by which actual caches can be supplied to +FS-Cache for it to then serve out to network filesystems and other interested +parties. + +This API is declared in <linux/fscache-cache.h>. + + +==================================== +INITIALISING AND REGISTERING A CACHE +==================================== + +To start off, a cache definition must be initialised and registered for each +cache the backend wants to make available. For instance, CacheFS does this in +the fill_super() operation on mounting. + +The cache definition (struct fscache_cache) should be initialised by calling: + + void fscache_init_cache(struct fscache_cache *cache, + struct fscache_cache_ops *ops, + const char *idfmt, + ...) + +Where: + + (*) "cache" is a pointer to the cache definition; + + (*) "ops" is a pointer to the table of operations that the backend supports on + this cache; + + (*) and a format and printf-style arguments for constructing a label for the + cache. + + +The cache should then be registered with FS-Cache by passing a pointer to the +previously initialised cache definition to: + + int fscache_add_cache(struct fscache_cache *cache, + struct fscache_object *fsdef, + const char *tagname); + +Two extra arguments should also be supplied: + + (*) "fsdef" which should point to the object representation for the FS-Cache + master index in this cache. Netfs primary index entries will be created + here. + + (*) "tagname" which, if given, should be a text string naming this cache. If + this is NULL, the identifier will be used instead. For CacheFS, the + identifier is set to name the underlying block device and the tag can be + supplied by mount. + +This function may return -ENOMEM if it ran out of memory or -EEXIST if the tag +is already in use. 0 will be returned on success. + + +===================== +UNREGISTERING A CACHE +===================== + +A cache can be withdrawn from the system by calling this function with a +pointer to the cache definition: + + void fscache_withdraw_cache(struct fscache_cache *cache) + +In CacheFS's case, this is called by put_super(). + + +================== +FS-CACHE UTILITIES +================== + +FS-Cache provides some utilities that a cache backend may make use of: + + (*) Find the parent of an object: + + struct fscache_object * + fscache_find_parent_object(struct fscache_object *object) + + This allows a backend to find the logical parent of an index or data file + in the cache hierarchy. + + (*) Note occurrence of an I/O error in a cache: + + void fscache_io_error(struct fscache_cache *cache) + + This tells FS-Cache that an I/O error occurred in the cache. After this + has been called, only resource dissociation operations (object and page + release) will be passed from the netfs to the cache backend for the + specified cache. + + This does not actually withdraw the cache. That must be done separately. + + (*) Get an extra reference to a read or write context: + + void *fscache_get_context(struct fscache_cookie *cookie, void *context) + + and release a reference: + + void *fscache_put_context(struct fscache_cookie *cookie, void *context) + + These should be used to maintain the presence of the read or write context + passed to the cache read/write functions. This context must then be + passed to the I/O completion function. + + +======================== +RELEVANT DATA STRUCTURES +======================== + + (*) Index/Data file FS-Cache representation cookie: + + struct fscache_cookie { + struct fscache_object_def *def; + struct fscache_netfs *netfs; + void *netfs_data; + ... + }; + + The fields that might be of use to the backend describe the object + definition, the netfs definition and the netfs's data for this cookie. + The object definition contain functions supplied by the netfs for loading + and matching index entries; these are required to provide some of the + cache operations. + + (*) In-cache object representation: + + struct fscache_object { + struct fscache_cache *cache; + struct fscache_cookie *cookie; + unsigned long flags; + #define FSCACHE_OBJECT_RECYCLING 1 + ... + }; + + Structures of this type should be allocated by the cache backend and + passed to FS-Cache when requested by the appropriate cache operation. In + the case of CacheFS, they're embedded in CacheFS's internal object + structures. + + Each object contains a pointer to the cookie that represents the object it + is backing. It also contains a flag that indicates whether the object is + being retired when put_object() is called. This should be initialised by + calling fscache_object_init(object). + + +================ +CACHE OPERATIONS +================ + +The cache backend provides FS-Cache with a table of operations that can be +performed on the denizens of the cache. These are held in a structure of type: + + struct fscache_cache_ops + + (*) Name of cache provider [mandatory]: + + const char *name + + This isn't strictly an operation, but should be pointed at a string naming + the backend. + + (*) Object lookup [mandatory]: + + struct fscache_object *(*lookup_object)(struct fscache_cache *cache, + struct fscache_object *parent, + struct fscache_cookie *cookie) + + This method is used to look up an object in the specified cache, given a + pointer to the parent object and the cookie to which the object will be + attached. This should instantiate that object in the cache if it can, or + return -ENOBUFS or -ENOMEM if it can't. + + (*) Increment object refcount [mandatory]: + + struct fscache_object *(*grab_object)(struct fscache_object *object) + + This method is called to increment the reference count on an object. It + may fail (for instance if the cache is being withdrawn) by returning NULL. + It should return the object pointer if successful. + + (*) Lock/Unlock object [mandatory]: + + void (*lock_object)(struct fscache_object *object) + void (*unlock_object)(struct fscache_object *object) + + These methods are used to exclusively lock an object. It must be possible + to schedule with the lock held, so a spinlock isn't sufficient. + + (*) Pin/Unpin object [optional]: + + int (*pin_object)(struct fscache_object *object) + void (*unpin_object)(struct fscache_object *object) + + These methods are used to pin an object into the cache. Once pinned an + object cannot be reclaimed to make space. Return -ENOSPC if there's not + enough space in the cache to permit this. + + (*) Update object [mandatory]: + + int (*update_object)(struct fscache_object *object) + + This is called to update the index entry for the specified object. The + new information should be in object->cookie->netfs_data. This can be + obtained by calling object->cookie->def->get_aux()/get_attr(). + + (*) Release object reference [mandatory]: + + void (*put_object)(struct fscache_object *object) + + This method is used to discard a reference to an object. The object may + be destroyed when all the references held by FS-Cache are released. + + (*) Synchronise a cache [mandatory]: + + void (*sync)(struct fscache_cache *cache) + + This is called to ask the backend to synchronise a cache with its backing + device. + + (*) Dissociate a cache [mandatory]: + + void (*dissociate_pages)(struct fscache_cache *cache) + + This is called to ask a cache to perform any page dissociations as part of + cache withdrawal. + + (*) Set the data size on a cache file [mandatory]: + + int (*set_i_size)(struct fscache_object *object, loff_t i_size); + + This is called to indicate to the cache the maximum size a file may reach. + The cache may use this to reserve space on the cache. It may also return + -ENOBUFS to indicate that insufficient space is available to expand the + metadata used to track the data. It should return 0 if successful or + -ENOMEM or -EIO on error. + + (*) Reserve cache space for an object's data [optional]: + + int (*reserve_space)(struct fscache_object *object, loff_t size); + + This is called to request that cache space be reserved to hold the data + for an object and the metadata used to track it. Zero size should be + taken as request to cancel a reservation. + + This should return 0 if successful, -ENOSPC if there isn't enough space + available, or -ENOMEM or -EIO on other errors. + + The reservation may exceed the size of the object, thus permitting future + expansion. If the amount of space consumed by an object would exceed the + reservation, it's permitted to refuse requests to allocate pages, but not + required. An object may be pruned down to its reservation size if larger + than that already. + + (*) Request page be read from cache [mandatory]: + + int (*read_or_alloc_page)(struct fscache_object *object, + struct page *page, + fscache_rw_complete_t end_io_func, + void *end_io_data, + gfp_t gfp) + + This is called to attempt to read a netfs page from the cache, or to + reserve a backing block if not. FS-Cache will have done as much checking + as it can before calling, but most of the work belongs to the backend. + + If there's no page in the cache, then -ENODATA should be returned if the + backend managed to reserve a backing block; -ENOBUFS, -ENOMEM or -EIO if + it didn't. + + If there is a page in the cache, then a read operation should be queued + and 0 returned. When the read finishes, end_io_func() should be called + with the following arguments: + + (*end_io_func)(object->cookie->netfs_data, + page, + end_io_data, + error); + + The mark_pages_cached() cookie operation should be called for the page if + any cache metadata is retained. This will indicate to the netfs that the + page needs explicit uncaching. This operation takes a pagevec, thus + allowing several pages to be marked at once. + + (*) Request pages be read from cache [mandatory]: + + int (*read_or_alloc_pages)(struct fscache_object *object, + struct address_space *mapping, + struct list_head *pages, + unsigned *nr_pages, + fscache_rw_complete_t end_io_func, + void *end_io_data, + gfp_t gfp) + + This is like the previous operation, except it will be handed a list of + pages instead of one page. Any pages on which a read operation is started + must be added to the page cache for the specified mapping and also to the + LRU. Such pages must also be removed from the pages list and nr_pages + decremented per page. + + If there was an error such as -ENOMEM, then that should be returned; else + if one or more pages couldn't be read or allocated, then -ENOBUFS should + be returned; else if one or more pages couldn't be read, then -ENODATA + should be returned. If all the pages are dispatched then 0 should be + returned. + + (*) Request page be allocated in the cache [mandatory]: + + int (*allocate_page)(struct fscache_object *object, + struct page *page, + gfp_t gfp) + + This is like read_or_alloc_page(), except that it shouldn't read from the + cache, even if there's data there that could be retrieved. It should, + however, set up any internal metadata required such that write_page() can + write to the cache. + + If there's no backing block available, then -ENOBUFS should be returned + (or -ENOMEM or -EIO if there were other problems). If a block is + successfully allocated, then the netfs page should be marked and 0 + returned. + + (*) Request page be written to cache [mandatory]: + + int (*write_page)(struct fscache_object *object, + struct page *page, + fscache_rw_complete_t end_io_func, + void *end_io_data, + gfp_t gfp) + + This is called to write from a page on which there was a previously + successful read_or_alloc_page() call. FS-Cache filters out pages that + don't have mappings. + + If there's no backing block available, then -ENOBUFS should be returned + (or -ENOMEM or -EIO if there were other problems). + + If the write operation could be queued, then 0 should be returned. When + the write completes, end_io_func() should be called with the following + arguments: + + (*end_io_func)(object->cookie->netfs_data, + page, + end_io_data, + error); + + (*) Discard retained per-page metadata [mandatory]: + + void (*uncache_pages)(struct fscache_object *object, + struct pagevec *pagevec) + + This is called when one or more netfs pages are being evicted from the + pagecache. The cache backend should tear down any internal representation + or tracking it maintains. diff --git a/Documentation/filesystems/caching/cachefiles.txt b/Documentation/filesystems/caching/cachefiles.txt new file mode 100644 index 000000000..37b6385e0 --- /dev/null +++ b/Documentation/filesystems/caching/cachefiles.txt @@ -0,0 +1,281 @@ + =============================================== + CacheFiles: CACHE ON ALREADY MOUNTED FILESYSTEM + =============================================== + +Contents: + + (*) Overview. + + (*) Requirements. + + (*) Configuration. + + (*) Starting the cache. + + (*) Things to avoid. + + +======== +OVERVIEW +======== + +CacheFiles is a caching backend that's meant to use as a cache a directory on +an already mounted filesystem of a local type (such as Ext3). + +CacheFiles uses a userspace daemon to do some of the cache management - such as +reaping stale nodes and culling. This is called cachefilesd and lives in +/sbin. + +The filesystem and data integrity of the cache are only as good as those of the +filesystem providing the backing services. Note that CacheFiles does not +attempt to journal anything since the journalling interfaces of the various +filesystems are very specific in nature. + +CacheFiles creates a proc-file - "/proc/fs/cachefiles" - that is used for +communication with the daemon. Only one thing may have this open at once, and +whilst it is open, a cache is at least partially in existence. The daemon +opens this and sends commands down it to control the cache. + +CacheFiles is currently limited to a single cache. + +CacheFiles attempts to maintain at least a certain percentage of free space on +the filesystem, shrinking the cache by culling the objects it contains to make +space if necessary - see the "Cache Culling" section. This means it can be +placed on the same medium as a live set of data, and will expand to make use of +spare space and automatically contract when the set of data requires more +space. + + +============ +REQUIREMENTS +============ + +The use of CacheFiles and its daemon requires the following features to be +available in the system and in the cache filesystem: + + - dnotify. + + - extended attributes (xattrs). + + - openat() and friends. + + - bmap() support on files in the filesystem (FIBMAP ioctl). + + - The use of bmap() to detect a partial page at the end of the file. + +It is strongly recommended that the "dir_index" option is enabled on Ext3 +filesystems being used as a cache. + + +============= +CONFIGURATION +============= + +The cache is configured by a script in /etc/cachefilesd.conf. These commands +set up cache ready for use. The following script commands are available: + + (*) brun <N>% + (*) bcull <N>% + (*) bstop <N>% + + Configure the culling limits. Optional. See the section on culling + The defaults are 7%, 5% and 1% respectively. + + (*) dir <path> + + Specify the directory containing the root of the cache. Mandatory. + + (*) tag <name> + + Specify a tag to FS-Cache to use in distinguishing multiple caches. + Optional. The default is "CacheFiles". + + (*) debug <mask> + + Specify a numeric bitmask to control debugging in the kernel module. + Optional. The default is zero (all off). The following values can be + OR'd into the mask to collect various information: + + 1 Turn on trace of function entry (_enter() macros) + 2 Turn on trace of function exit (_leave() macros) + 4 Turn on trace of internal debug points (_debug()) + + This mask can also be set through /proc/sys/fs/cachefiles/debug. + + +================== +STARTING THE CACHE +================== + +The cache is started by running the daemon. The daemon opens the cache proc +file, configures the cache and tells it to begin caching. At that point the +cache binds to fscache and the cache becomes live. + +The daemon is run as follows: + + /sbin/cachefilesd [-d]* [-s] [-n] [-f <configfile>] + +The flags are: + + (*) -d + + Increase the debugging level. This can be specified multiple times and + is cumulative with itself. + + (*) -s + + Send messages to stderr instead of syslog. + + (*) -n + + Don't daemonise and go into background. + + (*) -f <configfile> + + Use an alternative configuration file rather than the default one. + + +=============== +THINGS TO AVOID +=============== + +Do not mount other things within the cache as this will cause problems. The +kernel module contains its own very cut-down path walking facility that ignores +mountpoints, but the daemon can't avoid them. + +Do not create, rename or unlink files and directories in the cache whilst the +cache is active, as this may cause the state to become uncertain. + +Renaming files in the cache might make objects appear to be other objects (the +filename is part of the lookup key). + +Do not change or remove the extended attributes attached to cache files by the +cache as this will cause the cache state management to get confused. + +Do not create files or directories in the cache, lest the cache get confused or +serve incorrect data. + +Do not chmod files in the cache. The module creates things with minimal +permissions to prevent random users being able to access them directly. + + +============= +CACHE CULLING +============= + +The cache may need culling occasionally to make space. This involves +discarding objects from the cache that have been used less recently than +anything else. Culling is based on the access time of data objects. Empty +directories are culled if not in use. + +Cache culling is done on the basis of the percentage of blocks available in the +underlying filesystem. There are three "limits": + + (*) brun + + If the amount of available space in the cache rises above this limit, then + culling is turned off. + + (*) bcull + + If the amount of available space in the cache falls below this limit, then + culling is started. + + (*) bstop + + If the amount of available space in the cache falls below this limit, then + no further allocation of disk space is permitted until culling has raised + the amount above this limit again. + +These must be configured thusly: + + 0 <= bstop < bcull < brun < 100 + +Note that these are percentages of available space, and do _not_ appear as 100 +minus the percentage displayed by the "df" program. + +The userspace daemon scans the cache to build up a table of cullable objects. +These are then culled in least recently used order. A new scan of the cache is +started as soon as space is made in the table. Objects will be skipped if +their atimes have changed or if the kernel module says it is still using them. + + +=============== +CACHE STRUCTURE +=============== + +The CacheFiles module will create two directories in the directory it was +given: + + (*) cache/ + + (*) graveyard/ + +The active cache objects all reside in the first directory. The CacheFiles +kernel module moves any retired or culled objects that it can't simply unlink +to the graveyard from which the daemon will actually delete them. + +The daemon uses dnotify to monitor the graveyard directory, and will delete +anything that appears therein. + + +The module represents index objects as directories with the filename "I..." or +"J...". Note that the "cache/" directory is itself a special index. + +Data objects are represented as files if they have no children, or directories +if they do. Their filenames all begin "D..." or "E...". If represented as a +directory, data objects will have a file in the directory called "data" that +actually holds the data. + +Special objects are similar to data objects, except their filenames begin +"S..." or "T...". + + +If an object has children, then it will be represented as a directory. +Immediately in the representative directory are a collection of directories +named for hash values of the child object keys with an '@' prepended. Into +this directory, if possible, will be placed the representations of the child +objects: + + INDEX INDEX INDEX DATA FILES + ========= ========== ================================= ================ + cache/@4a/I03nfs/@30/Ji000000000000000--fHg8hi8400 + cache/@4a/I03nfs/@30/Ji000000000000000--fHg8hi8400/@75/Es0g000w...DB1ry + cache/@4a/I03nfs/@30/Ji000000000000000--fHg8hi8400/@75/Es0g000w...N22ry + cache/@4a/I03nfs/@30/Ji000000000000000--fHg8hi8400/@75/Es0g000w...FP1ry + + +If the key is so long that it exceeds NAME_MAX with the decorations added on to +it, then it will be cut into pieces, the first few of which will be used to +make a nest of directories, and the last one of which will be the objects +inside the last directory. The names of the intermediate directories will have +'+' prepended: + + J1223/@23/+xy...z/+kl...m/Epqr + + +Note that keys are raw data, and not only may they exceed NAME_MAX in size, +they may also contain things like '/' and NUL characters, and so they may not +be suitable for turning directly into a filename. + +To handle this, CacheFiles will use a suitably printable filename directly and +"base-64" encode ones that aren't directly suitable. The two versions of +object filenames indicate the encoding: + + OBJECT TYPE PRINTABLE ENCODED + =============== =============== =============== + Index "I..." "J..." + Data "D..." "E..." + Special "S..." "T..." + +Intermediate directories are always "@" or "+" as appropriate. + + +Each object in the cache has an extended attribute label that holds the object +type ID (required to distinguish special objects) and the auxiliary data from +the netfs. The latter is used to detect stale objects in the cache and update +or retire them. + + +Note that CacheFiles will erase from the cache any file it doesn't recognise or +any file of an incorrect type (such as a FIFO file or a device file). diff --git a/Documentation/filesystems/caching/fscache.txt b/Documentation/filesystems/caching/fscache.txt new file mode 100644 index 000000000..82c31682e --- /dev/null +++ b/Documentation/filesystems/caching/fscache.txt @@ -0,0 +1,151 @@ + ========================== + General Filesystem Caching + ========================== + +======== +OVERVIEW +======== + +This facility is a general purpose cache for network filesystems, though it +could be used for caching other things such as ISO9660 filesystems too. + +FS-Cache mediates between cache backends (such as CacheFS) and network +filesystems: + + +---------+ + | | +--------------+ + | NFS |--+ | | + | | | +-->| CacheFS | + +---------+ | +----------+ | | /dev/hda5 | + | | | | +--------------+ + +---------+ +-->| | | + | | | |--+ + | AFS |----->| FS-Cache | + | | | |--+ + +---------+ +-->| | | + | | | | +--------------+ + +---------+ | +----------+ | | | + | | | +-->| CacheFiles | + | ISOFS |--+ | /var/cache | + | | +--------------+ + +---------+ + + +FS-Cache does not follow the idea of completely loading every netfs file +opened in its entirety into a cache before permitting it to be accessed and +then serving the pages out of that cache rather than the netfs inode because: + + (1) It must be practical to operate without a cache. + + (2) The size of any accessible file must not be limited to the size of the + cache. + + (3) The combined size of all opened files (this includes mapped libraries) + must not be limited to the size of the cache. + + (4) The user should not be forced to download an entire file just to do a + one-off access of a small portion of it (such as might be done with the + "file" program). + +It instead serves the cache out in PAGE_SIZE chunks as and when requested by +the netfs('s) using it. + + +FS-Cache provides the following facilities: + + (1) More than one cache can be used at once. Caches can be selected + explicitly by use of tags. + + (2) Caches can be added / removed at any time. + + (3) The netfs is provided with an interface that allows either party to + withdraw caching facilities from a file (required for (2)). + + (4) The interface to the netfs returns as few errors as possible, preferring + rather to let the netfs remain oblivious. + + (5) Cookies are used to represent indices, files and other objects to the + netfs. The simplest cookie is just a NULL pointer - indicating nothing + cached there. + + (6) The netfs is allowed to propose - dynamically - any index hierarchy it + desires, though it must be aware that the index search function is + recursive, stack space is limited, and indices can only be children of + indices. + + (7) Data I/O is done direct to and from the netfs's pages. The netfs + indicates that page A is at index B of the data-file represented by cookie + C, and that it should be read or written. The cache backend may or may + not start I/O on that page, but if it does, a netfs callback will be + invoked to indicate completion. The I/O may be either synchronous or + asynchronous. + + (8) Cookies can be "retired" upon release. At this point FS-Cache will mark + them as obsolete and the index hierarchy rooted at that point will get + recycled. + + (9) The netfs provides a "match" function for index searches. In addition to + saying whether a match was made or not, this can also specify that an + entry should be updated or deleted. + + +FS-Cache maintains a virtual indexing tree in which all indices, files, objects +and pages are kept. Bits of this tree may actually reside in one or more +caches. + + FSDEF + | + +------------------------------------+ + | | + NFS AFS + | | + +--------------------------+ +-----------+ + | | | | + homedir mirror afs.org redhat.com + | | | + +------------+ +---------------+ +----------+ + | | | | | | + 00001 00002 00007 00125 vol00001 vol00002 + | | | | | + +---+---+ +-----+ +---+ +------+------+ +-----+----+ + | | | | | | | | | | | | | +PG0 PG1 PG2 PG0 XATTR PG0 PG1 DIRENT DIRENT DIRENT R/W R/O Bak + | | + PG0 +-------+ + | | + 00001 00003 + | + +---+---+ + | | | + PG0 PG1 PG2 + +In the example above, you can see two netfs's being backed: NFS and AFS. These +have different index hierarchies: + + (*) The NFS primary index contains per-server indices. Each server index is + indexed by NFS file handles to get data file objects. Each data file + objects can have an array of pages, but may also have further child + objects, such as extended attributes and directory entries. Extended + attribute objects themselves have page-array contents. + + (*) The AFS primary index contains per-cell indices. Each cell index contains + per-logical-volume indices. Each of volume index contains up to three + indices for the read-write, read-only and backup mirrors of those volumes. + Each of these contains vnode data file objects, each of which contains an + array of pages. + +The very top index is the FS-Cache master index in which individual netfs's +have entries. + +Any index object may reside in more than one cache, provided it only has index +children. Any index with non-index object children will be assumed to only +reside in one cache. + + +The netfs API to FS-Cache can be found in: + + Documentation/filesystems/caching/netfs-api.txt + +The cache backend API to FS-Cache can be found in: + + Documentation/filesystems/caching/backend-api.txt diff --git a/Documentation/filesystems/caching/netfs-api.txt b/Documentation/filesystems/caching/netfs-api.txt new file mode 100644 index 000000000..a1a182beb --- /dev/null +++ b/Documentation/filesystems/caching/netfs-api.txt @@ -0,0 +1,752 @@ + =============================== + FS-CACHE NETWORK FILESYSTEM API + =============================== + +There's an API by which a network filesystem can make use of the FS-Cache +facilities. This is based around a number of principles: + + (1) Caches can store a number of different object types. There are two main + object types: indices and files. The first is a special type used by + FS-Cache to make finding objects faster and to make retiring of groups of + objects easier. + + (2) Every index, file or other object is represented by a cookie. This cookie + may or may not have anything associated with it, but the netfs doesn't + need to care. + + (3) Barring the top-level index (one entry per cached netfs), the index + hierarchy for each netfs is structured according the whim of the netfs. + +This API is declared in <linux/fscache.h>. + +This document contains the following sections: + + (1) Network filesystem definition + (2) Index definition + (3) Object definition + (4) Network filesystem (un)registration + (5) Cache tag lookup + (6) Index registration + (7) Data file registration + (8) Miscellaneous object registration + (9) Setting the data file size + (10) Page alloc/read/write + (11) Page uncaching + (12) Index and data file update + (13) Miscellaneous cookie operations + (14) Cookie unregistration + (15) Index and data file invalidation + + +============================= +NETWORK FILESYSTEM DEFINITION +============================= + +FS-Cache needs a description of the network filesystem. This is specified +using a record of the following structure: + + struct fscache_netfs { + uint32_t version; + const char *name; + struct fscache_netfs_operations *ops; + struct fscache_cookie *primary_index; + ... + }; + +This first three fields should be filled in before registration, and the fourth +will be filled in by the registration function; any other fields should just be +ignored and are for internal use only. + +The fields are: + + (1) The name of the netfs (used as the key in the toplevel index). + + (2) The version of the netfs (if the name matches but the version doesn't, the + entire in-cache hierarchy for this netfs will be scrapped and begun + afresh). + + (3) The operations table is defined as follows: + + struct fscache_netfs_operations { + }; + + Currently there aren't any functions here. + + (4) The cookie representing the primary index will be allocated according to + another parameter passed into the registration function. + +For example, kAFS (linux/fs/afs/) uses the following definitions to describe +itself: + + static struct fscache_netfs_operations afs_cache_ops = { + }; + + struct fscache_netfs afs_cache_netfs = { + .version = 0, + .name = "afs", + .ops = &afs_cache_ops, + }; + + +================ +INDEX DEFINITION +================ + +Indices are used for two purposes: + + (1) To aid the finding of a file based on a series of keys (such as AFS's + "cell", "volume ID", "vnode ID"). + + (2) To make it easier to discard a subset of all the files cached based around + a particular key - for instance to mirror the removal of an AFS volume. + +However, since it's unlikely that any two netfs's are going to want to define +their index hierarchies in quite the same way, FS-Cache tries to impose as few +restraints as possible on how an index is structured and where it is placed in +the tree. The netfs can even mix indices and data files at the same level, but +it's not recommended. + +Each index entry consists of a key of indeterminate length plus some auxilliary +data, also of indeterminate length. + +There are some limits on indices: + + (1) Any index containing non-index objects should be restricted to a single + cache. Any such objects created within an index will be created in the + first cache only. The cache in which an index is created can be + controlled by cache tags (see below). + + (2) The entry data must be atomically journallable, so it is limited to about + 400 bytes at present. At least 400 bytes will be available. + + (3) The depth of the index tree should be judged with care as the search + function is recursive. Too many layers will run the kernel out of stack. + + +================= +OBJECT DEFINITION +================= + +To define an object, a structure of the following type should be filled out: + + struct fscache_object_def + { + uint8_t name[16]; + uint8_t type; + + struct fscache_cache_tag *(*select_cache)( + const void *parent_netfs_data, + const void *cookie_netfs_data); + + uint16_t (*get_key)(const void *cookie_netfs_data, + void *buffer, + uint16_t bufmax); + + void (*get_attr)(const void *cookie_netfs_data, + uint64_t *size); + + uint16_t (*get_aux)(const void *cookie_netfs_data, + void *buffer, + uint16_t bufmax); + + fscache_checkaux_t (*check_aux)(void *cookie_netfs_data, + const void *data, + uint16_t datalen); + + void (*get_context)(void *cookie_netfs_data, void *context); + + void (*put_context)(void *cookie_netfs_data, void *context); + + void (*mark_pages_cached)(void *cookie_netfs_data, + struct address_space *mapping, + struct pagevec *cached_pvec); + + void (*now_uncached)(void *cookie_netfs_data); + }; + +This has the following fields: + + (1) The type of the object [mandatory]. + + This is one of the following values: + + (*) FSCACHE_COOKIE_TYPE_INDEX + + This defines an index, which is a special FS-Cache type. + + (*) FSCACHE_COOKIE_TYPE_DATAFILE + + This defines an ordinary data file. + + (*) Any other value between 2 and 255 + + This defines an extraordinary object such as an XATTR. + + (2) The name of the object type (NUL terminated unless all 16 chars are used) + [optional]. + + (3) A function to select the cache in which to store an index [optional]. + + This function is invoked when an index needs to be instantiated in a cache + during the instantiation of a non-index object. Only the immediate index + parent for the non-index object will be queried. Any indices above that + in the hierarchy may be stored in multiple caches. This function does not + need to be supplied for any non-index object or any index that will only + have index children. + + If this function is not supplied or if it returns NULL then the first + cache in the parent's list will be chosed, or failing that, the first + cache in the master list. + + (4) A function to retrieve an object's key from the netfs [mandatory]. + + This function will be called with the netfs data that was passed to the + cookie acquisition function and the maximum length of key data that it may + provide. It should write the required key data into the given buffer and + return the quantity it wrote. + + (5) A function to retrieve attribute data from the netfs [optional]. + + This function will be called with the netfs data that was passed to the + cookie acquisition function. It should return the size of the file if + this is a data file. The size may be used to govern how much cache must + be reserved for this file in the cache. + + If the function is absent, a file size of 0 is assumed. + + (6) A function to retrieve auxilliary data from the netfs [optional]. + + This function will be called with the netfs data that was passed to the + cookie acquisition function and the maximum length of auxilliary data that + it may provide. It should write the auxilliary data into the given buffer + and return the quantity it wrote. + + If this function is absent, the auxilliary data length will be set to 0. + + The length of the auxilliary data buffer may be dependent on the key + length. A netfs mustn't rely on being able to provide more than 400 bytes + for both. + + (7) A function to check the auxilliary data [optional]. + + This function will be called to check that a match found in the cache for + this object is valid. For instance with AFS it could check the auxilliary + data against the data version number returned by the server to determine + whether the index entry in a cache is still valid. + + If this function is absent, it will be assumed that matching objects in a + cache are always valid. + + If present, the function should return one of the following values: + + (*) FSCACHE_CHECKAUX_OKAY - the entry is okay as is + (*) FSCACHE_CHECKAUX_NEEDS_UPDATE - the entry requires update + (*) FSCACHE_CHECKAUX_OBSOLETE - the entry should be deleted + + This function can also be used to extract data from the auxilliary data in + the cache and copy it into the netfs's structures. + + (8) A pair of functions to manage contexts for the completion callback + [optional]. + + The cache read/write functions are passed a context which is then passed + to the I/O completion callback function. To ensure this context remains + valid until after the I/O completion is called, two functions may be + provided: one to get an extra reference on the context, and one to drop a + reference to it. + + If the context is not used or is a type of object that won't go out of + scope, then these functions are not required. These functions are not + required for indices as indices may not contain data. These functions may + be called in interrupt context and so may not sleep. + + (9) A function to mark a page as retaining cache metadata [mandatory]. + + This is called by the cache to indicate that it is retaining in-memory + information for this page and that the netfs should uncache the page when + it has finished. This does not indicate whether there's data on the disk + or not. Note that several pages at once may be presented for marking. + + kAFS and NFS use the PG_private bit on the page structure for this, but + that may not be appropriate in all cases. + + This function is not required for indices as they're not permitted data. + +(10) A function to unmark all the pages retaining cache metadata [mandatory]. + + This is called by FS-Cache to indicate that a backing store is being + unbound from a cookie and that all the marks on the pages should be + cleared to prevent confusion. Note that the cache will have torn down all + its tracking information so that the pages don't need to be explicitly + uncached. + + This function is not required for indices as they're not permitted data. + + +=================================== +NETWORK FILESYSTEM (UN)REGISTRATION +=================================== + +The first step is to declare the network filesystem to the cache. This also +involves specifying the layout of the primary index (for AFS, this would be the +"cell" level). + +The registration function is: + + int fscache_register_netfs(struct fscache_netfs *netfs); + +It just takes a pointer to the netfs definition. It returns 0 or an error as +appropriate. + +For kAFS, registration is done as follows: + + ret = fscache_register_netfs(&afs_cache_netfs); + +The last step is, of course, unregistration: + + void fscache_unregister_netfs(struct fscache_netfs *netfs); + + +================ +CACHE TAG LOOKUP +================ + +FS-Cache permits the use of more than one cache. To permit particular index +subtrees to be bound to particular caches, the second step is to look up cache +representation tags. This step is optional; it can be left entirely up to +FS-Cache as to which cache should be used. The problem with doing that is that +FS-Cache will always pick the first cache that was registered. + +To get the representation for a named tag: + + struct fscache_cache_tag *fscache_lookup_cache_tag(const char *name); + +This takes a text string as the name and returns a representation of a tag. It +will never return an error. It may return a dummy tag, however, if it runs out +of memory; this will inhibit caching with this tag. + +Any representation so obtained must be released by passing it to this function: + + void fscache_release_cache_tag(struct fscache_cache_tag *tag); + +The tag will be retrieved by FS-Cache when it calls the object definition +operation select_cache(). + + +================== +INDEX REGISTRATION +================== + +The third step is to inform FS-Cache about part of an index hierarchy that can +be used to locate files. This is done by requesting a cookie for each index in +the path to the file: + + struct fscache_cookie * + fscache_acquire_cookie(struct fscache_cookie *parent, + struct fscache_object_def *def, + void *netfs_data); + +This function creates an index entry in the index represented by parent, +filling in the index entry by calling the operations pointed to by def. + +Note that this function never returns an error - all errors are handled +internally. It may also return NULL to indicate no cookie. It is quite +acceptable to pass this token back to this function as the parent to another +acquisition (or even to the relinquish cookie, read page and write page +functions - see below). + +Note also that no indices are actually created in a cache until a non-index +object needs to be created somewhere down the hierarchy. Furthermore, an index +may be created in several different caches independently at different times. +This is all handled transparently, and the netfs doesn't see any of it. + +For example, with AFS, a cell would be added to the primary index. This index +entry would have a dependent inode containing a volume location index for the +volume mappings within this cell: + + cell->cache = + fscache_acquire_cookie(afs_cache_netfs.primary_index, + &afs_cell_cache_index_def, + cell); + +Then when a volume location was accessed, it would be entered into the cell's +index and an inode would be allocated that acts as a volume type and hash chain +combination: + + vlocation->cache = + fscache_acquire_cookie(cell->cache, + &afs_vlocation_cache_index_def, + vlocation); + +And then a particular flavour of volume (R/O for example) could be added to +that index, creating another index for vnodes (AFS inode equivalents): + + volume->cache = + fscache_acquire_cookie(vlocation->cache, + &afs_volume_cache_index_def, + volume); + + +====================== +DATA FILE REGISTRATION +====================== + +The fourth step is to request a data file be created in the cache. This is +identical to index cookie acquisition. The only difference is that the type in +the object definition should be something other than index type. + + vnode->cache = + fscache_acquire_cookie(volume->cache, + &afs_vnode_cache_object_def, + vnode); + + +================================= +MISCELLANEOUS OBJECT REGISTRATION +================================= + +An optional step is to request an object of miscellaneous type be created in +the cache. This is almost identical to index cookie acquisition. The only +difference is that the type in the object definition should be something other +than index type. Whilst the parent object could be an index, it's more likely +it would be some other type of object such as a data file. + + xattr->cache = + fscache_acquire_cookie(vnode->cache, + &afs_xattr_cache_object_def, + xattr); + +Miscellaneous objects might be used to store extended attributes or directory +entries for example. + + +========================== +SETTING THE DATA FILE SIZE +========================== + +The fifth step is to set the size of the file. This doesn't automatically +reserve any space in the cache, but permits the cache to adjust its metadata +for data tracking appropriately: + + int fscache_set_i_size(struct fscache_cookie *cookie, loff_t i_size); + +The cache will return -ENOBUFS if there is no backing cache or if there is no +space to allocate any extra metadata required in the cache. + +Note that attempts to read or write data pages in the cache over this size may +be rebuffed with -ENOBUFS. + + +===================== +PAGE READ/ALLOC/WRITE +===================== + +And the sixth step is to store and retrieve pages in the cache. There are +three functions that are used to do this. + +Note: + + (1) A page should not be re-read or re-allocated without uncaching it first. + + (2) A read or allocated page must be uncached when the netfs page is released + from the pagecache. + + (3) A page should only be written to the cache if previous read or allocated. + +This permits the cache to maintain its page tracking in proper order. + + +PAGE READ +--------- + +Firstly, the netfs should ask FS-Cache to examine the caches and read the +contents cached for a particular page of a particular file if present, or else +allocate space to store the contents if not: + + typedef + void (*fscache_rw_complete_t)(struct page *page, + void *context, + int error); + + int fscache_read_or_alloc_page(struct fscache_cookie *cookie, + struct page *page, + fscache_rw_complete_t end_io_func, + void *end_io_data, + gfp_t gfp); + +The cookie argument must specify a cookie for an object that isn't an index, +the page specified will have the data loaded into it (and is also used to +specify the page number), and the gfp argument is used to control how any +memory allocations made are satisfied. + +If the cookie indicates the inode is not cached: + + (1) The function will return -ENOBUFS. + +Else if there's a copy of the page resident in the cache: + + (1) The mark_pages_cached() cookie operation will be called on that page. + + (2) The function will submit a request to read the data from the cache's + backing device directly into the page specified. + + (3) The function will return 0. + + (4) When the read is complete, end_io_func() will be invoked with: + + (*) The netfs data supplied when the cookie was created. + + (*) The page descriptor. + + (*) The context argument passed to the above function. This will be + maintained with the get_context/put_context functions mentioned above. + + (*) An argument that's 0 on success or negative for an error code. + + If an error occurs, it should be assumed that the page contains no usable + data. + + end_io_func() will be called in process context if the read is results in + an error, but it might be called in interrupt context if the read is + successful. + +Otherwise, if there's not a copy available in cache, but the cache may be able +to store the page: + + (1) The mark_pages_cached() cookie operation will be called on that page. + + (2) A block may be reserved in the cache and attached to the object at the + appropriate place. + + (3) The function will return -ENODATA. + +This function may also return -ENOMEM or -EINTR, in which case it won't have +read any data from the cache. + + +PAGE ALLOCATE +------------- + +Alternatively, if there's not expected to be any data in the cache for a page +because the file has been extended, a block can simply be allocated instead: + + int fscache_alloc_page(struct fscache_cookie *cookie, + struct page *page, + gfp_t gfp); + +This is similar to the fscache_read_or_alloc_page() function, except that it +never reads from the cache. It will return 0 if a block has been allocated, +rather than -ENODATA as the other would. One or the other must be performed +before writing to the cache. + +The mark_pages_cached() cookie operation will be called on the page if +successful. + + +PAGE WRITE +---------- + +Secondly, if the netfs changes the contents of the page (either due to an +initial download or if a user performs a write), then the page should be +written back to the cache: + + int fscache_write_page(struct fscache_cookie *cookie, + struct page *page, + fscache_rw_complete_t end_io_func, + void *context, + gfp_t gfp); + +The cookie argument must specify a data file cookie, the page specified should +contain the data to be written (and is also used to specify the page number), +and the gfp argument is used to control how any memory allocations made are +satisfied. + +The page must have first been read or allocated successfully and must not have +been uncached before writing is performed. + +If the cookie indicates the inode is not cached then: + + (1) The function will return -ENOBUFS. + +Else if space can be allocated in the cache to hold this page: + + (1) The function will submit a request to write the data to cache's backing + device directly from the page specified. + + (2) The function will return 0. + + (3) When the write is complete the end_io_func() will be invoked with: + + (*) The netfs data supplied when the cookie was created. + + (*) The page descriptor. + + (*) The context argument passed to the function. This will be maintained + with the get_context/put_context functions mentioned above. + + (*) An argument that's 0 on success or negative for an error. + + If an error occurs, it can be assumed that the page has not been written + to the cache, and that either there's a block containing the old data or + no block at all in the cache. + + end_io_func() might be called in interrupt context. + +Else if there's no space available in the cache, -ENOBUFS will be returned. + + +MULTIPLE PAGE READ +------------------ + +A facility is provided to read several pages at once, as requested by the +readpages() address space operation: + + int fscache_read_or_alloc_pages(struct fscache_cookie *cookie, + struct address_space *mapping, + struct list_head *pages, + int *nr_pages, + fscache_rw_complete_t end_io_func, + void *context, + gfp_t gfp); + +This works in a similar way to fscache_read_or_alloc_page(), except: + + (1) Any page it can retrieve data for is removed from pages and nr_pages and + dispatched for reading to the disk. Reads of adjacent pages on disk may + be merged for greater efficiency. + + (2) The mark_pages_cached() cookie operation will be called on several pages + at once if they're being read or allocated. + + (3) If there was an general error, then that error will be returned. + + Else if some pages couldn't be allocated or read, then -ENOBUFS will be + returned. + + Else if some pages couldn't be read but were allocated, then -ENODATA will + be returned. + + Otherwise, if all pages had reads dispatched, then 0 will be returned, the + list will be empty and *nr_pages will be 0. + + (4) end_io_func will be called once for each page being read as the reads + complete. It will be called in process context if error != 0, but it may + be called in interrupt context if there is no error. + +Note that a return of -ENODATA, -ENOBUFS or any other error does not preclude +some of the pages being read and some being allocated. Those pages will have +been marked appropriately and will need uncaching. + + +============== +PAGE UNCACHING +============== + +To uncache a page, this function should be called: + + void fscache_uncache_page(struct fscache_cookie *cookie, + struct page *page); + +This function permits the cache to release any in-memory representation it +might be holding for this netfs page. This function must be called once for +each page on which the read or write page functions above have been called to +make sure the cache's in-memory tracking information gets torn down. + +Note that pages can't be explicitly deleted from the a data file. The whole +data file must be retired (see the relinquish cookie function below). + +Furthermore, note that this does not cancel the asynchronous read or write +operation started by the read/alloc and write functions. + +There is another unbinding operation similar to the above that takes a set of +pages to unbind in one go: + + void fscache_uncache_pagevec(struct fscache_cookie *cookie, + struct pagevec *pagevec); + + +========================== +INDEX AND DATA FILE UPDATE +========================== + +To request an update of the index data for an index or other object, the +following function should be called: + + void fscache_update_cookie(struct fscache_cookie *cookie); + +This function will refer back to the netfs_data pointer stored in the cookie by +the acquisition function to obtain the data to write into each revised index +entry. The update method in the parent index definition will be called to +transfer the data. + +Note that partial updates may happen automatically at other times, such as when +data blocks are added to a data file object. + + +=============================== +MISCELLANEOUS COOKIE OPERATIONS +=============================== + +There are a number of operations that can be used to control cookies: + + (*) Cookie pinning: + + int fscache_pin_cookie(struct fscache_cookie *cookie); + void fscache_unpin_cookie(struct fscache_cookie *cookie); + + These operations permit data cookies to be pinned into the cache and to + have the pinning removed. They are not permitted on index cookies. + + The pinning function will return 0 if successful, -ENOBUFS in the cookie + isn't backed by a cache, -EOPNOTSUPP if the cache doesn't support pinning, + -ENOSPC if there isn't enough space to honour the operation, -ENOMEM or + -EIO if there's any other problem. + + (*) Data space reservation: + + int fscache_reserve_space(struct fscache_cookie *cookie, loff_t size); + + This permits a netfs to request cache space be reserved to store up to the + given amount of a file. It is permitted to ask for more than the current + size of the file to allow for future file expansion. + + If size is given as zero then the reservation will be cancelled. + + The function will return 0 if successful, -ENOBUFS in the cookie isn't + backed by a cache, -EOPNOTSUPP if the cache doesn't support reservations, + -ENOSPC if there isn't enough space to honour the operation, -ENOMEM or + -EIO if there's any other problem. + + Note that this doesn't pin an object in a cache; it can still be culled to + make space if it's not in use. + + +===================== +COOKIE UNREGISTRATION +===================== + +To get rid of a cookie, this function should be called. + + void fscache_relinquish_cookie(struct fscache_cookie *cookie, + int retire); + +If retire is non-zero, then the object will be marked for recycling, and all +copies of it will be removed from all active caches in which it is present. +Not only that but all child objects will also be retired. + +If retire is zero, then the object may be available again when next the +acquisition function is called. Retirement here will overrule the pinning on a +cookie. + +One very important note - relinquish must NOT be called for a cookie unless all +the cookies for "child" indices, objects and pages have been relinquished +first. + + +================================ +INDEX AND DATA FILE INVALIDATION +================================ + +There is no direct way to invalidate an index subtree or a data file. To do +this, the caller should relinquish and retire the cookie they have, and then +acquire a new one. diff --git a/Documentation/filesystems/relay.txt b/Documentation/filesystems/relay.txt new file mode 100644 index 000000000..d6788dae0 --- /dev/null +++ b/Documentation/filesystems/relay.txt @@ -0,0 +1,479 @@ +relay interface (formerly relayfs) +================================== + +The relay interface provides a means for kernel applications to +efficiently log and transfer large quantities of data from the kernel +to userspace via user-defined 'relay channels'. + +A 'relay channel' is a kernel->user data relay mechanism implemented +as a set of per-cpu kernel buffers ('channel buffers'), each +represented as a regular file ('relay file') in user space. Kernel +clients write into the channel buffers using efficient write +functions; these automatically log into the current cpu's channel +buffer. User space applications mmap() or read() from the relay files +and retrieve the data as it becomes available. The relay files +themselves are files created in a host filesystem, e.g. debugfs, and +are associated with the channel buffers using the API described below. + +The format of the data logged into the channel buffers is completely +up to the kernel client; the relay interface does however provide +hooks which allow kernel clients to impose some structure on the +buffer data. The relay interface doesn't implement any form of data +filtering - this also is left to the kernel client. The purpose is to +keep things as simple as possible. + +This document provides an overview of the relay interface API. The +details of the function parameters are documented along with the +functions in the relay interface code - please see that for details. + +Semantics +========= + +Each relay channel has one buffer per CPU, each buffer has one or more +sub-buffers. Messages are written to the first sub-buffer until it is +too full to contain a new message, in which case it it is written to +the next (if available). Messages are never split across sub-buffers. +At this point, userspace can be notified so it empties the first +sub-buffer, while the kernel continues writing to the next. + +When notified that a sub-buffer is full, the kernel knows how many +bytes of it are padding i.e. unused space occurring because a complete +message couldn't fit into a sub-buffer. Userspace can use this +knowledge to copy only valid data. + +After copying it, userspace can notify the kernel that a sub-buffer +has been consumed. + +A relay channel can operate in a mode where it will overwrite data not +yet collected by userspace, and not wait for it to be consumed. + +The relay channel itself does not provide for communication of such +data between userspace and kernel, allowing the kernel side to remain +simple and not impose a single interface on userspace. It does +provide a set of examples and a separate helper though, described +below. + +The read() interface both removes padding and internally consumes the +read sub-buffers; thus in cases where read(2) is being used to drain +the channel buffers, special-purpose communication between kernel and +user isn't necessary for basic operation. + +One of the major goals of the relay interface is to provide a low +overhead mechanism for conveying kernel data to userspace. While the +read() interface is easy to use, it's not as efficient as the mmap() +approach; the example code attempts to make the tradeoff between the +two approaches as small as possible. + +klog and relay-apps example code +================================ + +The relay interface itself is ready to use, but to make things easier, +a couple simple utility functions and a set of examples are provided. + +The relay-apps example tarball, available on the relay sourceforge +site, contains a set of self-contained examples, each consisting of a +pair of .c files containing boilerplate code for each of the user and +kernel sides of a relay application. When combined these two sets of +boilerplate code provide glue to easily stream data to disk, without +having to bother with mundane housekeeping chores. + +The 'klog debugging functions' patch (klog.patch in the relay-apps +tarball) provides a couple of high-level logging functions to the +kernel which allow writing formatted text or raw data to a channel, +regardless of whether a channel to write into exists or not, or even +whether the relay interface is compiled into the kernel or not. These +functions allow you to put unconditional 'trace' statements anywhere +in the kernel or kernel modules; only when there is a 'klog handler' +registered will data actually be logged (see the klog and kleak +examples for details). + +It is of course possible to use the relay interface from scratch, +i.e. without using any of the relay-apps example code or klog, but +you'll have to implement communication between userspace and kernel, +allowing both to convey the state of buffers (full, empty, amount of +padding). The read() interface both removes padding and internally +consumes the read sub-buffers; thus in cases where read(2) is being +used to drain the channel buffers, special-purpose communication +between kernel and user isn't necessary for basic operation. Things +such as buffer-full conditions would still need to be communicated via +some channel though. + +klog and the relay-apps examples can be found in the relay-apps +tarball on http://relayfs.sourceforge.net + +The relay interface user space API +================================== + +The relay interface implements basic file operations for user space +access to relay channel buffer data. Here are the file operations +that are available and some comments regarding their behavior: + +open() enables user to open an _existing_ channel buffer. + +mmap() results in channel buffer being mapped into the caller's + memory space. Note that you can't do a partial mmap - you + must map the entire file, which is NRBUF * SUBBUFSIZE. + +read() read the contents of a channel buffer. The bytes read are + 'consumed' by the reader, i.e. they won't be available + again to subsequent reads. If the channel is being used + in no-overwrite mode (the default), it can be read at any + time even if there's an active kernel writer. If the + channel is being used in overwrite mode and there are + active channel writers, results may be unpredictable - + users should make sure that all logging to the channel has + ended before using read() with overwrite mode. Sub-buffer + padding is automatically removed and will not be seen by + the reader. + +sendfile() transfer data from a channel buffer to an output file + descriptor. Sub-buffer padding is automatically removed + and will not be seen by the reader. + +poll() POLLIN/POLLRDNORM/POLLERR supported. User applications are + notified when sub-buffer boundaries are crossed. + +close() decrements the channel buffer's refcount. When the refcount + reaches 0, i.e. when no process or kernel client has the + buffer open, the channel buffer is freed. + +In order for a user application to make use of relay files, the +host filesystem must be mounted. For example, + + mount -t debugfs debugfs /debug + +NOTE: the host filesystem doesn't need to be mounted for kernel + clients to create or use channels - it only needs to be + mounted when user space applications need access to the buffer + data. + + +The relay interface kernel API +============================== + +Here's a summary of the API the relay interface provides to in-kernel clients: + +TBD(curr. line MT:/API/) + channel management functions: + + relay_open(base_filename, parent, subbuf_size, n_subbufs, + callbacks) + relay_close(chan) + relay_flush(chan) + relay_reset(chan) + + channel management typically called on instigation of userspace: + + relay_subbufs_consumed(chan, cpu, subbufs_consumed) + + write functions: + + relay_write(chan, data, length) + __relay_write(chan, data, length) + relay_reserve(chan, length) + + callbacks: + + subbuf_start(buf, subbuf, prev_subbuf, prev_padding) + buf_mapped(buf, filp) + buf_unmapped(buf, filp) + create_buf_file(filename, parent, mode, buf, is_global) + remove_buf_file(dentry) + + helper functions: + + relay_buf_full(buf) + subbuf_start_reserve(buf, length) + + +Creating a channel +------------------ + +relay_open() is used to create a channel, along with its per-cpu +channel buffers. Each channel buffer will have an associated file +created for it in the host filesystem, which can be and mmapped or +read from in user space. The files are named basename0...basenameN-1 +where N is the number of online cpus, and by default will be created +in the root of the filesystem (if the parent param is NULL). If you +want a directory structure to contain your relay files, you should +create it using the host filesystem's directory creation function, +e.g. debugfs_create_dir(), and pass the parent directory to +relay_open(). Users are responsible for cleaning up any directory +structure they create, when the channel is closed - again the host +filesystem's directory removal functions should be used for that, +e.g. debugfs_remove(). + +In order for a channel to be created and the host filesystem's files +associated with its channel buffers, the user must provide definitions +for two callback functions, create_buf_file() and remove_buf_file(). +create_buf_file() is called once for each per-cpu buffer from +relay_open() and allows the user to create the file which will be used +to represent the corresponding channel buffer. The callback should +return the dentry of the file created to represent the channel buffer. +remove_buf_file() must also be defined; it's responsible for deleting +the file(s) created in create_buf_file() and is called during +relay_close(). + +Here are some typical definitions for these callbacks, in this case +using debugfs: + +/* + * create_buf_file() callback. Creates relay file in debugfs. + */ +static struct dentry *create_buf_file_handler(const char *filename, + struct dentry *parent, + int mode, + struct rchan_buf *buf, + int *is_global) +{ + return debugfs_create_file(filename, mode, parent, buf, + &relay_file_operations); +} + +/* + * remove_buf_file() callback. Removes relay file from debugfs. + */ +static int remove_buf_file_handler(struct dentry *dentry) +{ + debugfs_remove(dentry); + + return 0; +} + +/* + * relay interface callbacks + */ +static struct rchan_callbacks relay_callbacks = +{ + .create_buf_file = create_buf_file_handler, + .remove_buf_file = remove_buf_file_handler, +}; + +And an example relay_open() invocation using them: + + chan = relay_open("cpu", NULL, SUBBUF_SIZE, N_SUBBUFS, &relay_callbacks); + +If the create_buf_file() callback fails, or isn't defined, channel +creation and thus relay_open() will fail. + +The total size of each per-cpu buffer is calculated by multiplying the +number of sub-buffers by the sub-buffer size passed into relay_open(). +The idea behind sub-buffers is that they're basically an extension of +double-buffering to N buffers, and they also allow applications to +easily implement random-access-on-buffer-boundary schemes, which can +be important for some high-volume applications. The number and size +of sub-buffers is completely dependent on the application and even for +the same application, different conditions will warrant different +values for these parameters at different times. Typically, the right +values to use are best decided after some experimentation; in general, +though, it's safe to assume that having only 1 sub-buffer is a bad +idea - you're guaranteed to either overwrite data or lose events +depending on the channel mode being used. + +The create_buf_file() implementation can also be defined in such a way +as to allow the creation of a single 'global' buffer instead of the +default per-cpu set. This can be useful for applications interested +mainly in seeing the relative ordering of system-wide events without +the need to bother with saving explicit timestamps for the purpose of +merging/sorting per-cpu files in a postprocessing step. + +To have relay_open() create a global buffer, the create_buf_file() +implementation should set the value of the is_global outparam to a +non-zero value in addition to creating the file that will be used to +represent the single buffer. In the case of a global buffer, +create_buf_file() and remove_buf_file() will be called only once. The +normal channel-writing functions, e.g. relay_write(), can still be +used - writes from any cpu will transparently end up in the global +buffer - but since it is a global buffer, callers should make sure +they use the proper locking for such a buffer, either by wrapping +writes in a spinlock, or by copying a write function from relay.h and +creating a local version that internally does the proper locking. + +Channel 'modes' +--------------- + +relay channels can be used in either of two modes - 'overwrite' or +'no-overwrite'. The mode is entirely determined by the implementation +of the subbuf_start() callback, as described below. The default if no +subbuf_start() callback is defined is 'no-overwrite' mode. If the +default mode suits your needs, and you plan to use the read() +interface to retrieve channel data, you can ignore the details of this +section, as it pertains mainly to mmap() implementations. + +In 'overwrite' mode, also known as 'flight recorder' mode, writes +continuously cycle around the buffer and will never fail, but will +unconditionally overwrite old data regardless of whether it's actually +been consumed. In no-overwrite mode, writes will fail, i.e. data will +be lost, if the number of unconsumed sub-buffers equals the total +number of sub-buffers in the channel. It should be clear that if +there is no consumer or if the consumer can't consume sub-buffers fast +enough, data will be lost in either case; the only difference is +whether data is lost from the beginning or the end of a buffer. + +As explained above, a relay channel is made of up one or more +per-cpu channel buffers, each implemented as a circular buffer +subdivided into one or more sub-buffers. Messages are written into +the current sub-buffer of the channel's current per-cpu buffer via the +write functions described below. Whenever a message can't fit into +the current sub-buffer, because there's no room left for it, the +client is notified via the subbuf_start() callback that a switch to a +new sub-buffer is about to occur. The client uses this callback to 1) +initialize the next sub-buffer if appropriate 2) finalize the previous +sub-buffer if appropriate and 3) return a boolean value indicating +whether or not to actually move on to the next sub-buffer. + +To implement 'no-overwrite' mode, the userspace client would provide +an implementation of the subbuf_start() callback something like the +following: + +static int subbuf_start(struct rchan_buf *buf, + void *subbuf, + void *prev_subbuf, + unsigned int prev_padding) +{ + if (prev_subbuf) + *((unsigned *)prev_subbuf) = prev_padding; + + if (relay_buf_full(buf)) + return 0; + + subbuf_start_reserve(buf, sizeof(unsigned int)); + + return 1; +} + +If the current buffer is full, i.e. all sub-buffers remain unconsumed, +the callback returns 0 to indicate that the buffer switch should not +occur yet, i.e. until the consumer has had a chance to read the +current set of ready sub-buffers. For the relay_buf_full() function +to make sense, the consumer is reponsible for notifying the relay +interface when sub-buffers have been consumed via +relay_subbufs_consumed(). Any subsequent attempts to write into the +buffer will again invoke the subbuf_start() callback with the same +parameters; only when the consumer has consumed one or more of the +ready sub-buffers will relay_buf_full() return 0, in which case the +buffer switch can continue. + +The implementation of the subbuf_start() callback for 'overwrite' mode +would be very similar: + +static int subbuf_start(struct rchan_buf *buf, + void *subbuf, + void *prev_subbuf, + unsigned int prev_padding) +{ + if (prev_subbuf) + *((unsigned *)prev_subbuf) = prev_padding; + + subbuf_start_reserve(buf, sizeof(unsigned int)); + + return 1; +} + +In this case, the relay_buf_full() check is meaningless and the +callback always returns 1, causing the buffer switch to occur +unconditionally. It's also meaningless for the client to use the +relay_subbufs_consumed() function in this mode, as it's never +consulted. + +The default subbuf_start() implementation, used if the client doesn't +define any callbacks, or doesn't define the subbuf_start() callback, +implements the simplest possible 'no-overwrite' mode, i.e. it does +nothing but return 0. + +Header information can be reserved at the beginning of each sub-buffer +by calling the subbuf_start_reserve() helper function from within the +subbuf_start() callback. This reserved area can be used to store +whatever information the client wants. In the example above, room is +reserved in each sub-buffer to store the padding count for that +sub-buffer. This is filled in for the previous sub-buffer in the +subbuf_start() implementation; the padding value for the previous +sub-buffer is passed into the subbuf_start() callback along with a +pointer to the previous sub-buffer, since the padding value isn't +known until a sub-buffer is filled. The subbuf_start() callback is +also called for the first sub-buffer when the channel is opened, to +give the client a chance to reserve space in it. In this case the +previous sub-buffer pointer passed into the callback will be NULL, so +the client should check the value of the prev_subbuf pointer before +writing into the previous sub-buffer. + +Writing to a channel +-------------------- + +Kernel clients write data into the current cpu's channel buffer using +relay_write() or __relay_write(). relay_write() is the main logging +function - it uses local_irqsave() to protect the buffer and should be +used if you might be logging from interrupt context. If you know +you'll never be logging from interrupt context, you can use +__relay_write(), which only disables preemption. These functions +don't return a value, so you can't determine whether or not they +failed - the assumption is that you wouldn't want to check a return +value in the fast logging path anyway, and that they'll always succeed +unless the buffer is full and no-overwrite mode is being used, in +which case you can detect a failed write in the subbuf_start() +callback by calling the relay_buf_full() helper function. + +relay_reserve() is used to reserve a slot in a channel buffer which +can be written to later. This would typically be used in applications +that need to write directly into a channel buffer without having to +stage data in a temporary buffer beforehand. Because the actual write +may not happen immediately after the slot is reserved, applications +using relay_reserve() can keep a count of the number of bytes actually +written, either in space reserved in the sub-buffers themselves or as +a separate array. See the 'reserve' example in the relay-apps tarball +at http://relayfs.sourceforge.net for an example of how this can be +done. Because the write is under control of the client and is +separated from the reserve, relay_reserve() doesn't protect the buffer +at all - it's up to the client to provide the appropriate +synchronization when using relay_reserve(). + +Closing a channel +----------------- + +The client calls relay_close() when it's finished using the channel. +The channel and its associated buffers are destroyed when there are no +longer any references to any of the channel buffers. relay_flush() +forces a sub-buffer switch on all the channel buffers, and can be used +to finalize and process the last sub-buffers before the channel is +closed. + +Misc +---- + +Some applications may want to keep a channel around and re-use it +rather than open and close a new channel for each use. relay_reset() +can be used for this purpose - it resets a channel to its initial +state without reallocating channel buffer memory or destroying +existing mappings. It should however only be called when it's safe to +do so, i.e. when the channel isn't currently being written to. + +Finally, there are a couple of utility callbacks that can be used for +different purposes. buf_mapped() is called whenever a channel buffer +is mmapped from user space and buf_unmapped() is called when it's +unmapped. The client can use this notification to trigger actions +within the kernel application, such as enabling/disabling logging to +the channel. + + +Resources +========= + +For news, example code, mailing list, etc. see the relay interface homepage: + + http://relayfs.sourceforge.net + + +Credits +======= + +The ideas and specs for the relay interface came about as a result of +discussions on tracing involving the following: + +Michel Dagenais <michel.dagenais@polymtl.ca> +Richard Moore <richardj_moore@uk.ibm.com> +Bob Wisniewski <bob@watson.ibm.com> +Karim Yaghmour <karim@opersys.com> +Tom Zanussi <zanussi@us.ibm.com> + +Also thanks to Hubertus Franke for a lot of useful suggestions and bug +reports. diff --git a/Documentation/hwmon/abituguru b/Documentation/hwmon/abituguru new file mode 100644 index 000000000..b2c0d61b3 --- /dev/null +++ b/Documentation/hwmon/abituguru @@ -0,0 +1,87 @@ +Kernel driver abituguru +======================= + +Supported chips: + * Abit uGuru revision 1-3 (Hardware Monitor part only) + Prefix: 'abituguru' + Addresses scanned: ISA 0x0E0 + Datasheet: Not available, this driver is based on reverse engineering. + A "Datasheet" has been written based on the reverse engineering it + should be available in the same dir as this file under the name + abituguru-datasheet. + Note: + The uGuru is a microcontroller with onboard firmware which programs + it to behave as a hwmon IC. There are many different revisions of the + firmware and thus effectivly many different revisions of the uGuru. + Below is an incomplete list with which revisions are used for which + Motherboards: + uGuru 1.00 ~ 1.24 (AI7, KV8-MAX3, AN7) (1) + uGuru 2.0.0.0 ~ 2.0.4.2 (KV8-PRO) + uGuru 2.1.0.0 ~ 2.1.2.8 (AS8, AV8, AA8, AG8, AA8XE, AX8) + uGuru 2.2.0.0 ~ 2.2.0.6 (AA8 Fatal1ty) + uGuru 2.3.0.0 ~ 2.3.0.9 (AN8) + uGuru 3.0.0.0 ~ 3.0.1.2 (AW8, AL8, NI8) + uGuru 4.xxxxx? (AT8 32X) (2) + 1) For revisions 2 and 3 uGuru's the driver can autodetect the + sensortype (Volt or Temp) for bank1 sensors, for revision 1 uGuru's + this doesnot always work. For these uGuru's the autodection can + be overriden with the bank1_types module param. For all 3 known + revison 1 motherboards the correct use of this param is: + bank1_types=1,1,0,0,0,0,0,2,0,0,0,0,2,0,0,1 + You may also need to specify the fan_sensors option for these boards + fan_sensors=5 + 2) The current version of the abituguru driver is known to NOT work + on these Motherboards + +Authors: + Hans de Goede <j.w.r.degoede@hhs.nl>, + (Initial reverse engineering done by Olle Sandberg + <ollebull@gmail.com>) + + +Module Parameters +----------------- + +* force: bool Force detection. Note this parameter only causes the + detection to be skipped, if the uGuru can't be read + the module initialization (insmod) will still fail. +* bank1_types: int[] Bank1 sensortype autodetection override: + -1 autodetect (default) + 0 volt sensor + 1 temp sensor + 2 not connected +* fan_sensors: int Tell the driver how many fan speed sensors there are + on your motherboard. Default: 0 (autodetect). +* pwms: int Tell the driver how many fan speed controls (fan + pwms) your motherboard has. Default: 0 (autodetect). +* verbose: int How verbose should the driver be? (0-3): + 0 normal output + 1 + verbose error reporting + 2 + sensors type probing info (default) + 3 + retryable error reporting + Default: 2 (the driver is still in the testing phase) + +Notice if you need any of the first three options above please insmod the +driver with verbose set to 3 and mail me <j.w.r.degoede@hhs.nl> the output of: +dmesg | grep abituguru + + +Description +----------- + +This driver supports the hardware monitoring features of the Abit uGuru chip +found on Abit uGuru featuring motherboards (most modern Abit motherboards). + +The uGuru chip in reality is a Winbond W83L950D in disguise (despite Abit +claiming it is "a new microprocessor designed by the ABIT Engineers"). +Unfortunatly this doesn't help since the W83L950D is a generic +microcontroller with a custom Abit application running on it. + +Despite Abit not releasing any information regarding the uGuru, Olle +Sandberg <ollebull@gmail.com> has managed to reverse engineer the sensor part +of the uGuru. Without his work this driver would not have been possible. + +Known Issues +------------ + +The voltage and frequency control parts of the Abit uGuru are not supported. diff --git a/Documentation/hwmon/abituguru-datasheet b/Documentation/hwmon/abituguru-datasheet new file mode 100644 index 000000000..aef5a9b36 --- /dev/null +++ b/Documentation/hwmon/abituguru-datasheet @@ -0,0 +1,312 @@ +uGuru datasheet +=============== + +First of all, what I know about uGuru is no fact based on any help, hints or +datasheet from Abit. The data I have got on uGuru have I assembled through +my weak knowledge in "backwards engineering". +And just for the record, you may have noticed uGuru isn't a chip developed by +Abit, as they claim it to be. It's realy just an microprocessor (uC) created by +Winbond (W83L950D). And no, reading the manual for this specific uC or +mailing Windbond for help won't give any usefull data about uGuru, as it is +the program inside the uC that is responding to calls. + +Olle Sandberg <ollebull@gmail.com>, 2005-05-25 + + +Original version by Olle Sandberg who did the heavy lifting of the initial +reverse engineering. This version has been almost fully rewritten for clarity +and extended with write support and info on more databanks, the write support +is once again reverse engineered by Olle the additional databanks have been +reverse engineered by me. I would like to express my thanks to Olle, this +document and the Linux driver could not have been written without his efforts. + +Note: because of the lack of specs only the sensors part of the uGuru is +described here and not the CPU / RAM / etc voltage & frequency control. + +Hans de Goede <j.w.r.degoede@hhs.nl>, 28-01-2006 + + +Detection +========= + +As far as known the uGuru is always placed at and using the (ISA) I/O-ports +0xE0 and 0xE4, so we don't have to scan any port-range, just check what the two +ports are holding for detection. We will refer to 0xE0 as CMD (command-port) +and 0xE4 as DATA because Abit refers to them with these names. + +If DATA holds 0x00 or 0x08 and CMD holds 0x00 or 0xAC an uGuru could be +present. We have to check for two different values at data-port, because +after a reboot uGuru will hold 0x00 here, but if the driver is removed and +later on attached again data-port will hold 0x08, more about this later. + +After wider testing of the Linux kernel driver some variants of the uGuru have +turned up which will hold 0x00 instead of 0xAC at the CMD port, thus we also +have to test CMD for two different values. On these uGuru's DATA will initally +hold 0x09 and will only hold 0x08 after reading CMD first, so CMD must be read +first! + +To be really sure an uGuru is present a test read of one or more register +sets should be done. + + +Reading / Writing +================= + +Addressing +---------- + +The uGuru has a number of different addressing levels. The first addressing +level we will call banks. A bank holds data for one or more sensors. The data +in a bank for a sensor is one or more bytes large. + +The number of bytes is fixed for a given bank, you should always read or write +that many bytes, reading / writing more will fail, the results when writing +less then the number of bytes for a given bank are undetermined. + +See below for all known bank addresses, numbers of sensors in that bank, +number of bytes data per sensor and contents/meaning of those bytes. + +Although both this document and the kernel driver have kept the sensor +terminoligy for the addressing within a bank this is not 100% correct, in +bank 0x24 for example the addressing within the bank selects a PWM output not +a sensor. + +Notice that some banks have both a read and a write address this is how the +uGuru determines if a read from or a write to the bank is taking place, thus +when reading you should always use the read address and when writing the +write address. The write address is always one (1) more then the read address. + + +uGuru ready +----------- + +Before you can read from or write to the uGuru you must first put the uGuru +in "ready" mode. + +To put the uGuru in ready mode first write 0x00 to DATA and then wait for DATA +to hold 0x09, DATA should read 0x09 within 250 read cycles. + +Next CMD _must_ be read and should hold 0xAC, usually CMD will hold 0xAC the +first read but sometimes it takes a while before CMD holds 0xAC and thus it +has to be read a number of times (max 50). + +After reading CMD, DATA should hold 0x08 which means that the uGuru is ready +for input. As above DATA will usually hold 0x08 the first read but not always. +This step can be skipped, but it is undetermined what happens if the uGuru has +not yet reported 0x08 at DATA and you proceed with writing a bank address. + + +Sending bank and sensor addresses to the uGuru +---------------------------------------------- + +First the uGuru must be in "ready" mode as described above, DATA should hold +0x08 indicating that the uGuru wants input, in this case the bank address. + +Next write the bank address to DATA. After the bank address has been written +wait for to DATA to hold 0x08 again indicating that it wants / is ready for +more input (max 250 reads). + +Once DATA holds 0x08 again write the sensor address to CMD. + + +Reading +------- + +First send the bank and sensor addresses as described above. +Then for each byte of data you want to read wait for DATA to hold 0x01 +which indicates that the uGuru is ready to be read (max 250 reads) and once +DATA holds 0x01 read the byte from CMD. + +Once all bytes have been read data will hold 0x09, but there is no reason to +test for this. Notice that the number of bytes is bank address dependent see +above and below. + +After completing a successfull read it is advised to put the uGuru back in +ready mode, so that it is ready for the next read / write cycle. This way +if your program / driver is unloaded and later loaded again the detection +algorithm described above will still work. + + + +Writing +------- + +First send the bank and sensor addresses as described above. +Then for each byte of data you want to write wait for DATA to hold 0x00 +which indicates that the uGuru is ready to be written (max 250 reads) and +once DATA holds 0x00 write the byte to CMD. + +Once all bytes have been written wait for DATA to hold 0x01 (max 250 reads) +don't ask why this is the way it is. + +Once DATA holds 0x01 read CMD it should hold 0xAC now. + +After completing a successfull write it is advised to put the uGuru back in +ready mode, so that it is ready for the next read / write cycle. This way +if your program / driver is unloaded and later loaded again the detection +algorithm described above will still work. + + +Gotchas +------- + +After wider testing of the Linux kernel driver some variants of the uGuru have +turned up which do not hold 0x08 at DATA within 250 reads after writing the +bank address. With these versions this happens quite frequent, using larger +timeouts doesn't help, they just go offline for a second or 2, doing some +internal callibration or whatever. Your code should be prepared to handle +this and in case of no response in this specific case just goto sleep for a +while and then retry. + + +Address Map +=========== + +Bank 0x20 Alarms (R) +-------------------- +This bank contains 0 sensors, iow the sensor address is ignored (but must be +written) just use 0. Bank 0x20 contains 3 bytes: + +Byte 0: +This byte holds the alarm flags for sensor 0-7 of Sensor Bank1, with bit 0 +corresponding to sensor 0, 1 to 1, etc. + +Byte 1: +This byte holds the alarm flags for sensor 8-15 of Sensor Bank1, with bit 0 +corresponding to sensor 8, 1 to 9, etc. + +Byte 2: +This byte holds the alarm flags for sensor 0-5 of Sensor Bank2, with bit 0 +corresponding to sensor 0, 1 to 1, etc. + + +Bank 0x21 Sensor Bank1 Values / Readings (R) +-------------------------------------------- +This bank contains 16 sensors, for each sensor it contains 1 byte. +So far the following sensors are known to be available on all motherboards: +Sensor 0 CPU temp +Sensor 1 SYS temp +Sensor 3 CPU core volt +Sensor 4 DDR volt +Sensor 10 DDR Vtt volt +Sensor 15 PWM temp + +Byte 0: +This byte holds the reading from the sensor. Sensors in Bank1 can be both +volt and temp sensors, this is motherboard specific. The uGuru however does +seem to know (be programmed with) what kindoff sensor is attached see Sensor +Bank1 Settings description. + +Volt sensors use a linear scale, a reading 0 corresponds with 0 volt and a +reading of 255 with 3494 mV. The sensors for higher voltages however are +connected through a division circuit. The currently known division circuits +in use result in ranges of: 0-4361mV, 0-6248mV or 0-14510mV. 3.3 volt sources +use the 0-4361mV range, 5 volt the 0-6248mV and 12 volt the 0-14510mV . + +Temp sensors also use a linear scale, a reading of 0 corresponds with 0 degree +Celsius and a reading of 255 with a reading of 255 degrees Celsius. + + +Bank 0x22 Sensor Bank1 Settings (R) +Bank 0x23 Sensor Bank1 Settings (W) +----------------------------------- + +This bank contains 16 sensors, for each sensor it contains 3 bytes. Each +set of 3 bytes contains the settings for the sensor with the same sensor +address in Bank 0x21 . + +Byte 0: +Alarm behaviour for the selected sensor. A 1 enables the described behaviour. +Bit 0: Give an alarm if measured temp is over the warning threshold (RW) * +Bit 1: Give an alarm if measured volt is over the max threshold (RW) ** +Bit 2: Give an alarm if measured volt is under the min threshold (RW) ** +Bit 3: Beep if alarm (RW) +Bit 4: 1 if alarm cause measured temp is over the warning threshold (R) +Bit 5: 1 if alarm cause measured volt is over the max threshold (R) +Bit 6: 1 if alarm cause measured volt is under the min threshold (R) +Bit 7: Volt sensor: Shutdown if alarm persist for more then 4 seconds (RW) + Temp sensor: Shutdown if temp is over the shutdown threshold (RW) + +* This bit is only honored/used by the uGuru if a temp sensor is connected +** This bit is only honored/used by the uGuru if a volt sensor is connected +Note with some trickery this can be used to find out what kinda sensor is +detected see the Linux kernel driver for an example with many comments on +how todo this. + +Byte 1: +Temp sensor: warning threshold (scale as bank 0x21) +Volt sensor: min threshold (scale as bank 0x21) + +Byte 2: +Temp sensor: shutdown threshold (scale as bank 0x21) +Volt sensor: max threshold (scale as bank 0x21) + + +Bank 0x24 PWM outputs for FAN's (R) +Bank 0x25 PWM outputs for FAN's (W) +----------------------------------- + +This bank contains 3 "sensors", for each sensor it contains 5 bytes. +Sensor 0 usually controls the CPU fan +Sensor 1 usually controls the NB (or chipset for single chip) fan +Sensor 2 usually controls the System fan + +Byte 0: +Flag 0x80 to enable control, Fan runs at 100% when disabled. +low nibble (temp)sensor address at bank 0x21 used for control. + +Byte 1: +0-255 = 0-12v (linear), specify voltage at which fan will rotate when under +low threshold temp (specified in byte 3) + +Byte 2: +0-255 = 0-12v (linear), specify voltage at which fan will rotate when above +high threshold temp (specified in byte 4) + +Byte 3: +Low threshold temp (scale as bank 0x21) + +byte 4: +High threshold temp (scale as bank 0x21) + + +Bank 0x26 Sensors Bank2 Values / Readings (R) +--------------------------------------------- + +This bank contains 6 sensors (AFAIK), for each sensor it contains 1 byte. +So far the following sensors are known to be available on all motherboards: +Sensor 0: CPU fan speed +Sensor 1: NB (or chipset for single chip) fan speed +Sensor 2: SYS fan speed + +Byte 0: +This byte holds the reading from the sensor. 0-255 = 0-15300 (linear) + + +Bank 0x27 Sensors Bank2 Settings (R) +Bank 0x28 Sensors Bank2 Settings (W) +------------------------------------ + +This bank contains 6 sensors (AFAIK), for each sensor it contains 2 bytes. + +Byte 0: +Alarm behaviour for the selected sensor. A 1 enables the described behaviour. +Bit 0: Give an alarm if measured rpm is under the min threshold (RW) +Bit 3: Beep if alarm (RW) +Bit 7: Shutdown if alarm persist for more then 4 seconds (RW) + +Byte 1: +min threshold (scale as bank 0x26) + + +Warning for the adventerous +=========================== + +A word of caution to those who want to experiment and see if they can figure +the voltage / clock programming out, I tried reading and only reading banks +0-0x30 with the reading code used for the sensor banks (0x20-0x28) and this +resulted in a _permanent_ reprogramming of the voltages, luckily I had the +sensors part configured so that it would shutdown my system on any out of spec +voltages which proprably safed my computer (after a reboot I managed to +immediatly enter the bios and reload the defaults). This probably means that +the read/write cycle for the non sensor part is different from the sensor part. diff --git a/Documentation/hwmon/lm70 b/Documentation/hwmon/lm70 new file mode 100644 index 000000000..2bdd3feeb --- /dev/null +++ b/Documentation/hwmon/lm70 @@ -0,0 +1,31 @@ +Kernel driver lm70 +================== + +Supported chip: + * National Semiconductor LM70 + Datasheet: http://www.national.com/pf/LM/LM70.html + +Author: + Kaiwan N Billimoria <kaiwan@designergraphix.com> + +Description +----------- + +This driver implements support for the National Semiconductor LM70 +temperature sensor. + +The LM70 temperature sensor chip supports a single temperature sensor. +It communicates with a host processor (or microcontroller) via an +SPI/Microwire Bus interface. + +Communication with the LM70 is simple: when the temperature is to be sensed, +the driver accesses the LM70 using SPI communication: 16 SCLK cycles +comprise the MOSI/MISO loop. At the end of the transfer, the 11-bit 2's +complement digital temperature (sent via the SIO line), is available in the +driver for interpretation. This driver makes use of the kernel's in-core +SPI support. + +Thanks to +--------- +Jean Delvare <khali@linux-fr.org> for mentoring the hwmon-side driver +development. diff --git a/Documentation/hwmon/smsc47m192 b/Documentation/hwmon/smsc47m192 new file mode 100644 index 000000000..45d6453cd --- /dev/null +++ b/Documentation/hwmon/smsc47m192 @@ -0,0 +1,102 @@ +Kernel driver smsc47m192 +======================== + +Supported chips: + * SMSC LPC47M192 and LPC47M997 + Prefix: 'smsc47m192' + Addresses scanned: I2C 0x2c - 0x2d + Datasheet: The datasheet for LPC47M192 is publicly available from + http://www.smsc.com/ + The LPC47M997 is compatible for hardware monitoring. + +Author: Hartmut Rick <linux@rick.claranet.de> + Special thanks to Jean Delvare for careful checking + of the code and many helpful comments and suggestions. + + +Description +----------- + +This driver implements support for the hardware sensor capabilities +of the SMSC LPC47M192 and LPC47M997 Super-I/O chips. + +These chips support 3 temperature channels and 8 voltage inputs +as well as CPU voltage VID input. + +They do also have fan monitoring and control capabilities, but the +these features are accessed via ISA bus and are not supported by this +driver. Use the 'smsc47m1' driver for fan monitoring and control. + +Voltages and temperatures are measured by an 8-bit ADC, the resolution +of the temperatures is 1 bit per degree C. +Voltages are scaled such that the nominal voltage corresponds to +192 counts, i.e. 3/4 of the full range. Thus the available range for +each voltage channel is 0V ... 255/192*(nominal voltage), the resolution +is 1 bit per (nominal voltage)/192. +Both voltage and temperature values are scaled by 1000, the sys files +show voltages in mV and temperatures in units of 0.001 degC. + +The +12V analog voltage input channel (in4_input) is multiplexed with +bit 4 of the encoded CPU voltage. This means that you either get +a +12V voltage measurement or a 5 bit CPU VID, but not both. +The default setting is to use the pin as 12V input, and use only 4 bit VID. +This driver assumes that the information in the configuration register +is correct, i.e. that the BIOS has updated the configuration if +the motherboard has this input wired to VID4. + +The temperature and voltage readings are updated once every 1.5 seconds. +Reading them more often repeats the same values. + + +sysfs interface +--------------- + +in0_input - +2.5V voltage input +in1_input - CPU voltage input (nominal 2.25V) +in2_input - +3.3V voltage input +in3_input - +5V voltage input +in4_input - +12V voltage input (may be missing if used as VID4) +in5_input - Vcc voltage input (nominal 3.3V) + This is the supply voltage of the sensor chip itself. +in6_input - +1.5V voltage input +in7_input - +1.8V voltage input + +in[0-7]_min, +in[0-7]_max - lower and upper alarm thresholds for in[0-7]_input reading + + All voltages are read and written in mV. + +in[0-7]_alarm - alarm flags for voltage inputs + These files read '1' in case of alarm, '0' otherwise. + +temp1_input - chip temperature measured by on-chip diode +temp[2-3]_input - temperature measured by external diodes (one of these would + typically be wired to the diode inside the CPU) + +temp[1-3]_min, +temp[1-3]_max - lower and upper alarm thresholds for temperatures + +temp[1-3]_offset - temperature offset registers + The chip adds the offsets stored in these registers to + the corresponding temperature readings. + Note that temp1 and temp2 offsets share the same register, + they cannot both be different from zero at the same time. + Writing a non-zero number to one of them will reset the other + offset to zero. + + All temperatures and offsets are read and written in + units of 0.001 degC. + +temp[1-3]_alarm - alarm flags for temperature inputs, '1' in case of alarm, + '0' otherwise. +temp[2-3]_input_fault - diode fault flags for temperature inputs 2 and 3. + A fault is detected if the two pins for the corresponding + sensor are open or shorted, or any of the two is shorted + to ground or Vcc. '1' indicates a diode fault. + +cpu0_vid - CPU voltage as received from the CPU + +vrm - CPU VID standard used for decoding CPU voltage + + The *_min, *_max, *_offset and vrm files can be read and + written, all others are read-only. diff --git a/Documentation/hwmon/w83791d b/Documentation/hwmon/w83791d new file mode 100644 index 000000000..83a383628 --- /dev/null +++ b/Documentation/hwmon/w83791d @@ -0,0 +1,113 @@ +Kernel driver w83791d +===================== + +Supported chips: + * Winbond W83791D + Prefix: 'w83791d' + Addresses scanned: I2C 0x2c - 0x2f + Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83791Da.pdf + +Author: Charles Spirakis <bezaur@gmail.com> + +This driver was derived from the w83781d.c and w83792d.c source files. + +Credits: + w83781d.c: + Frodo Looijaard <frodol@dds.nl>, + Philip Edelbrock <phil@netroedge.com>, + and Mark Studebaker <mdsxyz123@yahoo.com> + w83792d.c: + Chunhao Huang <DZShen@Winbond.com.tw>, + Rudolf Marek <r.marek@sh.cvut.cz> + +Module Parameters +----------------- + +* init boolean + (default 0) + Use 'init=1' to have the driver do extra software initializations. + The default behavior is to do the minimum initialization possible + and depend on the BIOS to properly setup the chip. If you know you + have a w83791d and you're having problems, try init=1 before trying + reset=1. + +* reset boolean + (default 0) + Use 'reset=1' to reset the chip (via index 0x40, bit 7). The default + behavior is no chip reset to preserve BIOS settings. + +* force_subclients=bus,caddr,saddr,saddr + This is used to force the i2c addresses for subclients of + a certain chip. Example usage is `force_subclients=0,0x2f,0x4a,0x4b' + to force the subclients of chip 0x2f on bus 0 to i2c addresses + 0x4a and 0x4b. + + +Description +----------- + +This driver implements support for the Winbond W83791D chip. + +Detection of the chip can sometimes be foiled because it can be in an +internal state that allows no clean access (Bank with ID register is not +currently selected). If you know the address of the chip, use a 'force' +parameter; this will put it into a more well-behaved state first. + +The driver implements three temperature sensors, five fan rotation speed +sensors, and ten voltage sensors. + +Temperatures are measured in degrees Celsius and measurement resolution is 1 +degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when +the temperature gets higher than the Overtemperature Shutdown value; it stays +on until the temperature falls below the Hysteresis value. + +Fan rotation speeds are reported in RPM (rotations per minute). An alarm is +triggered if the rotation speed has dropped below a programmable limit. Fan +readings can be divided by a programmable divider (1, 2, 4, 8 for fan 1/2/3 +and 1, 2, 4, 8, 16, 32, 64 or 128 for fan 4/5) to give the readings more +range or accuracy. + +Voltage sensors (also known as IN sensors) report their values in millivolts. +An alarm is triggered if the voltage has crossed a programmable minimum +or maximum limit. + +Alarms are provided as output from a "realtime status register". The +following bits are defined: + +bit - alarm on: +0 - Vcore +1 - VINR0 +2 - +3.3VIN +3 - 5VDD +4 - temp1 +5 - temp2 +6 - fan1 +7 - fan2 +8 - +12VIN +9 - -12VIN +10 - -5VIN +11 - fan3 +12 - chassis +13 - temp3 +14 - VINR1 +15 - reserved +16 - tart1 +17 - tart2 +18 - tart3 +19 - VSB +20 - VBAT +21 - fan4 +22 - fan5 +23 - reserved + +When an alarm goes off, you can be warned by a beeping signal through your +computer speaker. It is possible to enable all beeping globally, or only +the beeping for some alarms. + +The driver only reads the chip values each 3 seconds; reading them more +often will do no harm, but will return 'old' values. + +W83791D TODO: +--------------- +Provide a patch for per-file alarms as discussed on the mailing list +Provide a patch for smart-fan control (still need appropriate motherboard/fans) diff --git a/Documentation/i2c/busses/i2c-ocores b/Documentation/i2c/busses/i2c-ocores new file mode 100644 index 000000000..cfcebb10d --- /dev/null +++ b/Documentation/i2c/busses/i2c-ocores @@ -0,0 +1,51 @@ +Kernel driver i2c-ocores + +Supported adapters: + * OpenCores.org I2C controller by Richard Herveille (see datasheet link) + Datasheet: http://www.opencores.org/projects.cgi/web/i2c/overview + +Author: Peter Korsgaard <jacmet@sunsite.dk> + +Description +----------- + +i2c-ocores is an i2c bus driver for the OpenCores.org I2C controller +IP core by Richard Herveille. + +Usage +----- + +i2c-ocores uses the platform bus, so you need to provide a struct +platform_device with the base address and interrupt number. The +dev.platform_data of the device should also point to a struct +ocores_i2c_platform_data (see linux/i2c-ocores.h) describing the +distance between registers and the input clock speed. + +E.G. something like: + +static struct resource ocores_resources[] = { + [0] = { + .start = MYI2C_BASEADDR, + .end = MYI2C_BASEADDR + 8, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = MYI2C_IRQ, + .end = MYI2C_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct ocores_i2c_platform_data myi2c_data = { + .regstep = 2, /* two bytes between registers */ + .clock_khz = 50000, /* input clock of 50MHz */ +}; + +static struct platform_device myi2c = { + .name = "ocores-i2c", + .dev = { + .platform_data = &myi2c_data, + }, + .num_resources = ARRAY_SIZE(ocores_resources), + .resource = ocores_resources, +}; diff --git a/Documentation/ia64/aliasing.txt b/Documentation/ia64/aliasing.txt new file mode 100644 index 000000000..38f9a52d1 --- /dev/null +++ b/Documentation/ia64/aliasing.txt @@ -0,0 +1,208 @@ + MEMORY ATTRIBUTE ALIASING ON IA-64 + + Bjorn Helgaas + <bjorn.helgaas@hp.com> + May 4, 2006 + + +MEMORY ATTRIBUTES + + Itanium supports several attributes for virtual memory references. + The attribute is part of the virtual translation, i.e., it is + contained in the TLB entry. The ones of most interest to the Linux + kernel are: + + WB Write-back (cacheable) + UC Uncacheable + WC Write-coalescing + + System memory typically uses the WB attribute. The UC attribute is + used for memory-mapped I/O devices. The WC attribute is uncacheable + like UC is, but writes may be delayed and combined to increase + performance for things like frame buffers. + + The Itanium architecture requires that we avoid accessing the same + page with both a cacheable mapping and an uncacheable mapping[1]. + + The design of the chipset determines which attributes are supported + on which regions of the address space. For example, some chipsets + support either WB or UC access to main memory, while others support + only WB access. + +MEMORY MAP + + Platform firmware describes the physical memory map and the + supported attributes for each region. At boot-time, the kernel uses + the EFI GetMemoryMap() interface. ACPI can also describe memory + devices and the attributes they support, but Linux/ia64 currently + doesn't use this information. + + The kernel uses the efi_memmap table returned from GetMemoryMap() to + learn the attributes supported by each region of physical address + space. Unfortunately, this table does not completely describe the + address space because some machines omit some or all of the MMIO + regions from the map. + + The kernel maintains another table, kern_memmap, which describes the + memory Linux is actually using and the attribute for each region. + This contains only system memory; it does not contain MMIO space. + + The kern_memmap table typically contains only a subset of the system + memory described by the efi_memmap. Linux/ia64 can't use all memory + in the system because of constraints imposed by the identity mapping + scheme. + + The efi_memmap table is preserved unmodified because the original + boot-time information is required for kexec. + +KERNEL IDENTITY MAPPINGS + + Linux/ia64 identity mappings are done with large pages, currently + either 16MB or 64MB, referred to as "granules." Cacheable mappings + are speculative[2], so the processor can read any location in the + page at any time, independent of the programmer's intentions. This + means that to avoid attribute aliasing, Linux can create a cacheable + identity mapping only when the entire granule supports cacheable + access. + + Therefore, kern_memmap contains only full granule-sized regions that + can referenced safely by an identity mapping. + + Uncacheable mappings are not speculative, so the processor will + generate UC accesses only to locations explicitly referenced by + software. This allows UC identity mappings to cover granules that + are only partially populated, or populated with a combination of UC + and WB regions. + +USER MAPPINGS + + User mappings are typically done with 16K or 64K pages. The smaller + page size allows more flexibility because only 16K or 64K has to be + homogeneous with respect to memory attributes. + +POTENTIAL ATTRIBUTE ALIASING CASES + + There are several ways the kernel creates new mappings: + + mmap of /dev/mem + + This uses remap_pfn_range(), which creates user mappings. These + mappings may be either WB or UC. If the region being mapped + happens to be in kern_memmap, meaning that it may also be mapped + by a kernel identity mapping, the user mapping must use the same + attribute as the kernel mapping. + + If the region is not in kern_memmap, the user mapping should use + an attribute reported as being supported in the EFI memory map. + + Since the EFI memory map does not describe MMIO on some + machines, this should use an uncacheable mapping as a fallback. + + mmap of /sys/class/pci_bus/.../legacy_mem + + This is very similar to mmap of /dev/mem, except that legacy_mem + only allows mmap of the one megabyte "legacy MMIO" area for a + specific PCI bus. Typically this is the first megabyte of + physical address space, but it may be different on machines with + several VGA devices. + + "X" uses this to access VGA frame buffers. Using legacy_mem + rather than /dev/mem allows multiple instances of X to talk to + different VGA cards. + + The /dev/mem mmap constraints apply. + + However, since this is for mapping legacy MMIO space, WB access + does not make sense. This matters on machines without legacy + VGA support: these machines may have WB memory for the entire + first megabyte (or even the entire first granule). + + On these machines, we could mmap legacy_mem as WB, which would + be safe in terms of attribute aliasing, but X has no way of + knowing that it is accessing regular memory, not a frame buffer, + so the kernel should fail the mmap rather than doing it with WB. + + read/write of /dev/mem + + This uses copy_from_user(), which implicitly uses a kernel + identity mapping. This is obviously safe for things in + kern_memmap. + + There may be corner cases of things that are not in kern_memmap, + but could be accessed this way. For example, registers in MMIO + space are not in kern_memmap, but could be accessed with a UC + mapping. This would not cause attribute aliasing. But + registers typically can be accessed only with four-byte or + eight-byte accesses, and the copy_from_user() path doesn't allow + any control over the access size, so this would be dangerous. + + ioremap() + + This returns a kernel identity mapping for use inside the + kernel. + + If the region is in kern_memmap, we should use the attribute + specified there. Otherwise, if the EFI memory map reports that + the entire granule supports WB, we should use that (granules + that are partially reserved or occupied by firmware do not appear + in kern_memmap). Otherwise, we should use a UC mapping. + +PAST PROBLEM CASES + + mmap of various MMIO regions from /dev/mem by "X" on Intel platforms + + The EFI memory map may not report these MMIO regions. + + These must be allowed so that X will work. This means that + when the EFI memory map is incomplete, every /dev/mem mmap must + succeed. It may create either WB or UC user mappings, depending + on whether the region is in kern_memmap or the EFI memory map. + + mmap of 0x0-0xA0000 /dev/mem by "hwinfo" on HP sx1000 with VGA enabled + + See https://bugzilla.novell.com/show_bug.cgi?id=140858. + + The EFI memory map reports the following attributes: + 0x00000-0x9FFFF WB only + 0xA0000-0xBFFFF UC only (VGA frame buffer) + 0xC0000-0xFFFFF WB only + + This mmap is done with user pages, not kernel identity mappings, + so it is safe to use WB mappings. + + The kernel VGA driver may ioremap the VGA frame buffer at 0xA0000, + which will use a granule-sized UC mapping covering 0-0xFFFFF. This + granule covers some WB-only memory, but since UC is non-speculative, + the processor will never generate an uncacheable reference to the + WB-only areas unless the driver explicitly touches them. + + mmap of 0x0-0xFFFFF legacy_mem by "X" + + If the EFI memory map reports this entire range as WB, there + is no VGA MMIO hole, and the mmap should fail or be done with + a WB mapping. + + There's no easy way for X to determine whether the 0xA0000-0xBFFFF + region is a frame buffer or just memory, so I think it's best to + just fail this mmap request rather than using a WB mapping. As + far as I know, there's no need to map legacy_mem with WB + mappings. + + Otherwise, a UC mapping of the entire region is probably safe. + The VGA hole means the region will not be in kern_memmap. The + HP sx1000 chipset doesn't support UC access to the memory surrounding + the VGA hole, but X doesn't need that area anyway and should not + reference it. + + mmap of 0xA0000-0xBFFFF legacy_mem by "X" on HP sx1000 with VGA disabled + + The EFI memory map reports the following attributes: + 0x00000-0xFFFFF WB only (no VGA MMIO hole) + + This is a special case of the previous case, and the mmap should + fail for the same reason as above. + +NOTES + + [1] SDM rev 2.2, vol 2, sec 4.4.1. + [2] SDM rev 2.2, vol 2, sec 4.4.6. diff --git a/Documentation/irqflags-tracing.txt b/Documentation/irqflags-tracing.txt new file mode 100644 index 000000000..6a444877e --- /dev/null +++ b/Documentation/irqflags-tracing.txt @@ -0,0 +1,57 @@ +IRQ-flags state tracing + +started by Ingo Molnar <mingo@redhat.com> + +the "irq-flags tracing" feature "traces" hardirq and softirq state, in +that it gives interested subsystems an opportunity to be notified of +every hardirqs-off/hardirqs-on, softirqs-off/softirqs-on event that +happens in the kernel. + +CONFIG_TRACE_IRQFLAGS_SUPPORT is needed for CONFIG_PROVE_SPIN_LOCKING +and CONFIG_PROVE_RW_LOCKING to be offered by the generic lock debugging +code. Otherwise only CONFIG_PROVE_MUTEX_LOCKING and +CONFIG_PROVE_RWSEM_LOCKING will be offered on an architecture - these +are locking APIs that are not used in IRQ context. (the one exception +for rwsems is worked around) + +architecture support for this is certainly not in the "trivial" +category, because lots of lowlevel assembly code deal with irq-flags +state changes. But an architecture can be irq-flags-tracing enabled in a +rather straightforward and risk-free manner. + +Architectures that want to support this need to do a couple of +code-organizational changes first: + +- move their irq-flags manipulation code from their asm/system.h header + to asm/irqflags.h + +- rename local_irq_disable()/etc to raw_local_irq_disable()/etc. so that + the linux/irqflags.h code can inject callbacks and can construct the + real local_irq_disable()/etc APIs. + +- add and enable TRACE_IRQFLAGS_SUPPORT in their arch level Kconfig file + +and then a couple of functional changes are needed as well to implement +irq-flags-tracing support: + +- in lowlevel entry code add (build-conditional) calls to the + trace_hardirqs_off()/trace_hardirqs_on() functions. The lock validator + closely guards whether the 'real' irq-flags matches the 'virtual' + irq-flags state, and complains loudly (and turns itself off) if the + two do not match. Usually most of the time for arch support for + irq-flags-tracing is spent in this state: look at the lockdep + complaint, try to figure out the assembly code we did not cover yet, + fix and repeat. Once the system has booted up and works without a + lockdep complaint in the irq-flags-tracing functions arch support is + complete. +- if the architecture has non-maskable interrupts then those need to be + excluded from the irq-tracing [and lock validation] mechanism via + lockdep_off()/lockdep_on(). + +in general there is no risk from having an incomplete irq-flags-tracing +implementation in an architecture: lockdep will detect that and will +turn itself off. I.e. the lock validator will still be reliable. There +should be no crashes due to irq-tracing bugs. (except if the assembly +changes break other code by modifying conditions or registers that +shouldnt be) + diff --git a/Documentation/lockdep-design.txt b/Documentation/lockdep-design.txt new file mode 100644 index 000000000..00d93605b --- /dev/null +++ b/Documentation/lockdep-design.txt @@ -0,0 +1,197 @@ +Runtime locking correctness validator +===================================== + +started by Ingo Molnar <mingo@redhat.com> +additions by Arjan van de Ven <arjan@linux.intel.com> + +Lock-class +---------- + +The basic object the validator operates upon is a 'class' of locks. + +A class of locks is a group of locks that are logically the same with +respect to locking rules, even if the locks may have multiple (possibly +tens of thousands of) instantiations. For example a lock in the inode +struct is one class, while each inode has its own instantiation of that +lock class. + +The validator tracks the 'state' of lock-classes, and it tracks +dependencies between different lock-classes. The validator maintains a +rolling proof that the state and the dependencies are correct. + +Unlike an lock instantiation, the lock-class itself never goes away: when +a lock-class is used for the first time after bootup it gets registered, +and all subsequent uses of that lock-class will be attached to this +lock-class. + +State +----- + +The validator tracks lock-class usage history into 5 separate state bits: + +- 'ever held in hardirq context' [ == hardirq-safe ] +- 'ever held in softirq context' [ == softirq-safe ] +- 'ever held with hardirqs enabled' [ == hardirq-unsafe ] +- 'ever held with softirqs and hardirqs enabled' [ == softirq-unsafe ] + +- 'ever used' [ == !unused ] + +Single-lock state rules: +------------------------ + +A softirq-unsafe lock-class is automatically hardirq-unsafe as well. The +following states are exclusive, and only one of them is allowed to be +set for any lock-class: + + <hardirq-safe> and <hardirq-unsafe> + <softirq-safe> and <softirq-unsafe> + +The validator detects and reports lock usage that violate these +single-lock state rules. + +Multi-lock dependency rules: +---------------------------- + +The same lock-class must not be acquired twice, because this could lead +to lock recursion deadlocks. + +Furthermore, two locks may not be taken in different order: + + <L1> -> <L2> + <L2> -> <L1> + +because this could lead to lock inversion deadlocks. (The validator +finds such dependencies in arbitrary complexity, i.e. there can be any +other locking sequence between the acquire-lock operations, the +validator will still track all dependencies between locks.) + +Furthermore, the following usage based lock dependencies are not allowed +between any two lock-classes: + + <hardirq-safe> -> <hardirq-unsafe> + <softirq-safe> -> <softirq-unsafe> + +The first rule comes from the fact the a hardirq-safe lock could be +taken by a hardirq context, interrupting a hardirq-unsafe lock - and +thus could result in a lock inversion deadlock. Likewise, a softirq-safe +lock could be taken by an softirq context, interrupting a softirq-unsafe +lock. + +The above rules are enforced for any locking sequence that occurs in the +kernel: when acquiring a new lock, the validator checks whether there is +any rule violation between the new lock and any of the held locks. + +When a lock-class changes its state, the following aspects of the above +dependency rules are enforced: + +- if a new hardirq-safe lock is discovered, we check whether it + took any hardirq-unsafe lock in the past. + +- if a new softirq-safe lock is discovered, we check whether it took + any softirq-unsafe lock in the past. + +- if a new hardirq-unsafe lock is discovered, we check whether any + hardirq-safe lock took it in the past. + +- if a new softirq-unsafe lock is discovered, we check whether any + softirq-safe lock took it in the past. + +(Again, we do these checks too on the basis that an interrupt context +could interrupt _any_ of the irq-unsafe or hardirq-unsafe locks, which +could lead to a lock inversion deadlock - even if that lock scenario did +not trigger in practice yet.) + +Exception: Nested data dependencies leading to nested locking +------------------------------------------------------------- + +There are a few cases where the Linux kernel acquires more than one +instance of the same lock-class. Such cases typically happen when there +is some sort of hierarchy within objects of the same type. In these +cases there is an inherent "natural" ordering between the two objects +(defined by the properties of the hierarchy), and the kernel grabs the +locks in this fixed order on each of the objects. + +An example of such an object hieararchy that results in "nested locking" +is that of a "whole disk" block-dev object and a "partition" block-dev +object; the partition is "part of" the whole device and as long as one +always takes the whole disk lock as a higher lock than the partition +lock, the lock ordering is fully correct. The validator does not +automatically detect this natural ordering, as the locking rule behind +the ordering is not static. + +In order to teach the validator about this correct usage model, new +versions of the various locking primitives were added that allow you to +specify a "nesting level". An example call, for the block device mutex, +looks like this: + +enum bdev_bd_mutex_lock_class +{ + BD_MUTEX_NORMAL, + BD_MUTEX_WHOLE, + BD_MUTEX_PARTITION +}; + + mutex_lock_nested(&bdev->bd_contains->bd_mutex, BD_MUTEX_PARTITION); + +In this case the locking is done on a bdev object that is known to be a +partition. + +The validator treats a lock that is taken in such a nested fasion as a +separate (sub)class for the purposes of validation. + +Note: When changing code to use the _nested() primitives, be careful and +check really thoroughly that the hiearchy is correctly mapped; otherwise +you can get false positives or false negatives. + +Proof of 100% correctness: +-------------------------- + +The validator achieves perfect, mathematical 'closure' (proof of locking +correctness) in the sense that for every simple, standalone single-task +locking sequence that occured at least once during the lifetime of the +kernel, the validator proves it with a 100% certainty that no +combination and timing of these locking sequences can cause any class of +lock related deadlock. [*] + +I.e. complex multi-CPU and multi-task locking scenarios do not have to +occur in practice to prove a deadlock: only the simple 'component' +locking chains have to occur at least once (anytime, in any +task/context) for the validator to be able to prove correctness. (For +example, complex deadlocks that would normally need more than 3 CPUs and +a very unlikely constellation of tasks, irq-contexts and timings to +occur, can be detected on a plain, lightly loaded single-CPU system as +well!) + +This radically decreases the complexity of locking related QA of the +kernel: what has to be done during QA is to trigger as many "simple" +single-task locking dependencies in the kernel as possible, at least +once, to prove locking correctness - instead of having to trigger every +possible combination of locking interaction between CPUs, combined with +every possible hardirq and softirq nesting scenario (which is impossible +to do in practice). + +[*] assuming that the validator itself is 100% correct, and no other + part of the system corrupts the state of the validator in any way. + We also assume that all NMI/SMM paths [which could interrupt + even hardirq-disabled codepaths] are correct and do not interfere + with the validator. We also assume that the 64-bit 'chain hash' + value is unique for every lock-chain in the system. Also, lock + recursion must not be higher than 20. + +Performance: +------------ + +The above rules require _massive_ amounts of runtime checking. If we did +that for every lock taken and for every irqs-enable event, it would +render the system practically unusably slow. The complexity of checking +is O(N^2), so even with just a few hundred lock-classes we'd have to do +tens of thousands of checks for every event. + +This problem is solved by checking any given 'locking scenario' (unique +sequence of locks taken after each other) only once. A simple stack of +held locks is maintained, and a lightweight 64-bit hash value is +calculated, which hash is unique for every lock chain. The hash value, +when the chain is validated for the first time, is then put into a hash +table, which hash-table can be checked in a lockfree manner. If the +locking chain occurs again later on, the hash table tells us that we +dont have to validate the chain again. diff --git a/Documentation/networking/ipvs-sysctl.txt b/Documentation/networking/ipvs-sysctl.txt new file mode 100644 index 000000000..4ccdbca03 --- /dev/null +++ b/Documentation/networking/ipvs-sysctl.txt @@ -0,0 +1,143 @@ +/proc/sys/net/ipv4/vs/* Variables: + +am_droprate - INTEGER + default 10 + + It sets the always mode drop rate, which is used in the mode 3 + of the drop_rate defense. + +amemthresh - INTEGER + default 1024 + + It sets the available memory threshold (in pages), which is + used in the automatic modes of defense. When there is no + enough available memory, the respective strategy will be + enabled and the variable is automatically set to 2, otherwise + the strategy is disabled and the variable is set to 1. + +cache_bypass - BOOLEAN + 0 - disabled (default) + not 0 - enabled + + If it is enabled, forward packets to the original destination + directly when no cache server is available and destination + address is not local (iph->daddr is RTN_UNICAST). It is mostly + used in transparent web cache cluster. + +debug_level - INTEGER + 0 - transmission error messages (default) + 1 - non-fatal error messages + 2 - configuration + 3 - destination trash + 4 - drop entry + 5 - service lookup + 6 - scheduling + 7 - connection new/expire, lookup and synchronization + 8 - state transition + 9 - binding destination, template checks and applications + 10 - IPVS packet transmission + 11 - IPVS packet handling (ip_vs_in/ip_vs_out) + 12 or more - packet traversal + + Only available when IPVS is compiled with the CONFIG_IPVS_DEBUG + + Higher debugging levels include the messages for lower debugging + levels, so setting debug level 2, includes level 0, 1 and 2 + messages. Thus, logging becomes more and more verbose the higher + the level. + +drop_entry - INTEGER + 0 - disabled (default) + + The drop_entry defense is to randomly drop entries in the + connection hash table, just in order to collect back some + memory for new connections. In the current code, the + drop_entry procedure can be activated every second, then it + randomly scans 1/32 of the whole and drops entries that are in + the SYN-RECV/SYNACK state, which should be effective against + syn-flooding attack. + + The valid values of drop_entry are from 0 to 3, where 0 means + that this strategy is always disabled, 1 and 2 mean automatic + modes (when there is no enough available memory, the strategy + is enabled and the variable is automatically set to 2, + otherwise the strategy is disabled and the variable is set to + 1), and 3 means that that the strategy is always enabled. + +drop_packet - INTEGER + 0 - disabled (default) + + The drop_packet defense is designed to drop 1/rate packets + before forwarding them to real servers. If the rate is 1, then + drop all the incoming packets. + + The value definition is the same as that of the drop_entry. In + the automatic mode, the rate is determined by the follow + formula: rate = amemthresh / (amemthresh - available_memory) + when available memory is less than the available memory + threshold. When the mode 3 is set, the always mode drop rate + is controlled by the /proc/sys/net/ipv4/vs/am_droprate. + +expire_nodest_conn - BOOLEAN + 0 - disabled (default) + not 0 - enabled + + The default value is 0, the load balancer will silently drop + packets when its destination server is not available. It may + be useful, when user-space monitoring program deletes the + destination server (because of server overload or wrong + detection) and add back the server later, and the connections + to the server can continue. + + If this feature is enabled, the load balancer will expire the + connection immediately when a packet arrives and its + destination server is not available, then the client program + will be notified that the connection is closed. This is + equivalent to the feature some people requires to flush + connections when its destination is not available. + +expire_quiescent_template - BOOLEAN + 0 - disabled (default) + not 0 - enabled + + When set to a non-zero value, the load balancer will expire + persistent templates when the destination server is quiescent. + This may be useful, when a user makes a destination server + quiescent by setting its weight to 0 and it is desired that + subsequent otherwise persistent connections are sent to a + different destination server. By default new persistent + connections are allowed to quiescent destination servers. + + If this feature is enabled, the load balancer will expire the + persistence template if it is to be used to schedule a new + connection and the destination server is quiescent. + +nat_icmp_send - BOOLEAN + 0 - disabled (default) + not 0 - enabled + + It controls sending icmp error messages (ICMP_DEST_UNREACH) + for VS/NAT when the load balancer receives packets from real + servers but the connection entries don't exist. + +secure_tcp - INTEGER + 0 - disabled (default) + + The secure_tcp defense is to use a more complicated state + transition table and some possible short timeouts of each + state. In the VS/NAT, it delays the entering the ESTABLISHED + until the real server starts to send data and ACK packet + (after 3-way handshake). + + The value definition is the same as that of drop_entry or + drop_packet. + +sync_threshold - INTEGER + default 3 + + It sets synchronization threshold, which is the minimum number + of incoming packets that a connection needs to receive before + the connection will be synchronized. A connection will be + synchronized, every time the number of its incoming packets + modulus 50 equals the threshold. The range of the threshold is + from 0 to 49. diff --git a/Documentation/pcmcia/crc32hash.c b/Documentation/pcmcia/crc32hash.c new file mode 100644 index 000000000..cbc36d299 --- /dev/null +++ b/Documentation/pcmcia/crc32hash.c @@ -0,0 +1,32 @@ +/* crc32hash.c - derived from linux/lib/crc32.c, GNU GPL v2 */ +/* Usage example: +$ ./crc32hash "Dual Speed" +*/ + +#include <string.h> +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> + +unsigned int crc32(unsigned char const *p, unsigned int len) +{ + int i; + unsigned int crc = 0; + while (len--) { + crc ^= *p++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0); + } + return crc; +} + +int main(int argc, char **argv) { + unsigned int result; + if (argc != 2) { + printf("no string passed as argument\n"); + return -1; + } + result = crc32(argv[1], strlen(argv[1])); + printf("0x%x\n", result); + return 0; +} diff --git a/Documentation/pi-futex.txt b/Documentation/pi-futex.txt new file mode 100644 index 000000000..5d61dacd2 --- /dev/null +++ b/Documentation/pi-futex.txt @@ -0,0 +1,121 @@ +Lightweight PI-futexes +---------------------- + +We are calling them lightweight for 3 reasons: + + - in the user-space fastpath a PI-enabled futex involves no kernel work + (or any other PI complexity) at all. No registration, no extra kernel + calls - just pure fast atomic ops in userspace. + + - even in the slowpath, the system call and scheduling pattern is very + similar to normal futexes. + + - the in-kernel PI implementation is streamlined around the mutex + abstraction, with strict rules that keep the implementation + relatively simple: only a single owner may own a lock (i.e. no + read-write lock support), only the owner may unlock a lock, no + recursive locking, etc. + +Priority Inheritance - why? +--------------------------- + +The short reply: user-space PI helps achieving/improving determinism for +user-space applications. In the best-case, it can help achieve +determinism and well-bound latencies. Even in the worst-case, PI will +improve the statistical distribution of locking related application +delays. + +The longer reply: +----------------- + +Firstly, sharing locks between multiple tasks is a common programming +technique that often cannot be replaced with lockless algorithms. As we +can see it in the kernel [which is a quite complex program in itself], +lockless structures are rather the exception than the norm - the current +ratio of lockless vs. locky code for shared data structures is somewhere +between 1:10 and 1:100. Lockless is hard, and the complexity of lockless +algorithms often endangers to ability to do robust reviews of said code. +I.e. critical RT apps often choose lock structures to protect critical +data structures, instead of lockless algorithms. Furthermore, there are +cases (like shared hardware, or other resource limits) where lockless +access is mathematically impossible. + +Media players (such as Jack) are an example of reasonable application +design with multiple tasks (with multiple priority levels) sharing +short-held locks: for example, a highprio audio playback thread is +combined with medium-prio construct-audio-data threads and low-prio +display-colory-stuff threads. Add video and decoding to the mix and +we've got even more priority levels. + +So once we accept that synchronization objects (locks) are an +unavoidable fact of life, and once we accept that multi-task userspace +apps have a very fair expectation of being able to use locks, we've got +to think about how to offer the option of a deterministic locking +implementation to user-space. + +Most of the technical counter-arguments against doing priority +inheritance only apply to kernel-space locks. But user-space locks are +different, there we cannot disable interrupts or make the task +non-preemptible in a critical section, so the 'use spinlocks' argument +does not apply (user-space spinlocks have the same priority inversion +problems as other user-space locking constructs). Fact is, pretty much +the only technique that currently enables good determinism for userspace +locks (such as futex-based pthread mutexes) is priority inheritance: + +Currently (without PI), if a high-prio and a low-prio task shares a lock +[this is a quite common scenario for most non-trivial RT applications], +even if all critical sections are coded carefully to be deterministic +(i.e. all critical sections are short in duration and only execute a +limited number of instructions), the kernel cannot guarantee any +deterministic execution of the high-prio task: any medium-priority task +could preempt the low-prio task while it holds the shared lock and +executes the critical section, and could delay it indefinitely. + +Implementation: +--------------- + +As mentioned before, the userspace fastpath of PI-enabled pthread +mutexes involves no kernel work at all - they behave quite similarly to +normal futex-based locks: a 0 value means unlocked, and a value==TID +means locked. (This is the same method as used by list-based robust +futexes.) Userspace uses atomic ops to lock/unlock these mutexes without +entering the kernel. + +To handle the slowpath, we have added two new futex ops: + + FUTEX_LOCK_PI + FUTEX_UNLOCK_PI + +If the lock-acquire fastpath fails, [i.e. an atomic transition from 0 to +TID fails], then FUTEX_LOCK_PI is called. The kernel does all the +remaining work: if there is no futex-queue attached to the futex address +yet then the code looks up the task that owns the futex [it has put its +own TID into the futex value], and attaches a 'PI state' structure to +the futex-queue. The pi_state includes an rt-mutex, which is a PI-aware, +kernel-based synchronization object. The 'other' task is made the owner +of the rt-mutex, and the FUTEX_WAITERS bit is atomically set in the +futex value. Then this task tries to lock the rt-mutex, on which it +blocks. Once it returns, it has the mutex acquired, and it sets the +futex value to its own TID and returns. Userspace has no other work to +perform - it now owns the lock, and futex value contains +FUTEX_WAITERS|TID. + +If the unlock side fastpath succeeds, [i.e. userspace manages to do a +TID -> 0 atomic transition of the futex value], then no kernel work is +triggered. + +If the unlock fastpath fails (because the FUTEX_WAITERS bit is set), +then FUTEX_UNLOCK_PI is called, and the kernel unlocks the futex on the +behalf of userspace - and it also unlocks the attached +pi_state->rt_mutex and thus wakes up any potential waiters. + +Note that under this approach, contrary to previous PI-futex approaches, +there is no prior 'registration' of a PI-futex. [which is not quite +possible anyway, due to existing ABI properties of pthread mutexes.] + +Also, under this scheme, 'robustness' and 'PI' are two orthogonal +properties of futexes, and all four combinations are possible: futex, +robust-futex, PI-futex, robust+PI-futex. + +More details about priority inheritance can be found in +Documentation/rtmutex.txt. diff --git a/Documentation/rt-mutex-design.txt b/Documentation/rt-mutex-design.txt new file mode 100644 index 000000000..c472ffacc --- /dev/null +++ b/Documentation/rt-mutex-design.txt @@ -0,0 +1,781 @@ +# +# Copyright (c) 2006 Steven Rostedt +# Licensed under the GNU Free Documentation License, Version 1.2 +# + +RT-mutex implementation design +------------------------------ + +This document tries to describe the design of the rtmutex.c implementation. +It doesn't describe the reasons why rtmutex.c exists. For that please see +Documentation/rt-mutex.txt. Although this document does explain problems +that happen without this code, but that is in the concept to understand +what the code actually is doing. + +The goal of this document is to help others understand the priority +inheritance (PI) algorithm that is used, as well as reasons for the +decisions that were made to implement PI in the manner that was done. + + +Unbounded Priority Inversion +---------------------------- + +Priority inversion is when a lower priority process executes while a higher +priority process wants to run. This happens for several reasons, and +most of the time it can't be helped. Anytime a high priority process wants +to use a resource that a lower priority process has (a mutex for example), +the high priority process must wait until the lower priority process is done +with the resource. This is a priority inversion. What we want to prevent +is something called unbounded priority inversion. That is when the high +priority process is prevented from running by a lower priority process for +an undetermined amount of time. + +The classic example of unbounded priority inversion is were you have three +processes, let's call them processes A, B, and C, where A is the highest +priority process, C is the lowest, and B is in between. A tries to grab a lock +that C owns and must wait and lets C run to release the lock. But in the +meantime, B executes, and since B is of a higher priority than C, it preempts C, +but by doing so, it is in fact preempting A which is a higher priority process. +Now there's no way of knowing how long A will be sleeping waiting for C +to release the lock, because for all we know, B is a CPU hog and will +never give C a chance to release the lock. This is called unbounded priority +inversion. + +Here's a little ASCII art to show the problem. + + grab lock L1 (owned by C) + | +A ---+ + C preempted by B + | +C +----+ + +B +--------> + B now keeps A from running. + + +Priority Inheritance (PI) +------------------------- + +There are several ways to solve this issue, but other ways are out of scope +for this document. Here we only discuss PI. + +PI is where a process inherits the priority of another process if the other +process blocks on a lock owned by the current process. To make this easier +to understand, let's use the previous example, with processes A, B, and C again. + +This time, when A blocks on the lock owned by C, C would inherit the priority +of A. So now if B becomes runnable, it would not preempt C, since C now has +the high priority of A. As soon as C releases the lock, it loses its +inherited priority, and A then can continue with the resource that C had. + +Terminology +----------- + +Here I explain some terminology that is used in this document to help describe +the design that is used to implement PI. + +PI chain - The PI chain is an ordered series of locks and processes that cause + processes to inherit priorities from a previous process that is + blocked on one of its locks. This is described in more detail + later in this document. + +mutex - In this document, to differentiate from locks that implement + PI and spin locks that are used in the PI code, from now on + the PI locks will be called a mutex. + +lock - In this document from now on, I will use the term lock when + referring to spin locks that are used to protect parts of the PI + algorithm. These locks disable preemption for UP (when + CONFIG_PREEMPT is enabled) and on SMP prevents multiple CPUs from + entering critical sections simultaneously. + +spin lock - Same as lock above. + +waiter - A waiter is a struct that is stored on the stack of a blocked + process. Since the scope of the waiter is within the code for + a process being blocked on the mutex, it is fine to allocate + the waiter on the process's stack (local variable). This + structure holds a pointer to the task, as well as the mutex that + the task is blocked on. It also has the plist node structures to + place the task in the waiter_list of a mutex as well as the + pi_list of a mutex owner task (described below). + + waiter is sometimes used in reference to the task that is waiting + on a mutex. This is the same as waiter->task. + +waiters - A list of processes that are blocked on a mutex. + +top waiter - The highest priority process waiting on a specific mutex. + +top pi waiter - The highest priority process waiting on one of the mutexes + that a specific process owns. + +Note: task and process are used interchangeably in this document, mostly to + differentiate between two processes that are being described together. + + +PI chain +-------- + +The PI chain is a list of processes and mutexes that may cause priority +inheritance to take place. Multiple chains may converge, but a chain +would never diverge, since a process can't be blocked on more than one +mutex at a time. + +Example: + + Process: A, B, C, D, E + Mutexes: L1, L2, L3, L4 + + A owns: L1 + B blocked on L1 + B owns L2 + C blocked on L2 + C owns L3 + D blocked on L3 + D owns L4 + E blocked on L4 + +The chain would be: + + E->L4->D->L3->C->L2->B->L1->A + +To show where two chains merge, we could add another process F and +another mutex L5 where B owns L5 and F is blocked on mutex L5. + +The chain for F would be: + + F->L5->B->L1->A + +Since a process may own more than one mutex, but never be blocked on more than +one, the chains merge. + +Here we show both chains: + + E->L4->D->L3->C->L2-+ + | + +->B->L1->A + | + F->L5-+ + +For PI to work, the processes at the right end of these chains (or we may +also call it the Top of the chain) must be equal to or higher in priority +than the processes to the left or below in the chain. + +Also since a mutex may have more than one process blocked on it, we can +have multiple chains merge at mutexes. If we add another process G that is +blocked on mutex L2: + + G->L2->B->L1->A + +And once again, to show how this can grow I will show the merging chains +again. + + E->L4->D->L3->C-+ + +->L2-+ + | | + G-+ +->B->L1->A + | + F->L5-+ + + +Plist +----- + +Before I go further and talk about how the PI chain is stored through lists +on both mutexes and processes, I'll explain the plist. This is similar to +the struct list_head functionality that is already in the kernel. +The implementation of plist is out of scope for this document, but it is +very important to understand what it does. + +There are a few differences between plist and list, the most important one +being that plist is a priority sorted linked list. This means that the +priorities of the plist are sorted, such that it takes O(1) to retrieve the +highest priority item in the list. Obviously this is useful to store processes +based on their priorities. + +Another difference, which is important for implementation, is that, unlike +list, the head of the list is a different element than the nodes of a list. +So the head of the list is declared as struct plist_head and nodes that will +be added to the list are declared as struct plist_node. + + +Mutex Waiter List +----------------- + +Every mutex keeps track of all the waiters that are blocked on itself. The mutex +has a plist to store these waiters by priority. This list is protected by +a spin lock that is located in the struct of the mutex. This lock is called +wait_lock. Since the modification of the waiter list is never done in +interrupt context, the wait_lock can be taken without disabling interrupts. + + +Task PI List +------------ + +To keep track of the PI chains, each process has its own PI list. This is +a list of all top waiters of the mutexes that are owned by the process. +Note that this list only holds the top waiters and not all waiters that are +blocked on mutexes owned by the process. + +The top of the task's PI list is always the highest priority task that +is waiting on a mutex that is owned by the task. So if the task has +inherited a priority, it will always be the priority of the task that is +at the top of this list. + +This list is stored in the task structure of a process as a plist called +pi_list. This list is protected by a spin lock also in the task structure, +called pi_lock. This lock may also be taken in interrupt context, so when +locking the pi_lock, interrupts must be disabled. + + +Depth of the PI Chain +--------------------- + +The maximum depth of the PI chain is not dynamic, and could actually be +defined. But is very complex to figure it out, since it depends on all +the nesting of mutexes. Let's look at the example where we have 3 mutexes, +L1, L2, and L3, and four separate functions func1, func2, func3 and func4. +The following shows a locking order of L1->L2->L3, but may not actually +be directly nested that way. + +void func1(void) +{ + mutex_lock(L1); + + /* do anything */ + + mutex_unlock(L1); +} + +void func2(void) +{ + mutex_lock(L1); + mutex_lock(L2); + + /* do something */ + + mutex_unlock(L2); + mutex_unlock(L1); +} + +void func3(void) +{ + mutex_lock(L2); + mutex_lock(L3); + + /* do something else */ + + mutex_unlock(L3); + mutex_unlock(L2); +} + +void func4(void) +{ + mutex_lock(L3); + + /* do something again */ + + mutex_unlock(L3); +} + +Now we add 4 processes that run each of these functions separately. +Processes A, B, C, and D which run functions func1, func2, func3 and func4 +respectively, and such that D runs first and A last. With D being preempted +in func4 in the "do something again" area, we have a locking that follows: + +D owns L3 + C blocked on L3 + C owns L2 + B blocked on L2 + B owns L1 + A blocked on L1 + +And thus we have the chain A->L1->B->L2->C->L3->D. + +This gives us a PI depth of 4 (four processes), but looking at any of the +functions individually, it seems as though they only have at most a locking +depth of two. So, although the locking depth is defined at compile time, +it still is very difficult to find the possibilities of that depth. + +Now since mutexes can be defined by user-land applications, we don't want a DOS +type of application that nests large amounts of mutexes to create a large +PI chain, and have the code holding spin locks while looking at a large +amount of data. So to prevent this, the implementation not only implements +a maximum lock depth, but also only holds at most two different locks at a +time, as it walks the PI chain. More about this below. + + +Mutex owner and flags +--------------------- + +The mutex structure contains a pointer to the owner of the mutex. If the +mutex is not owned, this owner is set to NULL. Since all architectures +have the task structure on at least a four byte alignment (and if this is +not true, the rtmutex.c code will be broken!), this allows for the two +least significant bits to be used as flags. This part is also described +in Documentation/rt-mutex.txt, but will also be briefly described here. + +Bit 0 is used as the "Pending Owner" flag. This is described later. +Bit 1 is used as the "Has Waiters" flags. This is also described later + in more detail, but is set whenever there are waiters on a mutex. + + +cmpxchg Tricks +-------------- + +Some architectures implement an atomic cmpxchg (Compare and Exchange). This +is used (when applicable) to keep the fast path of grabbing and releasing +mutexes short. + +cmpxchg is basically the following function performed atomically: + +unsigned long _cmpxchg(unsigned long *A, unsigned long *B, unsigned long *C) +{ + unsigned long T = *A; + if (*A == *B) { + *A = *C; + } + return T; +} +#define cmpxchg(a,b,c) _cmpxchg(&a,&b,&c) + +This is really nice to have, since it allows you to only update a variable +if the variable is what you expect it to be. You know if it succeeded if +the return value (the old value of A) is equal to B. + +The macro rt_mutex_cmpxchg is used to try to lock and unlock mutexes. If +the architecture does not support CMPXCHG, then this macro is simply set +to fail every time. But if CMPXCHG is supported, then this will +help out extremely to keep the fast path short. + +The use of rt_mutex_cmpxchg with the flags in the owner field help optimize +the system for architectures that support it. This will also be explained +later in this document. + + +Priority adjustments +-------------------- + +The implementation of the PI code in rtmutex.c has several places that a +process must adjust its priority. With the help of the pi_list of a +process this is rather easy to know what needs to be adjusted. + +The functions implementing the task adjustments are rt_mutex_adjust_prio, +__rt_mutex_adjust_prio (same as the former, but expects the task pi_lock +to already be taken), rt_mutex_get_prio, and rt_mutex_setprio. + +rt_mutex_getprio and rt_mutex_setprio are only used in __rt_mutex_adjust_prio. + +rt_mutex_getprio returns the priority that the task should have. Either the +task's own normal priority, or if a process of a higher priority is waiting on +a mutex owned by the task, then that higher priority should be returned. +Since the pi_list of a task holds an order by priority list of all the top +waiters of all the mutexes that the task owns, rt_mutex_getprio simply needs +to compare the top pi waiter to its own normal priority, and return the higher +priority back. + +(Note: if looking at the code, you will notice that the lower number of + prio is returned. This is because the prio field in the task structure + is an inverse order of the actual priority. So a "prio" of 5 is + of higher priority than a "prio" of 10.) + +__rt_mutex_adjust_prio examines the result of rt_mutex_getprio, and if the +result does not equal the task's current priority, then rt_mutex_setprio +is called to adjust the priority of the task to the new priority. +Note that rt_mutex_setprio is defined in kernel/sched.c to implement the +actual change in priority. + +It is interesting to note that __rt_mutex_adjust_prio can either increase +or decrease the priority of the task. In the case that a higher priority +process has just blocked on a mutex owned by the task, __rt_mutex_adjust_prio +would increase/boost the task's priority. But if a higher priority task +were for some reason to leave the mutex (timeout or signal), this same function +would decrease/unboost the priority of the task. That is because the pi_list +always contains the highest priority task that is waiting on a mutex owned +by the task, so we only need to compare the priority of that top pi waiter +to the normal priority of the given task. + + +High level overview of the PI chain walk +---------------------------------------- + +The PI chain walk is implemented by the function rt_mutex_adjust_prio_chain. + +The implementation has gone through several iterations, and has ended up +with what we believe is the best. It walks the PI chain by only grabbing +at most two locks at a time, and is very efficient. + +The rt_mutex_adjust_prio_chain can be used either to boost or lower process +priorities. + +rt_mutex_adjust_prio_chain is called with a task to be checked for PI +(de)boosting (the owner of a mutex that a process is blocking on), a flag to +check for deadlocking, the mutex that the task owns, and a pointer to a waiter +that is the process's waiter struct that is blocked on the mutex (although this +parameter may be NULL for deboosting). + +For this explanation, I will not mention deadlock detection. This explanation +will try to stay at a high level. + +When this function is called, there are no locks held. That also means +that the state of the owner and lock can change when entered into this function. + +Before this function is called, the task has already had rt_mutex_adjust_prio +performed on it. This means that the task is set to the priority that it +should be at, but the plist nodes of the task's waiter have not been updated +with the new priorities, and that this task may not be in the proper locations +in the pi_lists and wait_lists that the task is blocked on. This function +solves all that. + +A loop is entered, where task is the owner to be checked for PI changes that +was passed by parameter (for the first iteration). The pi_lock of this task is +taken to prevent any more changes to the pi_list of the task. This also +prevents new tasks from completing the blocking on a mutex that is owned by this +task. + +If the task is not blocked on a mutex then the loop is exited. We are at +the top of the PI chain. + +A check is now done to see if the original waiter (the process that is blocked +on the current mutex) is the top pi waiter of the task. That is, is this +waiter on the top of the task's pi_list. If it is not, it either means that +there is another process higher in priority that is blocked on one of the +mutexes that the task owns, or that the waiter has just woken up via a signal +or timeout and has left the PI chain. In either case, the loop is exited, since +we don't need to do any more changes to the priority of the current task, or any +task that owns a mutex that this current task is waiting on. A priority chain +walk is only needed when a new top pi waiter is made to a task. + +The next check sees if the task's waiter plist node has the priority equal to +the priority the task is set at. If they are equal, then we are done with +the loop. Remember that the function started with the priority of the +task adjusted, but the plist nodes that hold the task in other processes +pi_lists have not been adjusted. + +Next, we look at the mutex that the task is blocked on. The mutex's wait_lock +is taken. This is done by a spin_trylock, because the locking order of the +pi_lock and wait_lock goes in the opposite direction. If we fail to grab the +lock, the pi_lock is released, and we restart the loop. + +Now that we have both the pi_lock of the task as well as the wait_lock of +the mutex the task is blocked on, we update the task's waiter's plist node +that is located on the mutex's wait_list. + +Now we release the pi_lock of the task. + +Next the owner of the mutex has its pi_lock taken, so we can update the +task's entry in the owner's pi_list. If the task is the highest priority +process on the mutex's wait_list, then we remove the previous top waiter +from the owner's pi_list, and replace it with the task. + +Note: It is possible that the task was the current top waiter on the mutex, + in which case the task is not yet on the pi_list of the waiter. This + is OK, since plist_del does nothing if the plist node is not on any + list. + +If the task was not the top waiter of the mutex, but it was before we +did the priority updates, that means we are deboosting/lowering the +task. In this case, the task is removed from the pi_list of the owner, +and the new top waiter is added. + +Lastly, we unlock both the pi_lock of the task, as well as the mutex's +wait_lock, and continue the loop again. On the next iteration of the +loop, the previous owner of the mutex will be the task that will be +processed. + +Note: One might think that the owner of this mutex might have changed + since we just grab the mutex's wait_lock. And one could be right. + The important thing to remember is that the owner could not have + become the task that is being processed in the PI chain, since + we have taken that task's pi_lock at the beginning of the loop. + So as long as there is an owner of this mutex that is not the same + process as the tasked being worked on, we are OK. + + Looking closely at the code, one might be confused. The check for the + end of the PI chain is when the task isn't blocked on anything or the + task's waiter structure "task" element is NULL. This check is + protected only by the task's pi_lock. But the code to unlock the mutex + sets the task's waiter structure "task" element to NULL with only + the protection of the mutex's wait_lock, which was not taken yet. + Isn't this a race condition if the task becomes the new owner? + + The answer is No! The trick is the spin_trylock of the mutex's + wait_lock. If we fail that lock, we release the pi_lock of the + task and continue the loop, doing the end of PI chain check again. + + In the code to release the lock, the wait_lock of the mutex is held + the entire time, and it is not let go when we grab the pi_lock of the + new owner of the mutex. So if the switch of a new owner were to happen + after the check for end of the PI chain and the grabbing of the + wait_lock, the unlocking code would spin on the new owner's pi_lock + but never give up the wait_lock. So the PI chain loop is guaranteed to + fail the spin_trylock on the wait_lock, release the pi_lock, and + try again. + + If you don't quite understand the above, that's OK. You don't have to, + unless you really want to make a proof out of it ;) + + +Pending Owners and Lock stealing +-------------------------------- + +One of the flags in the owner field of the mutex structure is "Pending Owner". +What this means is that an owner was chosen by the process releasing the +mutex, but that owner has yet to wake up and actually take the mutex. + +Why is this important? Why can't we just give the mutex to another process +and be done with it? + +The PI code is to help with real-time processes, and to let the highest +priority process run as long as possible with little latencies and delays. +If a high priority process owns a mutex that a lower priority process is +blocked on, when the mutex is released it would be given to the lower priority +process. What if the higher priority process wants to take that mutex again. +The high priority process would fail to take that mutex that it just gave up +and it would need to boost the lower priority process to run with full +latency of that critical section (since the low priority process just entered +it). + +There's no reason a high priority process that gives up a mutex should be +penalized if it tries to take that mutex again. If the new owner of the +mutex has not woken up yet, there's no reason that the higher priority process +could not take that mutex away. + +To solve this, we introduced Pending Ownership and Lock Stealing. When a +new process is given a mutex that it was blocked on, it is only given +pending ownership. This means that it's the new owner, unless a higher +priority process comes in and tries to grab that mutex. If a higher priority +process does come along and wants that mutex, we let the higher priority +process "steal" the mutex from the pending owner (only if it is still pending) +and continue with the mutex. + + +Taking of a mutex (The walk through) +------------------------------------ + +OK, now let's take a look at the detailed walk through of what happens when +taking a mutex. + +The first thing that is tried is the fast taking of the mutex. This is +done when we have CMPXCHG enabled (otherwise the fast taking automatically +fails). Only when the owner field of the mutex is NULL can the lock be +taken with the CMPXCHG and nothing else needs to be done. + +If there is contention on the lock, whether it is owned or pending owner +we go about the slow path (rt_mutex_slowlock). + +The slow path function is where the task's waiter structure is created on +the stack. This is because the waiter structure is only needed for the +scope of this function. The waiter structure holds the nodes to store +the task on the wait_list of the mutex, and if need be, the pi_list of +the owner. + +The wait_lock of the mutex is taken since the slow path of unlocking the +mutex also takes this lock. + +We then call try_to_take_rt_mutex. This is where the architecture that +does not implement CMPXCHG would always grab the lock (if there's no +contention). + +try_to_take_rt_mutex is used every time the task tries to grab a mutex in the +slow path. The first thing that is done here is an atomic setting of +the "Has Waiters" flag of the mutex's owner field. Yes, this could really +be false, because if the the mutex has no owner, there are no waiters and +the current task also won't have any waiters. But we don't have the lock +yet, so we assume we are going to be a waiter. The reason for this is to +play nice for those architectures that do have CMPXCHG. By setting this flag +now, the owner of the mutex can't release the mutex without going into the +slow unlock path, and it would then need to grab the wait_lock, which this +code currently holds. So setting the "Has Waiters" flag forces the owner +to synchronize with this code. + +Now that we know that we can't have any races with the owner releasing the +mutex, we check to see if we can take the ownership. This is done if the +mutex doesn't have a owner, or if we can steal the mutex from a pending +owner. Let's look at the situations we have here. + + 1) Has owner that is pending + ---------------------------- + + The mutex has a owner, but it hasn't woken up and the mutex flag + "Pending Owner" is set. The first check is to see if the owner isn't the + current task. This is because this function is also used for the pending + owner to grab the mutex. When a pending owner wakes up, it checks to see + if it can take the mutex, and this is done if the owner is already set to + itself. If so, we succeed and leave the function, clearing the "Pending + Owner" bit. + + If the pending owner is not current, we check to see if the current priority is + higher than the pending owner. If not, we fail the function and return. + + There's also something special about a pending owner. That is a pending owner + is never blocked on a mutex. So there is no PI chain to worry about. It also + means that if the mutex doesn't have any waiters, there's no accounting needed + to update the pending owner's pi_list, since we only worry about processes + blocked on the current mutex. + + If there are waiters on this mutex, and we just stole the ownership, we need + to take the top waiter, remove it from the pi_list of the pending owner, and + add it to the current pi_list. Note that at this moment, the pending owner + is no longer on the list of waiters. This is fine, since the pending owner + would add itself back when it realizes that it had the ownership stolen + from itself. When the pending owner tries to grab the mutex, it will fail + in try_to_take_rt_mutex if the owner field points to another process. + + 2) No owner + ----------- + + If there is no owner (or we successfully stole the lock), we set the owner + of the mutex to current, and set the flag of "Has Waiters" if the current + mutex actually has waiters, or we clear the flag if it doesn't. See, it was + OK that we set that flag early, since now it is cleared. + + 3) Failed to grab ownership + --------------------------- + + The most interesting case is when we fail to take ownership. This means that + there exists an owner, or there's a pending owner with equal or higher + priority than the current task. + +We'll continue on the failed case. + +If the mutex has a timeout, we set up a timer to go off to break us out +of this mutex if we failed to get it after a specified amount of time. + +Now we enter a loop that will continue to try to take ownership of the mutex, or +fail from a timeout or signal. + +Once again we try to take the mutex. This will usually fail the first time +in the loop, since it had just failed to get the mutex. But the second time +in the loop, this would likely succeed, since the task would likely be +the pending owner. + +If the mutex is TASK_INTERRUPTIBLE a check for signals and timeout is done +here. + +The waiter structure has a "task" field that points to the task that is blocked +on the mutex. This field can be NULL the first time it goes through the loop +or if the task is a pending owner and had it's mutex stolen. If the "task" +field is NULL then we need to set up the accounting for it. + +Task blocks on mutex +-------------------- + +The accounting of a mutex and process is done with the waiter structure of +the process. The "task" field is set to the process, and the "lock" field +to the mutex. The plist nodes are initialized to the processes current +priority. + +Since the wait_lock was taken at the entry of the slow lock, we can safely +add the waiter to the wait_list. If the current process is the highest +priority process currently waiting on this mutex, then we remove the +previous top waiter process (if it exists) from the pi_list of the owner, +and add the current process to that list. Since the pi_list of the owner +has changed, we call rt_mutex_adjust_prio on the owner to see if the owner +should adjust its priority accordingly. + +If the owner is also blocked on a lock, and had its pi_list changed +(or deadlock checking is on), we unlock the wait_lock of the mutex and go ahead +and run rt_mutex_adjust_prio_chain on the owner, as described earlier. + +Now all locks are released, and if the current process is still blocked on a +mutex (waiter "task" field is not NULL), then we go to sleep (call schedule). + +Waking up in the loop +--------------------- + +The schedule can then wake up for a few reasons. + 1) we were given pending ownership of the mutex. + 2) we received a signal and was TASK_INTERRUPTIBLE + 3) we had a timeout and was TASK_INTERRUPTIBLE + +In any of these cases, we continue the loop and once again try to grab the +ownership of the mutex. If we succeed, we exit the loop, otherwise we continue +and on signal and timeout, will exit the loop, or if we had the mutex stolen +we just simply add ourselves back on the lists and go back to sleep. + +Note: For various reasons, because of timeout and signals, the steal mutex + algorithm needs to be careful. This is because the current process is + still on the wait_list. And because of dynamic changing of priorities, + especially on SCHED_OTHER tasks, the current process can be the + highest priority task on the wait_list. + +Failed to get mutex on Timeout or Signal +---------------------------------------- + +If a timeout or signal occurred, the waiter's "task" field would not be +NULL and the task needs to be taken off the wait_list of the mutex and perhaps +pi_list of the owner. If this process was a high priority process, then +the rt_mutex_adjust_prio_chain needs to be executed again on the owner, +but this time it will be lowering the priorities. + + +Unlocking the Mutex +------------------- + +The unlocking of a mutex also has a fast path for those architectures with +CMPXCHG. Since the taking of a mutex on contention always sets the +"Has Waiters" flag of the mutex's owner, we use this to know if we need to +take the slow path when unlocking the mutex. If the mutex doesn't have any +waiters, the owner field of the mutex would equal the current process and +the mutex can be unlocked by just replacing the owner field with NULL. + +If the owner field has the "Has Waiters" bit set (or CMPXCHG is not available), +the slow unlock path is taken. + +The first thing done in the slow unlock path is to take the wait_lock of the +mutex. This synchronizes the locking and unlocking of the mutex. + +A check is made to see if the mutex has waiters or not. On architectures that +do not have CMPXCHG, this is the location that the owner of the mutex will +determine if a waiter needs to be awoken or not. On architectures that +do have CMPXCHG, that check is done in the fast path, but it is still needed +in the slow path too. If a waiter of a mutex woke up because of a signal +or timeout between the time the owner failed the fast path CMPXCHG check and +the grabbing of the wait_lock, the mutex may not have any waiters, thus the +owner still needs to make this check. If there are no waiters than the mutex +owner field is set to NULL, the wait_lock is released and nothing more is +needed. + +If there are waiters, then we need to wake one up and give that waiter +pending ownership. + +On the wake up code, the pi_lock of the current owner is taken. The top +waiter of the lock is found and removed from the wait_list of the mutex +as well as the pi_list of the current owner. The task field of the new +pending owner's waiter structure is set to NULL, and the owner field of the +mutex is set to the new owner with the "Pending Owner" bit set, as well +as the "Has Waiters" bit if there still are other processes blocked on the +mutex. + +The pi_lock of the previous owner is released, and the new pending owner's +pi_lock is taken. Remember that this is the trick to prevent the race +condition in rt_mutex_adjust_prio_chain from adding itself as a waiter +on the mutex. + +We now clear the "pi_blocked_on" field of the new pending owner, and if +the mutex still has waiters pending, we add the new top waiter to the pi_list +of the pending owner. + +Finally we unlock the pi_lock of the pending owner and wake it up. + + +Contact +------- + +For updates on this document, please email Steven Rostedt <rostedt@goodmis.org> + + +Credits +------- + +Author: Steven Rostedt <rostedt@goodmis.org> + +Reviewers: Ingo Molnar, Thomas Gleixner, Thomas Duetsch, and Randy Dunlap + +Updates +------- + +This document was originally written for 2.6.17-rc3-mm1 diff --git a/Documentation/rt-mutex.txt b/Documentation/rt-mutex.txt new file mode 100644 index 000000000..243393d88 --- /dev/null +++ b/Documentation/rt-mutex.txt @@ -0,0 +1,79 @@ +RT-mutex subsystem with PI support +---------------------------------- + +RT-mutexes with priority inheritance are used to support PI-futexes, +which enable pthread_mutex_t priority inheritance attributes +(PTHREAD_PRIO_INHERIT). [See Documentation/pi-futex.txt for more details +about PI-futexes.] + +This technology was developed in the -rt tree and streamlined for +pthread_mutex support. + +Basic principles: +----------------- + +RT-mutexes extend the semantics of simple mutexes by the priority +inheritance protocol. + +A low priority owner of a rt-mutex inherits the priority of a higher +priority waiter until the rt-mutex is released. If the temporarily +boosted owner blocks on a rt-mutex itself it propagates the priority +boosting to the owner of the other rt_mutex it gets blocked on. The +priority boosting is immediately removed once the rt_mutex has been +unlocked. + +This approach allows us to shorten the block of high-prio tasks on +mutexes which protect shared resources. Priority inheritance is not a +magic bullet for poorly designed applications, but it allows +well-designed applications to use userspace locks in critical parts of +an high priority thread, without losing determinism. + +The enqueueing of the waiters into the rtmutex waiter list is done in +priority order. For same priorities FIFO order is chosen. For each +rtmutex, only the top priority waiter is enqueued into the owner's +priority waiters list. This list too queues in priority order. Whenever +the top priority waiter of a task changes (for example it timed out or +got a signal), the priority of the owner task is readjusted. [The +priority enqueueing is handled by "plists", see include/linux/plist.h +for more details.] + +RT-mutexes are optimized for fastpath operations and have no internal +locking overhead when locking an uncontended mutex or unlocking a mutex +without waiters. The optimized fastpath operations require cmpxchg +support. [If that is not available then the rt-mutex internal spinlock +is used] + +The state of the rt-mutex is tracked via the owner field of the rt-mutex +structure: + +rt_mutex->owner holds the task_struct pointer of the owner. Bit 0 and 1 +are used to keep track of the "owner is pending" and "rtmutex has +waiters" state. + + owner bit1 bit0 + NULL 0 0 mutex is free (fast acquire possible) + NULL 0 1 invalid state + NULL 1 0 Transitional state* + NULL 1 1 invalid state + taskpointer 0 0 mutex is held (fast release possible) + taskpointer 0 1 task is pending owner + taskpointer 1 0 mutex is held and has waiters + taskpointer 1 1 task is pending owner and mutex has waiters + +Pending-ownership handling is a performance optimization: +pending-ownership is assigned to the first (highest priority) waiter of +the mutex, when the mutex is released. The thread is woken up and once +it starts executing it can acquire the mutex. Until the mutex is taken +by it (bit 0 is cleared) a competing higher priority thread can "steal" +the mutex which puts the woken up thread back on the waiters list. + +The pending-ownership optimization is especially important for the +uninterrupted workflow of high-prio tasks which repeatedly +takes/releases locks that have lower-prio waiters. Without this +optimization the higher-prio thread would ping-pong to the lower-prio +task [because at unlock time we always assign a new owner]. + +(*) The "mutex has waiters" bit gets set to take the lock. If the lock +doesn't already have an owner, this bit is quickly cleared if there are +no waiters. So this is a transitional state to synchronize with looking +at the owner field of the mutex and the mutex owner releasing the lock. diff --git a/Documentation/scsi/hptiop.txt b/Documentation/scsi/hptiop.txt new file mode 100644 index 000000000..d28a31247 --- /dev/null +++ b/Documentation/scsi/hptiop.txt @@ -0,0 +1,92 @@ +HIGHPOINT ROCKETRAID 3xxx RAID DRIVER (hptiop) + +Controller Register Map +------------------------- + +The controller IOP is accessed via PCI BAR0. + + BAR0 offset Register + 0x10 Inbound Message Register 0 + 0x14 Inbound Message Register 1 + 0x18 Outbound Message Register 0 + 0x1C Outbound Message Register 1 + 0x20 Inbound Doorbell Register + 0x24 Inbound Interrupt Status Register + 0x28 Inbound Interrupt Mask Register + 0x30 Outbound Interrupt Status Register + 0x34 Outbound Interrupt Mask Register + 0x40 Inbound Queue Port + 0x44 Outbound Queue Port + + +I/O Request Workflow +---------------------- + +All queued requests are handled via inbound/outbound queue port. +A request packet can be allocated in either IOP or host memory. + +To send a request to the controller: + + - Get a free request packet by reading the inbound queue port or + allocate a free request in host DMA coherent memory. + + The value returned from the inbound queue port is an offset + relative to the IOP BAR0. + + Requests allocated in host memory must be aligned on 32-bytes boundary. + + - Fill the packet. + + - Post the packet to IOP by writing it to inbound queue. For requests + allocated in IOP memory, write the offset to inbound queue port. For + requests allocated in host memory, write (0x80000000|(bus_addr>>5)) + to the inbound queue port. + + - The IOP process the request. When the request is completed, it + will be put into outbound queue. An outbound interrupt will be + generated. + + For requests allocated in IOP memory, the request offset is posted to + outbound queue. + + For requests allocated in host memory, (0x80000000|(bus_addr>>5)) + is posted to the outbound queue. If IOP_REQUEST_FLAG_OUTPUT_CONTEXT + flag is set in the request, the low 32-bit context value will be + posted instead. + + - The host read the outbound queue and complete the request. + + For requests allocated in IOP memory, the host driver free the request + by writing it to the outbound queue. + +Non-queued requests (reset/flush etc) can be sent via inbound message +register 0. An outbound message with the same value indicates the completion +of an inbound message. + + +User-level Interface +--------------------- + +The driver exposes following sysfs attributes: + + NAME R/W Description + driver-version R driver version string + firmware-version R firmware version string + +The driver registers char device "hptiop" to communicate with HighPoint RAID +management software. Its ioctl routine acts as a general binary interface +between the IOP firmware and HighPoint RAID management software. New management +functions can be implemented in application/firmware without modification +in driver code. + + +----------------------------------------------------------------------------- +Copyright (C) 2006 HighPoint Technologies, Inc. All Rights Reserved. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + linux@highpoint-tech.com + http://www.highpoint-tech.com diff --git a/Documentation/utrace.txt b/Documentation/utrace.txt new file mode 100644 index 000000000..73858ed6e --- /dev/null +++ b/Documentation/utrace.txt @@ -0,0 +1,455 @@ +DRAFT DRAFT DRAFT WORK IN PROGRESS DRAFT DRAFT DRAFT + +This is work in progress and likely to change. + + + Roland McGrath <roland@redhat.com> + +--- + + User Debugging Data & Event Rendezvous + ---- --------- ---- - ----- ---------- + +See linux/utrace.h for all the declarations used here. +See also linux/tracehook.h for the utrace_regset declarations. + +The UTRACE is infrastructure code for tracing and controlling user +threads. This is the foundation for writing tracing engines, which +can be loadable kernel modules. The UTRACE interfaces provide three +basic facilities: + +* Thread event reporting + + Tracing engines can request callbacks for events of interest in + the thread: signals, system calls, exit, exec, clone, etc. + +* Core thread control + + Tracing engines can prevent a thread from running (keeping it in + TASK_TRACED state), or make it single-step or block-step (when + hardware supports it). Engines can cause a thread to abort system + calls, they change the behaviors of signals, and they can inject + signal-style actions at will. + +* Thread machine state access + + Tracing engines can read and write a thread's registers and + similar per-thread CPU state. + + + Tracing engines + ------- ------- + +The basic actors in UTRACE are the thread and the tracing engine. +A tracing engine is some body of code that calls into the utrace_* +interfaces, represented by a struct utrace_engine_ops. (Usually it's a +kernel module, though the legacy ptrace support is a tracing engine +that is not in a kernel module.) The UTRACE interface operates on +individual threads (struct task_struct). If an engine wants to +treat several threads as a group, that is up to its higher-level +code. Using the UTRACE starts out by attaching an engine to a thread. + + struct utrace_attached_engine * + utrace_attach(struct task_struct *target, int flags, + const struct utrace_engine_ops *ops, unsigned long data); + +Calling utrace_attach is what sets up a tracing engine to trace a +thread. Use UTRACE_ATTACH_CREATE in flags, and pass your engine's ops. +Check the return value with IS_ERR. If successful, it returns a +struct pointer that is the handle used in all other utrace_* calls. +The data argument is stored in the utrace_attached_engine structure, +for your code to use however it wants. + + void utrace_detach(struct task_struct *target, + struct utrace_attached_engine *engine); + +The utrace_detach call removes an engine from a thread. +No more callbacks will be made after this returns. + + +An attached engine does nothing by default. +An engine makes something happen by setting its flags. + + void utrace_set_flags(struct task_struct *target, + struct utrace_attached_engine *engine, + unsigned long flags); + + + Action Flags + ------ ----- + +There are two kinds of flags that an attached engine can set: event +flags, and action flags. Event flags register interest in particular +events; when an event happens and an engine has the right event flag +set, it gets a callback. Action flags change the normal behavior of +the thread. The action flags available are: + + UTRACE_ACTION_QUIESCE + + The thread will stay quiescent (see below). + As long as any engine asserts the QUIESCE action flag, + the thread will not resume running in user mode. + (Usually it will be in TASK_TRACED state.) + Nothing will wake the thread up except for SIGKILL + (and implicit SIGKILLs such as a core dump in + another thread sharing the same address space, or a + group exit or fatal signal in another thread in the + same thread group). + + UTRACE_ACTION_SINGLESTEP + + When the thread runs, it will run one instruction + and then trap. (Exiting a system call or entering a + signal handler is considered "an instruction" for this.) + This can be used only if ARCH_HAS_SINGLE_STEP #define'd + by <asm/tracehook.h> and evaluates to nonzero. + + UTRACE_ACTION_BLOCKSTEP + + When the thread runs, it will run until the next branch, + and then trap. (Exiting a system call or entering a + signal handler is considered a branch for this.) + When the SINGLESTEP flag is set, BLOCKSTEP has no effect. + This is only available on some machines (actually none yet). + This can be used only if ARCH_HAS_BLOCK_STEP #define'd + by <asm/tracehook.h> and evaluates to nonzero. + + UTRACE_ACTION_NOREAP + + When the thread exits or stops for job control, its + parent process will not receive a SIGCHLD and the + parent's wait calls will not wake up or report the + child as dead. A well-behaved tracing engine does not + want to interfere with the parent's normal notifications. + This is provided mainly for the ptrace compatibility + code to implement the traditional behavior. + +Event flags are specified using the macro UTRACE_EVENT(TYPE). +Each event type is associated with a report_* callback in struct +utrace_engine_ops. A tracing engine can leave unused callbacks NULL. +The only callbacks required are those used by the event flags it sets. + +Many engines can be attached to each thread. When a thread has an +event, each engine gets a report_* callback if it has set the event flag +for that event type. Engines are called in the order they attached. + +Each callback takes arguments giving the details of the particular +event. The first two arguments two every callback are the struct +utrace_attached_engine and struct task_struct pointers for the engine +and the thread producing the event. Usually this will be the current +thread that is running the callback functions. + +The return value of report_* callbacks is a bitmask. Some bits are +common to all callbacks, and some are particular to that callback and +event type. The value zero (UTRACE_ACTION_RESUME) always means the +simplest thing: do what would have happened with no tracing engine here. +These are the flags that can be set in any report_* return value: + + UTRACE_ACTION_NEWSTATE + + Update the action state flags, described above. Those + bits from the return value (UTRACE_ACTION_STATE_MASK) + replace those bits in the engine's flags. This has the + same effect as calling utrace_set_flags, but is a more + efficient short-cut. To change the event flags, you must + call utrace_set_flags. + + UTRACE_ACTION_DETACH + + Detach this engine. This has the effect of calling + utrace_detach, but is a more efficient short-cut. + + UTRACE_ACTION_HIDE + + Hide this event from other tracing engines. This is + only appropriate to do when the event was induced by + some action of this engine, such as a breakpoint trap. + Some events cannot be hidden, since every engine has to + know about them: exit, death, reap. + +The return value bits in UTRACE_ACTION_OP_MASK indicate a change to the +normal behavior of the event taking place. If zero, the thread does +whatever that event normally means. For report_signal, other values +control the disposition of the signal. + + + Quiescence + ---------- + +To control another thread and access its state, it must be "quiescent". +This means that it is stopped and won't start running again while we access +it. A quiescent thread is stopped in a place close to user mode, where the +user state can be accessed safely; either it's about to return to user +mode, or it's just entered the kernel from user mode, or it has already +finished exiting (TASK_ZOMBIE). Setting the UTRACE_ACTION_QUIESCE action +flag will force the attached thread to become quiescent soon. After +setting the flag, an engine must wait for an event callback when the thread +becomes quiescent. The thread may be running on another CPU, or may be in +an uninterruptible wait. When it is ready to be examined, it will make +callbacks to engines that set the UTRACE_EVENT(QUIESCE) event flag. + +As long as some engine has UTRACE_ACTION_QUIESCE set, then the thread will +remain stopped. SIGKILL will wake it up, but it will not run user code. +When the flag is cleared via utrace_set_flags or a callback return value, +the thread starts running again. + +During the event callbacks (report_*), the thread in question makes the +callback from a safe place. It is not quiescent, but it can safely access +its own state. Callbacks can access thread state directly without setting +the QUIESCE action flag. If a callback does want to prevent the thread +from resuming normal execution, it *must* use the QUIESCE action state +rather than simply blocking; see "Core Events & Callbacks", below. + + + Thread control + ------ ------- + +These calls must be made on a quiescent thread (or the current thread): + + int utrace_inject_signal(struct task_struct *target, + struct utrace_attached_engine *engine, + u32 action, siginfo_t *info, + const struct k_sigaction *ka); + +Cause a specified signal delivery in the target thread. This is not +like kill, which generates a signal to be dequeued and delivered later. +Injection directs the thread to deliver a signal now, before it next +resumes in user mode or dequeues any other pending signal. It's as if +the tracing engine intercepted a signal event and its report_signal +callback returned the action argument as its value (see below). The +info and ka arguments serve the same purposes as their counterparts in +a report_signal callback. + + const struct utrace_regset * + utrace_regset(struct task_struct *target, + struct utrace_attached_engine *engine, + const struct utrace_regset_view *view, + int which); + +Get access to machine state for the thread. The struct utrace_regset_view +indicates a view of machine state, corresponding to a user mode +architecture personality (such as 32-bit or 64-bit versions of a machine). +The which argument selects one of the register sets available in that view. +The utrace_regset call must be made before accessing any machine state, +each time the thread has been running and has then become quiescent. +It ensures that the thread's state is ready to be accessed, and returns +the struct utrace_regset giving its accessor functions. + +XXX needs front ends for argument checks, export utrace_native_view + + + Core Events & Callbacks + ---- ------ - --------- + +Event reporting callbacks have details particular to the event type, but +are all called in similar environments and have the same constraints. +Callbacks are made from safe spots, where no locks are held, no special +resources are pinned, and the user-mode state of the thread is accessible. +So, callback code has a pretty free hand. But to be a good citizen, +callback code should never block for long periods. It is fine to block in +kmalloc and the like, but never wait for i/o or for user mode to do +something. If you need the thread to wait, set UTRACE_ACTION_QUIESCE and +return from the callback quickly. When your i/o finishes or whatever, you +can use utrace_set_flags to resume the thread. + +Well-behaved callbacks are important to maintain two essential properties +of the interface. The first of these is that unrelated tracing engines not +interfere with each other. If your engine's event callback does not return +quickly, then another engine won't get the event notification in a timely +manner. The second important property is that tracing be as noninvasive as +possible to the normal operation of the system overall and of the traced +thread in particular. That is, attached tracing engines should not perturb +a thread's behavior, except to the extent that changing its user-visible +state is explicitly what you want to do. (Obviously some perturbation is +unavoidable, primarily timing changes, ranging from small delays due to the +overhead of tracing, to arbitrary pauses in user code execution when a user +stops a thread with a debugger for examination. When doing asynchronous +utrace_attach to a thread doing a system call, more troublesome side +effects are possible.) Even when you explicitly want the pertrubation of +making the traced thread block, just blocking directly in your callback has +more unwanted effects. For example, the CLONE event callbacks are called +when the new child thread has been created but not yet started running; the +child can never be scheduled until the CLONE tracing callbacks return. +(This allows engines tracing the parent to attach to the child.) If a +CLONE event callback blocks the parent thread, it also prevents the child +thread from running (even to process a SIGKILL). If what you want is to +make both the parent and child block, then use utrace_attach on the child +and then set the QUIESCE action state flag on both threads. A more crucial +problem with blocking in callbacks is that it can prevent SIGKILL from +working. A thread that is blocking due to UTRACE_ACTION_QUIESCE will still +wake up and die immediately when sent a SIGKILL, as all threads should. +Relying on the utrace infrastructure rather than on private synchronization +calls in event callbacks is an important way to help keep tracing robustly +noninvasive. + + +EVENT(REAP) Dead thread has been reaped +Callback: + void (*report_reap)(struct utrace_attached_engine *engine, + struct task_struct *tsk); + +This means the parent called wait, or else this was a detached thread or +a process whose parent ignores SIGCHLD. This cannot happen while the +UTRACE_ACTION_NOREAP flag is set. This is the only callback you are +guaranteed to get (if you set the flag). + +Unlike other callbacks, this can be called from the parent's context +rather than from the traced thread itself--it must not delay the parent by +blocking. This callback is different from all others, it returns void. +Once you get this callback, your engine is automatically detached and you +cannot access this thread or use this struct utrace_attached_engine handle +any longer. This is the place to clean up your data structures and +synchronize with your code that might try to make utrace_* calls using this +engine data structure. The struct is still valid during this callback, +but will be freed soon after it returns (via RCU). + +In all other callbacks, the return value is as described above. +The common UTRACE_ACTION_* flags in the return value are always observed. +Unless otherwise specified below, other bits in the return value are ignored. + + +EVENT(QUIESCE) Thread is quiescent +Callback: + u32 (*report_quiesce)(struct utrace_attached_engine *engine, + struct task_struct *tsk); + +This is the least interesting callback. It happens at any safe spot, +including after any other event callback. This lets the tracing engine +know that it is safe to access the thread's state, or to report to users +that it has stopped running user code. + +EVENT(CLONE) Thread is creating a child +Callback: + u32 (*report_clone)(struct utrace_attached_engine *engine, + struct task_struct *parent, + unsigned long clone_flags, + struct task_struct *child); + +A clone/clone2/fork/vfork system call has succeeded in creating a new +thread or child process. The new process is fully formed, but not yet +running. During this callback, other tracing engines are prevented from +using utrace_attach asynchronously on the child, so that engines tracing +the parent get the first opportunity to attach. After this callback +returns, the child will start and the parent's system call will return. +If CLONE_VFORK is set, the parent will block before returning. + +EVENT(VFORK_DONE) Finished waiting for CLONE_VFORK child +Callback: + u32 (*report_vfork_done)(struct utrace_attached_engine *engine, + struct task_struct *parent, pid_t child_pid); + +Event reported for parent using CLONE_VFORK or vfork system call. +The child has died or exec'd, so the vfork parent has unblocked +and is about to return child_pid. + +UTRACE_EVENT(EXEC) Completed exec +Callback: + u32 (*report_exec)(struct utrace_attached_engine *engine, + struct task_struct *tsk, + const struct linux_binprm *bprm, + struct pt_regs *regs); + +An execve system call has succeeded and the new program is about to +start running. The initial user register state is handy to be tweaked +directly, or utrace_regset can be used for full machine state access. + +UTRACE_EVENT(EXIT) Thread is exiting +Callback: + u32 (*report_exit)(struct utrace_attached_engine *engine, + struct task_struct *tsk, + long orig_code, long *code); + +The thread is exiting and cannot be prevented from doing so, but all its +state is still live. The *code value will be the wait result seen by +the parent, and can be changed by this engine or others. The orig_code +value is the real status, not changed by any tracing engine. + +UTRACE_EVENT(DEATH) Thread has finished exiting +Callback: + u32 (*report_death)(struct utrace_attached_engine *engine, + struct task_struct *tsk); + +The thread is really dead now. If the UTRACE_ACTION_NOREAP flag is set +after this callback, it remains an unreported zombie. Otherwise, it might +be reaped by its parent, or self-reap immediately. Though the actual +reaping may happen in parallel, a report_reap callback will always be +ordered after a report_death callback. + +UTRACE_EVENT(SYSCALL_ENTRY) Thread has entered kernel for a system call +Callback: + u32 (*report_syscall_entry)(struct utrace_attached_engine *engine, + struct task_struct *tsk, + struct pt_regs *regs); + +The system call number and arguments can be seen and modified in the +registers. The return value register has -ENOSYS, which will be +returned for an invalid system call. The macro tracehook_abort_syscall(regs) +will abort the system call so that we go immediately to syscall exit, +and return -ENOSYS (or whatever the register state is changed to). If +tracing enginges keep the thread quiescent here, the system call will +not be performed until it resumes. + +UTRACE_EVENT(SYSCALL_EXIT) Thread is leaving kernel after a system call +Callback: + u32 (*report_syscall_exit)(struct utrace_attached_engine *engine, + struct task_struct *tsk, + struct pt_regs *regs); + +The return value can be seen and modified in the registers. If the +thread is allowed to resume, it will see any pending signals and then +return to user mode. + +UTRACE_EVENT(SIGNAL) Signal caught by user handler +UTRACE_EVENT(SIGNAL_IGN) Signal with no effect (SIG_IGN or default) +UTRACE_EVENT(SIGNAL_STOP) Job control stop signal +UTRACE_EVENT(SIGNAL_TERM) Fatal termination signal +UTRACE_EVENT(SIGNAL_CORE) Fatal core-dump signal +UTRACE_EVENT_SIGNAL_ALL All of the above (bitmask) +Callback: + u32 (*report_signal)(struct utrace_attached_engine *engine, + struct task_struct *tsk, + u32 action, siginfo_t *info, + const struct k_sigaction *orig_ka, + struct k_sigaction *return_ka); + +There are five types of signal events, but all use the same callback. +These happen when a thread is dequeuing a signal to be delivered. +(Not immediately when the signal is sent, and not when the signal is +blocked.) No signal event is reported for SIGKILL; no tracing engine +can prevent it from killing the thread immediately. The specific +event types allow an engine to trace signals based on what they do. +UTRACE_EVENT_SIGNAL_ALL is all of them OR'd together, to trace all +signals (except SIGKILL). A subset of these event flags can be used +e.g. to catch only fatal signals, not handled ones, or to catch only +core-dump signals, not normal termination signals. + +The action argument says what the signal's default disposition is: + + UTRACE_SIGNAL_DELIVER Run the user handler from sigaction. + UTRACE_SIGNAL_IGN Do nothing, ignore the signal. + UTRACE_SIGNAL_TERM Terminate the process. + UTRACE_SIGNAL_CORE Terminate the process a write a core dump. + UTRACE_SIGNAL_STOP Absolutely stop the process, a la SIGSTOP. + UTRACE_SIGNAL_TSTP Job control stop (no stop if orphaned). + +This selection is made from consulting the process's sigaction and the +default action for the signal number, but may already have been +changed by an earlier tracing engine (in which case you see its override). +A return value of UTRACE_ACTION_RESUME means to carry out this action. +If instead UTRACE_SIGNAL_* bits are in the return value, that overrides +the normal behavior of the signal. + +The signal number and other details of the signal are in info, and +this data can be changed to make the thread see a different signal. +A return value of UTRACE_SIGNAL_DELIVER says to follow the sigaction in +return_ka, which can specify a user handler or SIG_IGN to ignore the +signal or SIG_DFL to follow the default action for info->si_signo. +The orig_ka parameter shows the process's sigaction at the time the +signal was dequeued, and return_ka initially contains this. Tracing +engines can modify return_ka to change the effects of delivery. +For other UTRACE_SIGNAL_* return values, return_ka is ignored. + +UTRACE_SIGNAL_HOLD is a flag bit that can be OR'd into the return +value. It says to push the signal back on the thread's queue, with +the signal number and details possibly changed in info. When the +thread is allowed to resume, it will dequeue and report it again. diff --git a/Documentation/video4linux/README.pvrusb2 b/Documentation/video4linux/README.pvrusb2 new file mode 100644 index 000000000..c73a32c34 --- /dev/null +++ b/Documentation/video4linux/README.pvrusb2 @@ -0,0 +1,212 @@ + +$Id$ +Mike Isely <isely@pobox.com> + + pvrusb2 driver + +Background: + + This driver is intended for the "Hauppauge WinTV PVR USB 2.0", which + is a USB 2.0 hosted TV Tuner. This driver is a work in progress. + Its history started with the reverse-engineering effort by Björn + Danielsson <pvrusb2@dax.nu> whose web page can be found here: + + http://pvrusb2.dax.nu/ + + From there Aurelien Alleaume <slts@free.fr> began an effort to + create a video4linux compatible driver. I began with Aurelien's + last known snapshot and evolved the driver to the state it is in + here. + + More information on this driver can be found at: + + http://www.isely.net/pvrusb2.html + + + This driver has a strong separation of layers. They are very + roughly: + + 1a. Low level wire-protocol implementation with the device. + + 1b. I2C adaptor implementation and corresponding I2C client drivers + implemented elsewhere in V4L. + + 1c. High level hardware driver implementation which coordinates all + activities that ensure correct operation of the device. + + 2. A "context" layer which manages instancing of driver, setup, + tear-down, arbitration, and interaction with high level + interfaces appropriately as devices are hotplugged in the + system. + + 3. High level interfaces which glue the driver to various published + Linux APIs (V4L, sysfs, maybe DVB in the future). + + The most important shearing layer is between the top 2 layers. A + lot of work went into the driver to ensure that any kind of + conceivable API can be laid on top of the core driver. (Yes, the + driver internally leverages V4L to do its work but that really has + nothing to do with the API published by the driver to the outside + world.) The architecture allows for different APIs to + simultaneously access the driver. I have a strong sense of fairness + about APIs and also feel that it is a good design principle to keep + implementation and interface isolated from each other. Thus while + right now the V4L high level interface is the most complete, the + sysfs high level interface will work equally well for similar + functions, and there's no reason I see right now why it shouldn't be + possible to produce a DVB high level interface that can sit right + alongside V4L. + + NOTE: Complete documentation on the pvrusb2 driver is contained in + the html files within the doc directory; these are exactly the same + as what is on the web site at the time. Browse those files + (especially the FAQ) before asking questions. + + +Building + + To build these modules essentially amounts to just running "Make", + but you need the kernel source tree nearby and you will likely also + want to set a few controlling environment variables first in order + to link things up with that source tree. Please see the Makefile + here for comments that explain how to do that. + + +Source file list / functional overview: + + (Note: The term "module" used below generally refers to loosely + defined functional units within the pvrusb2 driver and bears no + relation to the Linux kernel's concept of a loadable module.) + + pvrusb2-audio.[ch] - This is glue logic that resides between this + driver and the msp3400.ko I2C client driver (which is found + elsewhere in V4L). + + pvrusb2-context.[ch] - This module implements the context for an + instance of the driver. Everything else eventually ties back to + or is otherwise instanced within the data structures implemented + here. Hotplugging is ultimately coordinated here. All high level + interfaces tie into the driver through this module. This module + helps arbitrate each interface's access to the actual driver core, + and is designed to allow concurrent access through multiple + instances of multiple interfaces (thus you can for example change + the tuner's frequency through sysfs while simultaneously streaming + video through V4L out to an instance of mplayer). + + pvrusb2-debug.h - This header defines a printk() wrapper and a mask + of debugging bit definitions for the various kinds of debug + messages that can be enabled within the driver. + + pvrusb2-debugifc.[ch] - This module implements a crude command line + oriented debug interface into the driver. Aside from being part + of the process for implementing manual firmware extraction (see + the pvrusb2 web site mentioned earlier), probably I'm the only one + who has ever used this. It is mainly a debugging aid. + + pvrusb2-eeprom.[ch] - This is glue logic that resides between this + driver the tveeprom.ko module, which is itself implemented + elsewhere in V4L. + + pvrusb2-encoder.[ch] - This module implements all protocol needed to + interact with the Conexant mpeg2 encoder chip within the pvrusb2 + device. It is a crude echo of corresponding logic in ivtv, + however the design goals (strict isolation) and physical layer + (proxy through USB instead of PCI) are enough different that this + implementation had to be completely different. + + pvrusb2-hdw-internal.h - This header defines the core data structure + in the driver used to track ALL internal state related to control + of the hardware. Nobody outside of the core hardware-handling + modules should have any business using this header. All external + access to the driver should be through one of the high level + interfaces (e.g. V4L, sysfs, etc), and in fact even those high + level interfaces are restricted to the API defined in + pvrusb2-hdw.h and NOT this header. + + pvrusb2-hdw.h - This header defines the full internal API for + controlling the hardware. High level interfaces (e.g. V4L, sysfs) + will work through here. + + pvrusb2-hdw.c - This module implements all the various bits of logic + that handle overall control of a specific pvrusb2 device. + (Policy, instantiation, and arbitration of pvrusb2 devices fall + within the jurisdiction of pvrusb-context not here). + + pvrusb2-i2c-chips-*.c - These modules implement the glue logic to + tie together and configure various I2C modules as they attach to + the I2C bus. There are two versions of this file. The "v4l2" + version is intended to be used in-tree alongside V4L, where we + implement just the logic that makes sense for a pure V4L + environment. The "all" version is intended for use outside of + V4L, where we might encounter other possibly "challenging" modules + from ivtv or older kernel snapshots (or even the support modules + in the standalone snapshot). + + pvrusb2-i2c-cmd-v4l1.[ch] - This module implements generic V4L1 + compatible commands to the I2C modules. It is here where state + changes inside the pvrusb2 driver are translated into V4L1 + commands that are in turn send to the various I2C modules. + + pvrusb2-i2c-cmd-v4l2.[ch] - This module implements generic V4L2 + compatible commands to the I2C modules. It is here where state + changes inside the pvrusb2 driver are translated into V4L2 + commands that are in turn send to the various I2C modules. + + pvrusb2-i2c-core.[ch] - This module provides an implementation of a + kernel-friendly I2C adaptor driver, through which other external + I2C client drivers (e.g. msp3400, tuner, lirc) may connect and + operate corresponding chips within the the pvrusb2 device. It is + through here that other V4L modules can reach into this driver to + operate specific pieces (and those modules are in turn driven by + glue logic which is coordinated by pvrusb2-hdw, doled out by + pvrusb2-context, and then ultimately made available to users + through one of the high level interfaces). + + pvrusb2-io.[ch] - This module implements a very low level ring of + transfer buffers, required in order to stream data from the + device. This module is *very* low level. It only operates the + buffers and makes no attempt to define any policy or mechanism for + how such buffers might be used. + + pvrusb2-ioread.[ch] - This module layers on top of pvrusb2-io.[ch] + to provide a streaming API usable by a read() system call style of + I/O. Right now this is the only layer on top of pvrusb2-io.[ch], + however the underlying architecture here was intended to allow for + other styles of I/O to be implemented with additonal modules, like + mmap()'ed buffers or something even more exotic. + + pvrusb2-main.c - This is the top level of the driver. Module level + and USB core entry points are here. This is our "main". + + pvrusb2-sysfs.[ch] - This is the high level interface which ties the + pvrusb2 driver into sysfs. Through this interface you can do + everything with the driver except actually stream data. + + pvrusb2-tuner.[ch] - This is glue logic that resides between this + driver and the tuner.ko I2C client driver (which is found + elsewhere in V4L). + + pvrusb2-util.h - This header defines some common macros used + throughout the driver. These macros are not really specific to + the driver, but they had to go somewhere. + + pvrusb2-v4l2.[ch] - This is the high level interface which ties the + pvrusb2 driver into video4linux. It is through here that V4L + applications can open and operate the driver in the usual V4L + ways. Note that **ALL** V4L functionality is published only + through here and nowhere else. + + pvrusb2-video-*.[ch] - This is glue logic that resides between this + driver and the saa711x.ko I2C client driver (which is found + elsewhere in V4L). Note that saa711x.ko used to be known as + saa7115.ko in ivtv. There are two versions of this; one is + selected depending on the particular saa711[5x].ko that is found. + + pvrusb2.h - This header contains compile time tunable parameters + (and at the moment the driver has very little that needs to be + tuned). + + + -Mike Isely + isely@pobox.com + diff --git a/Documentation/video4linux/cx2341x/fw-calling.txt b/Documentation/video4linux/cx2341x/fw-calling.txt new file mode 100644 index 000000000..8d21181de --- /dev/null +++ b/Documentation/video4linux/cx2341x/fw-calling.txt @@ -0,0 +1,69 @@ +This page describes how to make calls to the firmware api. + +How to call +=========== + +The preferred calling convention is known as the firmware mailbox. The +mailboxes are basically a fixed length array that serves as the call-stack. + +Firmware mailboxes can be located by searching the encoder and decoder memory +for a 16 byte signature. That signature will be located on a 256-byte boundary. + +Signature: +0x78, 0x56, 0x34, 0x12, 0x12, 0x78, 0x56, 0x34, +0x34, 0x12, 0x78, 0x56, 0x56, 0x34, 0x12, 0x78 + +The firmware implements 20 mailboxes of 20 32-bit words. The first 10 are +reserved for API calls. The second 10 are used by the firmware for event +notification. + + Index Name + ----- ---- + 0 Flags + 1 Command + 2 Return value + 3 Timeout + 4-19 Parameter/Result + + +The flags are defined in the following table. The direction is from the +perspective of the firmware. + + Bit Direction Purpose + --- --------- ------- + 2 O Firmware has processed the command. + 1 I Driver has finished setting the parameters. + 0 I Driver is using this mailbox. + + +The command is a 32-bit enumerator. The API specifics may be found in the +fw-*-api.txt documents. + +The return value is a 32-bit enumerator. Only two values are currently defined: +0=success and -1=command undefined. + +There are 16 parameters/results 32-bit fields. The driver populates these fields +with values for all the parameters required by the call. The driver overwrites +these fields with result values returned by the call. The API specifics may be +found in the fw-*-api.txt documents. + +The timeout value protects the card from a hung driver thread. If the driver +doesn't handle the completed call within the timeout specified, the firmware +will reset that mailbox. + +To make an API call, the driver iterates over each mailbox looking for the +first one available (bit 0 has been cleared). The driver sets that bit, fills +in the command enumerator, the timeout value and any required parameters. The +driver then sets the parameter ready bit (bit 1). The firmware scans the +mailboxes for pending commands, processes them, sets the result code, populates +the result value array with that call's return values and sets the call +complete bit (bit 2). Once bit 2 is set, the driver should retrieve the results +and clear all the flags. If the driver does not perform this task within the +time set in the timeout register, the firmware will reset that mailbox. + +Event notifications are sent from the firmware to the host. The host tells the +firmware which events it is interested in via an API call. That call tells the +firmware which notification mailbox to use. The firmware signals the host via +an interrupt. Only the 16 Results fields are used, the Flags, Command, Return +value and Timeout words are not used. + diff --git a/Documentation/video4linux/cx2341x/fw-decoder-api.txt b/Documentation/video4linux/cx2341x/fw-decoder-api.txt new file mode 100644 index 000000000..9df4fb3ea --- /dev/null +++ b/Documentation/video4linux/cx2341x/fw-decoder-api.txt @@ -0,0 +1,319 @@ +Decoder firmware API description +================================ + +Note: this API is part of the decoder firmware, so it's cx23415 only. + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_PING_FW +Enum 0/0x00 +Description + This API call does nothing. It may be used to check if the firmware + is responding. + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_START_PLAYBACK +Enum 1/0x01 +Description + Begin or resume playback. +Param[0] + 0 based frame number in GOP to begin playback from. +Param[1] + Specifies the number of muted audio frames to play before normal + audio resumes. + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_STOP_PLAYBACK +Enum 2/0x02 +Description + Ends playback and clears all decoder buffers. If PTS is not zero, + playback stops at specified PTS. +Param[0] + Display 0=last frame, 1=black +Param[1] + PTS low +Param[2] + PTS high + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_SET_PLAYBACK_SPEED +Enum 3/0x03 +Description + Playback stream at speed other than normal. There are two modes of + operation: + Smooth: host transfers entire stream and firmware drops unused + frames. + Coarse: host drops frames based on indexing as required to achieve + desired speed. +Param[0] + Bitmap: + 0:7 0 normal + 1 fast only "1.5 times" + n nX fast, 1/nX slow + 30 Framedrop: + '0' during 1.5 times play, every other B frame is dropped + '1' during 1.5 times play, stream is unchanged (bitrate + must not exceed 8mbps) + 31 Speed: + '0' slow + '1' fast +Param[1] + Direction: 0=forward, 1=reverse +Param[2] + Picture mask: + 1=I frames + 3=I, P frames + 7=I, P, B frames +Param[3] + B frames per GOP (for reverse play only) +Param[4] + Mute audio: 0=disable, 1=enable +Param[5] + Display 0=frame, 1=field +Param[6] + Specifies the number of muted audio frames to play before normal audio + resumes. + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_STEP_VIDEO +Enum 5/0x05 +Description + Each call to this API steps the playback to the next unit defined below + in the current playback direction. +Param[0] + 0=frame, 1=top field, 2=bottom field + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_SET_DMA_BLOCK_SIZE +Enum 8/0x08 +Description + Set DMA transfer block size. Counterpart to API 0xC9 +Param[0] + DMA transfer block size in bytes. A different size may be specified + when issuing the DMA transfer command. + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_GET_XFER_INFO +Enum 9/0x09 +Description + This API call may be used to detect an end of stream condtion. +Result[0] + Stream type +Result[1] + Address offset +Result[2] + Maximum bytes to transfer +Result[3] + Buffer fullness + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_GET_DMA_STATUS +Enum 10/0x0A +Description + Status of the last DMA transfer +Result[0] + Bit 1 set means transfer complete + Bit 2 set means DMA error + Bit 3 set means linked list error +Result[1] + DMA type: 0=MPEG, 1=OSD, 2=YUV + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_SCHED_DMA_FROM_HOST +Enum 11/0x0B +Description + Setup DMA from host operation. Counterpart to API 0xCC +Param[0] + Memory address of link list +Param[1] + Total # of bytes to transfer +Param[2] + DMA type (0=MPEG, 1=OSD, 2=YUV) + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_PAUSE_PLAYBACK +Enum 13/0x0D +Description + Freeze playback immediately. In this mode, when internal buffers are + full, no more data will be accepted and data request IRQs will be + masked. +Param[0] + Display: 0=last frame, 1=black + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_HALT_FW +Enum 14/0x0E +Description + The firmware is halted and no further API calls are serviced until + the firmware is uploaded again. + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_SET_STANDARD +Enum 16/0x10 +Description + Selects display standard +Param[0] + 0=NTSC, 1=PAL + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_GET_VERSION +Enum 17/0x11 +Description + Returns decoder firmware version information +Result[0] + Version bitmask: + Bits 0:15 build + Bits 16:23 minor + Bits 24:31 major + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_SET_STREAM_INPUT +Enum 20/0x14 +Description + Select decoder stream input port +Param[0] + 0=memory (default), 1=streaming + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_GET_TIMING_INFO +Enum 21/0x15 +Description + Returns timing information from start of playback +Result[0] + Frame count by decode order +Result[1] + Video PTS bits 0:31 by display order +Result[2] + Video PTS bit 32 by display order +Result[3] + SCR bits 0:31 by display order +Result[4] + SCR bit 32 by display order + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_SET_AUDIO_MODE +Enum 22/0x16 +Description + Select audio mode +Param[0] + Dual mono mode action +Param[1] + Stereo mode action: + 0=Stereo, 1=Left, 2=Right, 3=Mono, 4=Swap, -1=Unchanged + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_SET_EVENT_NOTIFICATION +Enum 23/0x17 +Description + Setup firmware to notify the host about a particular event. + Counterpart to API 0xD5 +Param[0] + Event: 0=Audio mode change between stereo and dual channel +Param[1] + Notification 0=disabled, 1=enabled +Param[2] + Interrupt bit +Param[3] + Mailbox slot, -1 if no mailbox required. + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_SET_DISPLAY_BUFFERS +Enum 24/0x18 +Description + Number of display buffers. To decode all frames in reverse playback you + must use nine buffers. +Param[0] + 0=six buffers, 1=nine buffers + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_EXTRACT_VBI +Enum 25/0x19 +Description + Extracts VBI data +Param[0] + 0=extract from extension & user data, 1=extract from private packets +Result[0] + VBI table location +Result[1] + VBI table size + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_SET_DECODER_SOURCE +Enum 26/0x1A +Description + Selects decoder source. Ensure that the parameters passed to this + API match the encoder settings. +Param[0] + Mode: 0=MPEG from host, 1=YUV from encoder, 2=YUV from host +Param[1] + YUV picture width +Param[2] + YUV picture height +Param[3] + Bitmap: see Param[0] of API 0xBD + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_SET_AUDIO_OUTPUT +Enum 27/0x1B +Description + Select audio output format +Param[0] + Bitmask: + 0:1 Data size: + '00' 16 bit + '01' 20 bit + '10' 24 bit + 2:7 Unused + 8:9 Mode: + '00' 2 channels + '01' 4 channels + '10' 6 channels + '11' 6 channels with one line data mode + (for left justified MSB first mode, 20 bit only) + 10:11 Unused + 12:13 Channel format: + '00' right justified MSB first mode + '01' left justified MSB first mode + '10' I2S mode + 14:15 Unused + 16:21 Right justify bit count + 22:31 Unused + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_SET_AV_DELAY +Enum 28/0x1C +Description + Set audio/video delay in 90Khz ticks +Param[0] + 0=A/V in sync, negative=audio lags, positive=video lags + +------------------------------------------------------------------------------- + +Name CX2341X_DEC_SET_PREBUFFERING +Enum 30/0x1E +Description + Decoder prebuffering, when enabled up to 128KB are buffered for + streams <8mpbs or 640KB for streams >8mbps +Param[0] + 0=off, 1=on diff --git a/Documentation/video4linux/cx2341x/fw-dma.txt b/Documentation/video4linux/cx2341x/fw-dma.txt new file mode 100644 index 000000000..8123e262d --- /dev/null +++ b/Documentation/video4linux/cx2341x/fw-dma.txt @@ -0,0 +1,94 @@ +This page describes the structures and procedures used by the cx2341x DMA +engine. + +Introduction +============ + +The cx2341x PCI interface is busmaster capable. This means it has a DMA +engine to efficiently transfer large volumes of data between the card and main +memory without requiring help from a CPU. Like most hardware, it must operate +on contiguous physical memory. This is difficult to come by in large quantities +on virtual memory machines. + +Therefore, it also supports a technique called "scatter-gather". The card can +transfer multiple buffers in one operation. Instead of allocating one large +contiguous buffer, the driver can allocate several smaller buffers. + +In practice, I've seen the average transfer to be roughly 80K, but transfers +above 128K were not uncommon, particularly at startup. The 128K figure is +important, because that is the largest block that the kernel can normally +allocate. Even still, 128K blocks are hard to come by, so the driver writer is +urged to choose a smaller block size and learn the scatter-gather technique. + +Mailbox #10 is reserved for DMA transfer information. + +Flow +==== + +This section describes, in general, the order of events when handling DMA +transfers. Detailed information follows this section. + +- The card raises the Encoder interrupt. +- The driver reads the transfer type, offset and size from Mailbox #10. +- The driver constructs the scatter-gather array from enough free dma buffers + to cover the size. +- The driver schedules the DMA transfer via the ScheduleDMAtoHost API call. +- The card raises the DMA Complete interrupt. +- The driver checks the DMA status register for any errors. +- The driver post-processes the newly transferred buffers. + +NOTE! It is possible that the Encoder and DMA Complete interrupts get raised +simultaneously. (End of the last, start of the next, etc.) + +Mailbox #10 +=========== + +The Flags, Command, Return Value and Timeout fields are ignored. + +Name: Mailbox #10 +Results[0]: Type: 0: MPEG. +Results[1]: Offset: The position relative to the card's memory space. +Results[2]: Size: The exact number of bytes to transfer. + +My speculation is that since the StartCapture API has a capture type of "RAW" +available, that the type field will have other values that correspond to YUV +and PCM data. + +Scatter-Gather Array +==================== + +The scatter-gather array is a contiguously allocated block of memory that +tells the card the source and destination of each data-block to transfer. +Card "addresses" are derived from the offset supplied by Mailbox #10. Host +addresses are the physical memory location of the target DMA buffer. + +Each S-G array element is a struct of three 32-bit words. The first word is +the source address, the second is the destination address. Both take up the +entire 32 bits. The lowest 16 bits of the third word is the transfer byte +count. The high-bit of the third word is the "last" flag. The last-flag tells +the card to raise the DMA_DONE interrupt. From hard personal experience, if +you forget to set this bit, the card will still "work" but the stream will +most likely get corrupted. + +The transfer count must be a multiple of 256. Therefore, the driver will need +to track how much data in the target buffer is valid and deal with it +accordingly. + +Array Element: + +- 32-bit Source Address +- 32-bit Destination Address +- 16-bit reserved (high bit is the last flag) +- 16-bit byte count + +DMA Transfer Status +=================== + +Register 0x0004 holds the DMA Transfer Status: + +Bit +4 Scatter-Gather array error +3 DMA write error +2 DMA read error +1 write completed +0 read completed diff --git a/Documentation/video4linux/cx2341x/fw-encoder-api.txt b/Documentation/video4linux/cx2341x/fw-encoder-api.txt new file mode 100644 index 000000000..001c68644 --- /dev/null +++ b/Documentation/video4linux/cx2341x/fw-encoder-api.txt @@ -0,0 +1,694 @@ +Encoder firmware API description +================================ + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_PING_FW +Enum 128/0x80 +Description + Does nothing. Can be used to check if the firmware is responding. + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_START_CAPTURE +Enum 129/0x81 +Description + Commences the capture of video, audio and/or VBI data. All encoding + parameters must be initialized prior to this API call. Captures frames + continuously or until a predefined number of frames have been captured. +Param[0] + Capture stream type: + 0=MPEG + 1=Raw + 2=Raw passthrough + 3=VBI + +Param[1] + Bitmask: + Bit 0 when set, captures YUV + Bit 1 when set, captures PCM audio + Bit 2 when set, captures VBI (same as param[0]=3) + Bit 3 when set, the capture destination is the decoder + (same as param[0]=2) + Bit 4 when set, the capture destination is the host + Note: this parameter is only meaningful for RAW capture type. + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_STOP_CAPTURE +Enum 130/0x82 +Description + Ends a capture in progress +Param[0] + 0=stop at end of GOP (generates IRQ) + 1=stop immediate (no IRQ) +Param[1] + Stream type to stop, see param[0] of API 0x81 +Param[2] + Subtype, see param[1] of API 0x81 + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_AUDIO_ID +Enum 137/0x89 +Description + Assigns the transport stream ID of the encoded audio stream +Param[0] + Audio Stream ID + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_VIDEO_ID +Enum 139/0x8B +Description + Set video transport stream ID +Param[0] + Video stream ID + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_PCR_ID +Enum 141/0x8D +Description + Assigns the transport stream ID for PCR packets +Param[0] + PCR Stream ID + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_FRAME_RATE +Enum 143/0x8F +Description + Set video frames per second. Change occurs at start of new GOP. +Param[0] + 0=30fps + 1=25fps + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_FRAME_SIZE +Enum 145/0x91 +Description + Select video stream encoding resolution. +Param[0] + Height in lines. Default 480 +Param[1] + Width in pixels. Default 720 + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_BIT_RATE +Enum 149/0x95 +Description + Assign average video stream bitrate. Note on the last three params: + Param[3] and [4] seem to be always 0, param [5] doesn't seem to be used. +Param[0] + 0=variable bitrate, 1=constant bitrate +Param[1] + bitrate in bits per second +Param[2] + peak bitrate in bits per second, divided by 400 +Param[3] + Mux bitrate in bits per second, divided by 400. May be 0 (default). +Param[4] + Rate Control VBR Padding +Param[5] + VBV Buffer used by encoder + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_GOP_PROPERTIES +Enum 151/0x97 +Description + Setup the GOP structure +Param[0] + GOP size (maximum is 34) +Param[1] + Number of B frames between the I and P frame, plus 1. + For example: IBBPBBPBBPBB --> GOP size: 12, number of B frames: 2+1 = 3 + Note that GOP size must be a multiple of (B-frames + 1). + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_ASPECT_RATIO +Enum 153/0x99 +Description + Sets the encoding aspect ratio. Changes in the aspect ratio take effect + at the start of the next GOP. +Param[0] + '0000' forbidden + '0001' 1:1 square + '0010' 4:3 + '0011' 16:9 + '0100' 2.21:1 + '0101' reserved + .... + '1111' reserved + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_DNR_FILTER_MODE +Enum 155/0x9B +Description + Assign Dynamic Noise Reduction operating mode +Param[0] + Bit0: Spatial filter, set=auto, clear=manual + Bit1: Temporal filter, set=auto, clear=manual +Param[1] + Median filter: + 0=Disabled + 1=Horizontal + 2=Vertical + 3=Horiz/Vert + 4=Diagonal + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_DNR_FILTER_PROPS +Enum 157/0x9D +Description + These Dynamic Noise Reduction filter values are only meaningful when + the respective filter is set to "manual" (See API 0x9B) +Param[0] + Spatial filter: default 0, range 0:15 +Param[1] + Temporal filter: default 0, range 0:31 + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_CORING_LEVELS +Enum 159/0x9F +Description + Assign Dynamic Noise Reduction median filter properties. +Param[0] + Threshold above which the luminance median filter is enabled. + Default: 0, range 0:255 +Param[1] + Threshold below which the luminance median filter is enabled. + Default: 255, range 0:255 +Param[2] + Threshold above which the chrominance median filter is enabled. + Default: 0, range 0:255 +Param[3] + Threshold below which the chrominance median filter is enabled. + Default: 255, range 0:255 + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_SPATIAL_FILTER_TYPE +Enum 161/0xA1 +Description + Assign spatial prefilter parameters +Param[0] + Luminance filter + 0=Off + 1=1D Horizontal + 2=1D Vertical + 3=2D H/V Separable (default) + 4=2D Symmetric non-separable +Param[1] + Chrominance filter + 0=Off + 1=1D Horizontal (default) + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_3_2_PULLDOWN +Enum 177/0xB1 +Description + 3:2 pulldown properties +Param[0] + 0=enabled + 1=disabled + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_VBI_LINE +Enum 183/0xB7 +Description + Selects VBI line number. +Param[0] + Bits 0:4 line number + Bit 31 0=top_field, 1=bottom_field + Bits 0:31 all set specifies "all lines" +Param[1] + VBI line information features: 0=disabled, 1=enabled +Param[2] + Slicing: 0=None, 1=Closed Caption + Almost certainly not implemented. Set to 0. +Param[3] + Luminance samples in this line. + Almost certainly not implemented. Set to 0. +Param[4] + Chrominance samples in this line + Almost certainly not implemented. Set to 0. + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_STREAM_TYPE +Enum 185/0xB9 +Description + Assign stream type + Note: Transport stream is not working in recent firmwares. + And in older firmwares the timestamps in the TS seem to be + unreliable. +Param[0] + 0=Program stream + 1=Transport stream + 2=MPEG1 stream + 3=PES A/V stream + 5=PES Video stream + 7=PES Audio stream + 10=DVD stream + 11=VCD stream + 12=SVCD stream + 13=DVD_S1 stream + 14=DVD_S2 stream + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_OUTPUT_PORT +Enum 187/0xBB +Description + Assign stream output port. Normally 0 when the data is copied through + the PCI bus (DMA), and 1 when the data is streamed to another chip + (pvrusb and cx88-blackbird). +Param[0] + 0=Memory (default) + 1=Streaming + 2=Serial +Param[1] + Unknown, but leaving this to 0 seems to work best. Indications are that + this might have to do with USB support, although passing anything but 0 + onl breaks things. + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_AUDIO_PROPERTIES +Enum 189/0xBD +Description + Set audio stream properties, may be called while encoding is in progress. + Note: all bitfields are consistent with ISO11172 documentation except + bits 2:3 which ISO docs define as: + '11' Layer I + '10' Layer II + '01' Layer III + '00' Undefined + This discrepancy may indicate a possible error in the documentation. + Testing indicated that only Layer II is actually working, and that + the minimum bitrate should be 192 kbps. +Param[0] + Bitmask: + 0:1 '00' 44.1Khz + '01' 48Khz + '10' 32Khz + '11' reserved + + 2:3 '01'=Layer I + '10'=Layer II + + 4:7 Bitrate: + Index | Layer I | Layer II + ------+-------------+------------ + '0000' | free format | free format + '0001' | 32 kbit/s | 32 kbit/s + '0010' | 64 kbit/s | 48 kbit/s + '0011' | 96 kbit/s | 56 kbit/s + '0100' | 128 kbit/s | 64 kbit/s + '0101' | 160 kbit/s | 80 kbit/s + '0110' | 192 kbit/s | 96 kbit/s + '0111' | 224 kbit/s | 112 kbit/s + '1000' | 256 kbit/s | 128 kbit/s + '1001' | 288 kbit/s | 160 kbit/s + '1010' | 320 kbit/s | 192 kbit/s + '1011' | 352 kbit/s | 224 kbit/s + '1100' | 384 kbit/s | 256 kbit/s + '1101' | 416 kbit/s | 320 kbit/s + '1110' | 448 kbit/s | 384 kbit/s + Note: For Layer II, not all combinations of total bitrate + and mode are allowed. See ISO11172-3 3-Annex B, Table 3-B.2 + + 8:9 '00'=Stereo + '01'=JointStereo + '10'=Dual + '11'=Mono + Note: testing seems to indicate that Mono and possibly + JointStereo are not working (default to stereo). + Dual does work, though. + + 10:11 Mode Extension used in joint_stereo mode. + In Layer I and II they indicate which subbands are in + intensity_stereo. All other subbands are coded in stereo. + '00' subbands 4-31 in intensity_stereo, bound==4 + '01' subbands 8-31 in intensity_stereo, bound==8 + '10' subbands 12-31 in intensity_stereo, bound==12 + '11' subbands 16-31 in intensity_stereo, bound==16 + + 12:13 Emphasis: + '00' None + '01' 50/15uS + '10' reserved + '11' CCITT J.17 + + 14 CRC: + '0' off + '1' on + + 15 Copyright: + '0' off + '1' on + + 16 Generation: + '0' copy + '1' original + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_HALT_FW +Enum 195/0xC3 +Description + The firmware is halted and no further API calls are serviced until the + firmware is uploaded again. + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_GET_VERSION +Enum 196/0xC4 +Description + Returns the version of the encoder firmware. +Result[0] + Version bitmask: + Bits 0:15 build + Bits 16:23 minor + Bits 24:31 major + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_GOP_CLOSURE +Enum 197/0xC5 +Description + Assigns the GOP open/close property. +Param[0] + 0=Open + 1=Closed + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_GET_SEQ_END +Enum 198/0xC6 +Description + Obtains the sequence end code of the encoder's buffer. When a capture + is started a number of interrupts are still generated, the last of + which will have Result[0] set to 1 and Result[1] will contain the size + of the buffer. +Result[0] + State of the transfer (1 if last buffer) +Result[1] + If Result[0] is 1, this contains the size of the last buffer, undefined + otherwise. + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_PGM_INDEX_INFO +Enum 199/0xC7 +Description + Sets the Program Index Information. +Param[0] + Picture Mask: + 0=No index capture + 1=I frames + 3=I,P frames + 7=I,P,B frames +Param[1] + Elements requested (up to 400) +Result[0] + Offset in SDF memory of the table. +Result[1] + Number of allocated elements up to a maximum of Param[1] + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_VBI_CONFIG +Enum 200/0xC8 +Description + Configure VBI settings +Param[0] + Bitmap: + 0 Mode '0' Sliced, '1' Raw + 1:3 Insertion: + '000' insert in extension & user data + '001' insert in private packets + '010' separate stream and user data + '111' separate stream and private data + 8:15 Stream ID (normally 0xBD) +Param[1] + Frames per interrupt (max 8). Only valid in raw mode. +Param[2] + Total raw VBI frames. Only valid in raw mode. +Param[3] + Start codes +Param[4] + Stop codes +Param[5] + Lines per frame +Param[6] + Byte per line +Result[0] + Observed frames per interrupt in raw mode only. Rage 1 to Param[1] +Result[1] + Observed number of frames in raw mode. Range 1 to Param[2] +Result[2] + Memory offset to start or raw VBI data + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_DMA_BLOCK_SIZE +Enum 201/0xC9 +Description + Set DMA transfer block size +Param[0] + DMA transfer block size in bytes or frames. When unit is bytes, + supported block sizes are 2^7, 2^8 and 2^9 bytes. +Param[1] + Unit: 0=bytes, 1=frames + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_GET_PREV_DMA_INFO_MB_10 +Enum 202/0xCA +Description + Returns information on the previous DMA transfer in conjunction with + bit 27 of the interrupt mask. Uses mailbox 10. +Result[0] + Type of stream +Result[1] + Address Offset +Result[2] + Maximum size of transfer + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_GET_PREV_DMA_INFO_MB_9 +Enum 203/0xCB +Description + Returns information on the previous DMA transfer in conjunction with + bit 27 of the interrupt mask. Uses mailbox 9. +Result[0] + Status bits: + Bit 0 set indicates transfer complete + Bit 2 set indicates transfer error + Bit 4 set indicates linked list error +Result[1] + DMA type +Result[2] + Presentation Time Stamp bits 0..31 +Result[3] + Presentation Time Stamp bit 32 + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SCHED_DMA_TO_HOST +Enum 204/0xCC +Description + Setup DMA to host operation +Param[0] + Memory address of link list +Param[1] + Length of link list (wtf: what units ???) +Param[2] + DMA type (0=MPEG) + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_INITIALIZE_INPUT +Enum 205/0xCD +Description + Initializes the video input + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_FRAME_DROP_RATE +Enum 208/0xD0 +Description + For each frame captured, skip specified number of frames. +Param[0] + Number of frames to skip + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_PAUSE_ENCODER +Enum 210/0xD2 +Description + During a pause condition, all frames are dropped instead of being encoded. +Param[0] + 0=Pause encoding + 1=Continue encoding + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_REFRESH_INPUT +Enum 211/0xD3 +Description + Refreshes the video input + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_COPYRIGHT +Enum 212/0xD4 +Description + Sets stream copyright property +Param[0] + 0=Stream is not copyrighted + 1=Stream is copyrighted + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_EVENT_NOTIFICATION +Enum 213/0xD5 +Description + Setup firmware to notify the host about a particular event. Host must + unmask the interrupt bit. +Param[0] + Event (0=refresh encoder input) +Param[1] + Notification 0=disabled 1=enabled +Param[2] + Interrupt bit +Param[3] + Mailbox slot, -1 if no mailbox required. + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_NUM_VSYNC_LINES +Enum 214/0xD6 +Description + Depending on the analog video decoder used, this assigns the number + of lines for field 1 and 2. +Param[0] + Field 1 number of lines: + 0x00EF for SAA7114 + 0x00F0 for SAA7115 + 0x0105 for Micronas +Param[1] + Field 2 number of lines: + 0x00EF for SAA7114 + 0x00F0 for SAA7115 + 0x0106 for Micronas + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_SET_PLACEHOLDER +Enum 215/0xD7 +Description + Provides a mechanism of inserting custom user data in the MPEG stream. +Param[0] + 0=extension & user data + 1=private packet with stream ID 0xBD +Param[1] + Rate at which to insert data, in units of frames (for private packet) + or GOPs (for ext. & user data) +Param[2] + Number of data DWORDs (below) to insert +Param[3] + Custom data 0 +Param[4] + Custom data 1 +Param[5] + Custom data 2 +Param[6] + Custom data 3 +Param[7] + Custom data 4 +Param[8] + Custom data 5 +Param[9] + Custom data 6 +Param[10] + Custom data 7 +Param[11] + Custom data 8 + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_MUTE_VIDEO +Enum 217/0xD9 +Description + Video muting +Param[0] + Bit usage: + 0 '0'=video not muted + '1'=video muted, creates frames with the YUV color defined below + 1:7 Unused + 8:15 V chrominance information + 16:23 U chrominance information + 24:31 Y luminance information + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_MUTE_AUDIO +Enum 218/0xDA +Description + Audio muting +Param[0] + 0=audio not muted + 1=audio muted (produces silent mpeg audio stream) + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_UNKNOWN +Enum 219/0xDB +Description + Unknown API, it's used by Hauppauge though. +Param[0] + 0 This is the value Hauppauge uses, Unknown what it means. + +------------------------------------------------------------------------------- + +Name CX2341X_ENC_MISC +Enum 220/0xDC +Description + Miscellaneous actions. Not known for 100% what it does. It's really a + sort of ioctl call. The first parameter is a command number, the second + the value. +Param[0] + Command number: + 1=set initial SCR value when starting encoding. + 2=set quality mode (apparently some test setting). + 3=setup advanced VIM protection handling (supposedly only for the cx23416 + for raw YUV). + Actually it looks like this should be 0 for saa7114/5 based card and 1 + for cx25840 based cards. + 4=generate artificial PTS timestamps + 5=USB flush mode + 6=something to do with the quantization matrix + 7=set navigation pack insertion for DVD + 8=enable scene change detection (seems to be a failure) + 9=set history parameters of the video input module + 10=set input field order of VIM + 11=set quantization matrix + 12=reset audio interface + 13=set audio volume delay + 14=set audio delay + +Param[1] + Command value. diff --git a/Documentation/video4linux/cx2341x/fw-memory.txt b/Documentation/video4linux/cx2341x/fw-memory.txt new file mode 100644 index 000000000..ef0aad3f8 --- /dev/null +++ b/Documentation/video4linux/cx2341x/fw-memory.txt @@ -0,0 +1,141 @@ +This document describes the cx2341x memory map and documents some of the register +space. + +Warning! This information was figured out from searching through the memory and +registers, this information may not be correct and is certainly not complete, and +was not derived from anything more than searching through the memory space with +commands like: + + ivtvctl -O min=0x02000000,max=0x020000ff + +So take this as is, I'm always searching for more stuff, it's a large +register space :-). + +Memory Map +========== + +The cx2341x exposes its entire 64M memory space to the PCI host via the PCI BAR0 +(Base Address Register 0). The addresses here are offsets relative to the +address held in BAR0. + +0x00000000-0x00ffffff Encoder memory space +0x00000000-0x0003ffff Encode.rom + ???-??? MPEG buffer(s) + ???-??? Raw video capture buffer(s) + ???-??? Raw audio capture buffer(s) + ???-??? Display buffers (6 or 9) + +0x01000000-0x01ffffff Decoder memory space +0x01000000-0x0103ffff Decode.rom + ???-??? MPEG buffers(s) +0x0114b000-0x0115afff Audio.rom (deprecated?) + +0x02000000-0x0200ffff Register Space + +Registers +========= + +The registers occupy the 64k space starting at the 0x02000000 offset from BAR0. +All of these registers are 32 bits wide. + +DMA Registers 0x000-0xff: + + 0x00 - Control: + 0=reset/cancel, 1=read, 2=write, 4=stop + 0x04 - DMA status: + 1=read busy, 2=write busy, 4=read error, 8=write error, 16=link list error + 0x08 - pci DMA pointer for read link list + 0x0c - pci DMA pointer for write link list + 0x10 - read/write DMA enable: + 1=read enable, 2=write enable + 0x14 - always 0xffffffff, if set any lower instability occurs, 0x00 crashes + 0x18 - ?? + 0x1c - always 0x20 or 32, smaller values slow down DMA transactions + 0x20 - always value of 0x780a010a + 0x24-0x3c - usually just random values??? + 0x40 - Interrupt status + 0x44 - Write a bit here and shows up in Interrupt status 0x40 + 0x48 - Interrupt Mask + 0x4C - always value of 0xfffdffff, + if changed to 0xffffffff DMA write interrupts break. + 0x50 - always 0xffffffff + 0x54 - always 0xffffffff (0x4c, 0x50, 0x54 seem like interrupt masks, are + 3 processors on chip, Java ones, VPU, SPU, APU, maybe these are the + interrupt masks???). + 0x60-0x7C - random values + 0x80 - first write linked list reg, for Encoder Memory addr + 0x84 - first write linked list reg, for pci memory addr + 0x88 - first write linked list reg, for length of buffer in memory addr + (|0x80000000 or this for last link) + 0x8c-0xcc - rest of write linked list reg, 8 sets of 3 total, DMA goes here + from linked list addr in reg 0x0c, firmware must push through or + something. + 0xe0 - first (and only) read linked list reg, for pci memory addr + 0xe4 - first (and only) read linked list reg, for Decoder memory addr + 0xe8 - first (and only) read linked list reg, for length of buffer + 0xec-0xff - Nothing seems to be in these registers, 0xec-f4 are 0x00000000. + +Memory locations for Encoder Buffers 0x700-0x7ff: + +These registers show offsets of memory locations pertaining to each +buffer area used for encoding, have to shift them by <<1 first. + +0x07F8: Encoder SDRAM refresh +0x07FC: Encoder SDRAM pre-charge + +Memory locations for Decoder Buffers 0x800-0x8ff: + +These registers show offsets of memory locations pertaining to each +buffer area used for decoding, have to shift them by <<1 first. + +0x08F8: Decoder SDRAM refresh +0x08FC: Decoder SDRAM pre-charge + +Other memory locations: + +0x2800: Video Display Module control +0x2D00: AO (audio output?) control +0x2D24: Bytes Flushed +0x7000: LSB I2C write clock bit (inverted) +0x7004: LSB I2C write data bit (inverted) +0x7008: LSB I2C read clock bit +0x700c: LSB I2C read data bit +0x9008: GPIO get input state +0x900c: GPIO set output state +0x9020: GPIO direction (Bit7 (GPIO 0..7) - 0:input, 1:output) +0x9050: SPU control +0x9054: Reset HW blocks +0x9058: VPU control +0xA018: Bit6: interrupt pending? +0xA064: APU command + + +Interrupt Status Register +========================= + +The definition of the bits in the interrupt status register 0x0040, and the +interrupt mask 0x0048. If a bit is cleared in the mask, then we want our ISR to +execute. + +Bit +31 Encoder Start Capture +30 Encoder EOS +29 Encoder VBI capture +28 Encoder Video Input Module reset event +27 Encoder DMA complete +26 +25 Decoder copy protect detection event +24 Decoder audio mode change detection event +23 +22 Decoder data request +21 Decoder I-Frame? done +20 Decoder DMA complete +19 Decoder VBI re-insertion +18 Decoder DMA err (linked-list bad) + +Missing +Encoder API call completed +Decoder API call completed +Encoder API post(?) +Decoder API post(?) +Decoder VTRACE event diff --git a/Documentation/video4linux/cx2341x/fw-osd-api.txt b/Documentation/video4linux/cx2341x/fw-osd-api.txt new file mode 100644 index 000000000..da98ae30a --- /dev/null +++ b/Documentation/video4linux/cx2341x/fw-osd-api.txt @@ -0,0 +1,342 @@ +OSD firmware API description +============================ + +Note: this API is part of the decoder firmware, so it's cx23415 only. + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_GET_FRAMEBUFFER +Enum 65/0x41 +Description + Return base and length of contiguous OSD memory. +Result[0] + OSD base address +Result[1] + OSD length + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_GET_PIXEL_FORMAT +Enum 66/0x42 +Description + Query OSD format +Result[0] + 0=8bit index, 4=AlphaRGB 8:8:8:8 + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_PIXEL_FORMAT +Enum 67/0x43 +Description + Assign pixel format +Param[0] + 0=8bit index, 4=AlphaRGB 8:8:8:8 + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_GET_STATE +Enum 68/0x44 +Description + Query OSD state +Result[0] + Bit 0 0=off, 1=on + Bits 1:2 alpha control + Bits 3:5 pixel format + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_STATE +Enum 69/0x45 +Description + OSD switch +Param[0] + 0=off, 1=on + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_GET_OSD_COORDS +Enum 70/0x46 +Description + Retrieve coordinates of OSD area blended with video +Result[0] + OSD buffer address +Result[1] + Stride in pixels +Result[2] + Lines in OSD buffer +Result[3] + Horizontal offset in buffer +Result[4] + Vertical offset in buffer + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_OSD_COORDS +Enum 71/0x47 +Description + Assign the coordinates of the OSD area to blend with video +Param[0] + buffer address +Param[1] + buffer stride in pixels +Param[2] + lines in buffer +Param[3] + horizontal offset +Param[4] + vertical offset + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_GET_SCREEN_COORDS +Enum 72/0x48 +Description + Retrieve OSD screen area coordinates +Result[0] + top left horizontal offset +Result[1] + top left vertical offset +Result[2] + bottom right hotizontal offset +Result[3] + bottom right vertical offset + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_SCREEN_COORDS +Enum 73/0x49 +Description + Assign the coordinates of the screen area to blend with video +Param[0] + top left horizontal offset +Param[1] + top left vertical offset +Param[2] + bottom left horizontal offset +Param[3] + bottom left vertical offset + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_GET_GLOBAL_ALPHA +Enum 74/0x4A +Description + Retrieve OSD global alpha +Result[0] + global alpha: 0=off, 1=on +Result[1] + bits 0:7 global alpha + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_GLOBAL_ALPHA +Enum 75/0x4B +Description + Update global alpha +Param[0] + global alpha: 0=off, 1=on +Param[1] + global alpha (8 bits) +Param[2] + local alpha: 0=on, 1=off + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_BLEND_COORDS +Enum 78/0x4C +Description + Move start of blending area within display buffer +Param[0] + horizontal offset in buffer +Param[1] + vertical offset in buffer + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_GET_FLICKER_STATE +Enum 79/0x4F +Description + Retrieve flicker reduction module state +Result[0] + flicker state: 0=off, 1=on + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_FLICKER_STATE +Enum 80/0x50 +Description + Set flicker reduction module state +Param[0] + State: 0=off, 1=on + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_BLT_COPY +Enum 82/0x52 +Description + BLT copy +Param[0] +'0000' zero +'0001' ~destination AND ~source +'0010' ~destination AND source +'0011' ~destination +'0100' destination AND ~source +'0101' ~source +'0110' destination XOR source +'0111' ~destination OR ~source +'1000' ~destination AND ~source +'1001' destination XNOR source +'1010' source +'1011' ~destination OR source +'1100' destination +'1101' destination OR ~source +'1110' destination OR source +'1111' one + +Param[1] + Resulting alpha blending + '01' source_alpha + '10' destination_alpha + '11' source_alpha*destination_alpha+1 + (zero if both source and destination alpha are zero) +Param[2] + '00' output_pixel = source_pixel + + '01' if source_alpha=0: + output_pixel = destination_pixel + if 256 > source_alpha > 1: + output_pixel = ((source_alpha + 1)*source_pixel + + (255 - source_alpha)*destination_pixel)/256 + + '10' if destination_alpha=0: + output_pixel = source_pixel + if 255 > destination_alpha > 0: + output_pixel = ((255 - destination_alpha)*source_pixel + + (destination_alpha + 1)*destination_pixel)/256 + + '11' if source_alpha=0: + source_temp = 0 + if source_alpha=255: + source_temp = source_pixel*256 + if 255 > source_alpha > 0: + source_temp = source_pixel*(source_alpha + 1) + if destination_alpha=0: + destination_temp = 0 + if destination_alpha=255: + destination_temp = destination_pixel*256 + if 255 > destination_alpha > 0: + destination_temp = destination_pixel*(destination_alpha + 1) + output_pixel = (source_temp + destination_temp)/256 +Param[3] + width +Param[4] + height +Param[5] + destination pixel mask +Param[6] + destination rectangle start address +Param[7] + destination stride in dwords +Param[8] + source stride in dwords +Param[9] + source rectangle start address + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_BLT_FILL +Enum 83/0x53 +Description + BLT fill color +Param[0] + Same as Param[0] on API 0x52 +Param[1] + Same as Param[1] on API 0x52 +Param[2] + Same as Param[2] on API 0x52 +Param[3] + width +Param[4] + height +Param[5] + destination pixel mask +Param[6] + destination rectangle start address +Param[7] + destination stride in dwords +Param[8] + color fill value + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_BLT_TEXT +Enum 84/0x54 +Description + BLT for 8 bit alpha text source +Param[0] + Same as Param[0] on API 0x52 +Param[1] + Same as Param[1] on API 0x52 +Param[2] + Same as Param[2] on API 0x52 +Param[3] + width +Param[4] + height +Param[5] + destination pixel mask +Param[6] + destination rectangle start address +Param[7] + destination stride in dwords +Param[8] + source stride in dwords +Param[9] + source rectangle start address +Param[10] + color fill value + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_FRAMEBUFFER_WINDOW +Enum 86/0x56 +Description + Positions the main output window on the screen. The coordinates must be + such that the entire window fits on the screen. +Param[0] + window width +Param[1] + window height +Param[2] + top left window corner horizontal offset +Param[3] + top left window corner vertical offset + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_CHROMA_KEY +Enum 96/0x60 +Description + Chroma key switch and color +Param[0] + state: 0=off, 1=on +Param[1] + color + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_GET_ALPHA_CONTENT_INDEX +Enum 97/0x61 +Description + Retrieve alpha content index +Result[0] + alpha content index, Range 0:15 + +------------------------------------------------------------------------------- + +Name CX2341X_OSD_SET_ALPHA_CONTENT_INDEX +Enum 98/0x62 +Description + Assign alpha content index +Param[0] + alpha content index, range 0:15 diff --git a/Documentation/video4linux/cx2341x/fw-upload.txt b/Documentation/video4linux/cx2341x/fw-upload.txt new file mode 100644 index 000000000..60c502ce3 --- /dev/null +++ b/Documentation/video4linux/cx2341x/fw-upload.txt @@ -0,0 +1,49 @@ +This document describes how to upload the cx2341x firmware to the card. + +How to find +=========== + +See the web pages of the various projects that uses this chip for information +on how to obtain the firmware. + +The firmware stored in a Windows driver can be detected as follows: + +- Each firmware image is 256k bytes. +- The 1st 32-bit word of the Encoder image is 0x0000da7 +- The 1st 32-bit word of the Decoder image is 0x00003a7 +- The 2nd 32-bit word of both images is 0xaa55bb66 + +How to load +=========== + +- Issue the FWapi command to stop the encoder if it is running. Wait for the + command to complete. +- Issue the FWapi command to stop the decoder if it is running. Wait for the + command to complete. +- Issue the I2C command to the digitizer to stop emitting VSYNC events. +- Issue the FWapi command to halt the encoder's firmware. +- Sleep for 10ms. +- Issue the FWapi command to halt the decoder's firmware. +- Sleep for 10ms. +- Write 0x00000000 to register 0x2800 to stop the Video Display Module. +- Write 0x00000005 to register 0x2D00 to stop the AO (audio output?). +- Write 0x00000000 to register 0xA064 to ping? the APU. +- Write 0xFFFFFFFE to register 0x9058 to stop the VPU. +- Write 0xFFFFFFFF to register 0x9054 to reset the HW blocks. +- Write 0x00000001 to register 0x9050 to stop the SPU. +- Sleep for 10ms. +- Write 0x0000001A to register 0x07FC to init the Encoder SDRAM's pre-charge. +- Write 0x80000640 to register 0x07F8 to init the Encoder SDRAM's refresh to 1us. +- Write 0x0000001A to register 0x08FC to init the Decoder SDRAM's pre-charge. +- Write 0x80000640 to register 0x08F8 to init the Decoder SDRAM's refresh to 1us. +- Sleep for 512ms. (600ms is recommended) +- Transfer the encoder's firmware image to offset 0 in Encoder memory space. +- Transfer the decoder's firmware image to offset 0 in Decoder memory space. +- Use a read-modify-write operation to Clear bit 0 of register 0x9050 to + re-enable the SPU. +- Sleep for 1 second. +- Use a read-modify-write operation to Clear bits 3 and 0 of register 0x9058 + to re-enable the VPU. +- Sleep for 1 second. +- Issue status API commands to both firmware images to verify. + diff --git a/Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt b/Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt new file mode 100644 index 000000000..93fec32a1 --- /dev/null +++ b/Documentation/video4linux/cx88/hauppauge-wintv-cx88-ir.txt @@ -0,0 +1,54 @@ +The controls for the mux are GPIO [0,1] for source, and GPIO 2 for muting. + +GPIO0 GPIO1 + 0 0 TV Audio + 1 0 FM radio + 0 1 Line-In + 1 1 Mono tuner bypass or CD passthru (tuner specific) + +GPIO 16(i believe) is tied to the IR port (if present). + +------------------------------------------------------------------------------------ + +>From the data sheet: + Register 24'h20004 PCI Interrupt Status + bit [18] IR_SMP_INT Set when 32 input samples have been collected over + gpio[16] pin into GP_SAMPLE register. + +What's missing from the data sheet: + +Setup 4KHz sampling rate (roughly 2x oversampled; good enough for our RC5 +compat remote) +set register 0x35C050 to 0xa80a80 + +enable sampling +set register 0x35C054 to 0x5 + +Of course, enable the IRQ bit 18 in the interrupt mask register .(and +provide for a handler) + +GP_SAMPLE register is at 0x35C058 + +Bits are then right shifted into the GP_SAMPLE register at the specified +rate; you get an interrupt when a full DWORD is recieved. +You need to recover the actual RC5 bits out of the (oversampled) IR sensor +bits. (Hint: look for the 0/1and 1/0 crossings of the RC5 bi-phase data) An +actual raw RC5 code will span 2-3 DWORDS, depending on the actual alignment. + +I'm pretty sure when no IR signal is present the receiver is always in a +marking state(1); but stray light, etc can cause intermittent noise values +as well. Remember, this is a free running sample of the IR receiver state +over time, so don't assume any sample starts at any particular place. + +http://www.atmel.com/dyn/resources/prod_documents/doc2817.pdf +This data sheet (google search) seems to have a lovely description of the +RC5 basics + +http://users.pandora.be/nenya/electronics/rc5/ and more data + +http://www.ee.washington.edu/circuit_archive/text/ir_decode.txt +and even a reference to how to decode a bi-phase data stream. + +http://www.xs4all.nl/~sbp/knowledge/ir/rc5.htm +still more info + diff --git a/Documentation/video4linux/v4lgrab.c b/Documentation/video4linux/v4lgrab.c new file mode 100644 index 000000000..079b62848 --- /dev/null +++ b/Documentation/video4linux/v4lgrab.c @@ -0,0 +1,192 @@ +/* Simple Video4Linux image grabber. */ +/* + * Video4Linux Driver Test/Example Framegrabbing Program + * + * Compile with: + * gcc -s -Wall -Wstrict-prototypes v4lgrab.c -o v4lgrab + * Use as: + * v4lgrab >image.ppm + * + * Copyright (C) 1998-05-03, Phil Blundell <philb@gnu.org> + * Copied from http://www.tazenda.demon.co.uk/phil/vgrabber.c + * with minor modifications (Dave Forrest, drf5n@virginia.edu). + * + */ + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#include <sys/ioctl.h> +#include <stdlib.h> + +#include <linux/types.h> +#include <linux/videodev.h> + +#define FILE "/dev/video0" + +/* Stole this from tvset.c */ + +#define READ_VIDEO_PIXEL(buf, format, depth, r, g, b) \ +{ \ + switch (format) \ + { \ + case VIDEO_PALETTE_GREY: \ + switch (depth) \ + { \ + case 4: \ + case 6: \ + case 8: \ + (r) = (g) = (b) = (*buf++ << 8);\ + break; \ + \ + case 16: \ + (r) = (g) = (b) = \ + *((unsigned short *) buf); \ + buf += 2; \ + break; \ + } \ + break; \ + \ + \ + case VIDEO_PALETTE_RGB565: \ + { \ + unsigned short tmp = *(unsigned short *)buf; \ + (r) = tmp&0xF800; \ + (g) = (tmp<<5)&0xFC00; \ + (b) = (tmp<<11)&0xF800; \ + buf += 2; \ + } \ + break; \ + \ + case VIDEO_PALETTE_RGB555: \ + (r) = (buf[0]&0xF8)<<8; \ + (g) = ((buf[0] << 5 | buf[1] >> 3)&0xF8)<<8; \ + (b) = ((buf[1] << 2 ) & 0xF8)<<8; \ + buf += 2; \ + break; \ + \ + case VIDEO_PALETTE_RGB24: \ + (r) = buf[0] << 8; (g) = buf[1] << 8; \ + (b) = buf[2] << 8; \ + buf += 3; \ + break; \ + \ + default: \ + fprintf(stderr, \ + "Format %d not yet supported\n", \ + format); \ + } \ +} + +int get_brightness_adj(unsigned char *image, long size, int *brightness) { + long i, tot = 0; + for (i=0;i<size*3;i++) + tot += image[i]; + *brightness = (128 - tot/(size*3))/3; + return !((tot/(size*3)) >= 126 && (tot/(size*3)) <= 130); +} + +int main(int argc, char ** argv) +{ + int fd = open(FILE, O_RDONLY), f; + struct video_capability cap; + struct video_window win; + struct video_picture vpic; + + unsigned char *buffer, *src; + int bpp = 24, r, g, b; + unsigned int i, src_depth; + + if (fd < 0) { + perror(FILE); + exit(1); + } + + if (ioctl(fd, VIDIOCGCAP, &cap) < 0) { + perror("VIDIOGCAP"); + fprintf(stderr, "(" FILE " not a video4linux device?)\n"); + close(fd); + exit(1); + } + + if (ioctl(fd, VIDIOCGWIN, &win) < 0) { + perror("VIDIOCGWIN"); + close(fd); + exit(1); + } + + if (ioctl(fd, VIDIOCGPICT, &vpic) < 0) { + perror("VIDIOCGPICT"); + close(fd); + exit(1); + } + + if (cap.type & VID_TYPE_MONOCHROME) { + vpic.depth=8; + vpic.palette=VIDEO_PALETTE_GREY; /* 8bit grey */ + if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { + vpic.depth=6; + if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { + vpic.depth=4; + if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { + fprintf(stderr, "Unable to find a supported capture format.\n"); + close(fd); + exit(1); + } + } + } + } else { + vpic.depth=24; + vpic.palette=VIDEO_PALETTE_RGB24; + + if(ioctl(fd, VIDIOCSPICT, &vpic) < 0) { + vpic.palette=VIDEO_PALETTE_RGB565; + vpic.depth=16; + + if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { + vpic.palette=VIDEO_PALETTE_RGB555; + vpic.depth=15; + + if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { + fprintf(stderr, "Unable to find a supported capture format.\n"); + return -1; + } + } + } + } + + buffer = malloc(win.width * win.height * bpp); + if (!buffer) { + fprintf(stderr, "Out of memory.\n"); + exit(1); + } + + do { + int newbright; + read(fd, buffer, win.width * win.height * bpp); + f = get_brightness_adj(buffer, win.width * win.height, &newbright); + if (f) { + vpic.brightness += (newbright << 8); + if(ioctl(fd, VIDIOCSPICT, &vpic)==-1) { + perror("VIDIOSPICT"); + break; + } + } + } while (f); + + fprintf(stdout, "P6\n%d %d 255\n", win.width, win.height); + + src = buffer; + + for (i = 0; i < win.width * win.height; i++) { + READ_VIDEO_PIXEL(src, vpic.palette, src_depth, r, g, b); + fputc(r>>8, stdout); + fputc(g>>8, stdout); + fputc(b>>8, stdout); + } + + close(fd); + return 0; +} diff --git a/Documentation/w1/masters/ds2490 b/Documentation/w1/masters/ds2490 new file mode 100644 index 000000000..44a4918bd --- /dev/null +++ b/Documentation/w1/masters/ds2490 @@ -0,0 +1,18 @@ +Kernel driver ds2490 +==================== + +Supported chips: + * Maxim DS2490 based + +Author: Evgeniy Polyakov <johnpol@2ka.mipt.ru> + + +Description +----------- + +The Maixm/Dallas Semiconductor DS2490 is a chip +which allows to build USB <-> W1 bridges. + +DS9490(R) is a USB <-> W1 bus master device +which has 0x81 family ID integrated chip and DS2490 +low-level operational chip. diff --git a/Documentation/w1/w1.netlink b/Documentation/w1/w1.netlink new file mode 100644 index 000000000..3640c7c87 --- /dev/null +++ b/Documentation/w1/w1.netlink @@ -0,0 +1,98 @@ +Userspace communication protocol over connector [1]. + + +Message types. +============= + +There are three types of messages between w1 core and userspace: +1. Events. They are generated each time new master or slave device found + either due to automatic or requested search. +2. Userspace commands. Includes read/write and search/alarm search comamnds. +3. Replies to userspace commands. + + +Protocol. +======== + +[struct cn_msg] - connector header. It's length field is equal to size of the attached data. +[struct w1_netlink_msg] - w1 netlink header. + __u8 type - message type. + W1_SLAVE_ADD/W1_SLAVE_REMOVE - slave add/remove events. + W1_MASTER_ADD/W1_MASTER_REMOVE - master add/remove events. + W1_MASTER_CMD - userspace command for bus master device (search/alarm search). + W1_SLAVE_CMD - userspace command for slave device (read/write/ search/alarm search + for bus master device where given slave device found). + __u8 res - reserved + __u16 len - size of attached to this header data. + union { + __u8 id; - slave unique device id + struct w1_mst { + __u32 id; - master's id. + __u32 res; - reserved + } mst; + } id; + +[strucrt w1_netlink_cmd] - command for gived master or slave device. + __u8 cmd - command opcode. + W1_CMD_READ - read command. + W1_CMD_WRITE - write command. + W1_CMD_SEARCH - search command. + W1_CMD_ALARM_SEARCH - alarm search command. + __u8 res - reserved + __u16 len - length of data for this command. + For read command data must be allocated like for write command. + __u8 data[0] - data for this command. + + +Each connector message can include one or more w1_netlink_msg with zero of more attached w1_netlink_cmd messages. + +For event messages there are no w1_netlink_cmd embedded structures, only connector header +and w1_netlink_msg strucutre with "len" field being zero and filled type (one of event types) +and id - either 8 bytes of slave unique id in host order, or master's id, which is assigned +to bus master device when it is added to w1 core. + +Currently replies to userspace commands are only generated for read command request. +One reply is generated exactly for one w1_netlink_cmd read request. +Replies are not combined when sent - i.e. typical reply messages looks like the following: +[cn_msg][w1_netlink_msg][w1_netlink_cmd] +cn_msg.len = sizeof(struct w1_netlink_msg) + sizeof(struct w1_netlink_cmd) + cmd->len; +w1_netlink_msg.len = sizeof(struct w1_netlink_cmd) + cmd->len; +w1_netlink_cmd.len = cmd->len; + + +Operation steps in w1 core when new command is received. +======================================================= + +When new message (w1_netlink_msg) is received w1 core detects if it is master of slave request, +according to w1_netlink_msg.type field. +Then master or slave device is searched for. +When found, master device (requested or those one on where slave device is found) is locked. +If slave command is requested, then reset/select procedure is started to select given device. + +Then all requested in w1_netlink_msg operations are performed one by one. +If command requires reply (like read command) it is sent on command completion. + +When all commands (w1_netlink_cmd) are processed muster device is unlocked +and next w1_netlink_msg header processing started. + + +Connector [1] specific documentation. +==================================== + +Each connector message includes two u32 fields as "address". +w1 uses CN_W1_IDX and CN_W1_VAL defined in include/linux/connector.h header. +Each message also includes sequence and acknowledge numbers. +Sequence number for event messages is appropriate bus master sequence number increased with +each event message sent "through" this master. +Sequence number for userspace requests is set by userspace application. +Sequence number for reply is the same as was in request, and +acknowledge number is set to seq+1. + + +Additional documantion, source code examples. +============================================ + +1. Documentation/connector +2. http://tservice.net.ru/~s0mbre/archive/w1 +This archive includes userspace application w1d.c which +uses read/write/search commands for all master/slave devices found on the bus. diff --git a/Documentation/watchdog/src/watchdog-simple.c b/Documentation/watchdog/src/watchdog-simple.c new file mode 100644 index 000000000..85cf17c48 --- /dev/null +++ b/Documentation/watchdog/src/watchdog-simple.c @@ -0,0 +1,15 @@ +#include <stdlib.h> +#include <fcntl.h> + +int main(int argc, const char *argv[]) { + int fd = open("/dev/watchdog", O_WRONLY); + if (fd == -1) { + perror("watchdog"); + exit(1); + } + while (1) { + write(fd, "\0", 1); + fsync(fd); + sleep(10); + } +} diff --git a/Documentation/watchdog/src/watchdog-test.c b/Documentation/watchdog/src/watchdog-test.c new file mode 100644 index 000000000..65f6c19cb --- /dev/null +++ b/Documentation/watchdog/src/watchdog-test.c @@ -0,0 +1,68 @@ +/* + * Watchdog Driver Test Program + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <linux/types.h> +#include <linux/watchdog.h> + +int fd; + +/* + * This function simply sends an IOCTL to the driver, which in turn ticks + * the PC Watchdog card to reset its internal timer so it doesn't trigger + * a computer reset. + */ +void keep_alive(void) +{ + int dummy; + + ioctl(fd, WDIOC_KEEPALIVE, &dummy); +} + +/* + * The main program. Run the program with "-d" to disable the card, + * or "-e" to enable the card. + */ +int main(int argc, char *argv[]) +{ + fd = open("/dev/watchdog", O_WRONLY); + + if (fd == -1) { + fprintf(stderr, "Watchdog device not enabled.\n"); + fflush(stderr); + exit(-1); + } + + if (argc > 1) { + if (!strncasecmp(argv[1], "-d", 2)) { + ioctl(fd, WDIOC_SETOPTIONS, WDIOS_DISABLECARD); + fprintf(stderr, "Watchdog card disabled.\n"); + fflush(stderr); + exit(0); + } else if (!strncasecmp(argv[1], "-e", 2)) { + ioctl(fd, WDIOC_SETOPTIONS, WDIOS_ENABLECARD); + fprintf(stderr, "Watchdog card enabled.\n"); + fflush(stderr); + exit(0); + } else { + fprintf(stderr, "-d to disable, -e to enable.\n"); + fprintf(stderr, "run by itself to tick the card.\n"); + fflush(stderr); + exit(0); + } + } else { + fprintf(stderr, "Watchdog Ticking Away!\n"); + fflush(stderr); + } + + while(1) { + keep_alive(); + sleep(1); + } +} diff --git a/arch/arm/configs/ateb9200_defconfig b/arch/arm/configs/ateb9200_defconfig new file mode 100644 index 000000000..bee7813d0 --- /dev/null +++ b/arch/arm/configs/ateb9200_defconfig @@ -0,0 +1,1313 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17-rc3 +# Sun May 7 16:53:18 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +CONFIG_ARCH_AT91=y +CONFIG_ARCH_AT91RM9200=y + +# +# AT91RM9200 Implementations +# + +# +# AT91RM9200 Board Type +# +# CONFIG_ARCH_AT91RM9200DK is not set +# CONFIG_MACH_AT91RM9200EK is not set +# CONFIG_MACH_CSB337 is not set +# CONFIG_MACH_CSB637 is not set +# CONFIG_MACH_CARMEVA is not set +# CONFIG_MACH_KB9200 is not set +CONFIG_MACH_ATEB9200=y +# CONFIG_MACH_KAFA is not set + +# +# AT91 Feature Selections +# +# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM920T=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=m +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=m +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y + +# +# PC-card bridges +# +CONFIG_AT91_CF=m + +# +# Kernel Features +# +CONFIG_PREEMPT=y +CONFIG_NO_IDLE_HZ=y +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +# CONFIG_DECNET is not set +CONFIG_LLC=m +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +# CONFIG_IEEE80211_SOFTMAC is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +# CONFIG_MTD_BLOCK is not set +CONFIG_MTD_BLOCK_RO=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_AT91_DATAFLASH=y +# CONFIG_MTD_AT91_DATAFLASH_CARD is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_PCMCIA_AHA152X is not set +# CONFIG_PCMCIA_FDOMAIN is not set +# CONFIG_PCMCIA_NINJA_SCSI is not set +# CONFIG_PCMCIA_QLOGIC is not set +# CONFIG_PCMCIA_SYM53C500 is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_DUMMY=m +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +CONFIG_DAVICOM_PHY=y +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_ARM_AT91_ETHER=y +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +# CONFIG_NET_WIRELESS_RTNETLINK is not set + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +# CONFIG_PCMCIA_WAVELAN is not set +# CONFIG_PCMCIA_NETWAVE is not set + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +# CONFIG_HERMES is not set +# CONFIG_ATMEL is not set + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +# CONFIG_AIRO_CS is not set +# CONFIG_PCMCIA_WL3501 is not set +# CONFIG_HOSTAP is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +# CONFIG_PPP_MPPE is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AT91=y +CONFIG_SERIAL_AT91_CONSOLE=y +# CONFIG_SERIAL_AT91_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set +CONFIG_AT91_SPI=y +CONFIG_AT91_SPIDEV=y + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +CONFIG_I2C_AT91=m +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +# CONFIG_SND is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +CONFIG_USB_USBNET=y +CONFIG_USB_NET_AX8817X=y +CONFIG_USB_NET_CDCETHER=y +CONFIG_USB_NET_GL620A=y +CONFIG_USB_NET_NET1080=y +CONFIG_USB_NET_PLUSB=y +CONFIG_USB_NET_RNDIS_HOST=y +CONFIG_USB_NET_CDC_SUBSET=y +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=y +# CONFIG_USB_ZD1201 is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_AIRPRIME is not set +# CONFIG_USB_SERIAL_ANYDATA is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +CONFIG_USB_SERIAL_CP2101=m +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +CONFIG_USB_SERIAL_FTDI_SIO=m +# CONFIG_USB_SERIAL_FUNSOFT is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# 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_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +CONFIG_USB_SERIAL_PL2303=m +# CONFIG_USB_SERIAL_HP4X is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +# CONFIG_USB_SERIAL_OPTION is not set +# CONFIG_USB_SERIAL_OMNINET is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=m +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +CONFIG_USB_GADGET_AT91=y +CONFIG_USB_AT91=m +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +# CONFIG_USB_ZERO is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m + +# +# MMC/SD Card support +# +CONFIG_MMC=m +CONFIG_MMC_DEBUG=y +CONFIG_MMC_BLOCK=m +CONFIG_MMC_AT91RM9200=m + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_HCTOSYS is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y + +# +# RTC drivers +# +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_AT91=y +# CONFIG_RTC_DRV_TEST is not set + +# +# File systems +# +CONFIG_EXT2_FS=m +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=m +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_REISERFS_FS_XATTR is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=m +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_RW=y + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# 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_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +CONFIG_NLS_CODEPAGE_932=m +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=m +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +CONFIG_NLS_ISO8859_15=m +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m + +# +# Profiling support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_FS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=m +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +CONFIG_CRYPTO_MICHAEL_MIC=m +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m diff --git a/arch/arm/configs/carmeva_defconfig b/arch/arm/configs/carmeva_defconfig new file mode 100644 index 000000000..8a075c8ec --- /dev/null +++ b/arch/arm/configs/carmeva_defconfig @@ -0,0 +1,724 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.12-rc4 +# Tue Jun 14 12:05:24 2005 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_IOMAP=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +# CONFIG_AUDIT is not set +# CONFIG_HOTPLUG is not set +CONFIG_KOBJECT_UEVENT=y +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +CONFIG_ARCH_AT91=y +CONFIG_ARCH_AT91RM9200=y + +# +# AT91RM9200 Implementations +# +# CONFIG_ARCH_AT91RM9200DK is not set +# CONFIG_MACH_AT91RM9200EK is not set +# CONFIG_MACH_CSB337 is not set +# CONFIG_MACH_CSB637 is not set +CONFIG_MACH_CARMEVA=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM920T=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set + +# +# Bus support +# +CONFIG_ISA_DMA_API=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_SMP is not set +# CONFIG_PREEMPT is not set +# CONFIG_DISCONTIGMEM is not set +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_AT91_DATAFLASH=y +# CONFIG_MTD_AT91_DATAFLASH_CARD is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_IP_TCPDIAG=y +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_ARM_AT91_ETHER=y +CONFIG_ARM_AT91_ETHER_RMII=y +# CONFIG_SMC91X is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=m +CONFIG_SERIO_SERPORT=m +# CONFIG_SERIO_LIBPS2 is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AT91=y +CONFIG_SERIAL_AT91_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_AT91_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +CONFIG_AT91_SPI=y +CONFIG_AT91_SPIDEV=y + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +CONFIG_MMC_DEBUG=y +CONFIG_MMC_BLOCK=m +CONFIG_MMC_AT91RM9200=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set + +# +# XFS support +# +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS_FS=y +CONFIG_JFFS_FS_VERBOSE=0 +CONFIG_JFFS_PROC_FS=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_NAND=y +# CONFIG_JFFS2_FS_NOR_ECC is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +CONFIG_NFSD_TCP=y +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff --git a/arch/arm/configs/kafa_defconfig b/arch/arm/configs/kafa_defconfig new file mode 100644 index 000000000..1db633e2c --- /dev/null +++ b/arch/arm/configs/kafa_defconfig @@ -0,0 +1,885 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17-rc3 +# Sun May 7 16:54:53 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +CONFIG_ARCH_AT91=y +CONFIG_ARCH_AT91RM9200=y + +# +# AT91RM9200 Implementations +# + +# +# AT91RM9200 Board Type +# +# CONFIG_ARCH_AT91RM9200DK is not set +# CONFIG_MACH_AT91RM9200EK is not set +# CONFIG_MACH_CSB337 is not set +# CONFIG_MACH_CSB637 is not set +# CONFIG_MACH_CARMEVA is not set +# CONFIG_MACH_KB9200 is not set +# CONFIG_MACH_ATEB9200 is not set +CONFIG_MACH_KAFA=y + +# +# AT91 Feature Selections +# +# CONFIG_AT91_PROGRAMMABLE_CLOCKS is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM920T=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_PREEMPT=y +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_LEDS=y +# CONFIG_LEDS_TIMER is not set +CONFIG_LEDS_CPU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="mem=32M console=ttyS0,115200 initrd=0x20800000,10M root=/dev/ram0 rw" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +# CONFIG_MTD_BLOCK is not set +CONFIG_MTD_BLOCK_RO=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_AT91_DATAFLASH=y +# CONFIG_MTD_AT91_DATAFLASH_CARD is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +CONFIG_DAVICOM_PHY=y +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_ARM_AT91_ETHER=y +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AT91=y +CONFIG_SERIAL_AT91_CONSOLE=y +# CONFIG_SERIAL_AT91_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=32 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_AT91_WATCHDOG=y +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set +CONFIG_AT91_SPI=y +CONFIG_AT91_SPIDEV=y + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +CONFIG_I2C_AT91=y +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_HCTOSYS is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y + +# +# RTC drivers +# +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_AT91=y +# CONFIG_RTC_DRV_TEST is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_FS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +# CONFIG_DEBUG_USER is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y diff --git a/arch/arm/configs/kb9202_defconfig b/arch/arm/configs/kb9202_defconfig new file mode 100644 index 000000000..45396e087 --- /dev/null +++ b/arch/arm/configs/kb9202_defconfig @@ -0,0 +1,781 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.13-rc2 +# Sun Aug 14 19:26:59 2005 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_CALIBRATE_DELAY=y + +# +# Code maturity level options +# +# CONFIG_EXPERIMENTAL is not set +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_SWAP is not set +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_HOTPLUG=y +# CONFIG_KOBJECT_UEVENT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SHMEM=y +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +CONFIG_ARCH_AT91=y +CONFIG_ARCH_AT91RM9200=y + +# +# AT91RM9200 Implementations +# +# CONFIG_ARCH_AT91RM9200DK is not set +# CONFIG_MACH_AT91RM9200EK is not set +# CONFIG_MACH_CSB337 is not set +# CONFIG_MACH_CSB637 is not set +# CONFIG_MACH_CARMEVA is not set +CONFIG_MACH_KB9200=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM920T=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set + +# +# Bus support +# +CONFIG_ISA_DMA_API=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_NO_IDLE_HZ is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x10000000 +CONFIG_ZBOOT_ROM_BSS=0x20040000 +CONFIG_ZBOOT_ROM=y +CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram rw initrd=0x20210000,654933" + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_MISC=y +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +CONFIG_DEBUG_DRIVER=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_IP_TCPDIAG is not set +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_ARM_AT91_ETHER=y +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AT91=y +CONFIG_SERIAL_AT91_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_AT91_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_AT91_SPI is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB=y +CONFIG_USB_DEBUG=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_BLUETOOTH_TTY is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DEBUG=y +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_DPCM is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_MTOUCH is not set +# CONFIG_USB_ITMTOUCH is not set +# CONFIG_USB_EGALAX is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MICROTEK is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network Adapters +# +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_MON is not set + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set + +# +# XFS support +# +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_DEVPTS_FS_XATTR=y +# CONFIG_DEVPTS_FS_SECURITY is not set +CONFIG_TMPFS=y +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_HFSPLUS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# 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 + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set diff --git a/arch/arm/configs/lpd270_defconfig b/arch/arm/configs/lpd270_defconfig new file mode 100644 index 000000000..4b29e0996 --- /dev/null +++ b/arch/arm/configs/lpd270_defconfig @@ -0,0 +1,981 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18-rc1 +# Sun Jul 9 14:15:23 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_MTD_XIP=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_RT_MUTEXES=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODULE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PNX4008 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set + +# +# Intel PXA2xx Implementations +# +# CONFIG_ARCH_LUBBOCK is not set +CONFIG_MACH_LOGICPD_PXA270=y +# CONFIG_MACH_MAINSTONE is not set +# CONFIG_ARCH_PXA_IDP is not set +# CONFIG_PXA_SHARPSL is not set +# CONFIG_MACH_TRIZEPS4 is not set +CONFIG_PXA27x=y +CONFIG_IWMMXT=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_XSCALE=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +CONFIG_XSCALE_PMU=y + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +# CONFIG_PREEMPT is not set +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="root=/dev/nfs ip=bootp console=ttyS0,115200 mem=64M" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +# CONFIG_PACKET is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=y +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +# CONFIG_MTD_CFI_I1 is not set +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set +# CONFIG_MTD_XIP is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_SHARP_SL is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +# CONFIG_IDE_GENERIC is not set +# CONFIG_IDE_ARM is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_SMC91X=y +# CONFIG_DM9000 is not set +# CONFIG_SMC911X is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_SERPORT is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_PXA=y +CONFIG_SERIAL_PXA_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_PXA=y +# CONFIG_FB_PXA_PARAMETERS is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_AC97_CODEC=y +CONFIG_SND_AC97_BUS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# ALSA ARM devices +# +CONFIG_SND_PXA2XX_PCM=y +CONFIG_SND_PXA2XX_AC97=y + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +# CONFIG_VFAT_FS is not set +CONFIG_FAT_DEFAULT_CODEPAGE=437 +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# 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 + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y diff --git a/arch/arm/configs/netx_defconfig b/arch/arm/configs/netx_defconfig new file mode 100644 index 000000000..61115a773 --- /dev/null +++ b/arch/arm/configs/netx_defconfig @@ -0,0 +1,926 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17-rc6 +# Tue Jun 6 15:26:53 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set +CONFIG_OBSOLETE_INTERMODULE=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_AT91RM9200 is not set +CONFIG_ARCH_NETX=y + +# +# NetX Implementations +# +CONFIG_MACH_NXDKN=y +CONFIG_MACH_NXDB500=y +CONFIG_MACH_NXEB500HMI=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set +CONFIG_ARM_VIC=y + +# +# Bus support +# +CONFIG_ARM_AMBA=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_PREEMPT=y +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="console=ttySMX0,115200" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=m +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +CONFIG_NET_IPGRE=m +# CONFIG_NET_IPGRE_BROADCAST is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_XFRM_TUNNEL=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +# CONFIG_IPV6_TUNNEL is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NETFILTER_XTABLES is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +# CONFIG_IP_NF_CT_ACCT is not set +# CONFIG_IP_NF_CONNTRACK_MARK is not set +# CONFIG_IP_NF_CONNTRACK_EVENTS is not set +# CONFIG_IP_NF_CT_PROTO_SCTP is not set +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +# CONFIG_IP_NF_PPTP is not set +# CONFIG_IP_NF_H323 is not set +CONFIG_IP_NF_QUEUE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +# CONFIG_IP6_NF_QUEUE is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_RAM=y +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +CONFIG_MTD_PLATRAM=y + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_SMC91X is not set +CONFIG_NET_NETX=y +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_NETX=y +CONFIG_SERIAL_NETX_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +CONFIG_NVRAM=m +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +CONFIG_FB_FIRMWARE_EDID=y +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set +CONFIG_FB_ARMCLCD=y +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m + +# +# RTC drivers +# +# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_NETX=m +# CONFIG_RTC_DRV_TEST is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +CONFIG_NFS_DIRECTIO=y +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_WAITQ is not set +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff --git a/arch/arm/configs/onearm_defconfig b/arch/arm/configs/onearm_defconfig new file mode 100644 index 000000000..6a93e3aae --- /dev/null +++ b/arch/arm/configs/onearm_defconfig @@ -0,0 +1,1076 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18-rc1 +# Sun Jul 9 14:16:20 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_RT_MUTEXES=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARCH_AT91=y +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set + +# +# Atmel AT91 System-on-Chip +# + +# +# Atmel AT91 Processors +# +CONFIG_ARCH_AT91RM9200=y +# CONFIG_ARCH_AT91SAM9260 is not set +# CONFIG_ARCH_AT91SAM9261 is not set + +# +# AT91RM9200 Board Type +# +CONFIG_MACH_ONEARM=y +# CONFIG_ARCH_AT91RM9200DK is not set +# CONFIG_MACH_AT91RM9200EK is not set +# CONFIG_MACH_CSB337 is not set +# CONFIG_MACH_CSB637 is not set +# CONFIG_MACH_CARMEVA is not set +# CONFIG_MACH_ATEB9200 is not set +# CONFIG_MACH_KB9200 is not set +# CONFIG_MACH_KAFA is not set + +# +# AT91 Feature Selections +# +CONFIG_AT91_PROGRAMMABLE_CLOCKS=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM920T=y +CONFIG_CPU_32v4=y +CONFIG_CPU_ABRT_EV4T=y +CONFIG_CPU_CACHE_V4WT=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +# CONFIG_ARM_THUMB is not set +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y + +# +# PC-card bridges +# +CONFIG_AT91_CF=y + +# +# Kernel Features +# +# CONFIG_PREEMPT is not set +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +# CONFIG_LEDS_CPU is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/nfs ip=bootp mem=64M" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set + +# +# Power management options +# +# CONFIG_PM is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x0 +CONFIG_MTD_PHYSMAP_LEN=0x0 +CONFIG_MTD_PHYSMAP_BANKWIDTH=0 +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +CONFIG_ARM_AT91_ETHER=y +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AT91=y +CONFIG_SERIAL_AT91_CONSOLE=y +# CONFIG_SERIAL_AT91_TTYAT is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_NOWAYOUT=y + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_AT91_WATCHDOG=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +CONFIG_USB_DEBUG=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +CONFIG_USB_GADGET_AT91=y +CONFIG_USB_AT91=y +# CONFIG_USB_GADGET_DUMMY_HCD is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=y +CONFIG_MMC_AT91RM9200=y + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_ERRORS is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_ICEDCC is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_PLIST=y diff --git a/arch/arm/configs/pnx4008_defconfig b/arch/arm/configs/pnx4008_defconfig new file mode 100644 index 000000000..a4989f44b --- /dev/null +++ b/arch/arm/configs/pnx4008_defconfig @@ -0,0 +1,1665 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18-rc6 +# Mon Sep 11 13:59:24 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +CONFIG_SYSCTL=y +CONFIG_AUDIT=y +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_RT_MUTEXES=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +CONFIG_ARCH_PNX4008=y +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_ARM926T=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5TJ=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_COPY_V4WB=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_WRITETHROUGH is not set +# CONFIG_CPU_CACHE_ROUND_ROBIN is not set + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_PREEMPT=y +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_CMDLINE="mem=64M console=ttyS0,115200" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +# CONFIG_FPE_FASTFPE is not set +# CONFIG_VFP is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_AOUT=m +CONFIG_BINFMT_MISC=m +# CONFIG_ARTHUR is not set + +# +# Power management options +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +# CONFIG_APM is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +# CONFIG_IPV6_ROUTER_PREF is not set +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NETFILTER_XTABLES is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +# CONFIG_IP_NF_CONNTRACK_EVENTS is not set +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +# CONFIG_IP_NF_PPTP is not set +# CONFIG_IP_NF_H323 is not set +# CONFIG_IP_NF_SIP is not set +CONFIG_IP_NF_QUEUE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m + +# +# DECnet: Netfilter Configuration +# +CONFIG_DECNET_NF_GRABULATOR=m + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +# CONFIG_BRIDGE_EBT_ULOG is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +CONFIG_ATM=y +CONFIG_ATM_CLIP=y +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +# CONFIG_DECNET_ROUTER is not set +CONFIG_LLC=m +CONFIG_LLC2=m +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +CONFIG_X25=m +CONFIG_LAPB=m +# CONFIG_NET_DIVERT is not set +CONFIG_ECONET=m +CONFIG_ECONET_AUNUDP=y +CONFIG_ECONET_NATIVE=y +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CLK_JIFFIES=y +# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +# CONFIG_NET_CLS_BASIC is not set +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +# CONFIG_CLS_U32_PERF is not set +# CONFIG_CLS_U32_MARK is not set +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +# CONFIG_NET_EMATCH is not set +# CONFIG_NET_CLS_ACT is not set +CONFIG_NET_CLS_POLICE=y +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +# CONFIG_IEEE80211_CRYPT_WEP is not set +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +# CONFIG_IEEE80211_SOFTMAC is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +CONFIG_MTD_SLRAM=m +CONFIG_MTD_PHRAM=m +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +CONFIG_MTD_DOC2000=m +CONFIG_MTD_DOC2001=m +CONFIG_MTD_DOC2001PLUS=m +CONFIG_MTD_DOCPROBE=m +CONFIG_MTD_DOCECC=m +# CONFIG_MTD_DOCPROBE_ADVANCED is not set +CONFIG_MTD_DOCPROBE_ADDRESS=0 + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +CONFIG_MTD_NAND_NANDSIM=m + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=y +CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +CONFIG_SCSI_SATA=m +CONFIG_SCSI_DEBUG=m + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +# CONFIG_NET_WIRELESS_RTNETLINK is not set + +# +# Obsolete Wireless cards support (pre-802.11) +# +CONFIG_STRIP=m +# CONFIG_USB_ZD1201 is not set +# CONFIG_HOSTAP is not set + +# +# Wan interfaces +# +CONFIG_WAN=y +CONFIG_HDLC=m +CONFIG_HDLC_RAW=y +CONFIG_HDLC_RAW_ETH=y +CONFIG_HDLC_CISCO=y +CONFIG_HDLC_FR=y +CONFIG_HDLC_PPP=y +CONFIG_HDLC_X25=y +CONFIG_DLCI=m +CONFIG_DLCI_COUNT=24 +CONFIG_DLCI_MAX=8 +CONFIG_WAN_ROUTER_DRIVERS=y +CONFIG_LAPBETHER=m +CONFIG_X25_ASY=m + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y +CONFIG_SHAPER=m +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_TSDEV=m +CONFIG_INPUT_TSDEV_SCREEN_X=240 +CONFIG_INPUT_TSDEV_SCREEN_Y=320 +CONFIG_INPUT_EVDEV=m +CONFIG_INPUT_EVBUG=m + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +CONFIG_KEYBOARD_SUNKBD=m +CONFIG_KEYBOARD_LKKBD=m +CONFIG_KEYBOARD_XTKBD=m +CONFIG_KEYBOARD_NEWTON=m +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +# CONFIG_JOYSTICK_TWIDJOY is not set +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +CONFIG_TOUCHSCREEN_GUNZE=m +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=m +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +# CONFIG_SENSORS_PCA9539 is not set +CONFIG_SENSORS_PCF8591=m +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_BITBANG=y + +# +# SPI Protocol Masters +# + +# +# Dallas's 1-wire bus +# + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported USB Adapters +# +# CONFIG_DVB_USB is not set +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +# CONFIG_DVB_B2C2_FLEXCOP is not set + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +# CONFIG_DVB_CX24123 is not set +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +# CONFIG_DVB_S5H1420 is not set + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +# CONFIG_DVB_ZL10353 is not set +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +# CONFIG_DVB_NXT200X is not set +# CONFIG_DVB_OR51211 is not set +# CONFIG_DVB_OR51132 is not set +# CONFIG_DVB_BCM3510 is not set +# CONFIG_DVB_LGDT330X is not set + +# +# Miscellaneous devices +# +CONFIG_DVB_LNBP21=m +# CONFIG_DVB_ISL6421 is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +CONFIG_FIRMWARE_EDID=y +# CONFIG_FB is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_MPU401=m + +# +# ALSA ARM devices +# + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m + +# +# Open Sound System +# +CONFIG_SOUND_PRIME=m +# CONFIG_OSS_OBSOLETE_DRIVER is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_BANDWIDTH=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_SL811_HCD=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +CONFIG_USB_HIDDEV=y + +# +# USB HID Boot Protocol drivers +# +CONFIG_USB_KBD=m +CONFIG_USB_MOUSE=m +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +# CONFIG_USB_ACECAD is not set +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +# CONFIG_USB_NET_GL620A is not set +CONFIG_USB_NET_NET1080=m +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_RNDIS_HOST is not set +# CONFIG_USB_NET_CDC_SUBSET is not set +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_AIRPRIME is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +# CONFIG_USB_SERIAL_CP2101 is not set +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +# CONFIG_USB_SERIAL_FUNSOFT is not set +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +# CONFIG_USB_SERIAL_GARMIN is not set +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +# CONFIG_USB_SERIAL_NAVMAN is not set +CONFIG_USB_SERIAL_PL2303=m +# CONFIG_USB_SERIAL_HP4X is not set +CONFIG_USB_SERIAL_SAFE=m +# CONFIG_USB_SERIAL_SAFE_PADDED is not set +# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set +# CONFIG_USB_SERIAL_TI is not set +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +# CONFIG_USB_SERIAL_OPTION is not set +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +CONFIG_USB_CYTHERM=m +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_LD is not set +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +# CONFIG_USB_CXACRU is not set +# CONFIG_USB_UEAGLEATM is not set +# CONFIG_USB_XUSBATM is not set + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=m +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_AT91 is not set +CONFIG_USB_GADGET_DUMMY_HCD=y +CONFIG_USB_DUMMY_HCD=m +CONFIG_USB_GADGET_DUALSPEED=y +CONFIG_USB_ZERO=m +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +# CONFIG_JFS_SECURITY is not set +# CONFIG_JFS_DEBUG is not set +CONFIG_JFS_STATISTICS=y +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_RT=y +# CONFIG_OCFS2_FS is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +CONFIG_QFMT_V1=m +CONFIG_QFMT_V2=m +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=m +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_RW is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +CONFIG_ADFS_FS=m +# CONFIG_ADFS_FS_RW is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_JFFS_FS=m +CONFIG_JFFS_FS_VERBOSE=0 +CONFIG_JFFS_PROC_FS=y +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=y +CONFIG_VXFS_FS=m +CONFIG_HPFS_FS=m +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +CONFIG_RPCSEC_GSS_SPKM3=m +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +# CONFIG_NCPFS_SMALLDOS is not set +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +CONFIG_AFS_FS=m +CONFIG_RXRPC=m +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +CONFIG_ACORN_PARTITION=y +# CONFIG_ACORN_PARTITION_CUMANA is not set +# CONFIG_ACORN_PARTITION_EESOX is not set +CONFIG_ACORN_PARTITION_ICS=y +# CONFIG_ACORN_PARTITION_ADFS is not set +# CONFIG_ACORN_PARTITION_POWERTEC is not set +CONFIG_ACORN_PARTITION_RISCIX=y +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +CONFIG_ATARI_PARTITION=y +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_LDM_PARTITION=y +# CONFIG_LDM_DEBUG is not set +CONFIG_SGI_PARTITION=y +CONFIG_ULTRIX_PARTITION=y +CONFIG_SUN_PARTITION=y +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=m +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_WAITQ is not set +# CONFIG_DEBUG_ERRORS is not set +# CONFIG_DEBUG_LL is not set + +# +# Security options +# +# CONFIG_KEYS is not set +CONFIG_SECURITY=y +# CONFIG_SECURITY_NETWORK is not set +CONFIG_SECURITY_CAPABILITIES=m +CONFIG_SECURITY_ROOTPLUG=m +CONFIG_SECURITY_SECLVL=m + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +CONFIG_CRYPTO_TEST=m + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_PLIST=y diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig new file mode 100644 index 000000000..a6698dc4f --- /dev/null +++ b/arch/arm/configs/trizeps4_defconfig @@ -0,0 +1,1579 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.17 +# Sat Jun 24 22:45:14 2006 +# +CONFIG_ARM=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_MTD_XIP=y +CONFIG_VECTORS_BASE=0xffff0000 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_SYSCTL=y +CONFIG_AUDIT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_UID16=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set +CONFIG_OBSOLETE_INTERMODULE=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_KMOD=y + +# +# Block layer +# +# CONFIG_BLK_DEV_IO_TRACE is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# System Type +# +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP3XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_L7200 is not set +CONFIG_ARCH_PXA=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_IMX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_AT91RM9200 is not set + +# +# Intel PXA2xx Implementations +# +# CONFIG_ARCH_LUBBOCK is not set +# CONFIG_MACH_LOGICPD_PXA270 is not set +# CONFIG_MACH_MAINSTONE is not set +# CONFIG_ARCH_PXA_IDP is not set +# CONFIG_PXA_SHARPSL is not set +CONFIG_MACH_TRIZEPS4=y +CONFIG_MACH_TRIZEPS4_CONXS=y +# CONFIG_MACH_TRIZEPS4_ANY is not set +CONFIG_PXA27x=y + +# +# Processor Type +# +CONFIG_CPU_32=y +CONFIG_CPU_XSCALE=y +CONFIG_CPU_32v5=y +CONFIG_CPU_ABRT_EV5T=y +CONFIG_CPU_CACHE_VIVT=y +CONFIG_CPU_TLB_V4WBI=y + +# +# Processor Features +# +CONFIG_ARM_THUMB=y +CONFIG_XSCALE_PMU=y + +# +# Bus support +# + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=m +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=m +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y + +# +# PC-card bridges +# +CONFIG_PCMCIA_PXA2XX=m + +# +# Kernel Features +# +CONFIG_PREEMPT=y +# CONFIG_NO_IDLE_HZ is not set +CONFIG_HZ=100 +# CONFIG_AEABI is not set +# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +CONFIG_LEDS_CPU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Boot options +# +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="root=/dev/nfs ip=bootp console=ttyS0,115200n8" +# CONFIG_XIP_KERNEL is not set + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +CONFIG_FPE_NWFPE=y +CONFIG_FPE_NWFPE_XP=y +# CONFIG_FPE_FASTFPE is not set + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=m +# CONFIG_ARTHUR is not set + +# +# Power management options +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +CONFIG_APM=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=m +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_IPV6_TUNNEL is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NETFILTER_XTABLES is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +# CONFIG_IP_NF_CONNTRACK_EVENTS is not set +# CONFIG_IP_NF_CT_PROTO_SCTP is not set +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +# CONFIG_IP_NF_PPTP is not set +# CONFIG_IP_NF_H323 is not set +CONFIG_IP_NF_QUEUE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +# CONFIG_IP6_NF_QUEUE is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +CONFIG_VLAN_8021Q=m +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +# CONFIG_DONGLE is not set + +# +# Old SIR device drivers +# +# CONFIG_IRPORT_SIR is not set + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +# CONFIG_USB_IRDA is not set +# CONFIG_SIGMATEL_FIR is not set +# CONFIG_PXA_FICP is not set +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +# CONFIG_BT_HCIUSB is not set +# CONFIG_BT_HCIUART is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIDTL1 is not set +# CONFIG_BT_HCIBT3C is not set +# CONFIG_BT_HCIBLUECARD is not set +# CONFIG_BT_HCIBTUART is not set +# CONFIG_BT_HCIVHCI is not set +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=y +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y +CONFIG_MTD_REDBOOT_PARTS_READONLY=y +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +CONFIG_NFTL=y +CONFIG_NFTL_RW=y +CONFIG_INFTL=y +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +# CONFIG_MTD_CFI_NOSWAP is not set +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +CONFIG_MTD_CFI_LE_BYTE_SWAP=y +CONFIG_MTD_CFI_GEOMETRY=y +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set +# CONFIG_MTD_XIP is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x0 +CONFIG_MTD_PHYSMAP_LEN=0x4000000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_TRIZEPS4 is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +# CONFIG_MTD_IMPA7 is not set +# CONFIG_MTD_SHARP_SL is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +CONFIG_MTD_DOC2001PLUS=y +CONFIG_MTD_DOCPROBE=y +CONFIG_MTD_DOCECC=y +# CONFIG_MTD_DOCPROBE_ADVANCED is not set +CONFIG_MTD_DOCPROBE_ADDRESS=0 + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_H1900 is not set +CONFIG_MTD_NAND_IDS=y +CONFIG_MTD_NAND_DISKONCHIP=y +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +# CONFIG_MTD_NAND_SHARPSL is not set +# CONFIG_MTD_NAND_NANDSIM is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=4 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_IDE_PXA_CF=y +CONFIG_IDE_ARM=y +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_PCMCIA_AHA152X is not set +# CONFIG_PCMCIA_FDOMAIN is not set +# CONFIG_PCMCIA_NINJA_SCSI is not set +# CONFIG_PCMCIA_QLOGIC is not set +# CONFIG_PCMCIA_SYM53C500 is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +CONFIG_DAVICOM_PHY=y +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_SMC91X is not set +CONFIG_DM9000=y + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +# CONFIG_NET_WIRELESS_RTNETLINK is not set + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +# CONFIG_PCMCIA_WAVELAN is not set +# CONFIG_PCMCIA_NETWAVE is not set + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +CONFIG_HERMES=m +# CONFIG_ATMEL is not set + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +# CONFIG_PCMCIA_SPECTRUM is not set +CONFIG_AIRO_CS=m +# CONFIG_PCMCIA_WL3501 is not set +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_CS=m +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +# CONFIG_NET_PCMCIA is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_MPPE=m +# CONFIG_PPPOE is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=640 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480 +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_TSDEV=y +CONFIG_INPUT_TSDEV_SCREEN_X=640 +CONFIG_INPUT_TSDEV_SCREEN_Y=480 +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +# CONFIG_MOUSE_PS2 is not set +CONFIG_MOUSE_SERIAL=y +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_INPUT_JOYSTICK is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_PXA=y +CONFIG_SERIAL_PXA_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_SA1100_WATCHDOG=y + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set + +# +# Ftape, the floppy tape device driver +# + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +CONFIG_I2C_PXA=y +CONFIG_I2C_PXA_SLAVE=y +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=m +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +CONFIG_SPI=y +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_BITBANG is not set +CONFIG_SPI_PXA2XX=m + +# +# SPI Protocol Masters +# + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia Capabilities Port drivers +# +CONFIG_UCB1400=y +CONFIG_UCB1400_TS=y + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_IDE_DISK=y + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +CONFIG_FB_FIRMWARE_EDID=y +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_PXA=y +# CONFIG_FB_PXA_PARAMETERS is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set + +# +# Logo configuration +# +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=y +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +# CONFIG_SND_SEQ_DUMMY is not set +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=y +CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y +# CONFIG_SND_SEQUENCER_OSS is not set +# CONFIG_SND_DYNAMIC_MINORS is not set +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +CONFIG_SND_VERBOSE_PRINTK=y +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_AC97_CODEC=y +CONFIG_SND_AC97_BUS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# ALSA ARM devices +# +CONFIG_SND_PXA2XX_PCM=y +CONFIG_SND_PXA2XX_AC97=y + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +# CONFIG_USB_ARCH_HAS_EHCI is not set +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# 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_USBAT 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_ALAUDA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +CONFIG_USB_TOUCHSCREEN=m +# CONFIG_USB_TOUCHSCREEN_EGALAX is not set +# CONFIG_USB_TOUCHSCREEN_PANJIT is not set +# CONFIG_USB_TOUCHSCREEN_3M is not set +# CONFIG_USB_TOUCHSCREEN_ITM is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_ZD1201 is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +# CONFIG_USB_GADGET_NET2280 is not set +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_AT91 is not set +CONFIG_USB_GADGET_DUMMY_HCD=y +CONFIG_USB_DUMMY_HCD=y +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_ZERO is not set +CONFIG_USB_ETH=m +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_GADGETFS=m +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_G_SERIAL=m + +# +# MMC/SD Card support +# +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=y +CONFIG_MMC_PXA=y + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y + +# +# RTC drivers +# +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_M48T86 is not set +CONFIG_RTC_DRV_SA1100=y +# CONFIG_RTC_DRV_TEST is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-15" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS_FS=y +CONFIG_JFFS_FS_VERBOSE=0 +CONFIG_JFFS_PROC_FS=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=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=y +# CONFIG_LDM_DEBUG is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-15" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=y +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +CONFIG_NLS_ISO8859_15=m +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m + +# +# Profiling support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=y + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_FS is not set +CONFIG_FRAME_POINTER=y +# CONFIG_UNWIND_INFO is not set +CONFIG_DEBUG_USER=y + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +# CONFIG_SECURITY_NETWORK is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=m +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +CONFIG_CRC32=y +CONFIG_LIBCRC32C=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_DEC16=y diff --git a/arch/arm/kernel/crunch-bits.S b/arch/arm/kernel/crunch-bits.S new file mode 100644 index 000000000..a26886758 --- /dev/null +++ b/arch/arm/kernel/crunch-bits.S @@ -0,0 +1,305 @@ +/* + * arch/arm/kernel/crunch-bits.S + * Cirrus MaverickCrunch context switching and handling + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * + * Shamelessly stolen from the iWMMXt code by Nicolas Pitre, which is + * Copyright (c) 2003-2004, MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/linkage.h> +#include <asm/ptrace.h> +#include <asm/thread_info.h> +#include <asm/asm-offsets.h> +#include <asm/arch/ep93xx-regs.h> + +/* + * We can't use hex constants here due to a bug in gas. + */ +#define CRUNCH_MVDX0 0 +#define CRUNCH_MVDX1 8 +#define CRUNCH_MVDX2 16 +#define CRUNCH_MVDX3 24 +#define CRUNCH_MVDX4 32 +#define CRUNCH_MVDX5 40 +#define CRUNCH_MVDX6 48 +#define CRUNCH_MVDX7 56 +#define CRUNCH_MVDX8 64 +#define CRUNCH_MVDX9 72 +#define CRUNCH_MVDX10 80 +#define CRUNCH_MVDX11 88 +#define CRUNCH_MVDX12 96 +#define CRUNCH_MVDX13 104 +#define CRUNCH_MVDX14 112 +#define CRUNCH_MVDX15 120 +#define CRUNCH_MVAX0L 128 +#define CRUNCH_MVAX0M 132 +#define CRUNCH_MVAX0H 136 +#define CRUNCH_MVAX1L 140 +#define CRUNCH_MVAX1M 144 +#define CRUNCH_MVAX1H 148 +#define CRUNCH_MVAX2L 152 +#define CRUNCH_MVAX2M 156 +#define CRUNCH_MVAX2H 160 +#define CRUNCH_MVAX3L 164 +#define CRUNCH_MVAX3M 168 +#define CRUNCH_MVAX3H 172 +#define CRUNCH_DSPSC 176 + +#define CRUNCH_SIZE 184 + + .text + +/* + * Lazy switching of crunch coprocessor context + * + * r10 = struct thread_info pointer + * r9 = ret_from_exception + * lr = undefined instr exit + * + * called from prefetch exception handler with interrupts disabled + */ +ENTRY(crunch_task_enable) + ldr r8, =(EP93XX_APB_VIRT_BASE + 0x00130000) @ syscon addr + + ldr r1, [r8, #0x80] + tst r1, #0x00800000 @ access to crunch enabled? + movne pc, lr @ if so no business here + mov r3, #0xaa @ unlock syscon swlock + str r3, [r8, #0xc0] + orr r1, r1, #0x00800000 @ enable access to crunch + str r1, [r8, #0x80] + + ldr r3, =crunch_owner + add r0, r10, #TI_CRUNCH_STATE @ get task crunch save area + ldr r2, [sp, #60] @ current task pc value + ldr r1, [r3] @ get current crunch owner + str r0, [r3] @ this task now owns crunch + sub r2, r2, #4 @ adjust pc back + str r2, [sp, #60] + + ldr r2, [r8, #0x80] + mov r2, r2 @ flush out enable (@@@) + + teq r1, #0 @ test for last ownership + mov lr, r9 @ normal exit from exception + beq crunch_load @ no owner, skip save + +crunch_save: + cfstr64 mvdx0, [r1, #CRUNCH_MVDX0] @ save 64b registers + cfstr64 mvdx1, [r1, #CRUNCH_MVDX1] + cfstr64 mvdx2, [r1, #CRUNCH_MVDX2] + cfstr64 mvdx3, [r1, #CRUNCH_MVDX3] + cfstr64 mvdx4, [r1, #CRUNCH_MVDX4] + cfstr64 mvdx5, [r1, #CRUNCH_MVDX5] + cfstr64 mvdx6, [r1, #CRUNCH_MVDX6] + cfstr64 mvdx7, [r1, #CRUNCH_MVDX7] + cfstr64 mvdx8, [r1, #CRUNCH_MVDX8] + cfstr64 mvdx9, [r1, #CRUNCH_MVDX9] + cfstr64 mvdx10, [r1, #CRUNCH_MVDX10] + cfstr64 mvdx11, [r1, #CRUNCH_MVDX11] + cfstr64 mvdx12, [r1, #CRUNCH_MVDX12] + cfstr64 mvdx13, [r1, #CRUNCH_MVDX13] + cfstr64 mvdx14, [r1, #CRUNCH_MVDX14] + cfstr64 mvdx15, [r1, #CRUNCH_MVDX15] + +#ifdef __ARMEB__ +#error fix me for ARMEB +#endif + + cfmv32al mvfx0, mvax0 @ save 72b accumulators + cfstr32 mvfx0, [r1, #CRUNCH_MVAX0L] + cfmv32am mvfx0, mvax0 + cfstr32 mvfx0, [r1, #CRUNCH_MVAX0M] + cfmv32ah mvfx0, mvax0 + cfstr32 mvfx0, [r1, #CRUNCH_MVAX0H] + cfmv32al mvfx0, mvax1 + cfstr32 mvfx0, [r1, #CRUNCH_MVAX1L] + cfmv32am mvfx0, mvax1 + cfstr32 mvfx0, [r1, #CRUNCH_MVAX1M] + cfmv32ah mvfx0, mvax1 + cfstr32 mvfx0, [r1, #CRUNCH_MVAX1H] + cfmv32al mvfx0, mvax2 + cfstr32 mvfx0, [r1, #CRUNCH_MVAX2L] + cfmv32am mvfx0, mvax2 + cfstr32 mvfx0, [r1, #CRUNCH_MVAX2M] + cfmv32ah mvfx0, mvax2 + cfstr32 mvfx0, [r1, #CRUNCH_MVAX2H] + cfmv32al mvfx0, mvax3 + cfstr32 mvfx0, [r1, #CRUNCH_MVAX3L] + cfmv32am mvfx0, mvax3 + cfstr32 mvfx0, [r1, #CRUNCH_MVAX3M] + cfmv32ah mvfx0, mvax3 + cfstr32 mvfx0, [r1, #CRUNCH_MVAX3H] + + cfmv32sc mvdx0, dspsc @ save status word + cfstr64 mvdx0, [r1, #CRUNCH_DSPSC] + + teq r0, #0 @ anything to load? + cfldr64eq mvdx0, [r1, #CRUNCH_MVDX0] @ mvdx0 was clobbered + moveq pc, lr + +crunch_load: + cfldr64 mvdx0, [r0, #CRUNCH_DSPSC] @ load status word + cfmvsc32 dspsc, mvdx0 + + cfldr32 mvfx0, [r0, #CRUNCH_MVAX0L] @ load 72b accumulators + cfmval32 mvax0, mvfx0 + cfldr32 mvfx0, [r0, #CRUNCH_MVAX0M] + cfmvam32 mvax0, mvfx0 + cfldr32 mvfx0, [r0, #CRUNCH_MVAX0H] + cfmvah32 mvax0, mvfx0 + cfldr32 mvfx0, [r0, #CRUNCH_MVAX1L] + cfmval32 mvax1, mvfx0 + cfldr32 mvfx0, [r0, #CRUNCH_MVAX1M] + cfmvam32 mvax1, mvfx0 + cfldr32 mvfx0, [r0, #CRUNCH_MVAX1H] + cfmvah32 mvax1, mvfx0 + cfldr32 mvfx0, [r0, #CRUNCH_MVAX2L] + cfmval32 mvax2, mvfx0 + cfldr32 mvfx0, [r0, #CRUNCH_MVAX2M] + cfmvam32 mvax2, mvfx0 + cfldr32 mvfx0, [r0, #CRUNCH_MVAX2H] + cfmvah32 mvax2, mvfx0 + cfldr32 mvfx0, [r0, #CRUNCH_MVAX3L] + cfmval32 mvax3, mvfx0 + cfldr32 mvfx0, [r0, #CRUNCH_MVAX3M] + cfmvam32 mvax3, mvfx0 + cfldr32 mvfx0, [r0, #CRUNCH_MVAX3H] + cfmvah32 mvax3, mvfx0 + + cfldr64 mvdx0, [r0, #CRUNCH_MVDX0] @ load 64b registers + cfldr64 mvdx1, [r0, #CRUNCH_MVDX1] + cfldr64 mvdx2, [r0, #CRUNCH_MVDX2] + cfldr64 mvdx3, [r0, #CRUNCH_MVDX3] + cfldr64 mvdx4, [r0, #CRUNCH_MVDX4] + cfldr64 mvdx5, [r0, #CRUNCH_MVDX5] + cfldr64 mvdx6, [r0, #CRUNCH_MVDX6] + cfldr64 mvdx7, [r0, #CRUNCH_MVDX7] + cfldr64 mvdx8, [r0, #CRUNCH_MVDX8] + cfldr64 mvdx9, [r0, #CRUNCH_MVDX9] + cfldr64 mvdx10, [r0, #CRUNCH_MVDX10] + cfldr64 mvdx11, [r0, #CRUNCH_MVDX11] + cfldr64 mvdx12, [r0, #CRUNCH_MVDX12] + cfldr64 mvdx13, [r0, #CRUNCH_MVDX13] + cfldr64 mvdx14, [r0, #CRUNCH_MVDX14] + cfldr64 mvdx15, [r0, #CRUNCH_MVDX15] + + mov pc, lr + +/* + * Back up crunch regs to save area and disable access to them + * (mainly for gdb or sleep mode usage) + * + * r0 = struct thread_info pointer of target task or NULL for any + */ +ENTRY(crunch_task_disable) + stmfd sp!, {r4, r5, lr} + + mrs ip, cpsr + orr r2, ip, #PSR_I_BIT @ disable interrupts + msr cpsr_c, r2 + + ldr r4, =(EP93XX_APB_VIRT_BASE + 0x00130000) @ syscon addr + + ldr r3, =crunch_owner + add r2, r0, #TI_CRUNCH_STATE @ get task crunch save area + ldr r1, [r3] @ get current crunch owner + teq r1, #0 @ any current owner? + beq 1f @ no: quit + teq r0, #0 @ any owner? + teqne r1, r2 @ or specified one? + bne 1f @ no: quit + + ldr r5, [r4, #0x80] @ enable access to crunch + mov r2, #0xaa + str r2, [r4, #0xc0] + orr r5, r5, #0x00800000 + str r5, [r4, #0x80] + + mov r0, #0 @ nothing to load + str r0, [r3] @ no more current owner + ldr r2, [r4, #0x80] @ flush out enable (@@@) + mov r2, r2 + bl crunch_save + + mov r2, #0xaa @ disable access to crunch + str r2, [r4, #0xc0] + bic r5, r5, #0x00800000 + str r5, [r4, #0x80] + ldr r5, [r4, #0x80] @ flush out enable (@@@) + mov r5, r5 + +1: msr cpsr_c, ip @ restore interrupt mode + ldmfd sp!, {r4, r5, pc} + +/* + * Copy crunch state to given memory address + * + * r0 = struct thread_info pointer of target task + * r1 = memory address where to store crunch state + * + * this is called mainly in the creation of signal stack frames + */ +ENTRY(crunch_task_copy) + mrs ip, cpsr + orr r2, ip, #PSR_I_BIT @ disable interrupts + msr cpsr_c, r2 + + ldr r3, =crunch_owner + add r2, r0, #TI_CRUNCH_STATE @ get task crunch save area + ldr r3, [r3] @ get current crunch owner + teq r2, r3 @ does this task own it... + beq 1f + + @ current crunch values are in the task save area + msr cpsr_c, ip @ restore interrupt mode + mov r0, r1 + mov r1, r2 + mov r2, #CRUNCH_SIZE + b memcpy + +1: @ this task owns crunch regs -- grab a copy from there + mov r0, #0 @ nothing to load + mov r3, lr @ preserve return address + bl crunch_save + msr cpsr_c, ip @ restore interrupt mode + mov pc, r3 + +/* + * Restore crunch state from given memory address + * + * r0 = struct thread_info pointer of target task + * r1 = memory address where to get crunch state from + * + * this is used to restore crunch state when unwinding a signal stack frame + */ +ENTRY(crunch_task_restore) + mrs ip, cpsr + orr r2, ip, #PSR_I_BIT @ disable interrupts + msr cpsr_c, r2 + + ldr r3, =crunch_owner + add r2, r0, #TI_CRUNCH_STATE @ get task crunch save area + ldr r3, [r3] @ get current crunch owner + teq r2, r3 @ does this task own it... + beq 1f + + @ this task doesn't own crunch regs -- use its save area + msr cpsr_c, ip @ restore interrupt mode + mov r0, r2 + mov r2, #CRUNCH_SIZE + b memcpy + +1: @ this task owns crunch regs -- load them directly + mov r0, r1 + mov r1, #0 @ nothing to save + mov r3, lr @ preserve return address + bl crunch_load + msr cpsr_c, ip @ restore interrupt mode + mov pc, r3 diff --git a/arch/arm/kernel/crunch.c b/arch/arm/kernel/crunch.c new file mode 100644 index 000000000..cec837832 --- /dev/null +++ b/arch/arm/kernel/crunch.c @@ -0,0 +1,82 @@ +/* + * arch/arm/kernel/crunch.c + * Cirrus MaverickCrunch context switching and handling + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/init.h> +#include <asm/arch/ep93xx-regs.h> +#include <asm/thread_notify.h> +#include <asm/io.h> + +struct crunch_state *crunch_owner; + +void crunch_task_release(struct thread_info *thread) +{ + local_irq_disable(); + if (crunch_owner == &thread->crunchstate) + crunch_owner = NULL; + local_irq_enable(); +} + +static int crunch_enabled(u32 devcfg) +{ + return !!(devcfg & EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE); +} + +static int crunch_do(struct notifier_block *self, unsigned long cmd, void *t) +{ + struct thread_info *thread = (struct thread_info *)t; + struct crunch_state *crunch_state; + u32 devcfg; + + crunch_state = &thread->crunchstate; + + switch (cmd) { + case THREAD_NOTIFY_FLUSH: + memset(crunch_state, 0, sizeof(*crunch_state)); + + /* + * FALLTHROUGH: Ensure we don't try to overwrite our newly + * initialised state information on the first fault. + */ + + case THREAD_NOTIFY_RELEASE: + crunch_task_release(thread); + break; + + case THREAD_NOTIFY_SWITCH: + devcfg = __raw_readl(EP93XX_SYSCON_DEVICE_CONFIG); + if (crunch_enabled(devcfg) || crunch_owner == crunch_state) { + devcfg ^= EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE; + __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); + __raw_writel(devcfg, EP93XX_SYSCON_DEVICE_CONFIG); + } + break; + } + + return NOTIFY_DONE; +} + +static struct notifier_block crunch_notifier_block = { + .notifier_call = crunch_do, +}; + +static int __init crunch_init(void) +{ + thread_register_notifier(&crunch_notifier_block); + + return 0; +} + +late_initcall(crunch_init); diff --git a/arch/arm/kernel/iwmmxt-notifier.c b/arch/arm/kernel/iwmmxt-notifier.c new file mode 100644 index 000000000..0d1a1db40 --- /dev/null +++ b/arch/arm/kernel/iwmmxt-notifier.c @@ -0,0 +1,63 @@ +/* + * linux/arch/arm/kernel/iwmmxt-notifier.c + * + * XScale iWMMXt (Concan) context switching and handling + * + * Initial code: + * Copyright (c) 2003, Intel Corporation + * + * Full lazy switching support, optimizations and more, by Nicolas Pitre + * Copyright (c) 2003-2004, MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/init.h> +#include <asm/thread_notify.h> +#include <asm/io.h> + +static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t) +{ + struct thread_info *thread = t; + + switch (cmd) { + case THREAD_NOTIFY_FLUSH: + /* + * flush_thread() zeroes thread->fpstate, so no need + * to do anything here. + * + * FALLTHROUGH: Ensure we don't try to overwrite our newly + * initialised state information on the first fault. + */ + + case THREAD_NOTIFY_RELEASE: + iwmmxt_task_release(thread); + break; + + case THREAD_NOTIFY_SWITCH: + iwmmxt_task_switch(thread); + break; + } + + return NOTIFY_DONE; +} + +static struct notifier_block iwmmxt_notifier_block = { + .notifier_call = iwmmxt_do, +}; + +static int __init iwmmxt_init(void) +{ + thread_register_notifier(&iwmmxt_notifier_block); + + return 0; +} + +late_initcall(iwmmxt_init); diff --git a/arch/arm/mach-at91rm9200/at91rm9200.c b/arch/arm/mach-at91rm9200/at91rm9200.c new file mode 100644 index 000000000..0985b1c42 --- /dev/null +++ b/arch/arm/mach-at91rm9200/at91rm9200.c @@ -0,0 +1,154 @@ +/* + * arch/arm/mach-at91rm9200/at91rm9200.c + * + * Copyright (C) 2005 SAN People + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/module.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <asm/hardware.h> +#include "generic.h" + +static struct map_desc at91rm9200_io_desc[] __initdata = { + { + .virtual = AT91_VA_BASE_SYS, + .pfn = __phys_to_pfn(AT91_BASE_SYS), + .length = SZ_4K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_SPI, + .pfn = __phys_to_pfn(AT91_BASE_SPI), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_SSC2, + .pfn = __phys_to_pfn(AT91_BASE_SSC2), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_SSC1, + .pfn = __phys_to_pfn(AT91_BASE_SSC1), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_SSC0, + .pfn = __phys_to_pfn(AT91_BASE_SSC0), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_US3, + .pfn = __phys_to_pfn(AT91_BASE_US3), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_US2, + .pfn = __phys_to_pfn(AT91_BASE_US2), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_US1, + .pfn = __phys_to_pfn(AT91_BASE_US1), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_US0, + .pfn = __phys_to_pfn(AT91_BASE_US0), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_EMAC, + .pfn = __phys_to_pfn(AT91_BASE_EMAC), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_TWI, + .pfn = __phys_to_pfn(AT91_BASE_TWI), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_MCI, + .pfn = __phys_to_pfn(AT91_BASE_MCI), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_UDP, + .pfn = __phys_to_pfn(AT91_BASE_UDP), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_TCB1, + .pfn = __phys_to_pfn(AT91_BASE_TCB1), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_VA_BASE_TCB0, + .pfn = __phys_to_pfn(AT91_BASE_TCB0), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_SRAM_VIRT_BASE, + .pfn = __phys_to_pfn(AT91_SRAM_BASE), + .length = AT91_SRAM_SIZE, + .type = MT_DEVICE, + }, +}; + +void __init at91rm9200_map_io(void) +{ + iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc)); +} + +/* + * The default interrupt priority levels (0 = lowest, 7 = highest). + */ +static unsigned int at91rm9200_default_irq_priority[NR_AIC_IRQS] __initdata = { + 7, /* Advanced Interrupt Controller (FIQ) */ + 7, /* System Peripherals */ + 0, /* Parallel IO Controller A */ + 0, /* Parallel IO Controller B */ + 0, /* Parallel IO Controller C */ + 0, /* Parallel IO Controller D */ + 6, /* USART 0 */ + 6, /* USART 1 */ + 6, /* USART 2 */ + 6, /* USART 3 */ + 0, /* Multimedia Card Interface */ + 4, /* USB Device Port */ + 0, /* Two-Wire Interface */ + 6, /* Serial Peripheral Interface */ + 5, /* Serial Synchronous Controller 0 */ + 5, /* Serial Synchronous Controller 1 */ + 5, /* Serial Synchronous Controller 2 */ + 0, /* Timer Counter 0 */ + 0, /* Timer Counter 1 */ + 0, /* Timer Counter 2 */ + 0, /* Timer Counter 3 */ + 0, /* Timer Counter 4 */ + 0, /* Timer Counter 5 */ + 3, /* USB Host port */ + 3, /* Ethernet MAC */ + 0, /* Advanced Interrupt Controller (IRQ0) */ + 0, /* Advanced Interrupt Controller (IRQ1) */ + 0, /* Advanced Interrupt Controller (IRQ2) */ + 0, /* Advanced Interrupt Controller (IRQ3) */ + 0, /* Advanced Interrupt Controller (IRQ4) */ + 0, /* Advanced Interrupt Controller (IRQ5) */ + 0 /* Advanced Interrupt Controller (IRQ6) */ +}; + +void __init at91rm9200_init_irq(unsigned int priority[NR_AIC_IRQS]) +{ + if (!priority) + priority = at91rm9200_default_irq_priority; + + at91_aic_init(priority); +} diff --git a/arch/arm/mach-at91rm9200/at91rm9200_time.c b/arch/arm/mach-at91rm9200/at91rm9200_time.c new file mode 100644 index 000000000..a92a8622c --- /dev/null +++ b/arch/arm/mach-at91rm9200/at91rm9200_time.c @@ -0,0 +1,141 @@ +/* + * linux/arch/arm/mach-at91rm9200/at91rm9200_time.c + * + * Copyright (C) 2003 SAN People + * Copyright (C) 2003 ATMEL + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> + +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/mach/time.h> + +static unsigned long last_crtr; + +/* + * The ST_CRTR is updated asynchronously to the master clock. It is therefore + * necessary to read it twice (with the same value) to ensure accuracy. + */ +static inline unsigned long read_CRTR(void) { + unsigned long x1, x2; + + do { + x1 = at91_sys_read(AT91_ST_CRTR); + x2 = at91_sys_read(AT91_ST_CRTR); + } while (x1 != x2); + + return x1; +} + +/* + * Returns number of microseconds since last timer interrupt. Note that interrupts + * will have been disabled by do_gettimeofday() + * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy. + * 'tick' is usecs per jiffy (linux/timex.h). + */ +static unsigned long at91rm9200_gettimeoffset(void) +{ + unsigned long elapsed; + + elapsed = (read_CRTR() - last_crtr) & AT91_ST_ALMV; + + return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH; +} + +/* + * IRQ handler for the timer. + */ +static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) { /* This is a shared interrupt */ + write_seqlock(&xtime_lock); + + while (((read_CRTR() - last_crtr) & AT91_ST_ALMV) >= LATCH) { + timer_tick(regs); + last_crtr = (last_crtr + LATCH) & AT91_ST_ALMV; + } + + write_sequnlock(&xtime_lock); + + return IRQ_HANDLED; + } + else + return IRQ_NONE; /* not handled */ +} + +static struct irqaction at91rm9200_timer_irq = { + .name = "at91_tick", + .flags = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER, + .handler = at91rm9200_timer_interrupt +}; + +void at91rm9200_timer_reset(void) +{ + last_crtr = 0; + + /* Real time counter incremented every 30.51758 microseconds */ + at91_sys_write(AT91_ST_RTMR, 1); + + /* Set Period Interval timer */ + at91_sys_write(AT91_ST_PIMR, LATCH); + + /* Enable Period Interval Timer interrupt */ + at91_sys_write(AT91_ST_IER, AT91_ST_PITS); +} + +/* + * Set up timer interrupt. + */ +void __init at91rm9200_timer_init(void) +{ + /* Disable all timer interrupts */ + at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS); + (void) at91_sys_read(AT91_ST_SR); /* Clear any pending interrupts */ + + /* Make IRQs happen for the system timer */ + setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq); + + /* Change the kernel's 'tick' value to 10009 usec. (the default is 10000) */ + tick_usec = (LATCH * 1000000) / CLOCK_TICK_RATE; + + /* Initialize and enable the timer interrupt */ + at91rm9200_timer_reset(); +} + +#ifdef CONFIG_PM +static void at91rm9200_timer_suspend(void) +{ + /* disable Period Interval Timer interrupt */ + at91_sys_write(AT91_ST_IDR, AT91_ST_PITS); +} +#else +#define at91rm9200_timer_suspend NULL +#endif + +struct sys_timer at91rm9200_timer = { + .init = at91rm9200_timer_init, + .offset = at91rm9200_gettimeoffset, + .suspend = at91rm9200_timer_suspend, + .resume = at91rm9200_timer_reset, +}; + diff --git a/arch/arm/mach-at91rm9200/board-1arm.c b/arch/arm/mach-at91rm9200/board-1arm.c new file mode 100644 index 000000000..051a295e8 --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-1arm.c @@ -0,0 +1,108 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-1arm.c + * + * Copyright (C) 2005 SAN People + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include <asm/hardware.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/irq.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <asm/hardware.h> +#include <asm/arch/board.h> +#include <asm/arch/gpio.h> + +#include "generic.h" + +static void __init onearm_init_irq(void) +{ + /* Initialize AIC controller */ + at91rm9200_init_irq(NULL); + + /* Set up the GPIO interrupts */ + at91_gpio_irq_setup(PQFP_GPIO_BANKS); +} + +/* + * Serial port configuration. + * 0 .. 3 = USART0 .. USART3 + * 4 = DBGU + */ +static struct at91_uart_config __initdata onearm_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 3, + .tty_map = { 4, 0, 1, -1, -1 }, /* ttyS0, ..., ttyS4 */ +}; + +static void __init onearm_map_io(void) +{ + at91rm9200_map_io(); + + /* Initialize clocks: 18.432 MHz crystal */ + at91_clock_init(18432000); + + /* Setup the serial ports and console */ + at91_init_serial(&onearm_uart_config); +} + +static struct at91_eth_data __initdata onearm_eth_data = { + .phy_irq_pin = AT91_PIN_PC4, + .is_rmii = 1, +}; + +static struct at91_usbh_data __initdata onearm_usbh_data = { + .ports = 1, +}; + +static struct at91_udc_data __initdata onearm_udc_data = { + .vbus_pin = AT91_PIN_PC2, + .pullup_pin = AT91_PIN_PC3, +}; + +static void __init onearm_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* Ethernet */ + at91_add_device_eth(&onearm_eth_data); + /* USB Host */ + at91_add_device_usbh(&onearm_usbh_data); + /* USB Device */ + at91_add_device_udc(&onearm_udc_data); +} + +MACHINE_START(ONEARM, "Ajeco 1ARM single board computer") + /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91rm9200_timer, + .map_io = onearm_map_io, + .init_irq = onearm_init_irq, + .init_machine = onearm_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91rm9200/board-carmeva.c b/arch/arm/mach-at91rm9200/board-carmeva.c new file mode 100644 index 000000000..1efcd04fd --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-carmeva.c @@ -0,0 +1,130 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-carmeva.c + * + * Copyright (c) 2005 Peer Georgi + * Conitec Datasystems + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include <asm/hardware.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/irq.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <asm/hardware.h> +#include <asm/arch/board.h> +#include <asm/arch/gpio.h> + +#include "generic.h" + +static void __init carmeva_init_irq(void) +{ + /* Initialize AIC controller */ + at91rm9200_init_irq(NULL); + + /* Set up the GPIO interrupts */ + at91_gpio_irq_setup(BGA_GPIO_BANKS); +} + +/* + * Serial port configuration. + * 0 .. 3 = USART0 .. USART3 + * 4 = DBGU + */ +static struct at91_uart_config __initdata carmeva_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 2, + .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; + +static void __init carmeva_map_io(void) +{ + at91rm9200_map_io(); + + /* Initialize clocks: 20.000 MHz crystal */ + at91_clock_init(20000000); + + /* Setup the serial ports and console */ + at91_init_serial(&carmeva_uart_config); +} + +static struct at91_eth_data __initdata carmeva_eth_data = { + .phy_irq_pin = AT91_PIN_PC4, + .is_rmii = 1, +}; + +static struct at91_usbh_data __initdata carmeva_usbh_data = { + .ports = 2, +}; + +static struct at91_udc_data __initdata carmeva_udc_data = { + .vbus_pin = AT91_PIN_PD12, + .pullup_pin = AT91_PIN_PD9, +}; + +/* FIXME: user dependend */ +// static struct at91_cf_data __initdata carmeva_cf_data = { +// .det_pin = AT91_PIN_PB0, +// .rst_pin = AT91_PIN_PC5, + // .irq_pin = ... not connected + // .vcc_pin = ... always powered +// }; + +static struct at91_mmc_data __initdata carmeva_mmc_data = { + .is_b = 0, + .wire4 = 1, +}; + +static void __init carmeva_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* Ethernet */ + at91_add_device_eth(&carmeva_eth_data); + /* USB Host */ + at91_add_device_usbh(&carmeva_usbh_data); + /* USB Device */ + at91_add_device_udc(&carmeva_udc_data); + /* I2C */ + at91_add_device_i2c(); + /* Compact Flash */ +// at91_add_device_cf(&carmeva_cf_data); + /* SPI */ +// at91_add_device_spi(NULL, 0); + /* MMC */ + at91_add_device_mmc(&carmeva_mmc_data); +} + +MACHINE_START(CARMEVA, "Carmeva") + /* Maintainer: Conitec Datasystems */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91rm9200_timer, + .map_io = carmeva_map_io, + .init_irq = carmeva_init_irq, + .init_machine = carmeva_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91rm9200/board-eb9200.c b/arch/arm/mach-at91rm9200/board-eb9200.c new file mode 100644 index 000000000..4531f34c6 --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-eb9200.c @@ -0,0 +1,129 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-eb9200.c + * + * Copyright (C) 2005 SAN People, adapted for ATEB9200 from Embest + * by Andrew Patrikalakis + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/device.h> + +#include <asm/hardware.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/irq.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <asm/hardware.h> +#include <asm/arch/board.h> +#include <asm/arch/gpio.h> + +#include "generic.h" + +static void __init eb9200_init_irq(void) +{ + /* Initialize AIC controller */ + at91rm9200_init_irq(NULL); + + /* Set up the GPIO interrupts */ + at91_gpio_irq_setup(BGA_GPIO_BANKS); +} + +/* + * Serial port configuration. + * 0 .. 3 = USART0 .. USART3 + * 4 = DBGU + */ +static struct at91_uart_config __initdata eb9200_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 2, + .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; + +static void __init eb9200_map_io(void) +{ + at91rm9200_map_io(); + + /* Initialize clocks: 18.432 MHz crystal */ + at91_clock_init(18432000); + + /* Setup the serial ports and console */ + at91_init_serial(&eb9200_uart_config); +} + +static struct at91_eth_data __initdata eb9200_eth_data = { + .phy_irq_pin = AT91_PIN_PC4, + .is_rmii = 1, +}; + +static struct at91_usbh_data __initdata eb9200_usbh_data = { + .ports = 2, +}; + +static struct at91_udc_data __initdata eb9200_udc_data = { + .vbus_pin = AT91_PIN_PD4, + .pullup_pin = AT91_PIN_PD5, +}; + +static struct at91_cf_data __initdata eb9200_cf_data = { + .det_pin = AT91_PIN_PB0, + .rst_pin = AT91_PIN_PC5, + // .irq_pin = ... not connected + // .vcc_pin = ... always powered +}; + +static struct at91_mmc_data __initdata eb9200_mmc_data = { + .is_b = 0, + .wire4 = 1, +}; + +static void __init eb9200_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* Ethernet */ + at91_add_device_eth(&eb9200_eth_data); + /* USB Host */ + at91_add_device_usbh(&eb9200_usbh_data); + /* USB Device */ + at91_add_device_udc(&eb9200_udc_data); + /* I2C */ + at91_add_device_i2c(); + /* Compact Flash */ + at91_add_device_cf(&eb9200_cf_data); + /* SPI */ + at91_add_device_spi(NULL, 0); + /* MMC */ + /* only supports 1 or 4 bit interface, not wired through to SPI */ + at91_add_device_mmc(&eb9200_mmc_data); +} + +MACHINE_START(ATEB9200, "Embest ATEB9200") + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91rm9200_timer, + .map_io = eb9200_map_io, + .init_irq = eb9200_init_irq, + .init_machine = eb9200_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91rm9200/board-kafa.c b/arch/arm/mach-at91rm9200/board-kafa.c new file mode 100644 index 000000000..354b91c6b --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-kafa.c @@ -0,0 +1,115 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-kafa.c + * + * Copyright (C) 2006 Sperry-Sun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include <asm/hardware.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/irq.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <asm/hardware.h> +#include <asm/arch/board.h> +#include <asm/arch/gpio.h> + +#include "generic.h" + +static void __init kafa_init_irq(void) +{ + /* Initialize AIC controller */ + at91rm9200_init_irq(NULL); + + /* Set up the GPIO interrupts */ + at91_gpio_irq_setup(PQFP_GPIO_BANKS); +} + +/* + * Serial port configuration. + * 0 .. 3 = USART0 .. USART3 + * 4 = DBGU + */ +static struct at91_uart_config __initdata kafa_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 2, + .tty_map = { 4, 0, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; + +static void __init kafa_map_io(void) +{ + at91rm9200_map_io(); + + /* Initialize clocks: 18.432 MHz crystal */ + at91_clock_init(18432000); + + /* Set up the LEDs */ + at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4); + + /* Setup the serial ports and console */ + at91_init_serial(&kafa_uart_config); +} + +static struct at91_eth_data __initdata kafa_eth_data = { + .phy_irq_pin = AT91_PIN_PC4, + .is_rmii = 0, +}; + +static struct at91_usbh_data __initdata kafa_usbh_data = { + .ports = 1, +}; + +static struct at91_udc_data __initdata kafa_udc_data = { + .vbus_pin = AT91_PIN_PB6, + .pullup_pin = AT91_PIN_PB7, +}; + +static void __init kafa_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* Ethernet */ + at91_add_device_eth(&kafa_eth_data); + /* USB Host */ + at91_add_device_usbh(&kafa_usbh_data); + /* USB Device */ + at91_add_device_udc(&kafa_udc_data); + /* I2C */ + at91_add_device_i2c(); + /* SPI */ + at91_add_device_spi(NULL, 0); +} + +MACHINE_START(KAFA, "Sperry-Sun KAFA") + /* Maintainer: Sergei Sharonov */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91rm9200_timer, + .map_io = kafa_map_io, + .init_irq = kafa_init_irq, + .init_machine = kafa_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91rm9200/board-kb9202.c b/arch/arm/mach-at91rm9200/board-kb9202.c new file mode 100644 index 000000000..1827db4c5 --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-kb9202.c @@ -0,0 +1,124 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-kb9202.c + * + * Copyright (c) 2005 kb_admin + * KwikByte, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include <asm/hardware.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/irq.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <asm/hardware.h> +#include <asm/arch/board.h> +#include <asm/arch/gpio.h> + +#include "generic.h" + +static void __init kb9202_init_irq(void) +{ + /* Initialize AIC controller */ + at91rm9200_init_irq(NULL); + + /* Set up the GPIO interrupts */ + at91_gpio_irq_setup(PQFP_GPIO_BANKS); +} + +/* + * Serial port configuration. + * 0 .. 3 = USART0 .. USART3 + * 4 = DBGU + */ +static struct at91_uart_config __initdata kb9202_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 3, + .tty_map = { 4, 0, 1, -1, -1 } /* ttyS0, ..., ttyS4 */ +}; + +static void __init kb9202_map_io(void) +{ + at91rm9200_map_io(); + + /* Initialize clocks: 10 MHz crystal */ + at91_clock_init(10000000); + + /* Set up the LEDs */ + at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18); + + /* Setup the serial ports and console */ + at91_init_serial(&kb9202_uart_config); +} + +static struct at91_eth_data __initdata kb9202_eth_data = { + .phy_irq_pin = AT91_PIN_PB29, + .is_rmii = 0, +}; + +static struct at91_usbh_data __initdata kb9202_usbh_data = { + .ports = 1, +}; + +static struct at91_udc_data __initdata kb9202_udc_data = { + .vbus_pin = AT91_PIN_PB24, + .pullup_pin = AT91_PIN_PB22, +}; + +static struct at91_mmc_data __initdata kb9202_mmc_data = { + .det_pin = AT91_PIN_PB2, + .is_b = 0, + .wire4 = 1, +}; + +static void __init kb9202_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* Ethernet */ + at91_add_device_eth(&kb9202_eth_data); + /* USB Host */ + at91_add_device_usbh(&kb9202_usbh_data); + /* USB Device */ + at91_add_device_udc(&kb9202_udc_data); + /* MMC */ + at91_add_device_mmc(&kb9202_mmc_data); + /* I2C */ + at91_add_device_i2c(); + /* SPI */ + at91_add_device_spi(NULL, 0); +} + +MACHINE_START(KB9200, "KB920x") + /* Maintainer: KwikByte, Inc. */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91rm9200_timer, + .map_io = kb9202_map_io, + .init_irq = kb9202_init_irq, + .init_machine = kb9202_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91rm9200/pm.c b/arch/arm/mach-at91rm9200/pm.c new file mode 100644 index 000000000..47e5480fe --- /dev/null +++ b/arch/arm/mach-at91rm9200/pm.c @@ -0,0 +1,225 @@ +/* + * arch/arm/mach-at91rm9200/pm.c + * AT91 Power Management + * + * Copyright (C) 2005 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/pm.h> +#include <linux/sched.h> +#include <linux/proc_fs.h> +#include <linux/pm.h> +#include <linux/interrupt.h> +#include <linux/sysfs.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/atomic.h> +#include <asm/mach/time.h> +#include <asm/mach/irq.h> +#include <asm/mach-types.h> + +#include <asm/arch/gpio.h> + +#include "generic.h" + + +static int at91_pm_valid_state(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_ON: + case PM_SUSPEND_STANDBY: + case PM_SUSPEND_MEM: + return 1; + + default: + return 0; + } +} + + +static suspend_state_t target_state; + +/* + * Called after processes are frozen, but before we shutdown devices. + */ +static int at91_pm_prepare(suspend_state_t state) +{ + target_state = state; + return 0; +} + +/* + * Verify that all the clocks are correct before entering + * slow-clock mode. + */ +static int at91_pm_verify_clocks(void) +{ + unsigned long scsr; + int i; + + scsr = at91_sys_read(AT91_PMC_SCSR); + + /* USB must not be using PLLB */ + if ((scsr & (AT91_PMC_UHP | AT91_PMC_UDP)) != 0) { + pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n"); + return 0; + } + +#ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS + /* PCK0..PCK3 must be disabled, or configured to use clk32k */ + for (i = 0; i < 4; i++) { + u32 css; + + if ((scsr & (AT91_PMC_PCK0 << i)) == 0) + continue; + + css = at91_sys_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS; + if (css != AT91_PMC_CSS_SLOW) { + pr_debug("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css); + return 0; + } + } +#endif + + return 1; +} + +/* + * Call this from platform driver suspend() to see how deeply to suspend. + * For example, some controllers (like OHCI) need one of the PLL clocks + * in order to act as a wakeup source, and those are not available when + * going into slow clock mode. + * + * REVISIT: generalize as clk_will_be_available(clk)? Other platforms have + * the very same problem (but not using at91 main_clk), and it'd be better + * to add one generic API rather than lots of platform-specific ones. + */ +int at91_suspend_entering_slow_clock(void) +{ + return (target_state == PM_SUSPEND_MEM); +} +EXPORT_SYMBOL(at91_suspend_entering_slow_clock); + + +static void (*slow_clock)(void); + + + +static int at91_pm_enter(suspend_state_t state) +{ + at91_gpio_suspend(); + at91_irq_suspend(); + + pr_debug("AT91: PM - wake mask %08x, pm state %d\n", + /* remember all the always-wake irqs */ + (at91_sys_read(AT91_PMC_PCSR) + | (1 << AT91_ID_FIQ) + | (1 << AT91_ID_SYS) + | (1 << AT91_ID_IRQ0) + | (1 << AT91_ID_IRQ1) + | (1 << AT91_ID_IRQ2) + | (1 << AT91_ID_IRQ3) + | (1 << AT91_ID_IRQ4) + | (1 << AT91_ID_IRQ5) + | (1 << AT91_ID_IRQ6)) + & at91_sys_read(AT91_AIC_IMR), + state); + + switch (state) { + /* + * Suspend-to-RAM is like STANDBY plus slow clock mode, so + * drivers must suspend more deeply: only the master clock + * controller may be using the main oscillator. + */ + case PM_SUSPEND_MEM: + /* + * Ensure that clocks are in a valid state. + */ + if (!at91_pm_verify_clocks()) + goto error; + + /* + * Enter slow clock mode by switching over to clk32k and + * turning off the main oscillator; reverse on wakeup. + */ + if (slow_clock) { + slow_clock(); + break; + } else { + /* DEVELOPMENT ONLY */ + pr_info("AT91: PM - no slow clock mode yet ...\n"); + /* FALLTHROUGH leaving master clock alone */ + } + + /* + * STANDBY mode has *all* drivers suspended; ignores irqs not + * marked as 'wakeup' event sources; and reduces DRAM power. + * But otherwise it's identical to PM_SUSPEND_ON: cpu idle, and + * nothing fancy done with main or cpu clocks. + */ + case PM_SUSPEND_STANDBY: + /* + * NOTE: the Wait-for-Interrupt instruction needs to be + * in icache so the SDRAM stays in self-refresh mode until + * the wakeup IRQ occurs. + */ + asm("b 1f; .align 5; 1:"); + asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */ + at91_sys_write(AT91_SDRAMC_SRR, 1); /* self-refresh mode */ + /* fall though to next state */ + + case PM_SUSPEND_ON: + asm("mcr p15, 0, r0, c7, c0, 4"); /* wait for interrupt */ + break; + + default: + pr_debug("AT91: PM - bogus suspend state %d\n", state); + goto error; + } + + pr_debug("AT91: PM - wakeup %08x\n", + at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR)); + +error: + target_state = PM_SUSPEND_ON; + at91_irq_resume(); + at91_gpio_resume(); + return 0; +} + + +static struct pm_ops at91_pm_ops ={ + .pm_disk_mode = 0, + .valid = at91_pm_valid_state, + .prepare = at91_pm_prepare, + .enter = at91_pm_enter, +}; + +static int __init at91_pm_init(void) +{ + printk("AT91: Power Management\n"); + +#ifdef CONFIG_AT91_PM_SLOW_CLOCK + /* REVISIT allocations of SRAM should be dynamically managed. + * FIQ handlers and other components will want SRAM/TCM too... + */ + slow_clock = (void *) (AT91_VA_BASE_SRAM + (3 * SZ_4K)); + memcpy(slow_clock, at91rm9200_slow_clock, at91rm9200_slow_clock_sz); +#endif + + /* Disable SDRAM low-power mode. Cannot be used with self-refresh. */ + at91_sys_write(AT91_SDRAMC_LPR, 0); + + pm_set_ops(&at91_pm_ops); + + return 0; +} +arch_initcall(at91_pm_init); diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c new file mode 100644 index 000000000..08ad782c1 --- /dev/null +++ b/arch/arm/mach-ep93xx/clock.c @@ -0,0 +1,156 @@ +/* + * arch/arm/mach-ep93xx/clock.c + * Clock control for Cirrus EP93xx chips. + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/string.h> +#include <asm/div64.h> +#include <asm/hardware.h> +#include <asm/io.h> + +struct clk { + char *name; + unsigned long rate; + int users; + u32 enable_reg; + u32 enable_mask; +}; + +static struct clk clk_pll1 = { + .name = "pll1", +}; +static struct clk clk_f = { + .name = "fclk", +}; +static struct clk clk_h = { + .name = "hclk", +}; +static struct clk clk_p = { + .name = "pclk", +}; +static struct clk clk_pll2 = { + .name = "pll2", +}; +static struct clk clk_usb_host = { + .name = "usb_host", + .enable_reg = EP93XX_SYSCON_CLOCK_CONTROL, + .enable_mask = EP93XX_SYSCON_CLOCK_USH_EN, +}; + + +static struct clk *clocks[] = { + &clk_pll1, + &clk_f, + &clk_h, + &clk_p, + &clk_pll2, + &clk_usb_host, +}; + +struct clk *clk_get(struct device *dev, const char *id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(clocks); i++) { + if (!strcmp(clocks[i]->name, id)) + return clocks[i]; + } + + return ERR_PTR(-ENOENT); +} + +int clk_enable(struct clk *clk) +{ + if (!clk->users++ && clk->enable_reg) { + u32 value; + + value = __raw_readl(clk->enable_reg); + __raw_writel(value | clk->enable_mask, clk->enable_reg); + } + + return 0; +} + +void clk_disable(struct clk *clk) +{ + if (!--clk->users && clk->enable_reg) { + u32 value; + + value = __raw_readl(clk->enable_reg); + __raw_writel(value & ~clk->enable_mask, clk->enable_reg); + } +} + +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} + +void clk_put(struct clk *clk) +{ +} + + + +static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 }; +static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 }; +static char pclk_divisors[] = { 1, 2, 4, 8 }; + +/* + * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS + */ +static unsigned long calc_pll_rate(u32 config_word) +{ + unsigned long long rate; + int i; + + rate = 14745600; + rate *= ((config_word >> 11) & 0x1f) + 1; /* X1FBD */ + rate *= ((config_word >> 5) & 0x3f) + 1; /* X2FBD */ + do_div(rate, (config_word & 0x1f) + 1); /* X2IPD */ + for (i = 0; i < ((config_word >> 16) & 3); i++) /* PS */ + rate >>= 1; + + return (unsigned long)rate; +} + +void ep93xx_clock_init(void) +{ + u32 value; + + value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1); + if (!(value & 0x00800000)) { /* PLL1 bypassed? */ + clk_pll1.rate = 14745600; + } else { + clk_pll1.rate = calc_pll_rate(value); + } + clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7]; + clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7]; + clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3]; + + value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2); + if (!(value & 0x00080000)) { /* PLL2 bypassed? */ + clk_pll2.rate = 14745600; + } else if (value & 0x00040000) { /* PLL2 enabled? */ + clk_pll2.rate = calc_pll_rate(value); + } else { + clk_pll2.rate = 0; + } + clk_usb_host.rate = clk_pll2.rate / (((value >> 28) & 0xf) + 1); + + printk(KERN_INFO "ep93xx: PLL1 running at %ld MHz, PLL2 at %ld MHz\n", + clk_pll1.rate / 1000000, clk_pll2.rate / 1000000); + printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n", + clk_f.rate / 1000000, clk_h.rate / 1000000, + clk_p.rate / 1000000); +} diff --git a/arch/arm/mach-ep93xx/edb9302.c b/arch/arm/mach-ep93xx/edb9302.c new file mode 100644 index 000000000..0315615b7 --- /dev/null +++ b/arch/arm/mach-ep93xx/edb9302.c @@ -0,0 +1,61 @@ +/* + * arch/arm/mach-ep93xx/edb9302.c + * Cirrus Logic EDB9302 support. + * + * Copyright (C) 2006 George Kashperko <george@chas.com.ua> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/mtd/physmap.h> +#include <linux/platform_device.h> +#include <asm/io.h> +#include <asm/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +static struct physmap_flash_data edb9302_flash_data = { + .width = 2, +}; + +static struct resource edb9302_flash_resource = { + .start = 0x60000000, + .end = 0x60ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device edb9302_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &edb9302_flash_data, + }, + .num_resources = 1, + .resource = &edb9302_flash_resource, +}; + +static void __init edb9302_init_machine(void) +{ + ep93xx_init_devices(); + platform_device_register(&edb9302_flash); +} + +MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board") + /* Maintainer: George Kashperko <george@chas.com.ua> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = edb9302_init_machine, +MACHINE_END diff --git a/arch/arm/mach-ep93xx/edb9315.c b/arch/arm/mach-ep93xx/edb9315.c new file mode 100644 index 000000000..249ca9e57 --- /dev/null +++ b/arch/arm/mach-ep93xx/edb9315.c @@ -0,0 +1,61 @@ +/* + * arch/arm/mach-ep93xx/edb9315.c + * Cirrus Logic EDB9315 support. + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/mtd/physmap.h> +#include <linux/platform_device.h> +#include <asm/io.h> +#include <asm/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +static struct physmap_flash_data edb9315_flash_data = { + .width = 4, +}; + +static struct resource edb9315_flash_resource = { + .start = 0x60000000, + .end = 0x61ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device edb9315_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &edb9315_flash_data, + }, + .num_resources = 1, + .resource = &edb9315_flash_resource, +}; + +static void __init edb9315_init_machine(void) +{ + ep93xx_init_devices(); + platform_device_register(&edb9315_flash); +} + +MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board") + /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = edb9315_init_machine, +MACHINE_END diff --git a/arch/arm/mach-ep93xx/edb9315a.c b/arch/arm/mach-ep93xx/edb9315a.c new file mode 100644 index 000000000..e03407e72 --- /dev/null +++ b/arch/arm/mach-ep93xx/edb9315a.c @@ -0,0 +1,61 @@ +/* + * arch/arm/mach-ep93xx/edb9315a.c + * Cirrus Logic EDB9315A support. + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/mtd/physmap.h> +#include <linux/platform_device.h> +#include <asm/io.h> +#include <asm/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +static struct physmap_flash_data edb9315a_flash_data = { + .width = 2, +}; + +static struct resource edb9315a_flash_resource = { + .start = 0x60000000, + .end = 0x60ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device edb9315a_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &edb9315a_flash_data, + }, + .num_resources = 1, + .resource = &edb9315a_flash_resource, +}; + +static void __init edb9315a_init_machine(void) +{ + ep93xx_init_devices(); + platform_device_register(&edb9315a_flash); +} + +MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board") + /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0xc0000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = edb9315a_init_machine, +MACHINE_END diff --git a/arch/arm/mach-lh7a40x/clcd.c b/arch/arm/mach-lh7a40x/clcd.c new file mode 100644 index 000000000..1992db4c2 --- /dev/null +++ b/arch/arm/mach-lh7a40x/clcd.c @@ -0,0 +1,241 @@ +/* + * arch/arm/mach-lh7a40x/clcd.c + * + * Copyright (C) 2004 Marc Singer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + */ + +#include <linux/init.h> +#include <linux/device.h> +#include <linux/dma-mapping.h> +#include <linux/sysdev.h> +#include <linux/interrupt.h> + +//#include <linux/module.h> +//#include <linux/time.h> +//#include <asm/hardware.h> + +//#include <asm/mach/time.h> +#include <asm/irq.h> +#include <asm/mach/irq.h> + +#include <asm/system.h> +#include <asm/hardware.h> +#include <linux/amba/bus.h> +#include <linux/amba/clcd.h> + +#define HRTFTC_HRSETUP __REG(HRTFTC_PHYS + 0x00) +#define HRTFTC_HRCON __REG(HRTFTC_PHYS + 0x04) +#define HRTFTC_HRTIMING1 __REG(HRTFTC_PHYS + 0x08) +#define HRTFTC_HRTIMING2 __REG(HRTFTC_PHYS + 0x0c) + +#define ALI_SETUP __REG(ALI_PHYS + 0x00) +#define ALI_CONTROL __REG(ALI_PHYS + 0x04) +#define ALI_TIMING1 __REG(ALI_PHYS + 0x08) +#define ALI_TIMING2 __REG(ALI_PHYS + 0x0c) + +#include "lcd-panel.h" + +static void lh7a40x_clcd_disable (struct clcd_fb *fb) +{ +#if defined (CONFIG_MACH_LPD7A400) + CPLD_CONTROL &= ~(1<<1); /* Disable LCD Vee */ +#endif + +#if defined (CONFIG_MACH_LPD7A404) + GPIO_PCD &= ~(1<<3); /* Disable LCD Vee */ +#endif + +#if defined (CONFIG_ARCH_LH7A400) + HRTFTC_HRSETUP &= ~(1<<13); /* Disable HRTFT controller */ +#endif + +#if defined (CONFIG_ARCH_LH7A404) + ALI_SETUP &= ~(1<<13); /* Disable ALI */ +#endif +} + +static void lh7a40x_clcd_enable (struct clcd_fb *fb) +{ + struct clcd_panel_extra* extra + = (struct clcd_panel_extra*) fb->board_data; + +#if defined (CONFIG_MACH_LPD7A400) + CPLD_CONTROL |= (1<<1); /* Enable LCD Vee */ +#endif + +#if defined (CONFIG_MACH_LPD7A404) + GPIO_PCDD &= ~(1<<3); /* Enable LCD Vee */ + GPIO_PCD |= (1<<3); +#endif + +#if defined (CONFIG_ARCH_LH7A400) + + if (extra) { + HRTFTC_HRSETUP + = (1 << 13) + | ((fb->fb.var.xres - 1) << 4) + | 0xc + | (extra->hrmode ? 1 : 0); + HRTFTC_HRCON + = ((extra->clsen ? 1 : 0) << 1) + | ((extra->spsen ? 1 : 0) << 0); + HRTFTC_HRTIMING1 + = (extra->pcdel << 8) + | (extra->revdel << 4) + | (extra->lpdel << 0); + HRTFTC_HRTIMING2 + = (extra->spldel << 9) + | (extra->pc2del << 0); + } + else + HRTFTC_HRSETUP + = (1 << 13) + | 0xc; +#endif + +#if defined (CONFIG_ARCH_LH7A404) + + if (extra) { + ALI_SETUP + = (1 << 13) + | ((fb->fb.var.xres - 1) << 4) + | 0xc + | (extra->hrmode ? 1 : 0); + ALI_CONTROL + = ((extra->clsen ? 1 : 0) << 1) + | ((extra->spsen ? 1 : 0) << 0); + ALI_TIMING1 + = (extra->pcdel << 8) + | (extra->revdel << 4) + | (extra->lpdel << 0); + ALI_TIMING2 + = (extra->spldel << 9) + | (extra->pc2del << 0); + } + else + ALI_SETUP + = (1 << 13) + | 0xc; +#endif + +} + +#define FRAMESIZE(s) (((s) + PAGE_SIZE - 1)&PAGE_MASK) + +static int lh7a40x_clcd_setup (struct clcd_fb *fb) +{ + dma_addr_t dma; + u32 len = FRAMESIZE (lcd_panel.mode.xres*lcd_panel.mode.yres + *(lcd_panel.bpp/8)); + + fb->panel = &lcd_panel; + + /* Enforce the sync polarity defaults */ + if (!(fb->panel->tim2 & TIM2_IHS)) + fb->fb.var.sync |= FB_SYNC_HOR_HIGH_ACT; + if (!(fb->panel->tim2 & TIM2_IVS)) + fb->fb.var.sync |= FB_SYNC_VERT_HIGH_ACT; + +#if defined (HAS_LCD_PANEL_EXTRA) + fb->board_data = &lcd_panel_extra; +#endif + + fb->fb.screen_base + = dma_alloc_writecombine (&fb->dev->dev, len, + &dma, GFP_KERNEL); + printk ("CLCD: LCD setup fb virt 0x%p phys 0x%p l %x io 0x%p \n", + fb->fb.screen_base, (void*) dma, len, + (void*) io_p2v (CLCDC_PHYS)); + printk ("CLCD: pixclock %d\n", lcd_panel.mode.pixclock); + + if (!fb->fb.screen_base) { + printk(KERN_ERR "CLCD: unable to map framebuffer\n"); + return -ENOMEM; + } + +#if defined (USE_RGB555) + fb->fb.var.green.length = 5; /* Panel uses RGB 5:5:5 */ +#endif + + fb->fb.fix.smem_start = dma; + fb->fb.fix.smem_len = len; + + /* Drive PE4 high to prevent CPLD crash */ + GPIO_PEDD |= (1<<4); + GPIO_PED |= (1<<4); + + GPIO_PINMUX |= (1<<1) | (1<<0); /* LCDVD[15:4] */ + +// fb->fb.fbops->fb_check_var (&fb->fb.var, &fb->fb); +// fb->fb.fbops->fb_set_par (&fb->fb); + + return 0; +} + +static int lh7a40x_clcd_mmap (struct clcd_fb *fb, struct vm_area_struct *vma) +{ + return dma_mmap_writecombine(&fb->dev->dev, vma, + fb->fb.screen_base, + fb->fb.fix.smem_start, + fb->fb.fix.smem_len); +} + +static void lh7a40x_clcd_remove (struct clcd_fb *fb) +{ + dma_free_writecombine (&fb->dev->dev, fb->fb.fix.smem_len, + fb->fb.screen_base, fb->fb.fix.smem_start); +} + +static struct clcd_board clcd_platform_data = { + .name = "lh7a40x FB", + .check = clcdfb_check, + .decode = clcdfb_decode, + .enable = lh7a40x_clcd_enable, + .setup = lh7a40x_clcd_setup, + .mmap = lh7a40x_clcd_mmap, + .remove = lh7a40x_clcd_remove, + .disable = lh7a40x_clcd_disable, +}; + +#define IRQ_CLCDC (IRQ_LCDINTR) + +#define AMBA_DEVICE(name,busid,base,plat,pid) \ +static struct amba_device name##_device = { \ + .dev = { \ + .coherent_dma_mask = ~0, \ + .bus_id = busid, \ + .platform_data = plat, \ + }, \ + .res = { \ + .start = base##_PHYS, \ + .end = (base##_PHYS) + (4*1024) - 1, \ + .flags = IORESOURCE_MEM, \ + }, \ + .dma_mask = ~0, \ + .irq = { IRQ_##base, }, \ + /* .dma = base##_DMA,*/ \ + .periphid = pid, \ +} + +AMBA_DEVICE(clcd, "cldc-lh7a40x", CLCDC, &clcd_platform_data, 0x41110); + +static struct amba_device *amba_devs[] __initdata = { + &clcd_device, +}; + +void __init lh7a40x_clcd_init (void) +{ + int i; + int result; + printk ("CLCD: registering amba devices\n"); + for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { + struct amba_device *d = amba_devs[i]; + result = amba_device_register(d, &iomem_resource); + printk (" %d -> %d\n", i ,result); + } +} diff --git a/arch/arm/mach-lh7a40x/clocks.c b/arch/arm/mach-lh7a40x/clocks.c new file mode 100644 index 000000000..7530a95c1 --- /dev/null +++ b/arch/arm/mach-lh7a40x/clocks.c @@ -0,0 +1,198 @@ +/* arch/arm/mach-lh7a40x/clocks.c + * + * Copyright (C) 2004 Marc Singer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + */ + +#include <linux/cpufreq.h> +#include <asm/hardware.h> +#include <asm/arch/clocks.h> +#include <linux/err.h> + +struct module; +struct icst525_params; + +struct clk { + struct list_head node; + unsigned long rate; + struct module *owner; + const char *name; +// void *data; +// const struct icst525_params *params; +// void (*setvco)(struct clk *, struct icst525_vco vco); +}; + +int clk_register(struct clk *clk); +void clk_unregister(struct clk *clk); + +/* ----- */ + +#define MAINDIV1(c) (((c) >> 7) & 0x0f) +#define MAINDIV2(c) (((c) >> 11) & 0x1f) +#define PS(c) (((c) >> 18) & 0x03) +#define PREDIV(c) (((c) >> 2) & 0x1f) +#define HCLKDIV(c) (((c) >> 0) & 0x02) +#define PCLKDIV(c) (((c) >> 16) & 0x03) + +unsigned int cpufreq_get (unsigned int cpu) /* in kHz */ +{ + return fclkfreq_get ()/1000; +} +EXPORT_SYMBOL(cpufreq_get); + +unsigned int fclkfreq_get (void) +{ + unsigned int clkset = CSC_CLKSET; + unsigned int gclk + = XTAL_IN + / (1 << PS(clkset)) + * (MAINDIV1(clkset) + 2) + / (PREDIV(clkset) + 2) + * (MAINDIV2(clkset) + 2) + ; + return gclk; +} + +unsigned int hclkfreq_get (void) +{ + unsigned int clkset = CSC_CLKSET; + unsigned int hclk = fclkfreq_get () / (HCLKDIV(clkset) + 1); + + return hclk; +} + +unsigned int pclkfreq_get (void) +{ + unsigned int clkset = CSC_CLKSET; + int pclkdiv = PCLKDIV(clkset); + unsigned int pclk; + if (pclkdiv == 0x3) + pclkdiv = 0x2; + pclk = hclkfreq_get () / (1 << pclkdiv); + + return pclk; +} + +/* ----- */ + +static LIST_HEAD(clocks); +static DECLARE_MUTEX(clocks_sem); + +struct clk *clk_get (struct device *dev, const char *id) +{ + struct clk *p; + struct clk *clk = ERR_PTR(-ENOENT); + + down (&clocks_sem); + list_for_each_entry (p, &clocks, node) { + if (strcmp (id, p->name) == 0 + && try_module_get(p->owner)) { + clk = p; + break; + } + } + up (&clocks_sem); + + return clk; +} +EXPORT_SYMBOL(clk_get); + +void clk_put (struct clk *clk) +{ + module_put(clk->owner); +} +EXPORT_SYMBOL(clk_put); + +int clk_enable (struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable (struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +int clk_use (struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_use); + +void clk_unuse (struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_unuse); + +unsigned long clk_get_rate (struct clk *clk) +{ + return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +long clk_round_rate (struct clk *clk, unsigned long rate) +{ + return rate; +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate (struct clk *clk, unsigned long rate) +{ + int ret = -EIO; + return ret; +} +EXPORT_SYMBOL(clk_set_rate); + +#if 0 +/* + * These are fixed clocks. + */ +static struct clk kmi_clk = { + .name = "KMIREFCLK", + .rate = 24000000, +}; + +static struct clk uart_clk = { + .name = "UARTCLK", + .rate = 24000000, +}; + +static struct clk mmci_clk = { + .name = "MCLK", + .rate = 33000000, +}; +#endif + +static struct clk clcd_clk = { + .name = "CLCDCLK", + .rate = 0, +}; + +int clk_register (struct clk *clk) +{ + down (&clocks_sem); + list_add (&clk->node, &clocks); + up (&clocks_sem); + return 0; +} +EXPORT_SYMBOL(clk_register); + +void clk_unregister (struct clk *clk) +{ + down (&clocks_sem); + list_del (&clk->node); + up (&clocks_sem); +} +EXPORT_SYMBOL(clk_unregister); + +static int __init clk_init (void) +{ + clk_register(&clcd_clk); + return 0; +} +arch_initcall(clk_init); diff --git a/arch/arm/mach-lh7a40x/lcd-panel.h b/arch/arm/mach-lh7a40x/lcd-panel.h new file mode 100644 index 000000000..4fb2efc49 --- /dev/null +++ b/arch/arm/mach-lh7a40x/lcd-panel.h @@ -0,0 +1,346 @@ +/* lcd-panel.h + $Id$ + + written by Marc Singer + 18 Jul 2005 + + Copyright (C) 2005 Marc Singer + + ----------- + DESCRIPTION + ----------- + + Only one panel may be defined at a time. + + The pixel clock is calculated to be no greater than the target. + + Each timing value is accompanied by a specification comment. + + UNITS/MIN/TYP/MAX + + Most of the units will be in clocks. + + USE_RGB555 + + Define this macro to configure the AMBA LCD controller to use an + RGB555 encoding for the pels instead of the normal RGB565. + + LPD9520, LPD79524, LPD7A400, LPD7A404-10, LPD7A404-11 + + These boards are best approximated by 555 for all panels. Some + can use an extra low-order bit of blue in bit 16 of the color + value, but we don't have a way to communicate this non-linear + mapping to the kernel. + +*/ + +#if !defined (__LCD_PANEL_H__) +# define __LCD_PANEL_H__ + +#if defined (MACH_LPD79520)\ + || defined (MACH_LPD79524)\ + || defined (MACH_LPD7A400)\ + || defined (MACH_LPD7A404) +# define USE_RGB555 +#endif + +struct clcd_panel_extra { + unsigned int hrmode; + unsigned int clsen; + unsigned int spsen; + unsigned int pcdel; + unsigned int revdel; + unsigned int lpdel; + unsigned int spldel; + unsigned int pc2del; +}; + +#define NS_TO_CLOCK(ns,c) ((((ns)*((c)/1000) + (1000000 - 1))/1000000)) +#define CLOCK_TO_DIV(e,c) (((c) + (e) - 1)/(e)) + +#if defined CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT + + /* Logic Product Development LCD 3.5" QVGA HRTFT -10 */ + /* Sharp PN LQ035Q7DB02 w/HRTFT controller chip */ + +#define PIX_CLOCK_TARGET (6800000) +#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK) +#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER) + +static struct clcd_panel lcd_panel = { + .mode = { + .name = "3.5in QVGA (LQ035Q7DB02)", + .xres = 240, + .yres = 320, + .pixclock = PIX_CLOCK, + .left_margin = 16, + .right_margin = 21, + .upper_margin = 8, // line/8/8/8 + .lower_margin = 5, + .hsync_len = 61, + .vsync_len = NS_TO_CLOCK (60, PIX_CLOCK), + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_IPC | (PIX_CLOCK_DIVIDER - 2), + .cntl = CNTL_LCDTFT | CNTL_WATERMARK, + .bpp = 16, +}; + +#define HAS_LCD_PANEL_EXTRA + +static struct clcd_panel_extra lcd_panel_extra = { + .hrmode = 1, + .clsen = 1, + .spsen = 1, + .pcdel = 8, + .revdel = 7, + .lpdel = 13, + .spldel = 77, + .pc2del = 208, +}; + +#endif + +#if defined CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02 + + /* Logic Product Development LCD 5.7" QVGA -10 */ + /* Sharp PN LQ057Q3DC02 */ + /* QVGA mode, V/Q=LOW */ + +/* From Sharp on 2006.1.3. I believe some of the values are incorrect + * based on the datasheet. + + Timing0 TIMING1 TIMING2 CONTROL + 0x140A0C4C 0x080504EF 0x013F380D 0x00000829 + HBP= 20 VBP= 8 BCD= 0 + HFP= 10 VFP= 5 CPL=319 + HSW= 12 VSW= 1 IOE= 0 + PPL= 19 LPP=239 IPC= 1 + IHS= 1 + IVS= 1 + ACB= 0 + CSEL= 0 + PCD= 13 + + */ + +/* The full horozontal cycle (Th) is clock/360/400/450. */ +/* The full vertical cycle (Tv) is line/251/262/280. */ + +#define PIX_CLOCK_TARGET (6300000) /* -/6.3/7 MHz */ +#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK) +#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER) + +static struct clcd_panel lcd_panel = { + .mode = { + .name = "5.7in QVGA (LQ057Q3DC02)", + .xres = 320, + .yres = 240, + .pixclock = PIX_CLOCK, + .left_margin = 11, + .right_margin = 400-11-320-2, + .upper_margin = 7, // line/7/7/7 + .lower_margin = 262-7-240-2, + .hsync_len = 2, // clk/2/96/200 + .vsync_len = 2, // line/2/-/34 + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_IHS | TIM2_IVS + | (PIX_CLOCK_DIVIDER - 2), + .cntl = CNTL_LCDTFT | CNTL_WATERMARK, + .bpp = 16, +}; + +#endif + +#if defined CONFIG_FB_ARMCLCD_SHARP_LQ64D343 + + /* Logic Product Development LCD 6.4" VGA -10 */ + /* Sharp PN LQ64D343 */ + +/* The full horozontal cycle (Th) is clock/750/800/900. */ +/* The full vertical cycle (Tv) is line/515/525/560. */ + +#define PIX_CLOCK_TARGET (28330000) +#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK) +#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER) + +static struct clcd_panel lcd_panel = { + .mode = { + .name = "6.4in QVGA (LQ64D343)", + .xres = 640, + .yres = 480, + .pixclock = PIX_CLOCK, + .left_margin = 32, + .right_margin = 800-32-640-96, + .upper_margin = 32, // line/34/34/34 + .lower_margin = 540-32-480-2, + .hsync_len = 96, // clk/2/96/200 + .vsync_len = 2, // line/2/-/34 + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_IHS | TIM2_IVS + | (PIX_CLOCK_DIVIDER - 2), + .cntl = CNTL_LCDTFT | CNTL_WATERMARK, + .bpp = 16, +}; + +#endif + +#if defined CONFIG_FB_ARMCLCD_SHARP_LQ10D368 + + /* Logic Product Development LCD 10.4" VGA -10 */ + /* Sharp PN LQ10D368 */ + +#define PIX_CLOCK_TARGET (28330000) +#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK) +#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER) + +static struct clcd_panel lcd_panel = { + .mode = { + .name = "10.4in VGA (LQ10D368)", + .xres = 640, + .yres = 480, + .pixclock = PIX_CLOCK, + .left_margin = 21, + .right_margin = 15, + .upper_margin = 34, + .lower_margin = 5, + .hsync_len = 96, + .vsync_len = 16, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_IHS | TIM2_IVS + | (PIX_CLOCK_DIVIDER - 2), + .cntl = CNTL_LCDTFT | CNTL_WATERMARK, + .bpp = 16, +}; + +#endif + +#if defined CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41 + + /* Logic Product Development LCD 12.1" SVGA -10 */ + /* Sharp PN LQ121S1DG41, was LQ121S1DG31 */ + +/* Note that with a 99993900 Hz HCLK, it is not possible to hit the + * target clock frequency range of 35MHz to 42MHz. */ + +/* If the target pixel clock is substantially lower than the panel + * spec, this is done to prevent the LCD display from glitching when + * the CPU is under load. A pixel clock higher than 25MHz + * (empirically determined) will compete with the CPU for bus cycles + * for the Ethernet chip. However, even a pixel clock of 10MHz + * competes with Compact Flash interface during some operations + * (fdisk, e2fsck). And, at that speed the display may have a visible + * flicker. */ + +/* The full horozontal cycle (Th) is clock/832/1056/1395. */ + +#define PIX_CLOCK_TARGET (20000000) +#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK) +#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER) + +static struct clcd_panel lcd_panel = { + .mode = { + .name = "12.1in SVGA (LQ121S1DG41)", + .xres = 800, + .yres = 600, + .pixclock = PIX_CLOCK, + .left_margin = 89, // ns/5/-/(1/PIX_CLOCK)-10 + .right_margin = 1056-800-89-128, + .upper_margin = 23, // line/23/23/23 + .lower_margin = 44, + .hsync_len = 128, // clk/2/128/200 + .vsync_len = 4, // line/2/4/6 + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_IHS | TIM2_IVS + | (PIX_CLOCK_DIVIDER - 2), + .cntl = CNTL_LCDTFT | CNTL_WATERMARK, + .bpp = 16, +}; + +#endif + +#if defined CONFIG_FB_ARMCLCD_HITACHI + + /* Hitachi*/ + /* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */ + +#define PIX_CLOCK_TARGET (49000000) +#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK) +#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER) + +static struct clcd_panel lcd_panel = { + .mode = { + .name = "Hitachi 800x480", + .xres = 800, + .yres = 480, + .pixclock = PIX_CLOCK, + .left_margin = 88, + .right_margin = 40, + .upper_margin = 32, + .lower_margin = 11, + .hsync_len = 128, + .vsync_len = 2, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_IPC | TIM2_IHS | TIM2_IVS + | (PIX_CLOCK_DIVIDER - 2), + .cntl = CNTL_LCDTFT | CNTL_WATERMARK, + .bpp = 16, +}; + +#endif + + +#if defined CONFIG_FB_ARMCLCD_AUO_A070VW01_WIDE + + /* AU Optotronics A070VW01 7.0 Wide Screen color Display*/ + /* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */ + +#define PIX_CLOCK_TARGET (10000000) +#define PIX_CLOCK_DIVIDER CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK) +#define PIX_CLOCK (HCLK/PIX_CLOCK_DIVIDER) + +static struct clcd_panel lcd_panel = { + .mode = { + .name = "7.0in Wide (A070VW01)", + .xres = 480, + .yres = 234, + .pixclock = PIX_CLOCK, + .left_margin = 30, + .right_margin = 25, + .upper_margin = 14, + .lower_margin = 12, + .hsync_len = 100, + .vsync_len = 1, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = TIM2_IPC | TIM2_IHS | TIM2_IVS + | (PIX_CLOCK_DIVIDER - 2), + .cntl = CNTL_LCDTFT | CNTL_WATERMARK, + .bpp = 16, +}; + +#endif + +#undef NS_TO_CLOCK +#undef CLOCK_TO_DIV + +#endif /* __LCD_PANEL_H__ */ diff --git a/arch/arm/mach-lh7a40x/ssp-cpld.c b/arch/arm/mach-lh7a40x/ssp-cpld.c new file mode 100644 index 000000000..a10830186 --- /dev/null +++ b/arch/arm/mach-lh7a40x/ssp-cpld.c @@ -0,0 +1,343 @@ +/* arch/arm/mach-lh7a40x/ssp-cpld.c + * + * Copyright (C) 2004,2005 Marc Singer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * SSP/SPI driver for the CardEngine CPLD. + * + */ + +/* NOTES + ----- + + o *** This driver is cribbed from the 7952x implementation. + Some comments may not apply. + + o This driver contains sufficient logic to control either the + serial EEPROMs or the audio codec. It is included in the kernel + to support the codec. The EEPROMs are really the responsibility + of the boot loader and should probably be left alone. + + o The code must be augmented to cope with multiple, simultaneous + clients. + o The audio codec writes to the codec chip whenever playback + starts. + o The touchscreen driver writes to the ads chip every time it + samples. + o The audio codec must write 16 bits, but the touch chip writes + are 8 bits long. + o We need to be able to keep these configurations separate while + simultaneously active. + + */ + +#include <linux/module.h> +#include <linux/kernel.h> +//#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/interrupt.h> +//#include <linux/ioport.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/spinlock.h> + +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/hardware.h> + +#include <asm/arch/ssp.h> + +//#define TALK + +#if defined (TALK) +#define PRINTK(f...) printk (f) +#else +#define PRINTK(f...) do {} while (0) +#endif + +#if defined (CONFIG_ARCH_LH7A400) +# define CPLD_SPID __REGP16(CPLD06_VIRT) /* SPI data */ +# define CPLD_SPIC __REGP16(CPLD08_VIRT) /* SPI control */ +# define CPLD_SPIC_CS_CODEC (1<<0) +# define CPLD_SPIC_CS_TOUCH (1<<1) +# define CPLD_SPIC_WRITE (0<<2) +# define CPLD_SPIC_READ (1<<2) +# define CPLD_SPIC_DONE (1<<3) /* r/o */ +# define CPLD_SPIC_LOAD (1<<4) +# define CPLD_SPIC_START (1<<4) +# define CPLD_SPIC_LOADED (1<<5) /* r/o */ +#endif + +#define CPLD_SPI __REGP16(CPLD0A_VIRT) /* SPI operation */ +#define CPLD_SPI_CS_EEPROM (1<<3) +#define CPLD_SPI_SCLK (1<<2) +#define CPLD_SPI_TX_SHIFT (1) +#define CPLD_SPI_TX (1<<CPLD_SPI_TX_SHIFT) +#define CPLD_SPI_RX_SHIFT (0) +#define CPLD_SPI_RX (1<<CPLD_SPI_RX_SHIFT) + +/* *** FIXME: these timing values are substantially larger than the + *** chip requires. We may implement an nsleep () function. */ +#define T_SKH 1 /* Clock time high (us) */ +#define T_SKL 1 /* Clock time low (us) */ +#define T_CS 1 /* Minimum chip select low time (us) */ +#define T_CSS 1 /* Minimum chip select setup time (us) */ +#define T_DIS 1 /* Data setup time (us) */ + + /* EEPROM SPI bits */ +#define P_START (1<<9) +#define P_WRITE (1<<7) +#define P_READ (2<<7) +#define P_ERASE (3<<7) +#define P_EWDS (0<<7) +#define P_WRAL (0<<7) +#define P_ERAL (0<<7) +#define P_EWEN (0<<7) +#define P_A_EWDS (0<<5) +#define P_A_WRAL (1<<5) +#define P_A_ERAL (2<<5) +#define P_A_EWEN (3<<5) + +struct ssp_configuration { + int device; + int mode; + int speed; + int frame_size_write; + int frame_size_read; +}; + +static struct ssp_configuration ssp_configuration; +static spinlock_t ssp_lock; + +static void enable_cs (void) +{ + switch (ssp_configuration.device) { + case DEVICE_EEPROM: + CPLD_SPI |= CPLD_SPI_CS_EEPROM; + break; + } + udelay (T_CSS); +} + +static void disable_cs (void) +{ + switch (ssp_configuration.device) { + case DEVICE_EEPROM: + CPLD_SPI &= ~CPLD_SPI_CS_EEPROM; + break; + } + udelay (T_CS); +} + +static void pulse_clock (void) +{ + CPLD_SPI |= CPLD_SPI_SCLK; + udelay (T_SKH); + CPLD_SPI &= ~CPLD_SPI_SCLK; + udelay (T_SKL); +} + + +/* execute_spi_command + + sends an spi command to a device. It first sends cwrite bits from + v. If cread is greater than zero it will read cread bits + (discarding the leading 0 bit) and return them. If cread is less + than zero it will check for completetion status and return 0 on + success or -1 on timeout. If cread is zero it does nothing other + than sending the command. + + On the LPD7A400, we can only read or write multiples of 8 bits on + the codec and the touch screen device. Here, we round up. + +*/ + +static int execute_spi_command (int v, int cwrite, int cread) +{ + unsigned long l = 0; + +#if defined (CONFIG_MACH_LPD7A400) + /* The codec and touch devices cannot be bit-banged. Instead, + * the CPLD provides an eight-bit shift register and a crude + * interface. */ + if ( ssp_configuration.device == DEVICE_CODEC + || ssp_configuration.device == DEVICE_TOUCH) { + int select = 0; + + PRINTK ("spi(%d %d.%d) 0x%04x", + ssp_configuration.device, cwrite, cread, + v); +#if defined (TALK) + if (ssp_configuration.device == DEVICE_CODEC) + PRINTK (" 0x%03x -> %2d", v & 0x1ff, (v >> 9) & 0x7f); +#endif + PRINTK ("\n"); + + if (ssp_configuration.device == DEVICE_CODEC) + select = CPLD_SPIC_CS_CODEC; + if (ssp_configuration.device == DEVICE_TOUCH) + select = CPLD_SPIC_CS_TOUCH; + if (cwrite) { + for (cwrite = (cwrite + 7)/8; cwrite-- > 0; ) { + CPLD_SPID = (v >> (8*cwrite)) & 0xff; + CPLD_SPIC = select | CPLD_SPIC_LOAD; + while (!(CPLD_SPIC & CPLD_SPIC_LOADED)) + ; + CPLD_SPIC = select; + while (!(CPLD_SPIC & CPLD_SPIC_DONE)) + ; + } + v = 0; + } + if (cread) { + mdelay (2); /* *** FIXME: required by ads7843? */ + v = 0; + for (cread = (cread + 7)/8; cread-- > 0;) { + CPLD_SPID = 0; + CPLD_SPIC = select | CPLD_SPIC_READ + | CPLD_SPIC_START; + while (!(CPLD_SPIC & CPLD_SPIC_LOADED)) + ; + CPLD_SPIC = select | CPLD_SPIC_READ; + while (!(CPLD_SPIC & CPLD_SPIC_DONE)) + ; + v = (v << 8) | CPLD_SPID; + } + } + return v; + } +#endif + + PRINTK ("spi(%d) 0x%04x -> 0x%x\r\n", ssp_configuration.device, + v & 0x1ff, (v >> 9) & 0x7f); + + enable_cs (); + + v <<= CPLD_SPI_TX_SHIFT; /* Correction for position of SPI_TX bit */ + while (cwrite--) { + CPLD_SPI + = (CPLD_SPI & ~CPLD_SPI_TX) + | ((v >> cwrite) & CPLD_SPI_TX); + udelay (T_DIS); + pulse_clock (); + } + + if (cread < 0) { + int delay = 10; + disable_cs (); + udelay (1); + enable_cs (); + + l = -1; + do { + if (CPLD_SPI & CPLD_SPI_RX) { + l = 0; + break; + } + } while (udelay (1), --delay); + } + else + /* We pulse the clock before the data to skip the leading zero. */ + while (cread-- > 0) { + pulse_clock (); + l = (l<<1) + | (((CPLD_SPI & CPLD_SPI_RX) + >> CPLD_SPI_RX_SHIFT) & 0x1); + } + + disable_cs (); + return l; +} + +static int ssp_init (void) +{ + spin_lock_init (&ssp_lock); + memset (&ssp_configuration, 0, sizeof (ssp_configuration)); + return 0; +} + + +/* ssp_chip_select + + drops the chip select line for the CPLD shift-register controlled + devices. It doesn't enable chip + +*/ + +static void ssp_chip_select (int enable) +{ +#if defined (CONFIG_MACH_LPD7A400) + int select; + + if (ssp_configuration.device == DEVICE_CODEC) + select = CPLD_SPIC_CS_CODEC; + else if (ssp_configuration.device == DEVICE_TOUCH) + select = CPLD_SPIC_CS_TOUCH; + else + return; + + if (enable) + CPLD_SPIC = select; + else + CPLD_SPIC = 0; +#endif +} + +static void ssp_acquire (void) +{ + spin_lock (&ssp_lock); +} + +static void ssp_release (void) +{ + ssp_chip_select (0); /* just in case */ + spin_unlock (&ssp_lock); +} + +static int ssp_configure (int device, int mode, int speed, + int frame_size_write, int frame_size_read) +{ + ssp_configuration.device = device; + ssp_configuration.mode = mode; + ssp_configuration.speed = speed; + ssp_configuration.frame_size_write = frame_size_write; + ssp_configuration.frame_size_read = frame_size_read; + + return 0; +} + +static int ssp_read (void) +{ + return execute_spi_command (0, 0, ssp_configuration.frame_size_read); +} + +static int ssp_write (u16 data) +{ + execute_spi_command (data, ssp_configuration.frame_size_write, 0); + return 0; +} + +static int ssp_write_read (u16 data) +{ + return execute_spi_command (data, ssp_configuration.frame_size_write, + ssp_configuration.frame_size_read); +} + +struct ssp_driver lh7a40x_cpld_ssp_driver = { + .init = ssp_init, + .acquire = ssp_acquire, + .release = ssp_release, + .configure = ssp_configure, + .chip_select = ssp_chip_select, + .read = ssp_read, + .write = ssp_write, + .write_read = ssp_write_read, +}; + + +MODULE_AUTHOR("Marc Singer"); +MODULE_DESCRIPTION("LPD7A40X CPLD SPI driver"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm/mach-netx/Kconfig b/arch/arm/mach-netx/Kconfig new file mode 100644 index 000000000..3d90ef19b --- /dev/null +++ b/arch/arm/mach-netx/Kconfig @@ -0,0 +1,24 @@ +menu "NetX Implementations" + depends on ARCH_NETX + +config MACH_NXDKN + bool "Enable Hilscher nxdkn Eval Board support" + depends on ARCH_NETX + help + Board support for the Hilscher NetX Eval Board + +config MACH_NXDB500 + bool "Enable Hilscher nxdb500 Eval Board support" + depends on ARCH_NETX + select ARM_AMBA + help + Board support for the Hilscher nxdb500 Eval Board + +config MACH_NXEB500HMI + bool "Enable Hilscher nxeb500hmi Eval Board support" + depends on ARCH_NETX + select ARM_AMBA + help + Board support for the Hilscher nxeb500hmi Eval Board + +endmenu diff --git a/arch/arm/mach-netx/Makefile b/arch/arm/mach-netx/Makefile new file mode 100644 index 000000000..18785ff37 --- /dev/null +++ b/arch/arm/mach-netx/Makefile @@ -0,0 +1,15 @@ +# +# Makefile for the linux kernel. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). + +# Object file lists. + +obj-y += time.o generic.o pfifo.o xc.o + +# Specific board support +obj-$(CONFIG_MACH_NXDKN) += nxdkn.o +obj-$(CONFIG_MACH_NXDB500) += nxdb500.o fb.o +obj-$(CONFIG_MACH_NXEB500HMI) += nxeb500hmi.o fb.o diff --git a/arch/arm/mach-netx/Makefile.boot b/arch/arm/mach-netx/Makefile.boot new file mode 100644 index 000000000..b81cf6aff --- /dev/null +++ b/arch/arm/mach-netx/Makefile.boot @@ -0,0 +1,2 @@ + zreladdr-y := 0x80008000 + diff --git a/arch/arm/mach-netx/fb.c b/arch/arm/mach-netx/fb.c new file mode 100644 index 000000000..ef0ab6115 --- /dev/null +++ b/arch/arm/mach-netx/fb.c @@ -0,0 +1,114 @@ +/* + * arch/arm/mach-netx/fb.c + * + * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/device.h> +#include <linux/init.h> +#include <linux/dma-mapping.h> +#include <linux/amba/bus.h> +#include <linux/amba/clcd.h> + +#include <asm/arch/netx-regs.h> +#include <asm/hardware.h> + +struct clk {}; + +static struct clk fb_clk; + +static struct clcd_panel *netx_panel; + +void netx_clcd_enable(struct clcd_fb *fb) +{ +} + +int netx_clcd_setup(struct clcd_fb *fb) +{ + dma_addr_t dma; + + fb->panel = netx_panel; + + fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, 1024*1024, + &dma, GFP_KERNEL); + if (!fb->fb.screen_base) { + printk(KERN_ERR "CLCD: unable to map framebuffer\n"); + return -ENOMEM; + } + + fb->fb.fix.smem_start = dma; + fb->fb.fix.smem_len = 1024*1024; + + return 0; +} + +int netx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) +{ + return dma_mmap_writecombine(&fb->dev->dev, vma, + fb->fb.screen_base, + fb->fb.fix.smem_start, + fb->fb.fix.smem_len); +} + +void netx_clcd_remove(struct clcd_fb *fb) +{ + dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len, + fb->fb.screen_base, fb->fb.fix.smem_start); +} + +void clk_disable(struct clk *clk) +{ +} + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + return 0; +} + +int clk_enable(struct clk *clk) +{ + return 0; +} + +struct clk *clk_get(struct device *dev, const char *id) +{ + return &fb_clk; +} + +void clk_put(struct clk *clk) +{ +} + +static struct amba_device fb_device = { + .dev = { + .bus_id = "fb", + .coherent_dma_mask = ~0, + }, + .res = { + .start = 0x00104000, + .end = 0x00104fff, + .flags = IORESOURCE_MEM, + }, + .irq = { NETX_IRQ_LCD, NO_IRQ }, + .periphid = 0x10112400, +}; + +int netx_fb_init(struct clcd_board *board, struct clcd_panel *panel) +{ + netx_panel = panel; + fb_device.dev.platform_data = board; + return amba_device_register(&fb_device, &iomem_resource); +} diff --git a/arch/arm/mach-netx/fb.h b/arch/arm/mach-netx/fb.h new file mode 100644 index 000000000..4919cf33a --- /dev/null +++ b/arch/arm/mach-netx/fb.h @@ -0,0 +1,24 @@ +/* + * arch/arm/mach-netx/fb.h + * + * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +void netx_clcd_enable(struct clcd_fb *fb); +int netx_clcd_setup(struct clcd_fb *fb); +int netx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma); +void netx_clcd_remove(struct clcd_fb *fb); +int netx_fb_init(struct clcd_board *board, struct clcd_panel *panel); diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c new file mode 100644 index 000000000..af0b13534 --- /dev/null +++ b/arch/arm/mach-netx/generic.c @@ -0,0 +1,193 @@ +/* + * arch/arm/mach-netx/generic.c + * + * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/device.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <asm/hardware.h> +#include <asm/mach/map.h> +#include <asm/hardware/vic.h> +#include <asm/io.h> +#include <asm/arch/netx-regs.h> +#include <asm/mach/irq.h> + +static struct map_desc netx_io_desc[] __initdata = { + { + .virtual = NETX_IO_VIRT, + .pfn = __phys_to_pfn(NETX_IO_PHYS), + .length = NETX_IO_SIZE, + .type = MT_DEVICE + } +}; + +void __init netx_map_io(void) +{ + iotable_init(netx_io_desc, ARRAY_SIZE(netx_io_desc)); +} + +static struct resource netx_rtc_resources[] = { + [0] = { + .start = 0x00101200, + .end = 0x00101220, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device netx_rtc_device = { + .name = "netx-rtc", + .id = 0, + .num_resources = ARRAY_SIZE(netx_rtc_resources), + .resource = netx_rtc_resources, +}; + +static struct platform_device *devices[] __initdata = { + &netx_rtc_device, +}; + +#if 0 +#define DEBUG_IRQ(fmt...) printk(fmt) +#else +#define DEBUG_IRQ(fmt...) while (0) {} +#endif + +static void +netx_hif_demux_handler(unsigned int irq_unused, struct irqdesc *desc, + struct pt_regs *regs) +{ + unsigned int irq = NETX_IRQ_HIF_CHAINED(0); + unsigned int stat; + + stat = ((readl(NETX_DPMAS_INT_EN) & + readl(NETX_DPMAS_INT_STAT)) >> 24) & 0x1f; + + desc = irq_desc + NETX_IRQ_HIF_CHAINED(0); + + while (stat) { + if (stat & 1) { + DEBUG_IRQ("handling irq %d\n", irq); + desc_handle_irq(irq, desc, regs); + } + irq++; + desc++; + stat >>= 1; + } +} + +static int +netx_hif_irq_type(unsigned int _irq, unsigned int type) +{ + unsigned int val, irq; + + val = readl(NETX_DPMAS_IF_CONF1); + + irq = _irq - NETX_IRQ_HIF_CHAINED(0); + + if (type & __IRQT_RISEDGE) { + DEBUG_IRQ("rising edges\n"); + val |= (1 << 26) << irq; + } + if (type & __IRQT_FALEDGE) { + DEBUG_IRQ("falling edges\n"); + val &= ~((1 << 26) << irq); + } + if (type & __IRQT_LOWLVL) { + DEBUG_IRQ("low level\n"); + val &= ~((1 << 26) << irq); + } + if (type & __IRQT_HIGHLVL) { + DEBUG_IRQ("high level\n"); + val |= (1 << 26) << irq; + } + + writel(val, NETX_DPMAS_IF_CONF1); + + return 0; +} + +static void +netx_hif_ack_irq(unsigned int _irq) +{ + unsigned int val, irq; + + irq = _irq - NETX_IRQ_HIF_CHAINED(0); + writel((1 << 24) << irq, NETX_DPMAS_INT_STAT); + + val = readl(NETX_DPMAS_INT_EN); + val &= ~((1 << 24) << irq); + writel(val, NETX_DPMAS_INT_EN); + + DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq); +} + +static void +netx_hif_mask_irq(unsigned int _irq) +{ + unsigned int val, irq; + + irq = _irq - NETX_IRQ_HIF_CHAINED(0); + val = readl(NETX_DPMAS_INT_EN); + val &= ~((1 << 24) << irq); + writel(val, NETX_DPMAS_INT_EN); + DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq); +} + +static void +netx_hif_unmask_irq(unsigned int _irq) +{ + unsigned int val, irq; + + irq = _irq - NETX_IRQ_HIF_CHAINED(0); + val = readl(NETX_DPMAS_INT_EN); + val |= (1 << 24) << irq; + writel(val, NETX_DPMAS_INT_EN); + DEBUG_IRQ("%s: irq %d\n", __FUNCTION__, _irq); +} + +static struct irqchip netx_hif_chip = { + .ack = netx_hif_ack_irq, + .mask = netx_hif_mask_irq, + .unmask = netx_hif_unmask_irq, + .set_type = netx_hif_irq_type, +}; + +void __init netx_init_irq(void) +{ + int irq; + + vic_init(__io(io_p2v(NETX_PA_VIC)), 0, ~0); + + for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) { + set_irq_chip(irq, &netx_hif_chip); + set_irq_handler(irq, do_level_IRQ); + set_irq_flags(irq, IRQF_VALID); + } + + writel(NETX_DPMAS_INT_EN_GLB_EN, NETX_DPMAS_INT_EN); + set_irq_chained_handler(NETX_IRQ_HIF, netx_hif_demux_handler); +} + +static int __init netx_init(void) +{ + return platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +subsys_initcall(netx_init); + diff --git a/arch/arm/mach-netx/generic.h b/arch/arm/mach-netx/generic.h new file mode 100644 index 000000000..ede2d3534 --- /dev/null +++ b/arch/arm/mach-netx/generic.h @@ -0,0 +1,24 @@ +/* + * arch/arm/mach-netx/generic.h + * + * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +extern void __init netx_map_io(void); +extern void __init netx_init_irq(void); + +struct sys_timer; +extern struct sys_timer netx_timer; diff --git a/arch/arm/mach-netx/nxdb500.c b/arch/arm/mach-netx/nxdb500.c new file mode 100644 index 000000000..e4a133d62 --- /dev/null +++ b/arch/arm/mach-netx/nxdb500.c @@ -0,0 +1,210 @@ +/* + * arch/arm/mach-netx/nxdb500.c + * + * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/dma-mapping.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/mtd/plat-ram.h> +#include <linux/platform_device.h> +#include <linux/amba/bus.h> +#include <linux/amba/clcd.h> + +#include <asm/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/arch/netx-regs.h> +#include <asm/arch/eth.h> + +#include "generic.h" +#include "fb.h" + +static struct clcd_panel qvga = { + .mode = { + .name = "QVGA", + .refresh = 60, + .xres = 240, + .yres = 320, + .pixclock = 187617, + .left_margin = 6, + .right_margin = 26, + .upper_margin = 0, + .lower_margin = 6, + .hsync_len = 6, + .vsync_len = 1, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = 16, + .cntl = CNTL_LCDTFT | CNTL_BGR, + .bpp = 16, + .grayscale = 0, +}; + +static inline int nxdb500_check(struct clcd_fb *fb, struct fb_var_screeninfo *var) +{ + var->green.length = 5; + var->green.msb_right = 0; + + return clcdfb_check(fb, var); +} + +static int nxdb500_clcd_setup(struct clcd_fb *fb) +{ + unsigned int val; + + fb->fb.var.green.length = 5; + fb->fb.var.green.msb_right = 0; + + /* enable asic control */ + val = readl(NETX_SYSTEM_IOC_ACCESS_KEY); + writel(val, NETX_SYSTEM_IOC_ACCESS_KEY); + + writel(3, NETX_SYSTEM_IOC_CR); + + val = readl(NETX_PIO_OUTPIO); + writel(val | 1, NETX_PIO_OUTPIO); + + val = readl(NETX_PIO_OEPIO); + writel(val | 1, NETX_PIO_OEPIO); + return netx_clcd_setup(fb); +} + +static struct clcd_board clcd_data = { + .name = "netX", + .check = nxdb500_check, + .decode = clcdfb_decode, + .enable = netx_clcd_enable, + .setup = nxdb500_clcd_setup, + .mmap = netx_clcd_mmap, + .remove = netx_clcd_remove, +}; + +static struct netxeth_platform_data eth0_platform_data = { + .xcno = 0, +}; + +static struct platform_device netx_eth0_device = { + .name = "netx-eth", + .id = 0, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð0_platform_data, + } +}; + +static struct netxeth_platform_data eth1_platform_data = { + .xcno = 1, +}; + +static struct platform_device netx_eth1_device = { + .name = "netx-eth", + .id = 1, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð1_platform_data, + } +}; + +static struct resource netx_uart0_resources[] = { + [0] = { + .start = 0x00100A00, + .end = 0x00100A3F, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = (NETX_IRQ_UART0), + .end = (NETX_IRQ_UART0), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device netx_uart0_device = { + .name = "netx-uart", + .id = 0, + .num_resources = ARRAY_SIZE(netx_uart0_resources), + .resource = netx_uart0_resources, +}; + +static struct resource netx_uart1_resources[] = { + [0] = { + .start = 0x00100A40, + .end = 0x00100A7F, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = (NETX_IRQ_UART1), + .end = (NETX_IRQ_UART1), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device netx_uart1_device = { + .name = "netx-uart", + .id = 1, + .num_resources = ARRAY_SIZE(netx_uart1_resources), + .resource = netx_uart1_resources, +}; + +static struct resource netx_uart2_resources[] = { + [0] = { + .start = 0x00100A80, + .end = 0x00100ABF, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = (NETX_IRQ_UART2), + .end = (NETX_IRQ_UART2), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device netx_uart2_device = { + .name = "netx-uart", + .id = 2, + .num_resources = ARRAY_SIZE(netx_uart2_resources), + .resource = netx_uart2_resources, +}; + +static struct platform_device *devices[] __initdata = { + &netx_eth0_device, + &netx_eth1_device, + &netx_uart0_device, + &netx_uart1_device, + &netx_uart2_device, +}; + +static void __init nxdb500_init(void) +{ + netx_fb_init(&clcd_data, &qvga); + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +MACHINE_START(NXDB500, "Hilscher nxdb500") + .phys_io = 0x00100000, + .io_pg_offst = (io_p2v(0x00100000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = netx_map_io, + .init_irq = netx_init_irq, + .timer = &netx_timer, + .init_machine = nxdb500_init, +MACHINE_END diff --git a/arch/arm/mach-netx/nxdkn.c b/arch/arm/mach-netx/nxdkn.c new file mode 100644 index 000000000..7e26c42d1 --- /dev/null +++ b/arch/arm/mach-netx/nxdkn.c @@ -0,0 +1,103 @@ +/* + * arch/arm/mach-netx/nxdkn.c + * + * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/dma-mapping.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/mtd/plat-ram.h> +#include <linux/platform_device.h> +#include <linux/amba/bus.h> +#include <linux/amba/clcd.h> + +#include <asm/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/arch/netx-regs.h> +#include <asm/arch/eth.h> + +#include "generic.h" + +static struct netxeth_platform_data eth0_platform_data = { + .xcno = 0, +}; + +static struct platform_device nxdkn_eth0_device = { + .name = "netx-eth", + .id = 0, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð0_platform_data, + } +}; + +static struct netxeth_platform_data eth1_platform_data = { + .xcno = 1, +}; + +static struct platform_device nxdkn_eth1_device = { + .name = "netx-eth", + .id = 1, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð1_platform_data, + } +}; + +static struct resource netx_uart0_resources[] = { + [0] = { + .start = 0x00100A00, + .end = 0x00100A3F, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = (NETX_IRQ_UART0), + .end = (NETX_IRQ_UART0), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device netx_uart0_device = { + .name = "netx-uart", + .id = 0, + .num_resources = ARRAY_SIZE(netx_uart0_resources), + .resource = netx_uart0_resources, +}; + +static struct platform_device *devices[] __initdata = { + &nxdkn_eth0_device, + &nxdkn_eth1_device, + &netx_uart0_device, +}; + +static void __init nxdkn_init(void) +{ + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +MACHINE_START(NXDKN, "Hilscher nxdkn") + .phys_io = 0x00100000, + .io_pg_offst = (io_p2v(0x00100000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = netx_map_io, + .init_irq = netx_init_irq, + .timer = &netx_timer, + .init_machine = nxdkn_init, +MACHINE_END diff --git a/arch/arm/mach-netx/nxeb500hmi.c b/arch/arm/mach-netx/nxeb500hmi.c new file mode 100644 index 000000000..53e10a984 --- /dev/null +++ b/arch/arm/mach-netx/nxeb500hmi.c @@ -0,0 +1,187 @@ +/* + * arch/arm/mach-netx/nxeb500hmi.c + * + * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/dma-mapping.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/mtd/plat-ram.h> +#include <linux/platform_device.h> +#include <linux/amba/bus.h> +#include <linux/amba/clcd.h> + +#include <asm/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/arch/netx-regs.h> +#include <asm/arch/eth.h> + +#include "generic.h" +#include "fb.h" + +static struct clcd_panel qvga = { + .mode = { + .name = "QVGA", + .refresh = 60, + .xres = 240, + .yres = 320, + .pixclock = 187617, + .left_margin = 6, + .right_margin = 26, + .upper_margin = 0, + .lower_margin = 6, + .hsync_len = 6, + .vsync_len = 1, + .sync = 0, + .vmode = FB_VMODE_NONINTERLACED, + }, + .width = -1, + .height = -1, + .tim2 = 16, + .cntl = CNTL_LCDTFT | CNTL_BGR, + .bpp = 16, + .grayscale = 0, +}; + +static inline int nxeb500hmi_check(struct clcd_fb *fb, struct fb_var_screeninfo *var) +{ + var->green.length = 5; + var->green.msb_right = 0; + + return clcdfb_check(fb, var); +} + +static int nxeb500hmi_clcd_setup(struct clcd_fb *fb) +{ + unsigned int val; + + fb->fb.var.green.length = 5; + fb->fb.var.green.msb_right = 0; + + /* enable asic control */ + val = readl(NETX_SYSTEM_IOC_ACCESS_KEY); + writel(val, NETX_SYSTEM_IOC_ACCESS_KEY); + + writel(3, NETX_SYSTEM_IOC_CR); + + /* GPIO 14 is used for display enable on newer boards */ + writel(9, NETX_GPIO_CFG(14)); + + val = readl(NETX_PIO_OUTPIO); + writel(val | 1, NETX_PIO_OUTPIO); + + val = readl(NETX_PIO_OEPIO); + writel(val | 1, NETX_PIO_OEPIO); + return netx_clcd_setup(fb); +} + +static struct clcd_board clcd_data = { + .name = "netX", + .check = nxeb500hmi_check, + .decode = clcdfb_decode, + .enable = netx_clcd_enable, + .setup = nxeb500hmi_clcd_setup, + .mmap = netx_clcd_mmap, + .remove = netx_clcd_remove, +}; + +static struct netxeth_platform_data eth0_platform_data = { + .xcno = 0, +}; + +static struct platform_device netx_eth0_device = { + .name = "netx-eth", + .id = 0, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð0_platform_data, + } +}; + +static struct netxeth_platform_data eth1_platform_data = { + .xcno = 1, +}; + +static struct platform_device netx_eth1_device = { + .name = "netx-eth", + .id = 1, + .num_resources = 0, + .resource = NULL, + .dev = { + .platform_data = ð1_platform_data, + } +}; + +static struct resource netx_cf_resources[] = { + [0] = { + .start = 0x20000000, + .end = 0x25ffffff, + .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT, + }, +}; + +static struct platform_device netx_cf_device = { + .name = "netx-cf", + .id = 0, + .resource = netx_cf_resources, + .num_resources = ARRAY_SIZE(netx_cf_resources), +}; + +static struct resource netx_uart0_resources[] = { + [0] = { + .start = 0x00100A00, + .end = 0x00100A3F, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = (NETX_IRQ_UART0), + .end = (NETX_IRQ_UART0), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device netx_uart0_device = { + .name = "netx-uart", + .id = 0, + .num_resources = ARRAY_SIZE(netx_uart0_resources), + .resource = netx_uart0_resources, +}; + +static struct platform_device *devices[] __initdata = { + &netx_eth0_device, + &netx_eth1_device, + &netx_cf_device, + &netx_uart0_device, +}; + +static void __init nxeb500hmi_init(void) +{ + netx_fb_init(&clcd_data, &qvga); + platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +MACHINE_START(NXEB500HMI, "Hilscher nxeb500hmi") + .phys_io = 0x00100000, + .io_pg_offst = (io_p2v(0x00100000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = netx_map_io, + .init_irq = netx_init_irq, + .timer = &netx_timer, + .init_machine = nxeb500hmi_init, +MACHINE_END diff --git a/arch/arm/mach-netx/pfifo.c b/arch/arm/mach-netx/pfifo.c new file mode 100644 index 000000000..44dea61a9 --- /dev/null +++ b/arch/arm/mach-netx/pfifo.c @@ -0,0 +1,68 @@ +/* + * arch/arm/mach-netx/pfifo.c + * + * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/mutex.h> + +#include <asm/io.h> +#include <asm/hardware.h> +#include <asm/arch/netx-regs.h> +#include <asm/arch/pfifo.h> + +static DEFINE_MUTEX(pfifo_lock); + +static unsigned int pfifo_used = 0; + +int pfifo_request(unsigned int pfifo_mask) +{ + int err = 0; + unsigned int val; + + mutex_lock(&pfifo_lock); + + if (pfifo_mask & pfifo_used) { + err = -EBUSY; + goto out; + } + + pfifo_used |= pfifo_mask; + + val = readl(NETX_PFIFO_RESET); + writel(val | pfifo_mask, NETX_PFIFO_RESET); + writel(val, NETX_PFIFO_RESET); + +out: + mutex_unlock(&pfifo_lock); + return err; +} + +void pfifo_free(unsigned int pfifo_mask) +{ + mutex_lock(&pfifo_lock); + pfifo_used &= ~pfifo_mask; + mutex_unlock(&pfifo_lock); +} + +EXPORT_SYMBOL(pfifo_push); +EXPORT_SYMBOL(pfifo_pop); +EXPORT_SYMBOL(pfifo_fill_level); +EXPORT_SYMBOL(pfifo_empty); +EXPORT_SYMBOL(pfifo_request); +EXPORT_SYMBOL(pfifo_free); diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c new file mode 100644 index 000000000..6d72c81b7 --- /dev/null +++ b/arch/arm/mach-netx/time.c @@ -0,0 +1,88 @@ +/* + * arch/arm/mach-netx/time.c + * + * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/init.h> +#include <linux/interrupt.h> + +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/mach/time.h> +#include <asm/arch/netx-regs.h> + +/* + * Returns number of us since last clock interrupt. Note that interrupts + * will have been disabled by do_gettimeoffset() + */ +static unsigned long netx_gettimeoffset(void) +{ + return readl(NETX_GPIO_COUNTER_CURRENT(0)) / 100; +} + +/* + * IRQ handler for the timer + */ +static irqreturn_t +netx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + write_seqlock(&xtime_lock); + + timer_tick(regs); + write_sequnlock(&xtime_lock); + + /* acknowledge interrupt */ + writel(COUNTER_BIT(0), NETX_GPIO_IRQ); + + return IRQ_HANDLED; +} + + +static struct irqaction netx_timer_irq = { + .name = "NetX Timer Tick", + .flags = IRQF_DISABLED | IRQF_TIMER, + .handler = netx_timer_interrupt, +}; + +/* + * Set up timer interrupt + */ +static void __init netx_timer_init(void) +{ + /* disable timer initially */ + writel(0, NETX_GPIO_COUNTER_CTRL(0)); + + /* Reset the timer value to zero */ + writel(0, NETX_GPIO_COUNTER_CURRENT(0)); + + writel(LATCH, NETX_GPIO_COUNTER_MAX(0)); + + /* acknowledge interrupt */ + writel(COUNTER_BIT(0), NETX_GPIO_IRQ); + + /* Enable the interrupt in the specific timer register and start timer */ + writel(COUNTER_BIT(0), NETX_GPIO_IRQ_ENABLE); + writel(NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN, + NETX_GPIO_COUNTER_CTRL(0)); + + setup_irq(NETX_IRQ_TIMER0, &netx_timer_irq); +} + +struct sys_timer netx_timer = { + .init = netx_timer_init, + .offset = netx_gettimeoffset, +}; diff --git a/arch/arm/mach-netx/xc.c b/arch/arm/mach-netx/xc.c new file mode 100644 index 000000000..172a058dd --- /dev/null +++ b/arch/arm/mach-netx/xc.c @@ -0,0 +1,255 @@ +/* + * arch/arm/mach-netx/xc.c + * + * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/init.h> +#include <linux/device.h> +#include <linux/firmware.h> +#include <linux/mutex.h> + +#include <asm/io.h> +#include <asm/hardware.h> +#include <asm/arch/netx-regs.h> + +#include <asm/arch/xc.h> + +static DEFINE_MUTEX(xc_lock); + +static int xc_in_use = 0; + +struct fw_desc { + unsigned int ofs; + unsigned int size; + unsigned int patch_ofs; + unsigned int patch_entries; +}; + +struct fw_header { + unsigned int magic; + unsigned int type; + unsigned int version; + unsigned int reserved[5]; + struct fw_desc fw_desc[3]; +} __attribute__ ((packed)); + +int xc_stop(struct xc *x) +{ + writel(RPU_HOLD_PC, x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS); + writel(TPU_HOLD_PC, x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS); + writel(XPU_HOLD_PC, x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS); + return 0; +} + +int xc_start(struct xc *x) +{ + writel(0, x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS); + writel(0, x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS); + writel(0, x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS); + return 0; +} + +int xc_running(struct xc *x) +{ + return (readl(x->xmac_base + NETX_XMAC_RPU_HOLD_PC_OFS) & RPU_HOLD_PC) + || (readl(x->xmac_base + NETX_XMAC_TPU_HOLD_PC_OFS) & TPU_HOLD_PC) + || (readl(x->xpec_base + NETX_XPEC_XPU_HOLD_PC_OFS) & XPU_HOLD_PC) ? + 0 : 1; +} + +int xc_reset(struct xc *x) +{ + writel(0, x->xpec_base + NETX_XPEC_PC_OFS); + return 0; +} + +static int xc_check_ptr(struct xc *x, unsigned long adr, unsigned int size) +{ + if (adr >= NETX_PA_XMAC(x->no) && + adr + size < NETX_PA_XMAC(x->no) + XMAC_MEM_SIZE) + return 0; + + if (adr >= NETX_PA_XPEC(x->no) && + adr + size < NETX_PA_XPEC(x->no) + XPEC_MEM_SIZE) + return 0; + + dev_err(x->dev, "Illegal pointer in firmware found. aborting\n"); + + return -1; +} + +static int xc_patch(struct xc *x, void *patch, int count) +{ + unsigned int val, adr; + unsigned int *data = patch; + + int i; + for (i = 0; i < count; i++) { + adr = *data++; + val = *data++; + if (xc_check_ptr(x, adr, 4) < 0) + return -EINVAL; + + writel(val, (void __iomem *)io_p2v(adr)); + } + return 0; +} + +int xc_request_firmware(struct xc *x) +{ + int ret; + char name[16]; + const struct firmware *fw; + struct fw_header *head; + unsigned int size; + int i; + void *src; + unsigned long dst; + + sprintf(name, "xc%d.bin", x->no); + + ret = request_firmware(&fw, name, x->dev); + + if (ret < 0) { + dev_err(x->dev, "request_firmware failed\n"); + return ret; + } + + head = (struct fw_header *)fw->data; + if (head->magic != 0x4e657458) { + if (head->magic == 0x5874654e) { + dev_err(x->dev, + "firmware magic is 'XteN'. Endianess problems?\n"); + ret = -ENODEV; + goto exit_release_firmware; + } + dev_err(x->dev, "unrecognized firmware magic 0x%08x\n", + head->magic); + ret = -ENODEV; + goto exit_release_firmware; + } + + x->type = head->type; + x->version = head->version; + + ret = -EINVAL; + + for (i = 0; i < 3; i++) { + src = fw->data + head->fw_desc[i].ofs; + dst = *(unsigned int *)src; + src += sizeof (unsigned int); + size = head->fw_desc[i].size - sizeof (unsigned int); + + if (xc_check_ptr(x, dst, size)) + goto exit_release_firmware; + + memcpy((void *)io_p2v(dst), src, size); + + src = fw->data + head->fw_desc[i].patch_ofs; + size = head->fw_desc[i].patch_entries; + ret = xc_patch(x, src, size); + if (ret < 0) + goto exit_release_firmware; + } + + ret = 0; + + exit_release_firmware: + release_firmware(fw); + + return ret; +} + +struct xc *request_xc(int xcno, struct device *dev) +{ + struct xc *x = NULL; + + mutex_lock(&xc_lock); + + if (xcno > 3) + goto exit; + if (xc_in_use & (1 << xcno)) + goto exit; + + x = kmalloc(sizeof (struct xc), GFP_KERNEL); + if (!x) + goto exit; + + if (!request_mem_region + (NETX_PA_XPEC(xcno), XPEC_MEM_SIZE, dev->kobj.name)) + goto exit_free; + + if (!request_mem_region + (NETX_PA_XMAC(xcno), XMAC_MEM_SIZE, dev->kobj.name)) + goto exit_release_1; + + if (!request_mem_region + (SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE, dev->kobj.name)) + goto exit_release_2; + + x->xpec_base = (void * __iomem)io_p2v(NETX_PA_XPEC(xcno)); + x->xmac_base = (void * __iomem)io_p2v(NETX_PA_XMAC(xcno)); + x->sram_base = ioremap(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE); + if (!x->sram_base) + goto exit_release_3; + + x->irq = NETX_IRQ_XPEC(xcno); + + x->no = xcno; + x->dev = dev; + + xc_in_use |= (1 << xcno); + + goto exit; + + exit_release_3: + release_mem_region(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE); + exit_release_2: + release_mem_region(NETX_PA_XMAC(xcno), XMAC_MEM_SIZE); + exit_release_1: + release_mem_region(NETX_PA_XPEC(xcno), XPEC_MEM_SIZE); + exit_free: + kfree(x); + x = NULL; + exit: + mutex_unlock(&xc_lock); + return x; +} + +void free_xc(struct xc *x) +{ + int xcno = x->no; + + mutex_lock(&xc_lock); + + iounmap(x->sram_base); + release_mem_region(SRAM_INTERNAL_PHYS(xcno), SRAM_MEM_SIZE); + release_mem_region(NETX_PA_XMAC(xcno), XMAC_MEM_SIZE); + release_mem_region(NETX_PA_XPEC(xcno), XPEC_MEM_SIZE); + xc_in_use &= ~(1 << x->no); + kfree(x); + + mutex_unlock(&xc_lock); +} + +EXPORT_SYMBOL(free_xc); +EXPORT_SYMBOL(request_xc); +EXPORT_SYMBOL(xc_request_firmware); +EXPORT_SYMBOL(xc_reset); +EXPORT_SYMBOL(xc_running); +EXPORT_SYMBOL(xc_start); +EXPORT_SYMBOL(xc_stop); diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c new file mode 100644 index 000000000..c753a3c5a --- /dev/null +++ b/arch/arm/mach-omap1/board-fsample.c @@ -0,0 +1,319 @@ +/* + * linux/arch/arm/mach-omap1/board-fsample.c + * + * Modified from board-perseus2.c + * + * Original OMAP730 support by Jean Pihet <j-pihet@ti.com> + * Updated for 2.6 by Kevin Hilman <kjh@hilman.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/partitions.h> +#include <linux/input.h> + +#include <asm/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/flash.h> +#include <asm/mach/map.h> + +#include <asm/arch/tc.h> +#include <asm/arch/gpio.h> +#include <asm/arch/mux.h> +#include <asm/arch/fpga.h> +#include <asm/arch/keypad.h> +#include <asm/arch/common.h> +#include <asm/arch/board.h> +#include <asm/arch/board-fsample.h> + +static int fsample_keymap[] = { + KEY(0,0,KEY_UP), + KEY(0,1,KEY_RIGHT), + KEY(0,2,KEY_LEFT), + KEY(0,3,KEY_DOWN), + KEY(0,4,KEY_CENTER), + KEY(0,5,KEY_0_5), + KEY(1,0,KEY_SOFT2), + KEY(1,1,KEY_SEND), + KEY(1,2,KEY_END), + KEY(1,3,KEY_VOLUMEDOWN), + KEY(1,4,KEY_VOLUMEUP), + KEY(1,5,KEY_RECORD), + KEY(2,0,KEY_SOFT1), + KEY(2,1,KEY_3), + KEY(2,2,KEY_6), + KEY(2,3,KEY_9), + KEY(2,4,KEY_SHARP), + KEY(2,5,KEY_2_5), + KEY(3,0,KEY_BACK), + KEY(3,1,KEY_2), + KEY(3,2,KEY_5), + KEY(3,3,KEY_8), + KEY(3,4,KEY_0), + KEY(3,5,KEY_HEADSETHOOK), + KEY(4,0,KEY_HOME), + KEY(4,1,KEY_1), + KEY(4,2,KEY_4), + KEY(4,3,KEY_7), + KEY(4,4,KEY_STAR), + KEY(4,5,KEY_POWER), + 0 +}; + +static struct resource smc91x_resources[] = { + [0] = { + .start = H2P2_DBG_FPGA_ETHR_START, /* Physical */ + .end = H2P2_DBG_FPGA_ETHR_START + 0xf, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = INT_730_MPU_EXT_NIRQ, + .end = 0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mtd_partition nor_partitions[] = { + /* bootloader (U-Boot, etc) in first sector */ + { + .name = "bootloader", + .offset = 0, + .size = SZ_128K, + .mask_flags = MTD_WRITEABLE, /* force read-only */ + }, + /* bootloader params in the next sector */ + { + .name = "params", + .offset = MTDPART_OFS_APPEND, + .size = SZ_128K, + .mask_flags = 0, + }, + /* kernel */ + { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = SZ_2M, + .mask_flags = 0 + }, + /* rest of flash is a file system */ + { + .name = "rootfs", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + .mask_flags = 0 + }, +}; + +static struct flash_platform_data nor_data = { + .map_name = "cfi_probe", + .width = 2, + .parts = nor_partitions, + .nr_parts = ARRAY_SIZE(nor_partitions), +}; + +static struct resource nor_resource = { + .start = OMAP_CS0_PHYS, + .end = OMAP_CS0_PHYS + SZ_32M - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device nor_device = { + .name = "omapflash", + .id = 0, + .dev = { + .platform_data = &nor_data, + }, + .num_resources = 1, + .resource = &nor_resource, +}; + +static struct nand_platform_data nand_data = { + .options = NAND_SAMSUNG_LP_OPTIONS, +}; + +static struct resource nand_resource = { + .start = OMAP_CS3_PHYS, + .end = OMAP_CS3_PHYS + SZ_4K - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device nand_device = { + .name = "omapnand", + .id = 0, + .dev = { + .platform_data = &nand_data, + }, + .num_resources = 1, + .resource = &nand_resource, +}; + +static struct platform_device smc91x_device = { + .name = "smc91x", + .id = 0, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, +}; + +static struct resource kp_resources[] = { + [0] = { + .start = INT_730_MPUIO_KEYPAD, + .end = INT_730_MPUIO_KEYPAD, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct omap_kp_platform_data kp_data = { + .rows = 8, + .cols = 8, + .keymap = fsample_keymap, +}; + +static struct platform_device kp_device = { + .name = "omap-keypad", + .id = -1, + .dev = { + .platform_data = &kp_data, + }, + .num_resources = ARRAY_SIZE(kp_resources), + .resource = kp_resources, +}; + +static struct platform_device lcd_device = { + .name = "lcd_p2", + .id = -1, +}; + +static struct platform_device *devices[] __initdata = { + &nor_device, + &nand_device, + &smc91x_device, + &kp_device, + &lcd_device, +}; + +#define P2_NAND_RB_GPIO_PIN 62 + +static int nand_dev_ready(struct nand_platform_data *data) +{ + return omap_get_gpio_datain(P2_NAND_RB_GPIO_PIN); +} + +static struct omap_uart_config fsample_uart_config __initdata = { + .enabled_uarts = ((1 << 0) | (1 << 1)), +}; + +static struct omap_lcd_config fsample_lcd_config __initdata = { + .ctrl_name = "internal", +}; + +static struct omap_board_config_kernel fsample_config[] = { + { OMAP_TAG_UART, &fsample_uart_config }, + { OMAP_TAG_LCD, &fsample_lcd_config }, +}; + +static void __init omap_fsample_init(void) +{ + if (!(omap_request_gpio(P2_NAND_RB_GPIO_PIN))) + nand_data.dev_ready = nand_dev_ready; + + omap_cfg_reg(L3_1610_FLASH_CS2B_OE); + omap_cfg_reg(M8_1610_FLASH_CS2B_WE); + + platform_add_devices(devices, ARRAY_SIZE(devices)); + + omap_board_config = fsample_config; + omap_board_config_size = ARRAY_SIZE(fsample_config); + omap_serial_init(); +} + +static void __init fsample_init_smc91x(void) +{ + fpga_write(1, H2P2_DBG_FPGA_LAN_RESET); + mdelay(50); + fpga_write(fpga_read(H2P2_DBG_FPGA_LAN_RESET) & ~1, + H2P2_DBG_FPGA_LAN_RESET); + mdelay(50); +} + +void omap_fsample_init_irq(void) +{ + omap1_init_common_hw(); + omap_init_irq(); + omap_gpio_init(); + fsample_init_smc91x(); +} + +/* Only FPGA needs to be mapped here. All others are done with ioremap */ +static struct map_desc omap_fsample_io_desc[] __initdata = { + { + .virtual = H2P2_DBG_FPGA_BASE, + .pfn = __phys_to_pfn(H2P2_DBG_FPGA_START), + .length = H2P2_DBG_FPGA_SIZE, + .type = MT_DEVICE + }, + { + .virtual = FSAMPLE_CPLD_BASE, + .pfn = __phys_to_pfn(FSAMPLE_CPLD_START), + .length = FSAMPLE_CPLD_SIZE, + .type = MT_DEVICE + } +}; + +static void __init omap_fsample_map_io(void) +{ + omap1_map_common_io(); + iotable_init(omap_fsample_io_desc, + ARRAY_SIZE(omap_fsample_io_desc)); + + /* Early, board-dependent init */ + + /* + * Hold GSM Reset until needed + */ + omap_writew(omap_readw(OMAP730_DSP_M_CTL) & ~1, OMAP730_DSP_M_CTL); + + /* + * UARTs -> done automagically by 8250 driver + */ + + /* + * CSx timings, GPIO Mux ... setup + */ + + /* Flash: CS0 timings setup */ + omap_writel(0x0000fff3, OMAP730_FLASH_CFG_0); + omap_writel(0x00000088, OMAP730_FLASH_ACFG_0); + + /* + * Ethernet support through the debug board + * CS1 timings setup + */ + omap_writel(0x0000fff3, OMAP730_FLASH_CFG_1); + omap_writel(0x00000000, OMAP730_FLASH_ACFG_1); + + /* + * Configure MPU_EXT_NIRQ IO in IO_CONF9 register, + * It is used as the Ethernet controller interrupt + */ + omap_writel(omap_readl(OMAP730_IO_CONF_9) & 0x1FFFFFFF, OMAP730_IO_CONF_9); +} + +MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample") +/* Maintainer: Brian Swetland <swetland@google.com> */ + .phys_io = 0xfff00000, + .io_pg_offst = ((0xfef00000) >> 18) & 0xfffc, + .boot_params = 0x10000100, + .map_io = omap_fsample_map_io, + .init_irq = omap_fsample_init_irq, + .init_machine = omap_fsample_init, + .timer = &omap_timer, +MACHINE_END diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c new file mode 100644 index 000000000..c7a48f921 --- /dev/null +++ b/arch/arm/mach-omap2/gpmc.c @@ -0,0 +1,209 @@ +/* + * GPMC support functions + * + * Copyright (C) 2005-2006 Nokia Corporation + * + * Author: Juha Yrjola + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/clk.h> + +#include <asm/io.h> +#include <asm/arch/gpmc.h> + +#undef DEBUG + +#define GPMC_BASE 0x6800a000 +#define GPMC_REVISION 0x00 +#define GPMC_SYSCONFIG 0x10 +#define GPMC_SYSSTATUS 0x14 +#define GPMC_IRQSTATUS 0x18 +#define GPMC_IRQENABLE 0x1c +#define GPMC_TIMEOUT_CONTROL 0x40 +#define GPMC_ERR_ADDRESS 0x44 +#define GPMC_ERR_TYPE 0x48 +#define GPMC_CONFIG 0x50 +#define GPMC_STATUS 0x54 +#define GPMC_PREFETCH_CONFIG1 0x1e0 +#define GPMC_PREFETCH_CONFIG2 0x1e4 +#define GPMC_PREFETCH_CONTROL 0x1e8 +#define GPMC_PREFETCH_STATUS 0x1f0 +#define GPMC_ECC_CONFIG 0x1f4 +#define GPMC_ECC_CONTROL 0x1f8 +#define GPMC_ECC_SIZE_CONFIG 0x1fc + +#define GPMC_CS0 0x60 +#define GPMC_CS_SIZE 0x30 + +static void __iomem *gpmc_base = + (void __iomem *) IO_ADDRESS(GPMC_BASE); +static void __iomem *gpmc_cs_base = + (void __iomem *) IO_ADDRESS(GPMC_BASE) + GPMC_CS0; + +static struct clk *gpmc_l3_clk; + +static void gpmc_write_reg(int idx, u32 val) +{ + __raw_writel(val, gpmc_base + idx); +} + +static u32 gpmc_read_reg(int idx) +{ + return __raw_readl(gpmc_base + idx); +} + +void gpmc_cs_write_reg(int cs, int idx, u32 val) +{ + void __iomem *reg_addr; + + reg_addr = gpmc_cs_base + (cs * GPMC_CS_SIZE) + idx; + __raw_writel(val, reg_addr); +} + +u32 gpmc_cs_read_reg(int cs, int idx) +{ + return __raw_readl(gpmc_cs_base + (cs * GPMC_CS_SIZE) + idx); +} + +/* TODO: Add support for gpmc_fck to clock framework and use it */ +static unsigned long gpmc_get_fclk_period(void) +{ + /* In picoseconds */ + return 1000000000 / ((clk_get_rate(gpmc_l3_clk)) / 1000); +} + +unsigned int gpmc_ns_to_ticks(unsigned int time_ns) +{ + unsigned long tick_ps; + + /* Calculate in picosecs to yield more exact results */ + tick_ps = gpmc_get_fclk_period(); + + return (time_ns * 1000 + tick_ps - 1) / tick_ps; +} + +#ifdef DEBUG +static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, + int time, const char *name) +#else +static int set_gpmc_timing_reg(int cs, int reg, int st_bit, int end_bit, + int time) +#endif +{ + u32 l; + int ticks, mask, nr_bits; + + if (time == 0) + ticks = 0; + else + ticks = gpmc_ns_to_ticks(time); + nr_bits = end_bit - st_bit + 1; + if (ticks >= 1 << nr_bits) + return -1; + + mask = (1 << nr_bits) - 1; + l = gpmc_cs_read_reg(cs, reg); +#ifdef DEBUG + printk(KERN_INFO "GPMC CS%d: %-10s: %d ticks, %3lu ns (was %i ticks)\n", + cs, name, ticks, gpmc_get_fclk_period() * ticks / 1000, + (l >> st_bit) & mask); +#endif + l &= ~(mask << st_bit); + l |= ticks << st_bit; + gpmc_cs_write_reg(cs, reg, l); + + return 0; +} + +#ifdef DEBUG +#define GPMC_SET_ONE(reg, st, end, field) \ + if (set_gpmc_timing_reg(cs, (reg), (st), (end), \ + t->field, #field) < 0) \ + return -1 +#else +#define GPMC_SET_ONE(reg, st, end, field) \ + if (set_gpmc_timing_reg(cs, (reg), (st), (end), t->field) < 0) \ + return -1 +#endif + +int gpmc_cs_calc_divider(int cs, unsigned int sync_clk) +{ + int div; + u32 l; + + l = sync_clk * 1000 + (gpmc_get_fclk_period() - 1); + div = l / gpmc_get_fclk_period(); + if (div > 4) + return -1; + if (div < 0) + div = 1; + + return div; +} + +int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t) +{ + int div; + u32 l; + + div = gpmc_cs_calc_divider(cs, t->sync_clk); + if (div < 0) + return -1; + + GPMC_SET_ONE(GPMC_CS_CONFIG2, 0, 3, cs_on); + GPMC_SET_ONE(GPMC_CS_CONFIG2, 8, 12, cs_rd_off); + GPMC_SET_ONE(GPMC_CS_CONFIG2, 16, 20, cs_wr_off); + + GPMC_SET_ONE(GPMC_CS_CONFIG3, 0, 3, adv_on); + GPMC_SET_ONE(GPMC_CS_CONFIG3, 8, 12, adv_rd_off); + GPMC_SET_ONE(GPMC_CS_CONFIG3, 16, 20, adv_wr_off); + + GPMC_SET_ONE(GPMC_CS_CONFIG4, 0, 3, oe_on); + GPMC_SET_ONE(GPMC_CS_CONFIG4, 8, 12, oe_off); + GPMC_SET_ONE(GPMC_CS_CONFIG4, 16, 19, we_on); + GPMC_SET_ONE(GPMC_CS_CONFIG4, 24, 28, we_off); + + GPMC_SET_ONE(GPMC_CS_CONFIG5, 0, 4, rd_cycle); + GPMC_SET_ONE(GPMC_CS_CONFIG5, 8, 12, wr_cycle); + GPMC_SET_ONE(GPMC_CS_CONFIG5, 16, 20, access); + + GPMC_SET_ONE(GPMC_CS_CONFIG5, 24, 27, page_burst_access); + +#ifdef DEBUG + printk(KERN_INFO "GPMC CS%d CLK period is %lu (div %d)\n", + cs, gpmc_get_fclk_period(), div); +#endif + + l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + l &= ~0x03; + l |= (div - 1); + + return 0; +} + +unsigned long gpmc_cs_get_base_addr(int cs) +{ + return (gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7) & 0x1f) << 24; +} + +void __init gpmc_init(void) +{ + u32 l; + + gpmc_l3_clk = clk_get(NULL, "core_l3_ck"); + BUG_ON(IS_ERR(gpmc_l3_clk)); + + l = gpmc_read_reg(GPMC_REVISION); + printk(KERN_INFO "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f); + /* Set smart idle mode and automatic L3 clock gating */ + l = gpmc_read_reg(GPMC_SYSCONFIG); + l &= 0x03 << 3; + l |= (0x02 << 3) | (1 << 0); + gpmc_write_reg(GPMC_SYSCONFIG, l); +} diff --git a/arch/arm/mach-omap2/pm-domain.c b/arch/arm/mach-omap2/pm-domain.c new file mode 100644 index 000000000..2494091a0 --- /dev/null +++ b/arch/arm/mach-omap2/pm-domain.c @@ -0,0 +1,299 @@ +/* + * linux/arch/arm/mach-omap2/pm-domain.c + * + * Power domain functions for OMAP2 + * + * Copyright (C) 2006 Nokia Corporation + * Tony Lindgren <tony@atomide.com> + * + * Some code based on earlier OMAP2 sample PM code + * Copyright (C) 2005 Texas Instruments, Inc. + * Richard Woodruff <r-woodruff2@ti.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/clk.h> + +#include <asm/io.h> + +#include "prcm-regs.h" + +/* Power domain offsets */ +#define PM_MPU_OFFSET 0x100 +#define PM_CORE_OFFSET 0x200 +#define PM_GFX_OFFSET 0x300 +#define PM_WKUP_OFFSET 0x400 /* Autoidle only */ +#define PM_PLL_OFFSET 0x500 /* Autoidle only */ +#define PM_DSP_OFFSET 0x800 +#define PM_MDM_OFFSET 0xc00 + +/* Power domain wake-up dependency control register */ +#define PM_WKDEP_OFFSET 0xc8 +#define EN_MDM (1 << 5) +#define EN_WKUP (1 << 4) +#define EN_GFX (1 << 3) +#define EN_DSP (1 << 2) +#define EN_MPU (1 << 1) +#define EN_CORE (1 << 0) + +/* Core power domain state transition control register */ +#define PM_PWSTCTRL_OFFSET 0xe0 +#define FORCESTATE (1 << 18) /* Only for DSP & GFX */ +#define MEM4RETSTATE (1 << 6) +#define MEM3RETSTATE (1 << 5) +#define MEM2RETSTATE (1 << 4) +#define MEM1RETSTATE (1 << 3) +#define LOGICRETSTATE (1 << 2) /* Logic is retained */ +#define POWERSTATE_OFF 0x3 +#define POWERSTATE_RETENTION 0x1 +#define POWERSTATE_ON 0x0 + +/* Power domain state register */ +#define PM_PWSTST_OFFSET 0xe4 + +/* Hardware supervised state transition control register */ +#define CM_CLKSTCTRL_OFFSET 0x48 +#define AUTOSTAT_MPU (1 << 0) /* MPU */ +#define AUTOSTAT_DSS (1 << 2) /* Core */ +#define AUTOSTAT_L4 (1 << 1) /* Core */ +#define AUTOSTAT_L3 (1 << 0) /* Core */ +#define AUTOSTAT_GFX (1 << 0) /* GFX */ +#define AUTOSTAT_IVA (1 << 8) /* 2420 IVA in DSP domain */ +#define AUTOSTAT_DSP (1 << 0) /* DSP */ +#define AUTOSTAT_MDM (1 << 0) /* MDM */ + +/* Automatic control of interface clock idling */ +#define CM_AUTOIDLE1_OFFSET 0x30 +#define CM_AUTOIDLE2_OFFSET 0x34 /* Core only */ +#define CM_AUTOIDLE3_OFFSET 0x38 /* Core only */ +#define CM_AUTOIDLE4_OFFSET 0x3c /* Core only */ +#define AUTO_54M(x) (((x) & 0x3) << 6) +#define AUTO_96M(x) (((x) & 0x3) << 2) +#define AUTO_DPLL(x) (((x) & 0x3) << 0) +#define AUTO_STOPPED 0x3 +#define AUTO_BYPASS_FAST 0x2 /* DPLL only */ +#define AUTO_BYPASS_LOW_POWER 0x1 /* DPLL only */ +#define AUTO_DISABLED 0x0 + +/* Voltage control PRCM_VOLTCTRL bits */ +#define AUTO_EXTVOLT (1 << 15) +#define FORCE_EXTVOLT (1 << 14) +#define SETOFF_LEVEL(x) (((x) & 0x3) << 12) +#define MEMRETCTRL (1 << 8) +#define SETRET_LEVEL(x) (((x) & 0x3) << 6) +#define VOLT_LEVEL(x) (((x) & 0x3) << 0) + +#define OMAP24XX_PRCM_VBASE IO_ADDRESS(OMAP24XX_PRCM_BASE) +#define prcm_readl(r) __raw_readl(OMAP24XX_PRCM_VBASE + (r)) +#define prcm_writel(v, r) __raw_writel((v), OMAP24XX_PRCM_VBASE + (r)) + +static u32 pmdomain_get_wakeup_dependencies(int domain_offset) +{ + return prcm_readl(domain_offset + PM_WKDEP_OFFSET); +} + +static void pmdomain_set_wakeup_dependencies(u32 state, int domain_offset) +{ + prcm_writel(state, domain_offset + PM_WKDEP_OFFSET); +} + +static u32 pmdomain_get_powerstate(int domain_offset) +{ + return prcm_readl(domain_offset + PM_PWSTCTRL_OFFSET); +} + +static void pmdomain_set_powerstate(u32 state, int domain_offset) +{ + prcm_writel(state, domain_offset + PM_PWSTCTRL_OFFSET); +} + +static u32 pmdomain_get_clock_autocontrol(int domain_offset) +{ + return prcm_readl(domain_offset + CM_CLKSTCTRL_OFFSET); +} + +static void pmdomain_set_clock_autocontrol(u32 state, int domain_offset) +{ + prcm_writel(state, domain_offset + CM_CLKSTCTRL_OFFSET); +} + +static u32 pmdomain_get_clock_autoidle1(int domain_offset) +{ + return prcm_readl(domain_offset + CM_AUTOIDLE1_OFFSET); +} + +/* Core domain only */ +static u32 pmdomain_get_clock_autoidle2(int domain_offset) +{ + return prcm_readl(domain_offset + CM_AUTOIDLE2_OFFSET); +} + +/* Core domain only */ +static u32 pmdomain_get_clock_autoidle3(int domain_offset) +{ + return prcm_readl(domain_offset + CM_AUTOIDLE3_OFFSET); +} + +/* Core domain only */ +static u32 pmdomain_get_clock_autoidle4(int domain_offset) +{ + return prcm_readl(domain_offset + CM_AUTOIDLE4_OFFSET); +} + +static void pmdomain_set_clock_autoidle1(u32 state, int domain_offset) +{ + prcm_writel(state, CM_AUTOIDLE1_OFFSET + domain_offset); +} + +/* Core domain only */ +static void pmdomain_set_clock_autoidle2(u32 state, int domain_offset) +{ + prcm_writel(state, CM_AUTOIDLE2_OFFSET + domain_offset); +} + +/* Core domain only */ +static void pmdomain_set_clock_autoidle3(u32 state, int domain_offset) +{ + prcm_writel(state, CM_AUTOIDLE3_OFFSET + domain_offset); +} + +/* Core domain only */ +static void pmdomain_set_clock_autoidle4(u32 state, int domain_offset) +{ + prcm_writel(state, CM_AUTOIDLE4_OFFSET + domain_offset); +} + +/* + * Configures power management domains to idle clocks automatically. + */ +void pmdomain_set_autoidle(void) +{ + u32 val; + + /* Set PLL auto stop for 54M, 96M & DPLL */ + pmdomain_set_clock_autoidle1(AUTO_54M(AUTO_STOPPED) | + AUTO_96M(AUTO_STOPPED) | + AUTO_DPLL(AUTO_STOPPED), PM_PLL_OFFSET); + + /* External clock input control + * REVISIT: Should this be in clock framework? + */ + PRCM_CLKSRC_CTRL |= (0x3 << 3); + + /* Configure number of 32KHz clock cycles for sys_clk */ + PRCM_CLKSSETUP = 0x00ff; + + /* Configure automatic voltage transition */ + PRCM_VOLTSETUP = 0; + val = PRCM_VOLTCTRL; + val &= ~(SETOFF_LEVEL(0x3) | VOLT_LEVEL(0x3)); + val |= SETOFF_LEVEL(1) | VOLT_LEVEL(1) | AUTO_EXTVOLT; + PRCM_VOLTCTRL = val; + + /* Disable emulation tools functional clock */ + PRCM_CLKEMUL_CTRL = 0x0; + + /* Set core memory retention state */ + val = pmdomain_get_powerstate(PM_CORE_OFFSET); + if (cpu_is_omap2420()) { + val &= ~(0x7 << 3); + val |= (MEM3RETSTATE | MEM2RETSTATE | MEM1RETSTATE); + } else { + val &= ~(0xf << 3); + val |= (MEM4RETSTATE | MEM3RETSTATE | MEM2RETSTATE | + MEM1RETSTATE); + } + pmdomain_set_powerstate(val, PM_CORE_OFFSET); + + /* OCP interface smart idle. REVISIT: Enable autoidle bit0 ? */ + val = SMS_SYSCONFIG; + val &= ~(0x3 << 3); + val |= (0x2 << 3) | (1 << 0); + SMS_SYSCONFIG |= val; + + val = SDRC_SYSCONFIG; + val &= ~(0x3 << 3); + val |= (0x2 << 3); + SDRC_SYSCONFIG = val; + + /* Configure L3 interface for smart idle. + * REVISIT: Enable autoidle bit0 ? + */ + val = GPMC_SYSCONFIG; + val &= ~(0x3 << 3); + val |= (0x2 << 3) | (1 << 0); + GPMC_SYSCONFIG = val; + + pmdomain_set_powerstate(LOGICRETSTATE | POWERSTATE_RETENTION, + PM_MPU_OFFSET); + pmdomain_set_powerstate(POWERSTATE_RETENTION, PM_CORE_OFFSET); + if (!cpu_is_omap2420()) + pmdomain_set_powerstate(POWERSTATE_RETENTION, PM_MDM_OFFSET); + + /* Assume suspend function has saved the state for DSP and GFX */ + pmdomain_set_powerstate(FORCESTATE | POWERSTATE_OFF, PM_DSP_OFFSET); + pmdomain_set_powerstate(FORCESTATE | POWERSTATE_OFF, PM_GFX_OFFSET); + +#if 0 + /* REVISIT: Internal USB needs special handling */ + force_standby_usb(); + if (cpu_is_omap2430()) + force_hsmmc(); + sdram_self_refresh_on_idle_req(1); +#endif + + /* Enable clock auto control for all domains. + * Note that CORE domain includes also DSS, L4 & L3. + */ + pmdomain_set_clock_autocontrol(AUTOSTAT_MPU, PM_MPU_OFFSET); + pmdomain_set_clock_autocontrol(AUTOSTAT_GFX, PM_GFX_OFFSET); + pmdomain_set_clock_autocontrol(AUTOSTAT_DSS | AUTOSTAT_L4 | AUTOSTAT_L3, + PM_CORE_OFFSET); + if (cpu_is_omap2420()) + pmdomain_set_clock_autocontrol(AUTOSTAT_IVA | AUTOSTAT_DSP, + PM_DSP_OFFSET); + else { + pmdomain_set_clock_autocontrol(AUTOSTAT_DSP, PM_DSP_OFFSET); + pmdomain_set_clock_autocontrol(AUTOSTAT_MDM, PM_MDM_OFFSET); + } + + /* Enable clock autoidle for all domains */ + pmdomain_set_clock_autoidle1(0x2, PM_DSP_OFFSET); + if (cpu_is_omap2420()) { + pmdomain_set_clock_autoidle1(0xfffffff9, PM_CORE_OFFSET); + pmdomain_set_clock_autoidle2(0x7, PM_CORE_OFFSET); + pmdomain_set_clock_autoidle1(0x3f, PM_WKUP_OFFSET); + } else { + pmdomain_set_clock_autoidle1(0xeafffff1, PM_CORE_OFFSET); + pmdomain_set_clock_autoidle2(0xfff, PM_CORE_OFFSET); + pmdomain_set_clock_autoidle1(0x7f, PM_WKUP_OFFSET); + pmdomain_set_clock_autoidle1(0x3, PM_MDM_OFFSET); + } + pmdomain_set_clock_autoidle3(0x7, PM_CORE_OFFSET); + pmdomain_set_clock_autoidle4(0x1f, PM_CORE_OFFSET); +} + +/* + * Initializes power domains by removing wake-up dependencies and powering + * down DSP and GFX. Gets called from PM init. Note that DSP and IVA code + * must re-enable DSP and GFX when used. + */ +void __init pmdomain_init(void) +{ + /* Remove all domain wakeup dependencies */ + pmdomain_set_wakeup_dependencies(EN_WKUP | EN_CORE, PM_MPU_OFFSET); + pmdomain_set_wakeup_dependencies(0, PM_DSP_OFFSET); + pmdomain_set_wakeup_dependencies(0, PM_GFX_OFFSET); + pmdomain_set_wakeup_dependencies(EN_WKUP | EN_MPU, PM_CORE_OFFSET); + if (cpu_is_omap2430()) + pmdomain_set_wakeup_dependencies(0, PM_MDM_OFFSET); + + /* Power down DSP and GFX */ + pmdomain_set_powerstate(POWERSTATE_OFF | FORCESTATE, PM_DSP_OFFSET); + pmdomain_set_powerstate(POWERSTATE_OFF | FORCESTATE, PM_GFX_OFFSET); +} diff --git a/arch/arm/mach-pnx4008/Makefile b/arch/arm/mach-pnx4008/Makefile new file mode 100644 index 000000000..b457ca0a4 --- /dev/null +++ b/arch/arm/mach-pnx4008/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for the linux kernel. +# + +obj-y := core.o irq.o time.o clock.o gpio.o serial.o dma.o +obj-m := +obj-n := +obj- := + +# Power Management +obj-$(CONFIG_PM) += pm.o sleep.o + diff --git a/arch/arm/mach-pnx4008/Makefile.boot b/arch/arm/mach-pnx4008/Makefile.boot new file mode 100644 index 000000000..44c7117e2 --- /dev/null +++ b/arch/arm/mach-pnx4008/Makefile.boot @@ -0,0 +1,4 @@ + zreladdr-y := 0x80008000 +params_phys-y := 0x80000100 +initrd_phys-y := 0x80800000 + diff --git a/arch/arm/mach-pnx4008/clock.c b/arch/arm/mach-pnx4008/clock.c new file mode 100644 index 000000000..f582ed2ec --- /dev/null +++ b/arch/arm/mach-pnx4008/clock.c @@ -0,0 +1,983 @@ +/* + * arch/arm/mach-pnx4008/clock.c + * + * Clock control driver for PNX4008 + * + * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com> + * Generic clock management functions are partially based on: + * linux/arch/arm/mach-omap/clock.c + * + * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/delay.h> + +#include <asm/semaphore.h> +#include <asm/hardware.h> +#include <asm/io.h> + +#include <asm/arch/clock.h> +#include "clock.h" + +/*forward declaration*/ +static struct clk per_ck; +static struct clk hclk_ck; +static struct clk ck_1MHz; +static struct clk ck_13MHz; +static struct clk ck_pll1; +static int local_set_rate(struct clk *clk, u32 rate); + +static inline void clock_lock(void) +{ + local_irq_disable(); +} + +static inline void clock_unlock(void) +{ + local_irq_enable(); +} + +static void propagate_rate(struct clk *clk) +{ + struct clk *tmp_clk; + + tmp_clk = clk; + while (tmp_clk->propagate_next) { + tmp_clk = tmp_clk->propagate_next; + local_set_rate(tmp_clk, tmp_clk->user_rate); + } +} + +static inline void clk_reg_disable(struct clk *clk) +{ + if (clk->enable_reg) + __raw_writel(__raw_readl(clk->enable_reg) & + ~(1 << clk->enable_shift), clk->enable_reg); +} + +static inline void clk_reg_enable(struct clk *clk) +{ + if (clk->enable_reg) + __raw_writel(__raw_readl(clk->enable_reg) | + (1 << clk->enable_shift), clk->enable_reg); +} + +static inline void clk_reg_disable1(struct clk *clk) +{ + if (clk->enable_reg1) + __raw_writel(__raw_readl(clk->enable_reg1) & + ~(1 << clk->enable_shift1), clk->enable_reg1); +} + +static inline void clk_reg_enable1(struct clk *clk) +{ + if (clk->enable_reg1) + __raw_writel(__raw_readl(clk->enable_reg1) | + (1 << clk->enable_shift1), clk->enable_reg1); +} + +static int clk_wait_for_pll_lock(struct clk *clk) +{ + int i; + i = 0; + while (i++ < 0xFFF && !(__raw_readl(clk->scale_reg) & 1)) ; /*wait for PLL to lock */ + + if (!(__raw_readl(clk->scale_reg) & 1)) { + printk(KERN_ERR + "%s ERROR: failed to lock, scale reg data: %x\n", + clk->name, __raw_readl(clk->scale_reg)); + return -1; + } + return 0; +} + +static int switch_to_dirty_13mhz(struct clk *clk) +{ + int i; + int ret; + u32 tmp_reg; + + ret = 0; + + if (!clk->rate) + clk_reg_enable1(clk); + + tmp_reg = __raw_readl(clk->parent_switch_reg); + /*if 13Mhz clock selected, select 13'MHz (dirty) source from OSC */ + if (!(tmp_reg & 1)) { + tmp_reg |= (1 << 1); /* Trigger switch to 13'MHz (dirty) clock */ + __raw_writel(tmp_reg, clk->parent_switch_reg); + i = 0; + while (i++ < 0xFFF && !(__raw_readl(clk->parent_switch_reg) & 1)) ; /*wait for 13'MHz selection status */ + + if (!(__raw_readl(clk->parent_switch_reg) & 1)) { + printk(KERN_ERR + "%s ERROR: failed to select 13'MHz, parent sw reg data: %x\n", + clk->name, __raw_readl(clk->parent_switch_reg)); + ret = -1; + } + } + + if (!clk->rate) + clk_reg_disable1(clk); + + return ret; +} + +static int switch_to_clean_13mhz(struct clk *clk) +{ + int i; + int ret; + u32 tmp_reg; + + ret = 0; + + if (!clk->rate) + clk_reg_enable1(clk); + + tmp_reg = __raw_readl(clk->parent_switch_reg); + /*if 13'Mhz clock selected, select 13MHz (clean) source from OSC */ + if (tmp_reg & 1) { + tmp_reg &= ~(1 << 1); /* Trigger switch to 13MHz (clean) clock */ + __raw_writel(tmp_reg, clk->parent_switch_reg); + i = 0; + while (i++ < 0xFFF && (__raw_readl(clk->parent_switch_reg) & 1)) ; /*wait for 13MHz selection status */ + + if (__raw_readl(clk->parent_switch_reg) & 1) { + printk(KERN_ERR + "%s ERROR: failed to select 13MHz, parent sw reg data: %x\n", + clk->name, __raw_readl(clk->parent_switch_reg)); + ret = -1; + } + } + + if (!clk->rate) + clk_reg_disable1(clk); + + return ret; +} + +static int set_13MHz_parent(struct clk *clk, struct clk *parent) +{ + int ret = -EINVAL; + + if (parent == &ck_13MHz) + ret = switch_to_clean_13mhz(clk); + else if (parent == &ck_pll1) + ret = switch_to_dirty_13mhz(clk); + + return ret; +} + +#define PLL160_MIN_FCCO 156000 +#define PLL160_MAX_FCCO 320000 + +/* + * Calculate pll160 settings. + * Possible input: up to 320MHz with step of clk->parent->rate. + * In PNX4008 parent rate for pll160s may be either 1 or 13MHz. + * Ignored paths: "feedback" (bit 13 set), "div-by-N". + * Setting ARM PLL4 rate to 0 will put CPU into direct run mode. + * Setting PLL5 and PLL3 rate to 0 will disable USB and DSP clock input. + * Please refer to PNX4008 IC manual for details. + */ + +static int pll160_set_rate(struct clk *clk, u32 rate) +{ + u32 tmp_reg, tmp_m, tmp_2p, i; + u32 parent_rate; + int ret = -EINVAL; + + parent_rate = clk->parent->rate; + + if (!parent_rate) + goto out; + + /* set direct run for ARM or disable output for others */ + clk_reg_disable(clk); + + /* disable source input as well (ignored for ARM) */ + clk_reg_disable1(clk); + + tmp_reg = __raw_readl(clk->scale_reg); + tmp_reg &= ~0x1ffff; /*clear all settings, power down */ + __raw_writel(tmp_reg, clk->scale_reg); + + rate -= rate % parent_rate; /*round down the input */ + + if (rate > PLL160_MAX_FCCO) + rate = PLL160_MAX_FCCO; + + if (!rate) { + clk->rate = 0; + ret = 0; + goto out; + } + + clk_reg_enable1(clk); + tmp_reg = __raw_readl(clk->scale_reg); + + if (rate == parent_rate) { + /*enter direct bypass mode */ + tmp_reg |= ((1 << 14) | (1 << 15)); + __raw_writel(tmp_reg, clk->scale_reg); + clk->rate = parent_rate; + clk_reg_enable(clk); + ret = 0; + goto out; + } + + i = 0; + for (tmp_2p = 1; tmp_2p < 16; tmp_2p <<= 1) { + if (rate * tmp_2p >= PLL160_MIN_FCCO) + break; + i++; + } + + if (tmp_2p > 1) + tmp_reg |= ((i - 1) << 11); + else + tmp_reg |= (1 << 14); /*direct mode, no divide */ + + tmp_m = rate * tmp_2p; + tmp_m /= parent_rate; + + tmp_reg |= (tmp_m - 1) << 1; /*calculate M */ + tmp_reg |= (1 << 16); /*power up PLL */ + __raw_writel(tmp_reg, clk->scale_reg); + + if (clk_wait_for_pll_lock(clk) < 0) { + clk_reg_disable(clk); + clk_reg_disable1(clk); + + tmp_reg = __raw_readl(clk->scale_reg); + tmp_reg &= ~0x1ffff; /*clear all settings, power down */ + __raw_writel(tmp_reg, clk->scale_reg); + clk->rate = 0; + ret = -EFAULT; + goto out; + } + + clk->rate = (tmp_m * parent_rate) / tmp_2p; + + if (clk->flags & RATE_PROPAGATES) + propagate_rate(clk); + + clk_reg_enable(clk); + ret = 0; + +out: + return ret; +} + +/*configure PER_CLK*/ +static int per_clk_set_rate(struct clk *clk, u32 rate) +{ + u32 tmp; + + tmp = __raw_readl(clk->scale_reg); + tmp &= ~(0x1f << 2); + tmp |= ((clk->parent->rate / clk->rate) - 1) << 2; + __raw_writel(tmp, clk->scale_reg); + clk->rate = rate; + return 0; +} + +/*configure HCLK*/ +static int hclk_set_rate(struct clk *clk, u32 rate) +{ + u32 tmp; + tmp = __raw_readl(clk->scale_reg); + tmp = tmp & ~0x3; + switch (rate) { + case 1: + break; + case 2: + tmp |= 1; + break; + case 4: + tmp |= 2; + break; + } + + __raw_writel(tmp, clk->scale_reg); + clk->rate = rate; + return 0; +} + +static u32 hclk_round_rate(struct clk *clk, u32 rate) +{ + switch (rate) { + case 1: + case 4: + return rate; + } + return 2; +} + +static u32 per_clk_round_rate(struct clk *clk, u32 rate) +{ + return CLK_RATE_13MHZ; +} + +static int on_off_set_rate(struct clk *clk, u32 rate) +{ + if (rate) { + clk_reg_enable(clk); + clk->rate = 1; + } else { + clk_reg_disable(clk); + clk->rate = 0; + } + return 0; +} + +static int on_off_inv_set_rate(struct clk *clk, u32 rate) +{ + if (rate) { + clk_reg_disable(clk); /*enable bit is inverted */ + clk->rate = 1; + } else { + clk_reg_enable(clk); + clk->rate = 0; + } + return 0; +} + +static u32 on_off_round_rate(struct clk *clk, u32 rate) +{ + return (rate ? 1 : 0); +} + +static u32 pll4_round_rate(struct clk *clk, u32 rate) +{ + if (rate > CLK_RATE_208MHZ) + rate = CLK_RATE_208MHZ; + if (rate == CLK_RATE_208MHZ && hclk_ck.user_rate == 1) + rate = CLK_RATE_208MHZ - CLK_RATE_13MHZ; + return (rate - (rate % (hclk_ck.user_rate * CLK_RATE_13MHZ))); +} + +static u32 pll3_round_rate(struct clk *clk, u32 rate) +{ + if (rate > CLK_RATE_208MHZ) + rate = CLK_RATE_208MHZ; + return (rate - rate % CLK_RATE_13MHZ); +} + +static u32 pll5_round_rate(struct clk *clk, u32 rate) +{ + return (rate ? CLK_RATE_48MHZ : 0); +} + +static u32 ck_13MHz_round_rate(struct clk *clk, u32 rate) +{ + return (rate ? CLK_RATE_13MHZ : 0); +} + +static int ck_13MHz_set_rate(struct clk *clk, u32 rate) +{ + if (rate) { + clk_reg_disable(clk); /*enable bit is inverted */ + udelay(500); + clk->rate = CLK_RATE_13MHZ; + ck_1MHz.rate = CLK_RATE_1MHZ; + } else { + clk_reg_enable(clk); + clk->rate = 0; + ck_1MHz.rate = 0; + } + return 0; +} + +static int pll1_set_rate(struct clk *clk, u32 rate) +{ +#if 0 /* doesn't work on some boards, probably a HW BUG */ + if (rate) { + clk_reg_disable(clk); /*enable bit is inverted */ + if (!clk_wait_for_pll_lock(clk)) { + clk->rate = CLK_RATE_13MHZ; + } else { + clk_reg_enable(clk); + clk->rate = 0; + } + + } else { + clk_reg_enable(clk); + clk->rate = 0; + } +#endif + return 0; +} + +/* Clock sources */ + +static struct clk osc_13MHz = { + .name = "osc_13MHz", + .flags = FIXED_RATE, + .rate = CLK_RATE_13MHZ, +}; + +static struct clk ck_13MHz = { + .name = "ck_13MHz", + .parent = &osc_13MHz, + .flags = NEEDS_INITIALIZATION, + .round_rate = &ck_13MHz_round_rate, + .set_rate = &ck_13MHz_set_rate, + .enable_reg = OSC13CTRL_REG, + .enable_shift = 0, + .rate = CLK_RATE_13MHZ, +}; + +static struct clk osc_32KHz = { + .name = "osc_32KHz", + .flags = FIXED_RATE, + .rate = CLK_RATE_32KHZ, +}; + +/*attached to PLL5*/ +static struct clk ck_1MHz = { + .name = "ck_1MHz", + .flags = FIXED_RATE | PARENT_SET_RATE, + .parent = &ck_13MHz, +}; + +/* PLL1 (397) - provides 13' MHz clock */ +static struct clk ck_pll1 = { + .name = "ck_pll1", + .parent = &osc_32KHz, + .flags = NEEDS_INITIALIZATION, + .round_rate = &ck_13MHz_round_rate, + .set_rate = &pll1_set_rate, + .enable_reg = PLLCTRL_REG, + .enable_shift = 1, + .scale_reg = PLLCTRL_REG, + .rate = CLK_RATE_13MHZ, +}; + +/* CPU/Bus PLL */ +static struct clk ck_pll4 = { + .name = "ck_pll4", + .parent = &ck_pll1, + .flags = RATE_PROPAGATES | NEEDS_INITIALIZATION, + .propagate_next = &per_ck, + .round_rate = &pll4_round_rate, + .set_rate = &pll160_set_rate, + .rate = CLK_RATE_208MHZ, + .scale_reg = HCLKPLLCTRL_REG, + .enable_reg = PWRCTRL_REG, + .enable_shift = 2, + .parent_switch_reg = SYSCLKCTRL_REG, + .set_parent = &set_13MHz_parent, +}; + +/* USB PLL */ +static struct clk ck_pll5 = { + .name = "ck_pll5", + .parent = &ck_1MHz, + .flags = NEEDS_INITIALIZATION, + .round_rate = &pll5_round_rate, + .set_rate = &pll160_set_rate, + .scale_reg = USBCTRL_REG, + .enable_reg = USBCTRL_REG, + .enable_shift = 18, + .enable_reg1 = USBCTRL_REG, + .enable_shift1 = 17, +}; + +/* XPERTTeak DSP PLL */ +static struct clk ck_pll3 = { + .name = "ck_pll3", + .parent = &ck_pll1, + .flags = NEEDS_INITIALIZATION, + .round_rate = &pll3_round_rate, + .set_rate = &pll160_set_rate, + .scale_reg = DSPPLLCTRL_REG, + .enable_reg = DSPCLKCTRL_REG, + .enable_shift = 3, + .enable_reg1 = DSPCLKCTRL_REG, + .enable_shift1 = 2, + .parent_switch_reg = DSPCLKCTRL_REG, + .set_parent = &set_13MHz_parent, +}; + +static struct clk hclk_ck = { + .name = "hclk_ck", + .parent = &ck_pll4, + .flags = PARENT_SET_RATE, + .set_rate = &hclk_set_rate, + .round_rate = &hclk_round_rate, + .scale_reg = HCLKDIVCTRL_REG, + .rate = 2, + .user_rate = 2, +}; + +static struct clk per_ck = { + .name = "per_ck", + .parent = &ck_pll4, + .flags = FIXED_RATE, + .propagate_next = &hclk_ck, + .set_rate = &per_clk_set_rate, + .round_rate = &per_clk_round_rate, + .scale_reg = HCLKDIVCTRL_REG, + .rate = CLK_RATE_13MHZ, + .user_rate = CLK_RATE_13MHZ, +}; + +static struct clk m2hclk_ck = { + .name = "m2hclk_ck", + .parent = &hclk_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_inv_set_rate, + .rate = 1, + .enable_shift = 6, + .enable_reg = PWRCTRL_REG, +}; + +static struct clk vfp9_ck = { + .name = "vfp9_ck", + .parent = &ck_pll4, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .rate = 1, + .enable_shift = 4, + .enable_reg = VFP9CLKCTRL_REG, +}; + +static struct clk keyscan_ck = { + .name = "keyscan_ck", + .parent = &osc_32KHz, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 0, + .enable_reg = KEYCLKCTRL_REG, +}; + +static struct clk touch_ck = { + .name = "touch_ck", + .parent = &osc_32KHz, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 0, + .enable_reg = TSCLKCTRL_REG, +}; + +static struct clk pwm1_ck = { + .name = "pwm1_ck", + .parent = &osc_32KHz, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 0, + .enable_reg = PWMCLKCTRL_REG, +}; + +static struct clk pwm2_ck = { + .name = "pwm2_ck", + .parent = &osc_32KHz, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 2, + .enable_reg = PWMCLKCTRL_REG, +}; + +static struct clk jpeg_ck = { + .name = "jpeg_ck", + .parent = &hclk_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 0, + .enable_reg = JPEGCLKCTRL_REG, +}; + +static struct clk ms_ck = { + .name = "ms_ck", + .parent = &ck_pll4, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 5, + .enable_reg = MSCTRL_REG, +}; + +static struct clk dum_ck = { + .name = "dum_ck", + .parent = &hclk_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 0, + .enable_reg = DUMCLKCTRL_REG, +}; + +static struct clk flash_ck = { + .name = "flash_ck", + .parent = &hclk_ck, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 1, /* Only MLC clock supported */ + .enable_reg = FLASHCLKCTRL_REG, +}; + +static struct clk i2c0_ck = { + .name = "i2c0_ck", + .parent = &per_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 0, + .enable_reg = I2CCLKCTRL_REG, +}; + +static struct clk i2c1_ck = { + .name = "i2c1_ck", + .parent = &per_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 1, + .enable_reg = I2CCLKCTRL_REG, +}; + +static struct clk i2c2_ck = { + .name = "i2c2_ck", + .parent = &per_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 2, + .enable_reg = USB_OTG_CLKCTRL_REG, +}; + +static struct clk spi0_ck = { + .name = "spi0_ck", + .parent = &hclk_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 0, + .enable_reg = SPICTRL_REG, +}; + +static struct clk spi1_ck = { + .name = "spi1_ck", + .parent = &hclk_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 4, + .enable_reg = SPICTRL_REG, +}; + +static struct clk dma_ck = { + .name = "dma_ck", + .parent = &hclk_ck, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 0, + .enable_reg = DMACLKCTRL_REG, +}; + +static struct clk uart3_ck = { + .name = "uart3_ck", + .parent = &per_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .rate = 1, + .enable_shift = 0, + .enable_reg = UARTCLKCTRL_REG, +}; + +static struct clk uart4_ck = { + .name = "uart4_ck", + .parent = &per_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 1, + .enable_reg = UARTCLKCTRL_REG, +}; + +static struct clk uart5_ck = { + .name = "uart5_ck", + .parent = &per_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .rate = 1, + .enable_shift = 2, + .enable_reg = UARTCLKCTRL_REG, +}; + +static struct clk uart6_ck = { + .name = "uart6_ck", + .parent = &per_ck, + .flags = NEEDS_INITIALIZATION, + .round_rate = &on_off_round_rate, + .set_rate = &on_off_set_rate, + .enable_shift = 3, + .enable_reg = UARTCLKCTRL_REG, +}; + +/* These clocks are visible outside this module + * and can be initialized + */ +static struct clk *onchip_clks[] = { + &ck_13MHz, + &ck_pll1, + &ck_pll4, + &ck_pll5, + &ck_pll3, + &vfp9_ck, + &m2hclk_ck, + &hclk_ck, + &dma_ck, + &flash_ck, + &dum_ck, + &keyscan_ck, + &pwm1_ck, + &pwm2_ck, + &jpeg_ck, + &ms_ck, + &touch_ck, + &i2c0_ck, + &i2c1_ck, + &i2c2_ck, + &spi0_ck, + &spi1_ck, + &uart3_ck, + &uart4_ck, + &uart5_ck, + &uart6_ck, +}; + +static int local_clk_enable(struct clk *clk) +{ + int ret = 0; + + if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate + && clk->user_rate) + ret = clk->set_rate(clk, clk->user_rate); + return ret; +} + +static void local_clk_disable(struct clk *clk) +{ + if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate) + clk->set_rate(clk, 0); +} + +static void local_clk_unuse(struct clk *clk) +{ + if (clk->usecount > 0 && !(--clk->usecount)) { + local_clk_disable(clk); + if (clk->parent) + local_clk_unuse(clk->parent); + } +} + +static int local_clk_use(struct clk *clk) +{ + int ret = 0; + if (clk->usecount++ == 0) { + if (clk->parent) + ret = local_clk_use(clk->parent); + + if (ret != 0) { + clk->usecount--; + goto out; + } + + ret = local_clk_enable(clk); + + if (ret != 0 && clk->parent) { + local_clk_unuse(clk->parent); + clk->usecount--; + } + } +out: + return ret; +} + +static int local_set_rate(struct clk *clk, u32 rate) +{ + int ret = -EINVAL; + if (clk->set_rate) { + + if (clk->user_rate == clk->rate && clk->parent->rate) { + /* if clock enabled or rate not set */ + clk->user_rate = clk->round_rate(clk, rate); + ret = clk->set_rate(clk, clk->user_rate); + } else + clk->user_rate = clk->round_rate(clk, rate); + ret = 0; + } + return ret; +} + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = -EINVAL; + + if (clk->flags & FIXED_RATE) + goto out; + + clock_lock(); + if ((clk->flags & PARENT_SET_RATE) && clk->parent) { + + clk->user_rate = clk->round_rate(clk, rate); + /* parent clock needs to be refreshed + for the setting to take effect */ + } else { + ret = local_set_rate(clk, rate); + } + ret = 0; + clock_unlock(); + +out: + return ret; +} + +EXPORT_SYMBOL(clk_set_rate); + +struct clk *clk_get(struct device *dev, const char *id) +{ + struct clk *clk = ERR_PTR(-ENOENT); + struct clk **clkp; + + clock_lock(); + for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks); + clkp++) { + if (strcmp(id, (*clkp)->name) == 0 + && try_module_get((*clkp)->owner)) { + clk = (*clkp); + break; + } + } + clock_unlock(); + + return clk; +} +EXPORT_SYMBOL(clk_get); + +void clk_put(struct clk *clk) +{ + clock_lock(); + if (clk && !IS_ERR(clk)) + module_put(clk->owner); + clock_unlock(); +} +EXPORT_SYMBOL(clk_put); + +unsigned long clk_get_rate(struct clk *clk) +{ + unsigned long ret; + clock_lock(); + ret = clk->rate; + clock_unlock(); + return ret; +} +EXPORT_SYMBOL(clk_get_rate); + +int clk_enable(struct clk *clk) +{ + int ret = 0; + + clock_lock(); + ret = local_clk_use(clk); + clock_unlock(); + return ret; +} + +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ + clock_lock(); + local_clk_unuse(clk); + clock_unlock(); +} + +EXPORT_SYMBOL(clk_disable); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + long ret; + clock_lock(); + if (clk->round_rate) + ret = clk->round_rate(clk, rate); + else + ret = clk->rate; + clock_unlock(); + return ret; +} + +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + int ret = -ENODEV; + if (!clk->set_parent) + goto out; + + clock_lock(); + ret = clk->set_parent(clk, parent); + if (!ret) + clk->parent = parent; + clock_unlock(); + +out: + return ret; +} + +EXPORT_SYMBOL(clk_set_parent); + +static int __init clk_init(void) +{ + struct clk **clkp; + + /* Disable autoclocking, as it doesn't seem to work */ + __raw_writel(0xff, AUTOCLK_CTRL); + + for (clkp = onchip_clks; clkp < onchip_clks + ARRAY_SIZE(onchip_clks); + clkp++) { + if (((*clkp)->flags & NEEDS_INITIALIZATION) + && ((*clkp)->set_rate)) { + (*clkp)->user_rate = (*clkp)->rate; + local_set_rate((*clkp), (*clkp)->user_rate); + if ((*clkp)->set_parent) + (*clkp)->set_parent((*clkp), (*clkp)->parent); + } + pr_debug("%s: clock %s, rate %ld\n", + __FUNCTION__, (*clkp)->name, (*clkp)->rate); + } + + local_clk_use(&ck_pll4); + + /* if ck_13MHz is not used, disable it. */ + if (ck_13MHz.usecount == 0) + local_clk_disable(&ck_13MHz); + + /* Disable autoclocking */ + __raw_writeb(0xff, AUTOCLK_CTRL); + + return 0; +} + +arch_initcall(clk_init); diff --git a/arch/arm/mach-pnx4008/clock.h b/arch/arm/mach-pnx4008/clock.h new file mode 100644 index 000000000..cd58f372c --- /dev/null +++ b/arch/arm/mach-pnx4008/clock.h @@ -0,0 +1,43 @@ +/* + * arch/arm/mach-pnx4008/clock.h + * + * Clock control driver for PNX4008 - internal header file + * + * Author: Vitaly Wool <source@mvista.com> + * + * 2006 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#ifndef __ARCH_ARM_PNX4008_CLOCK_H__ +#define __ARCH_ARM_PNX4008_CLOCK_H__ + +struct clk { + struct list_head node; + struct module *owner; + const char *name; + struct clk *parent; + struct clk *propagate_next; + u32 rate; + u32 user_rate; + s8 usecount; + u32 flags; + u32 scale_reg; + u8 enable_shift; + u32 enable_reg; + u8 enable_shift1; + u32 enable_reg1; + u32 parent_switch_reg; + u32(*round_rate) (struct clk *, u32); + int (*set_rate) (struct clk *, u32); + int (*set_parent) (struct clk * clk, struct clk * parent); +}; + +/* Flags */ +#define RATE_PROPAGATES (1<<0) +#define NEEDS_INITIALIZATION (1<<1) +#define PARENT_SET_RATE (1<<2) +#define FIXED_RATE (1<<3) + +#endif diff --git a/arch/arm/mach-pnx4008/core.c b/arch/arm/mach-pnx4008/core.c new file mode 100644 index 000000000..3d73c1e93 --- /dev/null +++ b/arch/arm/mach-pnx4008/core.c @@ -0,0 +1,205 @@ +/* + * arch/arm/mach-pnx4008/core.c + * + * PNX4008 core startup code + * + * Authors: Vitaly Wool, Dmitry Chigirev, + * Grigory Tolstolytkin, Dmitry Pervushin <source@mvista.com> + * + * Based on reference code received from Philips: + * Copyright (C) 2003 Philips Semiconductors + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/mm.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/serial_8250.h> +#include <linux/device.h> +#include <linux/spi/spi.h> + +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/pgtable.h> +#include <asm/page.h> +#include <asm/system.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/time.h> + +#include <asm/arch/irq.h> +#include <asm/arch/clock.h> +#include <asm/arch/dma.h> + +struct resource spipnx_0_resources[] = { + { + .start = PNX4008_SPI1_BASE, + .end = PNX4008_SPI1_BASE + SZ_4K, + .flags = IORESOURCE_MEM, + }, { + .start = PER_SPI1_REC_XMIT, + .flags = IORESOURCE_DMA, + }, { + .start = SPI1_INT, + .flags = IORESOURCE_IRQ, + }, { + .flags = 0, + }, +}; + +struct resource spipnx_1_resources[] = { + { + .start = PNX4008_SPI2_BASE, + .end = PNX4008_SPI2_BASE + SZ_4K, + .flags = IORESOURCE_MEM, + }, { + .start = PER_SPI2_REC_XMIT, + .flags = IORESOURCE_DMA, + }, { + .start = SPI2_INT, + .flags = IORESOURCE_IRQ, + }, { + .flags = 0, + } +}; + +static struct spi_board_info spi_board_info[] __initdata = { + { + .modalias = "m25p80", + .max_speed_hz = 1000000, + .bus_num = 1, + .chip_select = 0, + }, +}; + +static struct platform_device spipnx_1 = { + .name = "spipnx", + .id = 1, + .num_resources = ARRAY_SIZE(spipnx_0_resources), + .resource = spipnx_0_resources, + .dev = { + .coherent_dma_mask = 0xFFFFFFFF, + }, +}; + +static struct platform_device spipnx_2 = { + .name = "spipnx", + .id = 2, + .num_resources = ARRAY_SIZE(spipnx_1_resources), + .resource = spipnx_1_resources, + .dev = { + .coherent_dma_mask = 0xFFFFFFFF, + }, +}; + +static struct plat_serial8250_port platform_serial_ports[] = { + { + .membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART5_BASE)), + .mapbase = (unsigned long)PNX4008_UART5_BASE, + .irq = IIR5_INT, + .uartclk = PNX4008_UART_CLK, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST, + }, + { + .membase = (void *)__iomem(IO_ADDRESS(PNX4008_UART3_BASE)), + .mapbase = (unsigned long)PNX4008_UART3_BASE, + .irq = IIR3_INT, + .uartclk = PNX4008_UART_CLK, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART | UPF_SKIP_TEST, + }, + {} +}; + +static struct platform_device serial_device = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = &platform_serial_ports, + }, +}; + +static struct platform_device *devices[] __initdata = { + &spipnx_1, + &spipnx_2, + &serial_device, +}; + + +extern void pnx4008_uart_init(void); + +static void __init pnx4008_init(void) +{ + /*disable all START interrupt sources, + and clear all START interrupt flags */ + __raw_writel(0, START_INT_ER_REG(SE_PIN_BASE_INT)); + __raw_writel(0, START_INT_ER_REG(SE_INT_BASE_INT)); + __raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT)); + __raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT)); + + platform_add_devices(devices, ARRAY_SIZE(devices)); + spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); + /* Switch on the UART clocks */ + pnx4008_uart_init(); +} + +static struct map_desc pnx4008_io_desc[] __initdata = { + { + .virtual = IO_ADDRESS(PNX4008_IRAM_BASE), + .pfn = __phys_to_pfn(PNX4008_IRAM_BASE), + .length = SZ_64K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(PNX4008_NDF_FLASH_BASE), + .pfn = __phys_to_pfn(PNX4008_NDF_FLASH_BASE), + .length = SZ_1M - SZ_128K, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(PNX4008_JPEG_CONFIG_BASE), + .pfn = __phys_to_pfn(PNX4008_JPEG_CONFIG_BASE), + .length = SZ_128K * 3, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(PNX4008_DMA_CONFIG_BASE), + .pfn = __phys_to_pfn(PNX4008_DMA_CONFIG_BASE), + .length = SZ_1M, + .type = MT_DEVICE, + }, { + .virtual = IO_ADDRESS(PNX4008_AHB2FAB_BASE), + .pfn = __phys_to_pfn(PNX4008_AHB2FAB_BASE), + .length = SZ_1M, + .type = MT_DEVICE, + }, +}; + +void __init pnx4008_map_io(void) +{ + iotable_init(pnx4008_io_desc, ARRAY_SIZE(pnx4008_io_desc)); +} + +extern struct sys_timer pnx4008_timer; + +MACHINE_START(PNX4008, "Philips PNX4008") + /* Maintainer: MontaVista Software Inc. */ + .phys_io = 0x40090000, + .io_pg_offst = (0xf4090000 >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = pnx4008_map_io, + .init_irq = pnx4008_init_irq, + .init_machine = pnx4008_init, + .timer = &pnx4008_timer, +MACHINE_END diff --git a/arch/arm/mach-pnx4008/dma.c b/arch/arm/mach-pnx4008/dma.c new file mode 100644 index 000000000..ec01574f8 --- /dev/null +++ b/arch/arm/mach-pnx4008/dma.c @@ -0,0 +1,1108 @@ +/* + * linux/arch/arm/mach-pnx4008/dma.c + * + * PNX4008 DMA registration and IRQ dispatching + * + * Author: Vitaly Wool + * Copyright: MontaVista Software Inc. (c) 2005 + * + * Based on the code from Nicolas Pitre + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/interrupt.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/dma-mapping.h> +#include <linux/clk.h> + +#include <asm/system.h> +#include <asm/hardware.h> +#include <asm/dma.h> +#include <asm/dma-mapping.h> +#include <asm/io.h> +#include <asm/mach/dma.h> +#include <asm/arch/clock.h> + +static struct dma_channel { + char *name; + void (*irq_handler) (int, int, void *, struct pt_regs *); + void *data; + struct pnx4008_dma_ll *ll; + u32 ll_dma; + void *target_addr; + int target_id; +} dma_channels[MAX_DMA_CHANNELS]; + +static struct ll_pool { + void *vaddr; + void *cur; + dma_addr_t dma_addr; + int count; +} ll_pool; + +static spinlock_t ll_lock = SPIN_LOCK_UNLOCKED; + +struct pnx4008_dma_ll *pnx4008_alloc_ll_entry(dma_addr_t * ll_dma) +{ + struct pnx4008_dma_ll *ll = NULL; + unsigned long flags; + + spin_lock_irqsave(&ll_lock, flags); + if (ll_pool.count > 4) { /* can give one more */ + ll = *(struct pnx4008_dma_ll **) ll_pool.cur; + *ll_dma = ll_pool.dma_addr + ((void *)ll - ll_pool.vaddr); + *(void **)ll_pool.cur = **(void ***)ll_pool.cur; + memset(ll, 0, sizeof(*ll)); + ll_pool.count--; + } + spin_unlock_irqrestore(&ll_lock, flags); + + return ll; +} + +EXPORT_SYMBOL_GPL(pnx4008_alloc_ll_entry); + +void pnx4008_free_ll_entry(struct pnx4008_dma_ll * ll, dma_addr_t ll_dma) +{ + unsigned long flags; + + if (ll) { + if ((unsigned long)((long)ll - (long)ll_pool.vaddr) > 0x4000) { + printk(KERN_ERR "Trying to free entry not allocated by DMA\n"); + BUG(); + } + + if (ll->flags & DMA_BUFFER_ALLOCATED) + ll->free(ll->alloc_data); + + spin_lock_irqsave(&ll_lock, flags); + *(long *)ll = *(long *)ll_pool.cur; + *(long *)ll_pool.cur = (long)ll; + ll_pool.count++; + spin_unlock_irqrestore(&ll_lock, flags); + } +} + +EXPORT_SYMBOL_GPL(pnx4008_free_ll_entry); + +void pnx4008_free_ll(u32 ll_dma, struct pnx4008_dma_ll * ll) +{ + struct pnx4008_dma_ll *ptr; + u32 dma; + + while (ll) { + dma = ll->next_dma; + ptr = ll->next; + pnx4008_free_ll_entry(ll, ll_dma); + + ll_dma = dma; + ll = ptr; + } +} + +EXPORT_SYMBOL_GPL(pnx4008_free_ll); + +static int dma_channels_requested = 0; + +static inline void dma_increment_usage(void) +{ + if (!dma_channels_requested++) { + struct clk *clk = clk_get(0, "dma_ck"); + if (!IS_ERR(clk)) { + clk_set_rate(clk, 1); + clk_put(clk); + } + pnx4008_config_dma(-1, -1, 1); + } +} +static inline void dma_decrement_usage(void) +{ + if (!--dma_channels_requested) { + struct clk *clk = clk_get(0, "dma_ck"); + if (!IS_ERR(clk)) { + clk_set_rate(clk, 0); + clk_put(clk); + } + pnx4008_config_dma(-1, -1, 0); + + } +} + +static spinlock_t dma_lock = SPIN_LOCK_UNLOCKED; + +static inline void pnx4008_dma_lock(void) +{ + spin_lock_irq(&dma_lock); +} + +static inline void pnx4008_dma_unlock(void) +{ + spin_unlock_irq(&dma_lock); +} + +#define VALID_CHANNEL(c) (((c) >= 0) && ((c) < MAX_DMA_CHANNELS)) + +int pnx4008_request_channel(char *name, int ch, + void (*irq_handler) (int, int, void *, + struct pt_regs *), void *data) +{ + int i, found = 0; + + /* basic sanity checks */ + if (!name || (ch != -1 && !VALID_CHANNEL(ch))) + return -EINVAL; + + pnx4008_dma_lock(); + + /* try grabbing a DMA channel with the requested priority */ + for (i = MAX_DMA_CHANNELS - 1; i >= 0; i--) { + if (!dma_channels[i].name && (ch == -1 || ch == i)) { + found = 1; + break; + } + } + + if (found) { + dma_increment_usage(); + dma_channels[i].name = name; + dma_channels[i].irq_handler = irq_handler; + dma_channels[i].data = data; + dma_channels[i].ll = NULL; + dma_channels[i].ll_dma = 0; + } else { + printk(KERN_WARNING "No more available DMA channels for %s\n", + name); + i = -ENODEV; + } + + pnx4008_dma_unlock(); + return i; +} + +EXPORT_SYMBOL_GPL(pnx4008_request_channel); + +void pnx4008_free_channel(int ch) +{ + if (!dma_channels[ch].name) { + printk(KERN_CRIT + "%s: trying to free channel %d which is already freed\n", + __FUNCTION__, ch); + return; + } + + pnx4008_dma_lock(); + pnx4008_free_ll(dma_channels[ch].ll_dma, dma_channels[ch].ll); + dma_channels[ch].ll = NULL; + dma_decrement_usage(); + + dma_channels[ch].name = NULL; + pnx4008_dma_unlock(); +} + +EXPORT_SYMBOL_GPL(pnx4008_free_channel); + +int pnx4008_config_dma(int ahb_m1_be, int ahb_m2_be, int enable) +{ + unsigned long dma_cfg = __raw_readl(DMAC_CONFIG); + + switch (ahb_m1_be) { + case 0: + dma_cfg &= ~(1 << 1); + break; + case 1: + dma_cfg |= (1 << 1); + break; + default: + break; + } + + switch (ahb_m2_be) { + case 0: + dma_cfg &= ~(1 << 2); + break; + case 1: + dma_cfg |= (1 << 2); + break; + default: + break; + } + + switch (enable) { + case 0: + dma_cfg &= ~(1 << 0); + break; + case 1: + dma_cfg |= (1 << 0); + break; + default: + break; + } + + pnx4008_dma_lock(); + __raw_writel(dma_cfg, DMAC_CONFIG); + pnx4008_dma_unlock(); + + return 0; +} + +EXPORT_SYMBOL_GPL(pnx4008_config_dma); + +int pnx4008_dma_pack_control(const struct pnx4008_dma_ch_ctrl * ch_ctrl, + unsigned long *ctrl) +{ + int i = 0, dbsize, sbsize, err = 0; + + if (!ctrl || !ch_ctrl) { + err = -EINVAL; + goto out; + } + + *ctrl = 0; + + switch (ch_ctrl->tc_mask) { + case 0: + break; + case 1: + *ctrl |= (1 << 31); + break; + + default: + err = -EINVAL; + goto out; + } + + switch (ch_ctrl->cacheable) { + case 0: + break; + case 1: + *ctrl |= (1 << 30); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_ctrl->bufferable) { + case 0: + break; + case 1: + *ctrl |= (1 << 29); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_ctrl->priv_mode) { + case 0: + break; + case 1: + *ctrl |= (1 << 28); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_ctrl->di) { + case 0: + break; + case 1: + *ctrl |= (1 << 27); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_ctrl->si) { + case 0: + break; + case 1: + *ctrl |= (1 << 26); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_ctrl->dest_ahb1) { + case 0: + break; + case 1: + *ctrl |= (1 << 25); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_ctrl->src_ahb1) { + case 0: + break; + case 1: + *ctrl |= (1 << 24); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_ctrl->dwidth) { + case WIDTH_BYTE: + *ctrl &= ~(7 << 21); + break; + case WIDTH_HWORD: + *ctrl &= ~(7 << 21); + *ctrl |= (1 << 21); + break; + case WIDTH_WORD: + *ctrl &= ~(7 << 21); + *ctrl |= (2 << 21); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_ctrl->swidth) { + case WIDTH_BYTE: + *ctrl &= ~(7 << 18); + break; + case WIDTH_HWORD: + *ctrl &= ~(7 << 18); + *ctrl |= (1 << 18); + break; + case WIDTH_WORD: + *ctrl &= ~(7 << 18); + *ctrl |= (2 << 18); + break; + + default: + err = -EINVAL; + goto out; + } + dbsize = ch_ctrl->dbsize; + while (!(dbsize & 1)) { + i++; + dbsize >>= 1; + } + if (ch_ctrl->dbsize != 1 || i > 8 || i == 1) { + err = -EINVAL; + goto out; + } else if (i > 1) + i--; + *ctrl &= ~(7 << 15); + *ctrl |= (i << 15); + + sbsize = ch_ctrl->sbsize; + while (!(sbsize & 1)) { + i++; + sbsize >>= 1; + } + if (ch_ctrl->sbsize != 1 || i > 8 || i == 1) { + err = -EINVAL; + goto out; + } else if (i > 1) + i--; + *ctrl &= ~(7 << 12); + *ctrl |= (i << 12); + + if (ch_ctrl->tr_size > 0x7ff) { + err = -E2BIG; + goto out; + } + *ctrl &= ~0x7ff; + *ctrl |= ch_ctrl->tr_size & 0x7ff; + +out: + return err; +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_pack_control); + +int pnx4008_dma_parse_control(unsigned long ctrl, + struct pnx4008_dma_ch_ctrl * ch_ctrl) +{ + int err = 0; + + if (!ch_ctrl) { + err = -EINVAL; + goto out; + } + + ch_ctrl->tr_size = ctrl & 0x7ff; + ctrl >>= 12; + + ch_ctrl->sbsize = 1 << (ctrl & 7); + if (ch_ctrl->sbsize > 1) + ch_ctrl->sbsize <<= 1; + ctrl >>= 3; + + ch_ctrl->dbsize = 1 << (ctrl & 7); + if (ch_ctrl->dbsize > 1) + ch_ctrl->dbsize <<= 1; + ctrl >>= 3; + + switch (ctrl & 7) { + case 0: + ch_ctrl->swidth = WIDTH_BYTE; + break; + case 1: + ch_ctrl->swidth = WIDTH_HWORD; + break; + case 2: + ch_ctrl->swidth = WIDTH_WORD; + break; + default: + err = -EINVAL; + goto out; + } + ctrl >>= 3; + + switch (ctrl & 7) { + case 0: + ch_ctrl->dwidth = WIDTH_BYTE; + break; + case 1: + ch_ctrl->dwidth = WIDTH_HWORD; + break; + case 2: + ch_ctrl->dwidth = WIDTH_WORD; + break; + default: + err = -EINVAL; + goto out; + } + ctrl >>= 3; + + ch_ctrl->src_ahb1 = ctrl & 1; + ctrl >>= 1; + + ch_ctrl->dest_ahb1 = ctrl & 1; + ctrl >>= 1; + + ch_ctrl->si = ctrl & 1; + ctrl >>= 1; + + ch_ctrl->di = ctrl & 1; + ctrl >>= 1; + + ch_ctrl->priv_mode = ctrl & 1; + ctrl >>= 1; + + ch_ctrl->bufferable = ctrl & 1; + ctrl >>= 1; + + ch_ctrl->cacheable = ctrl & 1; + ctrl >>= 1; + + ch_ctrl->tc_mask = ctrl & 1; + +out: + return err; +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_parse_control); + +int pnx4008_dma_pack_config(const struct pnx4008_dma_ch_config * ch_cfg, + unsigned long *cfg) +{ + int err = 0; + + if (!cfg || !ch_cfg) { + err = -EINVAL; + goto out; + } + + *cfg = 0; + + switch (ch_cfg->halt) { + case 0: + break; + case 1: + *cfg |= (1 << 18); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_cfg->active) { + case 0: + break; + case 1: + *cfg |= (1 << 17); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_cfg->lock) { + case 0: + break; + case 1: + *cfg |= (1 << 16); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_cfg->itc) { + case 0: + break; + case 1: + *cfg |= (1 << 15); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_cfg->ie) { + case 0: + break; + case 1: + *cfg |= (1 << 14); + break; + + default: + err = -EINVAL; + goto out; + } + switch (ch_cfg->flow_cntrl) { + case FC_MEM2MEM_DMA: + *cfg &= ~(7 << 11); + break; + case FC_MEM2PER_DMA: + *cfg &= ~(7 << 11); + *cfg |= (1 << 11); + break; + case FC_PER2MEM_DMA: + *cfg &= ~(7 << 11); + *cfg |= (2 << 11); + break; + case FC_PER2PER_DMA: + *cfg &= ~(7 << 11); + *cfg |= (3 << 11); + break; + case FC_PER2PER_DPER: + *cfg &= ~(7 << 11); + *cfg |= (4 << 11); + break; + case FC_MEM2PER_PER: + *cfg &= ~(7 << 11); + *cfg |= (5 << 11); + break; + case FC_PER2MEM_PER: + *cfg &= ~(7 << 11); + *cfg |= (6 << 11); + break; + case FC_PER2PER_SPER: + *cfg |= (7 << 11); + break; + + default: + err = -EINVAL; + goto out; + } + *cfg &= ~(0x1f << 6); + *cfg |= ((ch_cfg->dest_per & 0x1f) << 6); + + *cfg &= ~(0x1f << 1); + *cfg |= ((ch_cfg->src_per & 0x1f) << 1); + +out: + return err; +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_pack_config); + +int pnx4008_dma_parse_config(unsigned long cfg, + struct pnx4008_dma_ch_config * ch_cfg) +{ + int err = 0; + + if (!ch_cfg) { + err = -EINVAL; + goto out; + } + + cfg >>= 1; + + ch_cfg->src_per = cfg & 0x1f; + cfg >>= 5; + + ch_cfg->dest_per = cfg & 0x1f; + cfg >>= 5; + + switch (cfg & 7) { + case 0: + ch_cfg->flow_cntrl = FC_MEM2MEM_DMA; + break; + case 1: + ch_cfg->flow_cntrl = FC_MEM2PER_DMA; + break; + case 2: + ch_cfg->flow_cntrl = FC_PER2MEM_DMA; + break; + case 3: + ch_cfg->flow_cntrl = FC_PER2PER_DMA; + break; + case 4: + ch_cfg->flow_cntrl = FC_PER2PER_DPER; + break; + case 5: + ch_cfg->flow_cntrl = FC_MEM2PER_PER; + break; + case 6: + ch_cfg->flow_cntrl = FC_PER2MEM_PER; + break; + case 7: + ch_cfg->flow_cntrl = FC_PER2PER_SPER; + } + cfg >>= 3; + + ch_cfg->ie = cfg & 1; + cfg >>= 1; + + ch_cfg->itc = cfg & 1; + cfg >>= 1; + + ch_cfg->lock = cfg & 1; + cfg >>= 1; + + ch_cfg->active = cfg & 1; + cfg >>= 1; + + ch_cfg->halt = cfg & 1; + +out: + return err; +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_parse_config); + +void pnx4008_dma_split_head_entry(struct pnx4008_dma_config * config, + struct pnx4008_dma_ch_ctrl * ctrl) +{ + int new_len = ctrl->tr_size, num_entries = 0; + int old_len = new_len; + int src_width, dest_width, count = 1; + + switch (ctrl->swidth) { + case WIDTH_BYTE: + src_width = 1; + break; + case WIDTH_HWORD: + src_width = 2; + break; + case WIDTH_WORD: + src_width = 4; + break; + default: + return; + } + + switch (ctrl->dwidth) { + case WIDTH_BYTE: + dest_width = 1; + break; + case WIDTH_HWORD: + dest_width = 2; + break; + case WIDTH_WORD: + dest_width = 4; + break; + default: + return; + } + + while (new_len > 0x7FF) { + num_entries++; + new_len = (ctrl->tr_size + num_entries) / (num_entries + 1); + } + if (num_entries != 0) { + struct pnx4008_dma_ll *ll = NULL; + config->ch_ctrl &= ~0x7ff; + config->ch_ctrl |= new_len; + if (!config->is_ll) { + config->is_ll = 1; + while (num_entries) { + if (!ll) { + config->ll = + pnx4008_alloc_ll_entry(&config-> + ll_dma); + ll = config->ll; + } else { + ll->next = + pnx4008_alloc_ll_entry(&ll-> + next_dma); + ll = ll->next; + } + + if (ctrl->si) + ll->src_addr = + config->src_addr + + src_width * new_len * count; + else + ll->src_addr = config->src_addr; + if (ctrl->di) + ll->dest_addr = + config->dest_addr + + dest_width * new_len * count; + else + ll->dest_addr = config->dest_addr; + ll->ch_ctrl = config->ch_ctrl & 0x7fffffff; + ll->next_dma = 0; + ll->next = NULL; + num_entries--; + count++; + } + } else { + struct pnx4008_dma_ll *ll_old = config->ll; + unsigned long ll_dma_old = config->ll_dma; + while (num_entries) { + if (!ll) { + config->ll = + pnx4008_alloc_ll_entry(&config-> + ll_dma); + ll = config->ll; + } else { + ll->next = + pnx4008_alloc_ll_entry(&ll-> + next_dma); + ll = ll->next; + } + + if (ctrl->si) + ll->src_addr = + config->src_addr + + src_width * new_len * count; + else + ll->src_addr = config->src_addr; + if (ctrl->di) + ll->dest_addr = + config->dest_addr + + dest_width * new_len * count; + else + ll->dest_addr = config->dest_addr; + ll->ch_ctrl = config->ch_ctrl & 0x7fffffff; + ll->next_dma = 0; + ll->next = NULL; + num_entries--; + count++; + } + ll->next_dma = ll_dma_old; + ll->next = ll_old; + } + /* adjust last length/tc */ + ll->ch_ctrl = config->ch_ctrl & (~0x7ff); + ll->ch_ctrl |= old_len - new_len * (count - 1); + config->ch_ctrl &= 0x7fffffff; + } +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_split_head_entry); + +void pnx4008_dma_split_ll_entry(struct pnx4008_dma_ll * cur_ll, + struct pnx4008_dma_ch_ctrl * ctrl) +{ + int new_len = ctrl->tr_size, num_entries = 0; + int old_len = new_len; + int src_width, dest_width, count = 1; + + switch (ctrl->swidth) { + case WIDTH_BYTE: + src_width = 1; + break; + case WIDTH_HWORD: + src_width = 2; + break; + case WIDTH_WORD: + src_width = 4; + break; + default: + return; + } + + switch (ctrl->dwidth) { + case WIDTH_BYTE: + dest_width = 1; + break; + case WIDTH_HWORD: + dest_width = 2; + break; + case WIDTH_WORD: + dest_width = 4; + break; + default: + return; + } + + while (new_len > 0x7FF) { + num_entries++; + new_len = (ctrl->tr_size + num_entries) / (num_entries + 1); + } + if (num_entries != 0) { + struct pnx4008_dma_ll *ll = NULL; + cur_ll->ch_ctrl &= ~0x7ff; + cur_ll->ch_ctrl |= new_len; + if (!cur_ll->next) { + while (num_entries) { + if (!ll) { + cur_ll->next = + pnx4008_alloc_ll_entry(&cur_ll-> + next_dma); + ll = cur_ll->next; + } else { + ll->next = + pnx4008_alloc_ll_entry(&ll-> + next_dma); + ll = ll->next; + } + + if (ctrl->si) + ll->src_addr = + cur_ll->src_addr + + src_width * new_len * count; + else + ll->src_addr = cur_ll->src_addr; + if (ctrl->di) + ll->dest_addr = + cur_ll->dest_addr + + dest_width * new_len * count; + else + ll->dest_addr = cur_ll->dest_addr; + ll->ch_ctrl = cur_ll->ch_ctrl & 0x7fffffff; + ll->next_dma = 0; + ll->next = NULL; + num_entries--; + count++; + } + } else { + struct pnx4008_dma_ll *ll_old = cur_ll->next; + unsigned long ll_dma_old = cur_ll->next_dma; + while (num_entries) { + if (!ll) { + cur_ll->next = + pnx4008_alloc_ll_entry(&cur_ll-> + next_dma); + ll = cur_ll->next; + } else { + ll->next = + pnx4008_alloc_ll_entry(&ll-> + next_dma); + ll = ll->next; + } + + if (ctrl->si) + ll->src_addr = + cur_ll->src_addr + + src_width * new_len * count; + else + ll->src_addr = cur_ll->src_addr; + if (ctrl->di) + ll->dest_addr = + cur_ll->dest_addr + + dest_width * new_len * count; + else + ll->dest_addr = cur_ll->dest_addr; + ll->ch_ctrl = cur_ll->ch_ctrl & 0x7fffffff; + ll->next_dma = 0; + ll->next = NULL; + num_entries--; + count++; + } + + ll->next_dma = ll_dma_old; + ll->next = ll_old; + } + /* adjust last length/tc */ + ll->ch_ctrl = cur_ll->ch_ctrl & (~0x7ff); + ll->ch_ctrl |= old_len - new_len * (count - 1); + cur_ll->ch_ctrl &= 0x7fffffff; + } +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_split_ll_entry); + +int pnx4008_config_channel(int ch, struct pnx4008_dma_config * config) +{ + if (!VALID_CHANNEL(ch) || !dma_channels[ch].name) + return -EINVAL; + + pnx4008_dma_lock(); + __raw_writel(config->src_addr, DMAC_Cx_SRC_ADDR(ch)); + __raw_writel(config->dest_addr, DMAC_Cx_DEST_ADDR(ch)); + + if (config->is_ll) + __raw_writel(config->ll_dma, DMAC_Cx_LLI(ch)); + else + __raw_writel(0, DMAC_Cx_LLI(ch)); + + __raw_writel(config->ch_ctrl, DMAC_Cx_CONTROL(ch)); + __raw_writel(config->ch_cfg, DMAC_Cx_CONFIG(ch)); + pnx4008_dma_unlock(); + + return 0; + +} + +EXPORT_SYMBOL_GPL(pnx4008_config_channel); + +int pnx4008_channel_get_config(int ch, struct pnx4008_dma_config * config) +{ + if (!VALID_CHANNEL(ch) || !dma_channels[ch].name || !config) + return -EINVAL; + + pnx4008_dma_lock(); + config->ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch)); + config->ch_ctrl = __raw_readl(DMAC_Cx_CONTROL(ch)); + + config->ll_dma = __raw_readl(DMAC_Cx_LLI(ch)); + config->is_ll = config->ll_dma ? 1 : 0; + + config->src_addr = __raw_readl(DMAC_Cx_SRC_ADDR(ch)); + config->dest_addr = __raw_readl(DMAC_Cx_DEST_ADDR(ch)); + pnx4008_dma_unlock(); + + return 0; +} + +EXPORT_SYMBOL_GPL(pnx4008_channel_get_config); + +int pnx4008_dma_ch_enable(int ch) +{ + unsigned long ch_cfg; + + if (!VALID_CHANNEL(ch) || !dma_channels[ch].name) + return -EINVAL; + + pnx4008_dma_lock(); + ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch)); + ch_cfg |= 1; + __raw_writel(ch_cfg, DMAC_Cx_CONFIG(ch)); + pnx4008_dma_unlock(); + + return 0; +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_ch_enable); + +int pnx4008_dma_ch_disable(int ch) +{ + unsigned long ch_cfg; + + if (!VALID_CHANNEL(ch) || !dma_channels[ch].name) + return -EINVAL; + + pnx4008_dma_lock(); + ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch)); + ch_cfg &= ~1; + __raw_writel(ch_cfg, DMAC_Cx_CONFIG(ch)); + pnx4008_dma_unlock(); + + return 0; +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_ch_disable); + +int pnx4008_dma_ch_enabled(int ch) +{ + unsigned long ch_cfg; + + if (!VALID_CHANNEL(ch) || !dma_channels[ch].name) + return -EINVAL; + + pnx4008_dma_lock(); + ch_cfg = __raw_readl(DMAC_Cx_CONFIG(ch)); + pnx4008_dma_unlock(); + + return ch_cfg & 1; +} + +EXPORT_SYMBOL_GPL(pnx4008_dma_ch_enabled); + +static irqreturn_t dma_irq_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + int i; + unsigned long dint = __raw_readl(DMAC_INT_STAT); + unsigned long tcint = __raw_readl(DMAC_INT_TC_STAT); + unsigned long eint = __raw_readl(DMAC_INT_ERR_STAT); + unsigned long i_bit; + + for (i = MAX_DMA_CHANNELS - 1; i >= 0; i--) { + i_bit = 1 << i; + if (dint & i_bit) { + struct dma_channel *channel = &dma_channels[i]; + + if (channel->name && channel->irq_handler) { + int cause = 0; + + if (eint & i_bit) + cause |= DMA_ERR_INT; + if (tcint & i_bit) + cause |= DMA_TC_INT; + channel->irq_handler(i, cause, channel->data, + regs); + } else { + /* + * IRQ for an unregistered DMA channel + */ + printk(KERN_WARNING + "spurious IRQ for DMA channel %d\n", i); + } + if (tcint & i_bit) + __raw_writel(i_bit, DMAC_INT_TC_CLEAR); + if (eint & i_bit) + __raw_writel(i_bit, DMAC_INT_ERR_CLEAR); + } + } + return IRQ_HANDLED; +} + +static int __init pnx4008_dma_init(void) +{ + int ret, i; + + ret = request_irq(DMA_INT, dma_irq_handler, 0, "DMA", NULL); + if (ret) { + printk(KERN_CRIT "Wow! Can't register IRQ for DMA\n"); + goto out; + } + + ll_pool.count = 0x4000 / sizeof(struct pnx4008_dma_ll); + ll_pool.cur = ll_pool.vaddr = + dma_alloc_coherent(NULL, ll_pool.count * sizeof(struct pnx4008_dma_ll), + &ll_pool.dma_addr, GFP_KERNEL); + + if (!ll_pool.vaddr) { + ret = -ENOMEM; + free_irq(DMA_INT, NULL); + goto out; + } + + for (i = 0; i < ll_pool.count - 1; i++) { + void **addr = ll_pool.vaddr + i * sizeof(struct pnx4008_dma_ll); + *addr = (void *)addr + sizeof(struct pnx4008_dma_ll); + } + *(long *)(ll_pool.vaddr + + (ll_pool.count - 1) * sizeof(struct pnx4008_dma_ll)) = + (long)ll_pool.vaddr; + + __raw_writel(1, DMAC_CONFIG); + +out: + return ret; +} +arch_initcall(pnx4008_dma_init); diff --git a/arch/arm/mach-pnx4008/gpio.c b/arch/arm/mach-pnx4008/gpio.c new file mode 100644 index 000000000..1ab84ced7 --- /dev/null +++ b/arch/arm/mach-pnx4008/gpio.c @@ -0,0 +1,329 @@ +/* + * arch/arm/mach-pnx4008/gpio.c + * + * PNX4008 GPIO driver + * + * Author: Dmitry Chigirev <source@mvista.com> + * + * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips: + * Copyright (c) 2005 Koninklijke Philips Electronics N.V. + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <asm/semaphore.h> +#include <asm/io.h> +#include <asm/arch/platform.h> +#include <asm/arch/gpio.h> + +/* register definitions */ +#define PIO_VA_BASE IO_ADDRESS(PNX4008_PIO_BASE) + +#define PIO_INP_STATE (0x00U) +#define PIO_OUTP_SET (0x04U) +#define PIO_OUTP_CLR (0x08U) +#define PIO_OUTP_STATE (0x0CU) +#define PIO_DRV_SET (0x10U) +#define PIO_DRV_CLR (0x14U) +#define PIO_DRV_STATE (0x18U) +#define PIO_SDINP_STATE (0x1CU) +#define PIO_SDOUTP_SET (0x20U) +#define PIO_SDOUTP_CLR (0x24U) +#define PIO_MUX_SET (0x28U) +#define PIO_MUX_CLR (0x2CU) +#define PIO_MUX_STATE (0x30U) + +static inline void gpio_lock(void) +{ + local_irq_disable(); +} + +static inline void gpio_unlock(void) +{ + local_irq_enable(); +} + +/* Inline functions */ +static inline int gpio_read_bit(u32 reg, int gpio) +{ + u32 bit, val; + int ret = -EFAULT; + + if (gpio < 0) + goto out; + + bit = GPIO_BIT(gpio); + if (bit) { + val = __raw_readl(PIO_VA_BASE + reg); + ret = (val & bit) ? 1 : 0; + } +out: + return ret; +} + +static inline int gpio_set_bit(u32 reg, int gpio) +{ + u32 bit, val; + int ret = -EFAULT; + + if (gpio < 0) + goto out; + + bit = GPIO_BIT(gpio); + if (bit) { + val = __raw_readl(PIO_VA_BASE + reg); + val |= bit; + __raw_writel(val, PIO_VA_BASE + reg); + ret = 0; + } +out: + return ret; +} + +/* Very simple access control, bitmap for allocated/free */ +static unsigned long access_map[4]; +#define INP_INDEX 0 +#define OUTP_INDEX 1 +#define GPIO_INDEX 2 +#define MUX_INDEX 3 + +/*GPIO to Input Mapping */ +static short gpio_to_inp_map[32] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 24, -1 +}; + +/*GPIO to Mux Mapping */ +static short gpio_to_mux_map[32] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 0, 1, 4, 5, -1 +}; + +/*Output to Mux Mapping */ +static short outp_to_mux_map[32] = { + -1, -1, -1, 6, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 2, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 +}; + +int pnx4008_gpio_register_pin(unsigned short pin) +{ + unsigned long bit = GPIO_BIT(pin); + int ret = -EBUSY; /* Already in use */ + + gpio_lock(); + + if (GPIO_ISBID(pin)) { + if (access_map[GPIO_INDEX] & bit) + goto out; + access_map[GPIO_INDEX] |= bit; + + } else if (GPIO_ISRAM(pin)) { + if (access_map[GPIO_INDEX] & bit) + goto out; + access_map[GPIO_INDEX] |= bit; + + } else if (GPIO_ISMUX(pin)) { + if (access_map[MUX_INDEX] & bit) + goto out; + access_map[MUX_INDEX] |= bit; + + } else if (GPIO_ISOUT(pin)) { + if (access_map[OUTP_INDEX] & bit) + goto out; + access_map[OUTP_INDEX] |= bit; + + } else if (GPIO_ISIN(pin)) { + if (access_map[INP_INDEX] & bit) + goto out; + access_map[INP_INDEX] |= bit; + } else + goto out; + ret = 0; + +out: + gpio_unlock(); + return ret; +} + +EXPORT_SYMBOL(pnx4008_gpio_register_pin); + +int pnx4008_gpio_unregister_pin(unsigned short pin) +{ + unsigned long bit = GPIO_BIT(pin); + int ret = -EFAULT; /* Not registered */ + + gpio_lock(); + + if (GPIO_ISBID(pin)) { + if (~access_map[GPIO_INDEX] & bit) + goto out; + access_map[GPIO_INDEX] &= ~bit; + } else if (GPIO_ISRAM(pin)) { + if (~access_map[GPIO_INDEX] & bit) + goto out; + access_map[GPIO_INDEX] &= ~bit; + } else if (GPIO_ISMUX(pin)) { + if (~access_map[MUX_INDEX] & bit) + goto out; + access_map[MUX_INDEX] &= ~bit; + } else if (GPIO_ISOUT(pin)) { + if (~access_map[OUTP_INDEX] & bit) + goto out; + access_map[OUTP_INDEX] &= ~bit; + } else if (GPIO_ISIN(pin)) { + if (~access_map[INP_INDEX] & bit) + goto out; + access_map[INP_INDEX] &= ~bit; + } else + goto out; + ret = 0; + +out: + gpio_unlock(); + return ret; +} + +EXPORT_SYMBOL(pnx4008_gpio_unregister_pin); + +unsigned long pnx4008_gpio_read_pin(unsigned short pin) +{ + unsigned long ret = -EFAULT; + int gpio = GPIO_BIT_MASK(pin); + gpio_lock(); + if (GPIO_ISOUT(pin)) { + ret = gpio_read_bit(PIO_OUTP_STATE, gpio); + } else if (GPIO_ISRAM(pin)) { + if (gpio_read_bit(PIO_DRV_STATE, gpio) == 0) { + ret = gpio_read_bit(PIO_SDINP_STATE, gpio); + } + } else if (GPIO_ISBID(pin)) { + ret = gpio_read_bit(PIO_DRV_STATE, gpio); + if (ret > 0) + ret = gpio_read_bit(PIO_OUTP_STATE, gpio); + else if (ret == 0) + ret = + gpio_read_bit(PIO_INP_STATE, gpio_to_inp_map[gpio]); + } else if (GPIO_ISIN(pin)) { + ret = gpio_read_bit(PIO_INP_STATE, gpio); + } + gpio_unlock(); + return ret; +} + +EXPORT_SYMBOL(pnx4008_gpio_read_pin); + +/* Write Value to output */ +int pnx4008_gpio_write_pin(unsigned short pin, int output) +{ + int gpio = GPIO_BIT_MASK(pin); + int ret = -EFAULT; + + gpio_lock(); + if (GPIO_ISOUT(pin)) { + printk( "writing '%x' to '%x'\n", + gpio, output ? PIO_OUTP_SET : PIO_OUTP_CLR ); + ret = gpio_set_bit(output ? PIO_OUTP_SET : PIO_OUTP_CLR, gpio); + } else if (GPIO_ISRAM(pin)) { + if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0) + ret = gpio_set_bit(output ? PIO_SDOUTP_SET : + PIO_SDOUTP_CLR, gpio); + } else if (GPIO_ISBID(pin)) { + if (gpio_read_bit(PIO_DRV_STATE, gpio) > 0) + ret = gpio_set_bit(output ? PIO_OUTP_SET : + PIO_OUTP_CLR, gpio); + } + gpio_unlock(); + return ret; +} + +EXPORT_SYMBOL(pnx4008_gpio_write_pin); + +/* Value = 1 : Set GPIO pin as output */ +/* Value = 0 : Set GPIO pin as input */ +int pnx4008_gpio_set_pin_direction(unsigned short pin, int output) +{ + int gpio = GPIO_BIT_MASK(pin); + int ret = -EFAULT; + + gpio_lock(); + if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) { + ret = gpio_set_bit(output ? PIO_DRV_SET : PIO_DRV_CLR, gpio); + } + gpio_unlock(); + return ret; +} + +EXPORT_SYMBOL(pnx4008_gpio_set_pin_direction); + +/* Read GPIO pin direction: 0= pin used as input, 1= pin used as output*/ +int pnx4008_gpio_read_pin_direction(unsigned short pin) +{ + int gpio = GPIO_BIT_MASK(pin); + int ret = -EFAULT; + + gpio_lock(); + if (GPIO_ISBID(pin) || GPIO_ISRAM(pin)) { + ret = gpio_read_bit(PIO_DRV_STATE, gpio); + } + gpio_unlock(); + return ret; +} + +EXPORT_SYMBOL(pnx4008_gpio_read_pin_direction); + +/* Value = 1 : Set pin to muxed function */ +/* Value = 0 : Set pin as GPIO */ +int pnx4008_gpio_set_pin_mux(unsigned short pin, int output) +{ + int gpio = GPIO_BIT_MASK(pin); + int ret = -EFAULT; + + gpio_lock(); + if (GPIO_ISBID(pin)) { + ret = + gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, + gpio_to_mux_map[gpio]); + } else if (GPIO_ISOUT(pin)) { + ret = + gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, + outp_to_mux_map[gpio]); + } else if (GPIO_ISMUX(pin)) { + ret = gpio_set_bit(output ? PIO_MUX_SET : PIO_MUX_CLR, gpio); + } + gpio_unlock(); + return ret; +} + +EXPORT_SYMBOL(pnx4008_gpio_set_pin_mux); + +/* Read pin mux function: 0= pin used as GPIO, 1= pin used for muxed function*/ +int pnx4008_gpio_read_pin_mux(unsigned short pin) +{ + int gpio = GPIO_BIT_MASK(pin); + int ret = -EFAULT; + + gpio_lock(); + if (GPIO_ISBID(pin)) { + ret = gpio_read_bit(PIO_MUX_STATE, gpio_to_mux_map[gpio]); + } else if (GPIO_ISOUT(pin)) { + ret = gpio_read_bit(PIO_MUX_STATE, outp_to_mux_map[gpio]); + } else if (GPIO_ISMUX(pin)) { + ret = gpio_read_bit(PIO_MUX_STATE, gpio); + } + gpio_unlock(); + return ret; +} + +EXPORT_SYMBOL(pnx4008_gpio_read_pin_mux); diff --git a/arch/arm/mach-pnx4008/irq.c b/arch/arm/mach-pnx4008/irq.c new file mode 100644 index 000000000..3a4bcf3d9 --- /dev/null +++ b/arch/arm/mach-pnx4008/irq.c @@ -0,0 +1,119 @@ +/* + * arch/arm/mach-pnx4008/irq.c + * + * PNX4008 IRQ controller driver + * + * Author: Dmitry Chigirev <source@mvista.com> + * + * Based on reference code received from Philips: + * Copyright (C) 2003 Philips Semiconductors + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/mm.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/device.h> +#include <linux/irq.h> +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/pgtable.h> +#include <asm/page.h> +#include <asm/system.h> +#include <asm/mach/arch.h> +#include <asm/mach/irq.h> +#include <asm/mach/map.h> +#include <asm/arch/irq.h> + +static u8 pnx4008_irq_type[NR_IRQS] = PNX4008_IRQ_TYPES; + +static void pnx4008_mask_irq(unsigned int irq) +{ + __raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq)); /* mask interrupt */ +} + +static void pnx4008_unmask_irq(unsigned int irq) +{ + __raw_writel(__raw_readl(INTC_ER(irq)) | INTC_BIT(irq), INTC_ER(irq)); /* unmask interrupt */ +} + +static void pnx4008_mask_ack_irq(unsigned int irq) +{ + __raw_writel(__raw_readl(INTC_ER(irq)) & ~INTC_BIT(irq), INTC_ER(irq)); /* mask interrupt */ + __raw_writel(INTC_BIT(irq), INTC_SR(irq)); /* clear interrupt status */ +} + +static int pnx4008_set_irq_type(unsigned int irq, unsigned int type) +{ + switch (type) { + case IRQT_RISING: + __raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq)); /*edge sensitive */ + __raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq)); /*rising edge */ + set_irq_handler(irq, do_edge_IRQ); + break; + case IRQT_FALLING: + __raw_writel(__raw_readl(INTC_ATR(irq)) | INTC_BIT(irq), INTC_ATR(irq)); /*edge sensitive */ + __raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq)); /*falling edge */ + set_irq_handler(irq, do_edge_IRQ); + break; + case IRQT_LOW: + __raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq)); /*level sensitive */ + __raw_writel(__raw_readl(INTC_APR(irq)) & ~INTC_BIT(irq), INTC_APR(irq)); /*low level */ + set_irq_handler(irq, do_level_IRQ); + break; + case IRQT_HIGH: + __raw_writel(__raw_readl(INTC_ATR(irq)) & ~INTC_BIT(irq), INTC_ATR(irq)); /*level sensitive */ + __raw_writel(__raw_readl(INTC_APR(irq)) | INTC_BIT(irq), INTC_APR(irq)); /* high level */ + set_irq_handler(irq, do_level_IRQ); + break; + + /* IRQT_BOTHEDGE is not supported */ + default: + printk(KERN_ERR "PNX4008 IRQ: Unsupported irq type %d\n", type); + return -1; + } + return 0; +} + +static struct irqchip pnx4008_irq_chip = { + .ack = pnx4008_mask_ack_irq, + .mask = pnx4008_mask_irq, + .unmask = pnx4008_unmask_irq, + .set_type = pnx4008_set_irq_type, +}; + +void __init pnx4008_init_irq(void) +{ + unsigned int i; + + /* configure IRQ's */ + for (i = 0; i < NR_IRQS; i++) { + set_irq_flags(i, IRQF_VALID); + set_irq_chip(i, &pnx4008_irq_chip); + pnx4008_set_irq_type(i, pnx4008_irq_type[i]); + } + + /* configure and enable IRQ 0,1,30,31 (cascade interrupts) */ + pnx4008_set_irq_type(SUB1_IRQ_N, pnx4008_irq_type[SUB1_IRQ_N]); + pnx4008_set_irq_type(SUB2_IRQ_N, pnx4008_irq_type[SUB2_IRQ_N]); + pnx4008_set_irq_type(SUB1_FIQ_N, pnx4008_irq_type[SUB1_FIQ_N]); + pnx4008_set_irq_type(SUB2_FIQ_N, pnx4008_irq_type[SUB2_FIQ_N]); + + /* mask all others */ + __raw_writel((1 << SUB2_FIQ_N) | (1 << SUB1_FIQ_N) | + (1 << SUB2_IRQ_N) | (1 << SUB1_IRQ_N), + INTC_ER(MAIN_BASE_INT)); + __raw_writel(0, INTC_ER(SIC1_BASE_INT)); + __raw_writel(0, INTC_ER(SIC2_BASE_INT)); +} + diff --git a/arch/arm/mach-pnx4008/pm.c b/arch/arm/mach-pnx4008/pm.c new file mode 100644 index 000000000..3649cd3df --- /dev/null +++ b/arch/arm/mach-pnx4008/pm.c @@ -0,0 +1,184 @@ +/* + * arch/arm/mach-pnx4008/pm.c + * + * Power Management driver for PNX4008 + * + * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com> + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include <linux/pm.h> +#include <linux/rtc.h> +#include <linux/sched.h> +#include <linux/proc_fs.h> +#include <linux/pm.h> +#include <linux/delay.h> +#include <linux/clk.h> + +#include <asm/io.h> +#include <asm/mach-types.h> +#include <asm/cacheflush.h> +#include <asm/arch/pm.h> +#include <asm/arch/clock.h> + +#define SRAM_VA IO_ADDRESS(PNX4008_IRAM_BASE) + +static void *saved_sram; + +static struct clk *pll4_clk; + +static inline void pnx4008_standby(void) +{ + void (*pnx4008_cpu_standby_ptr) (void); + + local_irq_disable(); + local_fiq_disable(); + + clk_disable(pll4_clk); + + /*saving portion of SRAM to be used by suspend function. */ + memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_standby_sz); + + /*make sure SRAM copy gets physically written into SDRAM. + SDRAM will be placed into self-refresh during power down */ + flush_cache_all(); + + /*copy suspend function into SRAM */ + memcpy((void *)SRAM_VA, pnx4008_cpu_standby, pnx4008_cpu_standby_sz); + + /*do suspend */ + pnx4008_cpu_standby_ptr = (void *)SRAM_VA; + pnx4008_cpu_standby_ptr(); + + /*restoring portion of SRAM that was used by suspend function */ + memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_standby_sz); + + clk_enable(pll4_clk); + + local_fiq_enable(); + local_irq_enable(); +} + +static inline void pnx4008_suspend(void) +{ + void (*pnx4008_cpu_suspend_ptr) (void); + + local_irq_disable(); + local_fiq_disable(); + + clk_disable(pll4_clk); + + __raw_writel(0xffffffff, START_INT_RSR_REG(SE_PIN_BASE_INT)); + __raw_writel(0xffffffff, START_INT_RSR_REG(SE_INT_BASE_INT)); + + /*saving portion of SRAM to be used by suspend function. */ + memcpy(saved_sram, (void *)SRAM_VA, pnx4008_cpu_suspend_sz); + + /*make sure SRAM copy gets physically written into SDRAM. + SDRAM will be placed into self-refresh during power down */ + flush_cache_all(); + + /*copy suspend function into SRAM */ + memcpy((void *)SRAM_VA, pnx4008_cpu_suspend, pnx4008_cpu_suspend_sz); + + /*do suspend */ + pnx4008_cpu_suspend_ptr = (void *)SRAM_VA; + pnx4008_cpu_suspend_ptr(); + + /*restoring portion of SRAM that was used by suspend function */ + memcpy((void *)SRAM_VA, saved_sram, pnx4008_cpu_suspend_sz); + + clk_enable(pll4_clk); + + local_fiq_enable(); + local_irq_enable(); +} + +static int pnx4008_pm_enter(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_STANDBY: + pnx4008_standby(); + break; + case PM_SUSPEND_MEM: + pnx4008_suspend(); + break; + case PM_SUSPEND_DISK: + return -ENOTSUPP; + default: + return -EINVAL; + } + return 0; +} + +/* + * Called after processes are frozen, but before we shut down devices. + */ +static int pnx4008_pm_prepare(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_STANDBY: + case PM_SUSPEND_MEM: + break; + + case PM_SUSPEND_DISK: + return -ENOTSUPP; + break; + + default: + return -EINVAL; + break; + } + return 0; +} + +/* + * Called after devices are re-setup, but before processes are thawed. + */ +static int pnx4008_pm_finish(suspend_state_t state) +{ + return 0; +} + +/* + * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk. + */ +static struct pm_ops pnx4008_pm_ops = { + .prepare = pnx4008_pm_prepare, + .enter = pnx4008_pm_enter, + .finish = pnx4008_pm_finish, +}; + +static int __init pnx4008_pm_init(void) +{ + u32 sram_size_to_allocate; + + pll4_clk = clk_get(0, "ck_pll4"); + if (IS_ERR(pll4_clk)) { + printk(KERN_ERR + "PM Suspend cannot acquire ARM(PLL4) clock control\n"); + return PTR_ERR(pll4_clk); + } + + if (pnx4008_cpu_standby_sz > pnx4008_cpu_suspend_sz) + sram_size_to_allocate = pnx4008_cpu_standby_sz; + else + sram_size_to_allocate = pnx4008_cpu_suspend_sz; + + saved_sram = kmalloc(sram_size_to_allocate, GFP_ATOMIC); + if (!saved_sram) { + printk(KERN_ERR + "PM Suspend: cannot allocate memory to save portion of SRAM\n"); + clk_put(pll4_clk); + return -ENOMEM; + } + + pm_set_ops(&pnx4008_pm_ops); + return 0; +} + +late_initcall(pnx4008_pm_init); diff --git a/arch/arm/mach-pnx4008/serial.c b/arch/arm/mach-pnx4008/serial.c new file mode 100644 index 000000000..95a1b3f96 --- /dev/null +++ b/arch/arm/mach-pnx4008/serial.c @@ -0,0 +1,69 @@ +/* + * linux/arch/arm/mach-pnx4008/serial.c + * + * PNX4008 UART initialization + * + * Copyright: MontaVista Software Inc. (c) 2005 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/types.h> + +#include <asm/io.h> + +#include <asm/arch/platform.h> +#include <asm/hardware.h> + +#include <linux/serial_core.h> +#include <linux/serial_reg.h> +#include <asm/arch/gpio.h> + +#include <asm/arch/clock.h> + +#define UART_3 0 +#define UART_4 1 +#define UART_5 2 +#define UART_6 3 +#define UART_UNKNOWN (-1) + +#define UART3_BASE_VA IO_ADDRESS(PNX4008_UART3_BASE) +#define UART4_BASE_VA IO_ADDRESS(PNX4008_UART4_BASE) +#define UART5_BASE_VA IO_ADDRESS(PNX4008_UART5_BASE) +#define UART6_BASE_VA IO_ADDRESS(PNX4008_UART6_BASE) + +#define UART_FCR_OFFSET 8 +#define UART_FIFO_SIZE 64 + +void pnx4008_uart_init(void) +{ + u32 tmp; + int i = UART_FIFO_SIZE; + + __raw_writel(0xC1, UART5_BASE_VA + UART_FCR_OFFSET); + __raw_writel(0xC1, UART3_BASE_VA + UART_FCR_OFFSET); + + /* Send a NULL to fix the UART HW bug */ + __raw_writel(0x00, UART5_BASE_VA); + __raw_writel(0x00, UART3_BASE_VA); + + while (i--) { + tmp = __raw_readl(UART5_BASE_VA); + tmp = __raw_readl(UART3_BASE_VA); + } + __raw_writel(0, UART5_BASE_VA + UART_FCR_OFFSET); + __raw_writel(0, UART3_BASE_VA + UART_FCR_OFFSET); + + /* setup wakeup interrupt */ + start_int_set_rising_edge(SE_U3_RX_INT); + start_int_ack(SE_U3_RX_INT); + start_int_umask(SE_U3_RX_INT); + + start_int_set_rising_edge(SE_U5_RX_INT); + start_int_ack(SE_U5_RX_INT); + start_int_umask(SE_U5_RX_INT); +} + diff --git a/arch/arm/mach-pnx4008/sleep.S b/arch/arm/mach-pnx4008/sleep.S new file mode 100644 index 000000000..fea1e17a3 --- /dev/null +++ b/arch/arm/mach-pnx4008/sleep.S @@ -0,0 +1,195 @@ +/* + * linux/arch/arm/mach-pnx4008/sleep.S + * + * PNX4008 support for STOP mode and SDRAM self-refresh + * + * Authors: Dmitry Chigirev, Vitaly Wool <source@mvista.com> + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> +#include <asm/hardware.h> + +#define PWRMAN_VA_BASE IO_ADDRESS(PNX4008_PWRMAN_BASE) +#define PWR_CTRL_REG_OFFS 0x44 + +#define SDRAM_CFG_VA_BASE IO_ADDRESS(PNX4008_SDRAM_CFG_BASE) +#define MPMC_STATUS_REG_OFFS 0x4 + + .text + +ENTRY(pnx4008_cpu_suspend) + @this function should be entered in Direct run mode. + + @ save registers on stack + stmfd sp!, {r0 - r6, lr} + + @ setup Power Manager base address in r4 + @ and put it's value in r5 + mov r4, #(PWRMAN_VA_BASE & 0xff000000) + orr r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000) + orr r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00) + orr r4, r4, #(PWRMAN_VA_BASE & 0x000000ff) + ldr r5, [r4, #PWR_CTRL_REG_OFFS] + + @ setup SDRAM controller base address in r2 + @ and put it's value in r3 + mov r2, #(SDRAM_CFG_VA_BASE & 0xff000000) + orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000) + orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00) + orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff) + ldr r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround + + @ clear SDRAM self-refresh bit latch + and r5, r5, #(~(1 << 8)) + @ clear SDRAM self-refresh bit + and r5, r5, #(~(1 << 9)) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ do save current bit settings in r1 + mov r1, r5 + + @ set SDRAM self-refresh bit + orr r5, r5, #(1 << 9) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ set SDRAM self-refresh bit latch + orr r5, r5, #(1 << 8) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ clear SDRAM self-refresh bit latch + and r5, r5, #(~(1 << 8)) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ clear SDRAM self-refresh bit + and r5, r5, #(~(1 << 9)) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ wait for SDRAM to get into self-refresh mode +2: ldr r3, [r2, #MPMC_STATUS_REG_OFFS] + tst r3, #(1 << 2) + beq 2b + + @ to prepare SDRAM to get out of self-refresh mode after wakeup + orr r5, r5, #(1 << 7) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ do enter stop mode + orr r5, r5, #(1 << 0) + str r5, [r4, #PWR_CTRL_REG_OFFS] + nop + nop + nop + nop + nop + nop + nop + nop + nop + + @ sleeping now... + + @ coming out of STOP mode into Direct Run mode + @ clear STOP mode and SDRAM self-refresh bits + str r1, [r4, #PWR_CTRL_REG_OFFS] + + @ wait for SDRAM to get out self-refresh mode +3: ldr r3, [r2, #MPMC_STATUS_REG_OFFS] + tst r3, #5 + bne 3b + + @ restore regs and return + ldmfd sp!, {r0 - r6, pc} + +ENTRY(pnx4008_cpu_suspend_sz) + .word . - pnx4008_cpu_suspend + +ENTRY(pnx4008_cpu_standby) + @ save registers on stack + stmfd sp!, {r0 - r6, lr} + + @ setup Power Manager base address in r4 + @ and put it's value in r5 + mov r4, #(PWRMAN_VA_BASE & 0xff000000) + orr r4, r4, #(PWRMAN_VA_BASE & 0x00ff0000) + orr r4, r4, #(PWRMAN_VA_BASE & 0x0000ff00) + orr r4, r4, #(PWRMAN_VA_BASE & 0x000000ff) + ldr r5, [r4, #PWR_CTRL_REG_OFFS] + + @ setup SDRAM controller base address in r2 + @ and put it's value in r3 + mov r2, #(SDRAM_CFG_VA_BASE & 0xff000000) + orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x00ff0000) + orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x0000ff00) + orr r2, r2, #(SDRAM_CFG_VA_BASE & 0x000000ff) + ldr r3, [r2, #MPMC_STATUS_REG_OFFS] @extra read - HW bug workaround + + @ clear SDRAM self-refresh bit latch + and r5, r5, #(~(1 << 8)) + @ clear SDRAM self-refresh bit + and r5, r5, #(~(1 << 9)) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ do save current bit settings in r1 + mov r1, r5 + + @ set SDRAM self-refresh bit + orr r5, r5, #(1 << 9) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ set SDRAM self-refresh bit latch + orr r5, r5, #(1 << 8) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ clear SDRAM self-refresh bit latch + and r5, r5, #(~(1 << 8)) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ clear SDRAM self-refresh bit + and r5, r5, #(~(1 << 9)) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ wait for SDRAM to get into self-refresh mode +2: ldr r3, [r2, #MPMC_STATUS_REG_OFFS] + tst r3, #(1 << 2) + beq 2b + + @ set 'get out of self-refresh mode after wakeup' bit + orr r5, r5, #(1 << 7) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + mcr p15, 0, r0, c7, c0, 4 @ kinda sleeping now... + + @ set SDRAM self-refresh bit latch + orr r5, r5, #(1 << 8) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ clear SDRAM self-refresh bit latch + and r5, r5, #(~(1 << 8)) + str r5, [r4, #PWR_CTRL_REG_OFFS] + + @ wait for SDRAM to get out self-refresh mode +3: ldr r3, [r2, #MPMC_STATUS_REG_OFFS] + tst r3, #5 + bne 3b + + @ restore regs and return + ldmfd sp!, {r0 - r6, pc} + +ENTRY(pnx4008_cpu_standby_sz) + .word . - pnx4008_cpu_standby + +ENTRY(pnx4008_cache_clean_invalidate) + stmfd sp!, {r0 - r6, lr} +#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH + mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache +#else +1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate + bne 1b +#endif + ldmfd sp!, {r0 - r6, pc} diff --git a/arch/arm/mach-pnx4008/time.c b/arch/arm/mach-pnx4008/time.c new file mode 100644 index 000000000..b986065cd --- /dev/null +++ b/arch/arm/mach-pnx4008/time.c @@ -0,0 +1,138 @@ +/* + * arch/arm/mach-pnx4008/time.c + * + * PNX4008 Timers + * + * Authors: Vitaly Wool, Dmitry Chigirev, Grigory Tolstolytkin <source@mvista.com> + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <linux/spinlock.h> +#include <linux/module.h> +#include <linux/kallsyms.h> +#include <linux/time.h> +#include <linux/timex.h> +#include <linux/irq.h> + +#include <asm/system.h> +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/leds.h> +#include <asm/mach/time.h> +#include <asm/errno.h> + +/*! Note: all timers are UPCOUNTING */ + +/*! + * Returns number of us since last clock interrupt. Note that interrupts + * will have been disabled by do_gettimeoffset() + */ +static unsigned long pnx4008_gettimeoffset(void) +{ + u32 ticks_to_match = + __raw_readl(HSTIM_MATCH0) - __raw_readl(HSTIM_COUNTER); + u32 elapsed = LATCH - ticks_to_match; + return (elapsed * (tick_nsec / 1000)) / LATCH; +} + +/*! + * IRQ handler for the timer + */ +static irqreturn_t pnx4008_timer_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + if (__raw_readl(HSTIM_INT) & MATCH0_INT) { + + write_seqlock(&xtime_lock); + + do { + timer_tick(regs); + + /* + * this algorithm takes care of possible delay + * for this interrupt handling longer than a normal + * timer period + */ + __raw_writel(__raw_readl(HSTIM_MATCH0) + LATCH, + HSTIM_MATCH0); + __raw_writel(MATCH0_INT, HSTIM_INT); /* clear interrupt */ + + /* + * The goal is to keep incrementing HSTIM_MATCH0 + * register until HSTIM_MATCH0 indicates time after + * what HSTIM_COUNTER indicates. + */ + } while ((signed) + (__raw_readl(HSTIM_MATCH0) - + __raw_readl(HSTIM_COUNTER)) < 0); + + write_sequnlock(&xtime_lock); + } + + return IRQ_HANDLED; +} + +static struct irqaction pnx4008_timer_irq = { + .name = "PNX4008 Tick Timer", + .flags = IRQF_DISABLED | IRQF_TIMER, + .handler = pnx4008_timer_interrupt +}; + +/*! + * Set up timer and timer interrupt. + */ +static __init void pnx4008_setup_timer(void) +{ + __raw_writel(RESET_COUNT, MSTIM_CTRL); + while (__raw_readl(MSTIM_COUNTER)) ; /* wait for reset to complete. 100% guarantee event */ + __raw_writel(0, MSTIM_CTRL); /* stop the timer */ + __raw_writel(0, MSTIM_MCTRL); + + __raw_writel(RESET_COUNT, HSTIM_CTRL); + while (__raw_readl(HSTIM_COUNTER)) ; /* wait for reset to complete. 100% guarantee event */ + __raw_writel(0, HSTIM_CTRL); + __raw_writel(0, HSTIM_MCTRL); + __raw_writel(0, HSTIM_CCR); + __raw_writel(12, HSTIM_PMATCH); /* scale down to 1 MHZ */ + __raw_writel(LATCH, HSTIM_MATCH0); + __raw_writel(MR0_INT, HSTIM_MCTRL); + + setup_irq(HSTIMER_INT, &pnx4008_timer_irq); + + __raw_writel(COUNT_ENAB | DEBUG_EN, HSTIM_CTRL); /*start timer, stop when JTAG active */ +} + +/* Timer Clock Control in PM register */ +#define TIMCLK_CTRL_REG IO_ADDRESS((PNX4008_PWRMAN_BASE + 0xBC)) +#define WATCHDOG_CLK_EN 1 +#define TIMER_CLK_EN 2 /* HS and MS timers? */ + +static u32 timclk_ctrl_reg_save; + +void pnx4008_timer_suspend(void) +{ + timclk_ctrl_reg_save = __raw_readl(TIMCLK_CTRL_REG); + __raw_writel(0, TIMCLK_CTRL_REG); /* disable timers */ +} + +void pnx4008_timer_resume(void) +{ + __raw_writel(timclk_ctrl_reg_save, TIMCLK_CTRL_REG); /* enable timers */ +} + +struct sys_timer pnx4008_timer = { + .init = pnx4008_setup_timer, + .offset = pnx4008_gettimeoffset, + .suspend = pnx4008_timer_suspend, + .resume = pnx4008_timer_resume, +}; + diff --git a/arch/arm/mach-pxa/leds-trizeps4.c b/arch/arm/mach-pxa/leds-trizeps4.c new file mode 100644 index 000000000..2271d20ff --- /dev/null +++ b/arch/arm/mach-pxa/leds-trizeps4.c @@ -0,0 +1,133 @@ +/* + * linux/arch/arm/mach-pxa/leds-trizeps4.c + * + * Author: Jürgen Schindele + * Created: 20 02, 2006 + * Copyright: Jürgen Schindele + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> + +#include <asm/hardware.h> +#include <asm/system.h> +#include <asm/types.h> +#include <asm/leds.h> + +#include <asm/arch/pxa-regs.h> +#include <asm/arch/trizeps4.h> + +#include "leds.h" + +#define LED_STATE_ENABLED 1 +#define LED_STATE_CLAIMED 2 + +#define SYS_BUSY 0x01 +#define HEARTBEAT 0x02 +#define BLINK 0x04 + +static unsigned int led_state; +static unsigned int hw_led_state; + +void trizeps4_leds_event(led_event_t evt) +{ + unsigned long flags; + + local_irq_save(flags); + + switch (evt) { + case led_start: + hw_led_state = 0; + pxa_gpio_mode( GPIO_SYS_BUSY_LED | GPIO_OUT); /* LED1 */ + pxa_gpio_mode( GPIO_HEARTBEAT_LED | GPIO_OUT); /* LED2 */ + led_state = LED_STATE_ENABLED; + break; + + case led_stop: + led_state &= ~LED_STATE_ENABLED; + break; + + case led_claim: + led_state |= LED_STATE_CLAIMED; + hw_led_state = 0; + break; + + case led_release: + led_state &= ~LED_STATE_CLAIMED; + hw_led_state = 0; + break; + +#ifdef CONFIG_LEDS_TIMER + case led_timer: + hw_led_state ^= HEARTBEAT; + break; +#endif + +#ifdef CONFIG_LEDS_CPU + case led_idle_start: + hw_led_state &= ~SYS_BUSY; + break; + + case led_idle_end: + hw_led_state |= SYS_BUSY; + break; +#endif + + case led_halted: + break; + + case led_green_on: + hw_led_state |= BLINK; + break; + + case led_green_off: + hw_led_state &= ~BLINK; + break; + + case led_amber_on: + break; + + case led_amber_off: + break; + + case led_red_on: + break; + + case led_red_off: + break; + + default: + break; + } + + if (led_state & LED_STATE_ENABLED) { + switch (hw_led_state) { + case 0: + GPSR(GPIO_SYS_BUSY_LED) |= GPIO_bit(GPIO_SYS_BUSY_LED); + GPSR(GPIO_HEARTBEAT_LED) |= GPIO_bit(GPIO_HEARTBEAT_LED); + break; + case 1: + GPCR(GPIO_SYS_BUSY_LED) |= GPIO_bit(GPIO_SYS_BUSY_LED); + GPSR(GPIO_HEARTBEAT_LED) |= GPIO_bit(GPIO_HEARTBEAT_LED); + break; + case 2: + GPSR(GPIO_SYS_BUSY_LED) |= GPIO_bit(GPIO_SYS_BUSY_LED); + GPCR(GPIO_HEARTBEAT_LED) |= GPIO_bit(GPIO_HEARTBEAT_LED); + break; + case 3: + GPCR(GPIO_SYS_BUSY_LED) |= GPIO_bit(GPIO_SYS_BUSY_LED); + GPCR(GPIO_HEARTBEAT_LED) |= GPIO_bit(GPIO_HEARTBEAT_LED); + break; + } + } + else { + /* turn all off */ + GPSR(GPIO_SYS_BUSY_LED) |= GPIO_bit(GPIO_SYS_BUSY_LED); + GPSR(GPIO_HEARTBEAT_LED) |= GPIO_bit(GPIO_HEARTBEAT_LED); + } + + local_irq_restore(flags); +} diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c new file mode 100644 index 000000000..7c3007df1 --- /dev/null +++ b/arch/arm/mach-pxa/trizeps4.c @@ -0,0 +1,473 @@ +/* + * linux/arch/arm/mach-pxa/trizeps4.c + * + * Support for the Keith und Koep Trizeps4 Module Platform. + * + * Author: Jürgen Schindele + * Created: 20 02, 2006 + * Copyright: Jürgen Schindele + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/sysdev.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <linux/bitops.h> +#include <linux/fb.h> +#include <linux/ioport.h> +#include <linux/delay.h> +#include <linux/serial_8250.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/partitions.h> + +#include <asm/types.h> +#include <asm/setup.h> +#include <asm/memory.h> +#include <asm/mach-types.h> +#include <asm/hardware.h> +#include <asm/irq.h> +#include <asm/sizes.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> +#include <asm/mach/flash.h> + +#include <asm/arch/pxa-regs.h> +#include <asm/arch/trizeps4.h> +#include <asm/arch/audio.h> +#include <asm/arch/pxafb.h> +#include <asm/arch/mmc.h> +#include <asm/arch/irda.h> +#include <asm/arch/ohci.h> + +#include "generic.h" + +/******************************************************************************************** + * ONBOARD FLASH + ********************************************************************************************/ +static struct mtd_partition trizeps4_partitions[] = { + { + .name = "Bootloader", + .size = 0x00040000, + .offset = 0, + .mask_flags = MTD_WRITEABLE /* force read-only */ + },{ + .name = "Kernel", + .size = 0x00400000, + .offset = 0x00040000 + },{ + .name = "Filesystem", + .size = MTDPART_SIZ_FULL, + .offset = 0x00440000 + } +}; + +static struct flash_platform_data trizeps4_flash_data[] = { + { + .map_name = "cfi_probe", + .parts = trizeps4_partitions, + .nr_parts = ARRAY_SIZE(trizeps4_partitions) + } +}; + +static struct resource flash_resource = { + .start = PXA_CS0_PHYS, + .end = PXA_CS0_PHYS + SZ_64M - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device flash_device = { + .name = "pxa2xx-flash", + .id = 0, + .dev = { + .platform_data = &trizeps4_flash_data, + }, + .resource = &flash_resource, + .num_resources = 1, +}; + +/******************************************************************************************** + * DAVICOM DM9000 Ethernet + ********************************************************************************************/ +static struct resource dm9000_resources[] = { + [0] = { + .start = TRIZEPS4_ETH_PHYS+0x300, + .end = TRIZEPS4_ETH_PHYS+0x400-1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = TRIZEPS4_ETH_PHYS+0x8300, + .end = TRIZEPS4_ETH_PHYS+0x8400-1, + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = TRIZEPS4_ETH_IRQ, + .end = TRIZEPS4_ETH_IRQ, + .flags = (IORESOURCE_IRQ | IRQT_RISING), + }, +}; + +static struct platform_device dm9000_device = { + .name = "dm9000", + .id = -1, + .num_resources = ARRAY_SIZE(dm9000_resources), + .resource = dm9000_resources, +}; + +/******************************************************************************************** + * PXA270 serial ports + ********************************************************************************************/ +static struct plat_serial8250_port tri_serial_ports[] = { +#ifdef CONFIG_SERIAL_PXA + /* this uses the own PXA driver */ + { + 0, + }, +#else + /* this uses the generic 8520 driver */ + [0] = { + .membase = (void *)&FFUART, + .irq = IRQ_FFUART, + .flags = UPF_BOOT_AUTOCONF, + .iotype = UPIO_MEM32, + .regshift = 2, + .uartclk = (921600*16), + }, + [1] = { + .membase = (void *)&BTUART, + .irq = IRQ_BTUART, + .flags = UPF_BOOT_AUTOCONF, + .iotype = UPIO_MEM32, + .regshift = 2, + .uartclk = (921600*16), + }, + { + 0, + }, +#endif +}; + +static struct platform_device uart_devices = { + .name = "serial8250", + .id = 0, + .dev = { + .platform_data = tri_serial_ports, + }, + .num_resources = 0, + .resource = NULL, +}; + +/******************************************************************************************** + * PXA270 ac97 sound codec + ********************************************************************************************/ +static struct platform_device ac97_audio_device = { + .name = "pxa2xx-ac97", + .id = -1, +}; + +static struct platform_device * trizeps4_devices[] __initdata = { + &flash_device, + &uart_devices, + &dm9000_device, + &ac97_audio_device, +}; + +#ifdef CONFIG_MACH_TRIZEPS4_CONXS +static short trizeps_conxs_bcr; + +/* PCCARD power switching supports only 3,3V */ +void board_pcmcia_power(int power) +{ + if (power) { + /* switch power on, put in reset and enable buffers */ + trizeps_conxs_bcr |= power; + trizeps_conxs_bcr |= ConXS_BCR_CF_RESET; + trizeps_conxs_bcr &= ~(ConXS_BCR_CF_BUF_EN); + ConXS_BCR = trizeps_conxs_bcr; + /* wait a little */ + udelay(2000); + /* take reset away */ + trizeps_conxs_bcr &= ~(ConXS_BCR_CF_RESET); + ConXS_BCR = trizeps_conxs_bcr; + udelay(2000); + } else { + /* put in reset */ + trizeps_conxs_bcr |= ConXS_BCR_CF_RESET; + ConXS_BCR = trizeps_conxs_bcr; + udelay(1000); + /* switch power off */ + trizeps_conxs_bcr &= ~(0xf); + ConXS_BCR = trizeps_conxs_bcr; + + } + pr_debug("%s: o%s 0x%x\n", __FUNCTION__, power ? "n": "ff", trizeps_conxs_bcr); +} + +/* backlight power switching for LCD panel */ +static void board_backlight_power(int on) +{ + if (on) { + trizeps_conxs_bcr |= ConXS_BCR_L_DISP; + } else { + trizeps_conxs_bcr &= ~ConXS_BCR_L_DISP; + } + pr_debug("%s: o%s 0x%x\n", __FUNCTION__, on ? "n" : "ff", trizeps_conxs_bcr); + ConXS_BCR = trizeps_conxs_bcr; +} + +/* Powersupply for MMC/SD cardslot */ +static void board_mci_power(struct device *dev, unsigned int vdd) +{ + struct pxamci_platform_data* p_d = dev->platform_data; + + if (( 1 << vdd) & p_d->ocr_mask) { + pr_debug("%s: on\n", __FUNCTION__); + /* FIXME fill in values here */ + } else { + pr_debug("%s: off\n", __FUNCTION__); + /* FIXME fill in values here */ + } +} + +static short trizeps_conxs_ircr; + +/* Switch modes and Power for IRDA receiver */ +static void board_irda_mode(struct device *dev, int mode) +{ + unsigned long flags; + + local_irq_save(flags); + if (mode & IR_SIRMODE) { + /* Slow mode */ + trizeps_conxs_ircr &= ~ConXS_IRCR_MODE; + } else if (mode & IR_FIRMODE) { + /* Fast mode */ + trizeps_conxs_ircr |= ConXS_IRCR_MODE; + } + if (mode & IR_OFF) { + trizeps_conxs_ircr |= ConXS_IRCR_SD; + } else { + trizeps_conxs_ircr &= ~ConXS_IRCR_SD; + } + /* FIXME write values to register */ + local_irq_restore(flags); +} + +#else +/* for other baseboards define dummies */ +void board_pcmcia_power(int power) {;} +#define board_backlight_power NULL +#define board_mci_power NULL +#define board_irda_mode NULL + +#endif /* CONFIG_MACH_TRIZEPS4_CONXS */ +EXPORT_SYMBOL(board_pcmcia_power); + +static int trizeps4_mci_init(struct device *dev, irqreturn_t (*mci_detect_int)(int, void *, struct pt_regs *), void *data) +{ + int err; + /* setup GPIO for PXA27x MMC controller */ + pxa_gpio_mode(GPIO32_MMCCLK_MD); + pxa_gpio_mode(GPIO112_MMCCMD_MD); + pxa_gpio_mode(GPIO92_MMCDAT0_MD); + pxa_gpio_mode(GPIO109_MMCDAT1_MD); + pxa_gpio_mode(GPIO110_MMCDAT2_MD); + pxa_gpio_mode(GPIO111_MMCDAT3_MD); + + pxa_gpio_mode(GPIO_MMC_DET | GPIO_IN); + + err = request_irq(TRIZEPS4_MMC_IRQ, mci_detect_int, + IRQF_DISABLED | IRQF_TRIGGER_RISING, + "MMC card detect", data); + if (err) { + printk(KERN_ERR "trizeps4_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); + return -1; + } + return 0; +} + +static void trizeps4_mci_exit(struct device *dev, void *data) +{ + free_irq(TRIZEPS4_MMC_IRQ, data); +} + +static struct pxamci_platform_data trizeps4_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, + .init = trizeps4_mci_init, + .exit = trizeps4_mci_exit, + .setpower = board_mci_power, +}; + +static struct pxaficp_platform_data trizeps4_ficp_platform_data = { + .transceiver_cap = IR_SIRMODE | IR_FIRMODE | IR_OFF, + .transceiver_mode = board_irda_mode, +}; + +static int trizeps4_ohci_init(struct device *dev) +{ + /* setup Port1 GPIO pin. */ + pxa_gpio_mode( 88 | GPIO_ALT_FN_1_IN); /* USBHPWR1 */ + pxa_gpio_mode( 89 | GPIO_ALT_FN_2_OUT); /* USBHPEN1 */ + + /* Set the Power Control Polarity Low and Power Sense + Polarity Low to active low. */ + UHCHR = (UHCHR | UHCHR_PCPL | UHCHR_PSPL) & + ~(UHCHR_SSEP1 | UHCHR_SSEP2 | UHCHR_SSEP3 | UHCHR_SSE); + + return 0; +} + +static void trizeps4_ohci_exit(struct device *dev) +{ + ; +} + +static struct pxaohci_platform_data trizeps4_ohci_platform_data = { + .port_mode = PMM_PERPORT_MODE, + .init = trizeps4_ohci_init, + .exit = trizeps4_ohci_exit, +}; + +static struct map_desc trizeps4_io_desc[] __initdata = { + { /* ConXS CFSR */ + .virtual = TRIZEPS4_CFSR_VIRT, + .pfn = __phys_to_pfn(TRIZEPS4_CFSR_PHYS), + .length = 0x00001000, + .type = MT_DEVICE + }, + { /* ConXS BCR */ + .virtual = TRIZEPS4_BOCR_VIRT, + .pfn = __phys_to_pfn(TRIZEPS4_BOCR_PHYS), + .length = 0x00001000, + .type = MT_DEVICE + }, + { /* ConXS IRCR */ + .virtual = TRIZEPS4_IRCR_VIRT, + .pfn = __phys_to_pfn(TRIZEPS4_IRCR_PHYS), + .length = 0x00001000, + .type = MT_DEVICE + }, + { /* ConXS DCR */ + .virtual = TRIZEPS4_DICR_VIRT, + .pfn = __phys_to_pfn(TRIZEPS4_DICR_PHYS), + .length = 0x00001000, + .type = MT_DEVICE + }, + { /* ConXS UPSR */ + .virtual = TRIZEPS4_UPSR_VIRT, + .pfn = __phys_to_pfn(TRIZEPS4_UPSR_PHYS), + .length = 0x00001000, + .type = MT_DEVICE + } +}; + +static struct pxafb_mach_info sharp_lcd __initdata = { + .pixclock = 78000, + .xres = 640, + .yres = 480, + .bpp = 8, + .hsync_len = 4, + .left_margin = 4, + .right_margin = 4, + .vsync_len = 2, + .upper_margin = 0, + .lower_margin = 0, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .cmap_greyscale = 0, + .cmap_inverse = 0, + .cmap_static = 0, + .lccr0 = LCCR0_Color | LCCR0_Pas | LCCR0_Dual, + .lccr3 = 0x0340ff02, + .pxafb_backlight_power = board_backlight_power, +}; + +static void __init trizeps4_fixup(struct machine_desc *desc, struct tag *tags, char **cmdline, struct meminfo *mi) +{ +} + +static void __init trizeps4_init(void) +{ + platform_add_devices(trizeps4_devices, ARRAY_SIZE(trizeps4_devices)); + + set_pxa_fb_info(&sharp_lcd); + + pxa_set_mci_info(&trizeps4_mci_platform_data); + pxa_set_ficp_info(&trizeps4_ficp_platform_data); + pxa_set_ohci_info(&trizeps4_ohci_platform_data); +} + +static void __init trizeps4_map_io(void) +{ + pxa_map_io(); + iotable_init(trizeps4_io_desc, ARRAY_SIZE(trizeps4_io_desc)); + + /* for DiskOnChip */ + pxa_gpio_mode(GPIO15_nCS_1_MD); + + /* for off-module PIC on ConXS board */ + pxa_gpio_mode(GPIO_PIC | GPIO_IN); + + /* UCB1400 irq */ + pxa_gpio_mode(GPIO_UCB1400 | GPIO_IN); + + /* for DM9000 LAN */ + pxa_gpio_mode(GPIO78_nCS_2_MD); + pxa_gpio_mode(GPIO_DM9000 | GPIO_IN); + + /* for PCMCIA device */ + pxa_gpio_mode(GPIO_PCD | GPIO_IN); + pxa_gpio_mode(GPIO_PRDY | GPIO_IN); + + /* for I2C adapter */ + pxa_gpio_mode(GPIO117_I2CSCL_MD); + pxa_gpio_mode(GPIO118_I2CSDA_MD); + + /* MMC_DET s.o. */ + pxa_gpio_mode(GPIO_MMC_DET | GPIO_IN); + + /* whats that for ??? */ + pxa_gpio_mode(GPIO79_nCS_3_MD); + + pxa_gpio_mode( GPIO_SYS_BUSY_LED | GPIO_OUT); /* LED1 */ + pxa_gpio_mode( GPIO_HEARTBEAT_LED | GPIO_OUT); /* LED2 */ + +#ifdef CONFIG_MACH_TRIZEPS4_CONXS +#ifdef CONFIG_IDE_PXA_CF + /* if boot direct from compact flash dont disable power */ + trizeps_conxs_bcr = 0x0009; +#else + /* this is the reset value */ + trizeps_conxs_bcr = 0x00A0; +#endif + ConXS_BCR = trizeps_conxs_bcr; +#endif + + PWER = 0x00000002; + PFER = 0x00000000; + PRER = 0x00000002; + PGSR0 = 0x0158C000; + PGSR1 = 0x00FF0080; + PGSR2 = 0x0001C004; + /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */ + PCFR |= PCFR_OPDE; +} + +MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module") + /* MAINTAINER("Jürgen Schindele") */ + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = TRIZEPS4_SDRAM_BASE + 0x100, + .fixup = trizeps4_fixup, + .init_machine = trizeps4_init, + .map_io = trizeps4_map_io, + .init_irq = pxa_init_irq, + .timer = &pxa_timer, +MACHINE_END + diff --git a/arch/arm/mach-s3c2410/mach-smdk2413.c b/arch/arm/mach-s3c2410/mach-smdk2413.c new file mode 100644 index 000000000..3a4ca7f6f --- /dev/null +++ b/arch/arm/mach-s3c2410/mach-smdk2413.c @@ -0,0 +1,139 @@ +/* linux/arch/arm/mach-s3c2410/mach-smdk2413.c + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * Thanks to Dimity Andric (TomTom) and Steven Ryu (Samsung) for the + * loans of SMDK2413 to work with. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/platform_device.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <asm/hardware.h> +#include <asm/hardware/iomd.h> +#include <asm/setup.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/mach-types.h> + +//#include <asm/debug-ll.h> +#include <asm/arch/regs-serial.h> +#include <asm/arch/regs-gpio.h> +#include <asm/arch/regs-lcd.h> + +#include <asm/arch/idle.h> +#include <asm/arch/fb.h> + +#include "s3c2410.h" +#include "s3c2412.h" +#include "clock.h" +#include "devs.h" +#include "cpu.h" + +#include "common-smdk.h" + +static struct map_desc smdk2413_iodesc[] __initdata = { +}; + +static struct s3c2410_uartcfg smdk2413_uartcfgs[] __initdata = { + [0] = { + .hwport = 0, + .flags = 0, + .ucon = 0x3c5, + .ulcon = 0x03, + .ufcon = 0x51, + }, + [1] = { + .hwport = 1, + .flags = 0, + .ucon = 0x3c5, + .ulcon = 0x03, + .ufcon = 0x51, + }, + /* IR port */ + [2] = { + .hwport = 2, + .flags = 0, + .ucon = 0x3c5, + .ulcon = 0x43, + .ufcon = 0x51, + } +}; + +static struct platform_device *smdk2413_devices[] __initdata = { + &s3c_device_usb, + //&s3c_device_lcd, + &s3c_device_wdt, + &s3c_device_i2c, + &s3c_device_iis, +}; + +static struct s3c24xx_board smdk2413_board __initdata = { + .devices = smdk2413_devices, + .devices_count = ARRAY_SIZE(smdk2413_devices) +}; + +static void __init smdk2413_fixup(struct machine_desc *desc, + struct tag *tags, char **cmdline, + struct meminfo *mi) +{ + if (tags != phys_to_virt(S3C2410_SDRAM_PA + 0x100)) { + mi->nr_banks=1; + mi->bank[0].start = 0x30000000; + mi->bank[0].size = SZ_64M; + mi->bank[0].node = 0; + } +} + +static void __init smdk2413_map_io(void) +{ + s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc)); + s3c24xx_init_clocks(12000000); + s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs)); + s3c24xx_set_board(&smdk2413_board); +} + +static void __init smdk2413_machine_init(void) +{ + smdk_machine_init(); +} + +MACHINE_START(S3C2413, "S3C2413") + /* Maintainer: Ben Dooks <ben@fluff.org> */ + .phys_io = S3C2410_PA_UART, + .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, + .boot_params = S3C2410_SDRAM_PA + 0x100, + + .fixup = smdk2413_fixup, + .init_irq = s3c24xx_init_irq, + .map_io = smdk2413_map_io, + .init_machine = smdk2413_machine_init, + .timer = &s3c24xx_timer, +MACHINE_END + +MACHINE_START(SMDK2413, "SMDK2413") + /* Maintainer: Ben Dooks <ben@fluff.org> */ + .phys_io = S3C2410_PA_UART, + .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, + .boot_params = S3C2410_SDRAM_PA + 0x100, + + .fixup = smdk2413_fixup, + .init_irq = s3c24xx_init_irq, + .map_io = smdk2413_map_io, + .init_machine = smdk2413_machine_init, + .timer = &s3c24xx_timer, +MACHINE_END diff --git a/arch/arm/mach-s3c2410/s3c2410-clock.c b/arch/arm/mach-s3c2410/s3c2410-clock.c new file mode 100644 index 000000000..997186633 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2410-clock.c @@ -0,0 +1,271 @@ +/* linux/arch/arm/mach-s3c2410/clock.c + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * S3C2410,S3C2440,S3C2442 Clock control support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/sysdev.h> +#include <linux/clk.h> +#include <linux/mutex.h> +#include <linux/delay.h> + +#include <asm/hardware.h> +#include <asm/io.h> + +#include <asm/arch/regs-clock.h> +#include <asm/arch/regs-gpio.h> + +#include "clock.h" +#include "cpu.h" + +int s3c2410_clkcon_enable(struct clk *clk, int enable) +{ + unsigned int clocks = clk->ctrlbit; + unsigned long clkcon; + + clkcon = __raw_readl(S3C2410_CLKCON); + + if (enable) + clkcon |= clocks; + else + clkcon &= ~clocks; + + /* ensure none of the special function bits set */ + clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER); + + __raw_writel(clkcon, S3C2410_CLKCON); + + return 0; +} + +static int s3c2410_upll_enable(struct clk *clk, int enable) +{ + unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); + unsigned long orig = clkslow; + + if (enable) + clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF; + else + clkslow |= S3C2410_CLKSLOW_UCLK_OFF; + + __raw_writel(clkslow, S3C2410_CLKSLOW); + + /* if we started the UPLL, then allow to settle */ + + if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF)) + udelay(200); + + return 0; +} + +/* standard clock definitions */ + +static struct clk init_clocks_disable[] = { + { + .name = "nand", + .id = -1, + .parent = &clk_h, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_NAND, + }, { + .name = "sdi", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_SDI, + }, { + .name = "adc", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_ADC, + }, { + .name = "i2c", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_IIC, + }, { + .name = "iis", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_IIS, + }, { + .name = "spi", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_SPI, + } +}; + +static struct clk init_clocks[] = { + { + .name = "lcd", + .id = -1, + .parent = &clk_h, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_LCDC, + }, { + .name = "gpio", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_GPIO, + }, { + .name = "usb-host", + .id = -1, + .parent = &clk_h, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_USBH, + }, { + .name = "usb-device", + .id = -1, + .parent = &clk_h, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_USBD, + }, { + .name = "timers", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_PWMT, + }, { + .name = "uart", + .id = 0, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_UART0, + }, { + .name = "uart", + .id = 1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_UART1, + }, { + .name = "uart", + .id = 2, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_UART2, + }, { + .name = "rtc", + .id = -1, + .parent = &clk_p, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2410_CLKCON_RTC, + }, { + .name = "watchdog", + .id = -1, + .parent = &clk_p, + .ctrlbit = 0, + }, { + .name = "usb-bus-host", + .id = -1, + .parent = &clk_usb_bus, + }, { + .name = "usb-bus-gadget", + .id = -1, + .parent = &clk_usb_bus, + }, +}; + +/* s3c2410_baseclk_add() + * + * Add all the clocks used by the s3c2410 or compatible CPUs + * such as the S3C2440 and S3C2442. + * + * We cannot use a system device as we are needed before any + * of the init-calls that initialise the devices are actually + * done. +*/ + +int __init s3c2410_baseclk_add(void) +{ + unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); + unsigned long clkcon = __raw_readl(S3C2410_CLKCON); + struct clk *clkp; + struct clk *xtal; + int ret; + int ptr; + + clk_upll.enable = s3c2410_upll_enable; + + if (s3c24xx_register_clock(&clk_usb_bus) < 0) + printk(KERN_ERR "failed to register usb bus clock\n"); + + /* register clocks from clock array */ + + clkp = init_clocks; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { + /* ensure that we note the clock state */ + + clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0; + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + } + + /* We must be careful disabling the clocks we are not intending to + * be using at boot time, as subsytems such as the LCD which do + * their own DMA requests to the bus can cause the system to lockup + * if they where in the middle of requesting bus access. + * + * Disabling the LCD clock if the LCD is active is very dangerous, + * and therefore the bootloader should be careful to not enable + * the LCD clock if it is not needed. + */ + + /* install (and disable) the clocks we do not need immediately */ + + clkp = init_clocks_disable; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + + s3c2410_clkcon_enable(clkp, 0); + } + + /* show the clock-slow value */ + + xtal = clk_get(NULL, "xtal"); + + printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n", + print_mhz(clk_get_rate(xtal) / + ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))), + (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast", + (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on", + (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on"); + + return 0; +} diff --git a/arch/arm/mach-s3c2410/s3c2412-clock.c b/arch/arm/mach-s3c2410/s3c2412-clock.c new file mode 100644 index 000000000..c95ed3e18 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2412-clock.c @@ -0,0 +1,711 @@ +/* linux/arch/arm/mach-s3c2410/s3c2412-clock.c + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * S3C2412,S3C2413 Clock control support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/sysdev.h> +#include <linux/clk.h> +#include <linux/mutex.h> +#include <linux/delay.h> + +#include <asm/hardware.h> +#include <asm/io.h> + +#include <asm/arch/regs-clock.h> +#include <asm/arch/regs-gpio.h> + +#include "clock.h" +#include "cpu.h" + +/* We currently have to assume that the system is running + * from the XTPll input, and that all ***REFCLKs are being + * fed from it, as we cannot read the state of OM[4] from + * software. + * + * It would be possible for each board initialisation to + * set the correct muxing at initialisation +*/ + +int s3c2412_clkcon_enable(struct clk *clk, int enable) +{ + unsigned int clocks = clk->ctrlbit; + unsigned long clkcon; + + clkcon = __raw_readl(S3C2410_CLKCON); + + if (enable) + clkcon |= clocks; + else + clkcon &= ~clocks; + + __raw_writel(clkcon, S3C2410_CLKCON); + + return 0; +} + +static int s3c2412_upll_enable(struct clk *clk, int enable) +{ + unsigned long upllcon = __raw_readl(S3C2410_UPLLCON); + unsigned long orig = upllcon; + + if (!enable) + upllcon |= S3C2412_PLLCON_OFF; + else + upllcon &= ~S3C2412_PLLCON_OFF; + + __raw_writel(upllcon, S3C2410_UPLLCON); + + /* allow ~150uS for the PLL to settle and lock */ + + if (enable && (orig & S3C2412_PLLCON_OFF)) + udelay(150); + + return 0; +} + +/* clock selections */ + +/* CPU EXTCLK input */ +static struct clk clk_ext = { + .name = "extclk", + .id = -1, +}; + +static struct clk clk_erefclk = { + .name = "erefclk", + .id = -1, +}; + +static struct clk clk_urefclk = { + .name = "urefclk", + .id = -1, +}; + +static int s3c2412_setparent_usysclk(struct clk *clk, struct clk *parent) +{ + unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); + + if (parent == &clk_urefclk) + clksrc &= ~S3C2412_CLKSRC_USYSCLK_UPLL; + else if (parent == &clk_upll) + clksrc |= S3C2412_CLKSRC_USYSCLK_UPLL; + else + return -EINVAL; + + clk->parent = parent; + + __raw_writel(clksrc, S3C2412_CLKSRC); + return 0; +} + +static struct clk clk_usysclk = { + .name = "usysclk", + .id = -1, + .parent = &clk_xtal, + .set_parent = s3c2412_setparent_usysclk, +}; + +static struct clk clk_mrefclk = { + .name = "mrefclk", + .parent = &clk_xtal, + .id = -1, +}; + +static struct clk clk_mdivclk = { + .name = "mdivclk", + .parent = &clk_xtal, + .id = -1, +}; + +static int s3c2412_setparent_usbsrc(struct clk *clk, struct clk *parent) +{ + unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); + + if (parent == &clk_usysclk) + clksrc &= ~S3C2412_CLKSRC_USBCLK_HCLK; + else if (parent == &clk_h) + clksrc |= S3C2412_CLKSRC_USBCLK_HCLK; + else + return -EINVAL; + + clk->parent = parent; + + __raw_writel(clksrc, S3C2412_CLKSRC); + return 0; +} + +static unsigned long s3c2412_roundrate_usbsrc(struct clk *clk, + unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + int div; + + if (rate > parent_rate) + return parent_rate; + + div = parent_rate / rate; + if (div > 2) + div = 2; + + return parent_rate / div; +} + +static unsigned long s3c2412_getrate_usbsrc(struct clk *clk) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long div = __raw_readl(S3C2410_CLKDIVN); + + return parent_rate / ((div & S3C2412_CLKDIVN_USB48DIV) ? 2 : 1); +} + +static int s3c2412_setrate_usbsrc(struct clk *clk, unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN); + + rate = s3c2412_roundrate_usbsrc(clk, rate); + + if ((parent_rate / rate) == 2) + clkdivn |= S3C2412_CLKDIVN_USB48DIV; + else + clkdivn &= ~S3C2412_CLKDIVN_USB48DIV; + + __raw_writel(clkdivn, S3C2410_CLKDIVN); + return 0; +} + +static struct clk clk_usbsrc = { + .name = "usbsrc", + .id = -1, + .get_rate = s3c2412_getrate_usbsrc, + .set_rate = s3c2412_setrate_usbsrc, + .round_rate = s3c2412_roundrate_usbsrc, + .set_parent = s3c2412_setparent_usbsrc, +}; + +static int s3c2412_setparent_msysclk(struct clk *clk, struct clk *parent) +{ + unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); + + if (parent == &clk_mdivclk) + clksrc &= ~S3C2412_CLKSRC_MSYSCLK_MPLL; + else if (parent == &clk_upll) + clksrc |= S3C2412_CLKSRC_MSYSCLK_MPLL; + else + return -EINVAL; + + clk->parent = parent; + + __raw_writel(clksrc, S3C2412_CLKSRC); + return 0; +} + +static struct clk clk_msysclk = { + .name = "msysclk", + .id = -1, + .set_parent = s3c2412_setparent_msysclk, +}; + +/* these next clocks have an divider immediately after them, + * so we can register them with their divider and leave out the + * intermediate clock stage +*/ +static unsigned long s3c2412_roundrate_clksrc(struct clk *clk, + unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + int div; + + if (rate > parent_rate) + return parent_rate; + + /* note, we remove the +/- 1 calculations as they cancel out */ + + div = (rate / parent_rate); + + if (div < 1) + div = 1; + else if (div > 16) + div = 16; + + return parent_rate / div; +} + +static int s3c2412_setparent_uart(struct clk *clk, struct clk *parent) +{ + unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); + + if (parent == &clk_erefclk) + clksrc &= ~S3C2412_CLKSRC_UARTCLK_MPLL; + else if (parent == &clk_mpll) + clksrc |= S3C2412_CLKSRC_UARTCLK_MPLL; + else + return -EINVAL; + + clk->parent = parent; + + __raw_writel(clksrc, S3C2412_CLKSRC); + return 0; +} + +static unsigned long s3c2412_getrate_uart(struct clk *clk) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long div = __raw_readl(S3C2410_CLKDIVN); + + div &= S3C2412_CLKDIVN_UARTDIV_MASK; + div >>= S3C2412_CLKDIVN_UARTDIV_SHIFT; + + return parent_rate / (div + 1); +} + +static int s3c2412_setrate_uart(struct clk *clk, unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN); + + rate = s3c2412_roundrate_clksrc(clk, rate); + + clkdivn &= ~S3C2412_CLKDIVN_UARTDIV_MASK; + clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_UARTDIV_SHIFT; + + __raw_writel(clkdivn, S3C2410_CLKDIVN); + return 0; +} + +static struct clk clk_uart = { + .name = "uartclk", + .id = -1, + .get_rate = s3c2412_getrate_uart, + .set_rate = s3c2412_setrate_uart, + .set_parent = s3c2412_setparent_uart, + .round_rate = s3c2412_roundrate_clksrc, +}; + +static int s3c2412_setparent_i2s(struct clk *clk, struct clk *parent) +{ + unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); + + if (parent == &clk_erefclk) + clksrc &= ~S3C2412_CLKSRC_I2SCLK_MPLL; + else if (parent == &clk_mpll) + clksrc |= S3C2412_CLKSRC_I2SCLK_MPLL; + else + return -EINVAL; + + clk->parent = parent; + + __raw_writel(clksrc, S3C2412_CLKSRC); + return 0; +} + +static unsigned long s3c2412_getrate_i2s(struct clk *clk) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long div = __raw_readl(S3C2410_CLKDIVN); + + div &= S3C2412_CLKDIVN_I2SDIV_MASK; + div >>= S3C2412_CLKDIVN_I2SDIV_SHIFT; + + return parent_rate / (div + 1); +} + +static int s3c2412_setrate_i2s(struct clk *clk, unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN); + + rate = s3c2412_roundrate_clksrc(clk, rate); + + clkdivn &= ~S3C2412_CLKDIVN_I2SDIV_MASK; + clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_I2SDIV_SHIFT; + + __raw_writel(clkdivn, S3C2410_CLKDIVN); + return 0; +} + +static struct clk clk_i2s = { + .name = "i2sclk", + .id = -1, + .get_rate = s3c2412_getrate_i2s, + .set_rate = s3c2412_setrate_i2s, + .set_parent = s3c2412_setparent_i2s, + .round_rate = s3c2412_roundrate_clksrc, +}; + +static int s3c2412_setparent_cam(struct clk *clk, struct clk *parent) +{ + unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); + + if (parent == &clk_usysclk) + clksrc &= ~S3C2412_CLKSRC_CAMCLK_HCLK; + else if (parent == &clk_h) + clksrc |= S3C2412_CLKSRC_CAMCLK_HCLK; + else + return -EINVAL; + + clk->parent = parent; + + __raw_writel(clksrc, S3C2412_CLKSRC); + return 0; +} +static unsigned long s3c2412_getrate_cam(struct clk *clk) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long div = __raw_readl(S3C2410_CLKDIVN); + + div &= S3C2412_CLKDIVN_CAMDIV_MASK; + div >>= S3C2412_CLKDIVN_CAMDIV_SHIFT; + + return parent_rate / (div + 1); +} + +static int s3c2412_setrate_cam(struct clk *clk, unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long clkdivn = __raw_readl(S3C2410_CLKDIVN); + + rate = s3c2412_roundrate_clksrc(clk, rate); + + clkdivn &= ~S3C2412_CLKDIVN_CAMDIV_MASK; + clkdivn |= ((parent_rate / rate) - 1) << S3C2412_CLKDIVN_CAMDIV_SHIFT; + + __raw_writel(clkdivn, S3C2410_CLKDIVN); + return 0; +} + +static struct clk clk_cam = { + .name = "camif-upll", /* same as 2440 name */ + .id = -1, + .get_rate = s3c2412_getrate_cam, + .set_rate = s3c2412_setrate_cam, + .set_parent = s3c2412_setparent_cam, + .round_rate = s3c2412_roundrate_clksrc, +}; + +/* standard clock definitions */ + +static struct clk init_clocks_disable[] = { + { + .name = "nand", + .id = -1, + .parent = &clk_h, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_NAND, + }, { + .name = "sdi", + .id = -1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_SDI, + }, { + .name = "adc", + .id = -1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_ADC, + }, { + .name = "i2c", + .id = -1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_IIC, + }, { + .name = "iis", + .id = -1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_IIS, + }, { + .name = "spi", + .id = -1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_SPI, + } +}; + +static struct clk init_clocks[] = { + { + .name = "dma", + .id = 0, + .parent = &clk_h, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_DMA0, + }, { + .name = "dma", + .id = 1, + .parent = &clk_h, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_DMA1, + }, { + .name = "dma", + .id = 2, + .parent = &clk_h, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_DMA2, + }, { + .name = "dma", + .id = 3, + .parent = &clk_h, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_DMA3, + }, { + .name = "lcd", + .id = -1, + .parent = &clk_h, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_LCDC, + }, { + .name = "gpio", + .id = -1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_GPIO, + }, { + .name = "usb-host", + .id = -1, + .parent = &clk_h, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_USBH, + }, { + .name = "usb-device", + .id = -1, + .parent = &clk_h, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_USBD, + }, { + .name = "timers", + .id = -1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_PWMT, + }, { + .name = "uart", + .id = 0, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_UART0, + }, { + .name = "uart", + .id = 1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_UART1, + }, { + .name = "uart", + .id = 2, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_UART2, + }, { + .name = "rtc", + .id = -1, + .parent = &clk_p, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_RTC, + }, { + .name = "watchdog", + .id = -1, + .parent = &clk_p, + .ctrlbit = 0, + }, { + .name = "usb-bus-gadget", + .id = -1, + .parent = &clk_usb_bus, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_USB_DEV48, + }, { + .name = "usb-bus-host", + .id = -1, + .parent = &clk_usb_bus, + .enable = s3c2412_clkcon_enable, + .ctrlbit = S3C2412_CLKCON_USB_HOST48, + } +}; + +/* clocks to add where we need to check their parentage */ + +struct clk_init { + struct clk *clk; + unsigned int bit; + struct clk *src_0; + struct clk *src_1; +}; + +struct clk_init clks_src[] __initdata = { + { + .clk = &clk_usysclk, + .bit = S3C2412_CLKSRC_USBCLK_HCLK, + .src_0 = &clk_urefclk, + .src_1 = &clk_upll, + }, { + .clk = &clk_i2s, + .bit = S3C2412_CLKSRC_I2SCLK_MPLL, + .src_0 = &clk_erefclk, + .src_1 = &clk_mpll, + }, { + .clk = &clk_cam, + .bit = S3C2412_CLKSRC_CAMCLK_HCLK, + .src_0 = &clk_usysclk, + .src_1 = &clk_h, + }, { + .clk = &clk_msysclk, + .bit = S3C2412_CLKSRC_MSYSCLK_MPLL, + .src_0 = &clk_mdivclk, + .src_1 = &clk_mpll, + }, { + .clk = &clk_uart, + .bit = S3C2412_CLKSRC_UARTCLK_MPLL, + .src_0 = &clk_erefclk, + .src_1 = &clk_mpll, + }, { + .clk = &clk_usbsrc, + .bit = S3C2412_CLKSRC_USBCLK_HCLK, + .src_0 = &clk_usysclk, + .src_1 = &clk_h, + }, +}; + +/* s3c2412_clk_initparents + * + * Initialise the parents for the clocks that we get at start-time +*/ + +static void __init s3c2412_clk_initparents(void) +{ + unsigned long clksrc = __raw_readl(S3C2412_CLKSRC); + struct clk_init *cip = clks_src; + struct clk *src; + int ptr; + int ret; + + for (ptr = 0; ptr < ARRAY_SIZE(clks_src); ptr++, cip++) { + ret = s3c24xx_register_clock(cip->clk); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + cip->clk->name, ret); + } + + src = (clksrc & cip->bit) ? cip->src_1 : cip->src_0; + + printk(KERN_INFO "%s: parent %s\n", cip->clk->name, src->name); + clk_set_parent(cip->clk, src); + } +} + +/* clocks to add straight away */ + +struct clk *clks[] __initdata = { + &clk_ext, + &clk_usb_bus, + &clk_erefclk, + &clk_urefclk, + &clk_mrefclk, +}; + +int __init s3c2412_baseclk_add(void) +{ + unsigned long clkcon = __raw_readl(S3C2410_CLKCON); + struct clk *clkp; + int ret; + int ptr; + + clk_upll.enable = s3c2412_upll_enable; + clk_usb_bus.parent = &clk_usbsrc; + clk_usb_bus.rate = 0x0; + + s3c2412_clk_initparents(); + + for (ptr = 0; ptr < ARRAY_SIZE(clks); ptr++) { + clkp = clks[ptr]; + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + } + + /* ensure usb bus clock is within correct rate of 48MHz */ + + if (clk_get_rate(&clk_usb_bus) != (48 * 1000 * 1000)) { + printk(KERN_INFO "Warning: USB bus clock not at 48MHz\n"); + + /* for the moment, let's use the UPLL, and see if we can + * get 48MHz */ + + clk_set_parent(&clk_usysclk, &clk_upll); + clk_set_parent(&clk_usbsrc, &clk_usysclk); + clk_set_rate(&clk_usbsrc, 48*1000*1000); + } + + printk("S3C2412: upll %s, %ld.%03ld MHz, usb-bus %ld.%03ld MHz\n", + (__raw_readl(S3C2410_UPLLCON) & S3C2412_PLLCON_OFF) ? "off":"on", + print_mhz(clk_get_rate(&clk_upll)), + print_mhz(clk_get_rate(&clk_usb_bus))); + + /* register clocks from clock array */ + + clkp = init_clocks; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { + /* ensure that we note the clock state */ + + clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0; + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + } + + /* We must be careful disabling the clocks we are not intending to + * be using at boot time, as subsytems such as the LCD which do + * their own DMA requests to the bus can cause the system to lockup + * if they where in the middle of requesting bus access. + * + * Disabling the LCD clock if the LCD is active is very dangerous, + * and therefore the bootloader should be careful to not enable + * the LCD clock if it is not needed. + */ + + /* install (and disable) the clocks we do not need immediately */ + + clkp = init_clocks_disable; + for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) { + + ret = s3c24xx_register_clock(clkp); + if (ret < 0) { + printk(KERN_ERR "Failed to register clock %s (%d)\n", + clkp->name, ret); + } + + s3c2412_clkcon_enable(clkp, 0); + } + + return 0; +} diff --git a/arch/arm/mach-s3c2410/s3c2412-irq.c b/arch/arm/mach-s3c2410/s3c2412-irq.c new file mode 100644 index 000000000..c80ec93df --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2412-irq.c @@ -0,0 +1,130 @@ +/* linux/arch/arm/mach-s3c2412/s3c2412-irq.c + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/ptrace.h> +#include <linux/sysdev.h> + +#include <asm/hardware.h> +#include <asm/irq.h> +#include <asm/io.h> + +#include <asm/mach/irq.h> + +#include <asm/arch/regs-irq.h> +#include <asm/arch/regs-gpio.h> + +#include "cpu.h" +#include "irq.h" + +/* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by + * having them turn up in both the INT* and the EINT* registers. Whilst + * both show the status, they both now need to be acked when the IRQs + * go off. +*/ + +static void +s3c2412_irq_mask(unsigned int irqno) +{ + unsigned long bitval = 1UL << (irqno - IRQ_EINT0); + unsigned long mask; + + mask = __raw_readl(S3C2410_INTMSK); + __raw_writel(mask | bitval, S3C2410_INTMSK); + + mask = __raw_readl(S3C2412_EINTMASK); + __raw_writel(mask | bitval, S3C2412_EINTMASK); +} + +static inline void +s3c2412_irq_ack(unsigned int irqno) +{ + unsigned long bitval = 1UL << (irqno - IRQ_EINT0); + + __raw_writel(bitval, S3C2412_EINTPEND); + __raw_writel(bitval, S3C2410_SRCPND); + __raw_writel(bitval, S3C2410_INTPND); +} + +static inline void +s3c2412_irq_maskack(unsigned int irqno) +{ + unsigned long bitval = 1UL << (irqno - IRQ_EINT0); + unsigned long mask; + + mask = __raw_readl(S3C2410_INTMSK); + __raw_writel(mask|bitval, S3C2410_INTMSK); + + mask = __raw_readl(S3C2412_EINTMASK); + __raw_writel(mask | bitval, S3C2412_EINTMASK); + + __raw_writel(bitval, S3C2412_EINTPEND); + __raw_writel(bitval, S3C2410_SRCPND); + __raw_writel(bitval, S3C2410_INTPND); +} + +static void +s3c2412_irq_unmask(unsigned int irqno) +{ + unsigned long bitval = 1UL << (irqno - IRQ_EINT0); + unsigned long mask; + + mask = __raw_readl(S3C2412_EINTMASK); + __raw_writel(mask & ~bitval, S3C2412_EINTMASK); + + mask = __raw_readl(S3C2410_INTMSK); + __raw_writel(mask & ~bitval, S3C2410_INTMSK); +} + +static struct irqchip s3c2412_irq_eint0t4 = { + .ack = s3c2412_irq_ack, + .mask = s3c2412_irq_mask, + .unmask = s3c2412_irq_unmask, + .set_wake = s3c_irq_wake, + .set_type = s3c_irqext_type, +}; + +static int s3c2412_irq_add(struct sys_device *sysdev) +{ + unsigned int irqno; + + for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) { + set_irq_chip(irqno, &s3c2412_irq_eint0t4); + set_irq_handler(irqno, do_edge_IRQ); + set_irq_flags(irqno, IRQF_VALID); + } + + return 0; +} + +static struct sysdev_driver s3c2412_irq_driver = { + .add = s3c2412_irq_add, +}; + +static int s3c2412_irq_init(void) +{ + return sysdev_driver_register(&s3c2412_sysclass, &s3c2412_irq_driver); +} + +arch_initcall(s3c2412_irq_init); diff --git a/arch/arm/mach-s3c2410/s3c2412.c b/arch/arm/mach-s3c2410/s3c2412.c new file mode 100644 index 000000000..2d163f760 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2412.c @@ -0,0 +1,224 @@ +/* linux/arch/arm/mach-s3c2410/s3c2412.c + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * http://armlinux.simtec.co.uk/. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Modifications: + * 16-May-2003 BJD Created initial version + * 16-Aug-2003 BJD Fixed header files and copyright, added URL + * 05-Sep-2003 BJD Moved to kernel v2.6 + * 18-Jan-2004 BJD Added serial port configuration + * 21-Aug-2004 BJD Added new struct s3c2410_board handler + * 28-Sep-2004 BJD Updates for new serial port bits + * 04-Nov-2004 BJD Updated UART configuration process + * 10-Jan-2005 BJD Removed s3c2410_clock_tick_rate + * 13-Aug-2005 DA Removed UART from initial I/O mappings +*/ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/sysdev.h> +#include <linux/platform_device.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <asm/hardware.h> +#include <asm/proc-fns.h> +#include <asm/io.h> +#include <asm/irq.h> + +#include <asm/arch/idle.h> + +#include <asm/arch/regs-clock.h> +#include <asm/arch/regs-serial.h> +#include <asm/arch/regs-power.h> +#include <asm/arch/regs-gpio.h> +#include <asm/arch/regs-gpioj.h> +#include <asm/arch/regs-dsc.h> + +#include "s3c2412.h" +#include "cpu.h" +#include "devs.h" +#include "clock.h" +#include "pm.h" + +#ifndef CONFIG_CPU_S3C2412_ONLY +void __iomem *s3c24xx_va_gpio2 = S3C24XX_VA_GPIO; +#endif + +/* Initial IO mappings */ + +static struct map_desc s3c2412_iodesc[] __initdata = { + IODESC_ENT(CLKPWR), + IODESC_ENT(LCD), + IODESC_ENT(TIMER), + IODESC_ENT(ADC), + IODESC_ENT(WATCHDOG), +}; + +/* uart registration process */ + +void __init s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no) +{ + s3c24xx_init_uartdevs("s3c2412-uart", s3c2410_uart_resources, cfg, no); + + /* rename devices that are s3c2412/s3c2413 specific */ + s3c_device_sdi.name = "s3c2412-sdi"; + s3c_device_nand.name = "s3c2412-nand"; +} + +/* s3c2412_idle + * + * use the standard idle call by ensuring the idle mode + * in power config, then issuing the idle co-processor + * instruction +*/ + +static void s3c2412_idle(void) +{ + unsigned long tmp; + + /* ensure our idle mode is to go to idle */ + + tmp = __raw_readl(S3C2412_PWRCFG); + tmp &= ~S3C2412_PWRCFG_STANDBYWFI_MASK; + tmp |= S3C2412_PWRCFG_STANDBYWFI_IDLE; + __raw_writel(tmp, S3C2412_PWRCFG); + + cpu_do_idle(); +} + +/* s3c2412_map_io + * + * register the standard cpu IO areas, and any passed in from the + * machine specific initialisation. +*/ + +void __init s3c2412_map_io(struct map_desc *mach_desc, int mach_size) +{ + /* move base of IO */ + + s3c24xx_va_gpio2 = S3C24XX_VA_GPIO + 0x10; + + /* set our idle function */ + + s3c24xx_idle = s3c2412_idle; + + /* register our io-tables */ + + iotable_init(s3c2412_iodesc, ARRAY_SIZE(s3c2412_iodesc)); + iotable_init(mach_desc, mach_size); +} + +void __init s3c2412_init_clocks(int xtal) +{ + unsigned long tmp; + unsigned long fclk; + unsigned long hclk; + unsigned long pclk; + + /* now we've got our machine bits initialised, work out what + * clocks we've got */ + + fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal*2); + + tmp = __raw_readl(S3C2410_CLKDIVN); + + /* work out clock scalings */ + + hclk = fclk / ((tmp & S3C2412_CLKDIVN_HDIVN_MASK) + 1); + hclk /= ((tmp & S3C2421_CLKDIVN_ARMDIVN) ? 2 : 1); + pclk = hclk / ((tmp & S3C2412_CLKDIVN_PDIVN) ? 2 : 1); + + /* print brieft summary of clocks, etc */ + + printk("S3C2412: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", + print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); + + /* initialise the clocks here, to allow other things like the + * console to use them + */ + + s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); + s3c2412_baseclk_add(); +} + +/* need to register class before we actually register the device, and + * we also need to ensure that it has been initialised before any of the + * drivers even try to use it (even if not on an s3c2412 based system) + * as a driver which may support both 2410 and 2440 may try and use it. +*/ + +#ifdef CONFIG_PM +static struct sleep_save s3c2412_sleep[] = { + SAVE_ITEM(S3C2412_DSC0), + SAVE_ITEM(S3C2412_DSC1), + SAVE_ITEM(S3C2413_GPJDAT), + SAVE_ITEM(S3C2413_GPJCON), + SAVE_ITEM(S3C2413_GPJUP), + + /* save the sleep configuration anyway, just in case these + * get damaged during wakeup */ + + SAVE_ITEM(S3C2412_GPBSLPCON), + SAVE_ITEM(S3C2412_GPCSLPCON), + SAVE_ITEM(S3C2412_GPDSLPCON), + SAVE_ITEM(S3C2412_GPESLPCON), + SAVE_ITEM(S3C2412_GPFSLPCON), + SAVE_ITEM(S3C2412_GPGSLPCON), + SAVE_ITEM(S3C2412_GPHSLPCON), + SAVE_ITEM(S3C2413_GPJSLPCON), +}; + +static int s3c2412_suspend(struct sys_device *dev, pm_message_t state) +{ + s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep)); + return 0; +} + +static int s3c2412_resume(struct sys_device *dev) +{ + s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep)); + return 0; +} + +#else +#define s3c2412_suspend NULL +#define s3c2412_resume NULL +#endif + +struct sysdev_class s3c2412_sysclass = { + set_kset_name("s3c2412-core"), + .suspend = s3c2412_suspend, + .resume = s3c2412_resume +}; + +static int __init s3c2412_core_init(void) +{ + return sysdev_class_register(&s3c2412_sysclass); +} + +core_initcall(s3c2412_core_init); + +static struct sys_device s3c2412_sysdev = { + .cls = &s3c2412_sysclass, +}; + +int __init s3c2412_init(void) +{ + printk("S3C2412: Initialising architecture\n"); + + return sysdev_register(&s3c2412_sysdev); +} diff --git a/arch/arm/mach-s3c2410/s3c2412.h b/arch/arm/mach-s3c2410/s3c2412.h new file mode 100644 index 000000000..c6e56032a --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2412.h @@ -0,0 +1,29 @@ +/* arch/arm/mach-s3c2410/s3c2412.h + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * Header file for s3c2412 cpu support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifdef CONFIG_CPU_S3C2412 + +extern int s3c2412_init(void); + +extern void s3c2412_map_io(struct map_desc *mach_desc, int size); + +extern void s3c2412_init_uarts(struct s3c2410_uartcfg *cfg, int no); + +extern void s3c2412_init_clocks(int xtal); + +extern int s3c2412_baseclk_add(void); +#else +#define s3c2412_init_clocks NULL +#define s3c2412_init_uarts NULL +#define s3c2412_map_io NULL +#define s3c2412_init NULL +#endif diff --git a/arch/arm/mach-s3c2410/s3c2442-clock.c b/arch/arm/mach-s3c2410/s3c2442-clock.c new file mode 100644 index 000000000..d9f54b5ca --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2442-clock.c @@ -0,0 +1,171 @@ +/* linux/arch/arm/mach-s3c2410/s3c2442-clock.c + * + * Copyright (c) 2004-2005 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C2442 Clock support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/device.h> +#include <linux/sysdev.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/mutex.h> +#include <linux/clk.h> + +#include <asm/hardware.h> +#include <asm/atomic.h> +#include <asm/irq.h> +#include <asm/io.h> + +#include <asm/arch/regs-clock.h> + +#include "clock.h" +#include "cpu.h" + +/* S3C2442 extended clock support */ + +static unsigned long s3c2442_camif_upll_round(struct clk *clk, + unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + int div; + + if (rate > parent_rate) + return parent_rate; + + div = parent_rate / rate; + + if (div == 3) + return parent_rate / 3; + + /* note, we remove the +/- 1 calculations for the divisor */ + + div /= 2; + + if (div < 1) + div = 1; + else if (div > 16) + div = 16; + + return parent_rate / (div * 2); +} + +static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate) +{ + unsigned long parent_rate = clk_get_rate(clk->parent); + unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); + + rate = s3c2442_camif_upll_round(clk, rate); + + camdivn &= ~S3C2442_CAMDIVN_CAMCLK_DIV3; + + if (rate == parent_rate) { + camdivn &= ~S3C2440_CAMDIVN_CAMCLK_SEL; + } else if ((parent_rate / rate) == 3) { + camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL; + camdivn |= S3C2442_CAMDIVN_CAMCLK_DIV3; + } else { + camdivn &= ~S3C2440_CAMDIVN_CAMCLK_MASK; + camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL; + camdivn |= (((parent_rate / rate) / 2) - 1); + } + + __raw_writel(camdivn, S3C2440_CAMDIVN); + + return 0; +} + +/* Extra S3C2442 clocks */ + +static struct clk s3c2442_clk_cam = { + .name = "camif", + .id = -1, + .enable = s3c2410_clkcon_enable, + .ctrlbit = S3C2440_CLKCON_CAMERA, +}; + +static struct clk s3c2442_clk_cam_upll = { + .name = "camif-upll", + .id = -1, + .set_rate = s3c2442_camif_upll_setrate, + .round_rate = s3c2442_camif_upll_round, +}; + +static int s3c2442_clk_add(struct sys_device *sysdev) +{ + unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); + unsigned long clkdivn; + struct clk *clk_h; + struct clk *clk_p; + struct clk *clk_upll; + + printk("S3C2442: Clock Support, DVS %s\n", + (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off"); + + clk_p = clk_get(NULL, "pclk"); + clk_h = clk_get(NULL, "hclk"); + clk_upll = clk_get(NULL, "upll"); + + if (IS_ERR(clk_p) || IS_ERR(clk_h) || IS_ERR(clk_upll)) { + printk(KERN_ERR "S3C2442: Failed to get parent clocks\n"); + return -EINVAL; + } + + /* check rate of UPLL, and if it is near 96MHz, then change + * to using half the UPLL rate for the system */ + + if (clk_get_rate(clk_upll) > (94 * MHZ)) { + clk_usb_bus.rate = clk_get_rate(clk_upll) / 2; + + mutex_lock(&clocks_mutex); + + clkdivn = __raw_readl(S3C2410_CLKDIVN); + clkdivn |= S3C2440_CLKDIVN_UCLK; + __raw_writel(clkdivn, S3C2410_CLKDIVN); + + mutex_unlock(&clocks_mutex); + } + + s3c2442_clk_cam.parent = clk_h; + s3c2442_clk_cam_upll.parent = clk_upll; + + s3c24xx_register_clock(&s3c2442_clk_cam); + s3c24xx_register_clock(&s3c2442_clk_cam_upll); + + clk_disable(&s3c2442_clk_cam); + + return 0; +} + +static struct sysdev_driver s3c2442_clk_driver = { + .add = s3c2442_clk_add, +}; + +static __init int s3c2442_clk_init(void) +{ + return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_clk_driver); +} + +arch_initcall(s3c2442_clk_init); diff --git a/arch/arm/mach-s3c2410/s3c2442.c b/arch/arm/mach-s3c2410/s3c2442.c new file mode 100644 index 000000000..debae2430 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2442.c @@ -0,0 +1,52 @@ +/* linux/arch/arm/mach-s3c2410/s3c2440.c + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * Samsung S3C2442 Mobile CPU support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/sysdev.h> +#include <linux/clk.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/irq.h> + +#include <asm/arch/regs-clock.h> +#include <asm/arch/regs-serial.h> +#include <asm/arch/regs-gpio.h> +#include <asm/arch/regs-gpioj.h> +#include <asm/arch/regs-dsc.h> + +#include "s3c2442.h" +#include "clock.h" +#include "devs.h" +#include "cpu.h" +#include "pm.h" + +static struct sys_device s3c2442_sysdev = { + .cls = &s3c2442_sysclass, +}; + +int __init s3c2442_init(void) +{ + printk("S3C2442: Initialising architecture\n"); + + return sysdev_register(&s3c2442_sysdev); +} diff --git a/arch/arm/mach-s3c2410/s3c2442.h b/arch/arm/mach-s3c2410/s3c2442.h new file mode 100644 index 000000000..0ae37d248 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c2442.h @@ -0,0 +1,17 @@ +/* arch/arm/mach-s3c2410/s3c2442.h + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * Header file for s3c2442 cpu support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifdef CONFIG_CPU_S3C2442 +extern int s3c2442_init(void); +#else +#define s3c2442_init NULL +#endif diff --git a/arch/arm/mach-s3c2410/s3c244x-irq.c b/arch/arm/mach-s3c2410/s3c244x-irq.c new file mode 100644 index 000000000..44c5affa9 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c244x-irq.c @@ -0,0 +1,142 @@ +/* linux/arch/arm/mach-s3c2410/s3c2440-irq.c + * + * Copyright (c) 2003,2004 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/ptrace.h> +#include <linux/sysdev.h> + +#include <asm/hardware.h> +#include <asm/irq.h> +#include <asm/io.h> + +#include <asm/mach/irq.h> + +#include <asm/arch/regs-irq.h> +#include <asm/arch/regs-gpio.h> + +#include "cpu.h" +#include "pm.h" +#include "irq.h" + +/* camera irq */ + +static void s3c_irq_demux_cam(unsigned int irq, + struct irqdesc *desc, + struct pt_regs *regs) +{ + unsigned int subsrc, submsk; + struct irqdesc *mydesc; + + /* read the current pending interrupts, and the mask + * for what it is available */ + + subsrc = __raw_readl(S3C2410_SUBSRCPND); + submsk = __raw_readl(S3C2410_INTSUBMSK); + + subsrc &= ~submsk; + subsrc >>= 11; + subsrc &= 3; + + if (subsrc != 0) { + if (subsrc & 1) { + mydesc = irq_desc + IRQ_S3C2440_CAM_C; + desc_handle_irq(IRQ_S3C2440_CAM_C, mydesc, regs); + } + if (subsrc & 2) { + mydesc = irq_desc + IRQ_S3C2440_CAM_P; + desc_handle_irq(IRQ_S3C2440_CAM_P, mydesc, regs); + } + } +} + +#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0)) + +static void +s3c_irq_cam_mask(unsigned int irqno) +{ + s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11); +} + +static void +s3c_irq_cam_unmask(unsigned int irqno) +{ + s3c_irqsub_unmask(irqno, INTMSK_CAM); +} + +static void +s3c_irq_cam_ack(unsigned int irqno) +{ + s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11); +} + +static struct irqchip s3c_irq_cam = { + .mask = s3c_irq_cam_mask, + .unmask = s3c_irq_cam_unmask, + .ack = s3c_irq_cam_ack, +}; + +static int s3c244x_irq_add(struct sys_device *sysdev) +{ + unsigned int irqno; + + set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip); + set_irq_handler(IRQ_NFCON, do_level_IRQ); + set_irq_flags(IRQ_NFCON, IRQF_VALID); + + /* add chained handler for camera */ + + set_irq_chip(IRQ_CAM, &s3c_irq_level_chip); + set_irq_handler(IRQ_CAM, do_level_IRQ); + set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam); + + for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) { + set_irq_chip(irqno, &s3c_irq_cam); + set_irq_handler(irqno, do_level_IRQ); + set_irq_flags(irqno, IRQF_VALID); + } + + return 0; +} + +static struct sysdev_driver s3c2440_irq_driver = { + .add = s3c244x_irq_add, +}; + +static int s3c2440_irq_init(void) +{ + return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver); +} + +arch_initcall(s3c2440_irq_init); + +static struct sysdev_driver s3c2442_irq_driver = { + .add = s3c244x_irq_add, +}; + +static int s3c2442_irq_init(void) +{ + return sysdev_driver_register(&s3c2442_sysclass, &s3c2442_irq_driver); +} + +arch_initcall(s3c2442_irq_init); diff --git a/arch/arm/mach-s3c2410/s3c244x.c b/arch/arm/mach-s3c2410/s3c244x.c new file mode 100644 index 000000000..9a2258270 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c244x.c @@ -0,0 +1,185 @@ +/* linux/arch/arm/mach-s3c2410/s3c244x.c + * + * Copyright (c) 2004-2006 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * Samsung S3C2440 and S3C2442 Mobile CPU support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/sysdev.h> +#include <linux/clk.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/irq.h> + +#include <asm/arch/regs-clock.h> +#include <asm/arch/regs-serial.h> +#include <asm/arch/regs-gpio.h> +#include <asm/arch/regs-gpioj.h> +#include <asm/arch/regs-dsc.h> + +#include "s3c2410.h" +#include "s3c2440.h" +#include "s3c244x.h" +#include "clock.h" +#include "devs.h" +#include "cpu.h" +#include "pm.h" + +static struct map_desc s3c244x_iodesc[] __initdata = { + IODESC_ENT(CLKPWR), + IODESC_ENT(TIMER), + IODESC_ENT(WATCHDOG), + IODESC_ENT(LCD), + IODESC_ENT(ADC), + IODESC_ENT(USBHOST), +}; + +/* uart initialisation */ + +void __init s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no) +{ + s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no); +} + +void __init s3c244x_map_io(struct map_desc *mach_desc, int size) +{ + /* register our io-tables */ + + iotable_init(s3c244x_iodesc, ARRAY_SIZE(s3c244x_iodesc)); + iotable_init(mach_desc, size); + + /* rename any peripherals used differing from the s3c2410 */ + + s3c_device_i2c.name = "s3c2440-i2c"; + s3c_device_nand.name = "s3c2440-nand"; + s3c_device_usbgadget.name = "s3c2440-usbgadget"; +} + +void __init s3c244x_init_clocks(int xtal) +{ + unsigned long clkdiv; + unsigned long camdiv; + unsigned long hclk, fclk, pclk; + int hdiv = 1; + + /* now we've got our machine bits initialised, work out what + * clocks we've got */ + + fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2; + + clkdiv = __raw_readl(S3C2410_CLKDIVN); + camdiv = __raw_readl(S3C2440_CAMDIVN); + + /* work out clock scalings */ + + switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) { + case S3C2440_CLKDIVN_HDIVN_1: + hdiv = 1; + break; + + case S3C2440_CLKDIVN_HDIVN_2: + hdiv = 2; + break; + + case S3C2440_CLKDIVN_HDIVN_4_8: + hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4; + break; + + case S3C2440_CLKDIVN_HDIVN_3_6: + hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3; + break; + } + + hclk = fclk / hdiv; + pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1); + + /* print brief summary of clocks, etc */ + + printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n", + print_mhz(fclk), print_mhz(hclk), print_mhz(pclk)); + + /* initialise the clocks here, to allow other things like the + * console to use them, and to add new ones after the initialisation + */ + + s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); + s3c2410_baseclk_add(); +} + +#ifdef CONFIG_PM + +static struct sleep_save s3c244x_sleep[] = { + SAVE_ITEM(S3C2440_DSC0), + SAVE_ITEM(S3C2440_DSC1), + SAVE_ITEM(S3C2440_GPJDAT), + SAVE_ITEM(S3C2440_GPJCON), + SAVE_ITEM(S3C2440_GPJUP) +}; + +static int s3c244x_suspend(struct sys_device *dev, pm_message_t state) +{ + s3c2410_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep)); + return 0; +} + +static int s3c244x_resume(struct sys_device *dev) +{ + s3c2410_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep)); + return 0; +} + +#else +#define s3c244x_suspend NULL +#define s3c244x_resume NULL +#endif + +/* Since the S3C2442 and S3C2440 share items, put both sysclasses here */ + +struct sysdev_class s3c2440_sysclass = { + set_kset_name("s3c2440-core"), + .suspend = s3c244x_suspend, + .resume = s3c244x_resume +}; + +struct sysdev_class s3c2442_sysclass = { + set_kset_name("s3c2442-core"), + .suspend = s3c244x_suspend, + .resume = s3c244x_resume +}; + +/* need to register class before we actually register the device, and + * we also need to ensure that it has been initialised before any of the + * drivers even try to use it (even if not on an s3c2440 based system) + * as a driver which may support both 2410 and 2440 may try and use it. +*/ + +static int __init s3c2440_core_init(void) +{ + return sysdev_class_register(&s3c2440_sysclass); +} + +core_initcall(s3c2440_core_init); + +static int __init s3c2442_core_init(void) +{ + return sysdev_class_register(&s3c2442_sysclass); +} + +core_initcall(s3c2442_core_init); diff --git a/arch/arm/mach-s3c2410/s3c244x.h b/arch/arm/mach-s3c2410/s3c244x.h new file mode 100644 index 000000000..3e7f5f751 --- /dev/null +++ b/arch/arm/mach-s3c2410/s3c244x.h @@ -0,0 +1,25 @@ +/* arch/arm/mach-s3c2410/s3c2440.h + * + * Copyright (c) 2004-2005 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * Header file for S3C2440 and S3C2442 cpu support + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442) + +extern void s3c244x_map_io(struct map_desc *mach_desc, int size); + +extern void s3c244x_init_uarts(struct s3c2410_uartcfg *cfg, int no); + +extern void s3c244x_init_clocks(int xtal); + +#else +#define s3c244x_init_clocks NULL +#define s3c244x_init_uarts NULL +#define s3c244x_map_io NULL +#endif diff --git a/arch/arm/mm/iomap.c b/arch/arm/mm/iomap.c new file mode 100644 index 000000000..62066f302 --- /dev/null +++ b/arch/arm/mm/iomap.c @@ -0,0 +1,55 @@ +/* + * linux/arch/arm/mm/iomap.c + * + * Map IO port and PCI memory spaces so that {read,write}[bwl] can + * be used to access this memory. + */ +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/ioport.h> + +#include <asm/io.h> + +#ifdef __io +void __iomem *ioport_map(unsigned long port, unsigned int nr) +{ + return __io(port); +} +EXPORT_SYMBOL(ioport_map); + +void ioport_unmap(void __iomem *addr) +{ +} +EXPORT_SYMBOL(ioport_unmap); +#endif + +#ifdef CONFIG_PCI +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) +{ + unsigned long start = pci_resource_start(dev, bar); + unsigned long len = pci_resource_len(dev, bar); + unsigned long flags = pci_resource_flags(dev, bar); + + if (!len || !start) + return NULL; + if (maxlen && len > maxlen) + len = maxlen; + if (flags & IORESOURCE_IO) + return ioport_map(start, len); + if (flags & IORESOURCE_MEM) { + if (flags & IORESOURCE_CACHEABLE) + return ioremap(start, len); + return ioremap_nocache(start, len); + } + return NULL; +} +EXPORT_SYMBOL(pci_iomap); + +void pci_iounmap(struct pci_dev *dev, void __iomem *addr) +{ + if ((unsigned long)addr >= VMALLOC_START && + (unsigned long)addr < VMALLOC_END) + iounmap(addr); +} +EXPORT_SYMBOL(pci_iounmap); +#endif diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c new file mode 100644 index 000000000..1464ed817 --- /dev/null +++ b/arch/arm/mm/nommu.c @@ -0,0 +1,39 @@ +/* + * linux/arch/arm/mm/nommu.c + * + * ARM uCLinux supporting functions. + */ +#include <linux/module.h> +#include <linux/mm.h> +#include <linux/pagemap.h> + +#include <asm/cacheflush.h> +#include <asm/io.h> +#include <asm/page.h> + +void flush_dcache_page(struct page *page) +{ + __cpuc_flush_dcache_page(page_address(page)); +} +EXPORT_SYMBOL(flush_dcache_page); + +void __iomem *__ioremap_pfn(unsigned long pfn, unsigned long offset, + size_t size, unsigned long flags) +{ + if (pfn >= (0x100000000ULL >> PAGE_SHIFT)) + return NULL; + return (void __iomem *) (offset + (pfn << PAGE_SHIFT)); +} +EXPORT_SYMBOL(__ioremap_pfn); + +void __iomem *__ioremap(unsigned long phys_addr, size_t size, + unsigned long flags) +{ + return (void __iomem *)phys_addr; +} +EXPORT_SYMBOL(__ioremap); + +void __iounmap(void __iomem *addr) +{ +} +EXPORT_SYMBOL(__iounmap); diff --git a/arch/i386/kernel/hpet.c b/arch/i386/kernel/hpet.c new file mode 100644 index 000000000..17647a530 --- /dev/null +++ b/arch/i386/kernel/hpet.c @@ -0,0 +1,67 @@ +#include <linux/clocksource.h> +#include <linux/errno.h> +#include <linux/hpet.h> +#include <linux/init.h> + +#include <asm/hpet.h> +#include <asm/io.h> + +#define HPET_MASK CLOCKSOURCE_MASK(32) +#define HPET_SHIFT 22 + +/* FSEC = 10^-15 NSEC = 10^-9 */ +#define FSEC_PER_NSEC 1000000 + +static void *hpet_ptr; + +static cycle_t read_hpet(void) +{ + return (cycle_t)readl(hpet_ptr); +} + +static struct clocksource clocksource_hpet = { + .name = "hpet", + .rating = 250, + .read = read_hpet, + .mask = HPET_MASK, + .mult = 0, /* set below */ + .shift = HPET_SHIFT, + .is_continuous = 1, +}; + +static int __init init_hpet_clocksource(void) +{ + unsigned long hpet_period; + void __iomem* hpet_base; + u64 tmp; + + if (!is_hpet_enabled()) + return -ENODEV; + + /* calculate the hpet address: */ + hpet_base = + (void __iomem*)ioremap_nocache(hpet_address, HPET_MMAP_SIZE); + hpet_ptr = hpet_base + HPET_COUNTER; + + /* calculate the frequency: */ + hpet_period = readl(hpet_base + HPET_PERIOD); + + /* + * hpet period is in femto seconds per cycle + * so we need to convert this to ns/cyc units + * aproximated by mult/2^shift + * + * fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift + * fsec/cyc * 1ns/1000000fsec * 2^shift = mult + * fsec/cyc * 2^shift * 1nsec/1000000fsec = mult + * (fsec/cyc << shift)/1000000 = mult + * (hpet_period << shift)/FSEC_PER_NSEC = mult + */ + tmp = (u64)hpet_period << HPET_SHIFT; + do_div(tmp, FSEC_PER_NSEC); + clocksource_hpet.mult = (u32)tmp; + + return clocksource_register(&clocksource_hpet); +} + +module_init(init_hpet_clocksource); diff --git a/arch/i386/kernel/i8253.c b/arch/i386/kernel/i8253.c new file mode 100644 index 000000000..477b24daf --- /dev/null +++ b/arch/i386/kernel/i8253.c @@ -0,0 +1,118 @@ +/* + * i8253.c 8253/PIT functions + * + */ +#include <linux/clocksource.h> +#include <linux/spinlock.h> +#include <linux/jiffies.h> +#include <linux/sysdev.h> +#include <linux/module.h> +#include <linux/init.h> + +#include <asm/smp.h> +#include <asm/delay.h> +#include <asm/i8253.h> +#include <asm/io.h> + +#include "io_ports.h" + +DEFINE_SPINLOCK(i8253_lock); +EXPORT_SYMBOL(i8253_lock); + +void setup_pit_timer(void) +{ + unsigned long flags; + + spin_lock_irqsave(&i8253_lock, flags); + outb_p(0x34,PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */ + udelay(10); + outb_p(LATCH & 0xff , PIT_CH0); /* LSB */ + udelay(10); + outb(LATCH >> 8 , PIT_CH0); /* MSB */ + spin_unlock_irqrestore(&i8253_lock, flags); +} + +/* + * Since the PIT overflows every tick, its not very useful + * to just read by itself. So use jiffies to emulate a free + * running counter: + */ +static cycle_t pit_read(void) +{ + unsigned long flags; + int count; + u32 jifs; + static int old_count; + static u32 old_jifs; + + spin_lock_irqsave(&i8253_lock, flags); + /* + * Although our caller may have the read side of xtime_lock, + * this is now a seqlock, and we are cheating in this routine + * by having side effects on state that we cannot undo if + * there is a collision on the seqlock and our caller has to + * retry. (Namely, old_jifs and old_count.) So we must treat + * jiffies as volatile despite the lock. We read jiffies + * before latching the timer count to guarantee that although + * the jiffies value might be older than the count (that is, + * the counter may underflow between the last point where + * jiffies was incremented and the point where we latch the + * count), it cannot be newer. + */ + jifs = jiffies; + outb_p(0x00, PIT_MODE); /* latch the count ASAP */ + count = inb_p(PIT_CH0); /* read the latched count */ + count |= inb_p(PIT_CH0) << 8; + + /* VIA686a test code... reset the latch if count > max + 1 */ + if (count > LATCH) { + outb_p(0x34, PIT_MODE); + outb_p(LATCH & 0xff, PIT_CH0); + outb(LATCH >> 8, PIT_CH0); + count = LATCH - 1; + } + + /* + * It's possible for count to appear to go the wrong way for a + * couple of reasons: + * + * 1. The timer counter underflows, but we haven't handled the + * resulting interrupt and incremented jiffies yet. + * 2. Hardware problem with the timer, not giving us continuous time, + * the counter does small "jumps" upwards on some Pentium systems, + * (see c't 95/10 page 335 for Neptun bug.) + * + * Previous attempts to handle these cases intelligently were + * buggy, so we just do the simple thing now. + */ + if (count > old_count && jifs == old_jifs) { + count = old_count; + } + old_count = count; + old_jifs = jifs; + + spin_unlock_irqrestore(&i8253_lock, flags); + + count = (LATCH - 1) - count; + + return (cycle_t)(jifs * LATCH) + count; +} + +static struct clocksource clocksource_pit = { + .name = "pit", + .rating = 110, + .read = pit_read, + .mask = CLOCKSOURCE_MASK(32), + .mult = 0, + .shift = 20, +}; + +static int __init init_pit_clocksource(void) +{ + if (num_possible_cpus() > 4) /* PIT does not scale! */ + return 0; + + clocksource_pit.mult = clocksource_hz2mult(CLOCK_TICK_RATE, 20); + return clocksource_register(&clocksource_pit); +} +module_init(init_pit_clocksource); diff --git a/arch/i386/kernel/tsc.c b/arch/i386/kernel/tsc.c new file mode 100644 index 000000000..650b7462a --- /dev/null +++ b/arch/i386/kernel/tsc.c @@ -0,0 +1,480 @@ +/* + * This code largely moved from arch/i386/kernel/timer/timer_tsc.c + * which was originally moved from arch/i386/kernel/time.c. + * See comments there for proper credits. + */ + +#include <linux/clocksource.h> +#include <linux/workqueue.h> +#include <linux/cpufreq.h> +#include <linux/jiffies.h> +#include <linux/init.h> +#include <linux/dmi.h> + +#include <asm/delay.h> +#include <asm/tsc.h> +#include <asm/delay.h> +#include <asm/io.h> + +#include "mach_timer.h" + +/* + * On some systems the TSC frequency does not + * change with the cpu frequency. So we need + * an extra value to store the TSC freq + */ +unsigned int tsc_khz; + +int tsc_disable __cpuinitdata = 0; + +#ifdef CONFIG_X86_TSC +static int __init tsc_setup(char *str) +{ + printk(KERN_WARNING "notsc: Kernel compiled with CONFIG_X86_TSC, " + "cannot disable TSC.\n"); + return 1; +} +#else +/* + * disable flag for tsc. Takes effect by clearing the TSC cpu flag + * in cpu/common.c + */ +static int __init tsc_setup(char *str) +{ + tsc_disable = 1; + + return 1; +} +#endif + +__setup("notsc", tsc_setup); + +/* + * code to mark and check if the TSC is unstable + * due to cpufreq or due to unsynced TSCs + */ +static int tsc_unstable; + +static inline int check_tsc_unstable(void) +{ + return tsc_unstable; +} + +void mark_tsc_unstable(void) +{ + tsc_unstable = 1; +} +EXPORT_SYMBOL_GPL(mark_tsc_unstable); + +/* Accellerators for sched_clock() + * convert from cycles(64bits) => nanoseconds (64bits) + * basic equation: + * ns = cycles / (freq / ns_per_sec) + * ns = cycles * (ns_per_sec / freq) + * ns = cycles * (10^9 / (cpu_khz * 10^3)) + * ns = cycles * (10^6 / cpu_khz) + * + * Then we use scaling math (suggested by george@mvista.com) to get: + * ns = cycles * (10^6 * SC / cpu_khz) / SC + * ns = cycles * cyc2ns_scale / SC + * + * And since SC is a constant power of two, we can convert the div + * into a shift. + * + * We can use khz divisor instead of mhz to keep a better percision, since + * cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits. + * (mathieu.desnoyers@polymtl.ca) + * + * -johnstul@us.ibm.com "math is hard, lets go shopping!" + */ +static unsigned long cyc2ns_scale __read_mostly; + +#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */ + +static inline void set_cyc2ns_scale(unsigned long cpu_khz) +{ + cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz; +} + +static inline unsigned long long cycles_2_ns(unsigned long long cyc) +{ + return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR; +} + +#ifndef CONFIG_XEN +/* + * Scheduler clock - returns current time in nanosec units. + */ +unsigned long long sched_clock(void) +{ + unsigned long long this_offset; + + /* + * in the NUMA case we dont use the TSC as they are not + * synchronized across all CPUs. + */ +#ifndef CONFIG_NUMA + if (!cpu_khz || check_tsc_unstable()) +#endif + /* no locking but a rare wrong value is not a big deal */ + return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ); + + /* read the Time Stamp Counter: */ + rdtscll(this_offset); + + /* return the value in ns */ + return cycles_2_ns(this_offset); +} +#endif + +static unsigned long calculate_cpu_khz(void) +{ + unsigned long long start, end; + unsigned long count; + u64 delta64; + int i; + unsigned long flags; + + local_irq_save(flags); + + /* run 3 times to ensure the cache is warm */ + for (i = 0; i < 3; i++) { + mach_prepare_counter(); + rdtscll(start); + mach_countup(&count); + rdtscll(end); + } + /* + * Error: ECTCNEVERSET + * The CTC wasn't reliable: we got a hit on the very first read, + * or the CPU was so fast/slow that the quotient wouldn't fit in + * 32 bits.. + */ + if (count <= 1) + goto err; + + delta64 = end - start; + + /* cpu freq too fast: */ + if (delta64 > (1ULL<<32)) + goto err; + + /* cpu freq too slow: */ + if (delta64 <= CALIBRATE_TIME_MSEC) + goto err; + + delta64 += CALIBRATE_TIME_MSEC/2; /* round for do_div */ + do_div(delta64,CALIBRATE_TIME_MSEC); + + local_irq_restore(flags); + return (unsigned long)delta64; +err: + local_irq_restore(flags); + return 0; +} + +int recalibrate_cpu_khz(void) +{ +#ifndef CONFIG_SMP + unsigned long cpu_khz_old = cpu_khz; + + if (cpu_has_tsc) { + cpu_khz = calculate_cpu_khz(); + tsc_khz = cpu_khz; + cpu_data[0].loops_per_jiffy = + cpufreq_scale(cpu_data[0].loops_per_jiffy, + cpu_khz_old, cpu_khz); + return 0; + } else + return -ENODEV; +#else + return -ENODEV; +#endif +} + +EXPORT_SYMBOL(recalibrate_cpu_khz); + +void tsc_init(void) +{ + if (!cpu_has_tsc || tsc_disable) + return; + + cpu_khz = calculate_cpu_khz(); + tsc_khz = cpu_khz; + + if (!cpu_khz) + return; + + printk("Detected %lu.%03lu MHz processor.\n", + (unsigned long)cpu_khz / 1000, + (unsigned long)cpu_khz % 1000); + + set_cyc2ns_scale(cpu_khz); + use_tsc_delay(); +} + +#ifdef CONFIG_CPU_FREQ + +static unsigned int cpufreq_delayed_issched = 0; +static unsigned int cpufreq_init = 0; +static struct work_struct cpufreq_delayed_get_work; + +static void handle_cpufreq_delayed_get(void *v) +{ + unsigned int cpu; + + for_each_online_cpu(cpu) + cpufreq_get(cpu); + + cpufreq_delayed_issched = 0; +} + +/* + * if we notice cpufreq oddness, schedule a call to cpufreq_get() as it tries + * to verify the CPU frequency the timing core thinks the CPU is running + * at is still correct. + */ +static inline void cpufreq_delayed_get(void) +{ + if (cpufreq_init && !cpufreq_delayed_issched) { + cpufreq_delayed_issched = 1; + printk(KERN_DEBUG "Checking if CPU frequency changed.\n"); + schedule_work(&cpufreq_delayed_get_work); + } +} + +/* + * if the CPU frequency is scaled, TSC-based delays will need a different + * loops_per_jiffy value to function properly. + */ +static unsigned int ref_freq = 0; +static unsigned long loops_per_jiffy_ref = 0; +static unsigned long cpu_khz_ref = 0; + +static int +time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) +{ + struct cpufreq_freqs *freq = data; + + if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE) + write_seqlock_irq(&xtime_lock); + + if (!ref_freq) { + if (!freq->old){ + ref_freq = freq->new; + goto end; + } + ref_freq = freq->old; + loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy; + cpu_khz_ref = cpu_khz; + } + + if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || + (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) || + (val == CPUFREQ_RESUMECHANGE)) { + if (!(freq->flags & CPUFREQ_CONST_LOOPS)) + cpu_data[freq->cpu].loops_per_jiffy = + cpufreq_scale(loops_per_jiffy_ref, + ref_freq, freq->new); + + if (cpu_khz) { + + if (num_online_cpus() == 1) + cpu_khz = cpufreq_scale(cpu_khz_ref, + ref_freq, freq->new); + if (!(freq->flags & CPUFREQ_CONST_LOOPS)) { + tsc_khz = cpu_khz; + set_cyc2ns_scale(cpu_khz); + /* + * TSC based sched_clock turns + * to junk w/ cpufreq + */ + mark_tsc_unstable(); + } + } + } +end: + if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE) + write_sequnlock_irq(&xtime_lock); + + return 0; +} + +static struct notifier_block time_cpufreq_notifier_block = { + .notifier_call = time_cpufreq_notifier +}; + +static int __init cpufreq_tsc(void) +{ + int ret; + + INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL); + ret = cpufreq_register_notifier(&time_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER); + if (!ret) + cpufreq_init = 1; + + return ret; +} + +core_initcall(cpufreq_tsc); + +#endif + +/* clock source code */ + +static unsigned long current_tsc_khz = 0; +static int tsc_update_callback(void); + +static cycle_t read_tsc(void) +{ + cycle_t ret; + + rdtscll(ret); + + return ret; +} + +static struct clocksource clocksource_tsc = { + .name = "tsc", + .rating = 300, + .read = read_tsc, + .mask = CLOCKSOURCE_MASK(64), + .mult = 0, /* to be set */ + .shift = 22, + .update_callback = tsc_update_callback, + .is_continuous = 1, +}; + +static int tsc_update_callback(void) +{ + int change = 0; + + /* check to see if we should switch to the safe clocksource: */ + if (clocksource_tsc.rating != 50 && check_tsc_unstable()) { + clocksource_tsc.rating = 50; + clocksource_reselect(); + change = 1; + } + + /* only update if tsc_khz has changed: */ + if (current_tsc_khz != tsc_khz) { + current_tsc_khz = tsc_khz; + clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz, + clocksource_tsc.shift); + change = 1; + } + + return change; +} + +static int __init dmi_mark_tsc_unstable(struct dmi_system_id *d) +{ + printk(KERN_NOTICE "%s detected: marking TSC unstable.\n", + d->ident); + mark_tsc_unstable(); + return 0; +} + +/* List of systems that have known TSC problems */ +static struct dmi_system_id __initdata bad_tsc_dmi_table[] = { + { + .callback = dmi_mark_tsc_unstable, + .ident = "IBM Thinkpad 380XD", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "IBM"), + DMI_MATCH(DMI_BOARD_NAME, "2635FA0"), + }, + }, + {} +}; + +#define TSC_FREQ_CHECK_INTERVAL (10*MSEC_PER_SEC) /* 10sec in MS */ +static struct timer_list verify_tsc_freq_timer; + +/* XXX - Probably should add locking */ +static void verify_tsc_freq(unsigned long unused) +{ + static u64 last_tsc; + static unsigned long last_jiffies; + + u64 now_tsc, interval_tsc; + unsigned long now_jiffies, interval_jiffies; + + + if (check_tsc_unstable()) + return; + + rdtscll(now_tsc); + now_jiffies = jiffies; + + if (!last_jiffies) { + goto out; + } + + interval_jiffies = now_jiffies - last_jiffies; + interval_tsc = now_tsc - last_tsc; + interval_tsc *= HZ; + do_div(interval_tsc, cpu_khz*1000); + + if (interval_tsc < (interval_jiffies * 3 / 4)) { + printk("TSC appears to be running slowly. " + "Marking it as unstable\n"); + mark_tsc_unstable(); + return; + } + +out: + last_tsc = now_tsc; + last_jiffies = now_jiffies; + /* set us up to go off on the next interval: */ + mod_timer(&verify_tsc_freq_timer, + jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL)); +} + +/* + * Make an educated guess if the TSC is trustworthy and synchronized + * over all CPUs. + */ +static __init int unsynchronized_tsc(void) +{ + /* + * Intel systems are normally all synchronized. + * Exceptions must mark TSC as unstable: + */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) + return 0; + + /* assume multi socket systems are not synchronized: */ + return num_possible_cpus() > 1; +} + +static int __init init_tsc_clocksource(void) +{ + + if (cpu_has_tsc && tsc_khz && !tsc_disable) { + /* check blacklist */ + dmi_check_system(bad_tsc_dmi_table); + + if (unsynchronized_tsc()) /* mark unstable if unsynced */ + mark_tsc_unstable(); + current_tsc_khz = tsc_khz; + clocksource_tsc.mult = clocksource_khz2mult(current_tsc_khz, + clocksource_tsc.shift); + /* lower the rating if we already know its unstable: */ + if (check_tsc_unstable()) + clocksource_tsc.rating = 50; + + init_timer(&verify_tsc_freq_timer); + verify_tsc_freq_timer.function = verify_tsc_freq; + verify_tsc_freq_timer.expires = + jiffies + msecs_to_jiffies(TSC_FREQ_CHECK_INTERVAL); + add_timer(&verify_tsc_freq_timer); + + return clocksource_register(&clocksource_tsc); + } + + return 0; +} + +module_init(init_tsc_clocksource); diff --git a/arch/i386/mach-xen/irqflags.c b/arch/i386/mach-xen/irqflags.c new file mode 100644 index 000000000..c990ca5d2 --- /dev/null +++ b/arch/i386/mach-xen/irqflags.c @@ -0,0 +1,99 @@ +#include <linux/module.h> +#include <linux/smp.h> +#include <asm/irqflags.h> +#include <asm/hypervisor.h> + +/* interrupt control.. */ + +/* + * The use of 'barrier' in the following reflects their use as local-lock + * operations. Reentrancy must be prevented (e.g., __cli()) /before/ following + * critical operations are executed. All critical operations must complete + * /before/ reentrancy is permitted (e.g., __sti()). Alpha architecture also + * includes these barriers, for example. + */ + +unsigned long __raw_local_save_flags(void) +{ + struct vcpu_info *_vcpu; + unsigned long flags; + + preempt_disable(); + _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; + flags = _vcpu->evtchn_upcall_mask; + preempt_enable(); + + return flags; +} +EXPORT_SYMBOL(__raw_local_save_flags); + +void raw_local_irq_restore(unsigned long flags) +{ + struct vcpu_info *_vcpu; + + preempt_disable(); + _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; + if ((_vcpu->evtchn_upcall_mask = flags) == 0) { + barrier(); /* unmask then check (avoid races) */ + if (unlikely(_vcpu->evtchn_upcall_pending)) + force_evtchn_callback(); + preempt_enable(); + } else + preempt_enable_no_resched(); + +} +EXPORT_SYMBOL(raw_local_irq_restore); + +void raw_local_irq_disable(void) +{ + struct vcpu_info *_vcpu; + + preempt_disable(); + _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; + _vcpu->evtchn_upcall_mask = 1; + preempt_enable_no_resched(); +} +EXPORT_SYMBOL(raw_local_irq_disable); + +void raw_local_irq_enable(void) +{ + struct vcpu_info *_vcpu; + + preempt_disable(); + _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; + _vcpu->evtchn_upcall_mask = 0; + barrier(); /* unmask then check (avoid races) */ + if (unlikely(_vcpu->evtchn_upcall_pending)) + force_evtchn_callback(); + preempt_enable(); +} +EXPORT_SYMBOL(raw_local_irq_enable); + +/* Cannot use preempt_enable() here as we would recurse in preempt_sched(). */ +int raw_irqs_disabled(void) +{ + struct vcpu_info *_vcpu; + int disabled; + + preempt_disable(); + _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; + disabled = (_vcpu->evtchn_upcall_mask != 0); + preempt_enable_no_resched(); + return disabled; +} +EXPORT_SYMBOL(raw_irqs_disabled); + +unsigned long __raw_local_irq_save(void) +{ + struct vcpu_info *_vcpu; + unsigned long flags; + + preempt_disable(); + _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; + flags = _vcpu->evtchn_upcall_mask; + _vcpu->evtchn_upcall_mask = 1; + preempt_enable_no_resched(); + + return flags; +} +EXPORT_SYMBOL(__raw_local_irq_save); diff --git a/arch/ia64/ia32/audit.c b/arch/ia64/ia32/audit.c new file mode 100644 index 000000000..92d7d0c8d --- /dev/null +++ b/arch/ia64/ia32/audit.c @@ -0,0 +1,37 @@ +#include <asm-i386/unistd.h> + +unsigned ia32_dir_class[] = { +#include <asm-generic/audit_dir_write.h> +~0U +}; + +unsigned ia32_chattr_class[] = { +#include <asm-generic/audit_change_attr.h> +~0U +}; + +unsigned ia32_write_class[] = { +#include <asm-generic/audit_write.h> +~0U +}; + +unsigned ia32_read_class[] = { +#include <asm-generic/audit_read.h> +~0U +}; + +int ia32_classify_syscall(unsigned syscall) +{ + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_socketcall: + return 4; + case __NR_execve: + return 5; + default: + return 1; + } +} diff --git a/arch/ia64/kernel/audit.c b/arch/ia64/kernel/audit.c new file mode 100644 index 000000000..04682555a --- /dev/null +++ b/arch/ia64/kernel/audit.c @@ -0,0 +1,64 @@ +#include <linux/init.h> +#include <linux/types.h> +#include <linux/audit.h> +#include <asm/unistd.h> + +static unsigned dir_class[] = { +#include <asm-generic/audit_dir_write.h> +~0U +}; + +static unsigned read_class[] = { +#include <asm-generic/audit_read.h> +~0U +}; + +static unsigned write_class[] = { +#include <asm-generic/audit_write.h> +~0U +}; + +static unsigned chattr_class[] = { +#include <asm-generic/audit_change_attr.h> +~0U +}; + +int audit_classify_syscall(int abi, unsigned syscall) +{ +#ifdef CONFIG_IA32_SUPPORT + extern int ia32_classify_syscall(unsigned); + if (abi == AUDIT_ARCH_I386) + return ia32_classify_syscall(syscall); +#endif + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_execve: + return 5; + default: + return 0; + } +} + +static int __init audit_classes_init(void) +{ +#ifdef CONFIG_IA32_SUPPORT + extern __u32 ia32_dir_class[]; + extern __u32 ia32_write_class[]; + extern __u32 ia32_read_class[]; + extern __u32 ia32_chattr_class[]; + audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class); + audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class); + audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class); + audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class); +#endif + audit_register_class(AUDIT_CLASS_WRITE, write_class); + audit_register_class(AUDIT_CLASS_READ, read_class); + audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); + audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); + return 0; +} + +__initcall(audit_classes_init); diff --git a/arch/ia64/xen/Makefile b/arch/ia64/xen/Makefile new file mode 100644 index 000000000..c2b4f94ed --- /dev/null +++ b/arch/ia64/xen/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for Xen components +# + +obj-y := hypercall.o xenivt.o xenentry.o xensetup.o xenpal.o xenhpski.o \ + hypervisor.o pci-dma-xen.o util.o + +pci-dma-xen-y := ../../i386/kernel/pci-dma-xen.o diff --git a/arch/ia64/xen/drivers/README b/arch/ia64/xen/drivers/README new file mode 100644 index 000000000..33aecaa2a --- /dev/null +++ b/arch/ia64/xen/drivers/README @@ -0,0 +1,2 @@ +This is a temporary location for source/Makefiles that need to be +patched/reworked in drivers/xen to work with xenlinux/ia64. diff --git a/arch/ia64/xen/hypercall.S b/arch/ia64/xen/hypercall.S new file mode 100644 index 000000000..399686576 --- /dev/null +++ b/arch/ia64/xen/hypercall.S @@ -0,0 +1,413 @@ +/* + * Support routines for Xen hypercalls + * + * Copyright (C) 2005 Dan Magenheimer <dan.magenheimer@hp.com> + */ + +#include <asm/processor.h> +#include <asm/asmmacro.h> + +/* To clear vpsr.ic, vpsr.i needs to be cleared first */ +#define XEN_CLEAR_PSR_IC \ + mov r14=1; \ + movl r15=XSI_PSR_I_ADDR; \ + movl r2=XSI_PSR_IC; \ + ;; \ + ld8 r15=[r15]; \ + ld4 r3=[r2]; \ + ;; \ + ld1 r16=[r15]; \ + ;; \ + st1 [r15]=r14; \ + st4 [r2]=r0; \ + ;; + +/* First restore vpsr.ic, and then vpsr.i */ +#define XEN_RESTORE_PSR_IC \ + st4 [r2]=r3; \ + st1 [r15]=r16; \ + ;; + +GLOBAL_ENTRY(xen_get_ivr) + movl r8=running_on_xen;; + ld4 r8=[r8];; + cmp.eq p7,p0=r8,r0;; +(p7) mov r8=cr.ivr;; +(p7) br.ret.sptk.many rp + ;; + XEN_CLEAR_PSR_IC + ;; + XEN_HYPER_GET_IVR + ;; + XEN_RESTORE_PSR_IC + ;; + br.ret.sptk.many rp + ;; +END(xen_get_ivr) + +GLOBAL_ENTRY(xen_get_tpr) + movl r8=running_on_xen;; + ld4 r8=[r8];; + cmp.eq p7,p0=r8,r0;; +(p7) mov r8=cr.tpr;; +(p7) br.ret.sptk.many rp + ;; + XEN_CLEAR_PSR_IC + ;; + XEN_HYPER_GET_TPR + ;; + XEN_RESTORE_PSR_IC + ;; + br.ret.sptk.many rp + ;; +END(xen_get_tpr) + +GLOBAL_ENTRY(xen_set_tpr) + movl r8=running_on_xen;; + ld4 r8=[r8];; + cmp.eq p7,p0=r8,r0;; +(p7) mov cr.tpr=r32;; +(p7) br.ret.sptk.many rp + ;; + mov r8=r32 + ;; + XEN_CLEAR_PSR_IC + ;; + XEN_HYPER_SET_TPR + ;; + XEN_RESTORE_PSR_IC + ;; + br.ret.sptk.many rp + ;; +END(xen_set_tpr) + +GLOBAL_ENTRY(xen_eoi) + movl r8=running_on_xen;; + ld4 r8=[r8];; + cmp.eq p7,p0=r8,r0;; +(p7) mov cr.eoi=r0;; +(p7) br.ret.sptk.many rp + ;; + mov r8=r32 + ;; + XEN_CLEAR_PSR_IC + ;; + XEN_HYPER_EOI + ;; + XEN_RESTORE_PSR_IC + ;; + br.ret.sptk.many rp + ;; +END(xen_eoi) + +GLOBAL_ENTRY(xen_thash) + movl r8=running_on_xen;; + ld4 r8=[r8];; + cmp.eq p7,p0=r8,r0;; +(p7) thash r8=r32;; +(p7) br.ret.sptk.many rp + ;; + mov r8=r32 + ;; + XEN_CLEAR_PSR_IC + ;; + XEN_HYPER_THASH + ;; + XEN_RESTORE_PSR_IC + ;; + br.ret.sptk.many rp + ;; +END(xen_thash) + +GLOBAL_ENTRY(xen_set_itm) + movl r8=running_on_xen;; + ld4 r8=[r8];; + cmp.eq p7,p0=r8,r0;; +(p7) mov cr.itm=r32;; +(p7) br.ret.sptk.many rp + ;; + mov r8=r32 + ;; + XEN_CLEAR_PSR_IC + ;; + XEN_HYPER_SET_ITM + ;; + XEN_RESTORE_PSR_IC + ;; + br.ret.sptk.many rp + ;; +END(xen_set_itm) + +GLOBAL_ENTRY(xen_ptcga) + movl r8=running_on_xen;; + ld4 r8=[r8];; + cmp.eq p7,p0=r8,r0;; +(p7) ptc.ga r32,r33;; +(p7) br.ret.sptk.many rp + ;; + mov r8=r32 + mov r9=r33 + ;; + XEN_CLEAR_PSR_IC + ;; + XEN_HYPER_PTC_GA + ;; + XEN_RESTORE_PSR_IC + ;; + br.ret.sptk.many rp + ;; +END(xen_ptcga) + +GLOBAL_ENTRY(xen_get_rr) + movl r8=running_on_xen;; + ld4 r8=[r8];; + cmp.eq p7,p0=r8,r0;; +(p7) mov r8=rr[r32];; +(p7) br.ret.sptk.many rp + ;; + mov r8=r32 + ;; + XEN_CLEAR_PSR_IC + ;; + XEN_HYPER_GET_RR + ;; + XEN_RESTORE_PSR_IC + ;; + br.ret.sptk.many rp + ;; +END(xen_get_rr) + +GLOBAL_ENTRY(xen_set_rr) + movl r8=running_on_xen;; + ld4 r8=[r8];; + cmp.eq p7,p0=r8,r0;; +(p7) mov rr[r32]=r33;; +(p7) br.ret.sptk.many rp + ;; + mov r8=r32 + mov r9=r33 + ;; + XEN_CLEAR_PSR_IC + ;; + XEN_HYPER_SET_RR + ;; + XEN_RESTORE_PSR_IC + ;; + br.ret.sptk.many rp + ;; +END(xen_set_rr) + +GLOBAL_ENTRY(xen_set_kr) + movl r8=running_on_xen;; + ld4 r8=[r8];; + cmp.ne p7,p0=r8,r0;; +(p7) br.cond.spnt.few 1f; + ;; + cmp.eq p7,p0=r8,r0 + adds r8=-1,r8;; +(p7) mov ar0=r9 +(p7) br.ret.sptk.many rp;; + cmp.eq p7,p0=r8,r0 + adds r8=-1,r8;; +(p7) mov ar1=r9 +(p7) br.ret.sptk.many rp;; + cmp.eq p7,p0=r8,r0 + adds r8=-1,r8;; +(p7) mov ar2=r9 +(p7) br.ret.sptk.many rp;; + cmp.eq p7,p0=r8,r0 + adds r8=-1,r8;; +(p7) mov ar3=r9 +(p7) br.ret.sptk.many rp;; + cmp.eq p7,p0=r8,r0 + adds r8=-1,r8;; +(p7) mov ar4=r9 +(p7) br.ret.sptk.many rp;; + cmp.eq p7,p0=r8,r0 + adds r8=-1,r8;; +(p7) mov ar5=r9 +(p7) br.ret.sptk.many rp;; + cmp.eq p7,p0=r8,r0 + adds r8=-1,r8;; +(p7) mov ar6=r9 +(p7) br.ret.sptk.many rp;; + cmp.eq p7,p0=r8,r0 + adds r8=-1,r8;; +(p7) mov ar7=r9 +(p7) br.ret.sptk.many rp;; + +1: mov r8=r32 + mov r9=r33 + ;; + XEN_CLEAR_PSR_IC + ;; + XEN_HYPER_SET_KR + ;; + XEN_RESTORE_PSR_IC + ;; + br.ret.sptk.many rp +END(xen_set_kr) + +GLOBAL_ENTRY(xen_fc) + movl r8=running_on_xen;; + ld4 r8=[r8];; + cmp.eq p7,p0=r8,r0;; +(p7) fc r32;; +(p7) br.ret.sptk.many rp + ;; + mov r8=r32 + ;; + XEN_CLEAR_PSR_IC + ;; + XEN_HYPER_FC + ;; + XEN_RESTORE_PSR_IC + ;; + br.ret.sptk.many rp +END(xen_fc) + +GLOBAL_ENTRY(xen_get_cpuid) + movl r8=running_on_xen;; + ld4 r8=[r8];; + cmp.eq p7,p0=r8,r0;; +(p7) mov r8=cpuid[r32];; +(p7) br.ret.sptk.many rp + ;; + mov r8=r32 + ;; + XEN_CLEAR_PSR_IC + ;; + XEN_HYPER_GET_CPUID + ;; + XEN_RESTORE_PSR_IC + ;; + br.ret.sptk.many rp +END(xen_get_cpuid) + +GLOBAL_ENTRY(xen_get_pmd) + movl r8=running_on_xen;; + ld4 r8=[r8];; + cmp.eq p7,p0=r8,r0;; +(p7) mov r8=pmd[r32];; +(p7) br.ret.sptk.many rp + ;; + mov r8=r32 + ;; + XEN_CLEAR_PSR_IC + ;; + XEN_HYPER_GET_PMD + ;; + XEN_RESTORE_PSR_IC + ;; + br.ret.sptk.many rp +END(xen_get_pmd) + +#ifdef CONFIG_IA32_SUPPORT +GLOBAL_ENTRY(xen_get_eflag) + movl r8=running_on_xen;; + ld4 r8=[r8];; + cmp.eq p7,p0=r8,r0;; +(p7) mov r8=ar24;; +(p7) br.ret.sptk.many rp + ;; + mov r8=r32 + ;; + XEN_CLEAR_PSR_IC + ;; + XEN_HYPER_GET_EFLAG + ;; + XEN_RESTORE_PSR_IC + ;; + br.ret.sptk.many rp +END(xen_get_eflag) + +// some bits aren't set if pl!=0, see SDM vol1 3.1.8 +GLOBAL_ENTRY(xen_set_eflag) + movl r8=running_on_xen;; + ld4 r8=[r8];; + cmp.eq p7,p0=r8,r0;; +(p7) mov ar24=r32 +(p7) br.ret.sptk.many rp + ;; + mov r8=r32 + ;; + XEN_CLEAR_PSR_IC + ;; + XEN_HYPER_SET_EFLAG + ;; + XEN_RESTORE_PSR_IC + ;; + br.ret.sptk.many rp +END(xen_set_eflag) +#endif + +GLOBAL_ENTRY(xen_send_ipi) + mov r14=r32 + mov r15=r33 + mov r2=0x400 + break 0x1000 + ;; + br.ret.sptk.many rp + ;; +END(xen_send_ipi) + +#ifdef CONFIG_XEN_IA64_VDSO_PARAVIRT +// Those are vdso specialized. +// In fsys mode, call, ret can't be used. +GLOBAL_ENTRY(xen_rsm_be_i) + ld8 r22=[r22] + ;; + st1 [r22]=r20 + st4 [r23]=r0 + XEN_HYPER_RSM_BE + st4 [r23]=r20 + brl.cond.sptk .vdso_rsm_be_i_ret + ;; +END(xen_rsm_be_i) + +GLOBAL_ENTRY(xen_get_psr) + mov r31=r8 + mov r25=IA64_PSR_IC + st4 [r23]=r0 + XEN_HYPER_GET_PSR + ;; + st4 [r23]=r20 + or r29=r8,r25 // vpsr.ic was cleared for hyperprivop + mov r8=r31 + brl.cond.sptk .vdso_get_psr_ret + ;; +END(xen_get_psr) + + // see xen_ssm_i() in privop.h + // r22 = &vcpu->evtchn_mask + // r23 = &vpsr.ic + // r24 = &vcpu->pending_interruption + // r25 = tmp + // r31 = tmp + // p11 = tmp + // p14 = tmp +#define XEN_SET_PSR_I \ + ld4 r31=[r22]; \ + ld4 r25=[r24]; \ + ;; \ + st4 [r22]=r0; \ + cmp.ne.unc p14,p0=r0,r31; \ + ;; \ +(p14) cmp.ne.unc p11,p0=r0,r25; \ + ;; \ +(p11) st4 [r22]=r20; \ +(p11) st4 [r23]=r0; \ +(p11) XEN_HYPER_SSM_I; + +GLOBAL_ENTRY(xen_ssm_i_0) + XEN_SET_PSR_I + brl.cond.sptk .vdso_ssm_i_0_ret + ;; +END(xen_ssm_i_0) + +GLOBAL_ENTRY(xen_ssm_i_1) + XEN_SET_PSR_I + brl.cond.sptk .vdso_ssm_i_1_ret + ;; +END(xen_ssm_i_1) +#endif diff --git a/arch/ia64/xen/hypervisor.c b/arch/ia64/xen/hypervisor.c new file mode 100644 index 000000000..0b286047b --- /dev/null +++ b/arch/ia64/xen/hypervisor.c @@ -0,0 +1,833 @@ +/****************************************************************************** + * include/asm-ia64/shadow.h + * + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +//#include <linux/kernel.h> +#include <linux/spinlock.h> +#include <linux/bootmem.h> +#include <linux/module.h> +#include <linux/vmalloc.h> +#include <asm/page.h> +#include <asm/hypervisor.h> +#include <asm/hypercall.h> +#include <xen/interface/memory.h> +#include <xen/balloon.h> + +shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)XSI_BASE; +EXPORT_SYMBOL(HYPERVISOR_shared_info); + +start_info_t *xen_start_info; +EXPORT_SYMBOL(xen_start_info); + +int running_on_xen; +EXPORT_SYMBOL(running_on_xen); + +//XXX xen/ia64 copy_from_guest() is broken. +// This is a temporal work around until it is fixed. +// used by balloon.c netfront.c + +// get_xen_guest_handle is defined only when __XEN_TOOLS__ is defined +// if the definition in arch-ia64.h is changed, this must be updated. +#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0) + +int +ia64_xenmem_reservation_op(unsigned long op, + struct xen_memory_reservation* reservation__) +{ + struct xen_memory_reservation reservation = *reservation__; + unsigned long* frame_list; + unsigned long nr_extents = reservation__->nr_extents; + int ret = 0; + get_xen_guest_handle(frame_list, reservation__->extent_start); + + BUG_ON(op != XENMEM_increase_reservation && + op != XENMEM_decrease_reservation && + op != XENMEM_populate_physmap); + + while (nr_extents > 0) { + int tmp_ret; + volatile unsigned long dummy; + + set_xen_guest_handle(reservation.extent_start, frame_list); + reservation.nr_extents = nr_extents; + + dummy = frame_list[0];// re-install tlb entry before hypercall + tmp_ret = ____HYPERVISOR_memory_op(op, &reservation); + if (tmp_ret < 0) { + if (ret == 0) { + ret = tmp_ret; + } + break; + } + if (tmp_ret == 0) { + //XXX dirty work around for skbuff_ctor() + // of a non-privileged domain, + if ((op == XENMEM_increase_reservation || + op == XENMEM_populate_physmap) && + !is_initial_xendomain() && + reservation.extent_order > 0) + return ret; + } + frame_list += tmp_ret; + nr_extents -= tmp_ret; + ret += tmp_ret; + } + return ret; +} +EXPORT_SYMBOL(ia64_xenmem_reservation_op); + +//XXX same as i386, x86_64 contiguous_bitmap_set(), contiguous_bitmap_clear() +// move those to lib/contiguous_bitmap? +//XXX discontigmem/sparsemem + +/* + * Bitmap is indexed by page number. If bit is set, the page is part of a + * xen_create_contiguous_region() area of memory. + */ +unsigned long *contiguous_bitmap; + +void +contiguous_bitmap_init(unsigned long end_pfn) +{ + unsigned long size = (end_pfn + 2 * BITS_PER_LONG) >> 3; + contiguous_bitmap = alloc_bootmem_low_pages(size); + BUG_ON(!contiguous_bitmap); + memset(contiguous_bitmap, 0, size); +} + +#if 0 +int +contiguous_bitmap_test(void* p) +{ + return test_bit(__pa(p) >> PAGE_SHIFT, contiguous_bitmap); +} +#endif + +static void contiguous_bitmap_set( + unsigned long first_page, unsigned long nr_pages) +{ + unsigned long start_off, end_off, curr_idx, end_idx; + + curr_idx = first_page / BITS_PER_LONG; + start_off = first_page & (BITS_PER_LONG-1); + end_idx = (first_page + nr_pages) / BITS_PER_LONG; + end_off = (first_page + nr_pages) & (BITS_PER_LONG-1); + + if (curr_idx == end_idx) { + contiguous_bitmap[curr_idx] |= + ((1UL<<end_off)-1) & -(1UL<<start_off); + } else { + contiguous_bitmap[curr_idx] |= -(1UL<<start_off); + while ( ++curr_idx < end_idx ) + contiguous_bitmap[curr_idx] = ~0UL; + contiguous_bitmap[curr_idx] |= (1UL<<end_off)-1; + } +} + +static void contiguous_bitmap_clear( + unsigned long first_page, unsigned long nr_pages) +{ + unsigned long start_off, end_off, curr_idx, end_idx; + + curr_idx = first_page / BITS_PER_LONG; + start_off = first_page & (BITS_PER_LONG-1); + end_idx = (first_page + nr_pages) / BITS_PER_LONG; + end_off = (first_page + nr_pages) & (BITS_PER_LONG-1); + + if (curr_idx == end_idx) { + contiguous_bitmap[curr_idx] &= + -(1UL<<end_off) | ((1UL<<start_off)-1); + } else { + contiguous_bitmap[curr_idx] &= (1UL<<start_off)-1; + while ( ++curr_idx != end_idx ) + contiguous_bitmap[curr_idx] = 0; + contiguous_bitmap[curr_idx] &= -(1UL<<end_off); + } +} + +// __xen_create_contiguous_region(), __xen_destroy_contiguous_region() +// are based on i386 xen_create_contiguous_region(), +// xen_destroy_contiguous_region() + +/* Protected by balloon_lock. */ +#define MAX_CONTIG_ORDER 7 +static unsigned long discontig_frames[1<<MAX_CONTIG_ORDER]; + +/* Ensure multi-page extents are contiguous in machine memory. */ +int +__xen_create_contiguous_region(unsigned long vstart, + unsigned int order, unsigned int address_bits) +{ + unsigned long error = 0; + unsigned long gphys = __pa(vstart); + unsigned long start_gpfn = gphys >> PAGE_SHIFT; + unsigned long num_gpfn = 1 << order; + unsigned long i; + unsigned long flags; + + unsigned long *in_frames = discontig_frames, out_frame; + int success; + struct xen_memory_exchange exchange = { + .in = { + .nr_extents = num_gpfn, + .extent_order = 0, + .domid = DOMID_SELF + }, + .out = { + .nr_extents = 1, + .extent_order = order, + .address_bits = address_bits, + .domid = DOMID_SELF + }, + .nr_exchanged = 0 + }; + + if (unlikely(order > MAX_CONTIG_ORDER)) + return -ENOMEM; + + set_xen_guest_handle(exchange.in.extent_start, in_frames); + set_xen_guest_handle(exchange.out.extent_start, &out_frame); + + scrub_pages(vstart, num_gpfn); + + balloon_lock(flags); + + /* Get a new contiguous memory extent. */ + for (i = 0; i < num_gpfn; i++) { + in_frames[i] = start_gpfn + i; + } + out_frame = start_gpfn; + error = HYPERVISOR_memory_op(XENMEM_exchange, &exchange); + success = (exchange.nr_exchanged == num_gpfn); + BUG_ON(!success && ((exchange.nr_exchanged != 0) || (error == 0))); + BUG_ON(success && (error != 0)); + if (unlikely(error == -ENOSYS)) { + /* Compatibility when XENMEM_exchange is unsupported. */ + error = HYPERVISOR_memory_op(XENMEM_decrease_reservation, + &exchange.in); + BUG_ON(error != num_gpfn); + error = HYPERVISOR_memory_op(XENMEM_populate_physmap, + &exchange.out); + if (error != 1) { + /* Couldn't get special memory: fall back to normal. */ + for (i = 0; i < num_gpfn; i++) { + in_frames[i] = start_gpfn + i; + } + error = HYPERVISOR_memory_op(XENMEM_populate_physmap, + &exchange.in); + BUG_ON(error != num_gpfn); + success = 0; + } else + success = 1; + } + if (success) + contiguous_bitmap_set(start_gpfn, num_gpfn); +#if 0 + if (success) { + unsigned long mfn; + unsigned long mfn_prev = ~0UL; + for (i = 0; i < num_gpfn; i++) { + mfn = pfn_to_mfn_for_dma(start_gpfn + i); + if (mfn_prev != ~0UL && mfn != mfn_prev + 1) { + xprintk("\n"); + xprintk("%s:%d order %d " + "start 0x%lx bus 0x%lx " + "machine 0x%lx\n", + __func__, __LINE__, order, + vstart, virt_to_bus((void*)vstart), + phys_to_machine_for_dma(gphys)); + xprintk("mfn: "); + for (i = 0; i < num_gpfn; i++) { + mfn = pfn_to_mfn_for_dma( + start_gpfn + i); + xprintk("0x%lx ", mfn); + } + xprintk("\n"); + break; + } + mfn_prev = mfn; + } + } +#endif + balloon_unlock(flags); + return success? 0: -ENOMEM; +} + +void +__xen_destroy_contiguous_region(unsigned long vstart, unsigned int order) +{ + unsigned long flags; + unsigned long error = 0; + unsigned long start_gpfn = __pa(vstart) >> PAGE_SHIFT; + unsigned long num_gpfn = 1UL << order; + unsigned long i; + + unsigned long *out_frames = discontig_frames, in_frame; + int success; + struct xen_memory_exchange exchange = { + .in = { + .nr_extents = 1, + .extent_order = order, + .domid = DOMID_SELF + }, + .out = { + .nr_extents = num_gpfn, + .extent_order = 0, + .address_bits = 0, + .domid = DOMID_SELF + }, + .nr_exchanged = 0 + }; + + + if (!test_bit(start_gpfn, contiguous_bitmap)) + return; + + if (unlikely(order > MAX_CONTIG_ORDER)) + return; + + set_xen_guest_handle(exchange.in.extent_start, &in_frame); + set_xen_guest_handle(exchange.out.extent_start, out_frames); + + scrub_pages(vstart, num_gpfn); + + balloon_lock(flags); + + contiguous_bitmap_clear(start_gpfn, num_gpfn); + + /* Do the exchange for non-contiguous MFNs. */ + in_frame = start_gpfn; + for (i = 0; i < num_gpfn; i++) { + out_frames[i] = start_gpfn + i; + } + error = HYPERVISOR_memory_op(XENMEM_exchange, &exchange); + success = (exchange.nr_exchanged == 1); + BUG_ON(!success && ((exchange.nr_exchanged != 0) || (error == 0))); + BUG_ON(success && (error != 0)); + if (unlikely(error == -ENOSYS)) { + /* Compatibility when XENMEM_exchange is unsupported. */ + error = HYPERVISOR_memory_op(XENMEM_decrease_reservation, + &exchange.in); + BUG_ON(error != 1); + + error = HYPERVISOR_memory_op(XENMEM_populate_physmap, + &exchange.out); + BUG_ON(error != num_gpfn); + } + balloon_unlock(flags); +} + + +/////////////////////////////////////////////////////////////////////////// +// grant table hack +// cmd: GNTTABOP_xxx + +#include <linux/mm.h> +#include <xen/interface/xen.h> +#include <xen/gnttab.h> + +static void +gnttab_map_grant_ref_pre(struct gnttab_map_grant_ref *uop) +{ + uint32_t flags; + + flags = uop->flags; + + if (flags & GNTMAP_host_map) { + if (flags & GNTMAP_application_map) { + xprintd("GNTMAP_application_map is not supported yet: flags 0x%x\n", flags); + BUG(); + } + if (flags & GNTMAP_contains_pte) { + xprintd("GNTMAP_contains_pte is not supported yet flags 0x%x\n", flags); + BUG(); + } + } else if (flags & GNTMAP_device_map) { + xprintd("GNTMAP_device_map is not supported yet 0x%x\n", flags); + BUG();//XXX not yet. actually this flag is not used. + } else { + BUG(); + } +} + +int +HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count) +{ + __u64 va1, va2, pa1, pa2; + + if (cmd == GNTTABOP_map_grant_ref) { + unsigned int i; + for (i = 0; i < count; i++) { + gnttab_map_grant_ref_pre( + (struct gnttab_map_grant_ref*)uop + i); + } + } + va1 = (__u64)uop & PAGE_MASK; + pa1 = pa2 = 0; + if ((REGION_NUMBER(va1) == 5) && + ((va1 - KERNEL_START) >= KERNEL_TR_PAGE_SIZE)) { + pa1 = ia64_tpa(va1); + if (cmd <= GNTTABOP_transfer) { + static uint32_t uop_size[GNTTABOP_transfer + 1] = { + sizeof(struct gnttab_map_grant_ref), + sizeof(struct gnttab_unmap_grant_ref), + sizeof(struct gnttab_setup_table), + sizeof(struct gnttab_dump_table), + sizeof(struct gnttab_transfer), + }; + va2 = (__u64)uop + (uop_size[cmd] * count) - 1; + va2 &= PAGE_MASK; + if (va1 != va2) { + /* maximum size of uop is 2pages */ + BUG_ON(va2 > va1 + PAGE_SIZE); + pa2 = ia64_tpa(va2); + } + } + } + return ____HYPERVISOR_grant_table_op(cmd, uop, count, pa1, pa2); +} +EXPORT_SYMBOL(HYPERVISOR_grant_table_op); + +/////////////////////////////////////////////////////////////////////////// +// PageForeign(), SetPageForeign(), ClearPageForeign() + +struct address_space xen_ia64_foreign_dummy_mapping; +EXPORT_SYMBOL(xen_ia64_foreign_dummy_mapping); + +/////////////////////////////////////////////////////////////////////////// +// foreign mapping +#include <linux/efi.h> +#include <asm/meminit.h> // for IA64_GRANULE_SIZE, GRANULEROUND{UP,DOWN}() + +static unsigned long privcmd_resource_min = 0; +// Xen/ia64 currently can handle pseudo physical address bits up to +// (PAGE_SHIFT * 3) +static unsigned long privcmd_resource_max = GRANULEROUNDDOWN((1UL << (PAGE_SHIFT * 3)) - 1); +static unsigned long privcmd_resource_align = IA64_GRANULE_SIZE; + +static unsigned long +md_end_addr(const efi_memory_desc_t *md) +{ + return md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT); +} + +#define XEN_IA64_PRIVCMD_LEAST_GAP_SIZE (1024 * 1024 * 1024UL) +static int +xen_ia64_privcmd_check_size(unsigned long start, unsigned long end) +{ + return (start < end && + (end - start) > XEN_IA64_PRIVCMD_LEAST_GAP_SIZE); +} + +static int __init +xen_ia64_privcmd_init(void) +{ + void *efi_map_start, *efi_map_end, *p; + u64 efi_desc_size; + efi_memory_desc_t *md; + unsigned long tmp_min; + unsigned long tmp_max; + unsigned long gap_size; + unsigned long prev_end; + + if (!is_running_on_xen()) + return -1; + + efi_map_start = __va(ia64_boot_param->efi_memmap); + efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; + efi_desc_size = ia64_boot_param->efi_memdesc_size; + + // at first check the used highest address + for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { + // nothing + } + md = p - efi_desc_size; + privcmd_resource_min = GRANULEROUNDUP(md_end_addr(md)); + if (xen_ia64_privcmd_check_size(privcmd_resource_min, + privcmd_resource_max)) { + goto out; + } + + // the used highest address is too large. try to find the largest gap. + tmp_min = privcmd_resource_max; + tmp_max = 0; + gap_size = 0; + prev_end = 0; + for (p = efi_map_start; + p < efi_map_end - efi_desc_size; + p += efi_desc_size) { + unsigned long end; + efi_memory_desc_t* next; + unsigned long next_start; + + md = p; + end = md_end_addr(md); + if (end > privcmd_resource_max) { + break; + } + if (end < prev_end) { + // work around. + // Xen may pass incompletely sorted memory + // descriptors like + // [x, x + length] + // [x, x] + // this order should be reversed. + continue; + } + next = p + efi_desc_size; + next_start = next->phys_addr; + if (next_start > privcmd_resource_max) { + next_start = privcmd_resource_max; + } + if (end < next_start && gap_size < (next_start - end)) { + tmp_min = end; + tmp_max = next_start; + gap_size = tmp_max - tmp_min; + } + prev_end = end; + } + + privcmd_resource_min = GRANULEROUNDUP(tmp_min); + if (xen_ia64_privcmd_check_size(privcmd_resource_min, tmp_max)) { + privcmd_resource_max = tmp_max; + goto out; + } + + privcmd_resource_min = tmp_min; + privcmd_resource_max = tmp_max; + if (!xen_ia64_privcmd_check_size(privcmd_resource_min, + privcmd_resource_max)) { + // Any large enough gap isn't found. + // go ahead anyway with the warning hoping that large region + // won't be requested. + printk(KERN_WARNING "xen privcmd: large enough region for privcmd mmap is not found.\n"); + } + +out: + printk(KERN_INFO "xen privcmd uses pseudo physical addr range [0x%lx, 0x%lx] (%ldMB)\n", + privcmd_resource_min, privcmd_resource_max, + (privcmd_resource_max - privcmd_resource_min) >> 20); + BUG_ON(privcmd_resource_min >= privcmd_resource_max); + return 0; +} +late_initcall(xen_ia64_privcmd_init); + +struct xen_ia64_privcmd_entry { + atomic_t map_count; +#define INVALID_GPFN (~0UL) + unsigned long gpfn; +}; + +struct xen_ia64_privcmd_range { + atomic_t ref_count; + unsigned long pgoff; // in PAGE_SIZE + struct resource* res; + + unsigned long num_entries; + struct xen_ia64_privcmd_entry entries[0]; +}; + +struct xen_ia64_privcmd_vma { + struct xen_ia64_privcmd_range* range; + + unsigned long num_entries; + struct xen_ia64_privcmd_entry* entries; +}; + +static void +xen_ia64_privcmd_init_entry(struct xen_ia64_privcmd_entry* entry) +{ + atomic_set(&entry->map_count, 0); + entry->gpfn = INVALID_GPFN; +} + +static int +xen_ia64_privcmd_entry_mmap(struct vm_area_struct* vma, + unsigned long addr, + struct xen_ia64_privcmd_range* privcmd_range, + int i, + unsigned long mfn, + pgprot_t prot, + domid_t domid) +{ + int error = 0; + struct xen_ia64_privcmd_entry* entry = &privcmd_range->entries[i]; + unsigned long gpfn; + unsigned long flags; + + if ((addr & ~PAGE_MASK) != 0 || mfn == INVALID_MFN) { + error = -EINVAL; + goto out; + } + + if (entry->gpfn != INVALID_GPFN) { + error = -EBUSY; + goto out; + } + gpfn = (privcmd_range->res->start >> PAGE_SHIFT) + i; + + flags = ASSIGN_writable; + if (pgprot_val(prot) == PROT_READ) { + flags = ASSIGN_readonly; + } + error = HYPERVISOR_add_physmap(gpfn, mfn, flags, domid); + if (error != 0) { + goto out; + } + + prot = vma->vm_page_prot; + error = remap_pfn_range(vma, addr, gpfn, 1 << PAGE_SHIFT, prot); + if (error != 0) { + error = HYPERVISOR_zap_physmap(gpfn, 0); + if (error) { + BUG();//XXX + } + } else { + atomic_inc(&entry->map_count); + entry->gpfn = gpfn; + } + +out: + return error; +} + +static void +xen_ia64_privcmd_entry_munmap(struct xen_ia64_privcmd_range* privcmd_range, + int i) +{ + struct xen_ia64_privcmd_entry* entry = &privcmd_range->entries[i]; + unsigned long gpfn = entry->gpfn; + //gpfn = (privcmd_range->res->start >> PAGE_SHIFT) + + // (vma->vm_pgoff - privcmd_range->pgoff); + int error; + + error = HYPERVISOR_zap_physmap(gpfn, 0); + if (error) { + BUG();//XXX + } + entry->gpfn = INVALID_GPFN; +} + +static void +xen_ia64_privcmd_entry_open(struct xen_ia64_privcmd_range* privcmd_range, + int i) +{ + struct xen_ia64_privcmd_entry* entry = &privcmd_range->entries[i]; + if (entry->gpfn != INVALID_GPFN) { + atomic_inc(&entry->map_count); + } else { + BUG_ON(atomic_read(&entry->map_count) != 0); + } +} + +static void +xen_ia64_privcmd_entry_close(struct xen_ia64_privcmd_range* privcmd_range, + int i) +{ + struct xen_ia64_privcmd_entry* entry = &privcmd_range->entries[i]; + if (entry->gpfn != INVALID_GPFN && + atomic_dec_and_test(&entry->map_count)) { + xen_ia64_privcmd_entry_munmap(privcmd_range, i); + } +} + +static void xen_ia64_privcmd_vma_open(struct vm_area_struct* vma); +static void xen_ia64_privcmd_vma_close(struct vm_area_struct* vma); + +struct vm_operations_struct xen_ia64_privcmd_vm_ops = { + .open = &xen_ia64_privcmd_vma_open, + .close = &xen_ia64_privcmd_vma_close, +}; + +static void +__xen_ia64_privcmd_vma_open(struct vm_area_struct* vma, + struct xen_ia64_privcmd_vma* privcmd_vma, + struct xen_ia64_privcmd_range* privcmd_range) +{ + unsigned long entry_offset = vma->vm_pgoff - privcmd_range->pgoff; + unsigned long num_entries = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + unsigned long i; + + BUG_ON(entry_offset < 0); + BUG_ON(entry_offset + num_entries > privcmd_range->num_entries); + + privcmd_vma->range = privcmd_range; + privcmd_vma->num_entries = num_entries; + privcmd_vma->entries = &privcmd_range->entries[entry_offset]; + vma->vm_private_data = privcmd_vma; + for (i = 0; i < privcmd_vma->num_entries; i++) { + xen_ia64_privcmd_entry_open(privcmd_range, entry_offset + i); + } + + vma->vm_private_data = privcmd_vma; + vma->vm_ops = &xen_ia64_privcmd_vm_ops; +} + +static void +xen_ia64_privcmd_vma_open(struct vm_area_struct* vma) +{ + struct xen_ia64_privcmd_vma* privcmd_vma = (struct xen_ia64_privcmd_vma*)vma->vm_private_data; + struct xen_ia64_privcmd_range* privcmd_range = privcmd_vma->range; + + atomic_inc(&privcmd_range->ref_count); + // vm_op->open() can't fail. + privcmd_vma = kmalloc(sizeof(*privcmd_vma), GFP_KERNEL | __GFP_NOFAIL); + + __xen_ia64_privcmd_vma_open(vma, privcmd_vma, privcmd_range); +} + +static void +xen_ia64_privcmd_vma_close(struct vm_area_struct* vma) +{ + struct xen_ia64_privcmd_vma* privcmd_vma = + (struct xen_ia64_privcmd_vma*)vma->vm_private_data; + struct xen_ia64_privcmd_range* privcmd_range = privcmd_vma->range; + unsigned long entry_offset = vma->vm_pgoff - privcmd_range->pgoff; + unsigned long i; + + for (i = 0; i < privcmd_vma->num_entries; i++) { + xen_ia64_privcmd_entry_close(privcmd_range, entry_offset + i); + } + vma->vm_private_data = NULL; + kfree(privcmd_vma); + + if (atomic_dec_and_test(&privcmd_range->ref_count)) { +#if 1 + for (i = 0; i < privcmd_range->num_entries; i++) { + struct xen_ia64_privcmd_entry* entry = + &privcmd_range->entries[i]; + BUG_ON(atomic_read(&entry->map_count) != 0); + BUG_ON(entry->gpfn != INVALID_GPFN); + } +#endif + release_resource(privcmd_range->res); + kfree(privcmd_range->res); + vfree(privcmd_range); + } +} + +int +privcmd_mmap(struct file * file, struct vm_area_struct * vma) +{ + int error; + unsigned long size = vma->vm_end - vma->vm_start; + unsigned long num_entries = size >> PAGE_SHIFT; + struct xen_ia64_privcmd_range* privcmd_range = NULL; + struct xen_ia64_privcmd_vma* privcmd_vma = NULL; + struct resource* res = NULL; + unsigned long i; + BUG_ON(!is_running_on_xen()); + + BUG_ON(file->private_data != NULL); + + error = -ENOMEM; + privcmd_range = + vmalloc(sizeof(*privcmd_range) + + sizeof(privcmd_range->entries[0]) * num_entries); + if (privcmd_range == NULL) { + goto out_enomem0; + } + privcmd_vma = kmalloc(sizeof(*privcmd_vma), GFP_KERNEL); + if (privcmd_vma == NULL) { + goto out_enomem1; + } + res = kzalloc(sizeof(*res), GFP_KERNEL); + if (res == NULL) { + goto out_enomem1; + } + res->name = "Xen privcmd mmap"; + error = allocate_resource(&iomem_resource, res, size, + privcmd_resource_min, privcmd_resource_max, + privcmd_resource_align, NULL, NULL); + if (error) { + goto out_enomem1; + } + privcmd_range->res = res; + + /* DONTCOPY is essential for Xen as copy_page_range is broken. */ + vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY | VM_PFNMAP; + + atomic_set(&privcmd_range->ref_count, 1); + privcmd_range->pgoff = vma->vm_pgoff; + privcmd_range->num_entries = num_entries; + for (i = 0; i < privcmd_range->num_entries; i++) { + xen_ia64_privcmd_init_entry(&privcmd_range->entries[i]); + } + + __xen_ia64_privcmd_vma_open(vma, privcmd_vma, privcmd_range); + return 0; + +out_enomem1: + kfree(res); + kfree(privcmd_vma); +out_enomem0: + vfree(privcmd_range); + return error; +} + +int +direct_remap_pfn_range(struct vm_area_struct *vma, + unsigned long address, // process virtual address + unsigned long mfn, // mfn, mfn + 1, ... mfn + size/PAGE_SIZE + unsigned long size, + pgprot_t prot, + domid_t domid) // target domain +{ + struct xen_ia64_privcmd_vma* privcmd_vma = + (struct xen_ia64_privcmd_vma*)vma->vm_private_data; + struct xen_ia64_privcmd_range* privcmd_range = privcmd_vma->range; + unsigned long entry_offset = vma->vm_pgoff - privcmd_range->pgoff; + + unsigned long i; + unsigned long offset; + int error = 0; + BUG_ON(!is_running_on_xen()); + +#if 0 + if (prot != vm->vm_page_prot) { + return -EINVAL; + } +#endif + + i = (address - vma->vm_start) >> PAGE_SHIFT; + for (offset = 0; offset < size; offset += PAGE_SIZE) { + error = xen_ia64_privcmd_entry_mmap(vma, (address + offset) & PAGE_MASK, privcmd_range, entry_offset + i, mfn, prot, domid); + if (error != 0) { + break; + } + + i++; + mfn++; + } + + return error; +} + + +/* Called after suspend, to resume time. */ +void +time_resume(void) +{ + extern void ia64_cpu_local_tick(void); + + /* Just trigger a tick. */ + ia64_cpu_local_tick(); +} diff --git a/arch/ia64/xen/util.c b/arch/ia64/xen/util.c new file mode 100644 index 000000000..03ac49584 --- /dev/null +++ b/arch/ia64/xen/util.c @@ -0,0 +1,115 @@ +/****************************************************************************** + * arch/ia64/xen/util.c + * This file is the ia64 counterpart of drivers/xen/util.c + * + * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp> + * VA Linux Systems Japan K.K. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <xen/driver_util.h> + +struct vm_struct *alloc_vm_area(unsigned long size) +{ + int order; + unsigned long virt; + unsigned long nr_pages; + struct vm_struct* area; + + order = get_order(size); + virt = __get_free_pages(GFP_KERNEL, order); + if (virt == 0) { + goto err0; + } + nr_pages = 1 << order; + scrub_pages(virt, nr_pages); + + area = kmalloc(sizeof(*area), GFP_KERNEL); + if (area == NULL) { + goto err1; + } + + area->flags = VM_IOREMAP;//XXX + area->addr = (void*)virt; + area->size = size; + area->pages = NULL; //XXX + area->nr_pages = nr_pages; + area->phys_addr = 0; /* xenbus_map_ring_valloc uses this field! */ + + return area; + +err1: + free_pages(virt, order); +err0: + return NULL; + +} +EXPORT_SYMBOL_GPL(alloc_vm_area); + +void free_vm_area(struct vm_struct *area) +{ + unsigned int order = get_order(area->size); + unsigned long i; + unsigned long phys_addr = __pa(area->addr); + + // This area is used for foreign page mappping. + // So underlying machine page may not be assigned. + for (i = 0; i < (1 << order); i++) { + unsigned long ret; + unsigned long gpfn = (phys_addr >> PAGE_SHIFT) + i; + struct xen_memory_reservation reservation = { + .nr_extents = 1, + .address_bits = 0, + .extent_order = 0, + .domid = DOMID_SELF + }; + set_xen_guest_handle(reservation.extent_start, &gpfn); + ret = HYPERVISOR_memory_op(XENMEM_populate_physmap, + &reservation); + BUG_ON(ret != 1); + } + free_pages((unsigned long)area->addr, order); + kfree(area); +} +EXPORT_SYMBOL_GPL(free_vm_area); + +void lock_vm_area(struct vm_struct *area) +{ + // nothing +} +EXPORT_SYMBOL_GPL(lock_vm_area); + +void unlock_vm_area(struct vm_struct *area) +{ + // nothing +} +EXPORT_SYMBOL_GPL(unlock_vm_area); + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/arch/ia64/xen/xenentry.S b/arch/ia64/xen/xenentry.S new file mode 100644 index 000000000..ad9e79a91 --- /dev/null +++ b/arch/ia64/xen/xenentry.S @@ -0,0 +1,867 @@ +/* + * ia64/xen/entry.S + * + * Alternate kernel routines for Xen. Heavily leveraged from + * ia64/kernel/entry.S + * + * Copyright (C) 2005 Hewlett-Packard Co + * Dan Magenheimer <dan.magenheimer@.hp.com> + */ + +#include <asm/asmmacro.h> +#include <asm/cache.h> +#include <asm/errno.h> +#include <asm/kregs.h> +#include <asm/asm-offsets.h> +#include <asm/pgtable.h> +#include <asm/percpu.h> +#include <asm/processor.h> +#include <asm/thread_info.h> +#include <asm/unistd.h> + +#ifdef CONFIG_XEN +#include "xenminstate.h" +#else +#include "minstate.h" +#endif + +/* + * prev_task <- ia64_switch_to(struct task_struct *next) + * With Ingo's new scheduler, interrupts are disabled when this routine gets + * called. The code starting at .map relies on this. The rest of the code + * doesn't care about the interrupt masking status. + */ +#ifdef CONFIG_XEN +GLOBAL_ENTRY(xen_switch_to) + .prologue + alloc r16=ar.pfs,1,0,0,0 + movl r22=running_on_xen;; + ld4 r22=[r22];; + cmp.eq p7,p0=r22,r0 +(p7) br.cond.sptk.many __ia64_switch_to;; +#else +GLOBAL_ENTRY(ia64_switch_to) + .prologue + alloc r16=ar.pfs,1,0,0,0 +#endif + DO_SAVE_SWITCH_STACK + .body + + adds r22=IA64_TASK_THREAD_KSP_OFFSET,r13 + movl r25=init_task + mov r27=IA64_KR(CURRENT_STACK) + adds r21=IA64_TASK_THREAD_KSP_OFFSET,in0 + dep r20=0,in0,61,3 // physical address of "next" + ;; + st8 [r22]=sp // save kernel stack pointer of old task + shr.u r26=r20,IA64_GRANULE_SHIFT + cmp.eq p7,p6=r25,in0 + ;; +#ifdef CONFIG_XEN + movl r8=XSI_PSR_IC + ;; + st4 [r8]=r0 // force psr.ic off for hyperprivop(s) + ;; +#endif + /* + * If we've already mapped this task's page, we can skip doing it again. + */ +(p6) cmp.eq p7,p6=r26,r27 +(p6) br.cond.dpnt .map + ;; +.done: +#ifdef CONFIG_XEN + // psr.ic already off + // update "current" application register + mov r8=IA64_KR_CURRENT + mov r9=in0;; + XEN_HYPER_SET_KR + ld8 sp=[r21] // load kernel stack pointer of new task + movl r27=XSI_PSR_IC + mov r8=1 + ;; + st4 [r27]=r8 // psr.ic back on +#else + ld8 sp=[r21] // load kernel stack pointer of new task + mov IA64_KR(CURRENT)=in0 // update "current" application register +#endif + mov r8=r13 // return pointer to previously running task + mov r13=in0 // set "current" pointer + ;; + DO_LOAD_SWITCH_STACK + +#ifdef CONFIG_SMP + sync.i // ensure "fc"s done by this CPU are visible on other CPUs +#endif + br.ret.sptk.many rp // boogie on out in new context + +.map: +#ifdef CONFIG_XEN + // psr.ic already off +#else + rsm psr.ic // interrupts (psr.i) are already disabled here +#endif + movl r25=PAGE_KERNEL + ;; + srlz.d + or r23=r25,r20 // construct PA | page properties + mov r25=IA64_GRANULE_SHIFT<<2 + ;; +#ifdef CONFIG_XEN + movl r8=XSI_ITIR + ;; + st8 [r8]=r25 + ;; + movl r8=XSI_IFA + ;; + st8 [r8]=in0 // VA of next task... + ;; + mov r25=IA64_TR_CURRENT_STACK + // remember last page we mapped... + mov r8=IA64_KR_CURRENT_STACK + mov r9=r26;; + XEN_HYPER_SET_KR;; +#else + mov cr.itir=r25 + mov cr.ifa=in0 // VA of next task... + ;; + mov r25=IA64_TR_CURRENT_STACK + mov IA64_KR(CURRENT_STACK)=r26 // remember last page we mapped... +#endif + ;; + itr.d dtr[r25]=r23 // wire in new mapping... +#ifndef CONFIG_XEN + ssm psr.ic // reenable the psr.ic bit + ;; + srlz.d +#endif + br.cond.sptk .done +#ifdef CONFIG_XEN +END(xen_switch_to) +#else +END(ia64_switch_to) +#endif + + /* + * Invoke a system call, but do some tracing before and after the call. + * We MUST preserve the current register frame throughout this routine + * because some system calls (such as ia64_execve) directly + * manipulate ar.pfs. + */ +#ifdef CONFIG_XEN +GLOBAL_ENTRY(xen_trace_syscall) + PT_REGS_UNWIND_INFO(0) + movl r16=running_on_xen;; + ld4 r16=[r16];; + cmp.eq p7,p0=r16,r0 +(p7) br.cond.sptk.many __ia64_trace_syscall;; +#else +GLOBAL_ENTRY(ia64_trace_syscall) + PT_REGS_UNWIND_INFO(0) +#endif + /* + * We need to preserve the scratch registers f6-f11 in case the system + * call is sigreturn. + */ + adds r16=PT(F6)+16,sp + adds r17=PT(F7)+16,sp + ;; + stf.spill [r16]=f6,32 + stf.spill [r17]=f7,32 + ;; + stf.spill [r16]=f8,32 + stf.spill [r17]=f9,32 + ;; + stf.spill [r16]=f10 + stf.spill [r17]=f11 + br.call.sptk.many rp=syscall_trace_enter // give parent a chance to catch syscall args + adds r16=PT(F6)+16,sp + adds r17=PT(F7)+16,sp + ;; + ldf.fill f6=[r16],32 + ldf.fill f7=[r17],32 + ;; + ldf.fill f8=[r16],32 + ldf.fill f9=[r17],32 + ;; + ldf.fill f10=[r16] + ldf.fill f11=[r17] + // the syscall number may have changed, so re-load it and re-calculate the + // syscall entry-point: + adds r15=PT(R15)+16,sp // r15 = &pt_regs.r15 (syscall #) + ;; + ld8 r15=[r15] + mov r3=NR_syscalls - 1 + ;; + adds r15=-1024,r15 + movl r16=sys_call_table + ;; + shladd r20=r15,3,r16 // r20 = sys_call_table + 8*(syscall-1024) + cmp.leu p6,p7=r15,r3 + ;; +(p6) ld8 r20=[r20] // load address of syscall entry point +(p7) movl r20=sys_ni_syscall + ;; + mov b6=r20 + br.call.sptk.many rp=b6 // do the syscall +.strace_check_retval: + cmp.lt p6,p0=r8,r0 // syscall failed? + adds r2=PT(R8)+16,sp // r2 = &pt_regs.r8 + adds r3=PT(R10)+16,sp // r3 = &pt_regs.r10 + mov r10=0 +(p6) br.cond.sptk strace_error // syscall failed -> + ;; // avoid RAW on r10 +.strace_save_retval: +.mem.offset 0,0; st8.spill [r2]=r8 // store return value in slot for r8 +.mem.offset 8,0; st8.spill [r3]=r10 // clear error indication in slot for r10 + br.call.sptk.many rp=syscall_trace_leave // give parent a chance to catch return value +.ret3: +(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk + br.cond.sptk .work_pending_syscall_end + +strace_error: + ld8 r3=[r2] // load pt_regs.r8 + sub r9=0,r8 // negate return value to get errno value + ;; + cmp.ne p6,p0=r3,r0 // is pt_regs.r8!=0? + adds r3=16,r2 // r3=&pt_regs.r10 + ;; +(p6) mov r10=-1 +(p6) mov r8=r9 + br.cond.sptk .strace_save_retval +#ifdef CONFIG_XEN +END(xen_trace_syscall) +#else +END(ia64_trace_syscall) +#endif + +/* + * ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't + * need to switch to bank 0 and doesn't restore the scratch registers. + * To avoid leaking kernel bits, the scratch registers are set to + * the following known-to-be-safe values: + * + * r1: restored (global pointer) + * r2: cleared + * r3: 1 (when returning to user-level) + * r8-r11: restored (syscall return value(s)) + * r12: restored (user-level stack pointer) + * r13: restored (user-level thread pointer) + * r14: set to __kernel_syscall_via_epc + * r15: restored (syscall #) + * r16-r17: cleared + * r18: user-level b6 + * r19: cleared + * r20: user-level ar.fpsr + * r21: user-level b0 + * r22: cleared + * r23: user-level ar.bspstore + * r24: user-level ar.rnat + * r25: user-level ar.unat + * r26: user-level ar.pfs + * r27: user-level ar.rsc + * r28: user-level ip + * r29: user-level psr + * r30: user-level cfm + * r31: user-level pr + * f6-f11: cleared + * pr: restored (user-level pr) + * b0: restored (user-level rp) + * b6: restored + * b7: set to __kernel_syscall_via_epc + * ar.unat: restored (user-level ar.unat) + * ar.pfs: restored (user-level ar.pfs) + * ar.rsc: restored (user-level ar.rsc) + * ar.rnat: restored (user-level ar.rnat) + * ar.bspstore: restored (user-level ar.bspstore) + * ar.fpsr: restored (user-level ar.fpsr) + * ar.ccv: cleared + * ar.csd: cleared + * ar.ssd: cleared + */ +#ifdef CONFIG_XEN +GLOBAL_ENTRY(xen_leave_syscall) + PT_REGS_UNWIND_INFO(0) + movl r22=running_on_xen;; + ld4 r22=[r22];; + cmp.eq p7,p0=r22,r0 +(p7) br.cond.sptk.many __ia64_leave_syscall;; +#else +ENTRY(ia64_leave_syscall) + PT_REGS_UNWIND_INFO(0) +#endif + /* + * work.need_resched etc. mustn't get changed by this CPU before it returns to + * user- or fsys-mode, hence we disable interrupts early on. + * + * p6 controls whether current_thread_info()->flags needs to be check for + * extra work. We always check for extra work when returning to user-level. + * With CONFIG_PREEMPT, we also check for extra work when the preempt_count + * is 0. After extra work processing has been completed, execution + * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check + * needs to be redone. + */ +#ifdef CONFIG_PREEMPT + rsm psr.i // disable interrupts + cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall +(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13 + ;; + .pred.rel.mutex pUStk,pKStk +(pKStk) ld4 r21=[r20] // r21 <- preempt_count +(pUStk) mov r21=0 // r21 <- 0 + ;; + cmp.eq p6,p0=r21,r0 // p6 <- pUStk || (preempt_count == 0) +#else /* !CONFIG_PREEMPT */ +#ifdef CONFIG_XEN + movl r2=XSI_PSR_I_ADDR + mov r18=1 + ;; + ld8 r2=[r2] + ;; +(pUStk) st1 [r2]=r18 +#else +(pUStk) rsm psr.i +#endif + cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall +(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk +#endif +.work_processed_syscall: + adds r2=PT(LOADRS)+16,r12 + adds r3=PT(AR_BSPSTORE)+16,r12 + adds r18=TI_FLAGS+IA64_TASK_SIZE,r13 + ;; +(p6) ld4 r31=[r18] // load current_thread_info()->flags + ld8 r19=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs" + nop.i 0 + ;; + mov r16=ar.bsp // M2 get existing backing store pointer + ld8 r18=[r2],PT(R9)-PT(B6) // load b6 +(p6) and r15=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE? + ;; + ld8 r23=[r3],PT(R11)-PT(AR_BSPSTORE) // load ar.bspstore (may be garbage) +(p6) cmp4.ne.unc p6,p0=r15, r0 // any special work pending? +(p6) br.cond.spnt .work_pending_syscall + ;; + // start restoring the state saved on the kernel stack (struct pt_regs): + ld8 r9=[r2],PT(CR_IPSR)-PT(R9) + ld8 r11=[r3],PT(CR_IIP)-PT(R11) +(pNonSys) break 0 // bug check: we shouldn't be here if pNonSys is TRUE! + ;; + invala // M0|1 invalidate ALAT +#ifdef CONFIG_XEN + movl r28=XSI_PSR_I_ADDR + movl r29=XSI_PSR_IC + ;; + ld8 r28=[r28] + mov r30=1 + ;; + st1 [r28]=r30 + st4 [r29]=r0 // note: clears both vpsr.i and vpsr.ic! + ;; +#else + rsm psr.i | psr.ic // M2 turn off interrupts and interruption collection +#endif + cmp.eq p9,p0=r0,r0 // A set p9 to indicate that we should restore cr.ifs + + ld8 r29=[r2],16 // M0|1 load cr.ipsr + ld8 r28=[r3],16 // M0|1 load cr.iip + mov r22=r0 // A clear r22 + ;; + ld8 r30=[r2],16 // M0|1 load cr.ifs + ld8 r25=[r3],16 // M0|1 load ar.unat +(pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13 + ;; + ld8 r26=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs +(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled + nop 0 + ;; + ld8 r21=[r2],PT(AR_RNAT)-PT(B0) // M0|1 load b0 + ld8 r27=[r3],PT(PR)-PT(AR_RSC) // M0|1 load ar.rsc + mov f6=f0 // F clear f6 + ;; + ld8 r24=[r2],PT(AR_FPSR)-PT(AR_RNAT) // M0|1 load ar.rnat (may be garbage) + ld8 r31=[r3],PT(R1)-PT(PR) // M0|1 load predicates + mov f7=f0 // F clear f7 + ;; + ld8 r20=[r2],PT(R12)-PT(AR_FPSR) // M0|1 load ar.fpsr + ld8.fill r1=[r3],16 // M0|1 load r1 +(pUStk) mov r17=1 // A + ;; +(pUStk) st1 [r14]=r17 // M2|3 + ld8.fill r13=[r3],16 // M0|1 + mov f8=f0 // F clear f8 + ;; + ld8.fill r12=[r2] // M0|1 restore r12 (sp) + ld8.fill r15=[r3] // M0|1 restore r15 + mov b6=r18 // I0 restore b6 + + addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0 // A + mov f9=f0 // F clear f9 +(pKStk) br.cond.dpnt.many skip_rbs_switch // B + + srlz.d // M0 ensure interruption collection is off (for cover) + shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition +#ifdef CONFIG_XEN + XEN_HYPER_COVER; +#else + cover // B add current frame into dirty partition & set cr.ifs +#endif + ;; +(pUStk) ld4 r17=[r17] // M0|1 r17 = cpu_data->phys_stacked_size_p8 + mov r19=ar.bsp // M2 get new backing store pointer + mov f10=f0 // F clear f10 + + nop.m 0 + movl r14=__kernel_syscall_via_epc // X + ;; + mov.m ar.csd=r0 // M2 clear ar.csd + mov.m ar.ccv=r0 // M2 clear ar.ccv + mov b7=r14 // I0 clear b7 (hint with __kernel_syscall_via_epc) + + mov.m ar.ssd=r0 // M2 clear ar.ssd + mov f11=f0 // F clear f11 + br.cond.sptk.many rbs_switch // B +#ifdef CONFIG_XEN +END(xen_leave_syscall) +#else +END(ia64_leave_syscall) +#endif + +#ifdef CONFIG_XEN +GLOBAL_ENTRY(xen_leave_kernel) + PT_REGS_UNWIND_INFO(0) + movl r22=running_on_xen;; + ld4 r22=[r22];; + cmp.eq p7,p0=r22,r0 +(p7) br.cond.sptk.many __ia64_leave_kernel;; +#else +GLOBAL_ENTRY(ia64_leave_kernel) + PT_REGS_UNWIND_INFO(0) +#endif + /* + * work.need_resched etc. mustn't get changed by this CPU before it returns to + * user- or fsys-mode, hence we disable interrupts early on. + * + * p6 controls whether current_thread_info()->flags needs to be check for + * extra work. We always check for extra work when returning to user-level. + * With CONFIG_PREEMPT, we also check for extra work when the preempt_count + * is 0. After extra work processing has been completed, execution + * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check + * needs to be redone. + */ +#ifdef CONFIG_PREEMPT + rsm psr.i // disable interrupts + cmp.eq p0,pLvSys=r0,r0 // pLvSys=0: leave from kernel +(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13 + ;; + .pred.rel.mutex pUStk,pKStk +(pKStk) ld4 r21=[r20] // r21 <- preempt_count +(pUStk) mov r21=0 // r21 <- 0 + ;; + cmp.eq p6,p0=r21,r0 // p6 <- pUStk || (preempt_count == 0) +#else +#ifdef CONFIG_XEN +(pUStk) movl r17=XSI_PSR_I_ADDR +(pUStk) mov r31=1 + ;; +(pUStk) ld8 r17=[r17] + ;; +(pUStk) st1 [r17]=r31 + ;; +#else +(pUStk) rsm psr.i +#endif + cmp.eq p0,pLvSys=r0,r0 // pLvSys=0: leave from kernel +(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk +#endif +.work_processed_kernel: + adds r17=TI_FLAGS+IA64_TASK_SIZE,r13 + ;; +(p6) ld4 r31=[r17] // load current_thread_info()->flags + adds r21=PT(PR)+16,r12 + ;; + + lfetch [r21],PT(CR_IPSR)-PT(PR) + adds r2=PT(B6)+16,r12 + adds r3=PT(R16)+16,r12 + ;; + lfetch [r21] + ld8 r28=[r2],8 // load b6 + adds r29=PT(R24)+16,r12 + + ld8.fill r16=[r3],PT(AR_CSD)-PT(R16) + adds r30=PT(AR_CCV)+16,r12 +(p6) and r19=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE? + ;; + ld8.fill r24=[r29] + ld8 r15=[r30] // load ar.ccv +(p6) cmp4.ne.unc p6,p0=r19, r0 // any special work pending? + ;; + ld8 r29=[r2],16 // load b7 + ld8 r30=[r3],16 // load ar.csd +(p6) br.cond.spnt .work_pending + ;; + ld8 r31=[r2],16 // load ar.ssd + ld8.fill r8=[r3],16 + ;; + ld8.fill r9=[r2],16 + ld8.fill r10=[r3],PT(R17)-PT(R10) + ;; + ld8.fill r11=[r2],PT(R18)-PT(R11) + ld8.fill r17=[r3],16 + ;; + ld8.fill r18=[r2],16 + ld8.fill r19=[r3],16 + ;; + ld8.fill r20=[r2],16 + ld8.fill r21=[r3],16 + mov ar.csd=r30 + mov ar.ssd=r31 + ;; +#ifdef CONFIG_XEN + movl r23=XSI_PSR_I_ADDR + movl r22=XSI_PSR_IC + ;; + ld8 r23=[r23] + mov r25=1 + ;; + st1 [r23]=r25 + st4 [r22]=r0 // note: clears both vpsr.i and vpsr.ic! + ;; +#else + rsm psr.i | psr.ic // initiate turning off of interrupt and interruption collection +#endif + invala // invalidate ALAT + ;; + ld8.fill r22=[r2],24 + ld8.fill r23=[r3],24 + mov b6=r28 + ;; + ld8.fill r25=[r2],16 + ld8.fill r26=[r3],16 + mov b7=r29 + ;; + ld8.fill r27=[r2],16 + ld8.fill r28=[r3],16 + ;; + ld8.fill r29=[r2],16 + ld8.fill r30=[r3],24 + ;; + ld8.fill r31=[r2],PT(F9)-PT(R31) + adds r3=PT(F10)-PT(F6),r3 + ;; + ldf.fill f9=[r2],PT(F6)-PT(F9) + ldf.fill f10=[r3],PT(F8)-PT(F10) + ;; + ldf.fill f6=[r2],PT(F7)-PT(F6) + ;; + ldf.fill f7=[r2],PT(F11)-PT(F7) + ldf.fill f8=[r3],32 + ;; + srlz.d // ensure that inter. collection is off (VHPT is don't care, since text is pinned) + mov ar.ccv=r15 + ;; + ldf.fill f11=[r2] +#ifdef CONFIG_XEN + ;; + // r16-r31 all now hold bank1 values + movl r2=XSI_BANK1_R16 + movl r3=XSI_BANK1_R16+8 + ;; +.mem.offset 0,0; st8.spill [r2]=r16,16 +.mem.offset 8,0; st8.spill [r3]=r17,16 + ;; +.mem.offset 0,0; st8.spill [r2]=r18,16 +.mem.offset 8,0; st8.spill [r3]=r19,16 + ;; +.mem.offset 0,0; st8.spill [r2]=r20,16 +.mem.offset 8,0; st8.spill [r3]=r21,16 + ;; +.mem.offset 0,0; st8.spill [r2]=r22,16 +.mem.offset 8,0; st8.spill [r3]=r23,16 + ;; +.mem.offset 0,0; st8.spill [r2]=r24,16 +.mem.offset 8,0; st8.spill [r3]=r25,16 + ;; +.mem.offset 0,0; st8.spill [r2]=r26,16 +.mem.offset 8,0; st8.spill [r3]=r27,16 + ;; +.mem.offset 0,0; st8.spill [r2]=r28,16 +.mem.offset 8,0; st8.spill [r3]=r29,16 + ;; +.mem.offset 0,0; st8.spill [r2]=r30,16 +.mem.offset 8,0; st8.spill [r3]=r31,16 + ;; + movl r2=XSI_BANKNUM;; + st4 [r2]=r0; +#else + bsw.0 // switch back to bank 0 (no stop bit required beforehand...) +#endif + ;; +(pUStk) mov r18=IA64_KR(CURRENT)// M2 (12 cycle read latency) + adds r16=PT(CR_IPSR)+16,r12 + adds r17=PT(CR_IIP)+16,r12 + +(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled + nop.i 0 + nop.i 0 + ;; + ld8 r29=[r16],16 // load cr.ipsr + ld8 r28=[r17],16 // load cr.iip + ;; + ld8 r30=[r16],16 // load cr.ifs + ld8 r25=[r17],16 // load ar.unat + ;; + ld8 r26=[r16],16 // load ar.pfs + ld8 r27=[r17],16 // load ar.rsc + cmp.eq p9,p0=r0,r0 // set p9 to indicate that we should restore cr.ifs + ;; + ld8 r24=[r16],16 // load ar.rnat (may be garbage) + ld8 r23=[r17],16 // load ar.bspstore (may be garbage) + ;; + ld8 r31=[r16],16 // load predicates + ld8 r21=[r17],16 // load b0 + ;; + ld8 r19=[r16],16 // load ar.rsc value for "loadrs" + ld8.fill r1=[r17],16 // load r1 + ;; + ld8.fill r12=[r16],16 + ld8.fill r13=[r17],16 +(pUStk) adds r18=IA64_TASK_THREAD_ON_USTACK_OFFSET,r18 + ;; + ld8 r20=[r16],16 // ar.fpsr + ld8.fill r15=[r17],16 + ;; + ld8.fill r14=[r16],16 + ld8.fill r2=[r17] +(pUStk) mov r17=1 + ;; + ld8.fill r3=[r16] +(pUStk) st1 [r18]=r17 // restore current->thread.on_ustack + shr.u r18=r19,16 // get byte size of existing "dirty" partition + ;; + mov r16=ar.bsp // get existing backing store pointer + addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0 + ;; + ld4 r17=[r17] // r17 = cpu_data->phys_stacked_size_p8 +(pKStk) br.cond.dpnt skip_rbs_switch + + /* + * Restore user backing store. + * + * NOTE: alloc, loadrs, and cover can't be predicated. + */ +(pNonSys) br.cond.dpnt dont_preserve_current_frame + +#ifdef CONFIG_XEN + XEN_HYPER_COVER; +#else + cover // add current frame into dirty partition and set cr.ifs +#endif + ;; + mov r19=ar.bsp // get new backing store pointer +rbs_switch: + sub r16=r16,r18 // krbs = old bsp - size of dirty partition + cmp.ne p9,p0=r0,r0 // clear p9 to skip restore of cr.ifs + ;; + sub r19=r19,r16 // calculate total byte size of dirty partition + add r18=64,r18 // don't force in0-in7 into memory... + ;; + shl r19=r19,16 // shift size of dirty partition into loadrs position + ;; +dont_preserve_current_frame: + /* + * To prevent leaking bits between the kernel and user-space, + * we must clear the stacked registers in the "invalid" partition here. + * Not pretty, but at least it's fast (3.34 registers/cycle on Itanium, + * 5 registers/cycle on McKinley). + */ +# define pRecurse p6 +# define pReturn p7 +#ifdef CONFIG_ITANIUM +# define Nregs 10 +#else +# define Nregs 14 +#endif + alloc loc0=ar.pfs,2,Nregs-2,2,0 + shr.u loc1=r18,9 // RNaTslots <= floor(dirtySize / (64*8)) + sub r17=r17,r18 // r17 = (physStackedSize + 8) - dirtySize + ;; + mov ar.rsc=r19 // load ar.rsc to be used for "loadrs" + shladd in0=loc1,3,r17 + mov in1=0 + ;; + TEXT_ALIGN(32) +rse_clear_invalid: +#ifdef CONFIG_ITANIUM + // cycle 0 + { .mii + alloc loc0=ar.pfs,2,Nregs-2,2,0 + cmp.lt pRecurse,p0=Nregs*8,in0 // if more than Nregs regs left to clear, (re)curse + add out0=-Nregs*8,in0 +}{ .mfb + add out1=1,in1 // increment recursion count + nop.f 0 + nop.b 0 // can't do br.call here because of alloc (WAW on CFM) + ;; +}{ .mfi // cycle 1 + mov loc1=0 + nop.f 0 + mov loc2=0 +}{ .mib + mov loc3=0 + mov loc4=0 +(pRecurse) br.call.sptk.many b0=rse_clear_invalid + +}{ .mfi // cycle 2 + mov loc5=0 + nop.f 0 + cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret +}{ .mib + mov loc6=0 + mov loc7=0 +(pReturn) br.ret.sptk.many b0 +} +#else /* !CONFIG_ITANIUM */ + alloc loc0=ar.pfs,2,Nregs-2,2,0 + cmp.lt pRecurse,p0=Nregs*8,in0 // if more than Nregs regs left to clear, (re)curse + add out0=-Nregs*8,in0 + add out1=1,in1 // increment recursion count + mov loc1=0 + mov loc2=0 + ;; + mov loc3=0 + mov loc4=0 + mov loc5=0 + mov loc6=0 + mov loc7=0 +(pRecurse) br.call.dptk.few b0=rse_clear_invalid + ;; + mov loc8=0 + mov loc9=0 + cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret + mov loc10=0 + mov loc11=0 +(pReturn) br.ret.dptk.many b0 +#endif /* !CONFIG_ITANIUM */ +# undef pRecurse +# undef pReturn + ;; + alloc r17=ar.pfs,0,0,0,0 // drop current register frame + ;; + loadrs + ;; +skip_rbs_switch: + mov ar.unat=r25 // M2 +(pKStk) extr.u r22=r22,21,1 // I0 extract current value of psr.pp from r22 +(pLvSys)mov r19=r0 // A clear r19 for leave_syscall, no-op otherwise + ;; +(pUStk) mov ar.bspstore=r23 // M2 +(pKStk) dep r29=r22,r29,21,1 // I0 update ipsr.pp with psr.pp +(pLvSys)mov r16=r0 // A clear r16 for leave_syscall, no-op otherwise + ;; +#ifdef CONFIG_XEN + movl r25=XSI_IPSR + ;; + st8[r25]=r29,XSI_IFS_OFS-XSI_IPSR_OFS + ;; +#else + mov cr.ipsr=r29 // M2 +#endif + mov ar.pfs=r26 // I0 +(pLvSys)mov r17=r0 // A clear r17 for leave_syscall, no-op otherwise + +#ifdef CONFIG_XEN +(p9) st8 [r25]=r30 + ;; + adds r25=XSI_IIP_OFS-XSI_IFS_OFS,r25 + ;; +#else +(p9) mov cr.ifs=r30 // M2 +#endif + mov b0=r21 // I0 +(pLvSys)mov r18=r0 // A clear r18 for leave_syscall, no-op otherwise + + mov ar.fpsr=r20 // M2 +#ifdef CONFIG_XEN + st8 [r25]=r28 +#else + mov cr.iip=r28 // M2 +#endif + nop 0 + ;; +(pUStk) mov ar.rnat=r24 // M2 must happen with RSE in lazy mode + nop 0 +(pLvSys)mov r2=r0 + + mov ar.rsc=r27 // M2 + mov pr=r31,-1 // I0 +#ifdef CONFIG_XEN + ;; + XEN_HYPER_RFI; +#else + rfi // B +#endif + + /* + * On entry: + * r20 = ¤t->thread_info->pre_count (if CONFIG_PREEMPT) + * r31 = current->thread_info->flags + * On exit: + * p6 = TRUE if work-pending-check needs to be redone + */ +.work_pending_syscall: + add r2=-8,r2 + add r3=-8,r3 + ;; + st8 [r2]=r8 + st8 [r3]=r10 +.work_pending: + tbit.z p6,p0=r31,TIF_NEED_RESCHED // current_thread_info()->need_resched==0? +(p6) br.cond.sptk.few .notify +#ifdef CONFIG_PREEMPT +(pKStk) dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1 + ;; +(pKStk) st4 [r20]=r21 + ssm psr.i // enable interrupts +#endif + br.call.spnt.many rp=schedule +.ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1 +#ifdef CONFIG_XEN + movl r2=XSI_PSR_I_ADDR + mov r20=1 + ;; + ld8 r2=[r2] + ;; + st1 [r2]=r20 +#else + rsm psr.i // disable interrupts +#endif + ;; +#ifdef CONFIG_PREEMPT +(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13 + ;; +(pKStk) st4 [r20]=r0 // preempt_count() <- 0 +#endif +(pLvSys)br.cond.sptk.few .work_pending_syscall_end + br.cond.sptk.many .work_processed_kernel // re-check + +.notify: +(pUStk) br.call.spnt.many rp=notify_resume_user +.ret10: cmp.ne p6,p0=r0,r0 // p6 <- 0 +(pLvSys)br.cond.sptk.few .work_pending_syscall_end + br.cond.sptk.many .work_processed_kernel // don't re-check + +.work_pending_syscall_end: + adds r2=PT(R8)+16,r12 + adds r3=PT(R10)+16,r12 + ;; + ld8 r8=[r2] + ld8 r10=[r3] + br.cond.sptk.many .work_processed_syscall // re-check + +#ifdef CONFIG_XEN +END(xen_leave_kernel) +#else +END(ia64_leave_kernel) +#endif diff --git a/arch/ia64/xen/xenhpski.c b/arch/ia64/xen/xenhpski.c new file mode 100644 index 000000000..3bc6cdbf7 --- /dev/null +++ b/arch/ia64/xen/xenhpski.c @@ -0,0 +1,19 @@ + +extern unsigned long xen_get_cpuid(int); + +int +running_on_sim(void) +{ + int i; + long cpuid[6]; + + for (i = 0; i < 5; ++i) + cpuid[i] = xen_get_cpuid(i); + if ((cpuid[0] & 0xff) != 'H') return 0; + if ((cpuid[3] & 0xff) != 0x4) return 0; + if (((cpuid[3] >> 8) & 0xff) != 0x0) return 0; + if (((cpuid[3] >> 16) & 0xff) != 0x0) return 0; + if (((cpuid[3] >> 24) & 0x7) != 0x7) return 0; + return 1; +} + diff --git a/arch/ia64/xen/xenivt.S b/arch/ia64/xen/xenivt.S new file mode 100644 index 000000000..9c9e9f267 --- /dev/null +++ b/arch/ia64/xen/xenivt.S @@ -0,0 +1,2169 @@ +/* + * arch/ia64/xen/ivt.S + * + * Copyright (C) 2005 Hewlett-Packard Co + * Dan Magenheimer <dan.magenheimer@hp.com> + */ +/* + * This file defines the interruption vector table used by the CPU. + * It does not include one entry per possible cause of interruption. + * + * The first 20 entries of the table contain 64 bundles each while the + * remaining 48 entries contain only 16 bundles each. + * + * The 64 bundles are used to allow inlining the whole handler for critical + * interruptions like TLB misses. + * + * For each entry, the comment is as follows: + * + * // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51) + * entry offset ----/ / / / / + * entry number ---------/ / / / + * size of the entry -------------/ / / + * vector name -------------------------------------/ / + * interruptions triggering this vector ----------------------/ + * + * The table is 32KB in size and must be aligned on 32KB boundary. + * (The CPU ignores the 15 lower bits of the address) + * + * Table is based upon EAS2.6 (Oct 1999) + */ + +#include <asm/asmmacro.h> +#include <asm/break.h> +#include <asm/ia32.h> +#include <asm/kregs.h> +#include <asm/asm-offsets.h> +#include <asm/pgtable.h> +#include <asm/processor.h> +#include <asm/ptrace.h> +#include <asm/system.h> +#include <asm/thread_info.h> +#include <asm/unistd.h> +#include <asm/errno.h> + +#ifdef CONFIG_XEN +#define ia64_ivt xen_ivt +#endif + +#if 1 +# define PSR_DEFAULT_BITS psr.ac +#else +# define PSR_DEFAULT_BITS 0 +#endif + +#if 0 + /* + * This lets you track the last eight faults that occurred on the CPU. Make sure ar.k2 isn't + * needed for something else before enabling this... + */ +# define DBG_FAULT(i) mov r16=ar.k2;; shl r16=r16,8;; add r16=(i),r16;;mov ar.k2=r16 +#else +# define DBG_FAULT(i) +#endif + +#define MINSTATE_VIRT /* needed by minstate.h */ +#include "xenminstate.h" + +#define FAULT(n) \ + mov r31=pr; \ + mov r19=n;; /* prepare to save predicates */ \ + br.sptk.many dispatch_to_fault_handler + + .section .text.ivt,"ax" + + .align 32768 // align on 32KB boundary + .global ia64_ivt +ia64_ivt: +///////////////////////////////////////////////////////////////////////////////////////// +// 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47) +ENTRY(vhpt_miss) + DBG_FAULT(0) + /* + * The VHPT vector is invoked when the TLB entry for the virtual page table + * is missing. This happens only as a result of a previous + * (the "original") TLB miss, which may either be caused by an instruction + * fetch or a data access (or non-access). + * + * What we do here is normal TLB miss handing for the _original_ miss, + * followed by inserting the TLB entry for the virtual page table page + * that the VHPT walker was attempting to access. The latter gets + * inserted as long as page table entry above pte level have valid + * mappings for the faulting address. The TLB entry for the original + * miss gets inserted only if the pte entry indicates that the page is + * present. + * + * do_page_fault gets invoked in the following cases: + * - the faulting virtual address uses unimplemented address bits + * - the faulting virtual address has no valid page table mapping + */ +#ifdef CONFIG_XEN + movl r16=XSI_IFA + ;; + ld8 r16=[r16] +#ifdef CONFIG_HUGETLB_PAGE + movl r18=PAGE_SHIFT + movl r25=XSI_ITIR + ;; + ld8 r25=[r25] +#endif + ;; +#else + mov r16=cr.ifa // get address that caused the TLB miss +#ifdef CONFIG_HUGETLB_PAGE + movl r18=PAGE_SHIFT + mov r25=cr.itir +#endif +#endif + ;; +#ifdef CONFIG_XEN + XEN_HYPER_RSM_PSR_DT; +#else + rsm psr.dt // use physical addressing for data +#endif + mov r31=pr // save the predicate registers + mov r19=IA64_KR(PT_BASE) // get page table base address + shl r21=r16,3 // shift bit 60 into sign bit + shr.u r17=r16,61 // get the region number into r17 + ;; + shr.u r22=r21,3 +#ifdef CONFIG_HUGETLB_PAGE + extr.u r26=r25,2,6 + ;; + cmp.ne p8,p0=r18,r26 + sub r27=r26,r18 + ;; +(p8) dep r25=r18,r25,2,6 +(p8) shr r22=r22,r27 +#endif + ;; + cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5? + shr.u r18=r22,PGDIR_SHIFT // get bottom portion of pgd index bit + ;; +(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place + + srlz.d + LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir + + .pred.rel "mutex", p6, p7 +(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT +(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3 + ;; +(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5 +(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4] + cmp.eq p7,p6=0,r21 // unused address bits all zeroes? +#ifdef CONFIG_PGTABLE_4 + shr.u r28=r22,PUD_SHIFT // shift pud index into position +#else + shr.u r18=r22,PMD_SHIFT // shift pmd index into position +#endif + ;; + ld8 r17=[r17] // get *pgd (may be 0) + ;; +(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) == NULL? +#ifdef CONFIG_PGTABLE_4 + dep r28=r28,r17,3,(PAGE_SHIFT-3) // r28=pud_offset(pgd,addr) + ;; + shr.u r18=r22,PMD_SHIFT // shift pmd index into position +(p7) ld8 r29=[r28] // get *pud (may be 0) + ;; +(p7) cmp.eq.or.andcm p6,p7=r29,r0 // was pud_present(*pud) == NULL? + dep r17=r18,r29,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr) +#else + dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pgd,addr) +#endif + ;; +(p7) ld8 r20=[r17] // get *pmd (may be 0) + shr.u r19=r22,PAGE_SHIFT // shift pte index into position + ;; +(p7) cmp.eq.or.andcm p6,p7=r20,r0 // was pmd_present(*pmd) == NULL? + dep r21=r19,r20,3,(PAGE_SHIFT-3) // r21=pte_offset(pmd,addr) + ;; +(p7) ld8 r18=[r21] // read *pte +#ifdef CONFIG_XEN + movl r19=XSI_ISR + ;; + ld8 r19=[r19] +#else + mov r19=cr.isr // cr.isr bit 32 tells us if this is an insn miss +#endif + ;; +(p7) tbit.z p6,p7=r18,_PAGE_P_BIT // page present bit cleared? +#ifdef CONFIG_XEN + movl r22=XSI_IHA + ;; + ld8 r22=[r22] +#else + mov r22=cr.iha // get the VHPT address that caused the TLB miss +#endif + ;; // avoid RAW on p7 +(p7) tbit.nz.unc p10,p11=r19,32 // is it an instruction TLB miss? + dep r23=0,r20,0,PAGE_SHIFT // clear low bits to get page address + ;; +#ifdef CONFIG_XEN + mov r24=r8 + mov r8=r18 + ;; +(p10) XEN_HYPER_ITC_I + ;; +(p11) XEN_HYPER_ITC_D + ;; + mov r8=r24 + ;; +#else +(p10) itc.i r18 // insert the instruction TLB entry +(p11) itc.d r18 // insert the data TLB entry +#endif +(p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault) +#ifdef CONFIG_XEN + movl r24=XSI_IFA + ;; + st8 [r24]=r22 + ;; +#else + mov cr.ifa=r22 +#endif + +#ifdef CONFIG_HUGETLB_PAGE +(p8) mov cr.itir=r25 // change to default page-size for VHPT +#endif + + /* + * Now compute and insert the TLB entry for the virtual page table. We never + * execute in a page table page so there is no need to set the exception deferral + * bit. + */ + adds r24=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r23 + ;; +#ifdef CONFIG_XEN +(p7) mov r25=r8 +(p7) mov r8=r24 + ;; +(p7) XEN_HYPER_ITC_D + ;; +(p7) mov r8=r25 + ;; +#else +(p7) itc.d r24 +#endif + ;; +#ifdef CONFIG_SMP + /* + * Tell the assemblers dependency-violation checker that the above "itc" instructions + * cannot possibly affect the following loads: + */ + dv_serialize_data + + /* + * Re-check pagetable entry. If they changed, we may have received a ptc.g + * between reading the pagetable and the "itc". If so, flush the entry we + * inserted and retry. At this point, we have: + * + * r28 = equivalent of pud_offset(pgd, ifa) + * r17 = equivalent of pmd_offset(pud, ifa) + * r21 = equivalent of pte_offset(pmd, ifa) + * + * r29 = *pud + * r20 = *pmd + * r18 = *pte + */ + ld8 r25=[r21] // read *pte again + ld8 r26=[r17] // read *pmd again +#ifdef CONFIG_PGTABLE_4 + ld8 r19=[r28] // read *pud again +#endif + cmp.ne p6,p7=r0,r0 + ;; + cmp.ne.or.andcm p6,p7=r26,r20 // did *pmd change +#ifdef CONFIG_PGTABLE_4 + cmp.ne.or.andcm p6,p7=r19,r29 // did *pud change +#endif + mov r27=PAGE_SHIFT<<2 + ;; +(p6) ptc.l r22,r27 // purge PTE page translation +(p7) cmp.ne.or.andcm p6,p7=r25,r18 // did *pte change + ;; +(p6) ptc.l r16,r27 // purge translation +#endif + + mov pr=r31,-1 // restore predicate registers +#ifdef CONFIG_XEN + XEN_HYPER_RFI + dv_serialize_data +#else + rfi +#endif +END(vhpt_miss) + + .org ia64_ivt+0x400 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x0400 Entry 1 (size 64 bundles) ITLB (21) +ENTRY(itlb_miss) + DBG_FAULT(1) + /* + * The ITLB handler accesses the PTE via the virtually mapped linear + * page table. If a nested TLB miss occurs, we switch into physical + * mode, walk the page table, and then re-execute the PTE read and + * go on normally after that. + */ +#ifdef CONFIG_XEN + movl r16=XSI_IFA + ;; + ld8 r16=[r16] +#else + mov r16=cr.ifa // get virtual address +#endif + mov r29=b0 // save b0 + mov r31=pr // save predicates +.itlb_fault: +#ifdef CONFIG_XEN + movl r17=XSI_IHA + ;; + ld8 r17=[r17] // get virtual address of L3 PTE +#else + mov r17=cr.iha // get virtual address of PTE +#endif + movl r30=1f // load nested fault continuation point + ;; +1: ld8 r18=[r17] // read *pte + ;; + mov b0=r29 + tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared? +(p6) br.cond.spnt page_fault + ;; +#ifdef CONFIG_XEN + mov r19=r8 + mov r8=r18 + ;; + XEN_HYPER_ITC_I + ;; + mov r8=r19 +#else + itc.i r18 +#endif + ;; +#ifdef CONFIG_SMP + /* + * Tell the assemblers dependency-violation checker that the above "itc" instructions + * cannot possibly affect the following loads: + */ + dv_serialize_data + + ld8 r19=[r17] // read *pte again and see if same + mov r20=PAGE_SHIFT<<2 // setup page size for purge + ;; + cmp.ne p7,p0=r18,r19 + ;; +(p7) ptc.l r16,r20 +#endif + mov pr=r31,-1 +#ifdef CONFIG_XEN + XEN_HYPER_RFI + dv_serialize_data +#else + rfi +#endif +END(itlb_miss) + + .org ia64_ivt+0x0800 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x0800 Entry 2 (size 64 bundles) DTLB (9,48) +ENTRY(dtlb_miss) + DBG_FAULT(2) + /* + * The DTLB handler accesses the PTE via the virtually mapped linear + * page table. If a nested TLB miss occurs, we switch into physical + * mode, walk the page table, and then re-execute the PTE read and + * go on normally after that. + */ +#ifdef CONFIG_XEN + movl r16=XSI_IFA + ;; + ld8 r16=[r16] +#else + mov r16=cr.ifa // get virtual address +#endif + mov r29=b0 // save b0 + mov r31=pr // save predicates +dtlb_fault: +#ifdef CONFIG_XEN + movl r17=XSI_IHA + ;; + ld8 r17=[r17] // get virtual address of L3 PTE +#else + mov r17=cr.iha // get virtual address of PTE +#endif + movl r30=1f // load nested fault continuation point + ;; +1: ld8 r18=[r17] // read *pte + ;; + mov b0=r29 + tbit.z p6,p0=r18,_PAGE_P_BIT // page present bit cleared? +(p6) br.cond.spnt page_fault + ;; +#ifdef CONFIG_XEN + mov r19=r8 + mov r8=r18 + ;; + XEN_HYPER_ITC_D + ;; + mov r8=r19 + ;; +#else + itc.d r18 +#endif + ;; +#ifdef CONFIG_SMP + /* + * Tell the assemblers dependency-violation checker that the above "itc" instructions + * cannot possibly affect the following loads: + */ + dv_serialize_data + + ld8 r19=[r17] // read *pte again and see if same + mov r20=PAGE_SHIFT<<2 // setup page size for purge + ;; + cmp.ne p7,p0=r18,r19 + ;; +(p7) ptc.l r16,r20 +#endif + mov pr=r31,-1 +#ifdef CONFIG_XEN + XEN_HYPER_RFI + dv_serialize_data +#else + rfi +#endif +END(dtlb_miss) + + .org ia64_ivt+0x0c00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19) +ENTRY(alt_itlb_miss) + DBG_FAULT(3) +#ifdef CONFIG_XEN + movl r31=XSI_IPSR + ;; + ld8 r21=[r31],XSI_IFA_OFS-XSI_IPSR_OFS // get ipsr, point to ifa + movl r17=PAGE_KERNEL + ;; + ld8 r16=[r31] // get ifa +#else + mov r16=cr.ifa // get address that caused the TLB miss + movl r17=PAGE_KERNEL + mov r21=cr.ipsr +#endif + movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff) + mov r31=pr + ;; +#ifdef CONFIG_DISABLE_VHPT + shr.u r22=r16,61 // get the region number into r21 + ;; + cmp.gt p8,p0=6,r22 // user mode + ;; +#ifndef CONFIG_XEN +(p8) thash r17=r16 + ;; +(p8) mov cr.iha=r17 +#endif +(p8) mov r29=b0 // save b0 +(p8) br.cond.dptk .itlb_fault +#endif + extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl + and r19=r19,r16 // clear ed, reserved bits, and PTE control bits + shr.u r18=r16,57 // move address bit 61 to bit 4 + ;; + andcm r18=0x10,r18 // bit 4=~address-bit(61) + cmp.ne p8,p0=r0,r23 // psr.cpl != 0? + or r19=r17,r19 // insert PTE control bits into r19 + ;; + or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6 +(p8) br.cond.spnt page_fault + ;; +#ifdef CONFIG_XEN + mov r18=r8 + mov r8=r19 + ;; + XEN_HYPER_ITC_I + ;; + mov r8=r18 + ;; + mov pr=r31,-1 + ;; + XEN_HYPER_RFI; +#else + itc.i r19 // insert the TLB entry + mov pr=r31,-1 + rfi +#endif +END(alt_itlb_miss) + + .org ia64_ivt+0x1000 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46) +ENTRY(alt_dtlb_miss) + DBG_FAULT(4) +#ifdef CONFIG_XEN + movl r31=XSI_IPSR + ;; + ld8 r21=[r31],XSI_ISR_OFS-XSI_IPSR_OFS // get ipsr, point to isr + movl r17=PAGE_KERNEL + ;; + ld8 r20=[r31],XSI_IFA_OFS-XSI_ISR_OFS // get isr, point to ifa + movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff) + ;; + ld8 r16=[r31] // get ifa +#else + mov r16=cr.ifa // get address that caused the TLB miss + movl r17=PAGE_KERNEL + mov r20=cr.isr + movl r19=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff) + mov r21=cr.ipsr +#endif + mov r31=pr + ;; +#ifdef CONFIG_DISABLE_VHPT + shr.u r22=r16,61 // get the region number into r21 + ;; + cmp.gt p8,p0=6,r22 // access to region 0-5 + ;; +#ifndef CONFIG_XEN +(p8) thash r17=r16 + ;; +(p8) mov cr.iha=r17 +#endif +(p8) mov r29=b0 // save b0 +(p8) br.cond.dptk dtlb_fault +#endif + extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl + and r22=IA64_ISR_CODE_MASK,r20 // get the isr.code field + tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on? + shr.u r18=r16,57 // move address bit 61 to bit 4 + and r19=r19,r16 // clear ed, reserved bits, and PTE control bits + tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on? + ;; + andcm r18=0x10,r18 // bit 4=~address-bit(61) + cmp.ne p8,p0=r0,r23 +(p9) cmp.eq.or.andcm p6,p7=IA64_ISR_CODE_LFETCH,r22 // check isr.code field +(p8) br.cond.spnt page_fault + + dep r21=-1,r21,IA64_PSR_ED_BIT,1 + or r19=r19,r17 // insert PTE control bits into r19 + ;; + or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6 +(p6) mov cr.ipsr=r21 + ;; +#ifdef CONFIG_XEN +(p7) mov r18=r8 +(p7) mov r8=r19 + ;; +(p7) XEN_HYPER_ITC_D + ;; +(p7) mov r8=r18 + ;; + mov pr=r31,-1 + ;; + XEN_HYPER_RFI; +#else +(p7) itc.d r19 // insert the TLB entry + mov pr=r31,-1 + rfi +#endif +END(alt_dtlb_miss) + + .org ia64_ivt+0x1400 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45) +ENTRY(nested_dtlb_miss) + /* + * In the absence of kernel bugs, we get here when the virtually mapped linear + * page table is accessed non-speculatively (e.g., in the Dirty-bit, Instruction + * Access-bit, or Data Access-bit faults). If the DTLB entry for the virtual page + * table is missing, a nested TLB miss fault is triggered and control is + * transferred to this point. When this happens, we lookup the pte for the + * faulting address by walking the page table in physical mode and return to the + * continuation point passed in register r30 (or call page_fault if the address is + * not mapped). + * + * Input: r16: faulting address + * r29: saved b0 + * r30: continuation address + * r31: saved pr + * + * Output: r17: physical address of PTE of faulting address + * r29: saved b0 + * r30: continuation address + * r31: saved pr + * + * Clobbered: b0, r18, r19, r21, r22, psr.dt (cleared) + */ +#ifdef CONFIG_XEN + XEN_HYPER_RSM_PSR_DT; +#else + rsm psr.dt // switch to using physical data addressing +#endif + mov r19=IA64_KR(PT_BASE) // get the page table base address + shl r21=r16,3 // shift bit 60 into sign bit +#ifdef CONFIG_XEN + movl r18=XSI_ITIR + ;; + ld8 r18=[r18] +#else + mov r18=cr.itir +#endif + ;; + shr.u r17=r16,61 // get the region number into r17 + extr.u r18=r18,2,6 // get the faulting page size + ;; + cmp.eq p6,p7=5,r17 // is faulting address in region 5? + add r22=-PAGE_SHIFT,r18 // adjustment for hugetlb address + add r18=PGDIR_SHIFT-PAGE_SHIFT,r18 + ;; + shr.u r22=r16,r22 + shr.u r18=r16,r18 +(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place + + srlz.d + LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir + + .pred.rel "mutex", p6, p7 +(p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT +(p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3 + ;; +(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=pgd_offset for region 5 +(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=pgd_offset for region[0-4] + cmp.eq p7,p6=0,r21 // unused address bits all zeroes? +#ifdef CONFIG_PGTABLE_4 + shr.u r18=r22,PUD_SHIFT // shift pud index into position +#else + shr.u r18=r22,PMD_SHIFT // shift pmd index into position +#endif + ;; + ld8 r17=[r17] // get *pgd (may be 0) + ;; +(p7) cmp.eq p6,p7=r17,r0 // was pgd_present(*pgd) == NULL? + dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=p[u|m]d_offset(pgd,addr) + ;; +#ifdef CONFIG_PGTABLE_4 +(p7) ld8 r17=[r17] // get *pud (may be 0) + shr.u r18=r22,PMD_SHIFT // shift pmd index into position + ;; +(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pud_present(*pud) == NULL? + dep r17=r18,r17,3,(PAGE_SHIFT-3) // r17=pmd_offset(pud,addr) + ;; +#endif +(p7) ld8 r17=[r17] // get *pmd (may be 0) + shr.u r19=r22,PAGE_SHIFT // shift pte index into position + ;; +(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was pmd_present(*pmd) == NULL? + dep r17=r19,r17,3,(PAGE_SHIFT-3) // r17=pte_offset(pmd,addr); +(p6) br.cond.spnt page_fault + mov b0=r30 + br.sptk.many b0 // return to continuation point +END(nested_dtlb_miss) + + .org ia64_ivt+0x1800 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24) +ENTRY(ikey_miss) + DBG_FAULT(6) + FAULT(6) +END(ikey_miss) + + //----------------------------------------------------------------------------------- + // call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address) +ENTRY(page_fault) +#ifdef CONFIG_XEN + XEN_HYPER_SSM_PSR_DT +#else + ssm psr.dt + ;; + srlz.i +#endif + ;; + SAVE_MIN_WITH_COVER + alloc r15=ar.pfs,0,0,3,0 +#ifdef CONFIG_XEN + movl r3=XSI_ISR + ;; + ld8 out1=[r3],XSI_IFA_OFS-XSI_ISR_OFS // get vcr.isr, point to ifa + ;; + ld8 out0=[r3] // get vcr.ifa + mov r14=1 + ;; + add r3=XSI_PSR_IC_OFS-XSI_IFA_OFS, r3 // point to vpsr.ic + ;; + st4 [r3]=r14 // vpsr.ic = 1 + adds r3=8,r2 // set up second base pointer + ;; +#else + mov out0=cr.ifa + mov out1=cr.isr + adds r3=8,r2 // set up second base pointer + ;; + ssm psr.ic | PSR_DEFAULT_BITS + ;; + srlz.i // guarantee that interruption collectin is on + ;; +#endif +#ifdef CONFIG_XEN + br.cond.sptk.many xen_page_fault + ;; +done_xen_page_fault: +#endif +(p15) ssm psr.i // restore psr.i + movl r14=ia64_leave_kernel + ;; + SAVE_REST + mov rp=r14 + ;; + adds out2=16,r12 // out2 = pointer to pt_regs + br.call.sptk.many b6=ia64_do_page_fault // ignore return address +END(page_fault) + + .org ia64_ivt+0x1c00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51) +ENTRY(dkey_miss) + DBG_FAULT(7) + FAULT(7) +#ifdef CONFIG_XEN + // Leaving this code inline above results in an IVT section overflow + // There is no particular reason for this code to be here... +xen_page_fault: +(p15) movl r3=XSI_PSR_I_ADDR + ;; +(p15) ld8 r3=[r3] + ;; +(p15) st1 [r3]=r0,XSI_PEND_OFS-XSI_PSR_I_ADDR_OFS // if (p15) vpsr.i = 1 + mov r14=r0 + ;; +(p15) ld4 r14=[r3] // if (pending_interrupts) + adds r3=8,r2 // re-set up second base pointer + ;; +(p15) cmp.ne p15,p0=r14,r0 + ;; + br.cond.sptk.many done_xen_page_fault + ;; +#endif +END(dkey_miss) + + .org ia64_ivt+0x2000 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54) +ENTRY(dirty_bit) + DBG_FAULT(8) + /* + * What we do here is to simply turn on the dirty bit in the PTE. We need to + * update both the page-table and the TLB entry. To efficiently access the PTE, + * we address it through the virtual page table. Most likely, the TLB entry for + * the relevant virtual page table page is still present in the TLB so we can + * normally do this without additional TLB misses. In case the necessary virtual + * page table TLB entry isn't present, we take a nested TLB miss hit where we look + * up the physical address of the L3 PTE and then continue at label 1 below. + */ +#ifdef CONFIG_XEN + movl r16=XSI_IFA + ;; + ld8 r16=[r16] + ;; +#else + mov r16=cr.ifa // get the address that caused the fault +#endif + movl r30=1f // load continuation point in case of nested fault + ;; +#ifdef CONFIG_XEN + mov r18=r8; + mov r8=r16; + XEN_HYPER_THASH;; + mov r17=r8; + mov r8=r18;; +#else + thash r17=r16 // compute virtual address of L3 PTE +#endif + mov r29=b0 // save b0 in case of nested fault + mov r31=pr // save pr +#ifdef CONFIG_SMP + mov r28=ar.ccv // save ar.ccv + ;; +1: ld8 r18=[r17] + ;; // avoid RAW on r18 + mov ar.ccv=r18 // set compare value for cmpxchg + or r25=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits + tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit + ;; +(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only update if page is present + mov r24=PAGE_SHIFT<<2 + ;; +(p6) cmp.eq p6,p7=r26,r18 // Only compare if page is present + ;; +#ifdef CONFIG_XEN +(p6) mov r18=r8 +(p6) mov r8=r25 + ;; +(p6) XEN_HYPER_ITC_D + ;; +(p6) mov r8=r18 +#else +(p6) itc.d r25 // install updated PTE +#endif + ;; + /* + * Tell the assemblers dependency-violation checker that the above "itc" instructions + * cannot possibly affect the following loads: + */ + dv_serialize_data + + ld8 r18=[r17] // read PTE again + ;; + cmp.eq p6,p7=r18,r25 // is it same as the newly installed + ;; +(p7) ptc.l r16,r24 + mov b0=r29 // restore b0 + mov ar.ccv=r28 +#else + ;; +1: ld8 r18=[r17] + ;; // avoid RAW on r18 + or r18=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits + mov b0=r29 // restore b0 + ;; + st8 [r17]=r18 // store back updated PTE + itc.d r18 // install updated PTE +#endif + mov pr=r31,-1 // restore pr +#ifdef CONFIG_XEN + XEN_HYPER_RFI + dv_serialize_data +#else + rfi +#endif +END(dirty_bit) + + .org ia64_ivt+0x2400 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27) +ENTRY(iaccess_bit) + DBG_FAULT(9) + // Like Entry 8, except for instruction access +#ifdef CONFIG_XEN + movl r16=XSI_IFA + ;; + ld8 r16=[r16] + ;; +#else + mov r16=cr.ifa // get the address that caused the fault +#endif + movl r30=1f // load continuation point in case of nested fault + mov r31=pr // save predicates +#ifdef CONFIG_ITANIUM + /* + * Erratum 10 (IFA may contain incorrect address) has "NoFix" status. + */ + mov r17=cr.ipsr + ;; + mov r18=cr.iip + tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set? + ;; +(p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa +#endif /* CONFIG_ITANIUM */ + ;; +#ifdef CONFIG_XEN + mov r18=r8; + mov r8=r16; + XEN_HYPER_THASH;; + mov r17=r8; + mov r8=r18;; +#else + thash r17=r16 // compute virtual address of L3 PTE +#endif + mov r29=b0 // save b0 in case of nested fault) +#ifdef CONFIG_SMP + mov r28=ar.ccv // save ar.ccv + ;; +1: ld8 r18=[r17] + ;; + mov ar.ccv=r18 // set compare value for cmpxchg + or r25=_PAGE_A,r18 // set the accessed bit + tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit + ;; +(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page present + mov r24=PAGE_SHIFT<<2 + ;; +(p6) cmp.eq p6,p7=r26,r18 // Only if page present + ;; +#ifdef CONFIG_XEN + mov r26=r8 + mov r8=r25 + ;; +(p6) XEN_HYPER_ITC_I + ;; + mov r8=r26 + ;; +#else +(p6) itc.i r25 // install updated PTE +#endif + ;; + /* + * Tell the assemblers dependency-violation checker that the above "itc" instructions + * cannot possibly affect the following loads: + */ + dv_serialize_data + + ld8 r18=[r17] // read PTE again + ;; + cmp.eq p6,p7=r18,r25 // is it same as the newly installed + ;; +(p7) ptc.l r16,r24 + mov b0=r29 // restore b0 + mov ar.ccv=r28 +#else /* !CONFIG_SMP */ + ;; +1: ld8 r18=[r17] + ;; + or r18=_PAGE_A,r18 // set the accessed bit + mov b0=r29 // restore b0 + ;; + st8 [r17]=r18 // store back updated PTE + itc.i r18 // install updated PTE +#endif /* !CONFIG_SMP */ + mov pr=r31,-1 +#ifdef CONFIG_XEN + XEN_HYPER_RFI + dv_serialize_data +#else + rfi +#endif +END(iaccess_bit) + + .org ia64_ivt+0x2800 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55) +ENTRY(daccess_bit) + DBG_FAULT(10) + // Like Entry 8, except for data access +#ifdef CONFIG_XEN + movl r16=XSI_IFA + ;; + ld8 r16=[r16] + ;; +#else + mov r16=cr.ifa // get the address that caused the fault +#endif + movl r30=1f // load continuation point in case of nested fault + ;; +#ifdef CONFIG_XEN + mov r18=r8 + mov r8=r16 + XEN_HYPER_THASH + ;; + mov r17=r8 + mov r8=r18 + ;; +#else + thash r17=r16 // compute virtual address of L3 PTE +#endif + mov r31=pr + mov r29=b0 // save b0 in case of nested fault) +#ifdef CONFIG_SMP + mov r28=ar.ccv // save ar.ccv + ;; +1: ld8 r18=[r17] + ;; // avoid RAW on r18 + mov ar.ccv=r18 // set compare value for cmpxchg + or r25=_PAGE_A,r18 // set the dirty bit + tbit.z p7,p6 = r18,_PAGE_P_BIT // Check present bit + ;; +(p6) cmpxchg8.acq r26=[r17],r25,ar.ccv // Only if page is present + mov r24=PAGE_SHIFT<<2 + ;; +(p6) cmp.eq p6,p7=r26,r18 // Only if page is present + ;; +#ifdef CONFIG_XEN + mov r26=r8 + mov r8=r25 + ;; +(p6) XEN_HYPER_ITC_D + ;; + mov r8=r26 + ;; +#else +(p6) itc.d r25 // install updated PTE +#endif + /* + * Tell the assemblers dependency-violation checker that the above "itc" instructions + * cannot possibly affect the following loads: + */ + dv_serialize_data + ;; + ld8 r18=[r17] // read PTE again + ;; + cmp.eq p6,p7=r18,r25 // is it same as the newly installed + ;; +(p7) ptc.l r16,r24 + mov ar.ccv=r28 +#else + ;; +1: ld8 r18=[r17] + ;; // avoid RAW on r18 + or r18=_PAGE_A,r18 // set the accessed bit + ;; + st8 [r17]=r18 // store back updated PTE + itc.d r18 // install updated PTE +#endif + mov b0=r29 // restore b0 + mov pr=r31,-1 +#ifdef CONFIG_XEN + XEN_HYPER_RFI + dv_serialize_data +#else + rfi +#endif +END(daccess_bit) + + .org ia64_ivt+0x2c00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x2c00 Entry 11 (size 64 bundles) Break instruction (33) +ENTRY(break_fault) + /* + * The streamlined system call entry/exit paths only save/restore the initial part + * of pt_regs. This implies that the callers of system-calls must adhere to the + * normal procedure calling conventions. + * + * Registers to be saved & restored: + * CR registers: cr.ipsr, cr.iip, cr.ifs + * AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, ar.fpsr + * others: pr, b0, b6, loadrs, r1, r11, r12, r13, r15 + * Registers to be restored only: + * r8-r11: output value from the system call. + * + * During system call exit, scratch registers (including r15) are modified/cleared + * to prevent leaking bits from kernel to user level. + */ + DBG_FAULT(11) + mov.m r16=IA64_KR(CURRENT) // M2 r16 <- current task (12 cyc) +#ifdef CONFIG_XEN + movl r22=XSI_IPSR + ;; + ld8 r29=[r22],XSI_IIM_OFS-XSI_IPSR_OFS // get ipsr, point to iip +#else + mov r29=cr.ipsr // M2 (12 cyc) +#endif + mov r31=pr // I0 (2 cyc) + +#ifdef CONFIG_XEN + ;; + ld8 r17=[r22],XSI_IIP_OFS-XSI_IIM_OFS +#else + mov r17=cr.iim // M2 (2 cyc) +#endif + mov.m r27=ar.rsc // M2 (12 cyc) + mov r18=__IA64_BREAK_SYSCALL // A + + mov.m ar.rsc=0 // M2 + mov.m r21=ar.fpsr // M2 (12 cyc) + mov r19=b6 // I0 (2 cyc) + ;; + mov.m r23=ar.bspstore // M2 (12 cyc) + mov.m r24=ar.rnat // M2 (5 cyc) + mov.i r26=ar.pfs // I0 (2 cyc) + + invala // M0|1 + nop.m 0 // M + mov r20=r1 // A save r1 + + nop.m 0 + movl r30=sys_call_table // X + +#ifdef CONFIG_XEN + ld8 r28=[r22] +#else + mov r28=cr.iip // M2 (2 cyc) +#endif + cmp.eq p0,p7=r18,r17 // I0 is this a system call? +(p7) br.cond.spnt non_syscall // B no -> + // + // From this point on, we are definitely on the syscall-path + // and we can use (non-banked) scratch registers. + // +/////////////////////////////////////////////////////////////////////// + mov r1=r16 // A move task-pointer to "addl"-addressable reg + mov r2=r16 // A setup r2 for ia64_syscall_setup + add r9=TI_FLAGS+IA64_TASK_SIZE,r16 // A r9 = ¤t_thread_info()->flags + + adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 + adds r15=-1024,r15 // A subtract 1024 from syscall number + mov r3=NR_syscalls - 1 + ;; + ld1.bias r17=[r16] // M0|1 r17 = current->thread.on_ustack flag + ld4 r9=[r9] // M0|1 r9 = current_thread_info()->flags + extr.u r8=r29,41,2 // I0 extract ei field from cr.ipsr + + shladd r30=r15,3,r30 // A r30 = sys_call_table + 8*(syscall-1024) + addl r22=IA64_RBS_OFFSET,r1 // A compute base of RBS + cmp.leu p6,p7=r15,r3 // A syscall number in range? + ;; + + lfetch.fault.excl.nt1 [r22] // M0|1 prefetch RBS +(p6) ld8 r30=[r30] // M0|1 load address of syscall entry point + tnat.nz.or p7,p0=r15 // I0 is syscall nr a NaT? + + mov.m ar.bspstore=r22 // M2 switch to kernel RBS + cmp.eq p8,p9=2,r8 // A isr.ei==2? + ;; + +(p8) mov r8=0 // A clear ei to 0 +(p7) movl r30=sys_ni_syscall // X + +(p8) adds r28=16,r28 // A switch cr.iip to next bundle +(p9) adds r8=1,r8 // A increment ei to next slot + nop.i 0 + ;; + + mov.m r25=ar.unat // M2 (5 cyc) + dep r29=r8,r29,41,2 // I0 insert new ei into cr.ipsr + adds r15=1024,r15 // A restore original syscall number + // + // If any of the above loads miss in L1D, we'll stall here until + // the data arrives. + // +/////////////////////////////////////////////////////////////////////// + st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag + mov b6=r30 // I0 setup syscall handler branch reg early + cmp.eq pKStk,pUStk=r0,r17 // A were we on kernel stacks already? + + and r9=_TIF_SYSCALL_TRACEAUDIT,r9 // A mask trace or audit + mov r18=ar.bsp // M2 (12 cyc) +(pKStk) br.cond.spnt .break_fixup // B we're already in kernel-mode -- fix up RBS + ;; +.back_from_break_fixup: +(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1 // A compute base of memory stack + cmp.eq p14,p0=r9,r0 // A are syscalls being traced/audited? + br.call.sptk.many b7=ia64_syscall_setup // B +1: + mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0 + nop 0 +#ifdef CONFIG_XEN + mov r2=b0; br.call.sptk b0=xen_bsw1;; mov b0=r2;; +#else + bsw.1 // B (6 cyc) regs are saved, switch to bank 1 +#endif + ;; + +#ifdef CONFIG_XEN + movl r16=XSI_PSR_IC + mov r3=1 + ;; + st4 [r16]=r3,XSI_PSR_I_ADDR_OFS-XSI_PSR_IC_OFS // vpsr.ic = 1 +#else + ssm psr.ic | PSR_DEFAULT_BITS // M2 now it's safe to re-enable intr.-collection +#endif + movl r3=ia64_ret_from_syscall // X + ;; + + srlz.i // M0 ensure interruption collection is on + mov rp=r3 // I0 set the real return addr +(p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT + +#ifdef CONFIG_XEN +(p15) ld8 r16=[r16] // vpsr.i + ;; +(p15) st1 [r16]=r0,XSI_PEND_OFS-XSI_PSR_I_ADDR_OFS // if (p15) vpsr.i = 1 + mov r2=r0 + ;; +(p15) ld4 r2=[r16] // if (pending_interrupts) + ;; + cmp.ne p6,p0=r2,r0 + ;; +(p6) ssm psr.i // do a real ssm psr.i +#else +(p15) ssm psr.i // M2 restore psr.i +#endif +(p14) br.call.sptk.many b6=b6 // B invoke syscall-handker (ignore return addr) + br.cond.spnt.many ia64_trace_syscall // B do syscall-tracing thingamagic + // NOT REACHED +/////////////////////////////////////////////////////////////////////// + // On entry, we optimistically assumed that we're coming from user-space. + // For the rare cases where a system-call is done from within the kernel, + // we fix things up at this point: +.break_fixup: + add r1=-IA64_PT_REGS_SIZE,sp // A allocate space for pt_regs structure + mov ar.rnat=r24 // M2 restore kernel's AR.RNAT + ;; + mov ar.bspstore=r23 // M2 restore kernel's AR.BSPSTORE + br.cond.sptk .back_from_break_fixup +END(break_fault) + + .org ia64_ivt+0x3000 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x3000 Entry 12 (size 64 bundles) External Interrupt (4) +ENTRY(interrupt) + DBG_FAULT(12) + mov r31=pr // prepare to save predicates + ;; + SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3 +#ifdef CONFIG_XEN + movl r3=XSI_PSR_IC + mov r14=1 + ;; + st4 [r3]=r14 +#else + ssm psr.ic | PSR_DEFAULT_BITS +#endif + ;; + adds r3=8,r2 // set up second base pointer for SAVE_REST + srlz.i // ensure everybody knows psr.ic is back on + ;; + SAVE_REST + ;; + alloc r14=ar.pfs,0,0,2,0 // must be first in an insn group +#ifdef CONFIG_XEN + ;; + br.call.sptk.many rp=xen_get_ivr + ;; + mov out0=r8 // pass cr.ivr as first arg +#else + mov out0=cr.ivr // pass cr.ivr as first arg +#endif + add out1=16,sp // pass pointer to pt_regs as second arg + ;; + srlz.d // make sure we see the effect of cr.ivr + movl r14=ia64_leave_kernel + ;; + mov rp=r14 + br.call.sptk.many b6=ia64_handle_irq +END(interrupt) + + .org ia64_ivt+0x3400 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x3400 Entry 13 (size 64 bundles) Reserved + DBG_FAULT(13) + FAULT(13) + + .org ia64_ivt+0x3800 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x3800 Entry 14 (size 64 bundles) Reserved + DBG_FAULT(14) + FAULT(14) + + /* + * There is no particular reason for this code to be here, other than that + * there happens to be space here that would go unused otherwise. If this + * fault ever gets "unreserved", simply moved the following code to a more + * suitable spot... + * + * ia64_syscall_setup() is a separate subroutine so that it can + * allocate stacked registers so it can safely demine any + * potential NaT values from the input registers. + * + * On entry: + * - executing on bank 0 or bank 1 register set (doesn't matter) + * - r1: stack pointer + * - r2: current task pointer + * - r3: preserved + * - r11: original contents (saved ar.pfs to be saved) + * - r12: original contents (sp to be saved) + * - r13: original contents (tp to be saved) + * - r15: original contents (syscall # to be saved) + * - r18: saved bsp (after switching to kernel stack) + * - r19: saved b6 + * - r20: saved r1 (gp) + * - r21: saved ar.fpsr + * - r22: kernel's register backing store base (krbs_base) + * - r23: saved ar.bspstore + * - r24: saved ar.rnat + * - r25: saved ar.unat + * - r26: saved ar.pfs + * - r27: saved ar.rsc + * - r28: saved cr.iip + * - r29: saved cr.ipsr + * - r31: saved pr + * - b0: original contents (to be saved) + * On exit: + * - p10: TRUE if syscall is invoked with more than 8 out + * registers or r15's Nat is true + * - r1: kernel's gp + * - r3: preserved (same as on entry) + * - r8: -EINVAL if p10 is true + * - r12: points to kernel stack + * - r13: points to current task + * - r14: preserved (same as on entry) + * - p13: preserved + * - p15: TRUE if interrupts need to be re-enabled + * - ar.fpsr: set to kernel settings + * - b6: preserved (same as on entry) + */ +#ifndef CONFIG_XEN +GLOBAL_ENTRY(ia64_syscall_setup) +#if PT(B6) != 0 +# error This code assumes that b6 is the first field in pt_regs. +#endif + st8 [r1]=r19 // save b6 + add r16=PT(CR_IPSR),r1 // initialize first base pointer + add r17=PT(R11),r1 // initialize second base pointer + ;; + alloc r19=ar.pfs,8,0,0,0 // ensure in0-in7 are writable + st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR) // save cr.ipsr + tnat.nz p8,p0=in0 + + st8.spill [r17]=r11,PT(CR_IIP)-PT(R11) // save r11 + tnat.nz p9,p0=in1 +(pKStk) mov r18=r0 // make sure r18 isn't NaT + ;; + + st8 [r16]=r26,PT(CR_IFS)-PT(AR_PFS) // save ar.pfs + st8 [r17]=r28,PT(AR_UNAT)-PT(CR_IIP) // save cr.iip + mov r28=b0 // save b0 (2 cyc) + ;; + + st8 [r17]=r25,PT(AR_RSC)-PT(AR_UNAT) // save ar.unat + dep r19=0,r19,38,26 // clear all bits but 0..37 [I0] +(p8) mov in0=-1 + ;; + + st8 [r16]=r19,PT(AR_RNAT)-PT(CR_IFS) // store ar.pfs.pfm in cr.ifs + extr.u r11=r19,7,7 // I0 // get sol of ar.pfs + and r8=0x7f,r19 // A // get sof of ar.pfs + + st8 [r17]=r27,PT(AR_BSPSTORE)-PT(AR_RSC)// save ar.rsc + tbit.nz p15,p0=r29,IA64_PSR_I_BIT // I0 +(p9) mov in1=-1 + ;; + +(pUStk) sub r18=r18,r22 // r18=RSE.ndirty*8 + tnat.nz p10,p0=in2 + add r11=8,r11 + ;; +(pKStk) adds r16=PT(PR)-PT(AR_RNAT),r16 // skip over ar_rnat field +(pKStk) adds r17=PT(B0)-PT(AR_BSPSTORE),r17 // skip over ar_bspstore field + tnat.nz p11,p0=in3 + ;; +(p10) mov in2=-1 + tnat.nz p12,p0=in4 // [I0] +(p11) mov in3=-1 + ;; +(pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT) // save ar.rnat +(pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE) // save ar.bspstore + shl r18=r18,16 // compute ar.rsc to be used for "loadrs" + ;; + st8 [r16]=r31,PT(LOADRS)-PT(PR) // save predicates + st8 [r17]=r28,PT(R1)-PT(B0) // save b0 + tnat.nz p13,p0=in5 // [I0] + ;; + st8 [r16]=r18,PT(R12)-PT(LOADRS) // save ar.rsc value for "loadrs" + st8.spill [r17]=r20,PT(R13)-PT(R1) // save original r1 +(p12) mov in4=-1 + ;; + +.mem.offset 0,0; st8.spill [r16]=r12,PT(AR_FPSR)-PT(R12) // save r12 +.mem.offset 8,0; st8.spill [r17]=r13,PT(R15)-PT(R13) // save r13 +(p13) mov in5=-1 + ;; + st8 [r16]=r21,PT(R8)-PT(AR_FPSR) // save ar.fpsr + tnat.nz p13,p0=in6 + cmp.lt p10,p9=r11,r8 // frame size can't be more than local+8 + ;; + mov r8=1 +(p9) tnat.nz p10,p0=r15 + adds r12=-16,r1 // switch to kernel memory stack (with 16 bytes of scratch) + + st8.spill [r17]=r15 // save r15 + tnat.nz p8,p0=in7 + nop.i 0 + + mov r13=r2 // establish `current' + movl r1=__gp // establish kernel global pointer + ;; + st8 [r16]=r8 // ensure pt_regs.r8 != 0 (see handle_syscall_error) +(p13) mov in6=-1 +(p8) mov in7=-1 + + cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0 + movl r17=FPSR_DEFAULT + ;; + mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value +(p10) mov r8=-EINVAL + br.ret.sptk.many b7 +END(ia64_syscall_setup) +#endif + + .org ia64_ivt+0x3c00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x3c00 Entry 15 (size 64 bundles) Reserved + DBG_FAULT(15) + FAULT(15) + + /* + * Squatting in this space ... + * + * This special case dispatcher for illegal operation faults allows preserved + * registers to be modified through a callback function (asm only) that is handed + * back from the fault handler in r8. Up to three arguments can be passed to the + * callback function by returning an aggregate with the callback as its first + * element, followed by the arguments. + */ +ENTRY(dispatch_illegal_op_fault) + .prologue + .body + SAVE_MIN_WITH_COVER + ssm psr.ic | PSR_DEFAULT_BITS + ;; + srlz.i // guarantee that interruption collection is on + ;; +(p15) ssm psr.i // restore psr.i + adds r3=8,r2 // set up second base pointer for SAVE_REST + ;; + alloc r14=ar.pfs,0,0,1,0 // must be first in insn group + mov out0=ar.ec + ;; + SAVE_REST + PT_REGS_UNWIND_INFO(0) + ;; + br.call.sptk.many rp=ia64_illegal_op_fault +.ret0: ;; + alloc r14=ar.pfs,0,0,3,0 // must be first in insn group + mov out0=r9 + mov out1=r10 + mov out2=r11 + movl r15=ia64_leave_kernel + ;; + mov rp=r15 + mov b6=r8 + ;; + cmp.ne p6,p0=0,r8 +(p6) br.call.dpnt.many b6=b6 // call returns to ia64_leave_kernel + br.sptk.many ia64_leave_kernel +END(dispatch_illegal_op_fault) + + .org ia64_ivt+0x4000 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x4000 Entry 16 (size 64 bundles) Reserved + DBG_FAULT(16) + FAULT(16) + + .org ia64_ivt+0x4400 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x4400 Entry 17 (size 64 bundles) Reserved + DBG_FAULT(17) + FAULT(17) + +ENTRY(non_syscall) + mov ar.rsc=r27 // restore ar.rsc before SAVE_MIN_WITH_COVER + ;; + SAVE_MIN_WITH_COVER + + // There is no particular reason for this code to be here, other than that + // there happens to be space here that would go unused otherwise. If this + // fault ever gets "unreserved", simply moved the following code to a more + // suitable spot... + + alloc r14=ar.pfs,0,0,2,0 + mov out0=cr.iim + add out1=16,sp + adds r3=8,r2 // set up second base pointer for SAVE_REST + + ssm psr.ic | PSR_DEFAULT_BITS + ;; + srlz.i // guarantee that interruption collection is on + ;; +(p15) ssm psr.i // restore psr.i + movl r15=ia64_leave_kernel + ;; + SAVE_REST + mov rp=r15 + ;; + br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and ignore return addr +END(non_syscall) + + .org ia64_ivt+0x4800 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x4800 Entry 18 (size 64 bundles) Reserved + DBG_FAULT(18) + FAULT(18) + + /* + * There is no particular reason for this code to be here, other than that + * there happens to be space here that would go unused otherwise. If this + * fault ever gets "unreserved", simply moved the following code to a more + * suitable spot... + */ + +ENTRY(dispatch_unaligned_handler) + SAVE_MIN_WITH_COVER + ;; + alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!) + mov out0=cr.ifa + adds out1=16,sp + + ssm psr.ic | PSR_DEFAULT_BITS + ;; + srlz.i // guarantee that interruption collection is on + ;; +(p15) ssm psr.i // restore psr.i + adds r3=8,r2 // set up second base pointer + ;; + SAVE_REST + movl r14=ia64_leave_kernel + ;; + mov rp=r14 + br.sptk.many ia64_prepare_handle_unaligned +END(dispatch_unaligned_handler) + + .org ia64_ivt+0x4c00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x4c00 Entry 19 (size 64 bundles) Reserved + DBG_FAULT(19) + FAULT(19) + + /* + * There is no particular reason for this code to be here, other than that + * there happens to be space here that would go unused otherwise. If this + * fault ever gets "unreserved", simply moved the following code to a more + * suitable spot... + */ + +ENTRY(dispatch_to_fault_handler) + /* + * Input: + * psr.ic: off + * r19: fault vector number (e.g., 24 for General Exception) + * r31: contains saved predicates (pr) + */ + SAVE_MIN_WITH_COVER_R19 + alloc r14=ar.pfs,0,0,5,0 + mov out0=r15 +#ifdef CONFIG_XEN + movl out1=XSI_ISR + ;; + adds out2=XSI_IFA-XSI_ISR,out1 + adds out3=XSI_IIM-XSI_ISR,out1 + adds out4=XSI_ITIR-XSI_ISR,out1 + ;; + ld8 out1=[out1] + ld8 out2=[out2] + ld8 out3=[out4] + ld8 out4=[out4] + ;; +#else + mov out1=cr.isr + mov out2=cr.ifa + mov out3=cr.iim + mov out4=cr.itir + ;; +#endif + ssm psr.ic | PSR_DEFAULT_BITS + ;; + srlz.i // guarantee that interruption collection is on + ;; +(p15) ssm psr.i // restore psr.i + adds r3=8,r2 // set up second base pointer for SAVE_REST + ;; + SAVE_REST + movl r14=ia64_leave_kernel + ;; + mov rp=r14 + br.call.sptk.many b6=ia64_fault +END(dispatch_to_fault_handler) + +// +// --- End of long entries, Beginning of short entries +// + + .org ia64_ivt+0x5000 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49) +ENTRY(page_not_present) + DBG_FAULT(20) + mov r16=cr.ifa + rsm psr.dt + /* + * The Linux page fault handler doesn't expect non-present pages to be in + * the TLB. Flush the existing entry now, so we meet that expectation. + */ + mov r17=PAGE_SHIFT<<2 + ;; + ptc.l r16,r17 + ;; + mov r31=pr + srlz.d + br.sptk.many page_fault +END(page_not_present) + + .org ia64_ivt+0x5100 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52) +ENTRY(key_permission) + DBG_FAULT(21) + mov r16=cr.ifa + rsm psr.dt + mov r31=pr + ;; + srlz.d + br.sptk.many page_fault +END(key_permission) + + .org ia64_ivt+0x5200 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26) +ENTRY(iaccess_rights) + DBG_FAULT(22) + mov r16=cr.ifa + rsm psr.dt + mov r31=pr + ;; + srlz.d + br.sptk.many page_fault +END(iaccess_rights) + + .org ia64_ivt+0x5300 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53) +ENTRY(daccess_rights) + DBG_FAULT(23) +#ifdef CONFIG_XEN + movl r16=XSI_IFA + ;; + ld8 r16=[r16] + ;; + XEN_HYPER_RSM_PSR_DT +#else + mov r16=cr.ifa + rsm psr.dt +#endif + mov r31=pr + ;; + srlz.d + br.sptk.many page_fault +END(daccess_rights) + + .org ia64_ivt+0x5400 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39) +ENTRY(general_exception) + DBG_FAULT(24) + mov r16=cr.isr + mov r31=pr + ;; + cmp4.eq p6,p0=0,r16 +(p6) br.sptk.many dispatch_illegal_op_fault + ;; + mov r19=24 // fault number + br.sptk.many dispatch_to_fault_handler +END(general_exception) + + .org ia64_ivt+0x5500 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35) +ENTRY(disabled_fp_reg) + DBG_FAULT(25) + rsm psr.dfh // ensure we can access fph + ;; + srlz.d + mov r31=pr + mov r19=25 + br.sptk.many dispatch_to_fault_handler +END(disabled_fp_reg) + + .org ia64_ivt+0x5600 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50) +ENTRY(nat_consumption) + DBG_FAULT(26) + + mov r16=cr.ipsr + mov r17=cr.isr + mov r31=pr // save PR + ;; + and r18=0xf,r17 // r18 = cr.ipsr.code{3:0} + tbit.z p6,p0=r17,IA64_ISR_NA_BIT + ;; + cmp.ne.or p6,p0=IA64_ISR_CODE_LFETCH,r18 + dep r16=-1,r16,IA64_PSR_ED_BIT,1 +(p6) br.cond.spnt 1f // branch if (cr.ispr.na == 0 || cr.ipsr.code{3:0} != LFETCH) + ;; + mov cr.ipsr=r16 // set cr.ipsr.na + mov pr=r31,-1 + ;; + rfi + +1: mov pr=r31,-1 + ;; + FAULT(26) +END(nat_consumption) + + .org ia64_ivt+0x5700 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x5700 Entry 27 (size 16 bundles) Speculation (40) +ENTRY(speculation_vector) + DBG_FAULT(27) + /* + * A [f]chk.[as] instruction needs to take the branch to the recovery code but + * this part of the architecture is not implemented in hardware on some CPUs, such + * as Itanium. Thus, in general we need to emulate the behavior. IIM contains + * the relative target (not yet sign extended). So after sign extending it we + * simply add it to IIP. We also need to reset the EI field of the IPSR to zero, + * i.e., the slot to restart into. + * + * cr.imm contains zero_ext(imm21) + */ + mov r18=cr.iim + ;; + mov r17=cr.iip + shl r18=r18,43 // put sign bit in position (43=64-21) + ;; + + mov r16=cr.ipsr + shr r18=r18,39 // sign extend (39=43-4) + ;; + + add r17=r17,r18 // now add the offset + ;; + mov cr.iip=r17 + dep r16=0,r16,41,2 // clear EI + ;; + + mov cr.ipsr=r16 + ;; + +#ifdef CONFIG_XEN + XEN_HYPER_RFI; +#else + rfi // and go back +#endif +END(speculation_vector) + + .org ia64_ivt+0x5800 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x5800 Entry 28 (size 16 bundles) Reserved + DBG_FAULT(28) + FAULT(28) + + .org ia64_ivt+0x5900 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56) +ENTRY(debug_vector) + DBG_FAULT(29) + FAULT(29) +END(debug_vector) + + .org ia64_ivt+0x5a00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57) +ENTRY(unaligned_access) + DBG_FAULT(30) + mov r31=pr // prepare to save predicates + ;; + br.sptk.many dispatch_unaligned_handler +END(unaligned_access) + + .org ia64_ivt+0x5b00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57) +ENTRY(unsupported_data_reference) + DBG_FAULT(31) + FAULT(31) +END(unsupported_data_reference) + + .org ia64_ivt+0x5c00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x5c00 Entry 32 (size 16 bundles) Floating-Point Fault (64) +ENTRY(floating_point_fault) + DBG_FAULT(32) + FAULT(32) +END(floating_point_fault) + + .org ia64_ivt+0x5d00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66) +ENTRY(floating_point_trap) + DBG_FAULT(33) + FAULT(33) +END(floating_point_trap) + + .org ia64_ivt+0x5e00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66) +ENTRY(lower_privilege_trap) + DBG_FAULT(34) + FAULT(34) +END(lower_privilege_trap) + + .org ia64_ivt+0x5f00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68) +ENTRY(taken_branch_trap) + DBG_FAULT(35) + FAULT(35) +END(taken_branch_trap) + + .org ia64_ivt+0x6000 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69) +ENTRY(single_step_trap) + DBG_FAULT(36) + FAULT(36) +END(single_step_trap) + + .org ia64_ivt+0x6100 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x6100 Entry 37 (size 16 bundles) Reserved + DBG_FAULT(37) + FAULT(37) + + .org ia64_ivt+0x6200 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x6200 Entry 38 (size 16 bundles) Reserved + DBG_FAULT(38) + FAULT(38) + + .org ia64_ivt+0x6300 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x6300 Entry 39 (size 16 bundles) Reserved + DBG_FAULT(39) + FAULT(39) + + .org ia64_ivt+0x6400 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x6400 Entry 40 (size 16 bundles) Reserved + DBG_FAULT(40) + FAULT(40) + + .org ia64_ivt+0x6500 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x6500 Entry 41 (size 16 bundles) Reserved + DBG_FAULT(41) + FAULT(41) + + .org ia64_ivt+0x6600 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x6600 Entry 42 (size 16 bundles) Reserved + DBG_FAULT(42) + FAULT(42) + + .org ia64_ivt+0x6700 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x6700 Entry 43 (size 16 bundles) Reserved + DBG_FAULT(43) + FAULT(43) + + .org ia64_ivt+0x6800 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x6800 Entry 44 (size 16 bundles) Reserved + DBG_FAULT(44) + FAULT(44) + + .org ia64_ivt+0x6900 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception (17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77) +ENTRY(ia32_exception) + DBG_FAULT(45) + FAULT(45) +END(ia32_exception) + + .org ia64_ivt+0x6a00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71) +ENTRY(ia32_intercept) + DBG_FAULT(46) +#ifdef CONFIG_IA32_SUPPORT + mov r31=pr + mov r16=cr.isr + ;; + extr.u r17=r16,16,8 // get ISR.code + mov r18=ar.eflag + mov r19=cr.iim // old eflag value + ;; + cmp.ne p6,p0=2,r17 +(p6) br.cond.spnt 1f // not a system flag fault + xor r16=r18,r19 + ;; + extr.u r17=r16,18,1 // get the eflags.ac bit + ;; + cmp.eq p6,p0=0,r17 +(p6) br.cond.spnt 1f // eflags.ac bit didn't change + ;; + mov pr=r31,-1 // restore predicate registers +#ifdef CONFIG_XEN + XEN_HYPER_RFI; +#else + rfi +#endif + +1: +#endif // CONFIG_IA32_SUPPORT + FAULT(46) +END(ia32_intercept) + + .org ia64_ivt+0x6b00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt (74) +ENTRY(ia32_interrupt) + DBG_FAULT(47) +#ifdef CONFIG_IA32_SUPPORT + mov r31=pr + br.sptk.many dispatch_to_ia32_handler +#else + FAULT(47) +#endif +END(ia32_interrupt) + + .org ia64_ivt+0x6c00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x6c00 Entry 48 (size 16 bundles) Reserved + DBG_FAULT(48) + FAULT(48) + + .org ia64_ivt+0x6d00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x6d00 Entry 49 (size 16 bundles) Reserved + DBG_FAULT(49) + FAULT(49) + + .org ia64_ivt+0x6e00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x6e00 Entry 50 (size 16 bundles) Reserved + DBG_FAULT(50) + FAULT(50) + + .org ia64_ivt+0x6f00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x6f00 Entry 51 (size 16 bundles) Reserved + DBG_FAULT(51) + FAULT(51) + + .org ia64_ivt+0x7000 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x7000 Entry 52 (size 16 bundles) Reserved + DBG_FAULT(52) + FAULT(52) + + .org ia64_ivt+0x7100 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x7100 Entry 53 (size 16 bundles) Reserved + DBG_FAULT(53) + FAULT(53) + + .org ia64_ivt+0x7200 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x7200 Entry 54 (size 16 bundles) Reserved + DBG_FAULT(54) + FAULT(54) + + .org ia64_ivt+0x7300 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x7300 Entry 55 (size 16 bundles) Reserved + DBG_FAULT(55) + FAULT(55) + + .org ia64_ivt+0x7400 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x7400 Entry 56 (size 16 bundles) Reserved + DBG_FAULT(56) + FAULT(56) + + .org ia64_ivt+0x7500 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x7500 Entry 57 (size 16 bundles) Reserved + DBG_FAULT(57) + FAULT(57) + + .org ia64_ivt+0x7600 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x7600 Entry 58 (size 16 bundles) Reserved + DBG_FAULT(58) + FAULT(58) + + .org ia64_ivt+0x7700 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x7700 Entry 59 (size 16 bundles) Reserved + DBG_FAULT(59) + FAULT(59) + + .org ia64_ivt+0x7800 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x7800 Entry 60 (size 16 bundles) Reserved + DBG_FAULT(60) + FAULT(60) + + .org ia64_ivt+0x7900 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x7900 Entry 61 (size 16 bundles) Reserved + DBG_FAULT(61) + FAULT(61) + + .org ia64_ivt+0x7a00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x7a00 Entry 62 (size 16 bundles) Reserved + DBG_FAULT(62) + FAULT(62) + + .org ia64_ivt+0x7b00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x7b00 Entry 63 (size 16 bundles) Reserved + DBG_FAULT(63) + FAULT(63) + + .org ia64_ivt+0x7c00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x7c00 Entry 64 (size 16 bundles) Reserved + DBG_FAULT(64) + FAULT(64) + + .org ia64_ivt+0x7d00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x7d00 Entry 65 (size 16 bundles) Reserved + DBG_FAULT(65) + FAULT(65) + + .org ia64_ivt+0x7e00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x7e00 Entry 66 (size 16 bundles) Reserved + DBG_FAULT(66) + FAULT(66) + +#ifdef CONFIG_XEN + /* + * There is no particular reason for this code to be here, other than that + * there happens to be space here that would go unused otherwise. If this + * fault ever gets "unreserved", simply moved the following code to a more + * suitable spot... + */ + +GLOBAL_ENTRY(xen_bsw1) + /* FIXME: THIS CODE IS NOT NaT SAFE! */ + movl r30=XSI_BANKNUM; + mov r31=1;; + st4 [r30]=r31; + movl r30=XSI_BANK1_R16; + movl r31=XSI_BANK1_R16+8;; + ld8 r16=[r30],16; ld8 r17=[r31],16;; + ld8 r18=[r30],16; ld8 r19=[r31],16;; + ld8 r20=[r30],16; ld8 r21=[r31],16;; + ld8 r22=[r30],16; ld8 r23=[r31],16;; + ld8 r24=[r30],16; ld8 r25=[r31],16;; + ld8 r26=[r30],16; ld8 r27=[r31],16;; + ld8 r28=[r30],16; ld8 r29=[r31],16;; + ld8 r30=[r30]; ld8 r31=[r31];; + br.ret.sptk.many b0 +END(xen_bsw1) +#endif + + .org ia64_ivt+0x7f00 +///////////////////////////////////////////////////////////////////////////////////////// +// 0x7f00 Entry 67 (size 16 bundles) Reserved + DBG_FAULT(67) + FAULT(67) + +#ifdef CONFIG_IA32_SUPPORT + + /* + * There is no particular reason for this code to be here, other than that + * there happens to be space here that would go unused otherwise. If this + * fault ever gets "unreserved", simply moved the following code to a more + * suitable spot... + */ + + // IA32 interrupt entry point + +ENTRY(dispatch_to_ia32_handler) + SAVE_MIN + ;; + mov r14=cr.isr + ssm psr.ic | PSR_DEFAULT_BITS + ;; + srlz.i // guarantee that interruption collection is on + ;; +(p15) ssm psr.i + adds r3=8,r2 // Base pointer for SAVE_REST + ;; + SAVE_REST + ;; + mov r15=0x80 + shr r14=r14,16 // Get interrupt number + ;; + cmp.ne p6,p0=r14,r15 +(p6) br.call.dpnt.many b6=non_ia32_syscall + + adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp // 16 byte hole per SW conventions + adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp + ;; + cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0 + ld8 r8=[r14] // get r8 + ;; + st8 [r15]=r8 // save original EAX in r1 (IA32 procs don't use the GP) + ;; + alloc r15=ar.pfs,0,0,6,0 // must first in an insn group + ;; + ld4 r8=[r14],8 // r8 == eax (syscall number) + mov r15=IA32_NR_syscalls + ;; + cmp.ltu.unc p6,p7=r8,r15 + ld4 out1=[r14],8 // r9 == ecx + ;; + ld4 out2=[r14],8 // r10 == edx + ;; + ld4 out0=[r14] // r11 == ebx + adds r14=(IA64_PT_REGS_R13_OFFSET) + 16,sp + ;; + ld4 out5=[r14],PT(R14)-PT(R13) // r13 == ebp + ;; + ld4 out3=[r14],PT(R15)-PT(R14) // r14 == esi + adds r2=TI_FLAGS+IA64_TASK_SIZE,r13 + ;; + ld4 out4=[r14] // r15 == edi + movl r16=ia32_syscall_table + ;; +(p6) shladd r16=r8,3,r16 // force ni_syscall if not valid syscall number + ld4 r2=[r2] // r2 = current_thread_info()->flags + ;; + ld8 r16=[r16] + and r2=_TIF_SYSCALL_TRACEAUDIT,r2 // mask trace or audit + ;; + mov b6=r16 + movl r15=ia32_ret_from_syscall + cmp.eq p8,p0=r2,r0 + ;; + mov rp=r15 +(p8) br.call.sptk.many b6=b6 + br.cond.sptk ia32_trace_syscall + +non_ia32_syscall: + alloc r15=ar.pfs,0,0,2,0 + mov out0=r14 // interrupt # + add out1=16,sp // pointer to pt_regs + ;; // avoid WAW on CFM + br.call.sptk.many rp=ia32_bad_interrupt +.ret1: movl r15=ia64_leave_kernel + ;; + mov rp=r15 + br.ret.sptk.many rp +END(dispatch_to_ia32_handler) +#endif /* CONFIG_IA32_SUPPORT */ + +#ifdef CONFIG_XEN + .section .text,"ax" +GLOBAL_ENTRY(xen_event_callback) + mov r31=pr // prepare to save predicates + ;; + SAVE_MIN_WITH_COVER // uses r31; defines r2 and r3 + ;; + movl r3=XSI_PSR_IC + mov r14=1 + ;; + st4 [r3]=r14 + ;; + adds r3=8,r2 // set up second base pointer for SAVE_REST + srlz.i // ensure everybody knows psr.ic is back on + ;; + SAVE_REST + ;; + alloc r14=ar.pfs,0,0,1,0 // must be first in an insn group + add out0=16,sp // pass pointer to pt_regs as first arg + ;; + srlz.d // make sure we see the effect of cr.ivr + movl r14=ia64_leave_kernel + ;; + mov rp=r14 + br.call.sptk.many b6=evtchn_do_upcall +END(xen_event_callback) +#endif diff --git a/arch/ia64/xen/xenminstate.h b/arch/ia64/xen/xenminstate.h new file mode 100644 index 000000000..f92fc6eda --- /dev/null +++ b/arch/ia64/xen/xenminstate.h @@ -0,0 +1,368 @@ + +#include <asm/cache.h> + +#ifdef CONFIG_XEN +#include "../kernel/entry.h" +#else +#include "entry.h" +#endif + +/* + * For ivt.s we want to access the stack virtually so we don't have to disable translation + * on interrupts. + * + * On entry: + * r1: pointer to current task (ar.k6) + */ +#define MINSTATE_START_SAVE_MIN_VIRT \ +(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \ + ;; \ +(pUStk) mov.m r24=ar.rnat; \ +(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of RBS */ \ +(pKStk) mov r1=sp; /* get sp */ \ + ;; \ +(pUStk) lfetch.fault.excl.nt1 [r22]; \ +(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \ +(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \ + ;; \ +(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \ +(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \ + ;; \ +(pUStk) mov r18=ar.bsp; \ +(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \ + +#define MINSTATE_END_SAVE_MIN_VIRT \ + bsw.1; /* switch back to bank 1 (must be last in insn group) */ \ + ;; + +/* + * For mca_asm.S we want to access the stack physically since the state is saved before we + * go virtual and don't want to destroy the iip or ipsr. + */ +#define MINSTATE_START_SAVE_MIN_PHYS \ +(pKStk) mov r3=IA64_KR(PER_CPU_DATA);; \ +(pKStk) addl r3=THIS_CPU(ia64_mca_data),r3;; \ +(pKStk) ld8 r3 = [r3];; \ +(pKStk) addl r3=IA64_MCA_CPU_INIT_STACK_OFFSET,r3;; \ +(pKStk) addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3; \ +(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \ +(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of register backing store */ \ + ;; \ +(pUStk) mov r24=ar.rnat; \ +(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1; /* compute base of memory stack */ \ +(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \ +(pUStk) dep r22=-1,r22,61,3; /* compute kernel virtual addr of RBS */ \ + ;; \ +(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \ +(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \ + ;; \ +(pUStk) mov r18=ar.bsp; \ +(pUStk) mov ar.rsc=0x3; /* set eager mode, pl 0, little-endian, loadrs=0 */ \ + +#define MINSTATE_END_SAVE_MIN_PHYS \ + dep r12=-1,r12,61,3; /* make sp a kernel virtual address */ \ + ;; + +#ifdef MINSTATE_VIRT +# define MINSTATE_GET_CURRENT(reg) mov reg=IA64_KR(CURRENT) +# define MINSTATE_START_SAVE_MIN MINSTATE_START_SAVE_MIN_VIRT +# define MINSTATE_END_SAVE_MIN MINSTATE_END_SAVE_MIN_VIRT +#endif + +#ifdef MINSTATE_PHYS +# define MINSTATE_GET_CURRENT(reg) mov reg=IA64_KR(CURRENT);; tpa reg=reg +# define MINSTATE_START_SAVE_MIN MINSTATE_START_SAVE_MIN_PHYS +# define MINSTATE_END_SAVE_MIN MINSTATE_END_SAVE_MIN_PHYS +#endif + +/* + * DO_SAVE_MIN switches to the kernel stacks (if necessary) and saves + * the minimum state necessary that allows us to turn psr.ic back + * on. + * + * Assumed state upon entry: + * psr.ic: off + * r31: contains saved predicates (pr) + * + * Upon exit, the state is as follows: + * psr.ic: off + * r2 = points to &pt_regs.r16 + * r8 = contents of ar.ccv + * r9 = contents of ar.csd + * r10 = contents of ar.ssd + * r11 = FPSR_DEFAULT + * r12 = kernel sp (kernel virtual address) + * r13 = points to current task_struct (kernel virtual address) + * p15 = TRUE if psr.i is set in cr.ipsr + * predicate registers (other than p2, p3, and p15), b6, r3, r14, r15: + * preserved + * CONFIG_XEN note: p6/p7 are not preserved + * + * Note that psr.ic is NOT turned on by this macro. This is so that + * we can pass interruption state as arguments to a handler. + */ +#ifdef CONFIG_XEN +#define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA) \ + MINSTATE_GET_CURRENT(r16); /* M (or M;;I) */ \ + mov r27=ar.rsc; /* M */ \ + mov r20=r1; /* A */ \ + mov r25=ar.unat; /* M */ \ + /* mov r29=cr.ipsr; /* M */ \ + movl r29=XSI_IPSR;; \ + ld8 r29=[r29];; \ + mov r26=ar.pfs; /* I */ \ + /* mov r28=cr.iip; /* M */ \ + movl r28=XSI_IIP;; \ + ld8 r28=[r28];; \ + mov r21=ar.fpsr; /* M */ \ + COVER; /* B;; (or nothing) */ \ + ;; \ + adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16; \ + ;; \ + ld1 r17=[r16]; /* load current->thread.on_ustack flag */ \ + st1 [r16]=r0; /* clear current->thread.on_ustack flag */ \ + adds r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 \ + /* switch from user to kernel RBS: */ \ + ;; \ + invala; /* M */ \ + /* SAVE_IFS; /* see xen special handling below */ \ + cmp.eq pKStk,pUStk=r0,r17; /* are we in kernel mode already? */ \ + ;; \ + MINSTATE_START_SAVE_MIN \ + adds r17=2*L1_CACHE_BYTES,r1; /* really: biggest cache-line size */ \ + adds r16=PT(CR_IPSR),r1; \ + ;; \ + lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES; \ + st8 [r16]=r29; /* save cr.ipsr */ \ + ;; \ + lfetch.fault.excl.nt1 [r17]; \ + tbit.nz p15,p0=r29,IA64_PSR_I_BIT; \ + mov r29=b0 \ + ;; \ + adds r16=PT(R8),r1; /* initialize first base pointer */ \ + adds r17=PT(R9),r1; /* initialize second base pointer */ \ +(pKStk) mov r18=r0; /* make sure r18 isn't NaT */ \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r8,16; \ +.mem.offset 8,0; st8.spill [r17]=r9,16; \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r10,24; \ +.mem.offset 8,0; st8.spill [r17]=r11,24; \ + ;; \ + /* xen special handling for possibly lazy cover */ \ + movl r8=XSI_INCOMPL_REGFR; \ + ;; \ + ld4 r30=[r8]; \ + ;; \ + /* set XSI_INCOMPL_REGFR 0 */ \ + st4 [r8]=r0; \ + cmp.eq p6,p7=r30,r0; \ + ;; /* not sure if this stop bit is necessary */ \ +(p6) adds r8=XSI_PRECOVER_IFS-XSI_INCOMPL_REGFR,r8; \ +(p7) adds r8=XSI_IFS-XSI_INCOMPL_REGFR,r8; \ + ;; \ + ld8 r30=[r8]; \ + ;; \ + st8 [r16]=r28,16; /* save cr.iip */ \ + st8 [r17]=r30,16; /* save cr.ifs */ \ +(pUStk) sub r18=r18,r22; /* r18=RSE.ndirty*8 */ \ + mov r8=ar.ccv; \ + mov r9=ar.csd; \ + mov r10=ar.ssd; \ + movl r11=FPSR_DEFAULT; /* L-unit */ \ + ;; \ + st8 [r16]=r25,16; /* save ar.unat */ \ + st8 [r17]=r26,16; /* save ar.pfs */ \ + shl r18=r18,16; /* compute ar.rsc to be used for "loadrs" */ \ + ;; \ + st8 [r16]=r27,16; /* save ar.rsc */ \ +(pUStk) st8 [r17]=r24,16; /* save ar.rnat */ \ +(pKStk) adds r17=16,r17; /* skip over ar_rnat field */ \ + ;; /* avoid RAW on r16 & r17 */ \ +(pUStk) st8 [r16]=r23,16; /* save ar.bspstore */ \ + st8 [r17]=r31,16; /* save predicates */ \ +(pKStk) adds r16=16,r16; /* skip over ar_bspstore field */ \ + ;; \ + st8 [r16]=r29,16; /* save b0 */ \ + st8 [r17]=r18,16; /* save ar.rsc value for "loadrs" */ \ + cmp.eq pNonSys,pSys=r0,r0 /* initialize pSys=0, pNonSys=1 */ \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r20,16; /* save original r1 */ \ +.mem.offset 8,0; st8.spill [r17]=r12,16; \ + adds r12=-16,r1; /* switch to kernel memory stack (with 16 bytes of scratch) */ \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r13,16; \ +.mem.offset 8,0; st8.spill [r17]=r21,16; /* save ar.fpsr */ \ + mov r13=IA64_KR(CURRENT); /* establish `current' */ \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r15,16; \ +.mem.offset 8,0; st8.spill [r17]=r14,16; \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r2,16; \ +.mem.offset 8,0; st8.spill [r17]=r3,16; \ + ;; \ + EXTRA; \ + mov r2=b0; br.call.sptk b0=xen_bsw1;; mov b0=r2; \ + adds r2=IA64_PT_REGS_R16_OFFSET,r1; \ + ;; \ + movl r1=__gp; /* establish kernel global pointer */ \ + ;; \ + /* MINSTATE_END_SAVE_MIN */ +#else +#define DO_SAVE_MIN(COVER,SAVE_IFS,EXTRA) \ + MINSTATE_GET_CURRENT(r16); /* M (or M;;I) */ \ + mov r27=ar.rsc; /* M */ \ + mov r20=r1; /* A */ \ + mov r25=ar.unat; /* M */ \ + mov r29=cr.ipsr; /* M */ \ + mov r26=ar.pfs; /* I */ \ + mov r28=cr.iip; /* M */ \ + mov r21=ar.fpsr; /* M */ \ + COVER; /* B;; (or nothing) */ \ + ;; \ + adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16; \ + ;; \ + ld1 r17=[r16]; /* load current->thread.on_ustack flag */ \ + st1 [r16]=r0; /* clear current->thread.on_ustack flag */ \ + adds r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 \ + /* switch from user to kernel RBS: */ \ + ;; \ + invala; /* M */ \ + SAVE_IFS; \ + cmp.eq pKStk,pUStk=r0,r17; /* are we in kernel mode already? */ \ + ;; \ + MINSTATE_START_SAVE_MIN \ + adds r17=2*L1_CACHE_BYTES,r1; /* really: biggest cache-line size */ \ + adds r16=PT(CR_IPSR),r1; \ + ;; \ + lfetch.fault.excl.nt1 [r17],L1_CACHE_BYTES; \ + st8 [r16]=r29; /* save cr.ipsr */ \ + ;; \ + lfetch.fault.excl.nt1 [r17]; \ + tbit.nz p15,p0=r29,IA64_PSR_I_BIT; \ + mov r29=b0 \ + ;; \ + adds r16=PT(R8),r1; /* initialize first base pointer */ \ + adds r17=PT(R9),r1; /* initialize second base pointer */ \ +(pKStk) mov r18=r0; /* make sure r18 isn't NaT */ \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r8,16; \ +.mem.offset 8,0; st8.spill [r17]=r9,16; \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r10,24; \ +.mem.offset 8,0; st8.spill [r17]=r11,24; \ + ;; \ + st8 [r16]=r28,16; /* save cr.iip */ \ + st8 [r17]=r30,16; /* save cr.ifs */ \ +(pUStk) sub r18=r18,r22; /* r18=RSE.ndirty*8 */ \ + mov r8=ar.ccv; \ + mov r9=ar.csd; \ + mov r10=ar.ssd; \ + movl r11=FPSR_DEFAULT; /* L-unit */ \ + ;; \ + st8 [r16]=r25,16; /* save ar.unat */ \ + st8 [r17]=r26,16; /* save ar.pfs */ \ + shl r18=r18,16; /* compute ar.rsc to be used for "loadrs" */ \ + ;; \ + st8 [r16]=r27,16; /* save ar.rsc */ \ +(pUStk) st8 [r17]=r24,16; /* save ar.rnat */ \ +(pKStk) adds r17=16,r17; /* skip over ar_rnat field */ \ + ;; /* avoid RAW on r16 & r17 */ \ +(pUStk) st8 [r16]=r23,16; /* save ar.bspstore */ \ + st8 [r17]=r31,16; /* save predicates */ \ +(pKStk) adds r16=16,r16; /* skip over ar_bspstore field */ \ + ;; \ + st8 [r16]=r29,16; /* save b0 */ \ + st8 [r17]=r18,16; /* save ar.rsc value for "loadrs" */ \ + cmp.eq pNonSys,pSys=r0,r0 /* initialize pSys=0, pNonSys=1 */ \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r20,16; /* save original r1 */ \ +.mem.offset 8,0; st8.spill [r17]=r12,16; \ + adds r12=-16,r1; /* switch to kernel memory stack (with 16 bytes of scratch) */ \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r13,16; \ +.mem.offset 8,0; st8.spill [r17]=r21,16; /* save ar.fpsr */ \ + mov r13=IA64_KR(CURRENT); /* establish `current' */ \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r15,16; \ +.mem.offset 8,0; st8.spill [r17]=r14,16; \ + ;; \ +.mem.offset 0,0; st8.spill [r16]=r2,16; \ +.mem.offset 8,0; st8.spill [r17]=r3,16; \ + adds r2=IA64_PT_REGS_R16_OFFSET,r1; \ + ;; \ + EXTRA; \ + movl r1=__gp; /* establish kernel global pointer */ \ + ;; \ + MINSTATE_END_SAVE_MIN +#endif + +/* + * SAVE_REST saves the remainder of pt_regs (with psr.ic on). + * + * Assumed state upon entry: + * psr.ic: on + * r2: points to &pt_regs.r16 + * r3: points to &pt_regs.r17 + * r8: contents of ar.ccv + * r9: contents of ar.csd + * r10: contents of ar.ssd + * r11: FPSR_DEFAULT + * + * Registers r14 and r15 are guaranteed not to be touched by SAVE_REST. + */ +#define SAVE_REST \ +.mem.offset 0,0; st8.spill [r2]=r16,16; \ +.mem.offset 8,0; st8.spill [r3]=r17,16; \ + ;; \ +.mem.offset 0,0; st8.spill [r2]=r18,16; \ +.mem.offset 8,0; st8.spill [r3]=r19,16; \ + ;; \ +.mem.offset 0,0; st8.spill [r2]=r20,16; \ +.mem.offset 8,0; st8.spill [r3]=r21,16; \ + mov r18=b6; \ + ;; \ +.mem.offset 0,0; st8.spill [r2]=r22,16; \ +.mem.offset 8,0; st8.spill [r3]=r23,16; \ + mov r19=b7; \ + ;; \ +.mem.offset 0,0; st8.spill [r2]=r24,16; \ +.mem.offset 8,0; st8.spill [r3]=r25,16; \ + ;; \ +.mem.offset 0,0; st8.spill [r2]=r26,16; \ +.mem.offset 8,0; st8.spill [r3]=r27,16; \ + ;; \ +.mem.offset 0,0; st8.spill [r2]=r28,16; \ +.mem.offset 8,0; st8.spill [r3]=r29,16; \ + ;; \ +.mem.offset 0,0; st8.spill [r2]=r30,16; \ +.mem.offset 8,0; st8.spill [r3]=r31,32; \ + ;; \ + mov ar.fpsr=r11; /* M-unit */ \ + st8 [r2]=r8,8; /* ar.ccv */ \ + adds r24=PT(B6)-PT(F7),r3; \ + ;; \ + stf.spill [r2]=f6,32; \ + stf.spill [r3]=f7,32; \ + ;; \ + stf.spill [r2]=f8,32; \ + stf.spill [r3]=f9,32; \ + ;; \ + stf.spill [r2]=f10; \ + stf.spill [r3]=f11; \ + adds r25=PT(B7)-PT(F11),r3; \ + ;; \ + st8 [r24]=r18,16; /* b6 */ \ + st8 [r25]=r19,16; /* b7 */ \ + ;; \ + st8 [r24]=r9; /* ar.csd */ \ + st8 [r25]=r10; /* ar.ssd */ \ + ;; + +#define SAVE_MIN_WITH_COVER DO_SAVE_MIN(cover, mov r30=cr.ifs,) +#define SAVE_MIN_WITH_COVER_R19 DO_SAVE_MIN(cover, mov r30=cr.ifs, mov r15=r19) +#ifdef CONFIG_XEN +#define SAVE_MIN break 0;; /* FIXME: non-cover version only for ia32 support? */ +#else +#define SAVE_MIN DO_SAVE_MIN( , mov r30=r0, ) +#endif diff --git a/arch/ia64/xen/xenpal.S b/arch/ia64/xen/xenpal.S new file mode 100644 index 000000000..5f9681e49 --- /dev/null +++ b/arch/ia64/xen/xenpal.S @@ -0,0 +1,76 @@ +/* + * ia64/xen/xenpal.S + * + * Alternate PAL routines for Xen. Heavily leveraged from + * ia64/kernel/pal.S + * + * Copyright (C) 2005 Hewlett-Packard Co + * Dan Magenheimer <dan.magenheimer@.hp.com> + */ + +#include <asm/asmmacro.h> +#include <asm/processor.h> + +GLOBAL_ENTRY(xen_pal_call_static) + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5) + alloc loc1 = ar.pfs,5,5,0,0 +#ifdef CONFIG_XEN + movl r22=running_on_xen;; + ld4 r22=[r22];; + cmp.eq p7,p0=r22,r0 +(p7) br.cond.spnt.many __ia64_pal_call_static;; +#endif + movl loc2 = pal_entry_point +1: { + mov r28 = in0 + mov r29 = in1 + mov r8 = ip + } + ;; + ld8 loc2 = [loc2] // loc2 <- entry point + tbit.nz p6,p7 = in4, 0 + adds r8 = 1f-1b,r8 + mov loc4=ar.rsc // save RSE configuration + ;; + mov ar.rsc=0 // put RSE in enforced lazy, LE mode + mov loc3 = psr + mov loc0 = rp + .body + mov r30 = in2 + +#ifdef CONFIG_XEN + // this is low priority for paravirtualization, but is called + // from the idle loop so confuses privop counting + movl r31=XSI_PSR_IC + ;; +(p6) st4 [r31]=r0 + ;; +(p7) adds r31=XSI_PSR_I_ADDR_OFS-XSI_PSR_IC_OFS,r31 +(p7) mov r22=1 + ;; +(p7) ld8 r31=[r31] + ;; +(p7) st1 [r31]=r22 + ;; + mov r31 = in3 + mov b7 = loc2 + ;; +#else +(p6) rsm psr.i | psr.ic + mov r31 = in3 + mov b7 = loc2 + +(p7) rsm psr.i + ;; +(p6) srlz.i +#endif + mov rp = r8 + br.cond.sptk.many b7 +1: mov psr.l = loc3 + mov ar.rsc = loc4 // restore RSE configuration + mov ar.pfs = loc1 + mov rp = loc0 + ;; + srlz.d // seralize restoration of psr.l + br.ret.sptk.many b0 +END(xen_pal_call_static) diff --git a/arch/ia64/xen/xensetup.S b/arch/ia64/xen/xensetup.S new file mode 100644 index 000000000..a2beb1cfd --- /dev/null +++ b/arch/ia64/xen/xensetup.S @@ -0,0 +1,54 @@ +/* + * Support routines for Xen + * + * Copyright (C) 2005 Dan Magenheimer <dan.magenheimer@hp.com> + */ + +#include <asm/processor.h> +#include <asm/asmmacro.h> + +#define isBP p3 // are we the Bootstrap Processor? + + .text +GLOBAL_ENTRY(early_xen_setup) + mov r8=ar.rsc // Initialized in head.S +(isBP) movl r9=running_on_xen;; + extr.u r8=r8,2,2;; // Extract pl fields + cmp.eq p7,p0=r8,r0 // p7: !running on xen + mov r8=1 // booleanize. +(p7) br.ret.sptk.many rp;; +(isBP) st4 [r9]=r8 + movl r10=xen_ivt;; + + mov cr.iva=r10 + +#if XSI_BASE != 0xf100000000000000UL + /* Backward compatibility. */ +(isBP) mov r2=0x600 +(isBP) movl r28=XSI_BASE;; +(isBP) break 0x1000;; +#endif + + br.ret.sptk.many rp + ;; +END(early_xen_setup) + +#include <xen/interface/xen.h> + +/* Stub for suspend. + Just force the stacked registers to be written in memory. */ +GLOBAL_ENTRY(HYPERVISOR_suspend) + alloc r20=ar.pfs,0,0,0,0 + mov r14=2 + mov r15=r12 + ;; + /* We don't want to deal with RSE. */ + flushrs + mov r2=__HYPERVISOR_sched_op + st4 [r12]=r14 + ;; + break 0x1000 + ;; + mov ar.pfs=r20 + br.ret.sptk.many b0 +END(HYPERVISOR_suspend) diff --git a/arch/m68k/kernel/dma.c b/arch/m68k/kernel/dma.c new file mode 100644 index 000000000..fc449f8b2 --- /dev/null +++ b/arch/m68k/kernel/dma.c @@ -0,0 +1,129 @@ +/* + * 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. + */ + +#undef DEBUG + +#include <linux/dma-mapping.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/vmalloc.h> + +#include <asm/pgalloc.h> +#include <asm/scatterlist.h> + +void *dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *handle, int flag) +{ + struct page *page, **map; + pgprot_t pgprot; + void *addr; + int i, order; + + pr_debug("dma_alloc_coherent: %d,%x\n", size, flag); + + size = PAGE_ALIGN(size); + order = get_order(size); + + page = alloc_pages(flag, order); + if (!page) + return NULL; + + *handle = page_to_phys(page); + map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA); + if (!map) { + __free_pages(page, order); + return NULL; + } + split_page(page, order); + + order = 1 << order; + size >>= PAGE_SHIFT; + map[0] = page; + for (i = 1; i < size; i++) + map[i] = page + i; + for (; i < order; i++) + __free_page(page + i); + pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY); + if (CPU_IS_040_OR_060) + pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S; + else + pgprot_val(pgprot) |= _PAGE_NOCACHE030; + addr = vmap(map, size, flag, pgprot); + kfree(map); + + return addr; +} +EXPORT_SYMBOL(dma_alloc_coherent); + +void dma_free_coherent(struct device *dev, size_t size, + void *addr, dma_addr_t handle) +{ + pr_debug("dma_free_coherent: %p, %x\n", addr, handle); + vfree(addr); +} +EXPORT_SYMBOL(dma_free_coherent); + +inline void dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size, + enum dma_data_direction dir) +{ + switch (dir) { + case DMA_TO_DEVICE: + cache_push(handle, size); + break; + case DMA_FROM_DEVICE: + cache_clear(handle, size); + break; + default: + if (printk_ratelimit()) + printk("dma_sync_single_for_device: unsupported dir %u\n", dir); + break; + } +} +EXPORT_SYMBOL(dma_sync_single_for_device); + +void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction dir) +{ + int i; + + for (i = 0; i < nents; sg++, i++) + dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir); +} +EXPORT_SYMBOL(dma_sync_sg_for_device); + +dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size, + enum dma_data_direction dir) +{ + dma_addr_t handle = virt_to_bus(addr); + + dma_sync_single_for_device(dev, handle, size, dir); + return handle; +} +EXPORT_SYMBOL(dma_map_single); + +dma_addr_t dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction dir) +{ + dma_addr_t handle = page_to_phys(page) + offset; + + dma_sync_single_for_device(dev, handle, size, dir); + return handle; +} +EXPORT_SYMBOL(dma_map_page); + +int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction dir) +{ + int i; + + for (i = 0; i < nents; sg++, i++) { + sg->dma_address = page_to_phys(sg->page) + sg->offset; + dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir); + } + return nents; +} +EXPORT_SYMBOL(dma_map_sg); diff --git a/arch/m68k/lib/uaccess.c b/arch/m68k/lib/uaccess.c new file mode 100644 index 000000000..1bc188c0d --- /dev/null +++ b/arch/m68k/lib/uaccess.c @@ -0,0 +1,222 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include <linux/module.h> +#include <asm/uaccess.h> + +unsigned long __generic_copy_from_user(void *to, const void __user *from, + unsigned long n) +{ + unsigned long tmp, res; + + asm volatile ("\n" + " tst.l %0\n" + " jeq 2f\n" + "1: moves.l (%1)+,%3\n" + " move.l %3,(%2)+\n" + " subq.l #1,%0\n" + " jne 1b\n" + "2: btst #1,%5\n" + " jeq 4f\n" + "3: moves.w (%1)+,%3\n" + " move.w %3,(%2)+\n" + "4: btst #0,%5\n" + " jeq 6f\n" + "5: moves.b (%1)+,%3\n" + " move.b %3,(%2)+\n" + "6:\n" + " .section .fixup,\"ax\"\n" + " .even\n" + "10: move.l %0,%3\n" + "7: clr.l (%2)+\n" + " subq.l #1,%3\n" + " jne 7b\n" + " lsl.l #2,%0\n" + " btst #1,%5\n" + " jeq 8f\n" + "30: clr.w (%2)+\n" + " addq.l #2,%0\n" + "8: btst #0,%5\n" + " jeq 6b\n" + "50: clr.b (%2)+\n" + " addq.l #1,%0\n" + " jra 6b\n" + " .previous\n" + "\n" + " .section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,10b\n" + " .long 3b,30b\n" + " .long 5b,50b\n" + " .previous" + : "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp) + : "0" (n / 4), "d" (n & 3)); + + return res; +} +EXPORT_SYMBOL(__generic_copy_from_user); + +unsigned long __generic_copy_to_user(void __user *to, const void *from, + unsigned long n) +{ + unsigned long tmp, res; + + asm volatile ("\n" + " tst.l %0\n" + " jeq 4f\n" + "1: move.l (%1)+,%3\n" + "2: moves.l %3,(%2)+\n" + "3: subq.l #1,%0\n" + " jne 1b\n" + "4: btst #1,%5\n" + " jeq 6f\n" + " move.w (%1)+,%3\n" + "5: moves.w %3,(%2)+\n" + "6: btst #0,%5\n" + " jeq 8f\n" + " move.b (%1)+,%3\n" + "7: moves.b %3,(%2)+\n" + "8:\n" + " .section .fixup,\"ax\"\n" + " .even\n" + "20: lsl.l #2,%0\n" + "50: add.l %5,%0\n" + " jra 7b\n" + " .previous\n" + "\n" + " .section __ex_table,\"a\"\n" + " .align 4\n" + " .long 2b,20b\n" + " .long 3b,20b\n" + " .long 5b,50b\n" + " .long 6b,50b\n" + " .long 7b,50b\n" + " .long 8b,50b\n" + " .previous" + : "=d" (res), "+a" (from), "+a" (to), "=&r" (tmp) + : "0" (n / 4), "d" (n & 3)); + + return res; +} +EXPORT_SYMBOL(__generic_copy_to_user); + +/* + * Copy a null terminated string from userspace. + */ +long strncpy_from_user(char *dst, const char __user *src, long count) +{ + long res; + char c; + + if (count <= 0) + return count; + + asm volatile ("\n" + "1: moves.b (%2)+,%4\n" + " move.b %4,(%1)+\n" + " jeq 2f\n" + " subq.l #1,%3\n" + " jne 1b\n" + "2: sub.l %3,%0\n" + "3:\n" + " .section .fixup,\"ax\"\n" + " .even\n" + "10: move.l %5,%0\n" + " jra 3b\n" + " .previous\n" + "\n" + " .section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,10b\n" + " .previous" + : "=d" (res), "+a" (dst), "+a" (src), "+r" (count), "=&d" (c) + : "i" (-EFAULT), "0" (count)); + + return res; +} +EXPORT_SYMBOL(strncpy_from_user); + +/* + * Return the size of a string (including the ending 0) + * + * Return 0 on exception, a value greater than N if too long + */ +long strnlen_user(const char __user *src, long n) +{ + char c; + long res; + + asm volatile ("\n" + "1: subq.l #1,%1\n" + " jmi 3f\n" + "2: moves.b (%0)+,%2\n" + " tst.b %2\n" + " jne 1b\n" + " jra 4f\n" + "\n" + "3: addq.l #1,%0\n" + "4: sub.l %4,%0\n" + "5:\n" + " .section .fixup,\"ax\"\n" + " .even\n" + "20: sub.l %0,%0\n" + " jra 5b\n" + " .previous\n" + "\n" + " .section __ex_table,\"a\"\n" + " .align 4\n" + " .long 2b,20b\n" + " .previous\n" + : "=&a" (res), "+d" (n), "=&d" (c) + : "0" (src), "r" (src)); + + return res; +} +EXPORT_SYMBOL(strnlen_user); + +/* + * Zero Userspace + */ + +unsigned long clear_user(void __user *to, unsigned long n) +{ + unsigned long res; + + asm volatile ("\n" + " tst.l %0\n" + " jeq 3f\n" + "1: moves.l %2,(%1)+\n" + "2: subq.l #1,%0\n" + " jne 1b\n" + "3: btst #1,%4\n" + " jeq 5f\n" + "4: moves.w %2,(%1)+\n" + "5: btst #0,%4\n" + " jeq 7f\n" + "6: moves.b %2,(%1)\n" + "7:\n" + " .section .fixup,\"ax\"\n" + " .even\n" + "10: lsl.l #2,%0\n" + "40: add.l %4,%0\n" + " jra 7b\n" + " .previous\n" + "\n" + " .section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,10b\n" + " .long 2b,10b\n" + " .long 4b,40b\n" + " .long 5b,40b\n" + " .long 6b,40b\n" + " .long 7b,40b\n" + " .previous" + : "=d" (res), "+a" (to) + : "r" (0), "0" (n / 4), "d" (n & 3)); + + return res; +} +EXPORT_SYMBOL(clear_user); diff --git a/arch/m68knommu/platform/532x/Makefile b/arch/m68knommu/platform/532x/Makefile new file mode 100644 index 000000000..12301803b --- /dev/null +++ b/arch/m68knommu/platform/532x/Makefile @@ -0,0 +1,20 @@ +# +# Makefile for the m68knommu linux kernel. +# + +# +# If you want to play with the HW breakpoints then you will +# need to add define this, which will give you a stack backtrace +# on the console port whenever a DBG interrupt occurs. You have to +# set up you HW breakpoints to trigger a DBG interrupt: +# +# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT +# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT +# + +ifdef CONFIG_FULLDEBUG +AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 +endif + +#obj-y := config.o usb-mcf532x.o spi-mcf532x.o +obj-y := config.o diff --git a/arch/m68knommu/platform/532x/config.c b/arch/m68knommu/platform/532x/config.c new file mode 100644 index 000000000..c7d6ad513 --- /dev/null +++ b/arch/m68knommu/platform/532x/config.c @@ -0,0 +1,485 @@ +/***************************************************************************/ + +/* + * linux/arch/m68knommu/platform/532x/config.c + * + * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) + * Copyright (C) 2000, Lineo (www.lineo.com) + * Yaroslav Vinogradov yaroslav.vinogradov@freescale.com + * Copyright Freescale Semiconductor, Inc 2006 + * Copyright (c) 2006, emlix, Sebastian Hess <sh@emlix.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +/***************************************************************************/ + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/param.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <asm/irq.h> +#include <asm/dma.h> +#include <asm/traps.h> +#include <asm/machdep.h> +#include <asm/coldfire.h> +#include <asm/mcftimer.h> +#include <asm/mcfsim.h> +#include <asm/mcfdma.h> +#include <asm/mcfwdebug.h> + +/***************************************************************************/ + +void coldfire_tick(void); +void coldfire_timer_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); +unsigned long coldfire_timer_offset(void); +void coldfire_trap_init(void); +void coldfire_reset(void); + +extern unsigned int mcf_timervector; +extern unsigned int mcf_profilevector; +extern unsigned int mcf_timerlevel; + +/***************************************************************************/ + +/* + * DMA channel base address table. + */ +unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { }; +unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; + +/***************************************************************************/ + +void mcf_settimericr(unsigned int timer, unsigned int level) +{ + volatile unsigned char *icrp; + unsigned int icr; + unsigned char irq; + + if (timer <= 2) { + switch (timer) { + case 2: irq = 33; icr = MCFSIM_ICR_TIMER2; break; + default: irq = 32; icr = MCFSIM_ICR_TIMER1; break; + } + + icrp = (volatile unsigned char *) (MCF_MBAR + icr); + *icrp = level; + mcf_enable_irq0(irq); + } +} + +/***************************************************************************/ + +int mcf_timerirqpending(int timer) +{ + unsigned int imr = 0; + + switch (timer) { + case 1: imr = 0x1; break; + case 2: imr = 0x2; break; + default: break; + } + return (mcf_getiprh() & imr); +} + +/***************************************************************************/ + +void config_BSP(char *commandp, int size) +{ + mcf_setimr(MCFSIM_IMR_MASKALL); + +#if defined(CONFIG_BOOTPARAM) + strncpy(commandp, CONFIG_BOOTPARAM_STRING, size); + commandp[size-1] = 0; +#else + /* Copy command line from FLASH to local buffer... */ + memcpy(commandp, (char *) 0x4000, 4); + if(strncmp(commandp, "kcl ", 4) == 0){ + memcpy(commandp, (char *) 0x4004, size); + commandp[size-1] = 0; + } else { + memset(commandp, 0, size); + } +#endif + + mcf_timervector = 64+32; + mcf_profilevector = 64+33; + mach_sched_init = coldfire_timer_init; + mach_tick = coldfire_tick; + mach_gettimeoffset = coldfire_timer_offset; + mach_trap_init = coldfire_trap_init; + mach_reset = coldfire_reset; + +#ifdef MCF_BDM_DISABLE + /* + * Disable the BDM clocking. This also turns off most of the rest of + * the BDM device. This is good for EMC reasons. This option is not + * incompatible with the memory protection option. + */ + wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK); +#endif +} + +/***************************************************************************/ +/* Board initialization */ + +/********************************************************************/ +/* + * PLL min/max specifications + */ +#define MAX_FVCO 500000 /* KHz */ +#define MAX_FSYS 80000 /* KHz */ +#define MIN_FSYS 58333 /* KHz */ +#define FREF 16000 /* KHz */ + + +#define MAX_MFD 135 /* Multiplier */ +#define MIN_MFD 88 /* Multiplier */ +#define BUSDIV 6 /* Divider */ + +/* + * Low Power Divider specifications + */ +#define MIN_LPD (1 << 0) /* Divider (not encoded) */ +#define MAX_LPD (1 << 15) /* Divider (not encoded) */ +#define DEFAULT_LPD (1 << 1) /* Divider (not encoded) */ + +#define SYS_CLK_KHZ 80000 +#define SYSTEM_PERIOD 12.5 +/* + * SDRAM Timing Parameters + */ +#define SDRAM_BL 8 /* # of beats in a burst */ +#define SDRAM_TWR 2 /* in clocks */ +#define SDRAM_CASL 2.5 /* CASL in clocks */ +#define SDRAM_TRCD 2 /* in clocks */ +#define SDRAM_TRP 2 /* in clocks */ +#define SDRAM_TRFC 7 /* in clocks */ +#define SDRAM_TREFI 7800 /* in ns */ + +#define EXT_SRAM_ADDRESS (0xC0000000) +#define FLASH_ADDRESS (0x00000000) +#define SDRAM_ADDRESS (0x40000000) + +#define NAND_FLASH_ADDRESS (0xD0000000) + +int sys_clk_khz = 0; +int sys_clk_mhz = 0; + +void wtm_init(void); +void scm_init(void); +void gpio_init(void); +void fbcs_init(void); +void sdramc_init(void); +int clock_pll (int fsys, int flags); +int clock_limp (int); +int clock_exit_limp (void); +int get_sys_clock (void); + +asmlinkage void __init sysinit(void) +{ + sys_clk_khz = clock_pll(0, 0); + sys_clk_mhz = sys_clk_khz/1000; + + wtm_init(); + scm_init(); + gpio_init(); + fbcs_init(); + sdramc_init(); +} + +void wtm_init(void) +{ + /* Disable watchdog timer */ + MCF_WTM_WCR = 0; +} + +#define MCF_SCM_BCR_GBW (0x00000100) +#define MCF_SCM_BCR_GBR (0x00000200) + +void scm_init(void) +{ + /* All masters are trusted */ + MCF_SCM_MPR = 0x77777777; + + /* Allow supervisor/user, read/write, and trusted/untrusted + access to all slaves */ + MCF_SCM_PACRA = 0; + MCF_SCM_PACRB = 0; + MCF_SCM_PACRC = 0; + MCF_SCM_PACRD = 0; + MCF_SCM_PACRE = 0; + MCF_SCM_PACRF = 0; + + /* Enable bursts */ + MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW); +} + + +void fbcs_init(void) +{ + MCF_GPIO_PAR_CS = 0x0000003E; + + /* Latch chip select */ + MCF_FBCS1_CSAR = 0x10080000; + + MCF_FBCS1_CSCR = 0x002A3780; + MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V); + + /* Initialize latch to drive signals to inactive states */ + *((u16 *)(0x10080000)) = 0xFFFF; + + /* External SRAM */ + MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS; + MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16 + | MCF_FBCS_CSCR_AA + | MCF_FBCS_CSCR_SBM + | MCF_FBCS_CSCR_WS(1)); + MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K + | MCF_FBCS_CSMR_V); + + /* Boot Flash connected to FBCS0 */ + MCF_FBCS0_CSAR = FLASH_ADDRESS; + MCF_FBCS0_CSCR = (MCF_FBCS_CSCR_PS_16 + | MCF_FBCS_CSCR_BEM + | MCF_FBCS_CSCR_AA + | MCF_FBCS_CSCR_SBM + | MCF_FBCS_CSCR_WS(7)); + MCF_FBCS0_CSMR = (MCF_FBCS_CSMR_BAM_32M + | MCF_FBCS_CSMR_V); +} + +void sdramc_init(void) +{ + /* + * Check to see if the SDRAM has already been initialized + * by a run control tool + */ + if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) { + /* SDRAM chip select initialization */ + + /* Initialize SDRAM chip select */ + MCF_SDRAMC_SDCS0 = (0 + | MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS) + | MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE)); + + /* + * Basic configuration and initialization + */ + MCF_SDRAMC_SDCFG1 = (0 + | MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5 )) + | MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1) + | MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2)) + | MCF_SDRAMC_SDCFG1_ACT2RW((int)((SDRAM_TRCD ) + 0.5)) + | MCF_SDRAMC_SDCFG1_PRE2ACT((int)((SDRAM_TRP ) + 0.5)) + | MCF_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC) ) + 0.5)) + | MCF_SDRAMC_SDCFG1_WTLAT(3)); + MCF_SDRAMC_SDCFG2 = (0 + | MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL/2 + 1) + | MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL/2 + SDRAM_TWR) + | MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL+SDRAM_BL/2-1.0)+0.5)) + | MCF_SDRAMC_SDCFG2_BL(SDRAM_BL-1)); + + + /* + * Precharge and enable write to SDMR + */ + MCF_SDRAMC_SDCR = (0 + | MCF_SDRAMC_SDCR_MODE_EN + | MCF_SDRAMC_SDCR_CKE + | MCF_SDRAMC_SDCR_DDR + | MCF_SDRAMC_SDCR_MUX(1) + | MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5)) + | MCF_SDRAMC_SDCR_PS_16 + | MCF_SDRAMC_SDCR_IPALL); + + /* + * Write extended mode register + */ + MCF_SDRAMC_SDMR = (0 + | MCF_SDRAMC_SDMR_BNKAD_LEMR + | MCF_SDRAMC_SDMR_AD(0x0) + | MCF_SDRAMC_SDMR_CMD); + + /* + * Write mode register and reset DLL + */ + MCF_SDRAMC_SDMR = (0 + | MCF_SDRAMC_SDMR_BNKAD_LMR + | MCF_SDRAMC_SDMR_AD(0x163) + | MCF_SDRAMC_SDMR_CMD); + + /* + * Execute a PALL command + */ + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL; + + /* + * Perform two REF cycles + */ + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF; + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF; + + /* + * Write mode register and clear reset DLL + */ + MCF_SDRAMC_SDMR = (0 + | MCF_SDRAMC_SDMR_BNKAD_LMR + | MCF_SDRAMC_SDMR_AD(0x063) + | MCF_SDRAMC_SDMR_CMD); + + /* + * Enable auto refresh and lock SDMR + */ + MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN; + MCF_SDRAMC_SDCR |= (0 + | MCF_SDRAMC_SDCR_REF + | MCF_SDRAMC_SDCR_DQS_OE(0xC)); + } +} + +void gpio_init(void) +{ + /* Enable UART0 pins */ + MCF_GPIO_PAR_UART = ( 0 + | MCF_GPIO_PAR_UART_PAR_URXD0 + | MCF_GPIO_PAR_UART_PAR_UTXD0); + + /* Initialize TIN3 as a GPIO output to enable the write + half of the latch */ + MCF_GPIO_PAR_TIMER = 0x00; + MCF_GPIO_PDDR_TIMER = 0x08; + MCF_GPIO_PCLRR_TIMER = 0x0; + +} + +int clock_pll(int fsys, int flags) +{ + int fref, temp, fout, mfd; + u32 i; + + fref = FREF; + + if (fsys == 0) { + /* Return current PLL output */ + mfd = MCF_PLL_PFDR; + + return (fref * mfd / (BUSDIV * 4)); + } + + /* Check bounds of requested system clock */ + if (fsys > MAX_FSYS) + fsys = MAX_FSYS; + if (fsys < MIN_FSYS) + fsys = MIN_FSYS; + + /* Multiplying by 100 when calculating the temp value, + and then dividing by 100 to calculate the mfd allows + for exact values without needing to include floating + point libraries. */ + temp = 100 * fsys / fref; + mfd = 4 * BUSDIV * temp / 100; + + /* Determine the output frequency for selected values */ + fout = (fref * mfd / (BUSDIV * 4)); + + /* + * Check to see if the SDRAM has already been initialized. + * If it has then the SDRAM needs to be put into self refresh + * mode before reprogramming the PLL. + */ + if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF) + /* Put SDRAM into self refresh mode */ + MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE; + + /* + * Initialize the PLL to generate the new system clock frequency. + * The device must be put into LIMP mode to reprogram the PLL. + */ + + /* Enter LIMP mode */ + clock_limp(DEFAULT_LPD); + + /* Reprogram PLL for desired fsys */ + MCF_PLL_PODR = (0 + | MCF_PLL_PODR_CPUDIV(BUSDIV/3) + | MCF_PLL_PODR_BUSDIV(BUSDIV)); + + MCF_PLL_PFDR = mfd; + + /* Exit LIMP mode */ + clock_exit_limp(); + + /* + * Return the SDRAM to normal operation if it is in use. + */ + if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF) + /* Exit self refresh mode */ + MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE; + + /* Errata - workaround for SDRAM opeartion after exiting LIMP mode */ + MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH; + + /* wait for DQS logic to relock */ + for (i = 0; i < 0x200; i++) + ; + + return fout; +} + +int clock_limp(int div) +{ + u32 temp; + + /* Check bounds of divider */ + if (div < MIN_LPD) + div = MIN_LPD; + if (div > MAX_LPD) + div = MAX_LPD; + + /* Save of the current value of the SSIDIV so we don't + overwrite the value*/ + temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF)); + + /* Apply the divider to the system clock */ + MCF_CCM_CDR = ( 0 + | MCF_CCM_CDR_LPDIV(div) + | MCF_CCM_CDR_SSIDIV(temp)); + + MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP; + + return (FREF/(3*(1 << div))); +} + +int clock_exit_limp(void) +{ + int fout; + + /* Exit LIMP mode */ + MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP); + + /* Wait for PLL to lock */ + while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK)) + ; + + fout = get_sys_clock(); + + return fout; +} + +int get_sys_clock(void) +{ + int divider; + + /* Test to see if device is in LIMP mode */ + if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) { + divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF); + return (FREF/(2 << divider)); + } + else + return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4)); +} diff --git a/arch/m68knommu/platform/68328/romvec.S b/arch/m68knommu/platform/68328/romvec.S new file mode 100644 index 000000000..31084466e --- /dev/null +++ b/arch/m68knommu/platform/68328/romvec.S @@ -0,0 +1,35 @@ +/* + * linux/arch/m68knommu/platform/68328/romvec.S + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Copyright 1996 Roman Zippel + * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com> + * Copyright 2006 Greg Ungerer <gerg@snapgear.com> + */ + +.global _start +.global _buserr +.global trap +.global system_call + +.section .romvec + +e_vectors: +.long CONFIG_RAMBASE+CONFIG_RAMSIZE-4, _start, buserr, trap +.long trap, trap, trap, trap +.long trap, trap, trap, trap +.long trap, trap, trap, trap +.long trap, trap, trap, trap +.long trap, trap, trap, trap +.long trap, trap, trap, trap +.long trap, trap, trap, trap +/* TRAP #0-15 */ +.long system_call, trap, trap, trap +.long trap, trap, trap, trap +.long trap, trap, trap, trap +.long trap, trap, trap, trap +.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + diff --git a/arch/mips/basler/excite/Makefile b/arch/mips/basler/excite/Makefile new file mode 100644 index 000000000..519142c2e --- /dev/null +++ b/arch/mips/basler/excite/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for Basler eXcite +# + +obj-$(CONFIG_BASLER_EXCITE) += excite_irq.o excite_prom.o excite_setup.o \ + excite_device.o excite_procfs.o + +obj-$(CONFIG_KGDB) += excite_dbg_io.o +obj-m += excite_iodev.o diff --git a/arch/mips/basler/excite/excite_dbg_io.c b/arch/mips/basler/excite/excite_dbg_io.c new file mode 100644 index 000000000..c04505afa --- /dev/null +++ b/arch/mips/basler/excite/excite_dbg_io.c @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2004 by Basler Vision Technologies AG + * Author: Thomas Koeller <thomas.koeller@baslerweb.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/linkage.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <asm/gdb-stub.h> +#include <asm/rm9k-ocd.h> +#include <excite.h> + +#if defined(CONFIG_SERIAL_8250) && CONFIG_SERIAL_8250_NR_UARTS > 1 +#error Debug port used by serial driver +#endif + +#define UART_CLK 25000000 +#define BASE_BAUD (UART_CLK / 16) +#define REGISTER_BASE_0 0x0208UL +#define REGISTER_BASE_1 0x0238UL + +#define REGISTER_BASE_DBG REGISTER_BASE_1 + +#define CPRR 0x0004 +#define UACFG 0x0200 +#define UAINTS 0x0204 +#define UARBR (REGISTER_BASE_DBG + 0x0000) +#define UATHR (REGISTER_BASE_DBG + 0x0004) +#define UADLL (REGISTER_BASE_DBG + 0x0008) +#define UAIER (REGISTER_BASE_DBG + 0x000c) +#define UADLH (REGISTER_BASE_DBG + 0x0010) +#define UAIIR (REGISTER_BASE_DBG + 0x0014) +#define UAFCR (REGISTER_BASE_DBG + 0x0018) +#define UALCR (REGISTER_BASE_DBG + 0x001c) +#define UAMCR (REGISTER_BASE_DBG + 0x0020) +#define UALSR (REGISTER_BASE_DBG + 0x0024) +#define UAMSR (REGISTER_BASE_DBG + 0x0028) +#define UASCR (REGISTER_BASE_DBG + 0x002c) + +#define PARITY_NONE 0 +#define PARITY_ODD 0x08 +#define PARITY_EVEN 0x18 +#define PARITY_MARK 0x28 +#define PARITY_SPACE 0x38 + +#define DATA_5BIT 0x0 +#define DATA_6BIT 0x1 +#define DATA_7BIT 0x2 +#define DATA_8BIT 0x3 + +#define STOP_1BIT 0x0 +#define STOP_2BIT 0x4 + +#define BAUD_DBG 57600 +#define PARITY_DBG PARITY_NONE +#define DATA_DBG DATA_8BIT +#define STOP_DBG STOP_1BIT + +/* Initialize the serial port for KGDB debugging */ +void __init excite_kgdb_init(void) +{ + const u32 divisor = BASE_BAUD / BAUD_DBG; + + /* Take the UART out of reset */ + titan_writel(0x00ff1cff, CPRR); + titan_writel(0x00000000, UACFG); + titan_writel(0x00000002, UACFG); + + titan_writel(0x0, UALCR); + titan_writel(0x0, UAIER); + + /* Disable FIFOs */ + titan_writel(0x00, UAFCR); + + titan_writel(0x80, UALCR); + titan_writel(divisor & 0xff, UADLL); + titan_writel((divisor & 0xff00) >> 8, UADLH); + titan_writel(0x0, UALCR); + + titan_writel(DATA_DBG | PARITY_DBG | STOP_DBG, UALCR); + + /* Enable receiver interrupt */ + titan_readl(UARBR); + titan_writel(0x1, UAIER); +} + +int getDebugChar(void) +{ + while (!(titan_readl(UALSR) & 0x1)); + return titan_readl(UARBR); +} + +int putDebugChar(int data) +{ + while (!(titan_readl(UALSR) & 0x20)); + titan_writel(data, UATHR); + return 1; +} + +/* KGDB interrupt handler */ +asmlinkage void excite_kgdb_inthdl(struct pt_regs *regs) +{ + if (unlikely( + ((titan_readl(UAIIR) & 0x7) == 4) + && ((titan_readl(UARBR) & 0xff) == 0x3))) + set_async_breakpoint(®s->cp0_epc); +} diff --git a/arch/mips/basler/excite/excite_device.c b/arch/mips/basler/excite/excite_device.c new file mode 100644 index 000000000..bbb4ea43d --- /dev/null +++ b/arch/mips/basler/excite/excite_device.c @@ -0,0 +1,403 @@ +/* + * Copyright (C) 2004 by Basler Vision Technologies AG + * Author: Thomas Koeller <thomas.koeller@baslerweb.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/ioport.h> +#include <linux/err.h> +#include <linux/jiffies.h> +#include <linux/sched.h> +#include <asm/types.h> +#include <asm/rm9k-ocd.h> + +#include <excite.h> +#include <rm9k_eth.h> +#include <rm9k_wdt.h> +#include <rm9k_xicap.h> +#include <excite_nandflash.h> + +#include "excite_iodev.h" + +#define RM9K_GE_UNIT 0 +#define XICAP_UNIT 0 +#define NAND_UNIT 0 + +#define DLL_TIMEOUT 3 /* seconds */ + + +#define RINIT(__start__, __end__, __name__, __parent__) { \ + .name = __name__ "_0", \ + .start = (__start__), \ + .end = (__end__), \ + .flags = 0, \ + .parent = (__parent__) \ +} + +#define RINIT_IRQ(__irq__, __name__) { \ + .name = __name__ "_0", \ + .start = (__irq__), \ + .end = (__irq__), \ + .flags = IORESOURCE_IRQ, \ + .parent = NULL \ +} + + + +enum { + slice_xicap, + slice_eth +}; + + + +static struct resource + excite_ctr_resource = { + .name = "GPI counters", + .start = 0, + .end = 5, + .flags = 0, + .parent = NULL, + .sibling = NULL, + .child = NULL + }, + excite_gpislice_resource = { + .name = "GPI slices", + .start = 0, + .end = 1, + .flags = 0, + .parent = NULL, + .sibling = NULL, + .child = NULL + }, + excite_mdio_channel_resource = { + .name = "MDIO channels", + .start = 0, + .end = 1, + .flags = 0, + .parent = NULL, + .sibling = NULL, + .child = NULL + }, + excite_fifomem_resource = { + .name = "FIFO memory", + .start = 0, + .end = 767, + .flags = 0, + .parent = NULL, + .sibling = NULL, + .child = NULL + }, + excite_scram_resource = { + .name = "Scratch RAM", + .start = EXCITE_PHYS_SCRAM, + .end = EXCITE_PHYS_SCRAM + EXCITE_SIZE_SCRAM - 1, + .flags = IORESOURCE_MEM, + .parent = NULL, + .sibling = NULL, + .child = NULL + }, + excite_fpga_resource = { + .name = "System FPGA", + .start = EXCITE_PHYS_FPGA, + .end = EXCITE_PHYS_FPGA + EXCITE_SIZE_FPGA - 1, + .flags = IORESOURCE_MEM, + .parent = NULL, + .sibling = NULL, + .child = NULL + }, + excite_nand_resource = { + .name = "NAND flash control", + .start = EXCITE_PHYS_NAND, + .end = EXCITE_PHYS_NAND + EXCITE_SIZE_NAND - 1, + .flags = IORESOURCE_MEM, + .parent = NULL, + .sibling = NULL, + .child = NULL + }, + excite_titan_resource = { + .name = "TITAN registers", + .start = EXCITE_PHYS_TITAN, + .end = EXCITE_PHYS_TITAN + EXCITE_SIZE_TITAN - 1, + .flags = IORESOURCE_MEM, + .parent = NULL, + .sibling = NULL, + .child = NULL + }; + + + +static void adjust_resources(struct resource *res, unsigned int n) +{ + struct resource *p; + const unsigned long mask = IORESOURCE_IO | IORESOURCE_MEM + | IORESOURCE_IRQ | IORESOURCE_DMA; + + for (p = res; p < res + n; p++) { + const struct resource * const parent = p->parent; + if (parent) { + p->start += parent->start; + p->end += parent->start; + p->flags = parent->flags & mask; + } + } +} + + + +#if defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE) +static struct resource xicap_rsrc[] = { + RINIT(0x4840, 0x486f, XICAP_RESOURCE_FIFO_RX, &excite_titan_resource), + RINIT(0x4940, 0x494b, XICAP_RESOURCE_FIFO_TX, &excite_titan_resource), + RINIT(0x5040, 0x5127, XICAP_RESOURCE_XDMA, &excite_titan_resource), + RINIT(0x1000, 0x112f, XICAP_RESOURCE_PKTPROC, &excite_titan_resource), + RINIT(0x1100, 0x110f, XICAP_RESOURCE_PKT_STREAM, &excite_fpga_resource), + RINIT(0x0800, 0x0bff, XICAP_RESOURCE_DMADESC, &excite_scram_resource), + RINIT(slice_xicap, slice_xicap, XICAP_RESOURCE_GPI_SLICE, &excite_gpislice_resource), + RINIT(0x0100, 0x02ff, XICAP_RESOURCE_FIFO_BLK, &excite_fifomem_resource), + RINIT_IRQ(TITAN_IRQ, XICAP_RESOURCE_IRQ) +}; + +static struct platform_device xicap_pdev = { + .name = XICAP_NAME, + .id = XICAP_UNIT, + .num_resources = ARRAY_SIZE(xicap_rsrc), + .resource = xicap_rsrc +}; + +/* + * Create a platform device for the GPI port that receives the + * image data from the embedded camera. + */ +static int __init xicap_devinit(void) +{ + unsigned long tend; + u32 reg; + int retval; + + adjust_resources(xicap_rsrc, ARRAY_SIZE(xicap_rsrc)); + + /* Power up the slice and configure it. */ + reg = titan_readl(CPTC1R); + reg &= ~(0x11100 << slice_xicap); + titan_writel(reg, CPTC1R); + + /* Enable slice & DLL. */ + reg= titan_readl(CPRR); + reg &= ~(0x00030003 << (slice_xicap * 2)); + titan_writel(reg, CPRR); + + /* Wait for DLLs to lock */ + tend = jiffies + DLL_TIMEOUT * HZ; + while (time_before(jiffies, tend)) { + if (!(~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4)))) + break; + yield(); + } + + if (~titan_readl(CPDSR) & (0x1 << (slice_xicap * 4))) { + printk(KERN_ERR "%s: DLL not locked after %u seconds\n", + xicap_pdev.name, DLL_TIMEOUT); + retval = -ETIME; + } else { + /* Register platform device */ + retval = platform_device_register(&xicap_pdev); + } + + return retval; +} + +device_initcall(xicap_devinit); +#endif /* defined(CONFIG_EXCITE_FCAP_GPI) || defined(CONFIG_EXCITE_FCAP_GPI_MODULE) */ + + + +#if defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE) +static struct resource wdt_rsrc[] = { + RINIT(0, 0, WDT_RESOURCE_COUNTER, &excite_ctr_resource), + RINIT(0x0084, 0x008f, WDT_RESOURCE_REGS, &excite_titan_resource), + RINIT_IRQ(TITAN_IRQ, WDT_RESOURCE_IRQ) +}; + +static struct platform_device wdt_pdev = { + .name = WDT_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(wdt_rsrc), + .resource = wdt_rsrc +}; + +/* + * Create a platform device for the GPI port that receives the + * image data from the embedded camera. + */ +static int __init wdt_devinit(void) +{ + adjust_resources(wdt_rsrc, ARRAY_SIZE(wdt_rsrc)); + return platform_device_register(&wdt_pdev); +} + +device_initcall(wdt_devinit); +#endif /* defined(CONFIG_WDT_RM9K_GPI) || defined(CONFIG_WDT_RM9K_GPI_MODULE) */ + + + +static struct resource excite_nandflash_rsrc[] = { + RINIT(0x2000, 0x201f, EXCITE_NANDFLASH_RESOURCE_REGS, &excite_nand_resource) +}; + +static struct platform_device excite_nandflash_pdev = { + .name = "excite_nand", + .id = NAND_UNIT, + .num_resources = ARRAY_SIZE(excite_nandflash_rsrc), + .resource = excite_nandflash_rsrc +}; + +/* + * Create a platform device for the access to the nand-flash + * port + */ +static int __init excite_nandflash_devinit(void) +{ + adjust_resources(excite_nandflash_rsrc, ARRAY_SIZE(excite_nandflash_rsrc)); + + /* nothing to be done here */ + + /* Register platform device */ + return platform_device_register(&excite_nandflash_pdev); +} + +device_initcall(excite_nandflash_devinit); + + + +static struct resource iodev_rsrc[] = { + RINIT_IRQ(FPGA1_IRQ, IODEV_RESOURCE_IRQ) +}; + +static struct platform_device io_pdev = { + .name = IODEV_NAME, + .id = -1, + .num_resources = ARRAY_SIZE(iodev_rsrc), + .resource = iodev_rsrc +}; + +/* + * Create a platform device for the external I/O ports. + */ +static int __init io_devinit(void) +{ + adjust_resources(iodev_rsrc, ARRAY_SIZE(iodev_rsrc)); + return platform_device_register(&io_pdev); +} + +device_initcall(io_devinit); + + + + +#if defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE) +static struct resource rm9k_ge_rsrc[] = { + RINIT(0x2200, 0x27ff, RM9K_GE_RESOURCE_MAC, &excite_titan_resource), + RINIT(0x1800, 0x1fff, RM9K_GE_RESOURCE_MSTAT, &excite_titan_resource), + RINIT(0x2000, 0x212f, RM9K_GE_RESOURCE_PKTPROC, &excite_titan_resource), + RINIT(0x5140, 0x5227, RM9K_GE_RESOURCE_XDMA, &excite_titan_resource), + RINIT(0x4870, 0x489f, RM9K_GE_RESOURCE_FIFO_RX, &excite_titan_resource), + RINIT(0x494c, 0x4957, RM9K_GE_RESOURCE_FIFO_TX, &excite_titan_resource), + RINIT(0x0000, 0x007f, RM9K_GE_RESOURCE_FIFOMEM_RX, &excite_fifomem_resource), + RINIT(0x0080, 0x00ff, RM9K_GE_RESOURCE_FIFOMEM_TX, &excite_fifomem_resource), + RINIT(0x0180, 0x019f, RM9K_GE_RESOURCE_PHY, &excite_titan_resource), + RINIT(0x0000, 0x03ff, RM9K_GE_RESOURCE_DMADESC_RX, &excite_scram_resource), + RINIT(0x0400, 0x07ff, RM9K_GE_RESOURCE_DMADESC_TX, &excite_scram_resource), + RINIT(slice_eth, slice_eth, RM9K_GE_RESOURCE_GPI_SLICE, &excite_gpislice_resource), + RINIT(0, 0, RM9K_GE_RESOURCE_MDIO_CHANNEL, &excite_mdio_channel_resource), + RINIT_IRQ(TITAN_IRQ, RM9K_GE_RESOURCE_IRQ_MAIN), + RINIT_IRQ(PHY_IRQ, RM9K_GE_RESOURCE_IRQ_PHY) +}; + +static struct platform_device rm9k_ge_pdev = { + .name = RM9K_GE_NAME, + .id = RM9K_GE_UNIT, + .num_resources = ARRAY_SIZE(rm9k_ge_rsrc), + .resource = rm9k_ge_rsrc +}; + + + +/* + * Create a platform device for the Ethernet port. + */ +static int __init rm9k_ge_devinit(void) +{ + u32 reg; + + adjust_resources(rm9k_ge_rsrc, ARRAY_SIZE(rm9k_ge_rsrc)); + + /* Power up the slice and configure it. */ + reg = titan_readl(CPTC1R); + reg &= ~(0x11000 << slice_eth); + reg |= 0x100 << slice_eth; + titan_writel(reg, CPTC1R); + + /* Take the MAC out of reset, reset the DLLs. */ + reg = titan_readl(CPRR); + reg &= ~(0x00030000 << (slice_eth * 2)); + reg |= 0x3 << (slice_eth * 2); + titan_writel(reg, CPRR); + + return platform_device_register(&rm9k_ge_pdev); +} + +device_initcall(rm9k_ge_devinit); +#endif /* defined(CONFIG_RM9K_GE) || defined(CONFIG_RM9K_GE_MODULE) */ + + + +static int __init excite_setup_devs(void) +{ + int res; + u32 reg; + + /* Enable xdma and fifo interrupts */ + reg = titan_readl(0x0050); + titan_writel(reg | 0x18000000, 0x0050); + + res = request_resource(&iomem_resource, &excite_titan_resource); + if (res) + return res; + res = request_resource(&iomem_resource, &excite_scram_resource); + if (res) + return res; + res = request_resource(&iomem_resource, &excite_fpga_resource); + if (res) + return res; + res = request_resource(&iomem_resource, &excite_nand_resource); + if (res) + return res; + excite_fpga_resource.flags = excite_fpga_resource.parent->flags & + ( IORESOURCE_IO | IORESOURCE_MEM + | IORESOURCE_IRQ | IORESOURCE_DMA); + excite_nand_resource.flags = excite_nand_resource.parent->flags & + ( IORESOURCE_IO | IORESOURCE_MEM + | IORESOURCE_IRQ | IORESOURCE_DMA); + + return 0; +} + +arch_initcall(excite_setup_devs); + diff --git a/arch/mips/basler/excite/excite_flashtest.c b/arch/mips/basler/excite/excite_flashtest.c new file mode 100644 index 000000000..f0024a8e3 --- /dev/null +++ b/arch/mips/basler/excite/excite_flashtest.c @@ -0,0 +1,294 @@ +/* +* Copyright (C) 2005 by Basler Vision Technologies AG +* Author: Thies Moeller <thies.moeller@baslerweb.com> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <linux/module.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/ioport.h> +#include <linux/device.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/kernel.h> + +#include <excite.h> + +#include <asm/io.h> + +#include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/nand_ecc.h> +#include <linux/mtd/partitions.h> +#include <asm/rm9k-ocd.h> // for ocd_write +#include <linux/workqueue.h> // for queue + +#include "excite_nandflash.h" +#include "nandflash.h" + +#define PFX "excite flashtest: " +typedef void __iomem *io_reg_t; + +#define io_readb(__a__) __raw_readb((__a__)) +#define io_writeb(__v__, __a__) __raw_writeb((__v__), (__a__)) + + + +static inline const struct resource *excite_nandflash_get_resource( + struct platform_device *d, unsigned long flags, const char *basename) +{ + const char fmt[] = "%s_%u"; + char buf[80]; + + if (unlikely(snprintf(buf, sizeof buf, fmt, basename, d->id) >= sizeof buf)) + return NULL; + + return platform_get_resource_byname(d, flags, buf); +} + +static inline io_reg_t +excite_nandflash_map_regs(struct platform_device *d, const char *basename) +{ + void *result = NULL; + const struct resource *const r = + excite_nandflash_get_resource(d, IORESOURCE_MEM, basename); + if (r) + result = ioremap_nocache(r->start, r->end + 1 - r->start); + return result; +} + +/* controller and mtd information */ + +struct excite_nandflash_drvdata { + struct mtd_info board_mtd; + struct nand_chip board_chip; + io_reg_t regs; +}; + + +/* command and control functions */ +static void excite_nandflash_hwcontrol(struct mtd_info *mtd, int cmd) +{ + struct nand_chip *this = mtd->priv; + io_reg_t regs = container_of(mtd,struct excite_nandflash_drvdata,board_mtd)->regs; + + switch (cmd) { + /* Select the command latch */ + case NAND_CTL_SETCLE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_CMD; + break; + /* Deselect the command latch */ + case NAND_CTL_CLRCLE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_DATA; + break; + /* Select the address latch */ + case NAND_CTL_SETALE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_ADDR; + break; + /* Deselect the address latch */ + case NAND_CTL_CLRALE: this->IO_ADDR_W = regs + EXCITE_NANDFLASH_DATA; + break; + /* Select the chip -- not used */ + case NAND_CTL_SETNCE: + break; + /* Deselect the chip -- not used */ + case NAND_CTL_CLRNCE: + break; + } + + this->IO_ADDR_R = this->IO_ADDR_W; +} + +/* excite_nandflash_devready() + * + * returns 0 if the nand is busy, 1 if it is ready + */ +static int excite_nandflash_devready(struct mtd_info *mtd) +{ + struct excite_nandflash_drvdata *drvdata = + container_of(mtd, struct excite_nandflash_drvdata, board_mtd); + + return io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS); +} + +/* device management functions */ + +/* excite_nandflash_remove + * + * called by device layer to remove the driver + * the binding to the mtd and all allocated + * resources are released + */ +static int excite_nandflash_remove(struct device *dev) +{ + struct excite_nandflash_drvdata *this = dev_get_drvdata(dev); + + pr_info(PFX "remove"); + + dev_set_drvdata(dev, NULL); + + if (this == NULL) { + pr_debug(PFX "call remove without private data!!"); + return 0; + } + + + /* free the common resources */ + if (this->regs != NULL) { + iounmap(this->regs); + this->regs = NULL; + } + + kfree(this); + + return 0; +} + +static int elapsed; + +void my_workqueue_handler(void *arg) +{ + elapsed = 1; +} + +DECLARE_WORK(sigElapsed, my_workqueue_handler, 0); + + +/* excite_nandflash_probe + * + * called by device layer when it finds a device matching + * one our driver can handled. This code checks to see if + * it can allocate all necessary resources then calls the + * nand layer to look for devices +*/ +static int excite_nandflash_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + struct excite_nandflash_drvdata *drvdata; /* private driver data */ + struct nand_chip *board_chip; /* private flash chip data */ + struct mtd_info *board_mtd; /* mtd info for this board */ + + int err = 0; + int count = 0; + struct timeval tv,endtv; + unsigned int dt; + + pr_info(PFX "probe dev: (%p)\n", dev); + + pr_info(PFX "adjust LB timing\n"); + ocd_writel(0x00000330, LDP2); + + drvdata = kmalloc(sizeof(*drvdata), GFP_KERNEL); + if (unlikely(!drvdata)) { + printk(KERN_ERR PFX "no memory for drvdata\n"); + err = -ENOMEM; + goto mem_error; + } + + /* Initialize structures */ + memset(drvdata, 0, sizeof(*drvdata)); + + /* bind private data into driver */ + dev_set_drvdata(dev, drvdata); + + /* allocate and map the resource */ + drvdata->regs = + excite_nandflash_map_regs(pdev, EXCITE_NANDFLASH_RESOURCE_REGS); + + if (unlikely(!drvdata->regs)) { + printk(KERN_ERR PFX "cannot reserve register region\n"); + err = -ENXIO; + goto io_error; + } + + /* initialise our chip */ + board_chip = &drvdata->board_chip; + + board_chip->IO_ADDR_R = drvdata->regs + EXCITE_NANDFLASH_DATA; + board_chip->IO_ADDR_W = drvdata->regs + EXCITE_NANDFLASH_DATA; + + board_chip->hwcontrol = excite_nandflash_hwcontrol; + board_chip->dev_ready = excite_nandflash_devready; + + board_chip->chip_delay = 25; + #if 0 + /* TODO: speedup the initial scan */ + board_chip->options = NAND_USE_FLASH_BBT; + #endif + board_chip->eccmode = NAND_ECC_SOFT; + + /* link chip to mtd */ + board_mtd = &drvdata->board_mtd; + board_mtd->priv = board_chip; + + + pr_info(PFX "FlashTest\n"); + elapsed = 0; +/* schedule_delayed_work(&sigElapsed, 1*HZ); + while (!elapsed) { + io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS); + count++; + } + pr_info(PFX "reads in 1 sec --> %d\n",count); +*/ + do_gettimeofday(&tv); + for (count = 0 ; count < 1000000; count ++) { + io_readb(drvdata->regs + EXCITE_NANDFLASH_STATUS); + } + do_gettimeofday(&endtv); + dt = (endtv.tv_sec - tv.tv_sec) * 1000000 + endtv.tv_usec - tv.tv_usec; + pr_info(PFX "%8d us timeval\n",dt); + pr_info(PFX "EndFlashTest\n"); + +/* return with error to unload everything +*/ +io_error: + iounmap(drvdata->regs); + +mem_error: + kfree(drvdata); + + if (err == 0) + err = -EINVAL; + return err; +} + +static struct device_driver excite_nandflash_driver = { + .name = "excite_nand", + .bus = &platform_bus_type, + .probe = excite_nandflash_probe, + .remove = excite_nandflash_remove, +}; + +static int __init excite_nandflash_init(void) +{ + pr_info(PFX "register Driver (Rev: $Revision:$)\n"); + return driver_register(&excite_nandflash_driver); +} + +static void __exit excite_nandflash_exit(void) +{ + driver_unregister(&excite_nandflash_driver); + pr_info(PFX "Driver unregistered"); +} + +module_init(excite_nandflash_init); +module_exit(excite_nandflash_exit); + +MODULE_AUTHOR("Thies Moeller <thies.moeller@baslerweb.com>"); +MODULE_DESCRIPTION("Basler eXcite NAND-Flash driver"); +MODULE_LICENSE("GPL"); diff --git a/arch/mips/basler/excite/excite_fpga.h b/arch/mips/basler/excite/excite_fpga.h new file mode 100644 index 000000000..38fcda703 --- /dev/null +++ b/arch/mips/basler/excite/excite_fpga.h @@ -0,0 +1,80 @@ +#ifndef EXCITE_FPGA_H_INCLUDED +#define EXCITE_FPGA_H_INCLUDED + + +/** + * Adress alignment of the individual FPGA bytes. + * The address arrangement of the individual bytes of the FPGA is two + * byte aligned at the embedded MK2 platform. + */ +#ifdef EXCITE_CCI_FPGA_MK2 +typedef unsigned char excite_cci_fpga_align_t __attribute__ ((aligned(2))); +#else +typedef unsigned char excite_cci_fpga_align_t; +#endif + + +/** + * Size of Dual Ported RAM. + */ +#define EXCITE_DPR_SIZE 263 + + +/** + * Size of Reserved Status Fields in Dual Ported RAM. + */ +#define EXCITE_DPR_STATUS_SIZE 7 + + + +/** + * FPGA. + * Hardware register layout of the FPGA interface. The FPGA must accessed + * byte wise solely. + * @see EXCITE_CCI_DPR_MK2 + */ +typedef struct excite_fpga { + + /** + * Dual Ported RAM. + */ + excite_cci_fpga_align_t dpr[EXCITE_DPR_SIZE]; + + /** + * Status. + */ + excite_cci_fpga_align_t status[EXCITE_DPR_STATUS_SIZE]; + +#ifdef EXCITE_CCI_FPGA_MK2 + /** + * RM9000 Interrupt. + * Write access initiates interrupt at the RM9000 (MIPS) processor of the eXcite. + */ + excite_cci_fpga_align_t rm9k_int; +#else + /** + * MK2 Interrupt. + * Write access initiates interrupt at the ARM processor of the MK2. + */ + excite_cci_fpga_align_t mk2_int; + + excite_cci_fpga_align_t gap[0x1000-0x10f]; + + /** + * IRQ Source/Acknowledge. + */ + excite_cci_fpga_align_t rm9k_irq_src; + + /** + * IRQ Mask. + * Set bits enable the related interrupt. + */ + excite_cci_fpga_align_t rm9k_irq_mask; +#endif + + +} excite_fpga; + + + +#endif /* ndef EXCITE_FPGA_H_INCLUDED */ diff --git a/arch/mips/basler/excite/excite_iodev.c b/arch/mips/basler/excite/excite_iodev.c new file mode 100644 index 000000000..10bbb8cfb --- /dev/null +++ b/arch/mips/basler/excite/excite_iodev.c @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2005 by Basler Vision Technologies AG + * Author: Thomas Koeller <thomas.koeller@baslerweb.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/compiler.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/wait.h> +#include <linux/poll.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/miscdevice.h> + +#include "excite_iodev.h" + + + +static const struct resource *iodev_get_resource(struct platform_device *, const char *, unsigned int); +static int __init iodev_probe(struct device *); +static int __exit iodev_remove(struct device *); +static int iodev_open(struct inode *, struct file *); +static int iodev_release(struct inode *, struct file *); +static ssize_t iodev_read(struct file *, char __user *, size_t s, loff_t *); +static unsigned int iodev_poll(struct file *, struct poll_table_struct *); +static irqreturn_t iodev_irqhdl(int, void *, struct pt_regs *); + + + +static const char iodev_name[] = "iodev"; +static unsigned int iodev_irq; +static DECLARE_WAIT_QUEUE_HEAD(wq); + + + +static struct file_operations fops = +{ + .owner = THIS_MODULE, + .open = iodev_open, + .release = iodev_release, + .read = iodev_read, + .poll = iodev_poll +}; + +static struct miscdevice miscdev = +{ + .minor = MISC_DYNAMIC_MINOR, + .name = iodev_name, + .fops = &fops +}; + +static struct device_driver iodev_driver = +{ + .name = (char *) iodev_name, + .bus = &platform_bus_type, + .owner = THIS_MODULE, + .probe = iodev_probe, + .remove = __exit_p(iodev_remove) +}; + + + +static const struct resource * +iodev_get_resource(struct platform_device *pdv, const char *name, + unsigned int type) +{ + char buf[80]; + if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf) + return NULL; + return platform_get_resource_byname(pdv, type, buf); +} + + + +/* No hotplugging on the platform bus - use __init */ +static int __init iodev_probe(struct device *dev) +{ + struct platform_device * const pdv = to_platform_device(dev); + const struct resource * const ri = + iodev_get_resource(pdv, IODEV_RESOURCE_IRQ, IORESOURCE_IRQ); + + if (unlikely(!ri)) + return -ENXIO; + + iodev_irq = ri->start; + return misc_register(&miscdev); +} + + + +static int __exit iodev_remove(struct device *dev) +{ + return misc_deregister(&miscdev); +} + + + +static int iodev_open(struct inode *i, struct file *f) +{ + return request_irq(iodev_irq, iodev_irqhdl, IRQF_DISABLED, + iodev_name, &miscdev); +} + + + +static int iodev_release(struct inode *i, struct file *f) +{ + free_irq(iodev_irq, &miscdev); + return 0; +} + + + + +static ssize_t +iodev_read(struct file *f, char __user *d, size_t s, loff_t *o) +{ + ssize_t ret; + DEFINE_WAIT(w); + + prepare_to_wait(&wq, &w, TASK_INTERRUPTIBLE); + if (!signal_pending(current)) + schedule(); + ret = signal_pending(current) ? -ERESTARTSYS : 0; + finish_wait(&wq, &w); + return ret; +} + + +static unsigned int iodev_poll(struct file *f, struct poll_table_struct *p) +{ + poll_wait(f, &wq, p); + return POLLOUT | POLLWRNORM; +} + + + + +static irqreturn_t iodev_irqhdl(int irq, void *ctxt, struct pt_regs *regs) +{ + wake_up(&wq); + return IRQ_HANDLED; +} + + + +static int __init iodev_init_module(void) +{ + return driver_register(&iodev_driver); +} + + + +static void __exit iodev_cleanup_module(void) +{ + driver_unregister(&iodev_driver); +} + +module_init(iodev_init_module); +module_exit(iodev_cleanup_module); + + + +MODULE_AUTHOR("Thomas Koeller <thomas.koeller@baslerweb.com>"); +MODULE_DESCRIPTION("Basler eXcite i/o interrupt handler"); +MODULE_VERSION("0.0"); +MODULE_LICENSE("GPL"); diff --git a/arch/mips/basler/excite/excite_iodev.h b/arch/mips/basler/excite/excite_iodev.h new file mode 100644 index 000000000..cbfbb5d2e --- /dev/null +++ b/arch/mips/basler/excite/excite_iodev.h @@ -0,0 +1,10 @@ +#ifndef __EXCITE_IODEV_H__ +#define __EXCITE_IODEV_H__ + +/* Device name */ +#define IODEV_NAME "iodev" + +/* Resource names */ +#define IODEV_RESOURCE_IRQ "excite_iodev_irq" + +#endif /* __EXCITE_IODEV_H__ */ diff --git a/arch/mips/basler/excite/excite_irq.c b/arch/mips/basler/excite/excite_irq.c new file mode 100644 index 000000000..511ad8730 --- /dev/null +++ b/arch/mips/basler/excite/excite_irq.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) by Basler Vision Technologies AG + * Author: Thomas Koeller <thomas.koeller@baslereb.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel_stat.h> +#include <linux/module.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/timex.h> +#include <linux/slab.h> +#include <linux/random.h> +#include <asm/bitops.h> +#include <asm/bootinfo.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/irq_cpu.h> +#include <asm/mipsregs.h> +#include <asm/system.h> +#include <asm/rm9k-ocd.h> + +#include <excite.h> + +extern asmlinkage void excite_handle_int(void); + +/* + * Initialize the interrupt handler + */ +void __init arch_init_irq(void) +{ + mips_cpu_irq_init(0); + rm7k_cpu_irq_init(8); + rm9k_cpu_irq_init(12); + +#ifdef CONFIG_KGDB + excite_kgdb_init(); +#endif +} + +asmlinkage void plat_irq_dispatch(struct pt_regs *regs) +{ + const u32 + interrupts = read_c0_cause() >> 8, + mask = ((read_c0_status() >> 8) & 0x000000ff) | + (read_c0_intcontrol() & 0x0000ff00), + pending = interrupts & mask; + u32 msgintflags, msgintmask, msgint; + + /* process timer interrupt */ + if (pending & (1 << TIMER_IRQ)) { + do_IRQ(TIMER_IRQ, regs); + return; + } + + /* Process PCI interrupts */ +#if USB_IRQ < 10 + msgintflags = ocd_readl(INTP0Status0 + (USB_MSGINT / 0x20 * 0x10)); + msgintmask = ocd_readl(INTP0Mask0 + (USB_MSGINT / 0x20 * 0x10)); + msgint = msgintflags & msgintmask & (0x1 << (USB_MSGINT % 0x20)); + if ((pending & (1 << USB_IRQ)) && msgint) { +#else + if (pending & (1 << USB_IRQ)) { +#endif + do_IRQ(USB_IRQ, regs); + return; + } + + /* Process TITAN interrupts */ + msgintflags = ocd_readl(INTP0Status0 + (TITAN_MSGINT / 0x20 * 0x10)); + msgintmask = ocd_readl(INTP0Mask0 + (TITAN_MSGINT / 0x20 * 0x10)); + msgint = msgintflags & msgintmask & (0x1 << (TITAN_MSGINT % 0x20)); + if ((pending & (1 << TITAN_IRQ)) && msgint) { + ocd_writel(msgint, INTP0Clear0 + (TITAN_MSGINT / 0x20 * 0x10)); +#if defined(CONFIG_KGDB) + excite_kgdb_inthdl(regs); +#endif + do_IRQ(TITAN_IRQ, regs); + return; + } + + /* Process FPGA line #0 interrupts */ + msgintflags = ocd_readl(INTP0Status0 + (FPGA0_MSGINT / 0x20 * 0x10)); + msgintmask = ocd_readl(INTP0Mask0 + (FPGA0_MSGINT / 0x20 * 0x10)); + msgint = msgintflags & msgintmask & (0x1 << (FPGA0_MSGINT % 0x20)); + if ((pending & (1 << FPGA0_IRQ)) && msgint) { + do_IRQ(FPGA0_IRQ, regs); + return; + } + + /* Process FPGA line #1 interrupts */ + msgintflags = ocd_readl(INTP0Status0 + (FPGA1_MSGINT / 0x20 * 0x10)); + msgintmask = ocd_readl(INTP0Mask0 + (FPGA1_MSGINT / 0x20 * 0x10)); + msgint = msgintflags & msgintmask & (0x1 << (FPGA1_MSGINT % 0x20)); + if ((pending & (1 << FPGA1_IRQ)) && msgint) { + do_IRQ(FPGA1_IRQ, regs); + return; + } + + /* Process PHY interrupts */ + msgintflags = ocd_readl(INTP0Status0 + (PHY_MSGINT / 0x20 * 0x10)); + msgintmask = ocd_readl(INTP0Mask0 + (PHY_MSGINT / 0x20 * 0x10)); + msgint = msgintflags & msgintmask & (0x1 << (PHY_MSGINT % 0x20)); + if ((pending & (1 << PHY_IRQ)) && msgint) { + do_IRQ(PHY_IRQ, regs); + return; + } + + /* Process spurious interrupts */ + spurious_interrupt(regs); +} diff --git a/arch/mips/basler/excite/excite_procfs.c b/arch/mips/basler/excite/excite_procfs.c new file mode 100644 index 000000000..9ee67a95f --- /dev/null +++ b/arch/mips/basler/excite/excite_procfs.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2004, 2005 by Basler Vision Technologies AG + * Author: Thomas Koeller <thomas.koeller@baslerweb.com> + * + * Procfs support for Basler eXcite + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/proc_fs.h> +#include <linux/stat.h> +#include <asm/page.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/rm9k-ocd.h> + +#include <excite.h> + +static int excite_get_unit_id(char *buf, char **addr, off_t offs, int size) +{ + const int len = snprintf(buf, PAGE_SIZE, "%06x", unit_id); + const int w = len - offs; + *addr = buf + offs; + return w < size ? w : size; +} + +static int +excite_bootrom_read(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + void __iomem * src; + + if (off >= EXCITE_SIZE_BOOTROM) { + *eof = 1; + return 0; + } + + if ((off + count) > EXCITE_SIZE_BOOTROM) + count = EXCITE_SIZE_BOOTROM - off; + + src = ioremap(EXCITE_PHYS_BOOTROM + off, count); + if (src) { + memcpy_fromio(page, src, count); + iounmap(src); + *start = page; + } else { + count = -ENOMEM; + } + + return count; +} + +void excite_procfs_init(void) +{ + /* Create & populate /proc/excite */ + struct proc_dir_entry * const pdir = proc_mkdir("excite", &proc_root); + if (pdir) { + struct proc_dir_entry * e; + + e = create_proc_info_entry("unit_id", S_IRUGO, pdir, + excite_get_unit_id); + if (e) e->size = 6; + + e = create_proc_read_entry("bootrom", S_IRUGO, pdir, + excite_bootrom_read, NULL); + if (e) e->size = EXCITE_SIZE_BOOTROM; + } +} diff --git a/arch/mips/basler/excite/excite_prom.c b/arch/mips/basler/excite/excite_prom.c new file mode 100644 index 000000000..6ecd512b9 --- /dev/null +++ b/arch/mips/basler/excite/excite_prom.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2004, 2005 by Thomas Koeller (thomas.koeller@baslerweb.com) + * Based on the PMC-Sierra Yosemite board support by Ralf Baechle and + * Manish Lachwani. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/delay.h> +#include <linux/smp.h> +#include <linux/module.h> +#include <asm/io.h> +#include <asm/pgtable.h> +#include <asm/processor.h> +#include <asm/reboot.h> +#include <asm/system.h> +#include <asm/bootinfo.h> +#include <asm/string.h> + +#include <excite.h> + +/* This struct is used by Redboot to pass arguments to the kernel */ +typedef struct +{ + char *name; + char *val; +} t_env_var; + +struct parmblock { + t_env_var memsize; + t_env_var modetty0; + t_env_var ethaddr; + t_env_var env_end; + char *argv[2]; + char text[0]; +}; + +static unsigned int prom_argc; +static const char ** prom_argv; +static const t_env_var * prom_env; + +static void prom_halt(void) __attribute__((noreturn)); +static void prom_exit(void) __attribute__((noreturn)); + + + +const char *get_system_type(void) +{ + return "Basler eXcite"; +} + +/* + * Halt the system + */ +static void prom_halt(void) +{ + printk(KERN_NOTICE "\n** System halted.\n"); + while (1) + asm volatile ( + "\t.set\tmips3\n" + "\twait\n" + "\t.set\tmips0\n" + ); +} + +/* + * Reset the CPU and re-enter Redboot + */ +static void prom_exit(void) +{ + unsigned int i; + volatile unsigned char * const flg = + (volatile unsigned char *) (EXCITE_ADDR_FPGA + EXCITE_FPGA_DPR); + + /* Clear the watchdog reset flag, set the reboot flag */ + *flg &= ~0x01; + *flg |= 0x80; + + for (i = 0; i < 10; i++) { + *(volatile unsigned char *) (EXCITE_ADDR_FPGA + EXCITE_FPGA_SYSCTL) = 0x02; + iob(); + mdelay(1000); + } + + printk(KERN_NOTICE "Reset failed\n"); + prom_halt(); +} + +static const char __init *prom_getenv(char *name) +{ + const t_env_var * p; + for (p = prom_env; p->name != NULL; p++) + if(strcmp(name, p->name) == 0) + break; + return p->val; +} + +/* + * Init routine which accepts the variables from Redboot + */ +void __init prom_init(void) +{ + const struct parmblock * const pb = (struct parmblock *) fw_arg2; + + prom_argc = fw_arg0; + prom_argv = (const char **) fw_arg1; + prom_env = &pb->memsize; + + /* Callbacks for halt, restart */ + _machine_restart = (void (*)(char *)) prom_exit; + _machine_halt = prom_halt; + +#ifdef CONFIG_32BIT + /* copy command line */ + strcpy(arcs_cmdline, prom_argv[1]); + memsize = simple_strtol(prom_getenv("memsize"), NULL, 16); + strcpy(modetty, prom_getenv("modetty0")); +#endif /* CONFIG_32BIT */ + +#ifdef CONFIG_64BIT +# error 64 bit support not implemented +#endif /* CONFIG_64BIT */ + + mips_machgroup = MACH_GROUP_TITAN; + mips_machtype = MACH_TITAN_EXCITE; +} + +/* This is called from free_initmem(), so we need to provide it */ +void __init prom_free_prom_memory(void) +{ + /* Nothing to do */ +} diff --git a/arch/mips/basler/excite/excite_setup.c b/arch/mips/basler/excite/excite_setup.c new file mode 100644 index 000000000..a1ce45800 --- /dev/null +++ b/arch/mips/basler/excite/excite_setup.c @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2004, 2005 by Basler Vision Technologies AG + * Author: Thomas Koeller <thomas.koeller@baslerweb.com> + * Based on the PMC-Sierra Yosemite board support by Ralf Baechle and + * Manish Lachwani. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/tty.h> +#include <linux/serial_core.h> +#include <linux/serial.h> +#include <linux/ioport.h> +#include <linux/spinlock.h> +#include <asm/bootinfo.h> +#include <asm/mipsregs.h> +#include <asm/pgtable-32.h> +#include <asm/io.h> +#include <asm/time.h> +#include <asm/rm9k-ocd.h> + +#include <excite.h> + +#define TITAN_UART_CLK 25000000 + +#if 1 +/* normal serial port assignment */ +#define REGBASE_SER0 0x0208 +#define REGBASE_SER1 0x0238 +#define MASK_SER0 0x1 +#define MASK_SER1 0x2 +#else +/* serial ports swapped */ +#define REGBASE_SER0 0x0238 +#define REGBASE_SER1 0x0208 +#define MASK_SER0 0x2 +#define MASK_SER1 0x1 +#endif + +unsigned long memsize; +char modetty[30]; +unsigned int titan_irq = TITAN_IRQ; +static void __iomem * ctl_regs; +u32 unit_id; + +volatile void __iomem * const ocd_base = (void *) (EXCITE_ADDR_OCD); +volatile void __iomem * const titan_base = (void *) (EXCITE_ADDR_TITAN); + +/* Protect access to shared GPI registers */ +spinlock_t titan_lock = SPIN_LOCK_UNLOCKED; +int titan_irqflags; + + +static void excite_timer_init(void) +{ + const u32 modebit5 = ocd_readl(0x00e4); + unsigned int + mult = ((modebit5 >> 11) & 0x1f) + 2, + div = ((modebit5 >> 16) & 0x1f) + 2; + + if (div == 33) div = 1; + mips_hpt_frequency = EXCITE_CPU_EXT_CLOCK * mult / div / 2; +} + +void __init plat_timer_setup(struct irqaction *irq) +{ + /* The eXcite platform uses the alternate timer interrupt */ + set_c0_intcontrol(0x80); + setup_irq(TIMER_IRQ, irq); +} + +static int __init excite_init_console(void) +{ +#if defined(CONFIG_SERIAL_8250) + static __initdata char serr[] = + KERN_ERR "Serial port #%u setup failed\n"; + struct uart_port up; + + /* Take the DUART out of reset */ + titan_writel(0x00ff1cff, CPRR); + +#if defined(CONFIG_KGDB) || (CONFIG_SERIAL_8250_NR_UARTS > 1) + /* Enable both ports */ + titan_writel(MASK_SER0 | MASK_SER1, UACFG); +#else + /* Enable port #0 only */ + titan_writel(MASK_SER0, UACFG); +#endif /* defined(CONFIG_KGDB) */ + + /* + * Set up serial port #0. Do not use autodetection; the result is + * not what we want. + */ + memset(&up, 0, sizeof(up)); + up.membase = (char *) titan_addr(REGBASE_SER0); + up.irq = TITAN_IRQ; + up.uartclk = TITAN_UART_CLK; + up.regshift = 0; + up.iotype = UPIO_MEM32; + up.type = PORT_RM9000; + up.flags = UPF_SHARE_IRQ; + up.line = 0; + if (early_serial_setup(&up)) + printk(serr, up.line); + +#if CONFIG_SERIAL_8250_NR_UARTS > 1 + /* And now for port #1. */ + up.membase = (char *) titan_addr(REGBASE_SER1); + up.line = 1; + if (early_serial_setup(&up)) + printk(serr, up.line); +#endif /* CONFIG_SERIAL_8250_NR_UARTS > 1 */ +#else + /* Leave the DUART in reset */ + titan_writel(0x00ff3cff, CPRR); +#endif /* defined(CONFIG_SERIAL_8250) */ + + return 0; +} + +static int __init excite_platform_init(void) +{ + unsigned int i; + unsigned char buf[3]; + u8 reg; + void __iomem * dpr; + + /* BIU buffer allocations */ + ocd_writel(8, CPURSLMT); /* CPU */ + titan_writel(4, CPGRWL); /* GPI / Ethernet */ + + /* Map control registers located in FPGA */ + ctl_regs = ioremap_nocache(EXCITE_PHYS_FPGA + EXCITE_FPGA_SYSCTL, 16); + if (!ctl_regs) + panic("eXcite: failed to map platform control registers\n"); + memcpy_fromio(buf, ctl_regs + 2, ARRAY_SIZE(buf)); + unit_id = buf[0] | (buf[1] << 8) | (buf[2] << 16); + + /* Clear the reboot flag */ + dpr = ioremap_nocache(EXCITE_PHYS_FPGA + EXCITE_FPGA_DPR, 1); + reg = __raw_readb(dpr); + __raw_writeb(reg & 0x7f, dpr); + iounmap(dpr); + + /* Interrupt controller setup */ + for (i = INTP0Status0; i < INTP0Status0 + 0x80; i += 0x10) { + ocd_writel(0x00000000, i + 0x04); + ocd_writel(0xffffffff, i + 0x0c); + } + ocd_writel(0x2, NMICONFIG); + + ocd_writel(0x1 << (TITAN_MSGINT % 0x20), + INTP0Mask0 + (0x10 * (TITAN_MSGINT / 0x20))); + ocd_writel((0x1 << (FPGA0_MSGINT % 0x20)) + | ocd_readl(INTP0Mask0 + (0x10 * (FPGA0_MSGINT / 0x20))), + INTP0Mask0 + (0x10 * (FPGA0_MSGINT / 0x20))); + ocd_writel((0x1 << (FPGA1_MSGINT % 0x20)) + | ocd_readl(INTP0Mask0 + (0x10 * (FPGA1_MSGINT / 0x20))), + INTP0Mask0 + (0x10 * (FPGA1_MSGINT / 0x20))); + ocd_writel((0x1 << (PHY_MSGINT % 0x20)) + | ocd_readl(INTP0Mask0 + (0x10 * (PHY_MSGINT / 0x20))), + INTP0Mask0 + (0x10 * (PHY_MSGINT / 0x20))); +#if USB_IRQ < 10 + ocd_writel((0x1 << (USB_MSGINT % 0x20)) + | ocd_readl(INTP0Mask0 + (0x10 * (USB_MSGINT / 0x20))), + INTP0Mask0 + (0x10 * (USB_MSGINT / 0x20))); +#endif + /* Enable the packet FIFO, XDMA and XDMA arbiter */ + titan_writel(0x00ff18ff, CPRR); + + /* + * Set up the PADMUX. Power down all ethernet slices, + * they will be powered up and configured at device startup. + */ + titan_writel(0x00878206, CPTC1R); + titan_writel(0x00001100, CPTC0R); /* latch PADMUX, enable WCIMODE */ + + /* Reset and enable the FIFO block */ + titan_writel(0x00000001, SDRXFCIE); + titan_writel(0x00000001, SDTXFCIE); + titan_writel(0x00000100, SDRXFCIE); + titan_writel(0x00000000, SDTXFCIE); + + /* + * Initialize the common interrupt shared by all components of + * the GPI/Ethernet subsystem. + */ + titan_writel((EXCITE_PHYS_OCD >> 12), CPCFG0); + titan_writel(TITAN_MSGINT, CPCFG1); + + /* + * XDMA configuration. + * In order for the XDMA to be sharable among multiple drivers, + * the setup must be done here in the platform. The reason is that + * this setup can only be done while the XDMA is in reset. If this + * were done in a driver, it would interrupt all other drivers + * using the XDMA. + */ + titan_writel(0x80021dff, GXCFG); /* XDMA reset */ + titan_writel(0x00000000, CPXCISRA); + titan_writel(0x00000000, CPXCISRB); /* clear pending interrupts */ +#if defined (CONFIG_HIGHMEM) +# error change for HIGHMEM support! +#else + titan_writel(0x00000000, GXDMADRPFX); /* buffer address prefix */ +#endif + titan_writel(0, GXDMA_DESCADR); + + for (i = 0x5040; i <= 0x5300; i += 0x0040) + titan_writel(0x80080000, i); /* reset channel */ + + titan_writel((0x1 << 29) /* no sparse tx descr. */ + | (0x1 << 28) /* no sparse rx descr. */ + | (0x1 << 23) | (0x1 << 24) /* descriptor coherency */ + | (0x1 << 21) | (0x1 << 22) /* data coherency */ + | (0x1 << 17) + | 0x1dff, + GXCFG); + +#if defined(CONFIG_SMP) +# error No SMP support +#else + /* All interrupts go to core #0 only. */ + titan_writel(0x1f007fff, CPDST0A); + titan_writel(0x00000000, CPDST0B); + titan_writel(0x0000ff3f, CPDST1A); + titan_writel(0x00000000, CPDST1B); + titan_writel(0x00ffffff, CPXDSTA); + titan_writel(0x00000000, CPXDSTB); +#endif + + /* Enable DUART interrupts, disable everything else. */ + titan_writel(0x04000000, CPGIG0ER); + titan_writel(0x000000c0, CPGIG1ER); + + excite_procfs_init(); + return 0; +} + +void __init plat_mem_setup(void) +{ + volatile u32 * const boot_ocd_base = (u32 *) 0xbf7fc000; + + /* Announce RAM to system */ + add_memory_region(0x00000000, memsize, BOOT_MEM_RAM); + + /* Set up timer initialization hooks */ + board_time_init = excite_timer_init; + + /* Set up the peripheral address map */ + *(boot_ocd_base + (LKB9 / sizeof (u32))) = 0; + *(boot_ocd_base + (LKB10 / sizeof (u32))) = 0; + *(boot_ocd_base + (LKB11 / sizeof (u32))) = 0; + *(boot_ocd_base + (LKB12 / sizeof (u32))) = 0; + wmb(); + *(boot_ocd_base + (LKB0 / sizeof (u32))) = EXCITE_PHYS_OCD >> 4; + wmb(); + + ocd_writel((EXCITE_PHYS_TITAN >> 4) | 0x1UL, LKB5); + ocd_writel(((EXCITE_SIZE_TITAN >> 4) & 0x7fffff00) - 0x100, LKM5); + ocd_writel((EXCITE_PHYS_SCRAM >> 4) | 0x1UL, LKB13); + ocd_writel(((EXCITE_SIZE_SCRAM >> 4) & 0xffffff00) - 0x100, LKM13); + + /* Local bus slot #0 */ + ocd_writel(0x00040510, LDP0); + ocd_writel((EXCITE_PHYS_BOOTROM >> 4) | 0x1UL, LKB9); + ocd_writel(((EXCITE_SIZE_BOOTROM >> 4) & 0x03ffff00) - 0x100, LKM9); + + /* Local bus slot #2 */ + ocd_writel(0x00000330, LDP2); + ocd_writel((EXCITE_PHYS_FPGA >> 4) | 0x1, LKB11); + ocd_writel(((EXCITE_SIZE_FPGA >> 4) - 0x100) & 0x03ffff00, LKM11); + + /* Local bus slot #3 */ + ocd_writel(0x00123413, LDP3); + ocd_writel((EXCITE_PHYS_NAND >> 4) | 0x1, LKB12); + ocd_writel(((EXCITE_SIZE_NAND >> 4) - 0x100) & 0x03ffff00, LKM12); +} + + + +console_initcall(excite_init_console); +arch_initcall(excite_platform_init); + +EXPORT_SYMBOL(titan_lock); +EXPORT_SYMBOL(titan_irqflags); +EXPORT_SYMBOL(titan_irq); +EXPORT_SYMBOL(ocd_base); +EXPORT_SYMBOL(titan_base); diff --git a/arch/mips/configs/emma2rh_defconfig b/arch/mips/configs/emma2rh_defconfig new file mode 100644 index 000000000..375b2ac24 --- /dev/null +++ b/arch/mips/configs/emma2rh_defconfig @@ -0,0 +1,1241 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18-rc1 +# Thu Jul 6 10:04:05 2006 +# +CONFIG_MIPS=y + +# +# Machine selection +# +# CONFIG_MIPS_MTX1 is not set +# CONFIG_MIPS_BOSPORUS is not set +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +# CONFIG_MIPS_PB1500 is not set +# CONFIG_MIPS_PB1550 is not set +# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_DB1000 is not set +# CONFIG_MIPS_DB1100 is not set +# CONFIG_MIPS_DB1500 is not set +# CONFIG_MIPS_DB1550 is not set +# CONFIG_MIPS_DB1200 is not set +# CONFIG_MIPS_MIRAGE is not set +# CONFIG_BASLER_EXCITE is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_LASAT is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_WR_PPMC is not set +# CONFIG_MIPS_SIM is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_3 is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MIPS_XXS1500 is not set +# CONFIG_PNX8550_V2PCI is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_DDB5477 is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_QEMU is not set +CONFIG_MARKEINS=y +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_PTSWARM is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_TOSHIBA_RBTX4938 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_CPU_BIG_ENDIAN=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_EMMA2RH=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 + +# +# CPU selection +# +# CONFIG_CPU_MIPS32_R1 is not set +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +CONFIG_CPU_R5000=y +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_SYS_HAS_CPU_R5000=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y + +# +# Kernel type +# +CONFIG_32BIT=y +# CONFIG_64BIT is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_MIPS_MT_DISABLED=y +# CONFIG_MIPS_MT_SMTC is not set +# CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_VPE_LOADER is not set +# CONFIG_64BIT_PHYS_ADDR is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_BKL=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_RT_MUTEXES=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +CONFIG_LBD=y +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_HW_HAS_PCI=y +CONFIG_PCI=y +CONFIG_MMU=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +# CONFIG_IP_ROUTE_FWMARK is not set +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +CONFIG_IPV6=m +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +# CONFIG_IPV6_TUNNEL is not set +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NF_CONNTRACK is not set +# CONFIG_NETFILTER_XTABLES is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +# CONFIG_IP6_NF_QUEUE is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x1e000000 +CONFIG_MTD_PHYSMAP_LEN=0x02000000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=m +# CONFIG_SCSI_PROC_FS is not set + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=m +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_DM9000 is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +CONFIG_NATSEMI=y +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_LAN_SAA9730 is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPP_MPPE is not set +# CONFIG_PPPOE is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=m +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set +CONFIG_RTC=m +CONFIG_GEN_RTC=m +CONFIG_GEN_RTC_X=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +CONFIG_I2C_DEBUG_CORE=y +# CONFIG_I2C_DEBUG_ALGO is not set +CONFIG_I2C_DEBUG_BUS=y +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_SECURITY is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_XFS_RT is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=m +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_RW is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_CMODE_NONE is not set +CONFIG_JFFS2_CMODE_PRIORITY=y +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V3_ACL is not set +# CONFIG_NFSD_V4 is not set +CONFIG_NFSD_TCP=y +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="" +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 +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=m +CONFIG_NLS_ISO8859_1=m +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +CONFIG_NLS_UTF8=m + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_FS is not set +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="console=ttyS0,115200 mem=192m ip=bootp root=/dev/nfs rw" + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y diff --git a/arch/mips/configs/excite_defconfig b/arch/mips/configs/excite_defconfig new file mode 100644 index 000000000..045ebd089 --- /dev/null +++ b/arch/mips/configs/excite_defconfig @@ -0,0 +1,1245 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18-rc1 +# Thu Jul 6 10:04:09 2006 +# +CONFIG_MIPS=y + +# +# Machine selection +# +# CONFIG_MIPS_MTX1 is not set +# CONFIG_MIPS_BOSPORUS is not set +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +# CONFIG_MIPS_PB1500 is not set +# CONFIG_MIPS_PB1550 is not set +# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_DB1000 is not set +# CONFIG_MIPS_DB1100 is not set +# CONFIG_MIPS_DB1500 is not set +# CONFIG_MIPS_DB1550 is not set +# CONFIG_MIPS_DB1200 is not set +# CONFIG_MIPS_MIRAGE is not set +CONFIG_BASLER_EXCITE=y +# CONFIG_BASLER_EXCITE_PROTOTYPE is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_LASAT is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_WR_PPMC is not set +# CONFIG_MIPS_SIM is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_3 is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MIPS_XXS1500 is not set +# CONFIG_PNX8550_V2PCI is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_DDB5477 is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_QEMU is not set +# CONFIG_MARKEINS is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_PTSWARM is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_TOSHIBA_RBTX4938 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_DMA_COHERENT=y +CONFIG_CPU_BIG_ENDIAN=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_IRQ_CPU_RM7K=y +CONFIG_IRQ_CPU_RM9K=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 + +# +# CPU selection +# +# CONFIG_CPU_MIPS32_R1 is not set +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +CONFIG_CPU_RM9000=y +# CONFIG_CPU_SB1 is not set +CONFIG_SYS_HAS_CPU_RM9000=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y + +# +# Kernel type +# +CONFIG_32BIT=y +# CONFIG_64BIT is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_MIPS_MT_DISABLED=y +# CONFIG_MIPS_MT_SMTC is not set +# CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_VPE_LOADER is not set +# CONFIG_64BIT_PHYS_ADDR is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_BKL=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_RT_MUTEXES=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y + +# +# Block layer +# +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_HW_HAS_PCI=y +CONFIG_PCI=y +CONFIG_MMU=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_NETWORK_SECMARK=y +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_VERIFY_WRITE=y +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_NANDSIM is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +# CONFIG_SCSI_PROC_FS is not set + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# + +# +# Ethernet (10 or 100Mbit) +# +# CONFIG_NET_ETHERNET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=m +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=m +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_EXTENDED=y +# CONFIG_SERIAL_8250_MANY_PORTS is not set +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_SMIVGX is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=m +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +# CONFIG_LOGO is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_SPLIT_ISO is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT 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_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_USB_MON is not set + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +# CONFIG_EXT3_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=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 is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +CONFIG_NLS_CODEPAGE_850=m +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=m +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# 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 + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_FS is not set +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="" + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_PLIST=y diff --git a/arch/mips/configs/wrppmc_defconfig b/arch/mips/configs/wrppmc_defconfig new file mode 100644 index 000000000..3e4b16b39 --- /dev/null +++ b/arch/mips/configs/wrppmc_defconfig @@ -0,0 +1,864 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18-rc1 +# Thu Jul 6 10:04:21 2006 +# +CONFIG_MIPS=y + +# +# Machine selection +# +# CONFIG_MIPS_MTX1 is not set +# CONFIG_MIPS_BOSPORUS is not set +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +# CONFIG_MIPS_PB1500 is not set +# CONFIG_MIPS_PB1550 is not set +# CONFIG_MIPS_PB1200 is not set +# CONFIG_MIPS_DB1000 is not set +# CONFIG_MIPS_DB1100 is not set +# CONFIG_MIPS_DB1500 is not set +# CONFIG_MIPS_DB1550 is not set +# CONFIG_MIPS_DB1200 is not set +# CONFIG_MIPS_MIRAGE is not set +# CONFIG_BASLER_EXCITE is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_LASAT is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +CONFIG_WR_PPMC=y +# CONFIG_MIPS_SIM is not set +# CONFIG_MOMENCO_JAGUAR_ATX is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_3 is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MIPS_XXS1500 is not set +# CONFIG_PNX8550_V2PCI is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_DDB5477 is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_QEMU is not set +# CONFIG_MARKEINS is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_PTSWARM is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_TOSHIBA_RBTX4938 is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_CPU_BIG_ENDIAN=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_MIPS_GT64120=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 + +# +# CPU selection +# +CONFIG_CPU_MIPS32_R1=y +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_CPU_MIPS32_R2=y +CONFIG_SYS_HAS_CPU_MIPS64_R1=y +CONFIG_SYS_HAS_CPU_NEVADA=y +CONFIG_SYS_HAS_CPU_RM7000=y +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPSR1=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y + +# +# Kernel type +# +CONFIG_32BIT=y +# CONFIG_64BIT is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_MIPS_MT_DISABLED=y +# CONFIG_MIPS_MT_SMTC is not set +# CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_VPE_LOADER is not set +# CONFIG_64BIT_PHYS_ADDR is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +# CONFIG_HZ_48 is not set +# CONFIG_HZ_100 is not set +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +CONFIG_HZ_1000=y +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=1000 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_RT_MUTEXES=y +CONFIG_FUTEX=y +# CONFIG_EPOLL is not set +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +# CONFIG_KMOD is not set + +# +# Block layer +# +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_HW_HAS_PCI=y +CONFIG_PCI=y +CONFIG_MMU=y + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +# CONFIG_HOTPLUG_PCI_FAKE is not set +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_TRAD_SIGNALS=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +CONFIG_IP_MROUTE=y +# CONFIG_IP_PIMSM_V1 is not set +# CONFIG_IP_PIMSM_V2 is not set +CONFIG_ARPD=y +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_NETWORK_SECMARK=y +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_DM9000 is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_LAN_SAA9730 is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=1 +CONFIG_SERIAL_8250_RUNTIME_UARTS=1 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set +CONFIG_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_FS is not set +CONFIG_CROSSCOMPILE=y +CONFIG_CMDLINE="console=ttyS0,115200n8" + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +CONFIG_CRC32=y +CONFIG_LIBCRC32C=y +CONFIG_PLIST=y diff --git a/arch/mips/emma2rh/common/Makefile b/arch/mips/emma2rh/common/Makefile new file mode 100644 index 000000000..859121b38 --- /dev/null +++ b/arch/mips/emma2rh/common/Makefile @@ -0,0 +1,13 @@ +# +# arch/mips/emma2rh/common/Makefile +# Makefile for the common code of NEC EMMA2RH based board. +# +# Copyright (C) NEC Electronics Corporation 2005-2006 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# + +obj-$(CONFIG_MARKEINS) += irq.o irq_emma2rh.o prom.o diff --git a/arch/mips/emma2rh/common/irq.c b/arch/mips/emma2rh/common/irq.c new file mode 100644 index 000000000..3af57693c --- /dev/null +++ b/arch/mips/emma2rh/common/irq.c @@ -0,0 +1,107 @@ +/* + * arch/mips/emma2rh/common/irq.c + * This file is common irq dispatcher. + * + * Copyright (C) NEC Electronics Corporation 2005-2006 + * + * This file is based on the arch/mips/ddb5xxx/ddb5477/irq.c + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/types.h> + +#include <asm/i8259.h> +#include <asm/system.h> +#include <asm/mipsregs.h> +#include <asm/debug.h> +#include <asm/addrspace.h> +#include <asm/bootinfo.h> + +#include <asm/emma2rh/emma2rh.h> + +/* + * the first level int-handler will jump here if it is a emma2rh irq + */ +asmlinkage void emma2rh_irq_dispatch(struct pt_regs *regs) +{ + u32 intStatus; + u32 bitmask; + u32 i; + + intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_0) + & emma2rh_in32(EMMA2RH_BHIF_INT_EN_0); + +#ifdef EMMA2RH_SW_CASCADE + if (intStatus & + (1 << ((EMMA2RH_SW_CASCADE - EMMA2RH_IRQ_INT0) & (32 - 1)))) { + u32 swIntStatus; + swIntStatus = emma2rh_in32(EMMA2RH_BHIF_SW_INT) + & emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN); + for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) { + if (swIntStatus & bitmask) { + do_IRQ(EMMA2RH_SW_IRQ_BASE + i, regs); + return; + } + } + } +#endif + + for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) { + if (intStatus & bitmask) { + do_IRQ(EMMA2RH_IRQ_BASE + i, regs); + return; + } + } + + intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_1) + & emma2rh_in32(EMMA2RH_BHIF_INT_EN_1); + +#ifdef EMMA2RH_GPIO_CASCADE + if (intStatus & + (1 << ((EMMA2RH_GPIO_CASCADE - EMMA2RH_IRQ_INT0) & (32 - 1)))) { + u32 gpioIntStatus; + gpioIntStatus = emma2rh_in32(EMMA2RH_GPIO_INT_ST) + & emma2rh_in32(EMMA2RH_GPIO_INT_MASK); + for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) { + if (gpioIntStatus & bitmask) { + do_IRQ(EMMA2RH_GPIO_IRQ_BASE + i, regs); + return; + } + } + } +#endif + + for (i = 32, bitmask = 1; i < 64; i++, bitmask <<= 1) { + if (intStatus & bitmask) { + do_IRQ(EMMA2RH_IRQ_BASE + i, regs); + return; + } + } + + intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_2) + & emma2rh_in32(EMMA2RH_BHIF_INT_EN_2); + + for (i = 64, bitmask = 1; i < 96; i++, bitmask <<= 1) { + if (intStatus & bitmask) { + do_IRQ(EMMA2RH_IRQ_BASE + i, regs); + return; + } + } +} diff --git a/arch/mips/emma2rh/common/irq_emma2rh.c b/arch/mips/emma2rh/common/irq_emma2rh.c new file mode 100644 index 000000000..7c930860c --- /dev/null +++ b/arch/mips/emma2rh/common/irq_emma2rh.c @@ -0,0 +1,134 @@ +/* + * arch/mips/emma2rh/common/irq_emma2rh.c + * This file defines the irq handler for EMMA2RH. + * + * Copyright (C) NEC Electronics Corporation 2005-2006 + * + * This file is based on the arch/mips/ddb5xxx/ddb5477/irq_5477.c + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * EMMA2RH defines 64 IRQs. + * + * This file exports one function: + * emma2rh_irq_init(u32 irq_base); + */ + +#include <linux/interrupt.h> +#include <linux/types.h> +#include <linux/ptrace.h> + +#include <asm/debug.h> + +#include <asm/emma2rh/emma2rh.h> + +/* number of total irqs supported by EMMA2RH */ +#define NUM_EMMA2RH_IRQ 96 + +static int emma2rh_irq_base = -1; + +void ll_emma2rh_irq_enable(int); +void ll_emma2rh_irq_disable(int); + +static void emma2rh_irq_enable(unsigned int irq) +{ + ll_emma2rh_irq_enable(irq - emma2rh_irq_base); +} + +static void emma2rh_irq_disable(unsigned int irq) +{ + ll_emma2rh_irq_disable(irq - emma2rh_irq_base); +} + +static unsigned int emma2rh_irq_startup(unsigned int irq) +{ + emma2rh_irq_enable(irq); + return 0; +} + +#define emma2rh_irq_shutdown emma2rh_irq_disable + +static void emma2rh_irq_ack(unsigned int irq) +{ + /* disable interrupt - some handler will re-enable the irq + * and if the interrupt is leveled, we will have infinite loop + */ + ll_emma2rh_irq_disable(irq - emma2rh_irq_base); +} + +static void emma2rh_irq_end(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + ll_emma2rh_irq_enable(irq - emma2rh_irq_base); +} + +struct irq_chip emma2rh_irq_controller = { + .typename = "emma2rh_irq", + .startup = emma2rh_irq_startup, + .shutdown = emma2rh_irq_shutdown, + .enable = emma2rh_irq_enable, + .disable = emma2rh_irq_disable, + .ack = emma2rh_irq_ack, + .end = emma2rh_irq_end, + .set_affinity = NULL /* no affinity stuff for UP */ +}; + +void emma2rh_irq_init(u32 irq_base) +{ + u32 i; + + for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].handler = &emma2rh_irq_controller; + } + + emma2rh_irq_base = irq_base; +} + +void ll_emma2rh_irq_enable(int emma2rh_irq) +{ + u32 reg_value; + u32 reg_bitmask; + u32 reg_index; + + reg_index = EMMA2RH_BHIF_INT_EN_0 + + (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0) + * (emma2rh_irq / 32); + reg_value = emma2rh_in32(reg_index); + reg_bitmask = 0x1 << (emma2rh_irq % 32); + db_assert((reg_value & reg_bitmask) == 0); + emma2rh_out32(reg_index, reg_value | reg_bitmask); +} + +void ll_emma2rh_irq_disable(int emma2rh_irq) +{ + u32 reg_value; + u32 reg_bitmask; + u32 reg_index; + + reg_index = EMMA2RH_BHIF_INT_EN_0 + + (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0) + * (emma2rh_irq / 32); + reg_value = emma2rh_in32(reg_index); + reg_bitmask = 0x1 << (emma2rh_irq % 32); + db_assert((reg_value & reg_bitmask) != 0); + emma2rh_out32(reg_index, reg_value & ~reg_bitmask); +} diff --git a/arch/mips/emma2rh/common/prom.c b/arch/mips/emma2rh/common/prom.c new file mode 100644 index 000000000..7433bd8e5 --- /dev/null +++ b/arch/mips/emma2rh/common/prom.c @@ -0,0 +1,76 @@ +/* + * arch/mips/emma2rh/common/prom.c + * This file is prom file. + * + * Copyright (C) NEC Electronics Corporation 2004-2006 + * + * This file is based on the arch/mips/ddb5xxx/common/prom.c + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/bootmem.h> + +#include <asm/addrspace.h> +#include <asm/bootinfo.h> +#include <asm/emma2rh/emma2rh.h> +#include <asm/debug.h> + +const char *get_system_type(void) +{ + switch (mips_machtype) { + case MACH_NEC_MARKEINS: + return "NEC EMMA2RH Mark-eins"; + default: + return "Unknown NEC board"; + } +} + +/* [jsun@junsun.net] PMON passes arguments in C main() style */ +void __init prom_init(void) +{ + int argc = fw_arg0; + char **arg = (char **)fw_arg1; + int i; + + /* if user passes kernel args, ignore the default one */ + if (argc > 1) + arcs_cmdline[0] = '\0'; + + /* arg[0] is "g", the rest is boot parameters */ + for (i = 1; i < argc; i++) { + if (strlen(arcs_cmdline) + strlen(arg[i] + 1) + >= sizeof(arcs_cmdline)) + break; + strcat(arcs_cmdline, arg[i]); + strcat(arcs_cmdline, " "); + } + + mips_machgroup = MACH_GROUP_NEC_EMMA2RH; + +#if defined(CONFIG_MARKEINS) + mips_machtype = MACH_NEC_MARKEINS; + add_memory_region(0, EMMA2RH_RAM_SIZE, BOOT_MEM_RAM); +#endif + +} + +void __init prom_free_prom_memory(void) +{ +} diff --git a/arch/mips/emma2rh/markeins/Makefile b/arch/mips/emma2rh/markeins/Makefile new file mode 100644 index 000000000..14fc268b1 --- /dev/null +++ b/arch/mips/emma2rh/markeins/Makefile @@ -0,0 +1,13 @@ +# +# arch/mips/emma2rh/markeins/Makefile +# Makefile for the common code of NEC EMMA2RH based board. +# +# Copyright (C) NEC Electronics Corporation 2005-2006 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# + +obj-$(CONFIG_MARKEINS) += irq.o irq_markeins.o setup.o led.o platform.o diff --git a/arch/mips/emma2rh/markeins/irq.c b/arch/mips/emma2rh/markeins/irq.c new file mode 100644 index 000000000..2a736be42 --- /dev/null +++ b/arch/mips/emma2rh/markeins/irq.c @@ -0,0 +1,133 @@ +/* + * arch/mips/emma2rh/markeins/irq.c + * This file defines the irq handler for EMMA2RH. + * + * Copyright (C) NEC Electronics Corporation 2004-2006 + * + * This file is based on the arch/mips/ddb5xxx/ddb5477/irq.c + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/types.h> +#include <linux/ptrace.h> +#include <linux/delay.h> + +#include <asm/i8259.h> +#include <asm/irq_cpu.h> +#include <asm/system.h> +#include <asm/mipsregs.h> +#include <asm/debug.h> +#include <asm/addrspace.h> +#include <asm/bootinfo.h> + +#include <asm/emma2rh/emma2rh.h> + +/* + * IRQ mapping + * + * 0-7: 8 CPU interrupts + * 0 - software interrupt 0 + * 1 - software interrupt 1 + * 2 - most Vrc5477 interrupts are routed to this pin + * 3 - (optional) some other interrupts routed to this pin for debugg + * 4 - not used + * 5 - not used + * 6 - not used + * 7 - cpu timer (used by default) + * + */ + +extern void emma2rh_sw_irq_init(u32 base); +extern void emma2rh_gpio_irq_init(u32 base); +extern void emma2rh_irq_init(u32 base); +extern asmlinkage void emma2rh_irq_dispatch(struct pt_regs *regs); + +static struct irqaction irq_cascade = { + .handler = no_action, + .flags = 0, + .mask = CPU_MASK_NONE, + .name = "cascade", + .dev_id = NULL, + .next = NULL, +}; + +void __init arch_init_irq(void) +{ + u32 reg; + + db_run(printk("markeins_irq_setup invoked.\n")); + + /* by default, interrupts are disabled. */ + emma2rh_out32(EMMA2RH_BHIF_INT_EN_0, 0); + emma2rh_out32(EMMA2RH_BHIF_INT_EN_1, 0); + emma2rh_out32(EMMA2RH_BHIF_INT_EN_2, 0); + emma2rh_out32(EMMA2RH_BHIF_INT1_EN_0, 0); + emma2rh_out32(EMMA2RH_BHIF_INT1_EN_1, 0); + emma2rh_out32(EMMA2RH_BHIF_INT1_EN_2, 0); + emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, 0); + + clear_c0_status(0xff00); + set_c0_status(0x0400); + +#define GPIO_PCI (0xf<<15) + /* setup GPIO interrupt for PCI interface */ + /* direction input */ + reg = emma2rh_in32(EMMA2RH_GPIO_DIR); + emma2rh_out32(EMMA2RH_GPIO_DIR, reg & ~GPIO_PCI); + /* disable interrupt */ + reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK); + emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg & ~GPIO_PCI); + /* level triggerd */ + reg = emma2rh_in32(EMMA2RH_GPIO_INT_MODE); + emma2rh_out32(EMMA2RH_GPIO_INT_MODE, reg | GPIO_PCI); + reg = emma2rh_in32(EMMA2RH_GPIO_INT_CND_A); + emma2rh_out32(EMMA2RH_GPIO_INT_CND_A, reg & (~GPIO_PCI)); + /* interrupt clear */ + emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~GPIO_PCI); + + /* init all controllers */ + emma2rh_irq_init(EMMA2RH_IRQ_BASE); + emma2rh_sw_irq_init(EMMA2RH_SW_IRQ_BASE); + emma2rh_gpio_irq_init(EMMA2RH_GPIO_IRQ_BASE); + mips_cpu_irq_init(CPU_IRQ_BASE); + + /* setup cascade interrupts */ + setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_SW_CASCADE, &irq_cascade); + setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_GPIO_CASCADE, &irq_cascade); + setup_irq(CPU_IRQ_BASE + CPU_EMMA2RH_CASCADE, &irq_cascade); +} + +asmlinkage void plat_irq_dispatch(struct pt_regs *regs) +{ + unsigned int pending = read_c0_status() & read_c0_cause(); + + if (pending & STATUSF_IP7) + do_IRQ(CPU_IRQ_BASE + 7, regs); + else if (pending & STATUSF_IP2) + emma2rh_irq_dispatch(regs); + else if (pending & STATUSF_IP1) + do_IRQ(CPU_IRQ_BASE + 1, regs); + else if (pending & STATUSF_IP0) + do_IRQ(CPU_IRQ_BASE + 0, regs); + else + spurious_interrupt(regs); +} + + diff --git a/arch/mips/emma2rh/markeins/irq_markeins.c b/arch/mips/emma2rh/markeins/irq_markeins.c new file mode 100644 index 000000000..f23ae9fcf --- /dev/null +++ b/arch/mips/emma2rh/markeins/irq_markeins.c @@ -0,0 +1,197 @@ +/* + * arch/mips/emma2rh/markeins/irq_markeins.c + * This file defines the irq handler for Mark-eins. + * + * Copyright (C) NEC Electronics Corporation 2004-2006 + * + * This file is based on the arch/mips/ddb5xxx/ddb5477/irq_5477.c + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/types.h> +#include <linux/ptrace.h> + +#include <asm/debug.h> +#include <asm/emma2rh/emma2rh.h> + +static int emma2rh_sw_irq_base = -1; +static int emma2rh_gpio_irq_base = -1; + +void ll_emma2rh_sw_irq_enable(int reg); +void ll_emma2rh_sw_irq_disable(int reg); +void ll_emma2rh_gpio_irq_enable(int reg); +void ll_emma2rh_gpio_irq_disable(int reg); + +static void emma2rh_sw_irq_enable(unsigned int irq) +{ + ll_emma2rh_sw_irq_enable(irq - emma2rh_sw_irq_base); +} + +static void emma2rh_sw_irq_disable(unsigned int irq) +{ + ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base); +} + +static unsigned int emma2rh_sw_irq_startup(unsigned int irq) +{ + emma2rh_sw_irq_enable(irq); + return 0; +} + +#define emma2rh_sw_irq_shutdown emma2rh_sw_irq_disable + +static void emma2rh_sw_irq_ack(unsigned int irq) +{ + ll_emma2rh_sw_irq_disable(irq - emma2rh_sw_irq_base); +} + +static void emma2rh_sw_irq_end(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + ll_emma2rh_sw_irq_enable(irq - emma2rh_sw_irq_base); +} + +struct irq_chip emma2rh_sw_irq_controller = { + .typename = "emma2rh_sw_irq", + .startup = emma2rh_sw_irq_startup, + .shutdown = emma2rh_sw_irq_shutdown, + .enable = emma2rh_sw_irq_enable, + .disable = emma2rh_sw_irq_disable, + .ack = emma2rh_sw_irq_ack, + .end = emma2rh_sw_irq_end, + .set_affinity = NULL, +}; + +void emma2rh_sw_irq_init(u32 irq_base) +{ + u32 i; + + for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_SW; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 2; + irq_desc[i].handler = &emma2rh_sw_irq_controller; + } + + emma2rh_sw_irq_base = irq_base; +} + +void ll_emma2rh_sw_irq_enable(int irq) +{ + u32 reg; + + db_assert(irq >= 0); + db_assert(irq < NUM_EMMA2RH_IRQ_SW); + + reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN); + reg |= 1 << irq; + emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg); +} + +void ll_emma2rh_sw_irq_disable(int irq) +{ + u32 reg; + + db_assert(irq >= 0); + db_assert(irq < 32); + + reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN); + reg &= ~(1 << irq); + emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg); +} + +static void emma2rh_gpio_irq_enable(unsigned int irq) +{ + ll_emma2rh_gpio_irq_enable(irq - emma2rh_gpio_irq_base); +} + +static void emma2rh_gpio_irq_disable(unsigned int irq) +{ + ll_emma2rh_gpio_irq_disable(irq - emma2rh_gpio_irq_base); +} + +static unsigned int emma2rh_gpio_irq_startup(unsigned int irq) +{ + emma2rh_gpio_irq_enable(irq); + return 0; +} + +#define emma2rh_gpio_irq_shutdown emma2rh_gpio_irq_disable + +static void emma2rh_gpio_irq_ack(unsigned int irq) +{ + irq -= emma2rh_gpio_irq_base; + emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq)); + ll_emma2rh_gpio_irq_disable(irq); +} + +static void emma2rh_gpio_irq_end(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + ll_emma2rh_gpio_irq_enable(irq - emma2rh_gpio_irq_base); +} + +struct irq_chip emma2rh_gpio_irq_controller = { + .typename = "emma2rh_gpio_irq", + .startup = emma2rh_gpio_irq_startup, + .shutdown = emma2rh_gpio_irq_shutdown, + .enable = emma2rh_gpio_irq_enable, + .disable = emma2rh_gpio_irq_disable, + .ack = emma2rh_gpio_irq_ack, + .end = emma2rh_gpio_irq_end, + .set_affinity = NULL, +}; + +void emma2rh_gpio_irq_init(u32 irq_base) +{ + u32 i; + + for (i = irq_base; i < irq_base + NUM_EMMA2RH_IRQ_GPIO; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 2; + irq_desc[i].handler = &emma2rh_gpio_irq_controller; + } + + emma2rh_gpio_irq_base = irq_base; +} + +void ll_emma2rh_gpio_irq_enable(int irq) +{ + u32 reg; + + db_assert(irq >= 0); + db_assert(irq < NUM_EMMA2RH_IRQ_GPIO); + + reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK); + reg |= 1 << irq; + emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg); +} + +void ll_emma2rh_gpio_irq_disable(int irq) +{ + u32 reg; + + db_assert(irq >= 0); + db_assert(irq < NUM_EMMA2RH_IRQ_GPIO); + + reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK); + reg &= ~(1 << irq); + emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg); +} diff --git a/arch/mips/emma2rh/markeins/led.c b/arch/mips/emma2rh/markeins/led.c new file mode 100644 index 000000000..b65254c1b --- /dev/null +++ b/arch/mips/emma2rh/markeins/led.c @@ -0,0 +1,60 @@ +/* + * arch/mips/emma2rh/markeins/led.c + * This file defines the led display for Mark-eins. + * + * Copyright (C) NEC Electronics Corporation 2004-2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/string.h> +#include <asm/emma2rh/emma2rh.h> + +const unsigned long clear = 0x20202020; + +#define LED_BASE 0xb1400038 + +void markeins_led_clear(void) +{ + emma2rh_out32(LED_BASE, clear); + emma2rh_out32(LED_BASE + 4, clear); +} + +void markeins_led(const char *str) +{ + int i; + int len = strlen(str); + + markeins_led_clear(); + if (len > 8) + len = 8; + + if (emma2rh_in32(0xb0000800) & (0x1 << 18)) + for (i = 0; i < len; i++) + emma2rh_out8(LED_BASE + i, str[i]); + else + for (i = 0; i < len; i++) + emma2rh_out8(LED_BASE + (i & 4) + (3 - (i & 3)), + str[i]); +} + +void markeins_led_hex(u32 val) +{ + char str[10]; + + sprintf(str, "%08x", val); + markeins_led(str); +} diff --git a/arch/mips/emma2rh/markeins/platform.c b/arch/mips/emma2rh/markeins/platform.c new file mode 100644 index 000000000..15cc61df3 --- /dev/null +++ b/arch/mips/emma2rh/markeins/platform.c @@ -0,0 +1,169 @@ +/* + * arch/mips/emma2rh/markeins/platofrm.c + * This file sets up platform devices for EMMA2RH Mark-eins. + * + * Copyright(C) MontaVista Software Inc, 2006 + * + * Author: dmitry pervushin <dpervushin@ru.mvista.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/ioport.h> +#include <linux/serial_8250.h> +#include <linux/mtd/physmap.h> + +#include <asm/cpu.h> +#include <asm/bootinfo.h> +#include <asm/addrspace.h> +#include <asm/time.h> +#include <asm/bcache.h> +#include <asm/irq.h> +#include <asm/reboot.h> +#include <asm/gdb-stub.h> +#include <asm/traps.h> +#include <asm/debug.h> + +#include <asm/emma2rh/emma2rh.h> + + +#define I2C_EMMA2RH "emma2rh-iic" /* must be in sync with IIC driver */ + +static struct resource i2c_emma_resources_0[] = { + { NULL, EMMA2RH_IRQ_PIIC0, EMMA2RH_IRQ_PIIC0, IORESOURCE_IRQ }, + { NULL, KSEG1ADDR(EMMA2RH_PIIC0_BASE), KSEG1ADDR(EMMA2RH_PIIC0_BASE + 0x1000), 0 }, +}; + +struct resource i2c_emma_resources_1[] = { + { NULL, EMMA2RH_IRQ_PIIC1, EMMA2RH_IRQ_PIIC1, IORESOURCE_IRQ }, + { NULL, KSEG1ADDR(EMMA2RH_PIIC1_BASE), KSEG1ADDR(EMMA2RH_PIIC1_BASE + 0x1000), 0 }, +}; + +struct resource i2c_emma_resources_2[] = { + { NULL, EMMA2RH_IRQ_PIIC2, EMMA2RH_IRQ_PIIC2, IORESOURCE_IRQ }, + { NULL, KSEG1ADDR(EMMA2RH_PIIC2_BASE), KSEG1ADDR(EMMA2RH_PIIC2_BASE + 0x1000), 0 }, +}; + +struct platform_device i2c_emma_devices[] = { + [0] = { + .name = I2C_EMMA2RH, + .id = 0, + .resource = i2c_emma_resources_0, + .num_resources = ARRAY_SIZE(i2c_emma_resources_0), + }, + [1] = { + .name = I2C_EMMA2RH, + .id = 1, + .resource = i2c_emma_resources_1, + .num_resources = ARRAY_SIZE(i2c_emma_resources_1), + }, + [2] = { + .name = I2C_EMMA2RH, + .id = 2, + .resource = i2c_emma_resources_2, + .num_resources = ARRAY_SIZE(i2c_emma_resources_2), + }, +}; + +#define EMMA2RH_SERIAL_CLOCK 18544000 +#define EMMA2RH_SERIAL_FLAGS UPF_BOOT_AUTOCONF | UPF_SKIP_TEST + +static struct plat_serial8250_port platform_serial_ports[] = { + [0] = { + .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3), + .irq = EMMA2RH_IRQ_PFUR0, + .uartclk = EMMA2RH_SERIAL_CLOCK, + .regshift = 4, + .iotype = UPIO_MEM, + .flags = EMMA2RH_SERIAL_FLAGS, + }, + [1] = { + .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3), + .irq = EMMA2RH_IRQ_PFUR1, + .uartclk = EMMA2RH_SERIAL_CLOCK, + .regshift = 4, + .iotype = UPIO_MEM, + .flags = EMMA2RH_SERIAL_FLAGS, + }, + [2] = { + .membase = (void __iomem*)KSEG1ADDR(EMMA2RH_PFUR2_BASE + 3), + .irq = EMMA2RH_IRQ_PFUR2, + .uartclk = EMMA2RH_SERIAL_CLOCK, + .regshift = 4, + .iotype = UPIO_MEM, + .flags = EMMA2RH_SERIAL_FLAGS, + }, + [3] = { + .flags = 0, + }, +}; + +static struct platform_device serial_emma = { + .name = "serial8250", + .dev = { + .platform_data = &platform_serial_ports, + }, +}; + +static struct platform_device *devices[] = { + &i2c_emma_devices[0], + &i2c_emma_devices[1], + &i2c_emma_devices[2], + &serial_emma, +}; + +static struct mtd_partition markeins_parts[] = { + [0] = { + .name = "RootFS", + .offset = 0x00000000, + .size = 0x00c00000, + }, + [1] = { + .name = "boot code area", + .offset = MTDPART_OFS_APPEND, + .size = 0x00100000, + }, + [2] = { + .name = "kernel image", + .offset = MTDPART_OFS_APPEND, + .size = 0x00300000, + }, + [3] = { + .name = "RootFS2", + .offset = MTDPART_OFS_APPEND, + .size = 0x00c00000, + }, + [4] = { + .name = "boot code area2", + .offset = MTDPART_OFS_APPEND, + .size = 0x00100000, + }, + [5] = { + .name = "kernel image2", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +static int __init platform_devices_setup(void) +{ + physmap_set_partitions(markeins_parts, ARRAY_SIZE(markeins_parts)); + return platform_add_devices(devices, ARRAY_SIZE(devices)); +} + +arch_initcall(platform_devices_setup); + diff --git a/arch/mips/emma2rh/markeins/setup.c b/arch/mips/emma2rh/markeins/setup.c new file mode 100644 index 000000000..b29a44739 --- /dev/null +++ b/arch/mips/emma2rh/markeins/setup.c @@ -0,0 +1,180 @@ +/* + * arch/mips/emma2rh/markeins/setup.c + * This file is setup for EMMA2RH Mark-eins. + * + * Copyright (C) NEC Electronics Corporation 2004-2006 + * + * This file is based on the arch/mips/ddb5xxx/ddb5477/setup.c. + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/initrd.h> +#include <linux/irq.h> +#include <linux/ide.h> +#include <linux/ioport.h> +#include <linux/param.h> /* for HZ */ +#include <linux/root_dev.h> +#include <linux/serial.h> +#include <linux/serial_core.h> + +#include <asm/cpu.h> +#include <asm/bootinfo.h> +#include <asm/addrspace.h> +#include <asm/time.h> +#include <asm/bcache.h> +#include <asm/irq.h> +#include <asm/reboot.h> +#include <asm/gdb-stub.h> +#include <asm/traps.h> +#include <asm/debug.h> + +#include <asm/emma2rh/emma2rh.h> + +#define USE_CPU_COUNTER_TIMER /* whether we use cpu counter */ + +extern void markeins_led(const char *); + +static int bus_frequency = 0; + +static void markeins_machine_restart(char *command) +{ + static void (*back_to_prom) (void) = (void (*)(void))0xbfc00000; + + printk("cannot EMMA2RH Mark-eins restart.\n"); + markeins_led("restart."); + back_to_prom(); +} + +static void markeins_machine_halt(void) +{ + printk("EMMA2RH Mark-eins halted.\n"); + markeins_led("halted."); + while (1) ; +} + +static void markeins_machine_power_off(void) +{ + printk("EMMA2RH Mark-eins halted. Please turn off the power.\n"); + markeins_led("poweroff."); + while (1) ; +} + +static unsigned long clock[4] = { 166500000, 187312500, 199800000, 210600000 }; + +static unsigned int __init detect_bus_frequency(unsigned long rtc_base) +{ + u32 reg; + + /* detect from boot strap */ + reg = emma2rh_in32(EMMA2RH_BHIF_STRAP_0); + reg = (reg >> 4) & 0x3; + return clock[reg]; +} + +static void __init emma2rh_time_init(void) +{ + u32 reg; + if (bus_frequency == 0) + bus_frequency = detect_bus_frequency(0); + + reg = emma2rh_in32(EMMA2RH_BHIF_STRAP_0); + if ((reg & 0x3) == 0) + reg = (reg >> 6) & 0x3; + else { + reg = emma2rh_in32(EMMA2RH_BHIF_MAIN_CTRL); + reg = (reg >> 4) & 0x3; + } + mips_hpt_frequency = (bus_frequency * (4 + reg)) / 4 / 2; +} + +void __init plat_timer_setup(struct irqaction *irq) +{ + /* we are using the cpu counter for timer interrupts */ + setup_irq(CPU_IRQ_BASE + 7, irq); +} + +static void markeins_board_init(void); +extern void markeins_irq_setup(void); + +static void inline __init markeins_sio_setup(void) +{ +#ifdef CONFIG_KGDB_8250 + struct uart_port emma_port; + + memset(&emma_port, 0, sizeof(emma_port)); + + emma_port.flags = + UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; + emma_port.iotype = UPIO_MEM; + emma_port.regshift = 4; /* I/O addresses are every 8 bytes */ + emma_port.uartclk = 18544000; /* Clock rate of the chip */ + + emma_port.line = 0; + emma_port.mapbase = KSEG1ADDR(EMMA2RH_PFUR0_BASE + 3); + emma_port.membase = (u8*)emma_port.mapbase; + early_serial_setup(&emma_port); + + emma_port.line = 1; + emma_port.mapbase = KSEG1ADDR(EMMA2RH_PFUR1_BASE + 3); + emma_port.membase = (u8*)emma_port.mapbase; + early_serial_setup(&emma_port); + + emma_port.irq = EMMA2RH_IRQ_PFUR1; + kgdb8250_add_port(1, &emma_port); +#endif +} + +void __init plat_mem_setup(void) +{ + /* initialize board - we don't trust the loader */ + markeins_board_init(); + + set_io_port_base(KSEG1ADDR(EMMA2RH_PCI_IO_BASE)); + + board_time_init = emma2rh_time_init; + + _machine_restart = markeins_machine_restart; + _machine_halt = markeins_machine_halt; + pm_power_off = markeins_machine_power_off; + + /* setup resource limits */ + ioport_resource.start = EMMA2RH_PCI_IO_BASE; + ioport_resource.end = EMMA2RH_PCI_IO_BASE + EMMA2RH_PCI_IO_SIZE - 1; + iomem_resource.start = EMMA2RH_IO_BASE; + iomem_resource.end = EMMA2RH_ROM_BASE - 1; + + /* Reboot on panic */ + panic_timeout = 180; + + markeins_sio_setup(); +} + +static void __init markeins_board_init(void) +{ + u32 val; + + val = emma2rh_in32(EMMA2RH_PBRD_INT_EN); /* open serial interrupts. */ + emma2rh_out32(EMMA2RH_PBRD_INT_EN, val | 0xaa); + val = emma2rh_in32(EMMA2RH_PBRD_CLKSEL); /* set serial clocks. */ + emma2rh_out32(EMMA2RH_PBRD_CLKSEL, val | 0x5); /* 18MHz */ + emma2rh_out32(EMMA2RH_PCI_CONTROL, 0); + + markeins_led("MVL E2RH"); +} diff --git a/arch/mips/gt64120/wrppmc/Makefile b/arch/mips/gt64120/wrppmc/Makefile new file mode 100644 index 000000000..7cf522055 --- /dev/null +++ b/arch/mips/gt64120/wrppmc/Makefile @@ -0,0 +1,14 @@ +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright 2006 Wind River System, Inc. +# Author: Rongkai.Zhan <rongkai.zhan@windriver.com> +# +# Makefile for the Wind River MIPS 4KC PPMC Eval Board +# + +obj-y += irq.o reset.o setup.o time.o pci.o + +EXTRA_AFLAGS := $(CFLAGS) diff --git a/arch/mips/gt64120/wrppmc/irq.c b/arch/mips/gt64120/wrppmc/irq.c new file mode 100644 index 000000000..8d75a43ce --- /dev/null +++ b/arch/mips/gt64120/wrppmc/irq.c @@ -0,0 +1,69 @@ +/* + * irq.c: GT64120 Interrupt Controller + * + * Copyright (C) 2006, Wind River System Inc. + * Author: Rongkai.Zhan, <rongkai.zhan@windriver.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel_stat.h> +#include <linux/module.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/timex.h> +#include <linux/slab.h> +#include <linux/random.h> +#include <linux/bitops.h> +#include <asm/bootinfo.h> +#include <asm/io.h> +#include <asm/bitops.h> +#include <asm/mipsregs.h> +#include <asm/system.h> +#include <asm/irq_cpu.h> +#include <asm/gt64120.h> + +asmlinkage void plat_irq_dispatch(struct pt_regs *regs) +{ + unsigned int pending = read_c0_status() & read_c0_cause(); + + if (pending & STATUSF_IP7) + do_IRQ(WRPPMC_MIPS_TIMER_IRQ, regs); /* CPU Compare/Count internal timer */ + else if (pending & STATUSF_IP6) + do_IRQ(WRPPMC_UART16550_IRQ, regs); /* UART 16550 port */ + else if (pending & STATUSF_IP3) + do_IRQ(WRPPMC_PCI_INTA_IRQ, regs); /* PCI INT_A */ + else + spurious_interrupt(regs); +} + +/** + * Initialize GT64120 Interrupt Controller + */ +void gt64120_init_pic(void) +{ + /* clear CPU Interrupt Cause Registers */ + GT_WRITE(GT_INTRCAUSE_OFS, (0x1F << 21)); + GT_WRITE(GT_HINTRCAUSE_OFS, 0x00); + + /* Disable all interrupts from GT64120 bridge chip */ + GT_WRITE(GT_INTRMASK_OFS, 0x00); + GT_WRITE(GT_HINTRMASK_OFS, 0x00); + GT_WRITE(GT_PCI0_ICMASK_OFS, 0x00); + GT_WRITE(GT_PCI0_HICMASK_OFS, 0x00); +} + +void __init arch_init_irq(void) +{ + /* IRQ 0 - 7 are for MIPS common irq_cpu controller */ + mips_cpu_irq_init(0); + + gt64120_init_pic(); +} diff --git a/arch/mips/gt64120/wrppmc/pci.c b/arch/mips/gt64120/wrppmc/pci.c new file mode 100644 index 000000000..2fbe93467 --- /dev/null +++ b/arch/mips/gt64120/wrppmc/pci.c @@ -0,0 +1,53 @@ +/* + * pci.c: GT64120 PCI support. + * + * Copyright (C) 2006, Wind River System Inc. Rongkai.Zhan <rongkai.zhan@windriver.com> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/init.h> +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/kernel.h> +#include <asm/gt64120.h> + +extern struct pci_ops gt64120_pci_ops; + +static struct resource pci0_io_resource = { + .name = "pci_0 io", + .start = GT_PCI_IO_BASE, + .end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1, + .flags = IORESOURCE_IO, +}; + +static struct resource pci0_mem_resource = { + .name = "pci_0 memory", + .start = GT_PCI_MEM_BASE, + .end = GT_PCI_MEM_BASE + GT_PCI_MEM_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct pci_controller hose_0 = { + .pci_ops = >64120_pci_ops, + .io_resource = &pci0_io_resource, + .mem_resource = &pci0_mem_resource, +}; + +static int __init gt64120_pci_init(void) +{ + u32 tmp; + + tmp = GT_READ(GT_PCI0_CMD_OFS); /* Huh??? -- Ralf */ + tmp = GT_READ(GT_PCI0_BARE_OFS); + + /* reset the whole PCI I/O space range */ + ioport_resource.start = GT_PCI_IO_BASE; + ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1; + + register_pci_controller(&hose_0); + return 0; +} + +arch_initcall(gt64120_pci_init); diff --git a/arch/mips/gt64120/wrppmc/reset.c b/arch/mips/gt64120/wrppmc/reset.c new file mode 100644 index 000000000..b97039c6d --- /dev/null +++ b/arch/mips/gt64120/wrppmc/reset.c @@ -0,0 +1,50 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1997 Ralf Baechle + */ +#include <linux/sched.h> +#include <linux/mm.h> +#include <asm/io.h> +#include <asm/pgtable.h> +#include <asm/processor.h> +#include <asm/reboot.h> +#include <asm/system.h> +#include <asm/cacheflush.h> + +void wrppmc_machine_restart(char *command) +{ + /* + * Ouch, we're still alive ... This time we take the silver bullet ... + * ... and find that we leave the hardware in a state in which the + * kernel in the flush locks up somewhen during of after the PCI + * detection stuff. + */ + local_irq_disable(); + set_c0_status(ST0_BEV | ST0_ERL); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_c0_wired(0); + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); +} + +void wrppmc_machine_halt(void) +{ + local_irq_disable(); + + printk(KERN_NOTICE "You can safely turn off the power\n"); + while (1) { + __asm__( + ".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0" + ); + } +} + +void wrppmc_machine_power_off(void) +{ + wrppmc_machine_halt(); +} diff --git a/arch/mips/gt64120/wrppmc/setup.c b/arch/mips/gt64120/wrppmc/setup.c new file mode 100644 index 000000000..429afc400 --- /dev/null +++ b/arch/mips/gt64120/wrppmc/setup.c @@ -0,0 +1,170 @@ +/* + * setup.c: Setup pointers to hardware dependent routines. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2006, Wind River System Inc. Rongkai.zhan <rongkai.zhan@windriver.com> + */ +#include <linux/init.h> +#include <linux/string.h> +#include <linux/kernel.h> +#include <linux/tty.h> +#include <linux/serial.h> +#include <linux/serial_core.h> +#include <linux/pm.h> + +#include <asm/io.h> +#include <asm/bootinfo.h> +#include <asm/reboot.h> +#include <asm/time.h> +#include <asm/gt64120.h> + +unsigned long gt64120_base = KSEG1ADDR(0x14000000); + +#ifdef WRPPMC_EARLY_DEBUG + +static volatile unsigned char * wrppmc_led = \ + (volatile unsigned char *)KSEG1ADDR(WRPPMC_LED_BASE); + +/* + * PPMC LED control register: + * -) bit[0] controls DS1 LED (1 - OFF, 0 - ON) + * -) bit[1] controls DS2 LED (1 - OFF, 0 - ON) + * -) bit[2] controls DS4 LED (1 - OFF, 0 - ON) + */ +void wrppmc_led_on(int mask) +{ + unsigned char value = *wrppmc_led; + + value &= (0xF8 | mask); + *wrppmc_led = value; +} + +/* If mask = 0, turn off all LEDs */ +void wrppmc_led_off(int mask) +{ + unsigned char value = *wrppmc_led; + + value |= (0x7 & mask); + *wrppmc_led = value; +} + +/* + * We assume that bootloader has initialized UART16550 correctly + */ +void __init wrppmc_early_putc(char ch) +{ + static volatile unsigned char *wrppmc_uart = \ + (volatile unsigned char *)KSEG1ADDR(WRPPMC_UART16550_BASE); + unsigned char value; + + /* Wait until Transmit-Holding-Register is empty */ + while (1) { + value = *(wrppmc_uart + 5); + if (value & 0x20) + break; + } + + *wrppmc_uart = ch; +} + +void __init wrppmc_early_printk(const char *fmt, ...) +{ + static char pbuf[256] = {'\0', }; + char *ch = pbuf; + va_list args; + unsigned int i; + + memset(pbuf, 0, 256); + va_start(args, fmt); + i = vsprintf(pbuf, fmt, args); + va_end(args); + + /* Print the string */ + while (*ch != '\0') { + wrppmc_early_putc(*ch); + /* if print '\n', also print '\r' */ + if (*ch++ == '\n') + wrppmc_early_putc('\r'); + } +} +#endif /* WRPPMC_EARLY_DEBUG */ + +unsigned long __init prom_free_prom_memory(void) +{ + return 0; +} + +#ifdef CONFIG_SERIAL_8250 +static void wrppmc_setup_serial(void) +{ + struct uart_port up; + + memset(&up, 0x00, sizeof(struct uart_port)); + + /* + * A note about mapbase/membase + * -) mapbase is the physical address of the IO port. + * -) membase is an 'ioremapped' cookie. + */ + up.line = 0; + up.type = PORT_16550; + up.iotype = UPIO_MEM; + up.mapbase = WRPPMC_UART16550_BASE; + up.membase = ioremap(up.mapbase, 8); + up.irq = WRPPMC_UART16550_IRQ; + up.uartclk = WRPPMC_UART16550_CLOCK; + up.flags = UPF_SKIP_TEST/* | UPF_BOOT_AUTOCONF */; + up.regshift = 0; + + early_serial_setup(&up); +} +#endif + +void __init plat_mem_setup(void) +{ + extern void wrppmc_time_init(void); + extern void wrppmc_machine_restart(char *command); + extern void wrppmc_machine_halt(void); + extern void wrppmc_machine_power_off(void); + + _machine_restart = wrppmc_machine_restart; + _machine_halt = wrppmc_machine_halt; + pm_power_off = wrppmc_machine_power_off; + + /* Use MIPS Count/Compare Timer */ + board_time_init = wrppmc_time_init; + + /* This makes the operations of 'in/out[bwl]' to the + * physical address ( < KSEG0) can work via KSEG1 + */ + set_io_port_base(KSEG1); + +#ifdef CONFIG_SERIAL_8250 + wrppmc_setup_serial(); +#endif +} + +const char *get_system_type(void) +{ + return "Wind River PPMC (GT64120)"; +} + +/* + * Initializes basic routines and structures pointers, memory size (as + * given by the bios and saves the command line. + */ +void __init prom_init(void) +{ + mips_machgroup = MACH_GROUP_GALILEO; + mips_machtype = MACH_EV64120A; + + add_memory_region(WRPPMC_SDRAM_SCS0_BASE, WRPPMC_SDRAM_SCS0_SIZE, BOOT_MEM_RAM); + add_memory_region(WRPPMC_BOOTROM_BASE, WRPPMC_BOOTROM_SIZE, BOOT_MEM_ROM_DATA); + + wrppmc_early_printk("prom_init: GT64120 SDRAM Bank 0: 0x%x - 0x%08lx\n", + WRPPMC_SDRAM_SCS0_BASE, (WRPPMC_SDRAM_SCS0_BASE + WRPPMC_SDRAM_SCS0_SIZE)); +} diff --git a/arch/mips/gt64120/wrppmc/time.c b/arch/mips/gt64120/wrppmc/time.c new file mode 100644 index 000000000..5b440859b --- /dev/null +++ b/arch/mips/gt64120/wrppmc/time.c @@ -0,0 +1,52 @@ +/* + * time.c: MIPS CPU Count/Compare timer hookup + * + * Author: Mark.Zhan, <rongkai.zhan@windriver.com> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 2006, Wind River System Inc. + */ +#include <linux/init.h> +#include <linux/string.h> +#include <linux/kernel.h> +#include <linux/param.h> /* for HZ */ +#include <linux/irq.h> +#include <linux/timex.h> +#include <linux/interrupt.h> + +#include <asm/reboot.h> +#include <asm/time.h> +#include <asm/io.h> +#include <asm/bootinfo.h> +#include <asm/gt64120.h> + +#define WRPPMC_CPU_CLK_FREQ 40000000 /* 40MHZ */ + +void __init plat_timer_setup(struct irqaction *irq) +{ + /* Install ISR for timer interrupt */ + setup_irq(WRPPMC_MIPS_TIMER_IRQ, irq); +} + +/* + * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect + * + * NOTE: We disable all GT64120 timers, and use MIPS processor internal + * timer as the source of kernel clock tick. + */ +void __init wrppmc_time_init(void) +{ + /* Disable GT64120 timers */ + GT_WRITE(GT_TC_CONTROL_OFS, 0x00); + GT_WRITE(GT_TC0_OFS, 0x00); + GT_WRITE(GT_TC1_OFS, 0x00); + GT_WRITE(GT_TC2_OFS, 0x00); + GT_WRITE(GT_TC3_OFS, 0x00); + + /* Use MIPS compare/count internal timer */ + mips_hpt_frequency = WRPPMC_CPU_CLK_FREQ; +} diff --git a/arch/mips/kernel/apm.c b/arch/mips/kernel/apm.c new file mode 100644 index 000000000..528e73104 --- /dev/null +++ b/arch/mips/kernel/apm.c @@ -0,0 +1,604 @@ +/* + * bios-less APM driver for MIPS Linux + * Jamey Hicks <jamey@crl.dec.com> + * adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com) + * + * APM 1.2 Reference: + * Intel Corporation, Microsoft Corporation. Advanced Power Management + * (APM) BIOS Interface Specification, Revision 1.2, February 1996. + * + * [This document is available from Microsoft at: + * http://www.microsoft.com/hwdev/busbios/amp_12.htm] + */ +#include <linux/module.h> +#include <linux/poll.h> +#include <linux/timer.h> +#include <linux/slab.h> +#include <linux/proc_fs.h> +#include <linux/miscdevice.h> +#include <linux/apm_bios.h> +#include <linux/capability.h> +#include <linux/sched.h> +#include <linux/pm.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/init.h> +#include <linux/completion.h> + +#include <asm/apm.h> /* apm_power_info */ +#include <asm/system.h> + +/* + * The apm_bios device is one of the misc char devices. + * This is its minor number. + */ +#define APM_MINOR_DEV 134 + +/* + * See Documentation/Config.help for the configuration options. + * + * Various options can be changed at boot time as follows: + * (We allow underscores for compatibility with the modules code) + * apm=on/off enable/disable APM + */ + +/* + * Maximum number of events stored + */ +#define APM_MAX_EVENTS 16 + +struct apm_queue { + unsigned int event_head; + unsigned int event_tail; + apm_event_t events[APM_MAX_EVENTS]; +}; + +/* + * The per-file APM data + */ +struct apm_user { + struct list_head list; + + unsigned int suser: 1; + unsigned int writer: 1; + unsigned int reader: 1; + + int suspend_result; + unsigned int suspend_state; +#define SUSPEND_NONE 0 /* no suspend pending */ +#define SUSPEND_PENDING 1 /* suspend pending read */ +#define SUSPEND_READ 2 /* suspend read, pending ack */ +#define SUSPEND_ACKED 3 /* suspend acked */ +#define SUSPEND_DONE 4 /* suspend completed */ + + struct apm_queue queue; +}; + +/* + * Local variables + */ +static int suspends_pending; +static int apm_disabled; +static int mips_apm_active; + +static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); +static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); + +/* + * This is a list of everyone who has opened /dev/apm_bios + */ +static DECLARE_RWSEM(user_list_lock); +static LIST_HEAD(apm_user_list); + +/* + * kapmd info. kapmd provides us a process context to handle + * "APM" events within - specifically necessary if we're going + * to be suspending the system. + */ +static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait); +static DECLARE_COMPLETION(kapmd_exit); +static DEFINE_SPINLOCK(kapmd_queue_lock); +static struct apm_queue kapmd_queue; + + +static const char driver_version[] = "1.13"; /* no spaces */ + + + +/* + * Compatibility cruft until the IPAQ people move over to the new + * interface. + */ +static void __apm_get_power_status(struct apm_power_info *info) +{ +} + +/* + * This allows machines to provide their own "apm get power status" function. + */ +void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status; +EXPORT_SYMBOL(apm_get_power_status); + + +/* + * APM event queue management. + */ +static inline int queue_empty(struct apm_queue *q) +{ + return q->event_head == q->event_tail; +} + +static inline apm_event_t queue_get_event(struct apm_queue *q) +{ + q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS; + return q->events[q->event_tail]; +} + +static void queue_add_event(struct apm_queue *q, apm_event_t event) +{ + q->event_head = (q->event_head + 1) % APM_MAX_EVENTS; + if (q->event_head == q->event_tail) { + static int notified; + + if (notified++ == 0) + printk(KERN_ERR "apm: an event queue overflowed\n"); + q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS; + } + q->events[q->event_head] = event; +} + +static void queue_event_one_user(struct apm_user *as, apm_event_t event) +{ + if (as->suser && as->writer) { + switch (event) { + case APM_SYS_SUSPEND: + case APM_USER_SUSPEND: + /* + * If this user already has a suspend pending, + * don't queue another one. + */ + if (as->suspend_state != SUSPEND_NONE) + return; + + as->suspend_state = SUSPEND_PENDING; + suspends_pending++; + break; + } + } + queue_add_event(&as->queue, event); +} + +static void queue_event(apm_event_t event, struct apm_user *sender) +{ + struct apm_user *as; + + down_read(&user_list_lock); + list_for_each_entry(as, &apm_user_list, list) { + if (as != sender && as->reader) + queue_event_one_user(as, event); + } + up_read(&user_list_lock); + wake_up_interruptible(&apm_waitqueue); +} + +static void apm_suspend(void) +{ + struct apm_user *as; + int err = pm_suspend(PM_SUSPEND_MEM); + + /* + * Anyone on the APM queues will think we're still suspended. + * Send a message so everyone knows we're now awake again. + */ + queue_event(APM_NORMAL_RESUME, NULL); + + /* + * Finally, wake up anyone who is sleeping on the suspend. + */ + down_read(&user_list_lock); + list_for_each_entry(as, &apm_user_list, list) { + as->suspend_result = err; + as->suspend_state = SUSPEND_DONE; + } + up_read(&user_list_lock); + + wake_up(&apm_suspend_waitqueue); +} + +static ssize_t apm_read(struct file *fp, char __user *buf, size_t count, loff_t *ppos) +{ + struct apm_user *as = fp->private_data; + apm_event_t event; + int i = count, ret = 0; + + if (count < sizeof(apm_event_t)) + return -EINVAL; + + if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK) + return -EAGAIN; + + wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue)); + + while ((i >= sizeof(event)) && !queue_empty(&as->queue)) { + event = queue_get_event(&as->queue); + + ret = -EFAULT; + if (copy_to_user(buf, &event, sizeof(event))) + break; + + if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND) + as->suspend_state = SUSPEND_READ; + + buf += sizeof(event); + i -= sizeof(event); + } + + if (i < count) + ret = count - i; + + return ret; +} + +static unsigned int apm_poll(struct file *fp, poll_table * wait) +{ + struct apm_user *as = fp->private_data; + + poll_wait(fp, &apm_waitqueue, wait); + return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM; +} + +/* + * apm_ioctl - handle APM ioctl + * + * APM_IOC_SUSPEND + * This IOCTL is overloaded, and performs two functions. It is used to: + * - initiate a suspend + * - acknowledge a suspend read from /dev/apm_bios. + * Only when everyone who has opened /dev/apm_bios with write permission + * has acknowledge does the actual suspend happen. + */ +static int +apm_ioctl(struct inode * inode, struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct apm_user *as = filp->private_data; + unsigned long flags; + int err = -EINVAL; + + if (!as->suser || !as->writer) + return -EPERM; + + switch (cmd) { + case APM_IOC_SUSPEND: + as->suspend_result = -EINTR; + + if (as->suspend_state == SUSPEND_READ) { + /* + * If we read a suspend command from /dev/apm_bios, + * then the corresponding APM_IOC_SUSPEND ioctl is + * interpreted as an acknowledge. + */ + as->suspend_state = SUSPEND_ACKED; + suspends_pending--; + } else { + /* + * Otherwise it is a request to suspend the system. + * Queue an event for all readers, and expect an + * acknowledge from all writers who haven't already + * acknowledged. + */ + queue_event(APM_USER_SUSPEND, as); + } + + /* + * If there are no further acknowledges required, suspend + * the system. + */ + if (suspends_pending == 0) + apm_suspend(); + + /* + * Wait for the suspend/resume to complete. If there are + * pending acknowledges, we wait here for them. + * + * Note that we need to ensure that the PM subsystem does + * not kick us out of the wait when it suspends the threads. + */ + flags = current->flags; + current->flags |= PF_NOFREEZE; + + /* + * Note: do not allow a thread which is acking the suspend + * to escape until the resume is complete. + */ + if (as->suspend_state == SUSPEND_ACKED) + wait_event(apm_suspend_waitqueue, + as->suspend_state == SUSPEND_DONE); + else + wait_event_interruptible(apm_suspend_waitqueue, + as->suspend_state == SUSPEND_DONE); + + current->flags = flags; + err = as->suspend_result; + as->suspend_state = SUSPEND_NONE; + break; + } + + return err; +} + +static int apm_release(struct inode * inode, struct file * filp) +{ + struct apm_user *as = filp->private_data; + filp->private_data = NULL; + + down_write(&user_list_lock); + list_del(&as->list); + up_write(&user_list_lock); + + /* + * We are now unhooked from the chain. As far as new + * events are concerned, we no longer exist. However, we + * need to balance suspends_pending, which means the + * possibility of sleeping. + */ + if (as->suspend_state != SUSPEND_NONE) { + suspends_pending -= 1; + if (suspends_pending == 0) + apm_suspend(); + } + + kfree(as); + return 0; +} + +static int apm_open(struct inode * inode, struct file * filp) +{ + struct apm_user *as; + + as = (struct apm_user *)kzalloc(sizeof(*as), GFP_KERNEL); + if (as) { + /* + * XXX - this is a tiny bit broken, when we consider BSD + * process accounting. If the device is opened by root, we + * instantly flag that we used superuser privs. Who knows, + * we might close the device immediately without doing a + * privileged operation -- cevans + */ + as->suser = capable(CAP_SYS_ADMIN); + as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE; + as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ; + + down_write(&user_list_lock); + list_add(&as->list, &apm_user_list); + up_write(&user_list_lock); + + filp->private_data = as; + } + + return as ? 0 : -ENOMEM; +} + +static struct file_operations apm_bios_fops = { + .owner = THIS_MODULE, + .read = apm_read, + .poll = apm_poll, + .ioctl = apm_ioctl, + .open = apm_open, + .release = apm_release, +}; + +static struct miscdevice apm_device = { + .minor = APM_MINOR_DEV, + .name = "apm_bios", + .fops = &apm_bios_fops +}; + + +#ifdef CONFIG_PROC_FS +/* + * Arguments, with symbols from linux/apm_bios.h. + * + * 0) Linux driver version (this will change if format changes) + * 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2. + * 2) APM flags from APM Installation Check (0x00): + * bit 0: APM_16_BIT_SUPPORT + * bit 1: APM_32_BIT_SUPPORT + * bit 2: APM_IDLE_SLOWS_CLOCK + * bit 3: APM_BIOS_DISABLED + * bit 4: APM_BIOS_DISENGAGED + * 3) AC line status + * 0x00: Off-line + * 0x01: On-line + * 0x02: On backup power (BIOS >= 1.1 only) + * 0xff: Unknown + * 4) Battery status + * 0x00: High + * 0x01: Low + * 0x02: Critical + * 0x03: Charging + * 0x04: Selected battery not present (BIOS >= 1.2 only) + * 0xff: Unknown + * 5) Battery flag + * bit 0: High + * bit 1: Low + * bit 2: Critical + * bit 3: Charging + * bit 7: No system battery + * 0xff: Unknown + * 6) Remaining battery life (percentage of charge): + * 0-100: valid + * -1: Unknown + * 7) Remaining battery life (time units): + * Number of remaining minutes or seconds + * -1: Unknown + * 8) min = minutes; sec = seconds + */ +static int apm_get_info(char *buf, char **start, off_t fpos, int length) +{ + struct apm_power_info info; + char *units; + int ret; + + info.ac_line_status = 0xff; + info.battery_status = 0xff; + info.battery_flag = 0xff; + info.battery_life = -1; + info.time = -1; + info.units = -1; + + if (apm_get_power_status) + apm_get_power_status(&info); + + switch (info.units) { + default: units = "?"; break; + case 0: units = "min"; break; + case 1: units = "sec"; break; + } + + ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n", + driver_version, APM_32_BIT_SUPPORT, + info.ac_line_status, info.battery_status, + info.battery_flag, info.battery_life, + info.time, units); + + return ret; +} +#endif + +static int kapmd(void *arg) +{ + daemonize("kapmd"); + current->flags |= PF_NOFREEZE; + + do { + apm_event_t event; + + wait_event_interruptible(kapmd_wait, + !queue_empty(&kapmd_queue) || !mips_apm_active); + + if (!mips_apm_active) + break; + + spin_lock_irq(&kapmd_queue_lock); + event = 0; + if (!queue_empty(&kapmd_queue)) + event = queue_get_event(&kapmd_queue); + spin_unlock_irq(&kapmd_queue_lock); + + switch (event) { + case 0: + break; + + case APM_LOW_BATTERY: + case APM_POWER_STATUS_CHANGE: + queue_event(event, NULL); + break; + + case APM_USER_SUSPEND: + case APM_SYS_SUSPEND: + queue_event(event, NULL); + if (suspends_pending == 0) + apm_suspend(); + break; + + case APM_CRITICAL_SUSPEND: + apm_suspend(); + break; + } + } while (1); + + complete_and_exit(&kapmd_exit, 0); +} + +static int __init apm_init(void) +{ + int ret; + + if (apm_disabled) { + printk(KERN_NOTICE "apm: disabled on user request.\n"); + return -ENODEV; + } + + mips_apm_active = 1; + + ret = kernel_thread(kapmd, NULL, CLONE_KERNEL); + if (ret < 0) { + mips_apm_active = 0; + return ret; + } + +#ifdef CONFIG_PROC_FS + create_proc_info_entry("apm", 0, NULL, apm_get_info); +#endif + + ret = misc_register(&apm_device); + if (ret != 0) { + remove_proc_entry("apm", NULL); + + mips_apm_active = 0; + wake_up(&kapmd_wait); + wait_for_completion(&kapmd_exit); + } + + return ret; +} + +static void __exit apm_exit(void) +{ + misc_deregister(&apm_device); + remove_proc_entry("apm", NULL); + + mips_apm_active = 0; + wake_up(&kapmd_wait); + wait_for_completion(&kapmd_exit); +} + +module_init(apm_init); +module_exit(apm_exit); + +MODULE_AUTHOR("Stephen Rothwell"); +MODULE_DESCRIPTION("Advanced Power Management"); +MODULE_LICENSE("GPL"); + +#ifndef MODULE +static int __init apm_setup(char *str) +{ + while ((str != NULL) && (*str != '\0')) { + if (strncmp(str, "off", 3) == 0) + apm_disabled = 1; + if (strncmp(str, "on", 2) == 0) + apm_disabled = 0; + str = strchr(str, ','); + if (str != NULL) + str += strspn(str, ", \t"); + } + return 1; +} + +__setup("apm=", apm_setup); +#endif + +/** + * apm_queue_event - queue an APM event for kapmd + * @event: APM event + * + * Queue an APM event for kapmd to process and ultimately take the + * appropriate action. Only a subset of events are handled: + * %APM_LOW_BATTERY + * %APM_POWER_STATUS_CHANGE + * %APM_USER_SUSPEND + * %APM_SYS_SUSPEND + * %APM_CRITICAL_SUSPEND + */ +void apm_queue_event(apm_event_t event) +{ + unsigned long flags; + + spin_lock_irqsave(&kapmd_queue_lock, flags); + queue_add_event(&kapmd_queue, event); + spin_unlock_irqrestore(&kapmd_queue_lock, flags); + + wake_up_interruptible(&kapmd_wait); +} +EXPORT_SYMBOL(apm_queue_event); diff --git a/arch/mips/lib/ashldi3.c b/arch/mips/lib/ashldi3.c new file mode 100644 index 000000000..beb80f316 --- /dev/null +++ b/arch/mips/lib/ashldi3.c @@ -0,0 +1,29 @@ +#include <linux/module.h> + +#include "libgcc.h" + +long long __ashldi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + w.s.low = 0; + w.s.high = (unsigned int) uu.s.low << -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.low >> bm; + + w.s.low = (unsigned int) uu.s.low << b; + w.s.high = ((unsigned int) uu.s.high << b) | carries; + } + + return w.ll; +} + +EXPORT_SYMBOL(__ashldi3); diff --git a/arch/mips/lib/ashrdi3.c b/arch/mips/lib/ashrdi3.c new file mode 100644 index 000000000..c884a912b --- /dev/null +++ b/arch/mips/lib/ashrdi3.c @@ -0,0 +1,31 @@ +#include <linux/module.h> + +#include "libgcc.h" + +long long __ashrdi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + /* w.s.high = 1..1 or 0..0 */ + w.s.high = + uu.s.high >> 31; + w.s.low = uu.s.high >> -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.high << bm; + + w.s.high = uu.s.high >> b; + w.s.low = ((unsigned int) uu.s.low >> b) | carries; + } + + return w.ll; +} + +EXPORT_SYMBOL(__ashrdi3); diff --git a/arch/mips/lib/libgcc.h b/arch/mips/lib/libgcc.h new file mode 100644 index 000000000..3f19d1c5d --- /dev/null +++ b/arch/mips/lib/libgcc.h @@ -0,0 +1,26 @@ +#ifndef __ASM_LIBGCC_H +#define __ASM_LIBGCC_H + +#include <asm/byteorder.h> + +typedef int word_type __attribute__ ((mode (__word__))); + +#ifdef __BIG_ENDIAN +struct DWstruct { + int high, low; +}; +#elif defined(__LITTLE_ENDIAN) +struct DWstruct { + int low, high; +}; +#else +#error I feel sick. +#endif + +typedef union +{ + struct DWstruct s; + long long ll; +} DWunion; + +#endif /* __ASM_LIBGCC_H */ diff --git a/arch/mips/lib/lshrdi3.c b/arch/mips/lib/lshrdi3.c new file mode 100644 index 000000000..dcf8d6810 --- /dev/null +++ b/arch/mips/lib/lshrdi3.c @@ -0,0 +1,29 @@ +#include <linux/module.h> + +#include "libgcc.h" + +long long __lshrdi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + w.s.high = 0; + w.s.low = (unsigned int) uu.s.high >> -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.high << bm; + + w.s.high = (unsigned int) uu.s.high >> b; + w.s.low = ((unsigned int) uu.s.low >> b) | carries; + } + + return w.ll; +} + +EXPORT_SYMBOL(__lshrdi3); diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c new file mode 100644 index 000000000..42b50964c --- /dev/null +++ b/arch/mips/mm/sc-mips.c @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2006 Chris Dearman (chris@mips.com), + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/mm.h> + +#include <asm/mipsregs.h> +#include <asm/bcache.h> +#include <asm/cacheops.h> +#include <asm/page.h> +#include <asm/pgtable.h> +#include <asm/system.h> +#include <asm/mmu_context.h> +#include <asm/r4kcache.h> + +/* + * MIPS32/MIPS64 L2 cache handling + */ + +/* + * Writeback and invalidate the secondary cache before DMA. + */ +static void mips_sc_wback_inv(unsigned long addr, unsigned long size) +{ + blast_scache_range(addr, addr + size); +} + +/* + * Invalidate the secondary cache before DMA. + */ +static void mips_sc_inv(unsigned long addr, unsigned long size) +{ + blast_inv_scache_range(addr, addr + size); +} + +static void mips_sc_enable(void) +{ + /* L2 cache is permanently enabled */ +} + +static void mips_sc_disable(void) +{ + /* L2 cache is permanently enabled */ +} + +static struct bcache_ops mips_sc_ops = { + .bc_enable = mips_sc_enable, + .bc_disable = mips_sc_disable, + .bc_wback_inv = mips_sc_wback_inv, + .bc_inv = mips_sc_inv +}; + +static inline int __init mips_sc_probe(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + unsigned int config1, config2; + unsigned int tmp; + + /* Mark as not present until probe completed */ + c->scache.flags |= MIPS_CACHE_NOT_PRESENT; + + /* Ignore anything but MIPSxx processors */ + if (c->isa_level != MIPS_CPU_ISA_M32R1 && + c->isa_level != MIPS_CPU_ISA_M32R2 && + c->isa_level != MIPS_CPU_ISA_M64R1 && + c->isa_level != MIPS_CPU_ISA_M64R2) + return 0; + + /* Does this MIPS32/MIPS64 CPU have a config2 register? */ + config1 = read_c0_config1(); + if (!(config1 & MIPS_CONF_M)) + return 0; + + config2 = read_c0_config2(); + tmp = (config2 >> 4) & 0x0f; + if (0 < tmp && tmp <= 7) + c->scache.linesz = 2 << tmp; + else + return 0; + + tmp = (config2 >> 8) & 0x0f; + if (0 <= tmp && tmp <= 7) + c->scache.sets = 64 << tmp; + else + return 0; + + tmp = (config2 >> 0) & 0x0f; + if (0 <= tmp && tmp <= 7) + c->scache.ways = tmp + 1; + else + return 0; + + c->scache.waysize = c->scache.sets * c->scache.linesz; + c->scache.waybit = __ffs(c->scache.waysize); + + c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT; + + return 1; +} + +int __init mips_sc_init(void) +{ + int found = mips_sc_probe (); + if (found) { + mips_sc_enable(); + bcops = &mips_sc_ops; + } + return found; +} + diff --git a/arch/mips/pci/fixup-emma2rh.c b/arch/mips/pci/fixup-emma2rh.c new file mode 100644 index 000000000..7abcfd175 --- /dev/null +++ b/arch/mips/pci/fixup-emma2rh.c @@ -0,0 +1,101 @@ +/* + * arch/mips/pci/fixup-emma2rh.c + * This file defines the PCI configration. + * + * Copyright (C) NEC Electronics Corporation 2004-2006 + * + * This file is based on the arch/mips/ddb5xxx/ddb5477/pci.c + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/pci.h> + +#include <asm/bootinfo.h> +#include <asm/debug.h> + +#include <asm/emma2rh/emma2rh.h> + +#define EMMA2RH_PCI_HOST_SLOT 0x09 +#define EMMA2RH_USB_SLOT 0x03 +#define PCI_DEVICE_ID_NEC_EMMA2RH 0x014b /* EMMA2RH PCI Host */ + +/* + * we fix up irqs based on the slot number. + * The first entry is at AD:11. + * Fortunately this works because, although we have two pci buses, + * they all have different slot numbers (except for rockhopper slot 20 + * which is handled below). + * + */ + +#define MAX_SLOT_NUM 10 +static unsigned char irq_map[][5] __initdata = { + [3] = {0, MARKEINS_PCI_IRQ_INTB, MARKEINS_PCI_IRQ_INTC, + MARKEINS_PCI_IRQ_INTD, 0,}, + [4] = {0, MARKEINS_PCI_IRQ_INTA, 0, 0, 0,}, + [5] = {0, 0, 0, 0, 0,}, + [6] = {0, MARKEINS_PCI_IRQ_INTC, MARKEINS_PCI_IRQ_INTD, + MARKEINS_PCI_IRQ_INTA, MARKEINS_PCI_IRQ_INTB,}, +}; + +static void __devinit nec_usb_controller_fixup(struct pci_dev *dev) +{ + if (PCI_SLOT(dev->devfn) == EMMA2RH_USB_SLOT) + /* on board USB controller configuration */ + pci_write_config_dword(dev, 0xe4, 1 << 5); +} + +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB, + nec_usb_controller_fixup); + +/* + * Prevent the PCI layer from seeing the resources allocated to this device + * if it is the host bridge by marking it as such. These resources are of + * no consequence to the PCI layer (they are handled elsewhere). + */ +static void __devinit emma2rh_pci_host_fixup(struct pci_dev *dev) +{ + int i; + + if (PCI_SLOT(dev->devfn) == EMMA2RH_PCI_HOST_SLOT) { + dev->class &= 0xff; + dev->class |= PCI_CLASS_BRIDGE_HOST << 8; + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + dev->resource[i].start = 0; + dev->resource[i].end = 0; + dev->resource[i].flags = 0; + } + } +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_EMMA2RH, + emma2rh_pci_host_fixup); + +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + return irq_map[slot][pin]; +} + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-excite.c b/arch/mips/pci/fixup-excite.c new file mode 100644 index 000000000..1da696d43 --- /dev/null +++ b/arch/mips/pci/fixup-excite.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2004 by Basler Vision Technologies AG + * Author: Thomas Koeller <thomas.koeller@baslerweb.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <excite.h> + +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + if (pin == 0) + return -1; + + return USB_IRQ; /* USB controller is the only PCI device */ +} + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-wrppmc.c b/arch/mips/pci/fixup-wrppmc.c new file mode 100644 index 000000000..3357c1300 --- /dev/null +++ b/arch/mips/pci/fixup-wrppmc.c @@ -0,0 +1,37 @@ +/* + * fixup-wrppmc.c: PPMC board specific PCI fixup + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2006, Wind River Inc. Rongkai.zhan (rongkai.zhan@windriver.com) + */ +#include <linux/init.h> +#include <linux/pci.h> +#include <asm/gt64120.h> + +/* PCI interrupt pins */ +#define PCI_INTA 1 +#define PCI_INTB 2 +#define PCI_INTC 3 +#define PCI_INTD 4 + +#define PCI_SLOT_MAXNR 32 /* Each PCI bus has 32 physical slots */ + +static char pci_irq_tab[PCI_SLOT_MAXNR][5] __initdata = { + /* 0 INTA INTB INTC INTD */ + [0] = {0, 0, 0, 0, 0}, /* Slot 0: GT64120 PCI bridge */ + [6] = {0, WRPPMC_PCI_INTA_IRQ, 0, 0, 0}, +}; + +int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + return pci_irq_tab[slot][pin]; +} + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/ops-bridge.c b/arch/mips/pci/ops-bridge.c new file mode 100644 index 000000000..1fa09929c --- /dev/null +++ b/arch/mips/pci/ops-bridge.c @@ -0,0 +1,306 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1999, 2000, 04, 06 Ralf Baechle (ralf@linux-mips.org) + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#include <linux/pci.h> +#include <asm/paccess.h> +#include <asm/pci/bridge.h> +#include <asm/sn/arch.h> +#include <asm/sn/intr.h> +#include <asm/sn/sn0/hub.h> + +/* + * The Bridge ASIC supports both type 0 and type 1 access. Type 1 is + * not really documented, so right now I can't write code which uses it. + * Therefore we use type 0 accesses for now even though they won't work + * correcly for PCI-to-PCI bridges. + * + * The function is complicated by the ultimate brokeness of the IOC3 chip + * which is used in SGI systems. The IOC3 can only handle 32-bit PCI + * accesses and does only decode parts of it's address space. + */ + +static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * value) +{ + struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); + bridge_t *bridge = bc->base; + int slot = PCI_SLOT(devfn); + int fn = PCI_FUNC(devfn); + volatile void *addr; + u32 cf, shift, mask; + int res; + + addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at it for real ... + */ + if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) + goto oh_my_gawd; + + addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; + + if (size == 1) + res = get_dbe(*value, (u8 *) addr); + else if (size == 2) + res = get_dbe(*value, (u16 *) addr); + else + res = get_dbe(*value, (u32 *) addr); + + return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; + +oh_my_gawd: + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at the wrong register. + */ + if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { + *value = 0; + return PCIBIOS_SUCCESSFUL; + } + + /* + * IOC3 is fucked fucked beyond believe ... Don't try to access + * anything but 32-bit words ... + */ + addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; + + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + shift = ((where & 3) << 3); + mask = (0xffffffffU >> ((4 - size) << 3)); + *value = (cf >> shift) & mask; + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * value) +{ + struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); + bridge_t *bridge = bc->base; + int busno = bus->number; + int slot = PCI_SLOT(devfn); + int fn = PCI_FUNC(devfn); + volatile void *addr; + u32 cf, shift, mask; + int res; + + bridge->b_pci_cfg = (busno << 16) | (slot << 11); + addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at it for real ... + */ + if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) + goto oh_my_gawd; + + bridge->b_pci_cfg = (busno << 16) | (slot << 11); + addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; + + if (size == 1) + res = get_dbe(*value, (u8 *) addr); + else if (size == 2) + res = get_dbe(*value, (u16 *) addr); + else + res = get_dbe(*value, (u32 *) addr); + + return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; + +oh_my_gawd: + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at the wrong register. + */ + if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { + *value = 0; + return PCIBIOS_SUCCESSFUL; + } + + /* + * IOC3 is fucked fucked beyond believe ... Don't try to access + * anything but 32-bit words ... + */ + bridge->b_pci_cfg = (busno << 16) | (slot << 11); + addr = &bridge->b_type1_cfg.c[(fn << 8) | where]; + + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + shift = ((where & 3) << 3); + mask = (0xffffffffU >> ((4 - size) << 3)); + *value = (cf >> shift) & mask; + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * value) +{ + if (bus->number > 0) + return pci_conf1_read_config(bus, devfn, where, size, value); + + return pci_conf0_read_config(bus, devfn, where, size, value); +} + +static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); + bridge_t *bridge = bc->base; + int slot = PCI_SLOT(devfn); + int fn = PCI_FUNC(devfn); + volatile void *addr; + u32 cf, shift, mask, smask; + int res; + + addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at it for real ... + */ + if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) + goto oh_my_gawd; + + addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; + + if (size == 1) { + res = put_dbe(value, (u8 *) addr); + } else if (size == 2) { + res = put_dbe(value, (u16 *) addr); + } else { + res = put_dbe(value, (u32 *) addr); + } + + if (res) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; + +oh_my_gawd: + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to touch the wrong register. + */ + if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) + return PCIBIOS_SUCCESSFUL; + + /* + * IOC3 is fucked fucked beyond believe ... Don't try to access + * anything but 32-bit words ... + */ + addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; + + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + shift = ((where & 3) << 3); + mask = (0xffffffffU >> ((4 - size) << 3)); + smask = mask << shift; + + cf = (cf & ~smask) | ((value & mask) << shift); + if (put_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); + bridge_t *bridge = bc->base; + int slot = PCI_SLOT(devfn); + int fn = PCI_FUNC(devfn); + int busno = bus->number; + volatile void *addr; + u32 cf, shift, mask, smask; + int res; + + bridge->b_pci_cfg = (busno << 16) | (slot << 11); + addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at it for real ... + */ + if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) + goto oh_my_gawd; + + addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; + + if (size == 1) { + res = put_dbe(value, (u8 *) addr); + } else if (size == 2) { + res = put_dbe(value, (u16 *) addr); + } else { + res = put_dbe(value, (u32 *) addr); + } + + if (res) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; + +oh_my_gawd: + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to touch the wrong register. + */ + if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) + return PCIBIOS_SUCCESSFUL; + + /* + * IOC3 is fucked fucked beyond believe ... Don't try to access + * anything but 32-bit words ... + */ + addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; + + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + shift = ((where & 3) << 3); + mask = (0xffffffffU >> ((4 - size) << 3)); + smask = mask << shift; + + cf = (cf & ~smask) | ((value & mask) << shift); + if (put_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + if (bus->number > 0) + return pci_conf1_write_config(bus, devfn, where, size, value); + + return pci_conf0_write_config(bus, devfn, where, size, value); +} + +struct pci_ops bridge_pci_ops = { + .read = pci_read_config, + .write = pci_write_config, +}; diff --git a/arch/mips/pci/ops-emma2rh.c b/arch/mips/pci/ops-emma2rh.c new file mode 100644 index 000000000..38f181625 --- /dev/null +++ b/arch/mips/pci/ops-emma2rh.c @@ -0,0 +1,185 @@ +/* + * arch/mips/pci/ops-emma2rh.c + * This file defines the PCI operation for EMMA2RH. + * + * Copyright (C) NEC Electronics Corporation 2004-2006 + * + * This file is based on the arch/mips/pci/ops-vr41xx.c + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/types.h> + +#include <asm/addrspace.h> +#include <asm/debug.h> + +#include <asm/emma2rh/emma2rh.h> + +#define RTABORT (0x1<<9) +#define RMABORT (0x1<<10) +#define EMMA2RH_PCI_SLOT_NUM 9 /* 0000:09.0 is final PCI device */ + +/* + * access config space + */ + +static int check_args(struct pci_bus *bus, u32 devfn, u32 * bus_num) +{ + /* check if the bus is top-level */ + if (bus->parent != NULL) { + *bus_num = bus->number; + db_assert(bus_num != 0); + } else + *bus_num = 0; + + if (*bus_num == 0) { + /* Type 0 */ + if (PCI_SLOT(devfn) >= 10) + return PCIBIOS_DEVICE_NOT_FOUND; + } else { + /* Type 1 */ + if ((*bus_num >= 64) || (PCI_SLOT(devfn) >= 16)) + return PCIBIOS_DEVICE_NOT_FOUND; + } + return 0; +} + +static inline int set_pci_configuration_address(unsigned char bus_num, + unsigned int devfn, int where) +{ + u32 config_win0; + + emma2rh_out32(EMMA2RH_PCI_INT, ~RMABORT); + if (bus_num == 0) + /* + * Type 0 configuration + */ + config_win0 = (1 << (22 + PCI_SLOT(devfn))) | (5 << 9); + else + /* + * Type 1 configuration + */ + config_win0 = (bus_num << 26) | (PCI_SLOT(devfn) << 22) | + (1 << 15) | (5 << 9); + + emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, config_win0); + + return 0; +} + +static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, + int size, uint32_t * val) +{ + u32 bus_num; + u32 base = KSEG1ADDR(EMMA2RH_PCI_CONFIG_BASE); + u32 backup_win0; + u32 data; + + *val = 0xffffffffU; + + if (check_args(bus, devfn, &bus_num) == PCIBIOS_DEVICE_NOT_FOUND) + return PCIBIOS_DEVICE_NOT_FOUND; + + backup_win0 = emma2rh_in32(EMMA2RH_PCI_IWIN0_CTR); + + if (set_pci_configuration_address(bus_num, devfn, where) < 0) + return PCIBIOS_DEVICE_NOT_FOUND; + + data = + *(volatile u32 *)(base + (PCI_FUNC(devfn) << 8) + + (where & 0xfffffffc)); + + switch (size) { + case 1: + *val = (data >> ((where & 3) << 3)) & 0xffU; + break; + case 2: + *val = (data >> ((where & 2) << 3)) & 0xffffU; + break; + case 4: + *val = data; + break; + default: + emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0); + return PCIBIOS_FUNC_NOT_SUPPORTED; + } + + emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0); + + if (emma2rh_in32(EMMA2RH_PCI_INT) & RMABORT) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 val) +{ + u32 bus_num; + u32 base = KSEG1ADDR(EMMA2RH_PCI_CONFIG_BASE); + u32 backup_win0; + u32 data; + int shift; + + if (check_args(bus, devfn, &bus_num) == PCIBIOS_DEVICE_NOT_FOUND) + return PCIBIOS_DEVICE_NOT_FOUND; + + backup_win0 = emma2rh_in32(EMMA2RH_PCI_IWIN0_CTR); + + if (set_pci_configuration_address(bus_num, devfn, where) < 0) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* read modify write */ + data = + *(volatile u32 *)(base + (PCI_FUNC(devfn) << 8) + + (where & 0xfffffffc)); + + switch (size) { + case 1: + shift = (where & 3) << 3; + data &= ~(0xffU << shift); + data |= ((val & 0xffU) << shift); + break; + case 2: + shift = (where & 2) << 3; + data &= ~(0xffffU << shift); + data |= ((val & 0xffffU) << shift); + break; + case 4: + data = val; + break; + default: + emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0); + return PCIBIOS_FUNC_NOT_SUPPORTED; + } + *(volatile u32 *)(base + (PCI_FUNC(devfn) << 8) + + (where & 0xfffffffc)) = data; + + emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, backup_win0); + if (emma2rh_in32(EMMA2RH_PCI_INT) & RMABORT) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops emma2rh_pci_ops = { + .read = pci_config_read, + .write = pci_config_write, +}; diff --git a/arch/mips/pci/pci-emma2rh.c b/arch/mips/pci/pci-emma2rh.c new file mode 100644 index 000000000..d99591a0c --- /dev/null +++ b/arch/mips/pci/pci-emma2rh.c @@ -0,0 +1,89 @@ +/* + * arch/mips/pci/pci-emma2rh.c + * This file defines the PCI configration. + * + * Copyright (C) NEC Electronics Corporation 2004-2006 + * + * This file is based on the arch/mips/ddb5xxx/ddb5477/pci.c + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/pci.h> + +#include <asm/bootinfo.h> +#include <asm/debug.h> + +#include <asm/emma2rh/emma2rh.h> + +static struct resource pci_io_resource = { + .name = "pci IO space", + .start = EMMA2RH_PCI_IO_BASE, + .end = EMMA2RH_PCI_IO_BASE + EMMA2RH_PCI_IO_SIZE - 1, + .flags = IORESOURCE_IO, +}; + +static struct resource pci_mem_resource = { + .name = "pci memory space", + .start = EMMA2RH_PCI_MEM_BASE, + .end = EMMA2RH_PCI_MEM_BASE + EMMA2RH_PCI_MEM_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +extern struct pci_ops emma2rh_pci_ops; + +static struct pci_controller emma2rh_pci_controller = { + .pci_ops = &emma2rh_pci_ops, + .mem_resource = &pci_mem_resource, + .io_resource = &pci_io_resource, + .mem_offset = -0x04000000, + .io_offset = 0, +}; + +static void __init emma2rh_pci_init(void) +{ + /* setup PCI interface */ + emma2rh_out32(EMMA2RH_PCI_ARBIT_CTR, 0x70f); + + emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, 0x80000a18); + emma2rh_out32(EMMA2RH_PCI_CONFIG_BASE + PCI_COMMAND, + PCI_STATUS_DEVSEL_MEDIUM | PCI_STATUS_CAP_LIST | + PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); + emma2rh_out32(EMMA2RH_PCI_CONFIG_BASE + PCI_BASE_ADDRESS_0, 0x10000000); + emma2rh_out32(EMMA2RH_PCI_CONFIG_BASE + PCI_BASE_ADDRESS_1, 0x00000000); + + emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR, 0x12000000 | 0x218); + emma2rh_out32(EMMA2RH_PCI_IWIN1_CTR, 0x18000000 | 0x600); + emma2rh_out32(EMMA2RH_PCI_INIT_ESWP, 0x00000200); + + emma2rh_out32(EMMA2RH_PCI_TWIN_CTR, 0x00009200); + emma2rh_out32(EMMA2RH_PCI_TWIN_BADR, 0x00000000); + emma2rh_out32(EMMA2RH_PCI_TWIN0_DADR, 0x00000000); + emma2rh_out32(EMMA2RH_PCI_TWIN1_DADR, 0x00000000); +} + +static int __init emma2rh_pci_setup(void) +{ + emma2rh_pci_init(); + register_pci_controller(&emma2rh_pci_controller); + return 0; +} + +arch_initcall(emma2rh_pci_setup); diff --git a/arch/mips/pci/pci-excite.c b/arch/mips/pci/pci-excite.c new file mode 100644 index 000000000..3c86c77cb --- /dev/null +++ b/arch/mips/pci/pci-excite.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2004 by Basler Vision Technologies AG + * Author: Thomas Koeller <thomas.koeller@baslerweb.com> + * Based on the PMC-Sierra Yosemite board support by Ralf Baechle. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/bitops.h> +#include <asm/rm9k-ocd.h> +#include <excite.h> + + +extern struct pci_ops titan_pci_ops; + + +static struct resource + mem_resource = { + .name = "PCI memory", + .start = EXCITE_PHYS_PCI_MEM, + .end = EXCITE_PHYS_PCI_MEM + EXCITE_SIZE_PCI_MEM - 1, + .flags = IORESOURCE_MEM + }, + io_resource = { + .name = "PCI I/O", + .start = EXCITE_PHYS_PCI_IO, + .end = EXCITE_PHYS_PCI_IO + EXCITE_SIZE_PCI_IO - 1, + .flags = IORESOURCE_IO + }; + + +static struct pci_controller bx_controller = { + .pci_ops = &titan_pci_ops, + .mem_resource = &mem_resource, + .mem_offset = 0x00000000UL, + .io_resource = &io_resource, + .io_offset = 0x00000000UL +}; + + +static char + iopage_failed[] __initdata = "Cannot allocate PCI I/O page", + modebits_no_pci[] __initdata = "PCI is not configured in mode bits"; + +#define RM9000x2_OCD_HTSC 0x0604 +#define RM9000x2_OCD_HTBHL 0x060c +#define RM9000x2_OCD_PCIHRST 0x078c + +#define RM9K_OCD_MODEBIT1 0x00d4 /* (MODEBIT1) Mode Bit 1 */ +#define RM9K_OCD_CPHDCR 0x00f4 /* CPU-PCI/HT Data Control. */ + +#define PCISC_FB2B 0x00000200 +#define PCISC_MWICG 0x00000010 +#define PCISC_EMC 0x00000004 +#define PCISC_ERMA 0x00000002 + + + +static int __init basler_excite_pci_setup(void) +{ + const unsigned int fullbars = memsize / (256 << 20); + unsigned int i; + + /* Check modebits to see if PCI is really enabled. */ + if (!((ocd_readl(RM9K_OCD_MODEBIT1) >> (47-32)) & 0x1)) + panic(modebits_no_pci); + + if (NULL == request_mem_region(EXCITE_PHYS_PCI_IO, EXCITE_SIZE_PCI_IO, + "Memory-mapped PCI I/O page")) + panic(iopage_failed); + + /* Enable PCI 0 as master for config cycles */ + ocd_writel(PCISC_EMC | PCISC_ERMA, RM9000x2_OCD_HTSC); + + + /* Set up latency timer */ + ocd_writel(0x8008, RM9000x2_OCD_HTBHL); + + /* Setup host IO and Memory space */ + ocd_writel((EXCITE_PHYS_PCI_IO >> 4) | 1, LKB7); + ocd_writel(((EXCITE_SIZE_PCI_IO >> 4) & 0x7fffff00) - 0x100, LKM7); + ocd_writel((EXCITE_PHYS_PCI_MEM >> 4) | 1, LKB8); + ocd_writel(((EXCITE_SIZE_PCI_MEM >> 4) & 0x7fffff00) - 0x100, LKM8); + + /* Set up PCI BARs to map all installed memory */ + for (i = 0; i < 6; i++) { + const unsigned int bar = 0x610 + i * 4; + + if (i < fullbars) { + ocd_writel(0x10000000 * i, bar); + ocd_writel(0x01000000 * i, bar + 0x140); + ocd_writel(0x0ffff029, bar + 0x100); + continue; + } + + if (i == fullbars) { + int o; + u32 mask; + + const unsigned long rem = memsize - i * 0x10000000; + if (!rem) { + ocd_writel(0x00000000, bar + 0x100); + continue; + } + + o = ffs(rem) - 1; + if (rem & ~(0x1 << o)) + o++; + mask = ((0x1 << o) & 0x0ffff000) - 0x1000; + ocd_writel(0x10000000 * i, bar); + ocd_writel(0x01000000 * i, bar + 0x140); + ocd_writel(0x00000029 | mask, bar + 0x100); + continue; + } + + ocd_writel(0x00000000, bar + 0x100); + } + + /* Finally, enable the PCI interupt */ +#if USB_IRQ > 7 + set_c0_intcontrol(1 << USB_IRQ); +#else + set_c0_status(1 << (USB_IRQ + 8)); +#endif + + ioport_resource.start = EXCITE_PHYS_PCI_IO; + ioport_resource.end = EXCITE_PHYS_PCI_IO + EXCITE_SIZE_PCI_IO - 1; + set_io_port_base((unsigned long) ioremap_nocache(EXCITE_PHYS_PCI_IO, EXCITE_SIZE_PCI_IO)); + register_pci_controller(&bx_controller); + return 0; +} + + +arch_initcall(basler_excite_pci_setup); diff --git a/arch/mips/qemu/q-reset.c b/arch/mips/qemu/q-reset.c new file mode 100644 index 000000000..dbbe44ad7 --- /dev/null +++ b/arch/mips/qemu/q-reset.c @@ -0,0 +1,33 @@ + +#include <asm/io.h> +#include <asm/reboot.h> +#include <asm/cacheflush.h> +#include <asm/qemu.h> + +static void qemu_machine_restart(char *command) +{ + volatile unsigned int *reg = (unsigned int *)QEMU_RESTART_REG; + + set_c0_status(ST0_BEV | ST0_ERL); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_c0_wired(0); + *reg = 42; + while (1) + cpu_wait(); +} + +static void qemu_machine_halt(void) +{ + volatile unsigned int *reg = (unsigned int *)QEMU_HALT_REG; + + *reg = 42; + while (1) + cpu_wait(); +} + +void qemu_reboot_setup(void) +{ + _machine_restart = qemu_machine_restart; + _machine_halt = qemu_machine_halt; +} diff --git a/arch/mips/sni/sniprom.c b/arch/mips/sni/sniprom.c new file mode 100644 index 000000000..d1d0f1f49 --- /dev/null +++ b/arch/mips/sni/sniprom.c @@ -0,0 +1,158 @@ +/* + * Big Endian PROM code for SNI RM machines + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2005-2006 Florian Lohoff (flo@rfc822.org) + * Copyright (C) 2005-2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de) + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/string.h> + +#include <asm/addrspace.h> +#include <asm/sni.h> +#include <asm/mipsprom.h> +#include <asm/bootinfo.h> + +/* special SNI prom calls */ +/* + * This does not exist in all proms - SINIX compares + * the prom env variable "version" against "2.0008" + * or greater. If lesser it tries to probe interesting + * registers + */ +#define PROM_GET_MEMCONF 58 + +#define PROM_VEC (u64 *)CKSEG1ADDR(0x1fc00000) +#define PROM_ENTRY(x) (PROM_VEC + (x)) + + +#undef DEBUG +#ifdef DEBUG +#define DBG_PRINTF(x...) prom_printf(x) +#else +#define DBG_PRINTF(x...) +#endif + +static int *(*__prom_putchar)(int) = (int *(*)(int))PROM_ENTRY(PROM_PUTCHAR); +static char *(*__prom_getenv)(char *) = (char *(*)(char *))PROM_ENTRY(PROM_GETENV); +static void (*__prom_get_memconf)(void *) = (void (*)(void *))PROM_ENTRY(PROM_GET_MEMCONF); + +char *prom_getenv (char *s) +{ + return __prom_getenv(s); +} + +void prom_printf(char *fmt, ...) +{ + va_list args; + char ppbuf[1024]; + char *bptr; + + va_start(args, fmt); + vsprintf(ppbuf, fmt, args); + + bptr = ppbuf; + + while (*bptr != 0) { + if (*bptr == '\n') + __prom_putchar('\r'); + + __prom_putchar(*bptr++); + } + va_end(args); +} + +unsigned long prom_free_prom_memory(void) +{ + return 0; +} + +/* + * /proc/cpuinfo system type + * + */ +static const char *systype = "Unknown"; +const char *get_system_type(void) +{ + return systype; +} + +#define SNI_IDPROM_BASE 0xbff00000 +#define SNI_IDPROM_MEMSIZE (SNI_IDPROM_BASE+0x28) /* Memsize in 16MB quantities */ +#define SNI_IDPROM_BRDTYPE (SNI_IDPROM_BASE+0x29) /* Board Type */ +#define SNI_IDPROM_CPUTYPE (SNI_IDPROM_BASE+0x30) /* CPU Type */ + +#define SNI_IDPROM_SIZE 0x1000 + +#ifdef DEBUG +static void sni_idprom_dump(void) +{ + int i; + + prom_printf("SNI IDProm dump (first 128byte):\n"); + for(i=0;i<128;i++) { + if (i%16 == 0) + prom_printf("%04x ", i); + + prom_printf("%02x ", *(unsigned char *) (SNI_IDPROM_BASE+i)); + + if (i%16 == 15) + prom_printf("\n"); + } +} +#endif + +static void sni_mem_init(void ) +{ + int i, memsize; + struct membank { + u32 size; + u32 base; + u32 size2; + u32 pad1; + u32 pad2; + } memconf[8]; + + /* MemSIZE from prom in 16MByte chunks */ + memsize=*((unsigned char *) SNI_IDPROM_MEMSIZE) * 16; + + DBG_PRINTF("IDProm memsize: %lu MByte\n", memsize); + + /* get memory bank layout from prom */ + __prom_get_memconf(&memconf); + + DBG_PRINTF("prom_get_mem_conf memory configuration:\n"); + for(i=0;i<8 && memconf[i].size;i++) { + prom_printf("Bank%d: %08x @ %08x\n", i, + memconf[i].size, memconf[i].base); + add_memory_region(memconf[i].base, memconf[i].size, BOOT_MEM_RAM); + } +} + +void __init prom_init(void) +{ + int argc = fw_arg0; + char **argv = (void *)fw_arg1; + unsigned int sni_brd_type = *(unsigned char *) SNI_IDPROM_BRDTYPE; + int i; + + DBG_PRINTF("Found SNI brdtype %02x\n", sni_brd_type); + +#ifdef DEBUG + sni_idprom_dump(); +#endif + sni_mem_init(); + + /* copy prom cmdline parameters to kernel cmdline */ + for (i = 1; i < argc; i++) { + strcat(arcs_cmdline, argv[i]); + if (i < (argc - 1)) + strcat(arcs_cmdline, " "); + } +} + diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts new file mode 100644 index 000000000..d7b985e6b --- /dev/null +++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts @@ -0,0 +1,190 @@ +/* + * MPC7448HPC2 (Taiga) board Device Tree Source + * + * Copyright 2006 Freescale Semiconductor Inc. + * 2006 Roy Zang <Roy Zang at freescale.com>. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + + +/ { + model = "mpc7448hpc2"; + compatible = "mpc74xx"; + #address-cells = <1>; + #size-cells = <1>; + linux,phandle = <100>; + + cpus { + #cpus = <1>; + #address-cells = <1>; + #size-cells =<0>; + linux,phandle = <200>; + + PowerPC,7448@0 { + device_type = "cpu"; + reg = <0>; + d-cache-line-size = <20>; // 32 bytes + i-cache-line-size = <20>; // 32 bytes + d-cache-size = <8000>; // L1, 32K bytes + i-cache-size = <8000>; // L1, 32K bytes + timebase-frequency = <0>; // 33 MHz, from uboot + clock-frequency = <0>; // From U-Boot + bus-frequency = <0>; // From U-Boot + 32-bit; + linux,phandle = <201>; + linux,boot-cpu; + }; + }; + + memory { + device_type = "memory"; + linux,phandle = <300>; + reg = <00000000 20000000 // DDR2 512M at 0 + >; + }; + + tsi108@c0000000 { + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <2>; + device_type = "tsi-bridge"; + ranges = <00000000 c0000000 00010000>; + reg = <c0000000 00010000>; + bus-frequency = <0>; + + i2c@7000 { + interrupt-parent = <7400>; + interrupts = <E 0>; + reg = <7000 400>; + device_type = "i2c"; + compatible = "tsi-i2c"; + }; + + mdio@6000 { + device_type = "mdio"; + compatible = "tsi-ethernet"; + + ethernet-phy@6000 { + linux,phandle = <6000>; + interrupt-parent = <7400>; + interrupts = <2 1>; + reg = <6000 50>; + phy-id = <8>; + device_type = "ethernet-phy"; + }; + + ethernet-phy@6400 { + linux,phandle = <6400>; + interrupt-parent = <7400>; + interrupts = <2 1>; + reg = <6000 50>; + phy-id = <9>; + device_type = "ethernet-phy"; + }; + + }; + + ethernet@6200 { + #size-cells = <0>; + device_type = "network"; + model = "TSI-ETH"; + compatible = "tsi-ethernet"; + reg = <6000 200>; + address = [ 00 06 D2 00 00 01 ]; + interrupts = <10 2>; + interrupt-parent = <7400>; + phy-handle = <6000>; + }; + + ethernet@6600 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "TSI-ETH"; + compatible = "tsi-ethernet"; + reg = <6400 200>; + address = [ 00 06 D2 00 00 02 ]; + interrupts = <11 2>; + interrupt-parent = <7400>; + phy-handle = <6400>; + }; + + serial@7808 { + device_type = "serial"; + compatible = "ns16550"; + reg = <7808 200>; + clock-frequency = <3f6b5a00>; + interrupts = <c 0>; + interrupt-parent = <7400>; + }; + + serial@7c08 { + device_type = "serial"; + compatible = "ns16550"; + reg = <7c08 200>; + clock-frequency = <3f6b5a00>; + interrupts = <d 0>; + interrupt-parent = <7400>; + }; + + pic@7400 { + linux,phandle = <7400>; + clock-frequency = <0>; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <7400 400>; + built-in; + compatible = "chrp,open-pic"; + device_type = "open-pic"; + big-endian; + }; + pci@1000 { + compatible = "tsi10x"; + device_type = "pci"; + linux,phandle = <1000>; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <1000 1000>; + bus-range = <0 0>; + ranges = <02000000 0 e0000000 e0000000 0 1A000000 + 01000000 0 00000000 fa000000 0 00010000>; + clock-frequency = <7f28154>; + interrupt-parent = <7400>; + interrupts = <17 2>; + interrupt-map-mask = <f800 0 0 7>; + interrupt-map = < + + /* IDSEL 0x11 */ + 0800 0 0 1 7400 24 0 + 0800 0 0 2 7400 25 0 + 0800 0 0 3 7400 26 0 + 0800 0 0 4 7400 27 0 + + /* IDSEL 0x12 */ + 1000 0 0 1 7400 25 0 + 1000 0 0 2 7400 26 0 + 1000 0 0 3 7400 27 0 + 1000 0 0 4 7400 24 0 + + /* IDSEL 0x13 */ + 1800 0 0 1 7400 26 0 + 1800 0 0 2 7400 27 0 + 1800 0 0 3 7400 24 0 + 1800 0 0 4 7400 25 0 + + /* IDSEL 0x14 */ + 2000 0 0 1 7400 27 0 + 2000 0 0 2 7400 24 0 + 2000 0 0 3 7400 25 0 + 2000 0 0 4 7400 26 0 + >; + }; + }; + +}; diff --git a/arch/powerpc/boot/dts/mpc8349emds.dts b/arch/powerpc/boot/dts/mpc8349emds.dts new file mode 100644 index 000000000..12f5dbf30 --- /dev/null +++ b/arch/powerpc/boot/dts/mpc8349emds.dts @@ -0,0 +1,328 @@ +/* + * MPC8349E MDS Device Tree Source + * + * Copyright 2005, 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +/ { + model = "MPC8349EMDS"; + compatible = "MPC834xMDS"; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #cpus = <1>; + #address-cells = <1>; + #size-cells = <0>; + + PowerPC,8349@0 { + device_type = "cpu"; + reg = <0>; + d-cache-line-size = <20>; // 32 bytes + i-cache-line-size = <20>; // 32 bytes + d-cache-size = <8000>; // L1, 32K + i-cache-size = <8000>; // L1, 32K + timebase-frequency = <0>; // from bootloader + bus-frequency = <0>; // from bootloader + clock-frequency = <0>; // from bootloader + 32-bit; + }; + }; + + memory { + device_type = "memory"; + reg = <00000000 10000000>; // 256MB at 0 + }; + + soc8349@e0000000 { + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <2>; + device_type = "soc"; + ranges = <0 e0000000 00100000>; + reg = <e0000000 00000200>; + bus-frequency = <0>; + + wdt@200 { + device_type = "watchdog"; + compatible = "mpc83xx_wdt"; + reg = <200 100>; + }; + + i2c@3000 { + device_type = "i2c"; + compatible = "fsl-i2c"; + reg = <3000 100>; + interrupts = <e 8>; + interrupt-parent = <700>; + dfsrr; + }; + + i2c@3100 { + device_type = "i2c"; + compatible = "fsl-i2c"; + reg = <3100 100>; + interrupts = <f 8>; + interrupt-parent = <700>; + dfsrr; + }; + + spi@7000 { + device_type = "spi"; + compatible = "mpc83xx_spi"; + reg = <7000 1000>; + interrupts = <10 8>; + interrupt-parent = <700>; + mode = <0>; + }; + + /* phy type (ULPI or SERIAL) are only types supportted for MPH */ + /* port = 0 or 1 */ + usb@22000 { + device_type = "usb"; + compatible = "fsl-usb2-mph"; + reg = <22000 1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupt-parent = <700>; + interrupts = <27 2>; + phy_type = "ulpi"; + port1; + }; + /* phy type (ULPI, UTMI, UTMI_WIDE, SERIAL) */ + usb@23000 { + device_type = "usb"; + compatible = "fsl-usb2-dr"; + reg = <23000 1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupt-parent = <700>; + interrupts = <26 2>; + phy_type = "ulpi"; + }; + + mdio@24520 { + device_type = "mdio"; + compatible = "gianfar"; + reg = <24520 20>; + #address-cells = <1>; + #size-cells = <0>; + linux,phandle = <24520>; + ethernet-phy@0 { + linux,phandle = <2452000>; + interrupt-parent = <700>; + interrupts = <11 2>; + reg = <0>; + device_type = "ethernet-phy"; + }; + ethernet-phy@1 { + linux,phandle = <2452001>; + interrupt-parent = <700>; + interrupts = <12 2>; + reg = <1>; + device_type = "ethernet-phy"; + }; + }; + + ethernet@24000 { + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <24000 1000>; + address = [ 00 00 00 00 00 00 ]; + local-mac-address = [ 00 00 00 00 00 00 ]; + interrupts = <20 8 21 8 22 8>; + interrupt-parent = <700>; + phy-handle = <2452000>; + }; + + ethernet@25000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <25000 1000>; + address = [ 00 00 00 00 00 00 ]; + local-mac-address = [ 00 00 00 00 00 00 ]; + interrupts = <23 8 24 8 25 8>; + interrupt-parent = <700>; + phy-handle = <2452001>; + }; + + serial@4500 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4500 100>; + clock-frequency = <0>; + interrupts = <9 8>; + interrupt-parent = <700>; + }; + + serial@4600 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4600 100>; + clock-frequency = <0>; + interrupts = <a 8>; + interrupt-parent = <700>; + }; + + pci@8500 { + interrupt-map-mask = <f800 0 0 7>; + interrupt-map = < + + /* IDSEL 0x11 */ + 8800 0 0 1 700 14 8 + 8800 0 0 2 700 15 8 + 8800 0 0 3 700 16 8 + 8800 0 0 4 700 17 8 + + /* IDSEL 0x12 */ + 9000 0 0 1 700 16 8 + 9000 0 0 2 700 17 8 + 9000 0 0 3 700 14 8 + 9000 0 0 4 700 15 8 + + /* IDSEL 0x13 */ + 9800 0 0 1 700 17 8 + 9800 0 0 2 700 14 8 + 9800 0 0 3 700 15 8 + 9800 0 0 4 700 16 8 + + /* IDSEL 0x15 */ + a800 0 0 1 700 14 8 + a800 0 0 2 700 15 8 + a800 0 0 3 700 16 8 + a800 0 0 4 700 17 8 + + /* IDSEL 0x16 */ + b000 0 0 1 700 17 8 + b000 0 0 2 700 14 8 + b000 0 0 3 700 15 8 + b000 0 0 4 700 16 8 + + /* IDSEL 0x17 */ + b800 0 0 1 700 16 8 + b800 0 0 2 700 17 8 + b800 0 0 3 700 14 8 + b800 0 0 4 700 15 8 + + /* IDSEL 0x18 */ + b000 0 0 1 700 15 8 + b000 0 0 2 700 16 8 + b000 0 0 3 700 17 8 + b000 0 0 4 700 14 8>; + interrupt-parent = <700>; + interrupts = <42 8>; + bus-range = <0 0>; + ranges = <02000000 0 a0000000 a0000000 0 10000000 + 42000000 0 80000000 80000000 0 10000000 + 01000000 0 00000000 e2000000 0 00100000>; + clock-frequency = <3f940aa>; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <8500 100>; + compatible = "83xx"; + device_type = "pci"; + }; + + pci@8600 { + interrupt-map-mask = <f800 0 0 7>; + interrupt-map = < + + /* IDSEL 0x11 */ + 8800 0 0 1 700 14 8 + 8800 0 0 2 700 15 8 + 8800 0 0 3 700 16 8 + 8800 0 0 4 700 17 8 + + /* IDSEL 0x12 */ + 9000 0 0 1 700 16 8 + 9000 0 0 2 700 17 8 + 9000 0 0 3 700 14 8 + 9000 0 0 4 700 15 8 + + /* IDSEL 0x13 */ + 9800 0 0 1 700 17 8 + 9800 0 0 2 700 14 8 + 9800 0 0 3 700 15 8 + 9800 0 0 4 700 16 8 + + /* IDSEL 0x15 */ + a800 0 0 1 700 14 8 + a800 0 0 2 700 15 8 + a800 0 0 3 700 16 8 + a800 0 0 4 700 17 8 + + /* IDSEL 0x16 */ + b000 0 0 1 700 17 8 + b000 0 0 2 700 14 8 + b000 0 0 3 700 15 8 + b000 0 0 4 700 16 8 + + /* IDSEL 0x17 */ + b800 0 0 1 700 16 8 + b800 0 0 2 700 17 8 + b800 0 0 3 700 14 8 + b800 0 0 4 700 15 8 + + /* IDSEL 0x18 */ + b000 0 0 1 700 15 8 + b000 0 0 2 700 16 8 + b000 0 0 3 700 17 8 + b000 0 0 4 700 14 8>; + interrupt-parent = <700>; + interrupts = <42 8>; + bus-range = <0 0>; + ranges = <02000000 0 b0000000 b0000000 0 10000000 + 42000000 0 90000000 90000000 0 10000000 + 01000000 0 00000000 e2100000 0 00100000>; + clock-frequency = <3f940aa>; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <8600 100>; + compatible = "83xx"; + device_type = "pci"; + }; + + /* May need to remove if on a part without crypto engine */ + crypto@30000 { + device_type = "crypto"; + model = "SEC2"; + compatible = "talitos"; + reg = <30000 10000>; + interrupts = <b 8>; + interrupt-parent = <700>; + num-channels = <4>; + channel-fifo-len = <18>; + exec-units-mask = <0000007e>; + /* desc mask is for rev2.0, + * we need runtime fixup for >2.0 */ + descriptor-types-mask = <01010ebf>; + }; + + /* IPIC + * interrupts cell = <intr #, sense> + * sense values match linux IORESOURCE_IRQ_* defines: + * sense == 8: Level, low assertion + * sense == 2: Edge, high-to-low change + */ + pic@700 { + linux,phandle = <700>; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <700 100>; + built-in; + device_type = "ipic"; + }; + }; +}; diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts new file mode 100644 index 000000000..5f41c1f7a --- /dev/null +++ b/arch/powerpc/boot/dts/mpc8540ads.dts @@ -0,0 +1,257 @@ +/* + * MPC8540 ADS Device Tree Source + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + + +/ { + model = "MPC8540ADS"; + compatible = "MPC85xxADS"; + #address-cells = <1>; + #size-cells = <1>; + linux,phandle = <100>; + + cpus { + #cpus = <1>; + #address-cells = <1>; + #size-cells = <0>; + linux,phandle = <200>; + + PowerPC,8540@0 { + device_type = "cpu"; + reg = <0>; + d-cache-line-size = <20>; // 32 bytes + i-cache-line-size = <20>; // 32 bytes + d-cache-size = <8000>; // L1, 32K + i-cache-size = <8000>; // L1, 32K + timebase-frequency = <0>; // 33 MHz, from uboot + bus-frequency = <0>; // 166 MHz + clock-frequency = <0>; // 825 MHz, from uboot + 32-bit; + linux,phandle = <201>; + }; + }; + + memory { + device_type = "memory"; + linux,phandle = <300>; + reg = <00000000 08000000>; // 128M at 0x0 + }; + + soc8540@e0000000 { + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <2>; + device_type = "soc"; + ranges = <0 e0000000 00100000>; + reg = <e0000000 00100000>; // CCSRBAR 1M + bus-frequency = <0>; + + i2c@3000 { + device_type = "i2c"; + compatible = "fsl-i2c"; + reg = <3000 100>; + interrupts = <1b 2>; + interrupt-parent = <40000>; + dfsrr; + }; + + mdio@24520 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "mdio"; + compatible = "gianfar"; + reg = <24520 20>; + linux,phandle = <24520>; + ethernet-phy@0 { + linux,phandle = <2452000>; + interrupt-parent = <40000>; + interrupts = <35 1>; + reg = <0>; + device_type = "ethernet-phy"; + }; + ethernet-phy@1 { + linux,phandle = <2452001>; + interrupt-parent = <40000>; + interrupts = <35 1>; + reg = <1>; + device_type = "ethernet-phy"; + }; + ethernet-phy@3 { + linux,phandle = <2452003>; + interrupt-parent = <40000>; + interrupts = <37 1>; + reg = <3>; + device_type = "ethernet-phy"; + }; + }; + + ethernet@24000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <24000 1000>; + address = [ 00 E0 0C 00 73 00 ]; + local-mac-address = [ 00 E0 0C 00 73 00 ]; + interrupts = <d 2 e 2 12 2>; + interrupt-parent = <40000>; + phy-handle = <2452000>; + }; + + ethernet@25000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <25000 1000>; + address = [ 00 E0 0C 00 73 01 ]; + local-mac-address = [ 00 E0 0C 00 73 01 ]; + interrupts = <13 2 14 2 18 2>; + interrupt-parent = <40000>; + phy-handle = <2452001>; + }; + + ethernet@26000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "FEC"; + compatible = "gianfar"; + reg = <26000 1000>; + address = [ 00 E0 0C 00 73 02 ]; + local-mac-address = [ 00 E0 0C 00 73 02 ]; + interrupts = <19 2>; + interrupt-parent = <40000>; + phy-handle = <2452003>; + }; + + serial@4500 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4500 100>; // reg base, size + clock-frequency = <0>; // should we fill in in uboot? + interrupts = <1a 2>; + interrupt-parent = <40000>; + }; + + serial@4600 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4600 100>; // reg base, size + clock-frequency = <0>; // should we fill in in uboot? + interrupts = <1a 2>; + interrupt-parent = <40000>; + }; + pci@8000 { + linux,phandle = <8000>; + interrupt-map-mask = <f800 0 0 7>; + interrupt-map = < + + /* IDSEL 0x02 */ + 1000 0 0 1 40000 31 1 + 1000 0 0 2 40000 32 1 + 1000 0 0 3 40000 33 1 + 1000 0 0 4 40000 34 1 + + /* IDSEL 0x03 */ + 1800 0 0 1 40000 34 1 + 1800 0 0 2 40000 31 1 + 1800 0 0 3 40000 32 1 + 1800 0 0 4 40000 33 1 + + /* IDSEL 0x04 */ + 2000 0 0 1 40000 33 1 + 2000 0 0 2 40000 34 1 + 2000 0 0 3 40000 31 1 + 2000 0 0 4 40000 32 1 + + /* IDSEL 0x05 */ + 2800 0 0 1 40000 32 1 + 2800 0 0 2 40000 33 1 + 2800 0 0 3 40000 34 1 + 2800 0 0 4 40000 31 1 + + /* IDSEL 0x0c */ + 6000 0 0 1 40000 31 1 + 6000 0 0 2 40000 32 1 + 6000 0 0 3 40000 33 1 + 6000 0 0 4 40000 34 1 + + /* IDSEL 0x0d */ + 6800 0 0 1 40000 34 1 + 6800 0 0 2 40000 31 1 + 6800 0 0 3 40000 32 1 + 6800 0 0 4 40000 33 1 + + /* IDSEL 0x0e */ + 7000 0 0 1 40000 33 1 + 7000 0 0 2 40000 34 1 + 7000 0 0 3 40000 31 1 + 7000 0 0 4 40000 32 1 + + /* IDSEL 0x0f */ + 7800 0 0 1 40000 32 1 + 7800 0 0 2 40000 33 1 + 7800 0 0 3 40000 34 1 + 7800 0 0 4 40000 31 1 + + /* IDSEL 0x12 */ + 9000 0 0 1 40000 31 1 + 9000 0 0 2 40000 32 1 + 9000 0 0 3 40000 33 1 + 9000 0 0 4 40000 34 1 + + /* IDSEL 0x13 */ + 9800 0 0 1 40000 34 1 + 9800 0 0 2 40000 31 1 + 9800 0 0 3 40000 32 1 + 9800 0 0 4 40000 33 1 + + /* IDSEL 0x14 */ + a000 0 0 1 40000 33 1 + a000 0 0 2 40000 34 1 + a000 0 0 3 40000 31 1 + a000 0 0 4 40000 32 1 + + /* IDSEL 0x15 */ + a800 0 0 1 40000 32 1 + a800 0 0 2 40000 33 1 + a800 0 0 3 40000 34 1 + a800 0 0 4 40000 31 1>; + interrupt-parent = <40000>; + interrupts = <08 2>; + bus-range = <0 0>; + ranges = <02000000 0 80000000 80000000 0 20000000 + 01000000 0 00000000 e2000000 0 00100000>; + clock-frequency = <3f940aa>; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <8000 1000>; + compatible = "85xx"; + device_type = "pci"; + }; + + pic@40000 { + linux,phandle = <40000>; + clock-frequency = <0>; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <40000 40000>; + built-in; + compatible = "chrp,open-pic"; + device_type = "open-pic"; + big-endian; + }; + }; +}; diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts new file mode 100644 index 000000000..7be0bc659 --- /dev/null +++ b/arch/powerpc/boot/dts/mpc8541cds.dts @@ -0,0 +1,244 @@ +/* + * MPC8541 CDS Device Tree Source + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + + +/ { + model = "MPC8541CDS"; + compatible = "MPC85xxCDS"; + #address-cells = <1>; + #size-cells = <1>; + linux,phandle = <100>; + + cpus { + #cpus = <1>; + #address-cells = <1>; + #size-cells = <0>; + linux,phandle = <200>; + + PowerPC,8541@0 { + device_type = "cpu"; + reg = <0>; + d-cache-line-size = <20>; // 32 bytes + i-cache-line-size = <20>; // 32 bytes + d-cache-size = <8000>; // L1, 32K + i-cache-size = <8000>; // L1, 32K + timebase-frequency = <0>; // 33 MHz, from uboot + bus-frequency = <0>; // 166 MHz + clock-frequency = <0>; // 825 MHz, from uboot + 32-bit; + linux,phandle = <201>; + }; + }; + + memory { + device_type = "memory"; + linux,phandle = <300>; + reg = <00000000 08000000>; // 128M at 0x0 + }; + + soc8541@e0000000 { + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <2>; + device_type = "soc"; + ranges = <0 e0000000 00100000>; + reg = <e0000000 00100000>; // CCSRBAR 1M + bus-frequency = <0>; + + i2c@3000 { + device_type = "i2c"; + compatible = "fsl-i2c"; + reg = <3000 100>; + interrupts = <1b 2>; + interrupt-parent = <40000>; + dfsrr; + }; + + mdio@24520 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "mdio"; + compatible = "gianfar"; + reg = <24520 20>; + linux,phandle = <24520>; + ethernet-phy@0 { + linux,phandle = <2452000>; + interrupt-parent = <40000>; + interrupts = <35 0>; + reg = <0>; + device_type = "ethernet-phy"; + }; + ethernet-phy@1 { + linux,phandle = <2452001>; + interrupt-parent = <40000>; + interrupts = <35 0>; + reg = <1>; + device_type = "ethernet-phy"; + }; + }; + + ethernet@24000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <24000 1000>; + local-mac-address = [ 00 E0 0C 00 73 00 ]; + interrupts = <d 2 e 2 12 2>; + interrupt-parent = <40000>; + phy-handle = <2452000>; + }; + + ethernet@25000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <25000 1000>; + local-mac-address = [ 00 E0 0C 00 73 01 ]; + interrupts = <13 2 14 2 18 2>; + interrupt-parent = <40000>; + phy-handle = <2452001>; + }; + + serial@4500 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4500 100>; // reg base, size + clock-frequency = <0>; // should we fill in in uboot? + interrupts = <1a 2>; + interrupt-parent = <40000>; + }; + + serial@4600 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4600 100>; // reg base, size + clock-frequency = <0>; // should we fill in in uboot? + interrupts = <1a 2>; + interrupt-parent = <40000>; + }; + + pci@8000 { + linux,phandle = <8000>; + interrupt-map-mask = <1f800 0 0 7>; + interrupt-map = < + + /* IDSEL 0x10 */ + 08000 0 0 1 40000 30 1 + 08000 0 0 2 40000 31 1 + 08000 0 0 3 40000 32 1 + 08000 0 0 4 40000 33 1 + + /* IDSEL 0x11 */ + 08800 0 0 1 40000 30 1 + 08800 0 0 2 40000 31 1 + 08800 0 0 3 40000 32 1 + 08800 0 0 4 40000 33 1 + + /* IDSEL 0x12 (Slot 1) */ + 09000 0 0 1 40000 30 1 + 09000 0 0 2 40000 31 1 + 09000 0 0 3 40000 32 1 + 09000 0 0 4 40000 33 1 + + /* IDSEL 0x13 (Slot 2) */ + 09800 0 0 1 40000 31 1 + 09800 0 0 2 40000 32 1 + 09800 0 0 3 40000 33 1 + 09800 0 0 4 40000 30 1 + + /* IDSEL 0x14 (Slot 3) */ + 0a000 0 0 1 40000 32 1 + 0a000 0 0 2 40000 33 1 + 0a000 0 0 3 40000 30 1 + 0a000 0 0 4 40000 31 1 + + /* IDSEL 0x15 (Slot 4) */ + 0a800 0 0 1 40000 33 1 + 0a800 0 0 2 40000 30 1 + 0a800 0 0 3 40000 31 1 + 0a800 0 0 4 40000 32 1 + + /* Bus 1 (Tundra Bridge) */ + /* IDSEL 0x12 (ISA bridge) */ + 19000 0 0 1 40000 30 1 + 19000 0 0 2 40000 31 1 + 19000 0 0 3 40000 32 1 + 19000 0 0 4 40000 33 1>; + interrupt-parent = <40000>; + interrupts = <08 2>; + bus-range = <0 0>; + ranges = <02000000 0 80000000 80000000 0 20000000 + 01000000 0 00000000 e2000000 0 00100000>; + clock-frequency = <3f940aa>; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <8000 1000>; + compatible = "85xx"; + device_type = "pci"; + + i8259@19000 { + clock-frequency = <0>; + interrupt-controller; + device_type = "interrupt-controller"; + reg = <19000 0 0 0 1>; + #address-cells = <0>; + #interrupt-cells = <2>; + built-in; + compatible = "chrp,iic"; + big-endian; + interrupts = <1>; + interrupt-parent = <8000>; + }; + }; + + pci@9000 { + linux,phandle = <9000>; + interrupt-map-mask = <f800 0 0 7>; + interrupt-map = < + + /* IDSEL 0x15 */ + a800 0 0 1 40000 3b 1 + a800 0 0 2 40000 3b 1 + a800 0 0 3 40000 3b 1 + a800 0 0 4 40000 3b 1>; + interrupt-parent = <40000>; + interrupts = <09 2>; + bus-range = <0 0>; + ranges = <02000000 0 a0000000 a0000000 0 20000000 + 01000000 0 00000000 e3000000 0 00100000>; + clock-frequency = <3f940aa>; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <9000 1000>; + compatible = "85xx"; + device_type = "pci"; + }; + + pic@40000 { + linux,phandle = <40000>; + clock-frequency = <0>; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <40000 40000>; + built-in; + compatible = "chrp,open-pic"; + device_type = "open-pic"; + big-endian; + }; + }; +}; diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts new file mode 100644 index 000000000..893d7957c --- /dev/null +++ b/arch/powerpc/boot/dts/mpc8548cds.dts @@ -0,0 +1,287 @@ +/* + * MPC8555 CDS Device Tree Source + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + + +/ { + model = "MPC8548CDS"; + compatible = "MPC85xxCDS"; + #address-cells = <1>; + #size-cells = <1>; + linux,phandle = <100>; + + cpus { + #cpus = <1>; + #address-cells = <1>; + #size-cells = <0>; + linux,phandle = <200>; + + PowerPC,8548@0 { + device_type = "cpu"; + reg = <0>; + d-cache-line-size = <20>; // 32 bytes + i-cache-line-size = <20>; // 32 bytes + d-cache-size = <8000>; // L1, 32K + i-cache-size = <8000>; // L1, 32K + timebase-frequency = <0>; // 33 MHz, from uboot + bus-frequency = <0>; // 166 MHz + clock-frequency = <0>; // 825 MHz, from uboot + 32-bit; + linux,phandle = <201>; + }; + }; + + memory { + device_type = "memory"; + linux,phandle = <300>; + reg = <00000000 08000000>; // 128M at 0x0 + }; + + soc8548@e0000000 { + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <2>; + device_type = "soc"; + ranges = <0 e0000000 00100000>; + reg = <e0000000 00100000>; // CCSRBAR 1M + bus-frequency = <0>; + + i2c@3000 { + device_type = "i2c"; + compatible = "fsl-i2c"; + reg = <3000 100>; + interrupts = <1b 2>; + interrupt-parent = <40000>; + dfsrr; + }; + + mdio@24520 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "mdio"; + compatible = "gianfar"; + reg = <24520 20>; + linux,phandle = <24520>; + ethernet-phy@0 { + linux,phandle = <2452000>; + interrupt-parent = <40000>; + interrupts = <35 0>; + reg = <0>; + device_type = "ethernet-phy"; + }; + ethernet-phy@1 { + linux,phandle = <2452001>; + interrupt-parent = <40000>; + interrupts = <35 0>; + reg = <1>; + device_type = "ethernet-phy"; + }; + + ethernet-phy@2 { + linux,phandle = <2452002>; + interrupt-parent = <40000>; + interrupts = <35 0>; + reg = <2>; + device_type = "ethernet-phy"; + }; + ethernet-phy@3 { + linux,phandle = <2452003>; + interrupt-parent = <40000>; + interrupts = <35 0>; + reg = <3>; + device_type = "ethernet-phy"; + }; + }; + + ethernet@24000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "eTSEC"; + compatible = "gianfar"; + reg = <24000 1000>; + local-mac-address = [ 00 E0 0C 00 73 00 ]; + interrupts = <d 2 e 2 12 2>; + interrupt-parent = <40000>; + phy-handle = <2452000>; + }; + + ethernet@25000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "eTSEC"; + compatible = "gianfar"; + reg = <25000 1000>; + local-mac-address = [ 00 E0 0C 00 73 01 ]; + interrupts = <13 2 14 2 18 2>; + interrupt-parent = <40000>; + phy-handle = <2452001>; + }; + + ethernet@26000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "eTSEC"; + compatible = "gianfar"; + reg = <26000 1000>; + local-mac-address = [ 00 E0 0C 00 73 02 ]; + interrupts = <f 2 10 2 11 2>; + interrupt-parent = <40000>; + phy-handle = <2452001>; + }; + +/* eTSEC 4 is currently broken + ethernet@27000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "eTSEC"; + compatible = "gianfar"; + reg = <27000 1000>; + local-mac-address = [ 00 E0 0C 00 73 03 ]; + interrupts = <15 2 16 2 17 2>; + interrupt-parent = <40000>; + phy-handle = <2452001>; + }; + */ + + serial@4500 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4500 100>; // reg base, size + clock-frequency = <0>; // should we fill in in uboot? + interrupts = <1a 2>; + interrupt-parent = <40000>; + }; + + serial@4600 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4600 100>; // reg base, size + clock-frequency = <0>; // should we fill in in uboot? + interrupts = <1a 2>; + interrupt-parent = <40000>; + }; + + pci@8000 { + linux,phandle = <8000>; + interrupt-map-mask = <1f800 0 0 7>; + interrupt-map = < + + /* IDSEL 0x10 */ + 08000 0 0 1 40000 30 1 + 08000 0 0 2 40000 31 1 + 08000 0 0 3 40000 32 1 + 08000 0 0 4 40000 33 1 + + /* IDSEL 0x11 */ + 08800 0 0 1 40000 30 1 + 08800 0 0 2 40000 31 1 + 08800 0 0 3 40000 32 1 + 08800 0 0 4 40000 33 1 + + /* IDSEL 0x12 (Slot 1) */ + 09000 0 0 1 40000 30 1 + 09000 0 0 2 40000 31 1 + 09000 0 0 3 40000 32 1 + 09000 0 0 4 40000 33 1 + + /* IDSEL 0x13 (Slot 2) */ + 09800 0 0 1 40000 31 1 + 09800 0 0 2 40000 32 1 + 09800 0 0 3 40000 33 1 + 09800 0 0 4 40000 30 1 + + /* IDSEL 0x14 (Slot 3) */ + 0a000 0 0 1 40000 32 1 + 0a000 0 0 2 40000 33 1 + 0a000 0 0 3 40000 30 1 + 0a000 0 0 4 40000 31 1 + + /* IDSEL 0x15 (Slot 4) */ + 0a800 0 0 1 40000 33 1 + 0a800 0 0 2 40000 30 1 + 0a800 0 0 3 40000 31 1 + 0a800 0 0 4 40000 32 1 + + /* Bus 1 (Tundra Bridge) */ + /* IDSEL 0x12 (ISA bridge) */ + 19000 0 0 1 40000 30 1 + 19000 0 0 2 40000 31 1 + 19000 0 0 3 40000 32 1 + 19000 0 0 4 40000 33 1>; + interrupt-parent = <40000>; + interrupts = <08 2>; + bus-range = <0 0>; + ranges = <02000000 0 80000000 80000000 0 20000000 + 01000000 0 00000000 e2000000 0 00100000>; + clock-frequency = <3f940aa>; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <8000 1000>; + compatible = "85xx"; + device_type = "pci"; + + i8259@19000 { + clock-frequency = <0>; + interrupt-controller; + device_type = "interrupt-controller"; + reg = <19000 0 0 0 1>; + #address-cells = <0>; + #interrupt-cells = <2>; + built-in; + compatible = "chrp,iic"; + big-endian; + interrupts = <1>; + interrupt-parent = <8000>; + }; + }; + + pci@9000 { + linux,phandle = <9000>; + interrupt-map-mask = <f800 0 0 7>; + interrupt-map = < + + /* IDSEL 0x15 */ + a800 0 0 1 40000 3b 1 + a800 0 0 2 40000 3b 1 + a800 0 0 3 40000 3b 1 + a800 0 0 4 40000 3b 1>; + interrupt-parent = <40000>; + interrupts = <09 2>; + bus-range = <0 0>; + ranges = <02000000 0 a0000000 a0000000 0 20000000 + 01000000 0 00000000 e3000000 0 00100000>; + clock-frequency = <3f940aa>; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <9000 1000>; + compatible = "85xx"; + device_type = "pci"; + }; + + pic@40000 { + linux,phandle = <40000>; + clock-frequency = <0>; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <40000 40000>; + built-in; + compatible = "chrp,open-pic"; + device_type = "open-pic"; + big-endian; + }; + }; +}; diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts new file mode 100644 index 000000000..118f5a887 --- /dev/null +++ b/arch/powerpc/boot/dts/mpc8555cds.dts @@ -0,0 +1,244 @@ +/* + * MPC8555 CDS Device Tree Source + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + + +/ { + model = "MPC8555CDS"; + compatible = "MPC85xxCDS"; + #address-cells = <1>; + #size-cells = <1>; + linux,phandle = <100>; + + cpus { + #cpus = <1>; + #address-cells = <1>; + #size-cells = <0>; + linux,phandle = <200>; + + PowerPC,8555@0 { + device_type = "cpu"; + reg = <0>; + d-cache-line-size = <20>; // 32 bytes + i-cache-line-size = <20>; // 32 bytes + d-cache-size = <8000>; // L1, 32K + i-cache-size = <8000>; // L1, 32K + timebase-frequency = <0>; // 33 MHz, from uboot + bus-frequency = <0>; // 166 MHz + clock-frequency = <0>; // 825 MHz, from uboot + 32-bit; + linux,phandle = <201>; + }; + }; + + memory { + device_type = "memory"; + linux,phandle = <300>; + reg = <00000000 08000000>; // 128M at 0x0 + }; + + soc8555@e0000000 { + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <2>; + device_type = "soc"; + ranges = <0 e0000000 00100000>; + reg = <e0000000 00100000>; // CCSRBAR 1M + bus-frequency = <0>; + + i2c@3000 { + device_type = "i2c"; + compatible = "fsl-i2c"; + reg = <3000 100>; + interrupts = <1b 2>; + interrupt-parent = <40000>; + dfsrr; + }; + + mdio@24520 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "mdio"; + compatible = "gianfar"; + reg = <24520 20>; + linux,phandle = <24520>; + ethernet-phy@0 { + linux,phandle = <2452000>; + interrupt-parent = <40000>; + interrupts = <35 0>; + reg = <0>; + device_type = "ethernet-phy"; + }; + ethernet-phy@1 { + linux,phandle = <2452001>; + interrupt-parent = <40000>; + interrupts = <35 0>; + reg = <1>; + device_type = "ethernet-phy"; + }; + }; + + ethernet@24000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <24000 1000>; + local-mac-address = [ 00 E0 0C 00 73 00 ]; + interrupts = <0d 2 0e 2 12 2>; + interrupt-parent = <40000>; + phy-handle = <2452000>; + }; + + ethernet@25000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <25000 1000>; + local-mac-address = [ 00 E0 0C 00 73 01 ]; + interrupts = <13 2 14 2 18 2>; + interrupt-parent = <40000>; + phy-handle = <2452001>; + }; + + serial@4500 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4500 100>; // reg base, size + clock-frequency = <0>; // should we fill in in uboot? + interrupts = <1a 2>; + interrupt-parent = <40000>; + }; + + serial@4600 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4600 100>; // reg base, size + clock-frequency = <0>; // should we fill in in uboot? + interrupts = <1a 2>; + interrupt-parent = <40000>; + }; + + pci@8000 { + linux,phandle = <8000>; + interrupt-map-mask = <1f800 0 0 7>; + interrupt-map = < + + /* IDSEL 0x10 */ + 08000 0 0 1 40000 30 1 + 08000 0 0 2 40000 31 1 + 08000 0 0 3 40000 32 1 + 08000 0 0 4 40000 33 1 + + /* IDSEL 0x11 */ + 08800 0 0 1 40000 30 1 + 08800 0 0 2 40000 31 1 + 08800 0 0 3 40000 32 1 + 08800 0 0 4 40000 33 1 + + /* IDSEL 0x12 (Slot 1) */ + 09000 0 0 1 40000 30 1 + 09000 0 0 2 40000 31 1 + 09000 0 0 3 40000 32 1 + 09000 0 0 4 40000 33 1 + + /* IDSEL 0x13 (Slot 2) */ + 09800 0 0 1 40000 31 1 + 09800 0 0 2 40000 32 1 + 09800 0 0 3 40000 33 1 + 09800 0 0 4 40000 30 1 + + /* IDSEL 0x14 (Slot 3) */ + 0a000 0 0 1 40000 32 1 + 0a000 0 0 2 40000 33 1 + 0a000 0 0 3 40000 30 1 + 0a000 0 0 4 40000 31 1 + + /* IDSEL 0x15 (Slot 4) */ + 0a800 0 0 1 40000 33 1 + 0a800 0 0 2 40000 30 1 + 0a800 0 0 3 40000 31 1 + 0a800 0 0 4 40000 32 1 + + /* Bus 1 (Tundra Bridge) */ + /* IDSEL 0x12 (ISA bridge) */ + 19000 0 0 1 40000 30 1 + 19000 0 0 2 40000 31 1 + 19000 0 0 3 40000 32 1 + 19000 0 0 4 40000 33 1>; + interrupt-parent = <40000>; + interrupts = <08 2>; + bus-range = <0 0>; + ranges = <02000000 0 80000000 80000000 0 20000000 + 01000000 0 00000000 e2000000 0 00100000>; + clock-frequency = <3f940aa>; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <8000 1000>; + compatible = "85xx"; + device_type = "pci"; + + i8259@19000 { + clock-frequency = <0>; + interrupt-controller; + device_type = "interrupt-controller"; + reg = <19000 0 0 0 1>; + #address-cells = <0>; + #interrupt-cells = <2>; + built-in; + compatible = "chrp,iic"; + big-endian; + interrupts = <1>; + interrupt-parent = <8000>; + }; + }; + + pci@9000 { + linux,phandle = <9000>; + interrupt-map-mask = <f800 0 0 7>; + interrupt-map = < + + /* IDSEL 0x15 */ + a800 0 0 1 40000 3b 1 + a800 0 0 2 40000 3b 1 + a800 0 0 3 40000 3b 1 + a800 0 0 4 40000 3b 1>; + interrupt-parent = <40000>; + interrupts = <09 2>; + bus-range = <0 0>; + ranges = <02000000 0 a0000000 a0000000 0 20000000 + 01000000 0 00000000 e3000000 0 00100000>; + clock-frequency = <3f940aa>; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <9000 1000>; + compatible = "85xx"; + device_type = "pci"; + }; + + pic@40000 { + linux,phandle = <40000>; + clock-frequency = <0>; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <40000 40000>; + built-in; + compatible = "chrp,open-pic"; + device_type = "open-pic"; + big-endian; + }; + }; +}; diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts new file mode 100644 index 000000000..f0c773174 --- /dev/null +++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts @@ -0,0 +1,339 @@ +/* + * MPC8641 HPCN Device Tree Source + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + + +/ { + model = "MPC8641HPCN"; + compatible = "mpc86xx"; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #cpus = <2>; + #address-cells = <1>; + #size-cells = <0>; + + PowerPC,8641@0 { + device_type = "cpu"; + reg = <0>; + d-cache-line-size = <20>; // 32 bytes + i-cache-line-size = <20>; // 32 bytes + d-cache-size = <8000>; // L1, 32K + i-cache-size = <8000>; // L1, 32K + timebase-frequency = <0>; // 33 MHz, from uboot + bus-frequency = <0>; // From uboot + clock-frequency = <0>; // From uboot + 32-bit; + linux,boot-cpu; + }; + PowerPC,8641@1 { + device_type = "cpu"; + reg = <1>; + d-cache-line-size = <20>; // 32 bytes + i-cache-line-size = <20>; // 32 bytes + d-cache-size = <8000>; // L1, 32K + i-cache-size = <8000>; // L1, 32K + timebase-frequency = <0>; // 33 MHz, from uboot + bus-frequency = <0>; // From uboot + clock-frequency = <0>; // From uboot + 32-bit; + }; + }; + + memory { + device_type = "memory"; + reg = <00000000 40000000>; // 1G at 0x0 + }; + + soc8641@f8000000 { + #address-cells = <1>; + #size-cells = <1>; + #interrupt-cells = <2>; + device_type = "soc"; + ranges = <0 f8000000 00100000>; + reg = <f8000000 00100000>; // CCSRBAR 1M + bus-frequency = <0>; + + i2c@3000 { + device_type = "i2c"; + compatible = "fsl-i2c"; + reg = <3000 100>; + interrupts = <2b 2>; + interrupt-parent = <40000>; + dfsrr; + }; + + i2c@3100 { + device_type = "i2c"; + compatible = "fsl-i2c"; + reg = <3100 100>; + interrupts = <2b 2>; + interrupt-parent = <40000>; + dfsrr; + }; + + mdio@24520 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "mdio"; + compatible = "gianfar"; + reg = <24520 20>; + linux,phandle = <24520>; + ethernet-phy@0 { + linux,phandle = <2452000>; + interrupt-parent = <40000>; + interrupts = <4a 1>; + reg = <0>; + device_type = "ethernet-phy"; + }; + ethernet-phy@1 { + linux,phandle = <2452001>; + interrupt-parent = <40000>; + interrupts = <4a 1>; + reg = <1>; + device_type = "ethernet-phy"; + }; + ethernet-phy@2 { + linux,phandle = <2452002>; + interrupt-parent = <40000>; + interrupts = <4a 1>; + reg = <2>; + device_type = "ethernet-phy"; + }; + ethernet-phy@3 { + linux,phandle = <2452003>; + interrupt-parent = <40000>; + interrupts = <4a 1>; + reg = <3>; + device_type = "ethernet-phy"; + }; + }; + + ethernet@24000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <24000 1000>; + mac-address = [ 00 E0 0C 00 73 00 ]; + interrupts = <1d 2 1e 2 22 2>; + interrupt-parent = <40000>; + phy-handle = <2452000>; + }; + + ethernet@25000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <25000 1000>; + mac-address = [ 00 E0 0C 00 73 01 ]; + interrupts = <23 2 24 2 28 2>; + interrupt-parent = <40000>; + phy-handle = <2452001>; + }; + + ethernet@26000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <26000 1000>; + mac-address = [ 00 E0 0C 00 02 FD ]; + interrupts = <1F 2 20 2 21 2>; + interrupt-parent = <40000>; + phy-handle = <2452002>; + }; + + ethernet@27000 { + #address-cells = <1>; + #size-cells = <0>; + device_type = "network"; + model = "TSEC"; + compatible = "gianfar"; + reg = <27000 1000>; + mac-address = [ 00 E0 0C 00 03 FD ]; + interrupts = <25 2 26 2 27 2>; + interrupt-parent = <40000>; + phy-handle = <2452003>; + }; + serial@4500 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4500 100>; + clock-frequency = <0>; + interrupts = <2a 2>; + interrupt-parent = <40000>; + }; + + serial@4600 { + device_type = "serial"; + compatible = "ns16550"; + reg = <4600 100>; + clock-frequency = <0>; + interrupts = <1c 2>; + interrupt-parent = <40000>; + }; + + pci@8000 { + compatible = "86xx"; + device_type = "pci"; + #interrupt-cells = <1>; + #size-cells = <2>; + #address-cells = <3>; + reg = <8000 1000>; + bus-range = <0 fe>; + ranges = <02000000 0 80000000 80000000 0 20000000 + 01000000 0 00000000 e2000000 0 00100000>; + clock-frequency = <1fca055>; + interrupt-parent = <40000>; + interrupts = <18 2>; + interrupt-map-mask = <f800 0 0 7>; + interrupt-map = < + /* IDSEL 0x11 */ + 8800 0 0 1 4d0 3 2 + 8800 0 0 2 4d0 4 2 + 8800 0 0 3 4d0 5 2 + 8800 0 0 4 4d0 6 2 + + /* IDSEL 0x12 */ + 9000 0 0 1 4d0 4 2 + 9000 0 0 2 4d0 5 2 + 9000 0 0 3 4d0 6 2 + 9000 0 0 4 4d0 3 2 + + /* IDSEL 0x13 */ + 9800 0 0 1 4d0 0 0 + 9800 0 0 2 4d0 0 0 + 9800 0 0 3 4d0 0 0 + 9800 0 0 4 4d0 0 0 + + /* IDSEL 0x14 */ + a000 0 0 1 4d0 0 0 + a000 0 0 2 4d0 0 0 + a000 0 0 3 4d0 0 0 + a000 0 0 4 4d0 0 0 + + /* IDSEL 0x15 */ + a800 0 0 1 4d0 0 0 + a800 0 0 2 4d0 0 0 + a800 0 0 3 4d0 0 0 + a800 0 0 4 4d0 0 0 + + /* IDSEL 0x16 */ + b000 0 0 1 4d0 0 0 + b000 0 0 2 4d0 0 0 + b000 0 0 3 4d0 0 0 + b000 0 0 4 4d0 0 0 + + /* IDSEL 0x17 */ + b800 0 0 1 4d0 0 0 + b800 0 0 2 4d0 0 0 + b800 0 0 3 4d0 0 0 + b800 0 0 4 4d0 0 0 + + /* IDSEL 0x18 */ + c000 0 0 1 4d0 0 0 + c000 0 0 2 4d0 0 0 + c000 0 0 3 4d0 0 0 + c000 0 0 4 4d0 0 0 + + /* IDSEL 0x19 */ + c800 0 0 1 4d0 0 0 + c800 0 0 2 4d0 0 0 + c800 0 0 3 4d0 0 0 + c800 0 0 4 4d0 0 0 + + /* IDSEL 0x1a */ + d000 0 0 1 4d0 6 2 + d000 0 0 2 4d0 3 2 + d000 0 0 3 4d0 4 2 + d000 0 0 4 4d0 5 2 + + + /* IDSEL 0x1b */ + d800 0 0 1 4d0 5 2 + d800 0 0 2 4d0 0 0 + d800 0 0 3 4d0 0 0 + d800 0 0 4 4d0 0 0 + + /* IDSEL 0x1c */ + e000 0 0 1 4d0 9 2 + e000 0 0 2 4d0 a 2 + e000 0 0 3 4d0 c 2 + e000 0 0 4 4d0 7 2 + + /* IDSEL 0x1d */ + e800 0 0 1 4d0 9 2 + e800 0 0 2 4d0 a 2 + e800 0 0 3 4d0 b 2 + e800 0 0 4 4d0 0 0 + + /* IDSEL 0x1e */ + f000 0 0 1 4d0 c 2 + f000 0 0 2 4d0 0 0 + f000 0 0 3 4d0 0 0 + f000 0 0 4 4d0 0 0 + + /* IDSEL 0x1f */ + f800 0 0 1 4d0 6 2 + f800 0 0 2 4d0 0 0 + f800 0 0 3 4d0 0 0 + f800 0 0 4 4d0 0 0 + >; + i8259@4d0 { + linux,phandle = <4d0>; + clock-frequency = <0>; + interrupt-controller; + device_type = "interrupt-controller"; + #address-cells = <0>; + #interrupt-cells = <2>; + built-in; + compatible = "chrp,iic"; + big-endian; + interrupts = <49 2>; + interrupt-parent = <40000>; + }; + + }; + pic@40000 { + linux,phandle = <40000>; + clock-frequency = <0>; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <2>; + reg = <40000 40000>; + built-in; + compatible = "chrp,open-pic"; + device_type = "open-pic"; + big-endian; + interrupts = < + 10 2 11 2 12 2 13 2 + 14 2 15 2 16 2 17 2 + 18 2 19 2 1a 2 1b 2 + 1c 2 1d 2 1e 2 1f 2 + 20 2 21 2 22 2 23 2 + 24 2 25 2 26 2 27 2 + 28 2 29 2 2a 2 2b 2 + 2c 2 2d 2 2e 2 2f 2 + 30 2 31 2 32 2 33 2 + 34 2 35 2 36 2 37 2 + 38 2 39 2 2a 2 3b 2 + 3c 2 3d 2 3e 2 3f 2 + 48 1 49 2 4a 1 + >; + interrupt-parent = <40000>; + }; + }; +}; diff --git a/arch/powerpc/configs/chrp32_defconfig b/arch/powerpc/configs/chrp32_defconfig new file mode 100644 index 000000000..bbf2b5f8a --- /dev/null +++ b/arch/powerpc/configs/chrp32_defconfig @@ -0,0 +1,1397 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18-rc6 +# Sun Sep 10 10:22:54 2006 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_IRQ_PER_CPU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +CONFIG_GENERIC_TBSYNC=y +# CONFIG_DEFAULT_UIMAGE is not set + +# +# Processor support +# +CONFIG_CLASSIC32=y +# CONFIG_PPC_52xx is not set +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +# CONFIG_PPC_85xx is not set +# CONFIG_PPC_86xx is not set +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +CONFIG_6xx=y +CONFIG_PPC_FPU=y +# CONFIG_ALTIVEC is not set +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_CPUSETS is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_RT_MUTEXES=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Block layer +# +CONFIG_LBD=y +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# Platform support +# +CONFIG_PPC_MULTIPLATFORM=y +# CONFIG_PPC_ISERIES is not set +# CONFIG_EMBEDDED6xx is not set +# CONFIG_APUS is not set +CONFIG_PPC_CHRP=y +# CONFIG_PPC_PMAC is not set +# CONFIG_PPC_CELL is not set +# CONFIG_PPC_CELL_NATIVE is not set +# CONFIG_UDBG_RTAS_CONSOLE is not set +CONFIG_PPC_RTAS=y +# CONFIG_RTAS_ERROR_LOGGING is not set +CONFIG_RTAS_PROC=y +# CONFIG_MMIO_NVRAM is not set +CONFIG_PPC_MPC106=y +# CONFIG_PPC_970_NAP is not set +# CONFIG_CPU_FREQ is not set +# CONFIG_TAU is not set +# CONFIG_WANT_EARLY_SERIAL is not set +CONFIG_MPIC=y + +# +# Kernel options +# +CONFIG_HIGHMEM=y +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +# CONFIG_KEXEC is not set +CONFIG_IRQ_ALL_CPUS=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_ISA=y +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_MPIC_WEIRD is not set +CONFIG_PPC_I8259=y +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCIEPORTBUS is not set +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# +# Core Netfilter Configuration +# +# CONFIG_NETFILTER_NETLINK is not set +# CONFIG_NETFILTER_XTABLES is not set + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +# CONFIG_IP_NF_CT_ACCT is not set +# CONFIG_IP_NF_CONNTRACK_MARK is not set +# CONFIG_IP_NF_CONNTRACK_EVENTS is not set +# CONFIG_IP_NF_CT_PROTO_SCTP is not set +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +# CONFIG_IP_NF_NETBIOS_NS is not set +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +# CONFIG_IP_NF_PPTP is not set +# CONFIG_IP_NF_H323 is not set +# CONFIG_IP_NF_SIP is not set +# CONFIG_IP_NF_QUEUE is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +# CONFIG_STANDALONE is not set +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +CONFIG_BLK_DEV_FD=y +# CONFIG_BLK_DEV_XD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_SL82C105=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +# CONFIG_IDE_CHIPSETS is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX 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_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA 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_GENERIC_NCR5380_MMIO is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_NCR53C406A is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_DC395x 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 + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +# CONFIG_DE2104X is not set +# CONFIG_TULIP is not set +CONFIG_DE4X5=y +# CONFIG_WINBOND_840 is not set +# CONFIG_DM9102 is not set +# CONFIG_ULI526X is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_CS89x0 is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +CONFIG_8139CP=y +CONFIG_8139TOO=y +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +CONFIG_VIA_RHINE=y +# CONFIG_VIA_RHINE_MMIO is not set +# CONFIG_VIA_RHINE_NAPI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_MV643XX_ETH=y +# CONFIG_MV643XX_ETH_0 is not set +# CONFIG_MV643XX_ETH_1 is not set +# CONFIG_MV643XX_ETH_2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_PCSPKR is not set +CONFIG_INPUT_UINPUT=y + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_HVC_RTAS is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set +CONFIG_NVRAM=y +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +# CONFIG_I2C_CHARDEV is not set + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_HYDRA is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_MPC is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +CONFIG_FIRMWARE_EDID=y +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_MACMODES=y +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_OF=y +# CONFIG_FB_CT65550 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_VGA16 is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +CONFIG_FB_MATROX=y +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +# CONFIG_FB_MATROX_I2C is not set +# CONFIG_FB_MATROX_MULTIHEAD is not set +CONFIG_FB_RADEON=y +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +# CONFIG_FB_ATY128 is not set +CONFIG_FB_ATY=y +CONFIG_FB_ATY_CT=y +# CONFIG_FB_ATY_GENERIC_LCD is not set +CONFIG_FB_ATY_GX=y +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +CONFIG_FB_3DFX=y +# CONFIG_FB_3DFX_ACCEL is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +# CONFIG_USB_EHCI_SPLIT_ISO is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# 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_USBAT 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_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +CONFIG_MSDOS_PARTITION=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 is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# 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 + +# +# Library routines +# +CONFIG_CRC_CCITT=m +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=m +CONFIG_ZLIB_DEFLATE=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_PLIST=y + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=15 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RWSEMS is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUGGER=y +CONFIG_XMON=y +CONFIG_XMON_DEFAULT=y +# CONFIG_BDI_SWITCH is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +CONFIG_CRYPTO_SHA1=m +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_ARC4=m +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# diff --git a/arch/powerpc/configs/mpc7448_hpc2_defconfig b/arch/powerpc/configs/mpc7448_hpc2_defconfig new file mode 100644 index 000000000..719fba4eb --- /dev/null +++ b/arch/powerpc/configs/mpc7448_hpc2_defconfig @@ -0,0 +1,963 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18-rc6 +# Sun Sep 10 10:26:55 2006 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_IRQ_PER_CPU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +# CONFIG_GENERIC_TBSYNC is not set +CONFIG_DEFAULT_UIMAGE=y + +# +# Processor support +# +CONFIG_CLASSIC32=y +# CONFIG_PPC_52xx is not set +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +# CONFIG_PPC_85xx is not set +# CONFIG_PPC_86xx is not set +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +CONFIG_6xx=y +CONFIG_PPC_FPU=y +# CONFIG_ALTIVEC is not set +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +# CONFIG_SMP is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_RT_MUTEXES=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Block layer +# +CONFIG_LBD=y +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# +# Platform support +# +# CONFIG_PPC_MULTIPLATFORM is not set +# CONFIG_PPC_ISERIES is not set +CONFIG_EMBEDDED6xx=y +# CONFIG_APUS is not set +# CONFIG_PPC_CELL is not set +# CONFIG_PPC_CELL_NATIVE is not set +# CONFIG_UDBG_RTAS_CONSOLE is not set +# CONFIG_PPC_RTAS is not set +# CONFIG_MMIO_NVRAM is not set +# CONFIG_PPC_MPC106 is not set +# CONFIG_PPC_970_NAP is not set +# CONFIG_CPU_FREQ is not set +# CONFIG_TAU is not set +# CONFIG_PPC_TODC is not set +# CONFIG_KATANA is not set +# CONFIG_WILLOW is not set +# CONFIG_CPCI690 is not set +# CONFIG_POWERPMC250 is not set +# CONFIG_CHESTNUT is not set +# CONFIG_SPRUCE is not set +# CONFIG_HDPU is not set +# CONFIG_EV64260 is not set +# CONFIG_LOPEC is not set +# CONFIG_MVME5100 is not set +# CONFIG_PPLUS is not set +# CONFIG_PRPMC750 is not set +# CONFIG_PRPMC800 is not set +# CONFIG_SANDPOINT is not set +CONFIG_MPC7448HPC2=y +# CONFIG_RADSTONE_PPC7D is not set +# CONFIG_PAL4 is not set +# CONFIG_GEMINI is not set +# CONFIG_EST8260 is not set +# CONFIG_SBC82xx is not set +# CONFIG_SBS8260 is not set +# CONFIG_RPX8260 is not set +# CONFIG_TQM8260 is not set +# CONFIG_ADS8272 is not set +# CONFIG_PQ2FADS is not set +# CONFIG_LITE5200 is not set +# CONFIG_EV64360 is not set +CONFIG_TSI108_BRIDGE=y +# CONFIG_WANT_EARLY_SERIAL is not set +CONFIG_MPIC=y + +# +# Kernel options +# +# CONFIG_HIGHMEM is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +# CONFIG_SECCOMP is not set +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_GENERIC_ISA_DMA=y +CONFIG_MPIC_WEIRD=y +# CONFIG_PPC_I8259 is not set +# CONFIG_PPC_INDIRECT_PCI is not set +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCIEPORTBUS is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=131072 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +CONFIG_SCSI_SATA=y +# CONFIG_SCSI_SATA_AHCI is not set +# CONFIG_SCSI_SATA_SVW is not set +# CONFIG_SCSI_ATA_PIIX is not set +CONFIG_SCSI_SATA_MV=y +# CONFIG_SCSI_SATA_NV is not set +# CONFIG_SCSI_PDC_ADMA is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_SATA_QSTOR is not set +# CONFIG_SCSI_SATA_PROMISE is not set +# CONFIG_SCSI_SATA_SX4 is not set +# CONFIG_SCSI_SATA_SIL is not set +# CONFIG_SCSI_SATA_SIL24 is not set +# CONFIG_SCSI_SATA_SIS is not set +# CONFIG_SCSI_SATA_ULI is not set +# CONFIG_SCSI_SATA_VIA is not set +# CONFIG_SCSI_SATA_VITESSE is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_FIXED_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +CONFIG_8139TOO=y +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FIRMWARE_EDID=y +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=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 is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_FS is not set +# CONFIG_UNWIND_INFO is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# diff --git a/arch/powerpc/configs/mpc834x_itx_defconfig b/arch/powerpc/configs/mpc834x_itx_defconfig new file mode 100644 index 000000000..8da6a47f0 --- /dev/null +++ b/arch/powerpc/configs/mpc834x_itx_defconfig @@ -0,0 +1,1344 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18-rc6 +# Sun Sep 10 10:28:05 2006 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_IRQ_PER_CPU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +# CONFIG_GENERIC_TBSYNC is not set +CONFIG_DEFAULT_UIMAGE=y + +# +# Processor support +# +# CONFIG_CLASSIC32 is not set +# CONFIG_PPC_52xx is not set +# CONFIG_PPC_82xx is not set +CONFIG_PPC_83xx=y +# CONFIG_PPC_85xx is not set +# CONFIG_PPC_86xx is not set +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +CONFIG_6xx=y +CONFIG_83xx=y +CONFIG_PPC_FPU=y +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +# CONFIG_SMP is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_EMBEDDED=y +# CONFIG_KALLSYMS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_RT_MUTEXES=y +CONFIG_FUTEX=y +# CONFIG_EPOLL is not set +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set + +# +# Block layer +# +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_PPC_GEN550=y +# CONFIG_WANT_EARLY_SERIAL is not set + +# +# Platform support +# +# CONFIG_MPC834x_SYS is not set +CONFIG_MPC834x_ITX=y +CONFIG_MPC834x=y +# CONFIG_MPIC is not set + +# +# Kernel options +# +# CONFIG_HIGHMEM is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_MPIC_WEIRD is not set +# CONFIG_PPC_I8259 is not set +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_FSL_SOC=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCIEPORTBUS is not set +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_PARTITIONS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +# CONFIG_MTD_BLOCK is not set +# CONFIG_MTD_BLOCK_RO is not set +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0xfe000000 +CONFIG_MTD_PHYSMAP_LEN=0x1000000 +CONFIG_MTD_PHYSMAP_BANKWIDTH=2 +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_M25P80 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=32768 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +# CONFIG_BLK_DEV_IDE is not set +# CONFIG_BLK_DEV_HD_ONLY is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set + +# +# SCSI low-level drivers +# +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +CONFIG_SCSI_SATA=y +# CONFIG_SCSI_SATA_AHCI is not set +# CONFIG_SCSI_SATA_SVW is not set +# CONFIG_SCSI_ATA_PIIX is not set +# CONFIG_SCSI_SATA_MV is not set +# CONFIG_SCSI_SATA_NV is not set +# CONFIG_SCSI_PDC_ADMA is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_SATA_QSTOR is not set +# CONFIG_SCSI_SATA_PROMISE is not set +# CONFIG_SCSI_SATA_SX4 is not set +CONFIG_SCSI_SATA_SIL=y +# CONFIG_SCSI_SATA_SIL24 is not set +# CONFIG_SCSI_SATA_SIS is not set +# CONFIG_SCSI_SATA_ULI is not set +# CONFIG_SCSI_SATA_VIA is not set +# CONFIG_SCSI_SATA_VITESSE is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +# CONFIG_MD_RAID10 is not set +# CONFIG_MD_RAID456 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_MD_FAULTY is not set +# CONFIG_BLK_DEV_DM is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_SPI is not set +# CONFIG_FUSION_FC is not set +# CONFIG_FUSION_SAS is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +CONFIG_CICADA_PHY=y +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_FIXED_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_GIANFAR=y +CONFIG_GFAR_NAPI=y + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_83xx_WDT=y + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set +CONFIG_HW_RANDOM=y +# CONFIG_NVRAM is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_MPC=y +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +CONFIG_SPI_BITBANG=y +CONFIG_SPI_MPC83xx=y + +# +# SPI Protocol Masters +# + +# +# Dallas's 1-wire bus +# + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set + +# +# Graphics support +# +CONFIG_FIRMWARE_EDID=y +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_SPLIT_ISO is not set +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +# CONFIG_USB_ISP116X_HCD is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=y +# CONFIG_USB_SL811_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_USBAT 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_ALAUDA is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Input Devices +# +# CONFIG_USB_HID is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_ACECAD is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_TOUCHSCREEN is not set +# CONFIG_USB_YEALINK is not set +# CONFIG_USB_XPAD is not set +# CONFIG_USB_ATI_REMOTE is not set +# CONFIG_USB_ATI_REMOTE2 is not set +# CONFIG_USB_KEYSPAN_REMOTE is not set +# CONFIG_USB_APPLETOUCH is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +CONFIG_USB_MON=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGETKIT is not set +# CONFIG_USB_PHIDGETSERVO is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TEST is not set + +# +# USB DSL modem support +# + +# +# USB Gadget Support +# +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_SELECTED=y +CONFIG_USB_GADGET_NET2280=y +CONFIG_USB_NET2280=y +# CONFIG_USB_GADGET_PXA2XX is not set +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_LH7A40X is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_AT91 is not set +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_ZERO is not set +CONFIG_USB_ETH=y +CONFIG_USB_ETH_RNDIS=y +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y + +# +# RTC drivers +# +# CONFIG_RTC_DRV_X1205 is not set +CONFIG_RTC_DRV_DS1307=y +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=y + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +CONFIG_PRINTK_TIME=y +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_DEBUGGER is not set +# CONFIG_BDI_SWITCH is not set +CONFIG_BOOTX_TEXT=y +CONFIG_SERIAL_TEXT_DEBUG=y +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# diff --git a/arch/powerpc/configs/mpc834x_mds_defconfig b/arch/powerpc/configs/mpc834x_mds_defconfig new file mode 100644 index 000000000..9eefab967 --- /dev/null +++ b/arch/powerpc/configs/mpc834x_mds_defconfig @@ -0,0 +1,971 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18-rc6 +# Sun Sep 10 10:28:54 2006 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_IRQ_PER_CPU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +# CONFIG_GENERIC_TBSYNC is not set +CONFIG_DEFAULT_UIMAGE=y + +# +# Processor support +# +# CONFIG_CLASSIC32 is not set +# CONFIG_PPC_52xx is not set +# CONFIG_PPC_82xx is not set +CONFIG_PPC_83xx=y +# CONFIG_PPC_85xx is not set +# CONFIG_PPC_86xx is not set +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +CONFIG_6xx=y +CONFIG_83xx=y +CONFIG_PPC_FPU=y +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +# CONFIG_SMP is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_EMBEDDED=y +# CONFIG_KALLSYMS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_RT_MUTEXES=y +CONFIG_FUTEX=y +# CONFIG_EPOLL is not set +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +# CONFIG_KMOD is not set + +# +# Block layer +# +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +CONFIG_PPC_GEN550=y +# CONFIG_WANT_EARLY_SERIAL is not set + +# +# Platform support +# +CONFIG_MPC834x_SYS=y +# CONFIG_MPC834x_ITX is not set +CONFIG_MPC834x=y +# CONFIG_MPIC is not set + +# +# Kernel options +# +# CONFIG_HIGHMEM is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +CONFIG_SECCOMP=y +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_MPIC_WEIRD is not set +# CONFIG_PPC_I8259 is not set +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_FSL_SOC=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCIEPORTBUS is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=m +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=32768 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=y +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_FIXED_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_GIANFAR=y +# CONFIG_GFAR_NAPI is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_83xx_WDT=y + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_MPC=y +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_FSCPOS is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FIRMWARE_EDID=y +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +CONFIG_RPCSEC_GSS_KRB5=y +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_DEBUG_FS is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_SERIAL_TEXT_DEBUG is not set +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_WP512 is not set +# CONFIG_CRYPTO_TGR192 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Hardware crypto devices +# diff --git a/arch/powerpc/configs/mpc85xx_cds_defconfig b/arch/powerpc/configs/mpc85xx_cds_defconfig new file mode 100644 index 000000000..72edf9f66 --- /dev/null +++ b/arch/powerpc/configs/mpc85xx_cds_defconfig @@ -0,0 +1,895 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18-rc6 +# Sun Sep 10 10:29:49 2006 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_IRQ_PER_CPU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +# CONFIG_GENERIC_TBSYNC is not set +CONFIG_DEFAULT_UIMAGE=y + +# +# Processor support +# +# CONFIG_CLASSIC32 is not set +# CONFIG_PPC_52xx is not set +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +CONFIG_PPC_85xx=y +# CONFIG_PPC_86xx is not set +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +CONFIG_85xx=y +CONFIG_E500=y +CONFIG_BOOKE=y +CONFIG_FSL_BOOKE=y +# CONFIG_PHYS_64BIT is not set +CONFIG_SPE=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_RT_MUTEXES=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Block layer +# +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" +# CONFIG_WANT_EARLY_SERIAL is not set + +# +# Platform support +# +# CONFIG_MPC8540_ADS is not set +CONFIG_MPC85xx_CDS=y +CONFIG_MPC8540=y +CONFIG_PPC_INDIRECT_PCI_BE=y +CONFIG_MPIC=y + +# +# Kernel options +# +# CONFIG_HIGHMEM is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_MATH_EMULATION=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +# CONFIG_SECCOMP is not set +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +# CONFIG_MPIC_WEIRD is not set +# CONFIG_PPC_I8259 is not set +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_FSL_SOC=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCIEPORTBUS is not set +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=32768 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +# CONFIG_BLK_DEV_IDEDISK is not set +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_SL82C105 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +# CONFIG_IDEDMA_PCI_AUTO is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_FIXED_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=y +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_GIANFAR=y +CONFIG_GFAR_NAPI=y + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# + +# +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FIRMWARE_EDID=y +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_DEBUGGER is not set +# CONFIG_BDI_SWITCH is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# diff --git a/arch/powerpc/configs/mpc8641_hpcn_defconfig b/arch/powerpc/configs/mpc8641_hpcn_defconfig new file mode 100644 index 000000000..92a527fcc --- /dev/null +++ b/arch/powerpc/configs/mpc8641_hpcn_defconfig @@ -0,0 +1,963 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18-rc6 +# Sun Sep 10 10:30:15 2006 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_IRQ_PER_CPU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +CONFIG_GENERIC_TBSYNC=y +# CONFIG_DEFAULT_UIMAGE is not set + +# +# Processor support +# +# CONFIG_CLASSIC32 is not set +# CONFIG_PPC_52xx is not set +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +# CONFIG_PPC_85xx is not set +CONFIG_PPC_86xx=y +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +CONFIG_6xx=y +CONFIG_PPC_FPU=y +CONFIG_ALTIVEC=y +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +CONFIG_SMP=y +CONFIG_NR_CPUS=2 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +# CONFIG_SWAP is not set +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_CPUSETS is not set +# CONFIG_RELAY is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +# CONFIG_ELF_CORE is not set +CONFIG_BASE_FULL=y +CONFIG_RT_MUTEXES=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +# CONFIG_SLAB is not set +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_SLOB=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Block layer +# +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +CONFIG_DEFAULT_DEADLINE=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="deadline" +# CONFIG_WANT_EARLY_SERIAL is not set +CONFIG_PPC_INDIRECT_PCI_BE=y +CONFIG_MPIC=y + +# +# Platform Support +# +CONFIG_MPC8641_HPCN=y +CONFIG_MPC8641=y + +# +# Kernel options +# +CONFIG_HIGHMEM=y +# CONFIG_HZ_100 is not set +# CONFIG_HZ_250 is not set +CONFIG_HZ_1000=y +CONFIG_HZ=1000 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +# CONFIG_IRQ_ALL_CPUS is not set +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_RESOURCES_64BIT is not set +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +# CONFIG_PM is not set +# CONFIG_SECCOMP is not set +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_MPIC_WEIRD is not set +CONFIG_PPC_I8259=y +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_FSL_SOC=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCIEPORTBUS is not set +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +# CONFIG_ADVANCED_OPTIONS is not set + +# +# Default settings for advanced configuration options are used +# +CONFIG_HIGHMEM_START=0xfe000000 +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_KERNEL_START=0xc0000000 +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +# CONFIG_IPV6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set + +# +# DCCP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_DCCP is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +# CONFIG_CONNECTOR is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=131072 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +CONFIG_VITESSE_PHY=y +# CONFIG_SMSC_PHY is not set +# CONFIG_FIXED_PHY is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +CONFIG_GIANFAR=y +# CONFIG_GFAR_NAPI is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_CHELSIO_T1 is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_NR_UARTS=2 +CONFIG_SERIAL_8250_RUNTIME_UARTS=2 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +# CONFIG_I2C_CHARDEV is not set + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_MPC=y +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set +# CONFIG_I2C_PCA_ISA is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +CONFIG_SENSORS_EEPROM=y +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_M41T00 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FIRMWARE_EDID=y +# CONFIG_FB is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +CONFIG_NFSD_TCP=y +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_RPCSEC_GSS_KRB5 is not set +# CONFIG_RPCSEC_GSS_SPKM3 is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +# CONFIG_9P_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=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=y +# CONFIG_LDM_DEBUG is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# 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 + +# +# Library routines +# +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC32=y +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y + +# +# Instrumentation Support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_DETECT_SOFTLOCKUP=y +# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_UNWIND_INFO is not set +CONFIG_FORCED_INLINING=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_DEBUGGER is not set +# CONFIG_BDI_SWITCH is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Hardware crypto devices +# diff --git a/arch/powerpc/kernel/audit.c b/arch/powerpc/kernel/audit.c new file mode 100644 index 000000000..7fe5e6300 --- /dev/null +++ b/arch/powerpc/kernel/audit.c @@ -0,0 +1,66 @@ +#include <linux/init.h> +#include <linux/types.h> +#include <linux/audit.h> +#include <asm/unistd.h> + +static unsigned dir_class[] = { +#include <asm-generic/audit_dir_write.h> +~0U +}; + +static unsigned read_class[] = { +#include <asm-generic/audit_read.h> +~0U +}; + +static unsigned write_class[] = { +#include <asm-generic/audit_write.h> +~0U +}; + +static unsigned chattr_class[] = { +#include <asm-generic/audit_change_attr.h> +~0U +}; + +int audit_classify_syscall(int abi, unsigned syscall) +{ +#ifdef CONFIG_PPC64 + extern int ppc32_classify_syscall(unsigned); + if (abi == AUDIT_ARCH_PPC) + return ppc32_classify_syscall(syscall); +#endif + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_socketcall: + return 4; + case __NR_execve: + return 5; + default: + return 0; + } +} + +static int __init audit_classes_init(void) +{ +#ifdef CONFIG_PPC64 + extern __u32 ppc32_dir_class[]; + extern __u32 ppc32_write_class[]; + extern __u32 ppc32_read_class[]; + extern __u32 ppc32_chattr_class[]; + audit_register_class(AUDIT_CLASS_WRITE_32, ppc32_write_class); + audit_register_class(AUDIT_CLASS_READ_32, ppc32_read_class); + audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ppc32_dir_class); + audit_register_class(AUDIT_CLASS_CHATTR_32, ppc32_chattr_class); +#endif + audit_register_class(AUDIT_CLASS_WRITE, write_class); + audit_register_class(AUDIT_CLASS_READ, read_class); + audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); + audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); + return 0; +} + +__initcall(audit_classes_init); diff --git a/arch/powerpc/kernel/compat_audit.c b/arch/powerpc/kernel/compat_audit.c new file mode 100644 index 000000000..640d4bb29 --- /dev/null +++ b/arch/powerpc/kernel/compat_audit.c @@ -0,0 +1,38 @@ +#undef __powerpc64__ +#include <asm/unistd.h> + +unsigned ppc32_dir_class[] = { +#include <asm-generic/audit_dir_write.h> +~0U +}; + +unsigned ppc32_chattr_class[] = { +#include <asm-generic/audit_change_attr.h> +~0U +}; + +unsigned ppc32_write_class[] = { +#include <asm-generic/audit_write.h> +~0U +}; + +unsigned ppc32_read_class[] = { +#include <asm-generic/audit_read.h> +~0U +}; + +int ppc32_classify_syscall(unsigned syscall) +{ + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_socketcall: + return 4; + case __NR_execve: + return 5; + default: + return 1; + } +} diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S new file mode 100644 index 000000000..f770805f1 --- /dev/null +++ b/arch/powerpc/kernel/misc.S @@ -0,0 +1,204 @@ +/* + * This file contains miscellaneous low-level functions. + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) + * and Paul Mackerras. + * + * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com) + * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include <asm/ppc_asm.h> + + .text + +/* + * Returns (address we are running at) - (address we were linked at) + * for use before the text and data are mapped to KERNELBASE. + */ + +_GLOBAL(reloc_offset) + mflr r0 + bl 1f +1: mflr r3 + LOAD_REG_IMMEDIATE(r4,1b) + subf r3,r4,r3 + mtlr r0 + blr + +/* + * add_reloc_offset(x) returns x + reloc_offset(). + */ +_GLOBAL(add_reloc_offset) + mflr r0 + bl 1f +1: mflr r5 + LOAD_REG_IMMEDIATE(r4,1b) + subf r5,r4,r5 + add r3,r3,r5 + mtlr r0 + blr + +/* + * I/O string operations + * + * insb(port, buf, len) + * outsb(port, buf, len) + * insw(port, buf, len) + * outsw(port, buf, len) + * insl(port, buf, len) + * outsl(port, buf, len) + * insw_ns(port, buf, len) + * outsw_ns(port, buf, len) + * insl_ns(port, buf, len) + * outsl_ns(port, buf, len) + * + * The *_ns versions don't do byte-swapping. + */ +_GLOBAL(_insb) + sync + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,1 + blelr- +00: lbz r5,0(r3) + eieio + stbu r5,1(r4) + bdnz 00b + twi 0,r5,0 + isync + blr + +_GLOBAL(_outsb) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,1 + blelr- + sync +00: lbzu r5,1(r4) + stb r5,0(r3) + bdnz 00b + sync + blr + +_GLOBAL(_insw) + sync + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,2 + blelr- +00: lhbrx r5,0,r3 + eieio + sthu r5,2(r4) + bdnz 00b + twi 0,r5,0 + isync + blr + +_GLOBAL(_outsw) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,2 + blelr- + sync +00: lhzu r5,2(r4) + sthbrx r5,0,r3 + bdnz 00b + sync + blr + +_GLOBAL(_insl) + sync + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,4 + blelr- +00: lwbrx r5,0,r3 + eieio + stwu r5,4(r4) + bdnz 00b + twi 0,r5,0 + isync + blr + +_GLOBAL(_outsl) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,4 + blelr- + sync +00: lwzu r5,4(r4) + stwbrx r5,0,r3 + bdnz 00b + sync + blr + +#ifdef CONFIG_PPC32 +_GLOBAL(__ide_mm_insw) +#endif +_GLOBAL(_insw_ns) + sync + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,2 + blelr- +00: lhz r5,0(r3) + eieio + sthu r5,2(r4) + bdnz 00b + twi 0,r5,0 + isync + blr + +#ifdef CONFIG_PPC32 +_GLOBAL(__ide_mm_outsw) +#endif +_GLOBAL(_outsw_ns) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,2 + blelr- + sync +00: lhzu r5,2(r4) + sth r5,0(r3) + bdnz 00b + sync + blr + +#ifdef CONFIG_PPC32 +_GLOBAL(__ide_mm_insl) +#endif +_GLOBAL(_insl_ns) + sync + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,4 + blelr- +00: lwz r5,0(r3) + eieio + stwu r5,4(r4) + bdnz 00b + twi 0,r5,0 + isync + blr + +#ifdef CONFIG_PPC32 +_GLOBAL(__ide_mm_outsl) +#endif +_GLOBAL(_outsl_ns) + cmpwi 0,r5,0 + mtctr r5 + subi r4,r4,4 + blelr- + sync +00: lwzu r5,4(r4) + stw r5,0(r3) + bdnz 00b + sync + blr + diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c new file mode 100644 index 000000000..8eed8723d --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c @@ -0,0 +1,124 @@ +/* + * arch/powerpc/platforms/83xx/mpc834x_itx.c + * + * MPC834x ITX board specific routines + * + * Maintainer: Kumar Gala <galak@kernel.crashing.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/reboot.h> +#include <linux/pci.h> +#include <linux/kdev_t.h> +#include <linux/major.h> +#include <linux/console.h> +#include <linux/delay.h> +#include <linux/seq_file.h> +#include <linux/root_dev.h> + +#include <asm/system.h> +#include <asm/atomic.h> +#include <asm/time.h> +#include <asm/io.h> +#include <asm/machdep.h> +#include <asm/ipic.h> +#include <asm/bootinfo.h> +#include <asm/irq.h> +#include <asm/prom.h> +#include <asm/udbg.h> +#include <sysdev/fsl_soc.h> + +#include "mpc83xx.h" + +#include <platforms/83xx/mpc834x_sys.h> + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + +/* ************************************************************************ + * + * Setup the architecture + * + */ +static void __init mpc834x_itx_setup_arch(void) +{ + struct device_node *np; + + if (ppc_md.progress) + ppc_md.progress("mpc834x_itx_setup_arch()", 0); + + np = of_find_node_by_type(NULL, "cpu"); + if (np != 0) { + unsigned int *fp = + (int *)get_property(np, "clock-frequency", NULL); + if (fp != 0) + loops_per_jiffy = *fp / HZ; + else + loops_per_jiffy = 50000000 / HZ; + of_node_put(np); + } +#ifdef CONFIG_PCI + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + add_bridge(np); + + ppc_md.pci_exclude_device = mpc83xx_exclude_device; +#endif + +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif +} + +void __init mpc834x_itx_init_IRQ(void) +{ + struct device_node *np; + + np = of_find_node_by_type(NULL, "ipic"); + if (!np) + return; + + ipic_init(np, 0); + + /* Initialize the default interrupt mapping priorities, + * in case the boot rom changed something on us. + */ + ipic_set_default_priority(); +} + +/* + * Called very early, MMU is off, device-tree isn't unflattened + */ +static int __init mpc834x_itx_probe(void) +{ + /* We always match for now, eventually we should look at the flat + dev tree to ensure this is the board we are suppose to run on + */ + return 1; +} + +define_machine(mpc834x_itx) { + .name = "MPC834x ITX", + .probe = mpc834x_itx_probe, + .setup_arch = mpc834x_itx_setup_arch, + .init_IRQ = mpc834x_itx_init_IRQ, + .get_irq = ipic_get_irq, + .restart = mpc83xx_restart, + .time_init = mpc83xx_time_init, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +#ifdef CONFIG_PCI + .pcibios_fixup = mpc83xx_pcibios_fixup, +#endif +}; diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.h b/arch/powerpc/platforms/83xx/mpc834x_itx.h new file mode 100644 index 000000000..174ca4ef5 --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc834x_itx.h @@ -0,0 +1,23 @@ +/* + * arch/powerpc/platforms/83xx/mpc834x_itx.h + * + * MPC834X ITX common board definitions + * + * Maintainer: Kumar Gala <galak@kernel.crashing.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __MACH_MPC83XX_ITX_H__ +#define __MACH_MPC83XX_ITX_H__ + +#define PIRQA MPC83xx_IRQ_EXT4 +#define PIRQB MPC83xx_IRQ_EXT5 +#define PIRQC MPC83xx_IRQ_EXT6 +#define PIRQD MPC83xx_IRQ_EXT7 + +#endif /* __MACH_MPC83XX_ITX_H__ */ diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.c b/arch/powerpc/platforms/85xx/mpc85xx_cds.c new file mode 100644 index 000000000..76b827ca8 --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.c @@ -0,0 +1,324 @@ +/* + * MPC85xx setup and early boot code plus other random bits. + * + * Maintained by Kumar Gala (see MAINTAINERS for contact information) + * + * Copyright 2005 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/reboot.h> +#include <linux/pci.h> +#include <linux/kdev_t.h> +#include <linux/major.h> +#include <linux/console.h> +#include <linux/delay.h> +#include <linux/seq_file.h> +#include <linux/root_dev.h> +#include <linux/initrd.h> +#include <linux/module.h> +#include <linux/fsl_devices.h> + +#include <asm/system.h> +#include <asm/pgtable.h> +#include <asm/page.h> +#include <asm/atomic.h> +#include <asm/time.h> +#include <asm/io.h> +#include <asm/machdep.h> +#include <asm/ipic.h> +#include <asm/bootinfo.h> +#include <asm/pci-bridge.h> +#include <asm/mpc85xx.h> +#include <asm/irq.h> +#include <mm/mmu_decl.h> +#include <asm/prom.h> +#include <asm/udbg.h> +#include <asm/mpic.h> +#include <asm/i8259.h> + +#include <sysdev/fsl_soc.h> +#include "mpc85xx.h" + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + +static int cds_pci_slot = 2; +static volatile u8 *cadmus; + + +#ifdef CONFIG_PCI + +#define ARCADIA_HOST_BRIDGE_IDSEL 17 +#define ARCADIA_2ND_BRIDGE_IDSEL 3 + +extern int mpc85xx_pci2_busno; + +int +mpc85xx_exclude_device(u_char bus, u_char devfn) +{ + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (mpc85xx_pci2_busno) + if (bus == (mpc85xx_pci2_busno) && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + /* We explicitly do not go past the Tundra 320 Bridge */ + if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) + return PCIBIOS_DEVICE_NOT_FOUND; + if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) + return PCIBIOS_DEVICE_NOT_FOUND; + else + return PCIBIOS_SUCCESSFUL; +} + +void __init +mpc85xx_cds_pcibios_fixup(void) +{ + struct pci_dev *dev; + u_char c; + + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_1, NULL))) { + /* + * U-Boot does not set the enable bits + * for the IDE device. Force them on here. + */ + pci_read_config_byte(dev, 0x40, &c); + c |= 0x03; /* IDE: Chip Enable Bits */ + pci_write_config_byte(dev, 0x40, c); + + /* + * Since only primary interface works, force the + * IDE function to standard primary IDE interrupt + * w/ 8259 offset + */ + dev->irq = 14; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + pci_dev_put(dev); + } + + /* + * Force legacy USB interrupt routing + */ + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_2, NULL))) { + dev->irq = 10; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10); + pci_dev_put(dev); + } + + if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, + PCI_DEVICE_ID_VIA_82C586_2, dev))) { + dev->irq = 11; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11); + pci_dev_put(dev); + } + + /* Now map all the PCI irqs */ + dev = NULL; + for_each_pci_dev(dev) + pci_read_irq_line(dev); +} + +#ifdef CONFIG_PPC_I8259 +#warning The i8259 PIC support is currently broken +static void mpc85xx_8259_cascade(unsigned int irq, struct + irq_desc *desc, struct pt_regs *regs) +{ + unsigned int cascade_irq = i8259_irq(regs); + + if (cascade_irq != NO_IRQ) + generic_handle_irq(cascade_irq, regs); + + desc->chip->eoi(irq); +} +#endif /* PPC_I8259 */ +#endif /* CONFIG_PCI */ + +void __init mpc85xx_cds_pic_init(void) +{ + struct mpic *mpic; + struct resource r; + struct device_node *np = NULL; + struct device_node *cascade_node = NULL; + int cascade_irq; + + np = of_find_node_by_type(np, "open-pic"); + + if (np == NULL) { + printk(KERN_ERR "Could not find open-pic node\n"); + return; + } + + if (of_address_to_resource(np, 0, &r)) { + printk(KERN_ERR "Failed to map mpic register space\n"); + of_node_put(np); + return; + } + + mpic = mpic_alloc(np, r.start, + MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, + 4, 0, " OpenPIC "); + BUG_ON(mpic == NULL); + + /* Return the mpic node */ + of_node_put(np); + + mpic_assign_isu(mpic, 0, r.start + 0x10200); + mpic_assign_isu(mpic, 1, r.start + 0x10280); + mpic_assign_isu(mpic, 2, r.start + 0x10300); + mpic_assign_isu(mpic, 3, r.start + 0x10380); + mpic_assign_isu(mpic, 4, r.start + 0x10400); + mpic_assign_isu(mpic, 5, r.start + 0x10480); + mpic_assign_isu(mpic, 6, r.start + 0x10500); + mpic_assign_isu(mpic, 7, r.start + 0x10580); + + /* Used only for 8548 so far, but no harm in + * allocating them for everyone */ + mpic_assign_isu(mpic, 8, r.start + 0x10600); + mpic_assign_isu(mpic, 9, r.start + 0x10680); + mpic_assign_isu(mpic, 10, r.start + 0x10700); + mpic_assign_isu(mpic, 11, r.start + 0x10780); + + /* External Interrupts */ + mpic_assign_isu(mpic, 12, r.start + 0x10000); + mpic_assign_isu(mpic, 13, r.start + 0x10080); + mpic_assign_isu(mpic, 14, r.start + 0x10100); + + mpic_init(mpic); + +#ifdef CONFIG_PPC_I8259 + /* Initialize the i8259 controller */ + for_each_node_by_type(np, "interrupt-controller") + if (device_is_compatible(np, "chrp,iic")) { + cascade_node = np; + break; + } + + if (cascade_node == NULL) { + printk(KERN_DEBUG "Could not find i8259 PIC\n"); + return; + } + + cascade_irq = irq_of_parse_and_map(cascade_node, 0); + if (cascade_irq == NO_IRQ) { + printk(KERN_ERR "Failed to map cascade interrupt\n"); + return; + } + + i8259_init(cascade_node, 0); + of_node_put(cascade_node); + + set_irq_chained_handler(cascade_irq, mpc85xx_8259_cascade); +#endif /* CONFIG_PPC_I8259 */ +} + + +/* + * Setup the architecture + */ +static void __init +mpc85xx_cds_setup_arch(void) +{ + struct device_node *cpu; +#ifdef CONFIG_PCI + struct device_node *np; +#endif + + if (ppc_md.progress) + ppc_md.progress("mpc85xx_cds_setup_arch()", 0); + + cpu = of_find_node_by_type(NULL, "cpu"); + if (cpu != 0) { + unsigned int *fp; + + fp = (int *)get_property(cpu, "clock-frequency", NULL); + if (fp != 0) + loops_per_jiffy = *fp / HZ; + else + loops_per_jiffy = 500000000 / HZ; + of_node_put(cpu); + } + + cadmus = ioremap(CADMUS_BASE, CADMUS_SIZE); + cds_pci_slot = ((cadmus[CM_CSR] >> 6) & 0x3) + 1; + + if (ppc_md.progress) { + char buf[40]; + snprintf(buf, 40, "CDS Version = 0x%x in slot %d\n", + cadmus[CM_VER], cds_pci_slot); + ppc_md.progress(buf, 0); + } + +#ifdef CONFIG_PCI + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + add_bridge(np); + + ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup; + ppc_md.pci_exclude_device = mpc85xx_exclude_device; +#endif + +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif +} + + +void +mpc85xx_cds_show_cpuinfo(struct seq_file *m) +{ + uint pvid, svid, phid1; + uint memsize = total_memory; + + pvid = mfspr(SPRN_PVR); + svid = mfspr(SPRN_SVR); + + seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); + seq_printf(m, "Machine\t\t: MPC85xx CDS (0x%x)\n", cadmus[CM_VER]); + seq_printf(m, "PVR\t\t: 0x%x\n", pvid); + seq_printf(m, "SVR\t\t: 0x%x\n", svid); + + /* Display cpu Pll setting */ + phid1 = mfspr(SPRN_HID1); + seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); + + /* Display the amount of memory */ + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); +} + + +/* + * Called very early, device-tree isn't unflattened + */ +static int __init mpc85xx_cds_probe(void) +{ + /* We always match for now, eventually we should look at + * the flat dev tree to ensure this is the board we are + * supposed to run on + */ + return 1; +} + +define_machine(mpc85xx_cds) { + .name = "MPC85xx CDS", + .probe = mpc85xx_cds_probe, + .setup_arch = mpc85xx_cds_setup_arch, + .init_IRQ = mpc85xx_cds_pic_init, + .show_cpuinfo = mpc85xx_cds_show_cpuinfo, + .get_irq = mpic_get_irq, + .restart = mpc85xx_restart, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/85xx/mpc85xx_cds.h b/arch/powerpc/platforms/85xx/mpc85xx_cds.h new file mode 100644 index 000000000..671f54ff1 --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc85xx_cds.h @@ -0,0 +1,43 @@ +/* + * arch/ppc/platforms/85xx/mpc85xx_cds_common.h + * + * MPC85xx CDS board definitions + * + * Maintainer: Kumar Gala <galak@kernel.crashing.org> + * + * Copyright 2004 Freescale Semiconductor, Inc + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __MACH_MPC85XX_CDS_H__ +#define __MACH_MPC85XX_CDS_H__ + +/* CADMUS info */ +#define CADMUS_BASE (0xf8004000) +#define CADMUS_SIZE (256) +#define CM_VER (0) +#define CM_CSR (1) +#define CM_RST (2) + +/* CDS NVRAM/RTC */ +#define CDS_RTC_ADDR (0xf8000000) +#define CDS_RTC_SIZE (8 * 1024) + +/* PCI interrupt controller */ +#define PIRQ0A MPC85xx_IRQ_EXT0 +#define PIRQ0B MPC85xx_IRQ_EXT1 +#define PIRQ0C MPC85xx_IRQ_EXT2 +#define PIRQ0D MPC85xx_IRQ_EXT3 +#define PIRQ1A MPC85xx_IRQ_EXT11 + +#define NR_8259_INTS 16 +#define CPM_IRQ_OFFSET NR_8259_INTS + +#define MPC85xx_OPENPIC_IRQ_OFFSET 80 + +#endif /* __MACH_MPC85XX_CDS_H__ */ diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig new file mode 100644 index 000000000..d1ecc0f9a --- /dev/null +++ b/arch/powerpc/platforms/86xx/Kconfig @@ -0,0 +1,32 @@ +menu "Platform Support" + depends on PPC_86xx + +choice + prompt "Machine Type" + default MPC8641_HPCN + +config MPC8641_HPCN + bool "Freescale MPC8641 HPCN" + select PPC_I8259 + help + This option enables support for the MPC8641 HPCN board. + +endchoice + + +config MPC8641 + bool + select PPC_INDIRECT_PCI + select PPC_UDBG_16550 + default y if MPC8641_HPCN + +config MPIC + bool + default y + +config PPC_INDIRECT_PCI_BE + bool + depends on PPC_86xx + default y + +endmenu diff --git a/arch/powerpc/platforms/86xx/Makefile b/arch/powerpc/platforms/86xx/Makefile new file mode 100644 index 000000000..476a6eeee --- /dev/null +++ b/arch/powerpc/platforms/86xx/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the PowerPC 86xx linux kernel. +# + +obj-$(CONFIG_SMP) += mpc86xx_smp.o +obj-$(CONFIG_MPC8641_HPCN) += mpc86xx_hpcn.o +obj-$(CONFIG_PCI) += pci.o mpc86xx_pcie.o diff --git a/arch/powerpc/platforms/86xx/mpc8641_hpcn.h b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h new file mode 100644 index 000000000..41e554c4a --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc8641_hpcn.h @@ -0,0 +1,21 @@ +/* + * MPC8641 HPCN board definitions + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Author: Xianghua Xiao <x.xiao@freescale.com> + */ + +#ifndef __MPC8641_HPCN_H__ +#define __MPC8641_HPCN_H__ + +#include <linux/init.h> + +#define MPC86XX_RSTCR_OFFSET (0xe00b0) /* Reset Control Register */ + +#endif /* __MPC8641_HPCN_H__ */ diff --git a/arch/powerpc/platforms/86xx/mpc86xx.h b/arch/powerpc/platforms/86xx/mpc86xx.h new file mode 100644 index 000000000..283446259 --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc86xx.h @@ -0,0 +1,30 @@ +/* + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __MPC86XX_H__ +#define __MPC86XX_H__ + +/* + * Declaration for the various functions exported by the + * mpc86xx_* files. Mostly for use by mpc86xx_setup(). + */ + +extern int add_bridge(struct device_node *dev); + +extern int mpc86xx_exclude_device(u_char bus, u_char devfn); + +extern void setup_indirect_pcie(struct pci_controller *hose, + u32 cfg_addr, u32 cfg_data); +extern void setup_indirect_pcie_nomap(struct pci_controller *hose, + void __iomem *cfg_addr, + void __iomem *cfg_data); + +extern void __init mpc86xx_smp_init(void); + +#endif /* __MPC86XX_H__ */ diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c new file mode 100644 index 000000000..5e583cf38 --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c @@ -0,0 +1,471 @@ +/* + * MPC86xx HPCN board specific routines + * + * Recode: ZHANG WEI <wei.zhang@freescale.com> + * Initial author: Xianghua Xiao <x.xiao@freescale.com> + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/kdev_t.h> +#include <linux/delay.h> +#include <linux/seq_file.h> +#include <linux/root_dev.h> + +#include <asm/system.h> +#include <asm/time.h> +#include <asm/machdep.h> +#include <asm/pci-bridge.h> +#include <asm/mpc86xx.h> +#include <asm/prom.h> +#include <mm/mmu_decl.h> +#include <asm/udbg.h> +#include <asm/i8259.h> + +#include <asm/mpic.h> + +#include <sysdev/fsl_soc.h> + +#include "mpc86xx.h" +#include "mpc8641_hpcn.h" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt...) do { printk(KERN_ERR fmt); } while(0) +#else +#define DBG(fmt...) do { } while(0) +#endif + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +unsigned long pci_dram_offset = 0; +#endif + + +#ifdef CONFIG_PCI +static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc, + struct pt_regs *regs) +{ + unsigned int cascade_irq = i8259_irq(regs); + if (cascade_irq != NO_IRQ) + generic_handle_irq(cascade_irq, regs); + desc->chip->eoi(irq); +} +#endif /* CONFIG_PCI */ + +void __init +mpc86xx_hpcn_init_irq(void) +{ + struct mpic *mpic1; + struct device_node *np; + struct resource res; +#ifdef CONFIG_PCI + struct device_node *cascade_node = NULL; + int cascade_irq; +#endif + + /* Determine PIC address. */ + np = of_find_node_by_type(NULL, "open-pic"); + if (np == NULL) + return; + of_address_to_resource(np, 0, &res); + + /* Alloc mpic structure and per isu has 16 INT entries. */ + mpic1 = mpic_alloc(np, res.start, + MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, + 16, NR_IRQS - 4, + " MPIC "); + BUG_ON(mpic1 == NULL); + + mpic_assign_isu(mpic1, 0, res.start + 0x10000); + + /* 48 Internal Interrupts */ + mpic_assign_isu(mpic1, 1, res.start + 0x10200); + mpic_assign_isu(mpic1, 2, res.start + 0x10400); + mpic_assign_isu(mpic1, 3, res.start + 0x10600); + + /* 16 External interrupts + * Moving them from [0 - 15] to [64 - 79] + */ + mpic_assign_isu(mpic1, 4, res.start + 0x10000); + + mpic_init(mpic1); + +#ifdef CONFIG_PCI + /* Initialize i8259 controller */ + for_each_node_by_type(np, "interrupt-controller") + if (device_is_compatible(np, "chrp,iic")) { + cascade_node = np; + break; + } + if (cascade_node == NULL) { + printk(KERN_DEBUG "mpc86xxhpcn: no ISA interrupt controller\n"); + return; + } + + cascade_irq = irq_of_parse_and_map(cascade_node, 0); + if (cascade_irq == NO_IRQ) { + printk(KERN_ERR "mpc86xxhpcn: failed to map cascade interrupt"); + return; + } + DBG("mpc86xxhpcn: cascade mapped to irq %d\n", cascade_irq); + + i8259_init(cascade_node, 0); + set_irq_chained_handler(cascade_irq, mpc86xx_8259_cascade); +#endif +} + +#ifdef CONFIG_PCI + +enum pirq{PIRQA = 8, PIRQB, PIRQC, PIRQD, PIRQE, PIRQF, PIRQG, PIRQH}; +const unsigned char uli1575_irq_route_table[16] = { + 0, /* 0: Reserved */ + 0x8, /* 1: 0b1000 */ + 0, /* 2: Reserved */ + 0x2, /* 3: 0b0010 */ + 0x4, /* 4: 0b0100 */ + 0x5, /* 5: 0b0101 */ + 0x7, /* 6: 0b0111 */ + 0x6, /* 7: 0b0110 */ + 0, /* 8: Reserved */ + 0x1, /* 9: 0b0001 */ + 0x3, /* 10: 0b0011 */ + 0x9, /* 11: 0b1001 */ + 0xb, /* 12: 0b1011 */ + 0, /* 13: Reserved */ + 0xd, /* 14, 0b1101 */ + 0xf, /* 15, 0b1111 */ +}; + +static int __devinit +get_pci_irq_from_of(struct pci_controller *hose, int slot, int pin) +{ + struct of_irq oirq; + u32 laddr[3]; + struct device_node *hosenode = hose ? hose->arch_data : NULL; + + if (!hosenode) return -EINVAL; + + laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(slot, 0) << 8); + laddr[1] = laddr[2] = 0; + of_irq_map_raw(hosenode, &pin, 1, laddr, &oirq); + DBG("mpc86xx_hpcn: pci irq addr %x, slot %d, pin %d, irq %d\n", + laddr[0], slot, pin, oirq.specifier[0]); + return oirq.specifier[0]; +} + +static void __devinit quirk_uli1575(struct pci_dev *dev) +{ + unsigned short temp; + struct pci_controller *hose = pci_bus_to_host(dev->bus); + unsigned char irq2pin[16]; + unsigned long pirq_map_word = 0; + u32 irq; + int i; + + /* + * ULI1575 interrupts route setup + */ + memset(irq2pin, 0, 16); /* Initialize default value 0 */ + + /* + * PIRQA -> PIRQD mapping read from OF-tree + * + * interrupts for PCI slot0 -- PIRQA / PIRQB / PIRQC / PIRQD + * PCI slot1 -- PIRQB / PIRQC / PIRQD / PIRQA + */ + for (i = 0; i < 4; i++){ + irq = get_pci_irq_from_of(hose, 17, i + 1); + if (irq > 0 && irq < 16) + irq2pin[irq] = PIRQA + i; + else + printk(KERN_WARNING "ULI1575 device" + "(slot %d, pin %d) irq %d is invalid.\n", + 17, i, irq); + } + + /* + * PIRQE -> PIRQF mapping set manually + * + * IRQ pin IRQ# + * PIRQE ---- 9 + * PIRQF ---- 10 + * PIRQG ---- 11 + * PIRQH ---- 12 + */ + for (i = 0; i < 4; i++) irq2pin[i + 9] = PIRQE + i; + + /* Set IRQ-PIRQ Mapping to ULI1575 */ + for (i = 0; i < 16; i++) + if (irq2pin[i]) + pirq_map_word |= (uli1575_irq_route_table[i] & 0xf) + << ((irq2pin[i] - PIRQA) * 4); + + /* ULI1575 IRQ mapping conf register default value is 0xb9317542 */ + DBG("Setup ULI1575 IRQ mapping configuration register value = 0x%x\n", + pirq_map_word); + pci_write_config_dword(dev, 0x48, pirq_map_word); + +#define ULI1575_SET_DEV_IRQ(slot, pin, reg) \ + do { \ + int irq; \ + irq = get_pci_irq_from_of(hose, slot, pin); \ + if (irq > 0 && irq < 16) \ + pci_write_config_byte(dev, reg, irq2pin[irq]); \ + else \ + printk(KERN_WARNING "ULI1575 device" \ + "(slot %d, pin %d) irq %d is invalid.\n", \ + slot, pin, irq); \ + } while(0) + + /* USB 1.1 OHCI controller 1, slot 28, pin 1 */ + ULI1575_SET_DEV_IRQ(28, 1, 0x86); + + /* USB 1.1 OHCI controller 2, slot 28, pin 2 */ + ULI1575_SET_DEV_IRQ(28, 2, 0x87); + + /* USB 1.1 OHCI controller 3, slot 28, pin 3 */ + ULI1575_SET_DEV_IRQ(28, 3, 0x88); + + /* USB 2.0 controller, slot 28, pin 4 */ + irq = get_pci_irq_from_of(hose, 28, 4); + if (irq >= 0 && irq <=15) + pci_write_config_dword(dev, 0x74, uli1575_irq_route_table[irq]); + + /* Audio controller, slot 29, pin 1 */ + ULI1575_SET_DEV_IRQ(29, 1, 0x8a); + + /* Modem controller, slot 29, pin 2 */ + ULI1575_SET_DEV_IRQ(29, 2, 0x8b); + + /* HD audio controller, slot 29, pin 3 */ + ULI1575_SET_DEV_IRQ(29, 3, 0x8c); + + /* SMB interrupt: slot 30, pin 1 */ + ULI1575_SET_DEV_IRQ(30, 1, 0x8e); + + /* PMU ACPI SCI interrupt: slot 30, pin 2 */ + ULI1575_SET_DEV_IRQ(30, 2, 0x8f); + + /* Serial ATA interrupt: slot 31, pin 1 */ + ULI1575_SET_DEV_IRQ(31, 1, 0x8d); + + /* Primary PATA IDE IRQ: 14 + * Secondary PATA IDE IRQ: 15 + */ + pci_write_config_byte(dev, 0x44, 0x30 | uli1575_irq_route_table[14]); + pci_write_config_byte(dev, 0x75, uli1575_irq_route_table[15]); + + /* Set IRQ14 and IRQ15 to legacy IRQs */ + pci_read_config_word(dev, 0x46, &temp); + temp |= 0xc000; + pci_write_config_word(dev, 0x46, temp); + + /* Set i8259 interrupt trigger + * IRQ 3: Level + * IRQ 4: Level + * IRQ 5: Level + * IRQ 6: Level + * IRQ 7: Level + * IRQ 9: Level + * IRQ 10: Level + * IRQ 11: Level + * IRQ 12: Level + * IRQ 14: Edge + * IRQ 15: Edge + */ + outb(0xfa, 0x4d0); + outb(0x1e, 0x4d1); + +#undef ULI1575_SET_DEV_IRQ +} + +static void __devinit quirk_uli5288(struct pci_dev *dev) +{ + unsigned char c; + + pci_read_config_byte(dev,0x83,&c); + c |= 0x80; + pci_write_config_byte(dev, 0x83, c); + + pci_write_config_byte(dev, 0x09, 0x01); + pci_write_config_byte(dev, 0x0a, 0x06); + + pci_read_config_byte(dev,0x83,&c); + c &= 0x7f; + pci_write_config_byte(dev, 0x83, c); + + pci_read_config_byte(dev,0x84,&c); + c |= 0x01; + pci_write_config_byte(dev, 0x84, c); +} + +static void __devinit quirk_uli5229(struct pci_dev *dev) +{ + unsigned short temp; + pci_write_config_word(dev, 0x04, 0x0405); + pci_read_config_word(dev, 0x4a, &temp); + temp |= 0x1000; + pci_write_config_word(dev, 0x4a, temp); +} + +static void __devinit early_uli5249(struct pci_dev *dev) +{ + unsigned char temp; + pci_write_config_word(dev, 0x04, 0x0007); + pci_read_config_byte(dev, 0x7c, &temp); + pci_write_config_byte(dev, 0x7c, 0x80); + pci_write_config_byte(dev, 0x09, 0x01); + pci_write_config_byte(dev, 0x7c, temp); + dev->class |= 0x1; +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_uli1575); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, 0x5249, early_uli5249); +#endif /* CONFIG_PCI */ + + +static void __init +mpc86xx_hpcn_setup_arch(void) +{ + struct device_node *np; + + if (ppc_md.progress) + ppc_md.progress("mpc86xx_hpcn_setup_arch()", 0); + + np = of_find_node_by_type(NULL, "cpu"); + if (np != 0) { + unsigned int *fp; + + fp = (int *)get_property(np, "clock-frequency", NULL); + if (fp != 0) + loops_per_jiffy = *fp / HZ; + else + loops_per_jiffy = 50000000 / HZ; + of_node_put(np); + } + +#ifdef CONFIG_PCI + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + add_bridge(np); + + ppc_md.pci_exclude_device = mpc86xx_exclude_device; +#endif + + printk("MPC86xx HPCN board from Freescale Semiconductor\n"); + +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif + +#ifdef CONFIG_SMP + mpc86xx_smp_init(); +#endif +} + + +void +mpc86xx_hpcn_show_cpuinfo(struct seq_file *m) +{ + struct device_node *root; + uint memsize = total_memory; + const char *model = ""; + uint svid = mfspr(SPRN_SVR); + + seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); + + root = of_find_node_by_path("/"); + if (root) + model = get_property(root, "model", NULL); + seq_printf(m, "Machine\t\t: %s\n", model); + of_node_put(root); + + seq_printf(m, "SVR\t\t: 0x%x\n", svid); + seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); +} + + +void __init mpc86xx_hpcn_pcibios_fixup(void) +{ + struct pci_dev *dev = NULL; + + for_each_pci_dev(dev) + pci_read_irq_line(dev); +} + + +/* + * Called very early, device-tree isn't unflattened + */ +static int __init mpc86xx_hpcn_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + if (of_flat_dt_is_compatible(root, "mpc86xx")) + return 1; /* Looks good */ + + return 0; +} + + +void +mpc86xx_restart(char *cmd) +{ + void __iomem *rstcr; + + rstcr = ioremap(get_immrbase() + MPC86XX_RSTCR_OFFSET, 0x100); + + local_irq_disable(); + + /* Assert reset request to Reset Control Register */ + out_be32(rstcr, 0x2); + + /* not reached */ +} + + +long __init +mpc86xx_time_init(void) +{ + unsigned int temp; + + /* Set the time base to zero */ + mtspr(SPRN_TBWL, 0); + mtspr(SPRN_TBWU, 0); + + temp = mfspr(SPRN_HID0); + temp |= HID0_TBEN; + mtspr(SPRN_HID0, temp); + asm volatile("isync"); + + return 0; +} + + +define_machine(mpc86xx_hpcn) { + .name = "MPC86xx HPCN", + .probe = mpc86xx_hpcn_probe, + .setup_arch = mpc86xx_hpcn_setup_arch, + .init_IRQ = mpc86xx_hpcn_init_irq, + .show_cpuinfo = mpc86xx_hpcn_show_cpuinfo, + .pcibios_fixup = mpc86xx_hpcn_pcibios_fixup, + .get_irq = mpic_get_irq, + .restart = mpc86xx_restart, + .time_init = mpc86xx_time_init, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/86xx/mpc86xx_pcie.c b/arch/powerpc/platforms/86xx/mpc86xx_pcie.c new file mode 100644 index 000000000..a2f4f7302 --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc86xx_pcie.c @@ -0,0 +1,173 @@ +/* + * Support for indirect PCI bridges. + * + * Copyright (C) 1998 Gabriel Paubert. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * "Temporary" MPC8548 Errata file - + * The standard indirect_pci code should work with future silicon versions. + */ + +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/delay.h> +#include <linux/string.h> +#include <linux/init.h> +#include <linux/bootmem.h> + +#include <asm/io.h> +#include <asm/prom.h> +#include <asm/pci-bridge.h> +#include <asm/machdep.h> + +#include "mpc86xx.h" + +#define PCI_CFG_OUT out_be32 + +/* ERRATA PCI-Ex 14 PCIE Controller timeout */ +#define PCIE_FIX out_be32(hose->cfg_addr+0x4, 0x0400ffff) + + +static int +indirect_read_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 *val) +{ + struct pci_controller *hose = bus->sysdata; + volatile void __iomem *cfg_data; + u32 temp; + + if (ppc_md.pci_exclude_device) + if (ppc_md.pci_exclude_device(bus->number, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* Possible artifact of CDCpp50937 needs further investigation */ + if (devfn != 0x0 && bus->number == 0xff) + return PCIBIOS_DEVICE_NOT_FOUND; + + PCIE_FIX; + if (bus->number == 0xff) { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000000 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } else { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000001 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } + + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */ + cfg_data = hose->cfg_data; + PCIE_FIX; + temp = in_le32(cfg_data); + switch (len) { + case 1: + *val = (temp >> (((offset & 3))*8)) & 0xff; + break; + case 2: + *val = (temp >> (((offset & 3))*8)) & 0xffff; + break; + default: + *val = temp; + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int +indirect_write_config_pcie(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 val) +{ + struct pci_controller *hose = bus->sysdata; + volatile void __iomem *cfg_data; + u32 temp; + + if (ppc_md.pci_exclude_device) + if (ppc_md.pci_exclude_device(bus->number, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* Possible artifact of CDCpp50937 needs further investigation */ + if (devfn != 0x0 && bus->number == 0xff) + return PCIBIOS_DEVICE_NOT_FOUND; + + PCIE_FIX; + if (bus->number == 0xff) { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000000 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } else { + PCI_CFG_OUT(hose->cfg_addr, + (0x80000001 | ((offset & 0xf00) << 16) | + ((bus->number - hose->bus_offset) << 16) + | (devfn << 8) | ((offset & 0xfc) ))); + } + + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */ + cfg_data = hose->cfg_data; + switch (len) { + case 1: + PCIE_FIX; + temp = in_le32(cfg_data); + temp = (temp & ~(0xff << ((offset & 3) * 8))) | + (val << ((offset & 3) * 8)); + PCIE_FIX; + out_le32(cfg_data, temp); + break; + case 2: + PCIE_FIX; + temp = in_le32(cfg_data); + temp = (temp & ~(0xffff << ((offset & 3) * 8))); + temp |= (val << ((offset & 3) * 8)) ; + PCIE_FIX; + out_le32(cfg_data, temp); + break; + default: + PCIE_FIX; + out_le32(cfg_data, val); + break; + } + PCIE_FIX; + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops indirect_pcie_ops = { + indirect_read_config_pcie, + indirect_write_config_pcie +}; + +void __init +setup_indirect_pcie_nomap(struct pci_controller* hose, void __iomem * cfg_addr, + void __iomem * cfg_data) +{ + hose->cfg_addr = cfg_addr; + hose->cfg_data = cfg_data; + hose->ops = &indirect_pcie_ops; +} + +void __init +setup_indirect_pcie(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data) +{ + unsigned long base = cfg_addr & PAGE_MASK; + void __iomem *mbase, *addr, *data; + + mbase = ioremap(base, PAGE_SIZE); + addr = mbase + (cfg_addr & ~PAGE_MASK); + if ((cfg_data & PAGE_MASK) != base) + mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE); + data = mbase + (cfg_data & ~PAGE_MASK); + setup_indirect_pcie_nomap(hose, addr, data); +} diff --git a/arch/powerpc/platforms/86xx/mpc86xx_smp.c b/arch/powerpc/platforms/86xx/mpc86xx_smp.c new file mode 100644 index 000000000..bb7fb4193 --- /dev/null +++ b/arch/powerpc/platforms/86xx/mpc86xx_smp.c @@ -0,0 +1,115 @@ +/* + * Author: Xianghua Xiao <x.xiao@freescale.com> + * Zhang Wei <wei.zhang@freescale.com> + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/delay.h> + +#include <asm/pgtable.h> +#include <asm/page.h> +#include <asm/pci-bridge.h> +#include <asm-powerpc/mpic.h> +#include <asm/mpc86xx.h> +#include <asm/cacheflush.h> + +#include <sysdev/fsl_soc.h> + +#include "mpc86xx.h" + +extern void __secondary_start_mpc86xx(void); +extern unsigned long __secondary_hold_acknowledge; + + +static void __init +smp_86xx_release_core(int nr) +{ + __be32 __iomem *mcm_vaddr; + unsigned long pcr; + + if (nr < 0 || nr >= NR_CPUS) + return; + + /* + * Startup Core #nr. + */ + mcm_vaddr = ioremap(get_immrbase() + MPC86xx_MCM_OFFSET, + MPC86xx_MCM_SIZE); + pcr = in_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2)); + pcr |= 1 << (nr + 24); + out_be32(mcm_vaddr + (MCM_PORT_CONFIG_OFFSET >> 2), pcr); +} + + +static void __init +smp_86xx_kick_cpu(int nr) +{ + unsigned int save_vector; + unsigned long target, flags; + int n = 0; + volatile unsigned int *vector + = (volatile unsigned int *)(KERNELBASE + 0x100); + + if (nr < 0 || nr >= NR_CPUS) + return; + + pr_debug("smp_86xx_kick_cpu: kick CPU #%d\n", nr); + + local_irq_save(flags); + local_irq_disable(); + + /* Save reset vector */ + save_vector = *vector; + + /* Setup fake reset vector to call __secondary_start_mpc86xx. */ + target = (unsigned long) __secondary_start_mpc86xx; + create_branch((unsigned long)vector, target, BRANCH_SET_LINK); + + /* Kick that CPU */ + smp_86xx_release_core(nr); + + /* Wait a bit for the CPU to take the exception. */ + while ((__secondary_hold_acknowledge != nr) && (n++, n < 1000)) + mdelay(1); + + /* Restore the exception vector */ + *vector = save_vector; + flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); + + local_irq_restore(flags); + + pr_debug("wait CPU #%d for %d msecs.\n", nr, n); +} + + +static void __init +smp_86xx_setup_cpu(int cpu_nr) +{ + mpic_setup_this_cpu(); +} + + +struct smp_ops_t smp_86xx_ops = { + .message_pass = smp_mpic_message_pass, + .probe = smp_mpic_probe, + .kick_cpu = smp_86xx_kick_cpu, + .setup_cpu = smp_86xx_setup_cpu, + .take_timebase = smp_generic_take_timebase, + .give_timebase = smp_generic_give_timebase, +}; + + +void __init +mpc86xx_smp_init(void) +{ + smp_ops = &smp_86xx_ops; +} diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c new file mode 100644 index 000000000..a8c8f0a44 --- /dev/null +++ b/arch/powerpc/platforms/86xx/pci.c @@ -0,0 +1,205 @@ +/* + * MPC86XX pci setup code + * + * Recode: ZHANG WEI <wei.zhang@freescale.com> + * Initial author: Xianghua Xiao <x.xiao@freescale.com> + * + * Copyright 2006 Freescale Semiconductor Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/types.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/serial.h> + +#include <asm/system.h> +#include <asm/atomic.h> +#include <asm/io.h> +#include <asm/prom.h> +#include <asm/immap_86xx.h> +#include <asm/pci-bridge.h> +#include <sysdev/fsl_soc.h> + +#include "mpc86xx.h" + +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args) +#else +#define DBG(fmt, args...) +#endif + +struct pcie_outbound_window_regs { + uint pexotar; /* 0x.0 - PCI Express outbound translation address register */ + uint pexotear; /* 0x.4 - PCI Express outbound translation extended address register */ + uint pexowbar; /* 0x.8 - PCI Express outbound window base address register */ + char res1[4]; + uint pexowar; /* 0x.10 - PCI Express outbound window attributes register */ + char res2[12]; +}; + +struct pcie_inbound_window_regs { + uint pexitar; /* 0x.0 - PCI Express inbound translation address register */ + char res1[4]; + uint pexiwbar; /* 0x.8 - PCI Express inbound window base address register */ + uint pexiwbear; /* 0x.c - PCI Express inbound window base extended address register */ + uint pexiwar; /* 0x.10 - PCI Express inbound window attributes register */ + char res2[12]; +}; + +static void __init setup_pcie_atmu(struct pci_controller *hose, struct resource *rsrc) +{ + volatile struct ccsr_pex *pcie; + volatile struct pcie_outbound_window_regs *pcieow; + volatile struct pcie_inbound_window_regs *pcieiw; + int i = 0; + + DBG("PCIE memory map start 0x%x, size 0x%x\n", rsrc->start, + rsrc->end - rsrc->start + 1); + pcie = ioremap(rsrc->start, rsrc->end - rsrc->start + 1); + + /* Disable all windows (except pexowar0 since its ignored) */ + pcie->pexowar1 = 0; + pcie->pexowar2 = 0; + pcie->pexowar3 = 0; + pcie->pexowar4 = 0; + pcie->pexiwar1 = 0; + pcie->pexiwar2 = 0; + pcie->pexiwar3 = 0; + + pcieow = (struct pcie_outbound_window_regs *)&pcie->pexotar1; + pcieiw = (struct pcie_inbound_window_regs *)&pcie->pexitar1; + + /* Setup outbound MEM window */ + for(i = 0; i < 3; i++) + if (hose->mem_resources[i].flags & IORESOURCE_MEM){ + DBG("PCIE MEM resource start 0x%08x, size 0x%08x.\n", + hose->mem_resources[i].start, + hose->mem_resources[i].end + - hose->mem_resources[i].start + 1); + pcieow->pexotar = (hose->mem_resources[i].start) >> 12 + & 0x000fffff; + pcieow->pexotear = 0; + pcieow->pexowbar = (hose->mem_resources[i].start) >> 12 + & 0x000fffff; + /* Enable, Mem R/W */ + pcieow->pexowar = 0x80044000 | + (__ilog2(hose->mem_resources[i].end + - hose->mem_resources[i].start + 1) + - 1); + pcieow++; + } + + /* Setup outbound IO window */ + if (hose->io_resource.flags & IORESOURCE_IO){ + DBG("PCIE IO resource start 0x%08x, size 0x%08x, phy base 0x%08x.\n", + hose->io_resource.start, + hose->io_resource.end - hose->io_resource.start + 1, + hose->io_base_phys); + pcieow->pexotar = (hose->io_resource.start) >> 12 & 0x000fffff; + pcieow->pexotear = 0; + pcieow->pexowbar = (hose->io_base_phys) >> 12 & 0x000fffff; + /* Enable, IO R/W */ + pcieow->pexowar = 0x80088000 | (__ilog2(hose->io_resource.end + - hose->io_resource.start + 1) - 1); + } + + /* Setup 2G inbound Memory Window @ 0 */ + pcieiw->pexitar = 0x00000000; + pcieiw->pexiwbar = 0x00000000; + /* Enable, Prefetch, Local Mem, Snoop R/W, 2G */ + pcieiw->pexiwar = 0xa0f5501e; +} + +static void __init +mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size) +{ + u16 cmd; + unsigned int temps; + + DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n", + pcie_offset, pcie_size); + + early_read_config_word(hose, 0, 0, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY + | PCI_COMMAND_IO; + early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd); + + early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80); + + /* PCIE Bus, Fix the MPC8641D host bridge's location to bus 0xFF. */ + early_read_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, &temps); + temps = (temps & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16); + early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps); +} + +int mpc86xx_exclude_device(u_char bus, u_char devfn) +{ + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +int __init add_bridge(struct device_node *dev) +{ + int len; + struct pci_controller *hose; + struct resource rsrc; + int *bus_range; + int has_address = 0; + int primary = 0; + + DBG("Adding PCIE host bridge %s\n", dev->full_name); + + /* Fetch host bridge registers address */ + has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); + + /* Get bus range if any */ + bus_range = (int *) get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) + printk(KERN_WARNING "Can't get bus-range for %s, assume" + " bus 0\n", dev->full_name); + + hose = pcibios_alloc_controller(); + if (!hose) + return -ENOMEM; + hose->arch_data = dev; + hose->set_cfg_type = 1; + + /* last_busno = 0xfe cause by MPC8641 PCIE bug */ + hose->first_busno = bus_range ? bus_range[0] : 0x0; + hose->last_busno = bus_range ? bus_range[1] : 0xfe; + + setup_indirect_pcie(hose, rsrc.start, rsrc.start + 0x4); + + /* Setup the PCIE host controller. */ + mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1); + + if ((rsrc.start & 0xfffff) == 0x8000) + primary = 1; + + printk(KERN_INFO "Found MPC86xx PCIE host bridge at 0x%08lx. " + "Firmware bus number: %d->%d\n", + (unsigned long) rsrc.start, + hose->first_busno, hose->last_busno); + + DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", + hose, hose->cfg_addr, hose->cfg_data); + + /* Interpret the "ranges" property */ + /* This also maps the I/O region and sets isa_io/mem_base */ + pci_process_bridge_OF_ranges(hose, dev, primary); + + /* Setup PEX window registers */ + setup_pcie_atmu(hose, &rsrc); + + return 0; +} diff --git a/arch/powerpc/platforms/cell/cbe_regs.c b/arch/powerpc/platforms/cell/cbe_regs.c new file mode 100644 index 000000000..7315f66d1 --- /dev/null +++ b/arch/powerpc/platforms/cell/cbe_regs.c @@ -0,0 +1,126 @@ +/* + * cbe_regs.c + * + * Accessor routines for the various MMIO register blocks of the CBE + * + * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp. + */ + +#include <linux/percpu.h> +#include <linux/types.h> + +#include <asm/io.h> +#include <asm/pgtable.h> +#include <asm/prom.h> +#include <asm/ptrace.h> + +#include "cbe_regs.h" + +#define MAX_CBE 2 + +/* + * Current implementation uses "cpu" nodes. We build our own mapping + * array of cpu numbers to cpu nodes locally for now to allow interrupt + * time code to have a fast path rather than call of_get_cpu_node(). If + * we implement cpu hotplug, we'll have to install an appropriate norifier + * in order to release references to the cpu going away + */ +static struct cbe_regs_map +{ + struct device_node *cpu_node; + struct cbe_pmd_regs __iomem *pmd_regs; + struct cbe_iic_regs __iomem *iic_regs; +} cbe_regs_maps[MAX_CBE]; +static int cbe_regs_map_count; + +static struct cbe_thread_map +{ + struct device_node *cpu_node; + struct cbe_regs_map *regs; +} cbe_thread_map[NR_CPUS]; + +static struct cbe_regs_map *cbe_find_map(struct device_node *np) +{ + int i; + + for (i = 0; i < cbe_regs_map_count; i++) + if (cbe_regs_maps[i].cpu_node == np) + return &cbe_regs_maps[i]; + return NULL; +} + +struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np) +{ + struct cbe_regs_map *map = cbe_find_map(np); + if (map == NULL) + return NULL; + return map->pmd_regs; +} + +struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu) +{ + struct cbe_regs_map *map = cbe_thread_map[cpu].regs; + if (map == NULL) + return NULL; + return map->pmd_regs; +} + + +struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np) +{ + struct cbe_regs_map *map = cbe_find_map(np); + if (map == NULL) + return NULL; + return map->iic_regs; +} +struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu) +{ + struct cbe_regs_map *map = cbe_thread_map[cpu].regs; + if (map == NULL) + return NULL; + return map->iic_regs; +} + +void __init cbe_regs_init(void) +{ + int i; + struct device_node *cpu; + + /* Build local fast map of CPUs */ + for_each_possible_cpu(i) + cbe_thread_map[i].cpu_node = of_get_cpu_node(i, NULL); + + /* Find maps for each device tree CPU */ + for_each_node_by_type(cpu, "cpu") { + struct cbe_regs_map *map = &cbe_regs_maps[cbe_regs_map_count++]; + + /* That hack must die die die ! */ + struct address_prop { + unsigned long address; + unsigned int len; + } __attribute__((packed)) *prop; + + + if (cbe_regs_map_count > MAX_CBE) { + printk(KERN_ERR "cbe_regs: More BE chips than supported" + "!\n"); + cbe_regs_map_count--; + return; + } + map->cpu_node = cpu; + for_each_possible_cpu(i) + if (cbe_thread_map[i].cpu_node == cpu) + cbe_thread_map[i].regs = map; + + prop = (struct address_prop *)get_property(cpu, "pervasive", + NULL); + if (prop != NULL) + map->pmd_regs = ioremap(prop->address, prop->len); + + prop = (struct address_prop *)get_property(cpu, "iic", + NULL); + if (prop != NULL) + map->iic_regs = ioremap(prop->address, prop->len); + } +} + diff --git a/arch/powerpc/platforms/cell/cbe_regs.h b/arch/powerpc/platforms/cell/cbe_regs.h new file mode 100644 index 000000000..e76e4a6af --- /dev/null +++ b/arch/powerpc/platforms/cell/cbe_regs.h @@ -0,0 +1,129 @@ +/* + * cbe_regs.h + * + * This file is intended to hold the various register definitions for CBE + * on-chip system devices (memory controller, IO controller, etc...) + * + * (c) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp. + */ + +#ifndef CBE_REGS_H +#define CBE_REGS_H + +/* + * + * Some HID register definitions + * + */ + +/* CBE specific HID0 bits */ +#define HID0_CBE_THERM_WAKEUP 0x0000020000000000ul +#define HID0_CBE_SYSERR_WAKEUP 0x0000008000000000ul +#define HID0_CBE_THERM_INT_EN 0x0000000400000000ul +#define HID0_CBE_SYSERR_INT_EN 0x0000000200000000ul + + +/* + * + * Pervasive unit register definitions + * + */ + +struct cbe_pmd_regs { + u8 pad_0x0000_0x0800[0x0800 - 0x0000]; /* 0x0000 */ + + /* Thermal Sensor Registers */ + u64 ts_ctsr1; /* 0x0800 */ + u64 ts_ctsr2; /* 0x0808 */ + u64 ts_mtsr1; /* 0x0810 */ + u64 ts_mtsr2; /* 0x0818 */ + u64 ts_itr1; /* 0x0820 */ + u64 ts_itr2; /* 0x0828 */ + u64 ts_gitr; /* 0x0830 */ + u64 ts_isr; /* 0x0838 */ + u64 ts_imr; /* 0x0840 */ + u64 tm_cr1; /* 0x0848 */ + u64 tm_cr2; /* 0x0850 */ + u64 tm_simr; /* 0x0858 */ + u64 tm_tpr; /* 0x0860 */ + u64 tm_str1; /* 0x0868 */ + u64 tm_str2; /* 0x0870 */ + u64 tm_tsr; /* 0x0878 */ + + /* Power Management */ + u64 pm_control; /* 0x0880 */ +#define CBE_PMD_PAUSE_ZERO_CONTROL 0x10000 + u64 pm_status; /* 0x0888 */ + + /* Time Base Register */ + u64 tbr; /* 0x0890 */ + + u8 pad_0x0898_0x0c00 [0x0c00 - 0x0898]; /* 0x0898 */ + + /* Fault Isolation Registers */ + u64 checkstop_fir; /* 0x0c00 */ + u64 recoverable_fir; + u64 spec_att_mchk_fir; + u64 fir_mode_reg; + u64 fir_enable_mask; + + u8 pad_0x0c28_0x1000 [0x1000 - 0x0c28]; /* 0x0c28 */ +}; + +extern struct cbe_pmd_regs __iomem *cbe_get_pmd_regs(struct device_node *np); +extern struct cbe_pmd_regs __iomem *cbe_get_cpu_pmd_regs(int cpu); + +/* + * + * IIC unit register definitions + * + */ + +struct cbe_iic_pending_bits { + u32 data; + u8 flags; + u8 class; + u8 source; + u8 prio; +}; + +#define CBE_IIC_IRQ_VALID 0x80 +#define CBE_IIC_IRQ_IPI 0x40 + +struct cbe_iic_thread_regs { + struct cbe_iic_pending_bits pending; + struct cbe_iic_pending_bits pending_destr; + u64 generate; + u64 prio; +}; + +struct cbe_iic_regs { + u8 pad_0x0000_0x0400[0x0400 - 0x0000]; /* 0x0000 */ + + /* IIC interrupt registers */ + struct cbe_iic_thread_regs thread[2]; /* 0x0400 */ + u64 iic_ir; /* 0x0440 */ + u64 iic_is; /* 0x0448 */ + + u8 pad_0x0450_0x0500[0x0500 - 0x0450]; /* 0x0450 */ + + /* IOC FIR */ + u64 ioc_fir_reset; /* 0x0500 */ + u64 ioc_fir_set; + u64 ioc_checkstop_enable; + u64 ioc_fir_error_mask; + u64 ioc_syserr_enable; + u64 ioc_fir; + + u8 pad_0x0530_0x1000[0x1000 - 0x0530]; /* 0x0530 */ +}; + +extern struct cbe_iic_regs __iomem *cbe_get_iic_regs(struct device_node *np); +extern struct cbe_iic_regs __iomem *cbe_get_cpu_iic_regs(int cpu); + + +/* Init this module early */ +extern void cbe_regs_init(void); + + +#endif /* CBE_REGS_H */ diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c new file mode 100644 index 000000000..0984c7071 --- /dev/null +++ b/arch/powerpc/platforms/cell/ras.c @@ -0,0 +1,111 @@ +#define DEBUG + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/smp.h> + +#include <asm/reg.h> +#include <asm/io.h> +#include <asm/prom.h> +#include <asm/machdep.h> + +#include "ras.h" +#include "cbe_regs.h" + + +static void dump_fir(int cpu) +{ + struct cbe_pmd_regs __iomem *pregs = cbe_get_cpu_pmd_regs(cpu); + struct cbe_iic_regs __iomem *iregs = cbe_get_cpu_iic_regs(cpu); + + if (pregs == NULL) + return; + + /* Todo: do some nicer parsing of bits and based on them go down + * to other sub-units FIRs and not only IIC + */ + printk(KERN_ERR "Global Checkstop FIR : 0x%016lx\n", + in_be64(&pregs->checkstop_fir)); + printk(KERN_ERR "Global Recoverable FIR : 0x%016lx\n", + in_be64(&pregs->checkstop_fir)); + printk(KERN_ERR "Global MachineCheck FIR : 0x%016lx\n", + in_be64(&pregs->spec_att_mchk_fir)); + + if (iregs == NULL) + return; + printk(KERN_ERR "IOC FIR : 0x%016lx\n", + in_be64(&iregs->ioc_fir)); + +} + +void cbe_system_error_exception(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + printk(KERN_ERR "System Error Interrupt on CPU %d !\n", cpu); + dump_fir(cpu); + dump_stack(); +} + +void cbe_maintenance_exception(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + /* + * Nothing implemented for the maintenance interrupt at this point + */ + + printk(KERN_ERR "Unhandled Maintenance interrupt on CPU %d !\n", cpu); + dump_stack(); +} + +void cbe_thermal_exception(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + /* + * Nothing implemented for the thermal interrupt at this point + */ + + printk(KERN_ERR "Unhandled Thermal interrupt on CPU %d !\n", cpu); + dump_stack(); +} + +static int cbe_machine_check_handler(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + printk(KERN_ERR "Machine Check Interrupt on CPU %d !\n", cpu); + dump_fir(cpu); + + /* No recovery from this code now, lets continue */ + return 0; +} + +void __init cbe_ras_init(void) +{ + unsigned long hid0; + + /* + * Enable System Error & thermal interrupts and wakeup conditions + */ + + hid0 = mfspr(SPRN_HID0); + hid0 |= HID0_CBE_THERM_INT_EN | HID0_CBE_THERM_WAKEUP | + HID0_CBE_SYSERR_INT_EN | HID0_CBE_SYSERR_WAKEUP; + mtspr(SPRN_HID0, hid0); + mb(); + + /* + * Install machine check handler. Leave setting of precise mode to + * what the firmware did for now + */ + ppc_md.machine_check_exception = cbe_machine_check_handler; + mb(); + + /* + * For now, we assume that IOC_FIR is already set to forward some + * error conditions to the System Error handler. If that is not true + * then it will have to be fixed up here. + */ +} diff --git a/arch/powerpc/platforms/cell/ras.h b/arch/powerpc/platforms/cell/ras.h new file mode 100644 index 000000000..eb7ee54c8 --- /dev/null +++ b/arch/powerpc/platforms/cell/ras.h @@ -0,0 +1,9 @@ +#ifndef RAS_H +#define RAS_H + +extern void cbe_system_error_exception(struct pt_regs *regs); +extern void cbe_maintenance_exception(struct pt_regs *regs); +extern void cbe_thermal_exception(struct pt_regs *regs); +extern void cbe_ras_init(void); + +#endif /* RAS_H */ diff --git a/arch/powerpc/platforms/cell/spu_priv1_mmio.c b/arch/powerpc/platforms/cell/spu_priv1_mmio.c new file mode 100644 index 000000000..71b69f0a1 --- /dev/null +++ b/arch/powerpc/platforms/cell/spu_priv1_mmio.c @@ -0,0 +1,159 @@ +/* + * spu hypervisor abstraction for direct hardware access. + * + * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 + * Copyright 2006 Sony Corp. + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/module.h> + +#include <asm/io.h> +#include <asm/spu.h> +#include <asm/spu_priv1.h> + +#include "interrupt.h" + +static void int_mask_and(struct spu *spu, int class, u64 mask) +{ + u64 old_mask; + + old_mask = in_be64(&spu->priv1->int_mask_RW[class]); + out_be64(&spu->priv1->int_mask_RW[class], old_mask & mask); +} + +static void int_mask_or(struct spu *spu, int class, u64 mask) +{ + u64 old_mask; + + old_mask = in_be64(&spu->priv1->int_mask_RW[class]); + out_be64(&spu->priv1->int_mask_RW[class], old_mask | mask); +} + +static void int_mask_set(struct spu *spu, int class, u64 mask) +{ + out_be64(&spu->priv1->int_mask_RW[class], mask); +} + +static u64 int_mask_get(struct spu *spu, int class) +{ + return in_be64(&spu->priv1->int_mask_RW[class]); +} + +static void int_stat_clear(struct spu *spu, int class, u64 stat) +{ + out_be64(&spu->priv1->int_stat_RW[class], stat); +} + +static u64 int_stat_get(struct spu *spu, int class) +{ + return in_be64(&spu->priv1->int_stat_RW[class]); +} + +static void cpu_affinity_set(struct spu *spu, int cpu) +{ + u64 target = iic_get_target_id(cpu); + u64 route = target << 48 | target << 32 | target << 16; + out_be64(&spu->priv1->int_route_RW, route); +} + +static u64 mfc_dar_get(struct spu *spu) +{ + return in_be64(&spu->priv1->mfc_dar_RW); +} + +static u64 mfc_dsisr_get(struct spu *spu) +{ + return in_be64(&spu->priv1->mfc_dsisr_RW); +} + +static void mfc_dsisr_set(struct spu *spu, u64 dsisr) +{ + out_be64(&spu->priv1->mfc_dsisr_RW, dsisr); +} + +static void mfc_sdr_set(struct spu *spu, u64 sdr) +{ + out_be64(&spu->priv1->mfc_sdr_RW, sdr); +} + +static void mfc_sr1_set(struct spu *spu, u64 sr1) +{ + out_be64(&spu->priv1->mfc_sr1_RW, sr1); +} + +static u64 mfc_sr1_get(struct spu *spu) +{ + return in_be64(&spu->priv1->mfc_sr1_RW); +} + +static void mfc_tclass_id_set(struct spu *spu, u64 tclass_id) +{ + out_be64(&spu->priv1->mfc_tclass_id_RW, tclass_id); +} + +static u64 mfc_tclass_id_get(struct spu *spu) +{ + return in_be64(&spu->priv1->mfc_tclass_id_RW); +} + +static void tlb_invalidate(struct spu *spu) +{ + out_be64(&spu->priv1->tlb_invalidate_entry_W, 0ul); +} + +static void resource_allocation_groupID_set(struct spu *spu, u64 id) +{ + out_be64(&spu->priv1->resource_allocation_groupID_RW, id); +} + +static u64 resource_allocation_groupID_get(struct spu *spu) +{ + return in_be64(&spu->priv1->resource_allocation_groupID_RW); +} + +static void resource_allocation_enable_set(struct spu *spu, u64 enable) +{ + out_be64(&spu->priv1->resource_allocation_enable_RW, enable); +} + +static u64 resource_allocation_enable_get(struct spu *spu) +{ + return in_be64(&spu->priv1->resource_allocation_enable_RW); +} + +const struct spu_priv1_ops spu_priv1_mmio_ops = +{ + .int_mask_and = int_mask_and, + .int_mask_or = int_mask_or, + .int_mask_set = int_mask_set, + .int_mask_get = int_mask_get, + .int_stat_clear = int_stat_clear, + .int_stat_get = int_stat_get, + .cpu_affinity_set = cpu_affinity_set, + .mfc_dar_get = mfc_dar_get, + .mfc_dsisr_get = mfc_dsisr_get, + .mfc_dsisr_set = mfc_dsisr_set, + .mfc_sdr_set = mfc_sdr_set, + .mfc_sr1_set = mfc_sr1_set, + .mfc_sr1_get = mfc_sr1_get, + .mfc_tclass_id_set = mfc_tclass_id_set, + .mfc_tclass_id_get = mfc_tclass_id_get, + .tlb_invalidate = tlb_invalidate, + .resource_allocation_groupID_set = resource_allocation_groupID_set, + .resource_allocation_groupID_get = resource_allocation_groupID_get, + .resource_allocation_enable_set = resource_allocation_enable_set, + .resource_allocation_enable_get = resource_allocation_enable_get, +}; diff --git a/arch/powerpc/platforms/embedded6xx/Makefile b/arch/powerpc/platforms/embedded6xx/Makefile new file mode 100644 index 000000000..fa499fe59 --- /dev/null +++ b/arch/powerpc/platforms/embedded6xx/Makefile @@ -0,0 +1,4 @@ +# +# Makefile for the 6xx/7xx/7xxxx linux kernel. +# +obj-$(CONFIG_MPC7448HPC2) += mpc7448_hpc2.o diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c new file mode 100644 index 000000000..6260bc526 --- /dev/null +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c @@ -0,0 +1,309 @@ +/* + * mpc7448_hpc2.c + * + * Board setup routines for the Freescale mpc7448hpc2(taiga) platform + * + * Author: Jacob Pan + * jacob.pan@freescale.com + * Author: Xianghua Xiao + * x.xiao@freescale.com + * Maintainer: Roy Zang <tie-fei.zang@freescale.com> + * Add Flat Device Tree support fot mpc7448hpc2 board + * + * Copyright 2004-2006 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/kdev_t.h> +#include <linux/console.h> +#include <linux/delay.h> +#include <linux/irq.h> +#include <linux/ide.h> +#include <linux/seq_file.h> +#include <linux/root_dev.h> +#include <linux/serial.h> +#include <linux/tty.h> +#include <linux/serial_core.h> + +#include <asm/system.h> +#include <asm/time.h> +#include <asm/machdep.h> +#include <asm/prom.h> +#include <asm/udbg.h> +#include <asm/tsi108.h> +#include <asm/pci-bridge.h> +#include <asm/reg.h> +#include <mm/mmu_decl.h> +#include "mpc7448_hpc2.h" +#include <asm/tsi108_irq.h> +#include <asm/mpic.h> + +#undef DEBUG +#ifdef DEBUG +#define DBG(fmt...) do { printk(fmt); } while(0) +#else +#define DBG(fmt...) do { } while(0) +#endif + +#ifndef CONFIG_PCI +isa_io_base = MPC7448_HPC2_ISA_IO_BASE; +isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE; +pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET; +#endif + +extern int tsi108_setup_pci(struct device_node *dev); +extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); +extern void tsi108_pci_int_init(void); +extern void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc, + struct pt_regs *regs); + +int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn) +{ + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + else + return PCIBIOS_SUCCESSFUL; +} + +/* + * find pci slot by devfn in interrupt map of OF tree + */ +u8 find_slot_by_devfn(unsigned int *interrupt_map, unsigned int devfn) +{ + int i; + unsigned int tmp; + for (i = 0; i < 4; i++){ + tmp = interrupt_map[i*4*7]; + if ((tmp >> 11) == (devfn >> 3)) + return i; + } + return i; +} + +/* + * Scans the interrupt map for pci device + */ +void mpc7448_hpc2_fixup_irq(struct pci_dev *dev) +{ + struct pci_controller *hose; + struct device_node *node; + unsigned int *interrupt; + int busnr; + int len; + u8 slot; + u8 pin; + + /* Lookup the hose */ + busnr = dev->bus->number; + hose = pci_bus_to_hose(busnr); + if (!hose) + printk(KERN_ERR "No pci hose found\n"); + + /* Check it has an OF node associated */ + node = (struct device_node *) hose->arch_data; + if (!node) + printk(KERN_ERR "No pci node found\n"); + + interrupt = (unsigned int *) get_property(node, "interrupt-map", &len); + slot = find_slot_by_devfn(interrupt, dev->devfn); + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + if (pin == 0 || pin > 4) + pin = 1; + pin--; + dev->irq = interrupt[slot*4*7 + pin*7 + 5]; + DBG("TSI_PCI: dev->irq = 0x%x\n", dev->irq); +} +/* temporary pci irq map fixup*/ + +void __init mpc7448_hpc2_pcibios_fixup(void) +{ + struct pci_dev *dev = NULL; + for_each_pci_dev(dev) { + mpc7448_hpc2_fixup_irq(dev); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + } +} + +static void __init mpc7448_hpc2_setup_arch(void) +{ + struct device_node *cpu; + struct device_node *np; + if (ppc_md.progress) + ppc_md.progress("mpc7448_hpc2_setup_arch():set_bridge", 0); + + cpu = of_find_node_by_type(NULL, "cpu"); + if (cpu != 0) { + unsigned int *fp; + + fp = (int *)get_property(cpu, "clock-frequency", NULL); + if (fp != 0) + loops_per_jiffy = *fp / HZ; + else + loops_per_jiffy = 50000000 / HZ; + of_node_put(cpu); + } + tsi108_csr_vir_base = get_vir_csrbase(); + +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif + +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = Root_RAM0; +#endif + + /* setup PCI host bridge */ +#ifdef CONFIG_PCI + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + tsi108_setup_pci(np); + + ppc_md.pci_exclude_device = mpc7448_hpc2_exclude_device; + if (ppc_md.progress) + ppc_md.progress("tsi108: resources set", 0x100); +#endif + + printk(KERN_INFO "MPC7448HPC2 (TAIGA) Platform\n"); + printk(KERN_INFO + "Jointly ported by Freescale and Tundra Semiconductor\n"); + printk(KERN_INFO + "Enabling L2 cache then enabling the HID0 prefetch engine.\n"); +} + +/* + * Interrupt setup and service. Interrrupts on the mpc7448_hpc2 come + * from the four external INT pins, PCI interrupts are routed via + * PCI interrupt control registers, it generates internal IRQ23 + * + * Interrupt routing on the Taiga Board: + * TSI108:PB_INT[0] -> CPU0:INT# + * TSI108:PB_INT[1] -> CPU0:MCP# + * TSI108:PB_INT[2] -> N/C + * TSI108:PB_INT[3] -> N/C + */ +static void __init mpc7448_hpc2_init_IRQ(void) +{ + struct mpic *mpic; + phys_addr_t mpic_paddr = 0; + unsigned int cascade_pci_irq; + struct device_node *tsi_pci; + struct device_node *tsi_pic; + + tsi_pic = of_find_node_by_type(NULL, "open-pic"); + if (tsi_pic) { + unsigned int size; + void *prop = get_property(tsi_pic, "reg", &size); + mpic_paddr = of_translate_address(tsi_pic, prop); + } + + if (mpic_paddr == 0) { + printk("%s: No tsi108 PIC found !\n", __FUNCTION__); + return; + } + + DBG("%s: tsi108pic phys_addr = 0x%x\n", __FUNCTION__, + (u32) mpic_paddr); + + mpic = mpic_alloc(tsi_pic, mpic_paddr, + MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET | + MPIC_SPV_EOI | MPIC_NO_PTHROU_DIS | MPIC_REGSET_TSI108, + 0, /* num_sources used */ + 0, /* num_sources used */ + "Tsi108_PIC"); + + BUG_ON(mpic == NULL); /* XXXX */ + mpic_init(mpic); + + tsi_pci = of_find_node_by_type(NULL, "pci"); + if (tsi_pci == 0) { + printk("%s: No tsi108 pci node found !\n", __FUNCTION__); + return; + } + + cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0); + set_irq_data(cascade_pci_irq, mpic); + set_irq_chained_handler(cascade_pci_irq, tsi108_irq_cascade); + + tsi108_pci_int_init(); + + /* Configure MPIC outputs to CPU0 */ + tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0); + of_node_put(tsi_pic); +} + +void mpc7448_hpc2_show_cpuinfo(struct seq_file *m) +{ + seq_printf(m, "vendor\t\t: Freescale Semiconductor\n"); + seq_printf(m, "machine\t\t: MPC7448hpc2\n"); +} + +void mpc7448_hpc2_restart(char *cmd) +{ + local_irq_disable(); + + /* Set exception prefix high - to the firmware */ + _nmask_and_or_msr(0, MSR_IP); + + for (;;) ; /* Spin until reset happens */ +} + +void mpc7448_hpc2_power_off(void) +{ + local_irq_disable(); + for (;;) ; /* No way to shut power off with software */ +} + +void mpc7448_hpc2_halt(void) +{ + mpc7448_hpc2_power_off(); +} + +/* + * Called very early, device-tree isn't unflattened + */ +static int __init mpc7448_hpc2_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + if (!of_flat_dt_is_compatible(root, "mpc74xx")) + return 0; + return 1; +} + +static int mpc7448_machine_check_exception(struct pt_regs *regs) +{ + extern void tsi108_clear_pci_cfg_error(void); + const struct exception_table_entry *entry; + + /* Are we prepared to handle this fault */ + if ((entry = search_exception_tables(regs->nip)) != NULL) { + tsi108_clear_pci_cfg_error(); + regs->msr |= MSR_RI; + regs->nip = entry->fixup; + return 1; + } + return 0; + +} + +define_machine(mpc7448_hpc2){ + .name = "MPC7448 HPC2", + .probe = mpc7448_hpc2_probe, + .setup_arch = mpc7448_hpc2_setup_arch, + .init_IRQ = mpc7448_hpc2_init_IRQ, + .show_cpuinfo = mpc7448_hpc2_show_cpuinfo, + .get_irq = mpic_get_irq, + .pcibios_fixup = mpc7448_hpc2_pcibios_fixup, + .restart = mpc7448_hpc2_restart, + .calibrate_decr = generic_calibrate_decr, + .machine_check_exception= mpc7448_machine_check_exception, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h new file mode 100644 index 000000000..a543a5242 --- /dev/null +++ b/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h @@ -0,0 +1,26 @@ +/* + * mpc7448_hpc2.h + * + * Definitions for Freescale MPC7448_HPC2 platform + * + * Author: Jacob Pan + * jacob.pan@freescale.com + * Maintainer: Roy Zang <roy.zang@freescale.com> + * + * 2006 (c) Freescale Semiconductor, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#ifndef __PPC_PLATFORMS_MPC7448_HPC2_H +#define __PPC_PLATFORMS_MPC7448_HPC2_H + +#include <asm/ppcboot.h> + +/* Base Addresses for the PCI bus + */ +#define MPC7448_HPC2_PCI_MEM_OFFSET (0x00000000) +#define MPC7448_HPC2_ISA_IO_BASE (0x00000000) +#define MPC7448_HPC2_ISA_MEM_BASE (0x00000000) +#endif /* __PPC_PLATFORMS_MPC7448_HPC2_H */ diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c new file mode 100644 index 000000000..d194140c1 --- /dev/null +++ b/arch/powerpc/platforms/iseries/dt.c @@ -0,0 +1,617 @@ +/* + * Copyright (c) 2005-2006 Michael Ellerman, IBM Corporation + * + * Description: + * This file contains all the routines to build a flattened device + * tree for a legacy iSeries machine. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#undef DEBUG + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/pci_regs.h> +#include <linux/pci_ids.h> +#include <linux/threads.h> +#include <linux/bitops.h> +#include <linux/string.h> +#include <linux/kernel.h> +#include <linux/if_ether.h> /* ETH_ALEN */ + +#include <asm/machdep.h> +#include <asm/prom.h> +#include <asm/lppaca.h> +#include <asm/cputable.h> +#include <asm/abs_addr.h> +#include <asm/system.h> +#include <asm/iseries/hv_types.h> +#include <asm/iseries/hv_lp_config.h> +#include <asm/iseries/hv_call_xm.h> +#include <asm/iseries/it_exp_vpd_panel.h> +#include <asm/udbg.h> + +#include "processor_vpd.h" +#include "call_hpt.h" +#include "call_pci.h" +#include "pci.h" + +#ifdef DEBUG +#define DBG(fmt...) udbg_printf(fmt) +#else +#define DBG(fmt...) +#endif + +/* + * These are created by the linker script at the start and end + * of the section containing all the strings from this file. + */ +extern char __dt_strings_start[]; +extern char __dt_strings_end[]; + +struct iseries_flat_dt { + struct boot_param_header header; + u64 reserve_map[2]; +}; + +static void * __initdata dt_data; + +/* + * Putting these strings here keeps them out of the section + * that we rename to .dt_strings using objcopy and capture + * for the strings blob of the flattened device tree. + */ +static char __initdata device_type_cpu[] = "cpu"; +static char __initdata device_type_memory[] = "memory"; +static char __initdata device_type_serial[] = "serial"; +static char __initdata device_type_network[] = "network"; +static char __initdata device_type_block[] = "block"; +static char __initdata device_type_byte[] = "byte"; +static char __initdata device_type_pci[] = "pci"; +static char __initdata device_type_vdevice[] = "vdevice"; +static char __initdata device_type_vscsi[] = "vscsi"; + +static struct iseries_flat_dt * __init dt_init(void) +{ + struct iseries_flat_dt *dt; + unsigned long str_len; + + str_len = __dt_strings_end - __dt_strings_start; + dt = (struct iseries_flat_dt *)ALIGN(klimit, 8); + dt->header.off_mem_rsvmap = + offsetof(struct iseries_flat_dt, reserve_map); + dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8); + dt->header.off_dt_struct = dt->header.off_dt_strings + + ALIGN(str_len, 8); + dt_data = (void *)((unsigned long)dt + dt->header.off_dt_struct); + dt->header.dt_strings_size = str_len; + + /* There is no notion of hardware cpu id on iSeries */ + dt->header.boot_cpuid_phys = smp_processor_id(); + + memcpy((char *)dt + dt->header.off_dt_strings, __dt_strings_start, + str_len); + + dt->header.magic = OF_DT_HEADER; + dt->header.version = 0x10; + dt->header.last_comp_version = 0x10; + + dt->reserve_map[0] = 0; + dt->reserve_map[1] = 0; + + return dt; +} + +static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value) +{ + *((u32 *)dt_data) = value; + dt_data += sizeof(u32); +} + +#ifdef notyet +static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value) +{ + *((u64 *)dt_data) = value; + dt_data += sizeof(u64); +} +#endif + +static void __init dt_push_bytes(struct iseries_flat_dt *dt, const char *data, + int len) +{ + memcpy(dt_data, data, len); + dt_data += ALIGN(len, 4); +} + +static void __init dt_start_node(struct iseries_flat_dt *dt, const char *name) +{ + dt_push_u32(dt, OF_DT_BEGIN_NODE); + dt_push_bytes(dt, name, strlen(name) + 1); +} + +#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) + +static void __init dt_prop(struct iseries_flat_dt *dt, const char *name, + const void *data, int len) +{ + unsigned long offset; + + dt_push_u32(dt, OF_DT_PROP); + + /* Length of the data */ + dt_push_u32(dt, len); + + offset = name - __dt_strings_start; + + /* The offset of the properties name in the string blob. */ + dt_push_u32(dt, (u32)offset); + + /* The actual data. */ + dt_push_bytes(dt, data, len); +} + +static void __init dt_prop_str(struct iseries_flat_dt *dt, const char *name, + const char *data) +{ + dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */ +} + +static void __init dt_prop_u32(struct iseries_flat_dt *dt, const char *name, + u32 data) +{ + dt_prop(dt, name, &data, sizeof(u32)); +} + +#ifdef notyet +static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name, + u64 data) +{ + dt_prop(dt, name, &data, sizeof(u64)); +} +#endif + +static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, + const char *name, u64 *data, int n) +{ + dt_prop(dt, name, data, sizeof(u64) * n); +} + +static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, + const char *name, u32 *data, int n) +{ + dt_prop(dt, name, data, sizeof(u32) * n); +} + +#ifdef notyet +static void __init dt_prop_empty(struct iseries_flat_dt *dt, const char *name) +{ + dt_prop(dt, name, NULL, 0); +} +#endif + +static void __init dt_cpus(struct iseries_flat_dt *dt) +{ + unsigned char buf[32]; + unsigned char *p; + unsigned int i, index; + struct IoHriProcessorVpd *d; + u32 pft_size[2]; + + /* yuck */ + snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name); + p = strchr(buf, ' '); + if (!p) p = buf + strlen(buf); + + dt_start_node(dt, "cpus"); + dt_prop_u32(dt, "#address-cells", 1); + dt_prop_u32(dt, "#size-cells", 0); + + pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA */ + pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); + + for (i = 0; i < NR_CPUS; i++) { + if (lppaca[i].dyn_proc_status >= 2) + continue; + + snprintf(p, 32 - (p - buf), "@%d", i); + dt_start_node(dt, buf); + + dt_prop_str(dt, "device_type", device_type_cpu); + + index = lppaca[i].dyn_hv_phys_proc_index; + d = &xIoHriProcessorVpd[index]; + + dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); + dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize); + + dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024); + dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize); + + /* magic conversions to Hz copied from old code */ + dt_prop_u32(dt, "clock-frequency", + ((1UL << 34) * 1000000) / d->xProcFreq); + dt_prop_u32(dt, "timebase-frequency", + ((1UL << 32) * 1000000) / d->xTimeBaseFreq); + + dt_prop_u32(dt, "reg", i); + + dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2); + + dt_end_node(dt); + } + + dt_end_node(dt); +} + +static void __init dt_model(struct iseries_flat_dt *dt) +{ + char buf[16] = "IBM,"; + + /* N.B. lparcfg.c knows about the "IBM," prefixes ... */ + /* "IBM," + mfgId[2:3] + systemSerial[1:5] */ + strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2); + strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5); + buf[11] = '\0'; + dt_prop_str(dt, "system-id", buf); + + /* "IBM," + machineType[0:4] */ + strne2a(buf + 4, xItExtVpdPanel.machineType, 4); + buf[8] = '\0'; + dt_prop_str(dt, "model", buf); + + dt_prop_str(dt, "compatible", "IBM,iSeries"); + dt_prop_u32(dt, "ibm,partition-no", HvLpConfig_getLpIndex()); +} + +static void __init dt_do_vdevice(struct iseries_flat_dt *dt, + const char *name, u32 reg, int unit, + const char *type, const char *compat, int end) +{ + char buf[32]; + + snprintf(buf, 32, "%s@%08x", name, reg + ((unit >= 0) ? unit : 0)); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", type); + if (compat) + dt_prop_str(dt, "compatible", compat); + dt_prop_u32(dt, "reg", reg + ((unit >= 0) ? unit : 0)); + if (unit >= 0) + dt_prop_u32(dt, "linux,unit_address", unit); + if (end) + dt_end_node(dt); +} + +static void __init dt_vdevices(struct iseries_flat_dt *dt) +{ + u32 reg = 0; + HvLpIndexMap vlan_map; + int i; + + dt_start_node(dt, "vdevice"); + dt_prop_str(dt, "device_type", device_type_vdevice); + dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice"); + dt_prop_u32(dt, "#address-cells", 1); + dt_prop_u32(dt, "#size-cells", 0); + + dt_do_vdevice(dt, "vty", reg, -1, device_type_serial, NULL, 1); + reg++; + + dt_do_vdevice(dt, "v-scsi", reg, -1, device_type_vscsi, + "IBM,v-scsi", 1); + reg++; + + vlan_map = HvLpConfig_getVirtualLanIndexMap(); + for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { + unsigned char mac_addr[ETH_ALEN]; + + if ((vlan_map & (0x8000 >> i)) == 0) + continue; + dt_do_vdevice(dt, "l-lan", reg, i, device_type_network, + "IBM,iSeries-l-lan", 0); + mac_addr[0] = 0x02; + mac_addr[1] = 0x01; + mac_addr[2] = 0xff; + mac_addr[3] = i; + mac_addr[4] = 0xff; + mac_addr[5] = HvLpConfig_getLpIndex_outline(); + dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN); + dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN); + dt_prop_u32(dt, "max-frame-size", 9000); + dt_prop_u32(dt, "address-bits", 48); + + dt_end_node(dt); + } + reg += HVMAXARCHITECTEDVIRTUALLANS; + + for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) + dt_do_vdevice(dt, "viodasd", reg, i, device_type_block, + "IBM,iSeries-viodasd", 1); + reg += HVMAXARCHITECTEDVIRTUALDISKS; + + for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) + dt_do_vdevice(dt, "viocd", reg, i, device_type_block, + "IBM,iSeries-viocd", 1); + reg += HVMAXARCHITECTEDVIRTUALCDROMS; + + for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) + dt_do_vdevice(dt, "viotape", reg, i, device_type_byte, + "IBM,iSeries-viotape", 1); + + dt_end_node(dt); +} + +struct pci_class_name { + u16 code; + const char *name; + const char *type; +}; + +static struct pci_class_name __initdata pci_class_name[] = { + { PCI_CLASS_NETWORK_ETHERNET, "ethernet", device_type_network }, +}; + +static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code) +{ + struct pci_class_name *cp; + + for (cp = pci_class_name; + cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++) + if (cp->code == class_code) + return cp; + return NULL; +} + +/* + * This assumes that the node slot is always on the primary bus! + */ +static void __init scan_bridge_slot(struct iseries_flat_dt *dt, + HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info) +{ + HvSubBusNumber sub_bus = bridge_info->subBusNumber; + u16 vendor_id; + u16 device_id; + u32 class_id; + int err; + char buf[32]; + u32 reg[5]; + int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus); + int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus); + HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function); + u8 devfn; + struct pci_class_name *cp; + + /* + * Connect all functions of any device found. + */ + for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) { + for (function = 0; function < 8; function++) { + HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel, + function); + err = HvCallXm_connectBusUnit(bus, sub_bus, + agent_id, 0); + if (err) { + if (err != 0x302) + DBG("connectBusUnit(%x, %x, %x) %x\n", + bus, sub_bus, agent_id, err); + continue; + } + + err = HvCallPci_configLoad16(bus, sub_bus, agent_id, + PCI_VENDOR_ID, &vendor_id); + if (err) { + DBG("ReadVendor(%x, %x, %x) %x\n", + bus, sub_bus, agent_id, err); + continue; + } + err = HvCallPci_configLoad16(bus, sub_bus, agent_id, + PCI_DEVICE_ID, &device_id); + if (err) { + DBG("ReadDevice(%x, %x, %x) %x\n", + bus, sub_bus, agent_id, err); + continue; + } + err = HvCallPci_configLoad32(bus, sub_bus, agent_id, + PCI_CLASS_REVISION , &class_id); + if (err) { + DBG("ReadClass(%x, %x, %x) %x\n", + bus, sub_bus, agent_id, err); + continue; + } + + devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel), + function); + cp = dt_find_pci_class_name(class_id >> 16); + if (cp && cp->name) + strncpy(buf, cp->name, sizeof(buf) - 1); + else + snprintf(buf, sizeof(buf), "pci%x,%x", + vendor_id, device_id); + buf[sizeof(buf) - 1] = '\0'; + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), + "@%x", PCI_SLOT(devfn)); + buf[sizeof(buf) - 1] = '\0'; + if (function != 0) + snprintf(buf + strlen(buf), + sizeof(buf) - strlen(buf), + ",%x", function); + dt_start_node(dt, buf); + reg[0] = (bus << 16) | (devfn << 8); + reg[1] = 0; + reg[2] = 0; + reg[3] = 0; + reg[4] = 0; + dt_prop_u32_list(dt, "reg", reg, 5); + if (cp && (cp->type || cp->name)) + dt_prop_str(dt, "device_type", + cp->type ? cp->type : cp->name); + dt_prop_u32(dt, "vendor-id", vendor_id); + dt_prop_u32(dt, "device-id", device_id); + dt_prop_u32(dt, "class-code", class_id >> 8); + dt_prop_u32(dt, "revision-id", class_id & 0xff); + dt_prop_u32(dt, "linux,subbus", sub_bus); + dt_prop_u32(dt, "linux,agent-id", agent_id); + dt_prop_u32(dt, "linux,logical-slot-number", + bridge_info->logicalSlotNumber); + dt_end_node(dt); + + } + } +} + +static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, + HvSubBusNumber sub_bus, int id_sel) +{ + struct HvCallPci_BridgeInfo bridge_info; + HvAgentId agent_id; + int function; + int ret; + + /* Note: hvSubBus and irq is always be 0 at this level! */ + for (function = 0; function < 8; ++function) { + agent_id = ISERIES_PCI_AGENTID(id_sel, function); + ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0); + if (ret != 0) { + if (ret != 0xb) + DBG("connectBusUnit(%x, %x, %x) %x\n", + bus, sub_bus, agent_id, ret); + continue; + } + DBG("found device at bus %d idsel %d func %d (AgentId %x)\n", + bus, id_sel, function, agent_id); + ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id, + iseries_hv_addr(&bridge_info), + sizeof(struct HvCallPci_BridgeInfo)); + if (ret != 0) + continue; + DBG("bridge info: type %x subbus %x " + "maxAgents %x maxsubbus %x logslot %x\n", + bridge_info.busUnitInfo.deviceType, + bridge_info.subBusNumber, + bridge_info.maxAgents, + bridge_info.maxSubBusNumber, + bridge_info.logicalSlotNumber); + if (bridge_info.busUnitInfo.deviceType == + HvCallPci_BridgeDevice) + scan_bridge_slot(dt, bus, &bridge_info); + else + DBG("PCI: Invalid Bridge Configuration(0x%02X)", + bridge_info.busUnitInfo.deviceType); + } +} + +static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) +{ + struct HvCallPci_DeviceInfo dev_info; + const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */ + int err; + int id_sel; + const int max_agents = 8; + + /* + * Probe for EADs Bridges + */ + for (id_sel = 1; id_sel < max_agents; ++id_sel) { + err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel, + iseries_hv_addr(&dev_info), + sizeof(struct HvCallPci_DeviceInfo)); + if (err) { + if (err != 0x302) + DBG("getDeviceInfo(%x, %x, %x) %x\n", + bus, sub_bus, id_sel, err); + continue; + } + if (dev_info.deviceType != HvCallPci_NodeDevice) { + DBG("PCI: Invalid System Configuration" + "(0x%02X) for bus 0x%02x id 0x%02x.\n", + dev_info.deviceType, bus, id_sel); + continue; + } + scan_bridge(dt, bus, sub_bus, id_sel); + } +} + +static void __init dt_pci_devices(struct iseries_flat_dt *dt) +{ + HvBusNumber bus; + char buf[32]; + u32 buses[2]; + int phb_num = 0; + + /* Check all possible buses. */ + for (bus = 0; bus < 256; bus++) { + int err = HvCallXm_testBus(bus); + + if (err) { + /* + * Check for Unexpected Return code, a clue that + * something has gone wrong. + */ + if (err != 0x0301) + DBG("Unexpected Return on Probe(0x%02X) " + "0x%04X\n", bus, err); + continue; + } + DBG("bus %d appears to exist\n", bus); + snprintf(buf, 32, "pci@%d", phb_num); + dt_start_node(dt, buf); + dt_prop_str(dt, "device_type", device_type_pci); + dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB"); + dt_prop_u32(dt, "#address-cells", 3); + dt_prop_u32(dt, "#size-cells", 2); + buses[0] = buses[1] = bus; + dt_prop_u32_list(dt, "bus-range", buses, 2); + scan_phb(dt, bus); + dt_end_node(dt); + phb_num++; + } +} + +static void dt_finish(struct iseries_flat_dt *dt) +{ + dt_push_u32(dt, OF_DT_END); + dt->header.totalsize = (unsigned long)dt_data - (unsigned long)dt; + klimit = ALIGN((unsigned long)dt_data, 8); +} + +void * __init build_flat_dt(unsigned long phys_mem_size) +{ + struct iseries_flat_dt *iseries_dt; + u64 tmp[2]; + + iseries_dt = dt_init(); + + dt_start_node(iseries_dt, ""); + + dt_prop_u32(iseries_dt, "#address-cells", 2); + dt_prop_u32(iseries_dt, "#size-cells", 2); + dt_model(iseries_dt); + + /* /memory */ + dt_start_node(iseries_dt, "memory@0"); + dt_prop_str(iseries_dt, "device_type", device_type_memory); + tmp[0] = 0; + tmp[1] = phys_mem_size; + dt_prop_u64_list(iseries_dt, "reg", tmp, 2); + dt_end_node(iseries_dt); + + /* /chosen */ + dt_start_node(iseries_dt, "chosen"); + dt_prop_str(iseries_dt, "bootargs", cmd_line); + dt_end_node(iseries_dt); + + dt_cpus(iseries_dt); + + dt_vdevices(iseries_dt); + dt_pci_devices(iseries_dt); + + dt_end_node(iseries_dt); + + dt_finish(iseries_dt); + + return iseries_dt; +} diff --git a/arch/powerpc/sysdev/todc.c b/arch/powerpc/sysdev/todc.c new file mode 100644 index 000000000..0a65980ef --- /dev/null +++ b/arch/powerpc/sysdev/todc.c @@ -0,0 +1,392 @@ +/* + * Time of Day Clock support for the M48T35, M48T37, M48T59, and MC146818 + * Real Time Clocks/Timekeepers. + * + * Author: Mark A. Greer <mgreer@mvista.com> + * + * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/time.h> +#include <linux/timex.h> +#include <linux/bcd.h> +#include <linux/mc146818rtc.h> + +#include <asm/machdep.h> +#include <asm/io.h> +#include <asm/time.h> +#include <asm/todc.h> + +/* + * Depending on the hardware on your board and your board design, the + * RTC/NVRAM may be accessed either directly (like normal memory) or via + * address/data registers. If your board uses the direct method, set + * 'nvram_data' to the base address of your nvram and leave 'nvram_as0' and + * 'nvram_as1' NULL. If your board uses address/data regs to access nvram, + * set 'nvram_as0' to the address of the lower byte, set 'nvram_as1' to the + * address of the upper byte (leave NULL if using mc146818), and set + * 'nvram_data' to the address of the 8-bit data register. + * + * Note: Even though the documentation for the various RTC chips say that it + * take up to a second before it starts updating once the 'R' bit is + * cleared, they always seem to update even though we bang on it many + * times a second. This is true, except for the Dallas Semi 1746/1747 + * (possibly others). Those chips seem to have a real problem whenever + * we set the 'R' bit before reading them, they basically stop counting. + * --MAG + */ + +/* + * 'todc_info' should be initialized in your *_setup.c file to + * point to a fully initialized 'todc_info_t' structure. + * This structure holds all the register offsets for your particular + * TODC/RTC chip. + * TODC_ALLOC()/TODC_INIT() will allocate and initialize this table for you. + */ + +#ifdef RTC_FREQ_SELECT +#undef RTC_FREQ_SELECT +#define RTC_FREQ_SELECT control_b /* Register A */ +#endif + +#ifdef RTC_CONTROL +#undef RTC_CONTROL +#define RTC_CONTROL control_a /* Register B */ +#endif + +#ifdef RTC_INTR_FLAGS +#undef RTC_INTR_FLAGS +#define RTC_INTR_FLAGS watchdog /* Register C */ +#endif + +#ifdef RTC_VALID +#undef RTC_VALID +#define RTC_VALID interrupts /* Register D */ +#endif + +/* Access routines when RTC accessed directly (like normal memory) */ +u_char +todc_direct_read_val(int addr) +{ + return readb((void __iomem *)(todc_info->nvram_data + addr)); +} + +void +todc_direct_write_val(int addr, unsigned char val) +{ + writeb(val, (void __iomem *)(todc_info->nvram_data + addr)); + return; +} + +/* Access routines for accessing m48txx type chips via addr/data regs */ +u_char +todc_m48txx_read_val(int addr) +{ + outb(addr, todc_info->nvram_as0); + outb(addr>>todc_info->as0_bits, todc_info->nvram_as1); + return inb(todc_info->nvram_data); +} + +void +todc_m48txx_write_val(int addr, unsigned char val) +{ + outb(addr, todc_info->nvram_as0); + outb(addr>>todc_info->as0_bits, todc_info->nvram_as1); + outb(val, todc_info->nvram_data); + return; +} + +/* Access routines for accessing mc146818 type chips via addr/data regs */ +u_char +todc_mc146818_read_val(int addr) +{ + outb_p(addr, todc_info->nvram_as0); + return inb_p(todc_info->nvram_data); +} + +void +todc_mc146818_write_val(int addr, unsigned char val) +{ + outb_p(addr, todc_info->nvram_as0); + outb_p(val, todc_info->nvram_data); +} + + +/* + * Routines to make RTC chips with NVRAM buried behind an addr/data pair + * have the NVRAM and clock regs appear at the same level. + * The NVRAM will appear to start at addr 0 and the clock regs will appear + * to start immediately after the NVRAM (actually, start at offset + * todc_info->nvram_size). + */ +static inline u_char +todc_read_val(int addr) +{ + u_char val; + + if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) { + if (addr < todc_info->nvram_size) { /* NVRAM */ + ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr); + val = ppc_md.rtc_read_val(todc_info->nvram_data_reg); + } else { /* Clock Reg */ + addr -= todc_info->nvram_size; + val = ppc_md.rtc_read_val(addr); + } + } else + val = ppc_md.rtc_read_val(addr); + + return val; +} + +static inline void +todc_write_val(int addr, u_char val) +{ + if (todc_info->sw_flags & TODC_FLAG_2_LEVEL_NVRAM) { + if (addr < todc_info->nvram_size) { /* NVRAM */ + ppc_md.rtc_write_val(todc_info->nvram_addr_reg, addr); + ppc_md.rtc_write_val(todc_info->nvram_data_reg, val); + } else { /* Clock Reg */ + addr -= todc_info->nvram_size; + ppc_md.rtc_write_val(addr, val); + } + } else + ppc_md.rtc_write_val(addr, val); +} + +/* + * TODC routines + * + * There is some ugly stuff in that there are assumptions for the mc146818. + * + * Assumptions: + * - todc_info->control_a has the offset as mc146818 Register B reg + * - todc_info->control_b has the offset as mc146818 Register A reg + * - m48txx control reg's write enable or 'W' bit is same as + * mc146818 Register B 'SET' bit (i.e., 0x80) + * + * These assumptions were made to make the code simpler. + */ +long __init +todc_time_init(void) +{ + u_char cntl_b; + + if (!ppc_md.rtc_read_val) + ppc_md.rtc_read_val = ppc_md.nvram_read_val; + if (!ppc_md.rtc_write_val) + ppc_md.rtc_write_val = ppc_md.nvram_write_val; + + cntl_b = todc_read_val(todc_info->control_b); + + if (todc_info->rtc_type == TODC_TYPE_MC146818) { + if ((cntl_b & 0x70) != 0x20) { + printk(KERN_INFO "TODC real-time-clock was stopped." + " Now starting..."); + cntl_b &= ~0x70; + cntl_b |= 0x20; + } + + todc_write_val(todc_info->control_b, cntl_b); + } else if (todc_info->rtc_type == TODC_TYPE_DS17285) { + u_char mode; + + mode = todc_read_val(TODC_TYPE_DS17285_CNTL_A); + /* Make sure countdown clear is not set */ + mode &= ~0x40; + /* Enable oscillator, extended register set */ + mode |= 0x30; + todc_write_val(TODC_TYPE_DS17285_CNTL_A, mode); + + } else if (todc_info->rtc_type == TODC_TYPE_DS1501) { + u_char month; + + todc_info->enable_read = TODC_DS1501_CNTL_B_TE; + todc_info->enable_write = TODC_DS1501_CNTL_B_TE; + + month = todc_read_val(todc_info->month); + + if ((month & 0x80) == 0x80) { + printk(KERN_INFO "TODC %s %s\n", + "real-time-clock was stopped.", + "Now starting..."); + month &= ~0x80; + todc_write_val(todc_info->month, month); + } + + cntl_b &= ~TODC_DS1501_CNTL_B_TE; + todc_write_val(todc_info->control_b, cntl_b); + } else { /* must be a m48txx type */ + u_char cntl_a; + + todc_info->enable_read = TODC_MK48TXX_CNTL_A_R; + todc_info->enable_write = TODC_MK48TXX_CNTL_A_W; + + cntl_a = todc_read_val(todc_info->control_a); + + /* Check & clear STOP bit in control B register */ + if (cntl_b & TODC_MK48TXX_DAY_CB) { + printk(KERN_INFO "TODC %s %s\n", + "real-time-clock was stopped.", + "Now starting..."); + + cntl_a |= todc_info->enable_write; + cntl_b &= ~TODC_MK48TXX_DAY_CB;/* Start Oscil */ + + todc_write_val(todc_info->control_a, cntl_a); + todc_write_val(todc_info->control_b, cntl_b); + } + + /* Make sure READ & WRITE bits are cleared. */ + cntl_a &= ~(todc_info->enable_write | todc_info->enable_read); + todc_write_val(todc_info->control_a, cntl_a); + } + + return 0; +} + +/* + * There is some ugly stuff in that there are assumptions that for a mc146818, + * the todc_info->control_a has the offset of the mc146818 Register B reg and + * that the register'ss 'SET' bit is the same as the m48txx's write enable + * bit in the control register of the m48txx (i.e., 0x80). + * + * It was done to make the code look simpler. + */ +void +todc_get_rtc_time(struct rtc_time *tm) +{ + uint year = 0, mon = 0, mday = 0, hour = 0, min = 0, sec = 0; + uint limit, i; + u_char save_control, uip = 0; + extern void GregorianDay(struct rtc_time *); + + spin_lock(&rtc_lock); + save_control = todc_read_val(todc_info->control_a); + + if (todc_info->rtc_type != TODC_TYPE_MC146818) { + limit = 1; + + switch (todc_info->rtc_type) { + case TODC_TYPE_DS1553: + case TODC_TYPE_DS1557: + case TODC_TYPE_DS1743: + case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */ + case TODC_TYPE_DS1747: + case TODC_TYPE_DS17285: + break; + default: + todc_write_val(todc_info->control_a, + (save_control | todc_info->enable_read)); + } + } else + limit = 100000000; + + for (i=0; i<limit; i++) { + if (todc_info->rtc_type == TODC_TYPE_MC146818) + uip = todc_read_val(todc_info->RTC_FREQ_SELECT); + + sec = todc_read_val(todc_info->seconds) & 0x7f; + min = todc_read_val(todc_info->minutes) & 0x7f; + hour = todc_read_val(todc_info->hours) & 0x3f; + mday = todc_read_val(todc_info->day_of_month) & 0x3f; + mon = todc_read_val(todc_info->month) & 0x1f; + year = todc_read_val(todc_info->year) & 0xff; + + if (todc_info->rtc_type == TODC_TYPE_MC146818) { + uip |= todc_read_val(todc_info->RTC_FREQ_SELECT); + if ((uip & RTC_UIP) == 0) + break; + } + } + + if (todc_info->rtc_type != TODC_TYPE_MC146818) { + switch (todc_info->rtc_type) { + case TODC_TYPE_DS1553: + case TODC_TYPE_DS1557: + case TODC_TYPE_DS1743: + case TODC_TYPE_DS1746: /* XXXX BAD HACK -> FIX */ + case TODC_TYPE_DS1747: + case TODC_TYPE_DS17285: + break; + default: + save_control &= ~(todc_info->enable_read); + todc_write_val(todc_info->control_a, save_control); + } + } + spin_unlock(&rtc_lock); + + if ((todc_info->rtc_type != TODC_TYPE_MC146818) + || ((save_control & RTC_DM_BINARY) == 0) + || RTC_ALWAYS_BCD) { + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(mday); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + } + + if ((year + 1900) < 1970) { + year += 100; + } + + tm->tm_sec = sec; + tm->tm_min = min; + tm->tm_hour = hour; + tm->tm_mday = mday; + tm->tm_mon = mon; + tm->tm_year = year; + + GregorianDay(tm); +} + +int +todc_set_rtc_time(struct rtc_time *tm) +{ + u_char save_control, save_freq_select = 0; + + spin_lock(&rtc_lock); + save_control = todc_read_val(todc_info->control_a); + + /* Assuming MK48T59_RTC_CA_WRITE & RTC_SET are equal */ + todc_write_val(todc_info->control_a, + (save_control | todc_info->enable_write)); + save_control &= ~(todc_info->enable_write); /* in case it was set */ + + if (todc_info->rtc_type == TODC_TYPE_MC146818) { + save_freq_select = todc_read_val(todc_info->RTC_FREQ_SELECT); + todc_write_val(todc_info->RTC_FREQ_SELECT, + save_freq_select | RTC_DIV_RESET2); + } + + if ((todc_info->rtc_type != TODC_TYPE_MC146818) + || ((save_control & RTC_DM_BINARY) == 0) + || RTC_ALWAYS_BCD) { + BIN_TO_BCD(tm->tm_sec); + BIN_TO_BCD(tm->tm_min); + BIN_TO_BCD(tm->tm_hour); + BIN_TO_BCD(tm->tm_mon); + BIN_TO_BCD(tm->tm_mday); + BIN_TO_BCD(tm->tm_year); + } + + todc_write_val(todc_info->seconds, tm->tm_sec); + todc_write_val(todc_info->minutes, tm->tm_min); + todc_write_val(todc_info->hours, tm->tm_hour); + todc_write_val(todc_info->month, tm->tm_mon); + todc_write_val(todc_info->day_of_month, tm->tm_mday); + todc_write_val(todc_info->year, tm->tm_year); + + todc_write_val(todc_info->control_a, save_control); + + if (todc_info->rtc_type == TODC_TYPE_MC146818) + todc_write_val(todc_info->RTC_FREQ_SELECT, save_freq_select); + + spin_unlock(&rtc_lock); + return 0; +} diff --git a/arch/powerpc/sysdev/tsi108_dev.c b/arch/powerpc/sysdev/tsi108_dev.c new file mode 100644 index 000000000..11de090eb --- /dev/null +++ b/arch/powerpc/sysdev/tsi108_dev.c @@ -0,0 +1,146 @@ +/* + * tsi108/109 device setup code + * + * Maintained by Roy Zang < tie-fei.zang@freescale.com > + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/major.h> +#include <linux/delay.h> +#include <linux/irq.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <asm/tsi108.h> + +#include <asm/system.h> +#include <asm/atomic.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/prom.h> +#include <mm/mmu_decl.h> + +#undef DEBUG + +#ifdef DEBUG +#define DBG(fmt...) do { printk(fmt); } while(0) +#else +#define DBG(fmt...) do { } while(0) +#endif + +static phys_addr_t tsi108_csr_base = -1; + +phys_addr_t get_csrbase(void) +{ + struct device_node *tsi; + + if (tsi108_csr_base != -1) + return tsi108_csr_base; + + tsi = of_find_node_by_type(NULL, "tsi-bridge"); + if (tsi) { + unsigned int size; + void *prop = get_property(tsi, "reg", &size); + tsi108_csr_base = of_translate_address(tsi, prop); + of_node_put(tsi); + }; + return tsi108_csr_base; +} + +u32 get_vir_csrbase(void) +{ + return (u32) (ioremap(get_csrbase(), 0x10000)); +} + +EXPORT_SYMBOL(get_csrbase); +EXPORT_SYMBOL(get_vir_csrbase); + +static int __init tsi108_eth_of_init(void) +{ + struct device_node *np; + unsigned int i; + struct platform_device *tsi_eth_dev; + struct resource res; + int ret; + + for (np = NULL, i = 0; + (np = of_find_compatible_node(np, "network", "tsi-ethernet")) != NULL; + i++) { + struct resource r[2]; + struct device_node *phy; + hw_info tsi_eth_data; + unsigned int *id; + unsigned int *phy_id; + void *mac_addr; + phandle *ph; + + memset(r, 0, sizeof(r)); + memset(&tsi_eth_data, 0, sizeof(tsi_eth_data)); + + ret = of_address_to_resource(np, 0, &r[0]); + DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n", + __FUNCTION__,r[0].name, r[0].start, r[0].end); + if (ret) + goto err; + + r[1].name = "tx"; + r[1].start = irq_of_parse_and_map(np, 0); + r[1].end = irq_of_parse_and_map(np, 0); + r[1].flags = IORESOURCE_IRQ; + DBG("%s: name:start->end = %s:0x%lx-> 0x%lx\n", + __FUNCTION__,r[1].name, r[1].start, r[1].end); + + tsi_eth_dev = + platform_device_register_simple("tsi-ethernet", i, &r[0], + 1); + + if (IS_ERR(tsi_eth_dev)) { + ret = PTR_ERR(tsi_eth_dev); + goto err; + } + + mac_addr = get_property(np, "address", NULL); + memcpy(tsi_eth_data.mac_addr, mac_addr, 6); + + ph = (phandle *) get_property(np, "phy-handle", NULL); + phy = of_find_node_by_phandle(*ph); + + if (phy == NULL) { + ret = -ENODEV; + goto unreg; + } + + id = (u32 *) get_property(phy, "reg", NULL); + phy_id = (u32 *) get_property(phy, "phy-id", NULL); + ret = of_address_to_resource(phy, 0, &res); + if (ret) { + of_node_put(phy); + goto unreg; + } + tsi_eth_data.regs = r[0].start; + tsi_eth_data.phyregs = res.start; + tsi_eth_data.phy = *phy_id; + tsi_eth_data.irq_num = irq_of_parse_and_map(np, 0); + of_node_put(phy); + ret = + platform_device_add_data(tsi_eth_dev, &tsi_eth_data, + sizeof(hw_info)); + if (ret) + goto unreg; + } + return 0; +unreg: + platform_device_unregister(tsi_eth_dev); +err: + return ret; +} + +arch_initcall(tsi108_eth_of_init); diff --git a/arch/powerpc/sysdev/tsi108_pci.c b/arch/powerpc/sysdev/tsi108_pci.c new file mode 100644 index 000000000..2ab06ed3a --- /dev/null +++ b/arch/powerpc/sysdev/tsi108_pci.c @@ -0,0 +1,415 @@ +/* + * Common routines for Tundra Semiconductor TSI108 host bridge. + * + * 2004-2005 (c) Tundra Semiconductor Corp. + * Author: Alex Bounine (alexandreb@tundra.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/slab.h> +#include <linux/irq.h> +#include <linux/interrupt.h> + +#include <asm/byteorder.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/uaccess.h> +#include <asm/machdep.h> +#include <asm/pci-bridge.h> +#include <asm/tsi108.h> +#include <asm/tsi108_irq.h> +#include <asm/prom.h> + +#undef DEBUG +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +#define tsi_mk_config_addr(bus, devfunc, offset) \ + ((((bus)<<16) | ((devfunc)<<8) | (offset & 0xfc)) + tsi108_pci_cfg_base) + +u32 tsi108_pci_cfg_base; +u32 tsi108_csr_vir_base; + +extern u32 get_vir_csrbase(void); +extern u32 tsi108_read_reg(u32 reg_offset); +extern void tsi108_write_reg(u32 reg_offset, u32 val); + +int +tsi108_direct_write_config(struct pci_bus *bus, unsigned int devfunc, + int offset, int len, u32 val) +{ + volatile unsigned char *cfg_addr; + + if (ppc_md.pci_exclude_device) + if (ppc_md.pci_exclude_device(bus->number, devfunc)) + return PCIBIOS_DEVICE_NOT_FOUND; + + cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number, + devfunc, offset) | + (offset & 0x03)); + +#ifdef DEBUG + printk("PCI CFG write : "); + printk("%d:0x%x:0x%x ", bus->number, devfunc, offset); + printk("%d ADDR=0x%08x ", len, (uint) cfg_addr); + printk("data = 0x%08x\n", val); +#endif + + switch (len) { + case 1: + out_8((u8 *) cfg_addr, val); + break; + case 2: + out_le16((u16 *) cfg_addr, val); + break; + default: + out_le32((u32 *) cfg_addr, val); + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +void tsi108_clear_pci_error(u32 pci_cfg_base) +{ + u32 err_stat, err_addr, pci_stat; + + /* + * Quietly clear PB and PCI error flags set as result + * of PCI/X configuration read requests. + */ + + /* Read PB Error Log Registers */ + + err_stat = tsi108_read_reg(TSI108_PB_OFFSET + TSI108_PB_ERRCS); + err_addr = tsi108_read_reg(TSI108_PB_OFFSET + TSI108_PB_AERR); + + if (err_stat & TSI108_PB_ERRCS_ES) { + /* Clear error flag */ + tsi108_write_reg(TSI108_PB_OFFSET + TSI108_PB_ERRCS, + TSI108_PB_ERRCS_ES); + + /* Clear read error reported in PB_ISR */ + tsi108_write_reg(TSI108_PB_OFFSET + TSI108_PB_ISR, + TSI108_PB_ISR_PBS_RD_ERR); + + /* Clear PCI/X bus cfg errors if applicable */ + if ((err_addr & 0xFF000000) == pci_cfg_base) { + pci_stat = + tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_CSR); + tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_CSR, + pci_stat); + } + } + + return; +} + +#define __tsi108_read_pci_config(x, addr, op) \ + __asm__ __volatile__( \ + " "op" %0,0,%1\n" \ + "1: eieio\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: li %0,-1\n" \ + " b 2b\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 2\n" \ + " .long 1b,3b\n" \ + ".text" \ + : "=r"(x) : "r"(addr)) + +int +tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn, int offset, + int len, u32 * val) +{ + volatile unsigned char *cfg_addr; + u32 temp; + + if (ppc_md.pci_exclude_device) + if (ppc_md.pci_exclude_device(bus->number, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + cfg_addr = (unsigned char *)(tsi_mk_config_addr(bus->number, + devfn, + offset) | (offset & + 0x03)); + + switch (len) { + case 1: + __tsi108_read_pci_config(temp, cfg_addr, "lbzx"); + break; + case 2: + __tsi108_read_pci_config(temp, cfg_addr, "lhbrx"); + break; + default: + __tsi108_read_pci_config(temp, cfg_addr, "lwbrx"); + break; + } + + *val = temp; + +#ifdef DEBUG + if ((0xFFFFFFFF != temp) && (0xFFFF != temp) && (0xFF != temp)) { + printk("PCI CFG read : "); + printk("%d:0x%x:0x%x ", bus->number, devfn, offset); + printk("%d ADDR=0x%08x ", len, (uint) cfg_addr); + printk("data = 0x%x\n", *val); + } +#endif + return PCIBIOS_SUCCESSFUL; +} + +void tsi108_clear_pci_cfg_error(void) +{ + tsi108_clear_pci_error(TSI108_PCI_CFG_BASE_PHYS); +} + +static struct pci_ops tsi108_direct_pci_ops = { + tsi108_direct_read_config, + tsi108_direct_write_config +}; + +int __init tsi108_setup_pci(struct device_node *dev) +{ + int len; + struct pci_controller *hose; + struct resource rsrc; + int *bus_range; + int primary = 0, has_address = 0; + + /* PCI Config mapping */ + tsi108_pci_cfg_base = (u32)ioremap(TSI108_PCI_CFG_BASE_PHYS, + TSI108_PCI_CFG_SIZE); + DBG("TSI_PCI: %s tsi108_pci_cfg_base=0x%x\n", __FUNCTION__, + tsi108_pci_cfg_base); + + /* Fetch host bridge registers address */ + has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); + + /* Get bus range if any */ + bus_range = (int *)get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s, assume" + " bus 0\n", dev->full_name); + } + + hose = pcibios_alloc_controller(); + + if (!hose) { + printk("PCI Host bridge init failed\n"); + return -ENOMEM; + } + hose->arch_data = dev; + hose->set_cfg_type = 1; + + hose->first_busno = bus_range ? bus_range[0] : 0; + hose->last_busno = bus_range ? bus_range[1] : 0xff; + + (hose)->ops = &tsi108_direct_pci_ops; + + printk(KERN_INFO "Found tsi108 PCI host bridge at 0x%08x. " + "Firmware bus number: %d->%d\n", + rsrc.start, hose->first_busno, hose->last_busno); + + /* Interpret the "ranges" property */ + /* This also maps the I/O region and sets isa_io/mem_base */ + pci_process_bridge_OF_ranges(hose, dev, primary); + return 0; +} + +/* + * Low level utility functions + */ + +static void tsi108_pci_int_mask(u_int irq) +{ + u_int irp_cfg; + int int_line = (irq - IRQ_PCI_INTAD_BASE); + + irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL); + mb(); + irp_cfg |= (1 << int_line); /* INTx_DIR = output */ + irp_cfg &= ~(3 << (8 + (int_line * 2))); /* INTx_TYPE = unused */ + tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL, irp_cfg); + mb(); + irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL); +} + +static void tsi108_pci_int_unmask(u_int irq) +{ + u_int irp_cfg; + int int_line = (irq - IRQ_PCI_INTAD_BASE); + + irp_cfg = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL); + mb(); + irp_cfg &= ~(1 << int_line); + irp_cfg |= (3 << (8 + (int_line * 2))); + tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL, irp_cfg); + mb(); +} + +static void init_pci_source(void) +{ + tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL, + 0x0000ff00); + tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE, + TSI108_PCI_IRP_ENABLE_P_INT); + mb(); +} + +static inline unsigned int get_pci_source(void) +{ + u_int temp = 0; + int irq = -1; + int i; + u_int pci_irp_stat; + static int mask = 0; + + /* Read PCI/X block interrupt status register */ + pci_irp_stat = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_STAT); + mb(); + + if (pci_irp_stat & TSI108_PCI_IRP_STAT_P_INT) { + /* Process Interrupt from PCI bus INTA# - INTD# lines */ + temp = + tsi108_read_reg(TSI108_PCI_OFFSET + + TSI108_PCI_IRP_INTAD) & 0xf; + mb(); + for (i = 0; i < 4; i++, mask++) { + if (temp & (1 << mask % 4)) { + irq = IRQ_PCI_INTA + mask % 4; + mask++; + break; + } + } + + /* Disable interrupts from PCI block */ + temp = tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE); + tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE, + temp & ~TSI108_PCI_IRP_ENABLE_P_INT); + mb(); + (void)tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE); + mb(); + } +#ifdef DEBUG + else { + printk("TSI108_PIC: error in TSI108_PCI_IRP_STAT\n"); + pci_irp_stat = + tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_STAT); + temp = + tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_INTAD); + mb(); + printk(">> stat=0x%08x intad=0x%08x ", pci_irp_stat, temp); + temp = + tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_CFG_CTL); + mb(); + printk("cfg_ctl=0x%08x ", temp); + temp = + tsi108_read_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE); + mb(); + printk("irp_enable=0x%08x\n", temp); + } +#endif /* end of DEBUG */ + + return irq; +} + + +/* + * Linux descriptor level callbacks + */ + +static void tsi108_pci_irq_enable(u_int irq) +{ + tsi108_pci_int_unmask(irq); +} + +static void tsi108_pci_irq_disable(u_int irq) +{ + tsi108_pci_int_mask(irq); +} + +static void tsi108_pci_irq_ack(u_int irq) +{ + tsi108_pci_int_mask(irq); +} + +static void tsi108_pci_irq_end(u_int irq) +{ + tsi108_pci_int_unmask(irq); + + /* Enable interrupts from PCI block */ + tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE, + tsi108_read_reg(TSI108_PCI_OFFSET + + TSI108_PCI_IRP_ENABLE) | + TSI108_PCI_IRP_ENABLE_P_INT); + mb(); +} + +/* + * Interrupt controller descriptor for cascaded PCI interrupt controller. + */ + +static struct irq_chip tsi108_pci_irq = { + .typename = "tsi108_PCI_int", + .mask = tsi108_pci_irq_disable, + .ack = tsi108_pci_irq_ack, + .end = tsi108_pci_irq_end, + .unmask = tsi108_pci_irq_enable, +}; + +/* + * Exported functions + */ + +/* + * The Tsi108 PCI interrupts initialization routine. + * + * The INTA# - INTD# interrupts on the PCI bus are reported by the PCI block + * to the MPIC using single interrupt source (IRQ_TSI108_PCI). Therefore the + * PCI block has to be treated as a cascaded interrupt controller connected + * to the MPIC. + */ + +void __init tsi108_pci_int_init(void) +{ + u_int i; + + DBG("Tsi108_pci_int_init: initializing PCI interrupts\n"); + + for (i = 0; i < NUM_PCI_IRQS; i++) { + irq_desc[i + IRQ_PCI_INTAD_BASE].chip = &tsi108_pci_irq; + irq_desc[i + IRQ_PCI_INTAD_BASE].status |= IRQ_LEVEL; + } + + init_pci_source(); +} + +void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc, + struct pt_regs *regs) +{ + unsigned int cascade_irq = get_pci_source(); + if (cascade_irq != NO_IRQ) + generic_handle_irq(cascade_irq, regs); + desc->chip->eoi(irq); +} diff --git a/arch/s390/hypfs/Makefile b/arch/s390/hypfs/Makefile new file mode 100644 index 000000000..f4b00cd81 --- /dev/null +++ b/arch/s390/hypfs/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the linux hypfs filesystem routines. +# + +obj-$(CONFIG_S390_HYPFS_FS) += s390_hypfs.o + +s390_hypfs-objs := inode.o hypfs_diag.o diff --git a/arch/s390/hypfs/hypfs.h b/arch/s390/hypfs/hypfs.h new file mode 100644 index 000000000..ea5567be0 --- /dev/null +++ b/arch/s390/hypfs/hypfs.h @@ -0,0 +1,30 @@ +/* + * fs/hypfs/hypfs.h + * Hypervisor filesystem for Linux on s390. + * + * Copyright (C) IBM Corp. 2006 + * Author(s): Michael Holzheu <holzheu@de.ibm.com> + */ + +#ifndef _HYPFS_H_ +#define _HYPFS_H_ + +#include <linux/fs.h> +#include <linux/types.h> + +#define REG_FILE_MODE 0440 +#define UPDATE_FILE_MODE 0220 +#define DIR_MODE 0550 + +extern struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent, + const char *name); + +extern struct dentry *hypfs_create_u64(struct super_block *sb, + struct dentry *dir, const char *name, + __u64 value); + +extern struct dentry *hypfs_create_str(struct super_block *sb, + struct dentry *dir, const char *name, + char *string); + +#endif /* _HYPFS_H_ */ diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c new file mode 100644 index 000000000..1785bce2b --- /dev/null +++ b/arch/s390/hypfs/hypfs_diag.c @@ -0,0 +1,696 @@ +/* + * fs/hypfs/hypfs_diag.c + * Hypervisor filesystem for Linux on s390. Diag 204 and 224 + * implementation. + * + * Copyright (C) IBM Corp. 2006 + * Author(s): Michael Holzheu <holzheu@de.ibm.com> + */ + +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/vmalloc.h> +#include <asm/ebcdic.h> +#include "hypfs.h" + +#define LPAR_NAME_LEN 8 /* lpar name len in diag 204 data */ +#define CPU_NAME_LEN 16 /* type name len of cpus in diag224 name table */ +#define TMP_SIZE 64 /* size of temporary buffers */ + +/* diag 204 subcodes */ +enum diag204_sc { + SUBC_STIB4 = 4, + SUBC_RSI = 5, + SUBC_STIB6 = 6, + SUBC_STIB7 = 7 +}; + +/* The two available diag 204 data formats */ +enum diag204_format { + INFO_SIMPLE = 0, + INFO_EXT = 0x00010000 +}; + +/* bit is set in flags, when physical cpu info is included in diag 204 data */ +#define LPAR_PHYS_FLG 0x80 + +static char *diag224_cpu_names; /* diag 224 name table */ +static enum diag204_sc diag204_store_sc; /* used subcode for store */ +static enum diag204_format diag204_info_type; /* used diag 204 data format */ + +static void *diag204_buf; /* 4K aligned buffer for diag204 data */ +static void *diag204_buf_vmalloc; /* vmalloc pointer for diag204 data */ +static int diag204_buf_pages; /* number of pages for diag204 data */ + +/* + * DIAG 204 data structures and member access functions. + * + * Since we have two different diag 204 data formats for old and new s390 + * machines, we do not access the structs directly, but use getter functions for + * each struct member instead. This should make the code more readable. + */ + +/* Time information block */ + +struct info_blk_hdr { + __u8 npar; + __u8 flags; + __u16 tslice; + __u16 phys_cpus; + __u16 this_part; + __u64 curtod; +} __attribute__ ((packed)); + +struct x_info_blk_hdr { + __u8 npar; + __u8 flags; + __u16 tslice; + __u16 phys_cpus; + __u16 this_part; + __u64 curtod1; + __u64 curtod2; + char reserved[40]; +} __attribute__ ((packed)); + +static inline int info_blk_hdr__size(enum diag204_format type) +{ + if (type == INFO_SIMPLE) + return sizeof(struct info_blk_hdr); + else /* INFO_EXT */ + return sizeof(struct x_info_blk_hdr); +} + +static inline __u8 info_blk_hdr__npar(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct info_blk_hdr *)hdr)->npar; + else /* INFO_EXT */ + return ((struct x_info_blk_hdr *)hdr)->npar; +} + +static inline __u8 info_blk_hdr__flags(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct info_blk_hdr *)hdr)->flags; + else /* INFO_EXT */ + return ((struct x_info_blk_hdr *)hdr)->flags; +} + +static inline __u16 info_blk_hdr__pcpus(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct info_blk_hdr *)hdr)->phys_cpus; + else /* INFO_EXT */ + return ((struct x_info_blk_hdr *)hdr)->phys_cpus; +} + +/* Partition header */ + +struct part_hdr { + __u8 pn; + __u8 cpus; + char reserved[6]; + char part_name[LPAR_NAME_LEN]; +} __attribute__ ((packed)); + +struct x_part_hdr { + __u8 pn; + __u8 cpus; + __u8 rcpus; + __u8 pflag; + __u32 mlu; + char part_name[LPAR_NAME_LEN]; + char lpc_name[8]; + char os_name[8]; + __u64 online_cs; + __u64 online_es; + __u8 upid; + char reserved1[3]; + __u32 group_mlu; + char group_name[8]; + char reserved2[32]; +} __attribute__ ((packed)); + +static inline int part_hdr__size(enum diag204_format type) +{ + if (type == INFO_SIMPLE) + return sizeof(struct part_hdr); + else /* INFO_EXT */ + return sizeof(struct x_part_hdr); +} + +static inline __u8 part_hdr__rcpus(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct part_hdr *)hdr)->cpus; + else /* INFO_EXT */ + return ((struct x_part_hdr *)hdr)->rcpus; +} + +static inline void part_hdr__part_name(enum diag204_format type, void *hdr, + char *name) +{ + if (type == INFO_SIMPLE) + memcpy(name, ((struct part_hdr *)hdr)->part_name, + LPAR_NAME_LEN); + else /* INFO_EXT */ + memcpy(name, ((struct x_part_hdr *)hdr)->part_name, + LPAR_NAME_LEN); + EBCASC(name, LPAR_NAME_LEN); + name[LPAR_NAME_LEN] = 0; + strstrip(name); +} + +struct cpu_info { + __u16 cpu_addr; + char reserved1[2]; + __u8 ctidx; + __u8 cflag; + __u16 weight; + __u64 acc_time; + __u64 lp_time; +} __attribute__ ((packed)); + +struct x_cpu_info { + __u16 cpu_addr; + char reserved1[2]; + __u8 ctidx; + __u8 cflag; + __u16 weight; + __u64 acc_time; + __u64 lp_time; + __u16 min_weight; + __u16 cur_weight; + __u16 max_weight; + char reseved2[2]; + __u64 online_time; + __u64 wait_time; + __u32 pma_weight; + __u32 polar_weight; + char reserved3[40]; +} __attribute__ ((packed)); + +/* CPU info block */ + +static inline int cpu_info__size(enum diag204_format type) +{ + if (type == INFO_SIMPLE) + return sizeof(struct cpu_info); + else /* INFO_EXT */ + return sizeof(struct x_cpu_info); +} + +static inline __u8 cpu_info__ctidx(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct cpu_info *)hdr)->ctidx; + else /* INFO_EXT */ + return ((struct x_cpu_info *)hdr)->ctidx; +} + +static inline __u16 cpu_info__cpu_addr(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct cpu_info *)hdr)->cpu_addr; + else /* INFO_EXT */ + return ((struct x_cpu_info *)hdr)->cpu_addr; +} + +static inline __u64 cpu_info__acc_time(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct cpu_info *)hdr)->acc_time; + else /* INFO_EXT */ + return ((struct x_cpu_info *)hdr)->acc_time; +} + +static inline __u64 cpu_info__lp_time(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct cpu_info *)hdr)->lp_time; + else /* INFO_EXT */ + return ((struct x_cpu_info *)hdr)->lp_time; +} + +static inline __u64 cpu_info__online_time(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return 0; /* online_time not available in simple info */ + else /* INFO_EXT */ + return ((struct x_cpu_info *)hdr)->online_time; +} + +/* Physical header */ + +struct phys_hdr { + char reserved1[1]; + __u8 cpus; + char reserved2[6]; + char mgm_name[8]; +} __attribute__ ((packed)); + +struct x_phys_hdr { + char reserved1[1]; + __u8 cpus; + char reserved2[6]; + char mgm_name[8]; + char reserved3[80]; +} __attribute__ ((packed)); + +static inline int phys_hdr__size(enum diag204_format type) +{ + if (type == INFO_SIMPLE) + return sizeof(struct phys_hdr); + else /* INFO_EXT */ + return sizeof(struct x_phys_hdr); +} + +static inline __u8 phys_hdr__cpus(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct phys_hdr *)hdr)->cpus; + else /* INFO_EXT */ + return ((struct x_phys_hdr *)hdr)->cpus; +} + +/* Physical CPU info block */ + +struct phys_cpu { + __u16 cpu_addr; + char reserved1[2]; + __u8 ctidx; + char reserved2[3]; + __u64 mgm_time; + char reserved3[8]; +} __attribute__ ((packed)); + +struct x_phys_cpu { + __u16 cpu_addr; + char reserved1[2]; + __u8 ctidx; + char reserved2[3]; + __u64 mgm_time; + char reserved3[80]; +} __attribute__ ((packed)); + +static inline int phys_cpu__size(enum diag204_format type) +{ + if (type == INFO_SIMPLE) + return sizeof(struct phys_cpu); + else /* INFO_EXT */ + return sizeof(struct x_phys_cpu); +} + +static inline __u16 phys_cpu__cpu_addr(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct phys_cpu *)hdr)->cpu_addr; + else /* INFO_EXT */ + return ((struct x_phys_cpu *)hdr)->cpu_addr; +} + +static inline __u64 phys_cpu__mgm_time(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct phys_cpu *)hdr)->mgm_time; + else /* INFO_EXT */ + return ((struct x_phys_cpu *)hdr)->mgm_time; +} + +static inline __u64 phys_cpu__ctidx(enum diag204_format type, void *hdr) +{ + if (type == INFO_SIMPLE) + return ((struct phys_cpu *)hdr)->ctidx; + else /* INFO_EXT */ + return ((struct x_phys_cpu *)hdr)->ctidx; +} + +/* Diagnose 204 functions */ + +static int diag204(unsigned long subcode, unsigned long size, void *addr) +{ + register unsigned long _subcode asm("0") = subcode; + register unsigned long _size asm("1") = size; + + asm volatile (" diag %2,%0,0x204\n" + "0: \n" ".section __ex_table,\"a\"\n" +#ifndef __s390x__ + " .align 4\n" + " .long 0b,0b\n" +#else + " .align 8\n" + " .quad 0b,0b\n" +#endif + ".previous":"+d" (_subcode), "+d"(_size) + :"d"(addr) + :"memory"); + if (_subcode) + return -1; + else + return _size; +} + +/* + * For the old diag subcode 4 with simple data format we have to use real + * memory. If we use subcode 6 or 7 with extended data format, we can (and + * should) use vmalloc, since we need a lot of memory in that case. Currently + * up to 93 pages! + */ + +static void diag204_free_buffer(void) +{ + if (!diag204_buf) + return; + if (diag204_buf_vmalloc) { + vfree(diag204_buf_vmalloc); + diag204_buf_vmalloc = NULL; + } else { + free_pages((unsigned long) diag204_buf, 0); + } + diag204_buf_pages = 0; + diag204_buf = NULL; +} + +static void *diag204_alloc_vbuf(int pages) +{ + /* The buffer has to be page aligned! */ + diag204_buf_vmalloc = vmalloc(PAGE_SIZE * (pages + 1)); + if (!diag204_buf_vmalloc) + return ERR_PTR(-ENOMEM); + diag204_buf = (void*)((unsigned long)diag204_buf_vmalloc + & ~0xfffUL) + 0x1000; + diag204_buf_pages = pages; + return diag204_buf; +} + +static void *diag204_alloc_rbuf(void) +{ + diag204_buf = (void*)__get_free_pages(GFP_KERNEL,0); + if (diag204_buf) + return ERR_PTR(-ENOMEM); + diag204_buf_pages = 1; + return diag204_buf; +} + +static void *diag204_get_buffer(enum diag204_format fmt, int *pages) +{ + if (diag204_buf) { + *pages = diag204_buf_pages; + return diag204_buf; + } + if (fmt == INFO_SIMPLE) { + *pages = 1; + return diag204_alloc_rbuf(); + } else {/* INFO_EXT */ + *pages = diag204(SUBC_RSI | INFO_EXT, 0, NULL); + if (*pages <= 0) + return ERR_PTR(-ENOSYS); + else + return diag204_alloc_vbuf(*pages); + } +} + +/* + * diag204_probe() has to find out, which type of diagnose 204 implementation + * we have on our machine. Currently there are three possible scanarios: + * - subcode 4 + simple data format (only one page) + * - subcode 4-6 + extended data format + * - subcode 4-7 + extended data format + * + * Subcode 5 is used to retrieve the size of the data, provided by subcodes + * 6 and 7. Subcode 7 basically has the same function as subcode 6. In addition + * to subcode 6 it provides also information about secondary cpus. + * In order to get as much information as possible, we first try + * subcode 7, then 6 and if both fail, we use subcode 4. + */ + +static int diag204_probe(void) +{ + void *buf; + int pages, rc; + + buf = diag204_get_buffer(INFO_EXT, &pages); + if (!IS_ERR(buf)) { + if (diag204(SUBC_STIB7 | INFO_EXT, pages, buf) >= 0) { + diag204_store_sc = SUBC_STIB7; + diag204_info_type = INFO_EXT; + goto out; + } + if (diag204(SUBC_STIB6 | INFO_EXT, pages, buf) >= 0) { + diag204_store_sc = SUBC_STIB7; + diag204_info_type = INFO_EXT; + goto out; + } + diag204_free_buffer(); + } + + /* subcodes 6 and 7 failed, now try subcode 4 */ + + buf = diag204_get_buffer(INFO_SIMPLE, &pages); + if (IS_ERR(buf)) { + rc = PTR_ERR(buf); + goto fail_alloc; + } + if (diag204(SUBC_STIB4 | INFO_SIMPLE, pages, buf) >= 0) { + diag204_store_sc = SUBC_STIB4; + diag204_info_type = INFO_SIMPLE; + goto out; + } else { + rc = -ENOSYS; + goto fail_store; + } +out: + rc = 0; +fail_store: + diag204_free_buffer(); +fail_alloc: + return rc; +} + +static void *diag204_store(void) +{ + void *buf; + int pages; + + buf = diag204_get_buffer(diag204_info_type, &pages); + if (IS_ERR(buf)) + goto out; + if (diag204(diag204_store_sc | diag204_info_type, pages, buf) < 0) + return ERR_PTR(-ENOSYS); +out: + return buf; +} + +/* Diagnose 224 functions */ + +static void diag224(void *ptr) +{ + asm volatile(" diag %0,%1,0x224\n" + : :"d" (0), "d"(ptr) : "memory"); +} + +static int diag224_get_name_table(void) +{ + /* memory must be below 2GB */ + diag224_cpu_names = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA); + if (!diag224_cpu_names) + return -ENOMEM; + diag224(diag224_cpu_names); + EBCASC(diag224_cpu_names + 16, (*diag224_cpu_names + 1) * 16); + return 0; +} + +static void diag224_delete_name_table(void) +{ + kfree(diag224_cpu_names); +} + +static int diag224_idx2name(int index, char *name) +{ + memcpy(name, diag224_cpu_names + ((index + 1) * CPU_NAME_LEN), + CPU_NAME_LEN); + name[CPU_NAME_LEN] = 0; + strstrip(name); + return 0; +} + +__init int hypfs_diag_init(void) +{ + int rc; + + if (diag204_probe()) { + printk(KERN_ERR "hypfs: diag 204 not working."); + return -ENODATA; + } + rc = diag224_get_name_table(); + if (rc) { + diag224_delete_name_table(); + printk(KERN_ERR "hypfs: could not get name table.\n"); + } + return rc; +} + +__exit void hypfs_diag_exit(void) +{ + diag224_delete_name_table(); + diag204_free_buffer(); +} + +/* + * Functions to create the directory structure + * ******************************************* + */ + +static int hypfs_create_cpu_files(struct super_block *sb, + struct dentry *cpus_dir, void *cpu_info) +{ + struct dentry *cpu_dir; + char buffer[TMP_SIZE]; + void *rc; + + snprintf(buffer, TMP_SIZE, "%d", cpu_info__cpu_addr(diag204_info_type, + cpu_info)); + cpu_dir = hypfs_mkdir(sb, cpus_dir, buffer); + rc = hypfs_create_u64(sb, cpu_dir, "mgmtime", + cpu_info__acc_time(diag204_info_type, cpu_info) - + cpu_info__lp_time(diag204_info_type, cpu_info)); + if (IS_ERR(rc)) + return PTR_ERR(rc); + rc = hypfs_create_u64(sb, cpu_dir, "cputime", + cpu_info__lp_time(diag204_info_type, cpu_info)); + if (IS_ERR(rc)) + return PTR_ERR(rc); + if (diag204_info_type == INFO_EXT) { + rc = hypfs_create_u64(sb, cpu_dir, "onlinetime", + cpu_info__online_time(diag204_info_type, + cpu_info)); + if (IS_ERR(rc)) + return PTR_ERR(rc); + } + diag224_idx2name(cpu_info__ctidx(diag204_info_type, cpu_info), buffer); + rc = hypfs_create_str(sb, cpu_dir, "type", buffer); + if (IS_ERR(rc)) + return PTR_ERR(rc); + return 0; +} + +static void *hypfs_create_lpar_files(struct super_block *sb, + struct dentry *systems_dir, void *part_hdr) +{ + struct dentry *cpus_dir; + struct dentry *lpar_dir; + char lpar_name[LPAR_NAME_LEN + 1]; + void *cpu_info; + int i; + + part_hdr__part_name(diag204_info_type, part_hdr, lpar_name); + lpar_name[LPAR_NAME_LEN] = 0; + lpar_dir = hypfs_mkdir(sb, systems_dir, lpar_name); + if (IS_ERR(lpar_dir)) + return lpar_dir; + cpus_dir = hypfs_mkdir(sb, lpar_dir, "cpus"); + if (IS_ERR(cpus_dir)) + return cpus_dir; + cpu_info = part_hdr + part_hdr__size(diag204_info_type); + for (i = 0; i < part_hdr__rcpus(diag204_info_type, part_hdr); i++) { + int rc; + rc = hypfs_create_cpu_files(sb, cpus_dir, cpu_info); + if (rc) + return ERR_PTR(rc); + cpu_info += cpu_info__size(diag204_info_type); + } + return cpu_info; +} + +static int hypfs_create_phys_cpu_files(struct super_block *sb, + struct dentry *cpus_dir, void *cpu_info) +{ + struct dentry *cpu_dir; + char buffer[TMP_SIZE]; + void *rc; + + snprintf(buffer, TMP_SIZE, "%i", phys_cpu__cpu_addr(diag204_info_type, + cpu_info)); + cpu_dir = hypfs_mkdir(sb, cpus_dir, buffer); + if (IS_ERR(cpu_dir)) + return PTR_ERR(cpu_dir); + rc = hypfs_create_u64(sb, cpu_dir, "mgmtime", + phys_cpu__mgm_time(diag204_info_type, cpu_info)); + if (IS_ERR(rc)) + return PTR_ERR(rc); + diag224_idx2name(phys_cpu__ctidx(diag204_info_type, cpu_info), buffer); + rc = hypfs_create_str(sb, cpu_dir, "type", buffer); + if (IS_ERR(rc)) + return PTR_ERR(rc); + return 0; +} + +static void *hypfs_create_phys_files(struct super_block *sb, + struct dentry *parent_dir, void *phys_hdr) +{ + int i; + void *cpu_info; + struct dentry *cpus_dir; + + cpus_dir = hypfs_mkdir(sb, parent_dir, "cpus"); + if (IS_ERR(cpus_dir)) + return cpus_dir; + cpu_info = phys_hdr + phys_hdr__size(diag204_info_type); + for (i = 0; i < phys_hdr__cpus(diag204_info_type, phys_hdr); i++) { + int rc; + rc = hypfs_create_phys_cpu_files(sb, cpus_dir, cpu_info); + if (rc) + return ERR_PTR(rc); + cpu_info += phys_cpu__size(diag204_info_type); + } + return cpu_info; +} + +int hypfs_diag_create_files(struct super_block *sb, struct dentry *root) +{ + struct dentry *systems_dir, *hyp_dir; + void *time_hdr, *part_hdr; + int i, rc; + void *buffer, *ptr; + + buffer = diag204_store(); + if (IS_ERR(buffer)) + return PTR_ERR(buffer); + + systems_dir = hypfs_mkdir(sb, root, "systems"); + if (IS_ERR(systems_dir)) { + rc = PTR_ERR(systems_dir); + goto err_out; + } + time_hdr = (struct x_info_blk_hdr *)buffer; + part_hdr = time_hdr + info_blk_hdr__size(diag204_info_type); + for (i = 0; i < info_blk_hdr__npar(diag204_info_type, time_hdr); i++) { + part_hdr = hypfs_create_lpar_files(sb, systems_dir, part_hdr); + if (IS_ERR(part_hdr)) { + rc = PTR_ERR(part_hdr); + goto err_out; + } + } + if (info_blk_hdr__flags(diag204_info_type, time_hdr) & LPAR_PHYS_FLG) { + ptr = hypfs_create_phys_files(sb, root, part_hdr); + if (IS_ERR(ptr)) { + rc = PTR_ERR(ptr); + goto err_out; + } + } + hyp_dir = hypfs_mkdir(sb, root, "hyp"); + if (IS_ERR(hyp_dir)) { + rc = PTR_ERR(hyp_dir); + goto err_out; + } + ptr = hypfs_create_str(sb, hyp_dir, "type", "LPAR Hypervisor"); + if (IS_ERR(ptr)) { + rc = PTR_ERR(ptr); + goto err_out; + } + rc = 0; + +err_out: + return rc; +} diff --git a/arch/s390/hypfs/hypfs_diag.h b/arch/s390/hypfs/hypfs_diag.h new file mode 100644 index 000000000..793dea6b9 --- /dev/null +++ b/arch/s390/hypfs/hypfs_diag.h @@ -0,0 +1,16 @@ +/* + * fs/hypfs/hypfs_diag.h + * Hypervisor filesystem for Linux on s390. + * + * Copyright (C) IBM Corp. 2006 + * Author(s): Michael Holzheu <holzheu@de.ibm.com> + */ + +#ifndef _HYPFS_DIAG_H_ +#define _HYPFS_DIAG_H_ + +extern int hypfs_diag_init(void); +extern void hypfs_diag_exit(void); +extern int hypfs_diag_create_files(struct super_block *sb, struct dentry *root); + +#endif /* _HYPFS_DIAG_H_ */ diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c new file mode 100644 index 000000000..666b946f3 --- /dev/null +++ b/arch/s390/hypfs/inode.c @@ -0,0 +1,490 @@ +/* + * fs/hypfs/inode.c + * Hypervisor filesystem for Linux on s390. + * + * Copyright (C) IBM Corp. 2006 + * Author(s): Michael Holzheu <holzheu@de.ibm.com> + */ + +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/namei.h> +#include <linux/vfs.h> +#include <linux/pagemap.h> +#include <linux/gfp.h> +#include <linux/time.h> +#include <linux/parser.h> +#include <linux/sysfs.h> +#include <linux/module.h> +#include <asm/ebcdic.h> +#include "hypfs.h" +#include "hypfs_diag.h" + +#define HYPFS_MAGIC 0x687970 /* ASCII 'hyp' */ +#define TMP_SIZE 64 /* size of temporary buffers */ + +static struct dentry *hypfs_create_update_file(struct super_block *sb, + struct dentry *dir); + +struct hypfs_sb_info { + uid_t uid; /* uid used for files and dirs */ + gid_t gid; /* gid used for files and dirs */ + struct dentry *update_file; /* file to trigger update */ + time_t last_update; /* last update time in secs since 1970 */ + struct mutex lock; /* lock to protect update process */ +}; + +static struct file_operations hypfs_file_ops; +static struct file_system_type hypfs_type; +static struct super_operations hypfs_s_ops; + +/* start of list of all dentries, which have to be deleted on update */ +static struct dentry *hypfs_last_dentry; + +static void hypfs_update_update(struct super_block *sb) +{ + struct hypfs_sb_info *sb_info = sb->s_fs_info; + struct inode *inode = sb_info->update_file->d_inode; + + sb_info->last_update = get_seconds(); + inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; +} + +/* directory tree removal functions */ + +static void hypfs_add_dentry(struct dentry *dentry) +{ + dentry->d_fsdata = hypfs_last_dentry; + hypfs_last_dentry = dentry; +} + +static void hypfs_remove(struct dentry *dentry) +{ + struct dentry *parent; + + parent = dentry->d_parent; + if (S_ISDIR(dentry->d_inode->i_mode)) + simple_rmdir(parent->d_inode, dentry); + else + simple_unlink(parent->d_inode, dentry); + d_delete(dentry); + dput(dentry); +} + +static void hypfs_delete_tree(struct dentry *root) +{ + while (hypfs_last_dentry) { + struct dentry *next_dentry; + next_dentry = hypfs_last_dentry->d_fsdata; + hypfs_remove(hypfs_last_dentry); + hypfs_last_dentry = next_dentry; + } +} + +static struct inode *hypfs_make_inode(struct super_block *sb, int mode) +{ + struct inode *ret = new_inode(sb); + + if (ret) { + struct hypfs_sb_info *hypfs_info = sb->s_fs_info; + ret->i_mode = mode; + ret->i_uid = hypfs_info->uid; + ret->i_gid = hypfs_info->gid; + ret->i_blocks = 0; + ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME; + if (mode & S_IFDIR) + ret->i_nlink = 2; + else + ret->i_nlink = 1; + } + return ret; +} + +static void hypfs_drop_inode(struct inode *inode) +{ + kfree(inode->i_private); + generic_delete_inode(inode); +} + +static int hypfs_open(struct inode *inode, struct file *filp) +{ + char *data = filp->f_dentry->d_inode->i_private; + struct hypfs_sb_info *fs_info; + + if (filp->f_mode & FMODE_WRITE) { + if (!(inode->i_mode & S_IWUGO)) + return -EACCES; + } + if (filp->f_mode & FMODE_READ) { + if (!(inode->i_mode & S_IRUGO)) + return -EACCES; + } + + fs_info = inode->i_sb->s_fs_info; + if(data) { + mutex_lock(&fs_info->lock); + filp->private_data = kstrdup(data, GFP_KERNEL); + if (!filp->private_data) { + mutex_unlock(&fs_info->lock); + return -ENOMEM; + } + mutex_unlock(&fs_info->lock); + } + return 0; +} + +static ssize_t hypfs_aio_read(struct kiocb *iocb, __user char *buf, + size_t count, loff_t offset) +{ + char *data; + size_t len; + struct file *filp = iocb->ki_filp; + + data = filp->private_data; + len = strlen(data); + if (offset > len) { + count = 0; + goto out; + } + if (count > len - offset) + count = len - offset; + if (copy_to_user(buf, data + offset, count)) { + count = -EFAULT; + goto out; + } + iocb->ki_pos += count; + file_accessed(filp); +out: + return count; +} +static ssize_t hypfs_aio_write(struct kiocb *iocb, const char __user *buf, + size_t count, loff_t pos) +{ + int rc; + struct super_block *sb; + struct hypfs_sb_info *fs_info; + + sb = iocb->ki_filp->f_dentry->d_inode->i_sb; + fs_info = sb->s_fs_info; + /* + * Currently we only allow one update per second for two reasons: + * 1. diag 204 is VERY expensive + * 2. If several processes do updates in parallel and then read the + * hypfs data, the likelihood of collisions is reduced, if we restrict + * the minimum update interval. A collision occurs, if during the + * data gathering of one process another process triggers an update + * If the first process wants to ensure consistent data, it has + * to restart data collection in this case. + */ + mutex_lock(&fs_info->lock); + if (fs_info->last_update == get_seconds()) { + rc = -EBUSY; + goto out; + } + hypfs_delete_tree(sb->s_root); + rc = hypfs_diag_create_files(sb, sb->s_root); + if (rc) { + printk(KERN_ERR "hypfs: Update failed\n"); + hypfs_delete_tree(sb->s_root); + goto out; + } + hypfs_update_update(sb); + rc = count; +out: + mutex_unlock(&fs_info->lock); + return rc; +} + +static int hypfs_release(struct inode *inode, struct file *filp) +{ + kfree(filp->private_data); + return 0; +} + +enum { opt_uid, opt_gid, opt_err }; + +static match_table_t hypfs_tokens = { + {opt_uid, "uid=%u"}, + {opt_gid, "gid=%u"}, + {opt_err, NULL} +}; + +static int hypfs_parse_options(char *options, struct super_block *sb) +{ + char *str; + substring_t args[MAX_OPT_ARGS]; + + if (!options) + return 0; + while ((str = strsep(&options, ",")) != NULL) { + int token, option; + struct hypfs_sb_info *hypfs_info = sb->s_fs_info; + + if (!*str) + continue; + token = match_token(str, hypfs_tokens, args); + switch (token) { + case opt_uid: + if (match_int(&args[0], &option)) + return -EINVAL; + hypfs_info->uid = option; + break; + case opt_gid: + if (match_int(&args[0], &option)) + return -EINVAL; + hypfs_info->gid = option; + break; + case opt_err: + default: + printk(KERN_ERR "hypfs: Unrecognized mount option " + "\"%s\" or missing value\n", str); + return -EINVAL; + } + } + return 0; +} + +static int hypfs_fill_super(struct super_block *sb, void *data, int silent) +{ + struct inode *root_inode; + struct dentry *root_dentry; + int rc = 0; + struct hypfs_sb_info *sbi; + + sbi = kzalloc(sizeof(struct hypfs_sb_info), GFP_KERNEL); + if (!sbi) + return -ENOMEM; + mutex_init(&sbi->lock); + sbi->uid = current->uid; + sbi->gid = current->gid; + sb->s_fs_info = sbi; + sb->s_blocksize = PAGE_CACHE_SIZE; + sb->s_blocksize_bits = PAGE_CACHE_SHIFT; + sb->s_magic = HYPFS_MAGIC; + sb->s_op = &hypfs_s_ops; + if (hypfs_parse_options(data, sb)) { + rc = -EINVAL; + goto err_alloc; + } + root_inode = hypfs_make_inode(sb, S_IFDIR | 0755); + if (!root_inode) { + rc = -ENOMEM; + goto err_alloc; + } + root_inode->i_op = &simple_dir_inode_operations; + root_inode->i_fop = &simple_dir_operations; + root_dentry = d_alloc_root(root_inode); + if (!root_dentry) { + iput(root_inode); + rc = -ENOMEM; + goto err_alloc; + } + rc = hypfs_diag_create_files(sb, root_dentry); + if (rc) + goto err_tree; + sbi->update_file = hypfs_create_update_file(sb, root_dentry); + if (IS_ERR(sbi->update_file)) { + rc = PTR_ERR(sbi->update_file); + goto err_tree; + } + hypfs_update_update(sb); + sb->s_root = root_dentry; + return 0; + +err_tree: + hypfs_delete_tree(root_dentry); + d_genocide(root_dentry); + dput(root_dentry); +err_alloc: + kfree(sbi); + return rc; +} + +static int hypfs_get_super(struct file_system_type *fst, int flags, + const char *devname, void *data, struct vfsmount *mnt) +{ + return get_sb_single(fst, flags, data, hypfs_fill_super, mnt); +} + +static void hypfs_kill_super(struct super_block *sb) +{ + struct hypfs_sb_info *sb_info = sb->s_fs_info; + + hypfs_delete_tree(sb->s_root); + hypfs_remove(sb_info->update_file); + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; + kill_litter_super(sb); +} + +static struct dentry *hypfs_create_file(struct super_block *sb, + struct dentry *parent, const char *name, + char *data, mode_t mode) +{ + struct dentry *dentry; + struct inode *inode; + struct qstr qname; + + qname.name = name; + qname.len = strlen(name); + qname.hash = full_name_hash(name, qname.len); + dentry = lookup_one_len(name, parent, strlen(name)); + if (IS_ERR(dentry)) + return ERR_PTR(-ENOMEM); + inode = hypfs_make_inode(sb, mode); + if (!inode) { + dput(dentry); + return ERR_PTR(-ENOMEM); + } + if (mode & S_IFREG) { + inode->i_fop = &hypfs_file_ops; + if (data) + inode->i_size = strlen(data); + else + inode->i_size = 0; + } else if (mode & S_IFDIR) { + inode->i_op = &simple_dir_inode_operations; + inode->i_fop = &simple_dir_operations; + parent->d_inode->i_nlink++; + } else + BUG(); + inode->i_private = data; + d_instantiate(dentry, inode); + dget(dentry); + return dentry; +} + +struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent, + const char *name) +{ + struct dentry *dentry; + + dentry = hypfs_create_file(sb, parent, name, NULL, S_IFDIR | DIR_MODE); + if (IS_ERR(dentry)) + return dentry; + hypfs_add_dentry(dentry); + parent->d_inode->i_nlink++; + return dentry; +} + +static struct dentry *hypfs_create_update_file(struct super_block *sb, + struct dentry *dir) +{ + struct dentry *dentry; + + dentry = hypfs_create_file(sb, dir, "update", NULL, + S_IFREG | UPDATE_FILE_MODE); + /* + * We do not put the update file on the 'delete' list with + * hypfs_add_dentry(), since it should not be removed when the tree + * is updated. + */ + return dentry; +} + +struct dentry *hypfs_create_u64(struct super_block *sb, struct dentry *dir, + const char *name, __u64 value) +{ + char *buffer; + char tmp[TMP_SIZE]; + struct dentry *dentry; + + snprintf(tmp, TMP_SIZE, "%lld\n", (unsigned long long int)value); + buffer = kstrdup(tmp, GFP_KERNEL); + if (!buffer) + return ERR_PTR(-ENOMEM); + dentry = + hypfs_create_file(sb, dir, name, buffer, S_IFREG | REG_FILE_MODE); + if (IS_ERR(dentry)) { + kfree(buffer); + return ERR_PTR(-ENOMEM); + } + hypfs_add_dentry(dentry); + return dentry; +} + +struct dentry *hypfs_create_str(struct super_block *sb, struct dentry *dir, + const char *name, char *string) +{ + char *buffer; + struct dentry *dentry; + + buffer = kmalloc(strlen(string) + 2, GFP_KERNEL); + if (!buffer) + return ERR_PTR(-ENOMEM); + sprintf(buffer, "%s\n", string); + dentry = + hypfs_create_file(sb, dir, name, buffer, S_IFREG | REG_FILE_MODE); + if (IS_ERR(dentry)) { + kfree(buffer); + return ERR_PTR(-ENOMEM); + } + hypfs_add_dentry(dentry); + return dentry; +} + +static struct file_operations hypfs_file_ops = { + .open = hypfs_open, + .release = hypfs_release, + .read = do_sync_read, + .write = do_sync_write, + .aio_read = hypfs_aio_read, + .aio_write = hypfs_aio_write, +}; + +static struct file_system_type hypfs_type = { + .owner = THIS_MODULE, + .name = "s390_hypfs", + .get_sb = hypfs_get_super, + .kill_sb = hypfs_kill_super +}; + +static struct super_operations hypfs_s_ops = { + .statfs = simple_statfs, + .drop_inode = hypfs_drop_inode, +}; + +static decl_subsys(s390, NULL, NULL); + +static int __init hypfs_init(void) +{ + int rc; + + if (MACHINE_IS_VM) + return -ENODATA; + if (hypfs_diag_init()) { + rc = -ENODATA; + goto fail_diag; + } + kset_set_kset_s(&s390_subsys, hypervisor_subsys); + rc = subsystem_register(&s390_subsys); + if (rc) + goto fail_sysfs; + rc = register_filesystem(&hypfs_type); + if (rc) + goto fail_filesystem; + return 0; + +fail_filesystem: + subsystem_unregister(&s390_subsys); +fail_sysfs: + hypfs_diag_exit(); +fail_diag: + printk(KERN_ERR "hypfs: Initialization failed with rc = %i.\n", rc); + return rc; +} + +static void __exit hypfs_exit(void) +{ + hypfs_diag_exit(); + unregister_filesystem(&hypfs_type); + subsystem_unregister(&s390_subsys); +} + +module_init(hypfs_init) +module_exit(hypfs_exit) + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Michael Holzheu <holzheu@de.ibm.com>"); +MODULE_DESCRIPTION("s390 Hypervisor Filesystem"); diff --git a/arch/s390/kernel/audit.c b/arch/s390/kernel/audit.c new file mode 100644 index 000000000..0741d9193 --- /dev/null +++ b/arch/s390/kernel/audit.c @@ -0,0 +1,66 @@ +#include <linux/init.h> +#include <linux/types.h> +#include <linux/audit.h> +#include <asm/unistd.h> + +static unsigned dir_class[] = { +#include <asm-generic/audit_dir_write.h> +~0U +}; + +static unsigned read_class[] = { +#include <asm-generic/audit_read.h> +~0U +}; + +static unsigned write_class[] = { +#include <asm-generic/audit_write.h> +~0U +}; + +static unsigned chattr_class[] = { +#include <asm-generic/audit_change_attr.h> +~0U +}; + +int audit_classify_syscall(int abi, unsigned syscall) +{ +#ifdef CONFIG_COMPAT + extern int s390_classify_syscall(unsigned); + if (abi == AUDIT_ARCH_S390) + return s390_classify_syscall(syscall); +#endif + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_socketcall: + return 4; + case __NR_execve: + return 5; + default: + return 0; + } +} + +static int __init audit_classes_init(void) +{ +#ifdef CONFIG_COMPAT + extern __u32 s390_dir_class[]; + extern __u32 s390_write_class[]; + extern __u32 s390_read_class[]; + extern __u32 s390_chattr_class[]; + audit_register_class(AUDIT_CLASS_WRITE_32, s390_write_class); + audit_register_class(AUDIT_CLASS_READ_32, s390_read_class); + audit_register_class(AUDIT_CLASS_DIR_WRITE_32, s390_dir_class); + audit_register_class(AUDIT_CLASS_CHATTR_32, s390_chattr_class); +#endif + audit_register_class(AUDIT_CLASS_WRITE, write_class); + audit_register_class(AUDIT_CLASS_READ, read_class); + audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); + audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); + return 0; +} + +__initcall(audit_classes_init); diff --git a/arch/s390/kernel/compat_audit.c b/arch/s390/kernel/compat_audit.c new file mode 100644 index 000000000..16d9436bf --- /dev/null +++ b/arch/s390/kernel/compat_audit.c @@ -0,0 +1,38 @@ +#undef __s390x__ +#include <asm/unistd.h> + +unsigned s390_dir_class[] = { +#include <asm-generic/audit_dir_write.h> +~0U +}; + +unsigned s390_chattr_class[] = { +#include <asm-generic/audit_change_attr.h> +~0U +}; + +unsigned s390_write_class[] = { +#include <asm-generic/audit_write.h> +~0U +}; + +unsigned s390_read_class[] = { +#include <asm-generic/audit_read.h> +~0U +}; + +int s390_classify_syscall(unsigned syscall) +{ + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_socketcall: + return 4; + case __NR_execve: + return 5; + default: + return 1; + } +} diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c new file mode 100644 index 000000000..d9428a0fc --- /dev/null +++ b/arch/s390/kernel/stacktrace.c @@ -0,0 +1,89 @@ +/* + * arch/s390/kernel/stacktrace.c + * + * Stack trace management functions + * + * Copyright (C) IBM Corp. 2006 + * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> + */ + +#include <linux/sched.h> +#include <linux/stacktrace.h> +#include <linux/kallsyms.h> + +static inline unsigned long save_context_stack(struct stack_trace *trace, + unsigned int *skip, + unsigned long sp, + unsigned long low, + unsigned long high) +{ + struct stack_frame *sf; + struct pt_regs *regs; + unsigned long addr; + + while(1) { + sp &= PSW_ADDR_INSN; + if (sp < low || sp > high) + return sp; + sf = (struct stack_frame *)sp; + while(1) { + addr = sf->gprs[8] & PSW_ADDR_INSN; + if (!(*skip)) + trace->entries[trace->nr_entries++] = addr; + else + (*skip)--; + if (trace->nr_entries >= trace->max_entries) + return sp; + low = sp; + sp = sf->back_chain & PSW_ADDR_INSN; + if (!sp) + break; + if (sp <= low || sp > high - sizeof(*sf)) + return sp; + sf = (struct stack_frame *)sp; + } + /* Zero backchain detected, check for interrupt frame. */ + sp = (unsigned long)(sf + 1); + if (sp <= low || sp > high - sizeof(*regs)) + return sp; + regs = (struct pt_regs *)sp; + addr = regs->psw.addr & PSW_ADDR_INSN; + if (!(*skip)) + trace->entries[trace->nr_entries++] = addr; + else + (*skip)--; + if (trace->nr_entries >= trace->max_entries) + return sp; + low = sp; + sp = regs->gprs[15]; + } +} + +void save_stack_trace(struct stack_trace *trace, struct task_struct *task) +{ + register unsigned long sp asm ("15"); + unsigned long orig_sp; + + sp &= PSW_ADDR_INSN; + orig_sp = sp; + + sp = save_context_stack(trace, &trace->skip, sp, + S390_lowcore.panic_stack - PAGE_SIZE, + S390_lowcore.panic_stack); + if ((sp != orig_sp) && !trace->all_contexts) + return; + sp = save_context_stack(trace, &trace->skip, sp, + S390_lowcore.async_stack - ASYNC_SIZE, + S390_lowcore.async_stack); + if ((sp != orig_sp) && !trace->all_contexts) + return; + if (task) + save_context_stack(trace, &trace->skip, sp, + (unsigned long) task_stack_page(task), + (unsigned long) task_stack_page(task) + THREAD_SIZE); + else + save_context_stack(trace, &trace->skip, sp, + S390_lowcore.thread_info, + S390_lowcore.thread_info + THREAD_SIZE); + return; +} diff --git a/arch/s390/lib/div64.c b/arch/s390/lib/div64.c new file mode 100644 index 000000000..0481f3424 --- /dev/null +++ b/arch/s390/lib/div64.c @@ -0,0 +1,151 @@ +/* + * arch/s390/lib/div64.c + * + * __div64_32 implementation for 31 bit. + * + * Copyright (C) IBM Corp. 2006 + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + */ + +#include <linux/types.h> +#include <linux/module.h> + +#ifdef CONFIG_MARCH_G5 + +/* + * Function to divide an unsigned 64 bit integer by an unsigned + * 31 bit integer using signed 64/32 bit division. + */ +static uint32_t __div64_31(uint64_t *n, uint32_t base) +{ + register uint32_t reg2 asm("2"); + register uint32_t reg3 asm("3"); + uint32_t *words = (uint32_t *) n; + uint32_t tmp; + + /* Special case base==1, remainder = 0, quotient = n */ + if (base == 1) + return 0; + /* + * Special case base==0 will cause a fixed point divide exception + * on the dr instruction and may not happen anyway. For the + * following calculation we can assume base > 1. The first + * signed 64 / 32 bit division with an upper half of 0 will + * give the correct upper half of the 64 bit quotient. + */ + reg2 = 0UL; + reg3 = words[0]; + asm volatile( + " dr %0,%2\n" + : "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" ); + words[0] = reg3; + reg3 = words[1]; + /* + * To get the lower half of the 64 bit quotient and the 32 bit + * remainder we have to use a little trick. Since we only have + * a signed division the quotient can get too big. To avoid this + * the 64 bit dividend is halved, then the signed division will + * work. Afterwards the quotient and the remainder are doubled. + * If the last bit of the dividend has been one the remainder + * is increased by one then checked against the base. If the + * remainder has overflown subtract base and increase the + * quotient. Simple, no ? + */ + asm volatile( + " nr %2,%1\n" + " srdl %0,1\n" + " dr %0,%3\n" + " alr %0,%0\n" + " alr %1,%1\n" + " alr %0,%2\n" + " clr %0,%3\n" + " jl 0f\n" + " slr %0,%3\n" + " alr %1,%2\n" + "0:\n" + : "+d" (reg2), "+d" (reg3), "=d" (tmp) + : "d" (base), "2" (1UL) : "cc" ); + words[1] = reg3; + return reg2; +} + +/* + * Function to divide an unsigned 64 bit integer by an unsigned + * 32 bit integer using the unsigned 64/31 bit division. + */ +uint32_t __div64_32(uint64_t *n, uint32_t base) +{ + uint32_t r; + + /* + * If the most significant bit of base is set, divide n by + * (base/2). That allows to use 64/31 bit division and gives a + * good approximation of the result: n = (base/2)*q + r. The + * result needs to be corrected with two simple transformations. + * If base is already < 2^31-1 __div64_31 can be used directly. + */ + r = __div64_31(n, ((signed) base < 0) ? (base/2) : base); + if ((signed) base < 0) { + uint64_t q = *n; + /* + * First transformation: + * n = (base/2)*q + r + * = ((base/2)*2)*(q/2) + ((q&1) ? (base/2) : 0) + r + * Since r < (base/2), r + (base/2) < base. + * With q1 = (q/2) and r1 = r + ((q&1) ? (base/2) : 0) + * n = ((base/2)*2)*q1 + r1 with r1 < base. + */ + if (q & 1) + r += base/2; + q >>= 1; + /* + * Second transformation. ((base/2)*2) could have lost the + * last bit. + * n = ((base/2)*2)*q1 + r1 + * = base*q1 - ((base&1) ? q1 : 0) + r1 + */ + if (base & 1) { + int64_t rx = r - q; + /* + * base is >= 2^31. The worst case for the while + * loop is n=2^64-1 base=2^31+1. That gives a + * maximum for q=(2^64-1)/2^31 = 0x1ffffffff. Since + * base >= 2^31 the loop is finished after a maximum + * of three iterations. + */ + while (rx < 0) { + rx += base; + q--; + } + r = rx; + } + *n = q; + } + return r; +} + +#else /* MARCH_G5 */ + +uint32_t __div64_32(uint64_t *n, uint32_t base) +{ + register uint32_t reg2 asm("2"); + register uint32_t reg3 asm("3"); + uint32_t *words = (uint32_t *) n; + + reg2 = 0UL; + reg3 = words[0]; + asm volatile( + " dlr %0,%2\n" + : "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" ); + words[0] = reg3; + reg3 = words[1]; + asm volatile( + " dlr %0,%2\n" + : "+d" (reg2), "+d" (reg3) : "d" (base) : "cc" ); + words[1] = reg3; + return reg2; +} + +#endif /* MARCH_G5 */ + +EXPORT_SYMBOL(__div64_32); diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c new file mode 100644 index 000000000..74bef2a2d --- /dev/null +++ b/arch/sparc/kernel/of_device.c @@ -0,0 +1,823 @@ +#include <linux/string.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/slab.h> + +#include <asm/errno.h> +#include <asm/of_device.h> + +/** + * of_match_device - Tell if an of_device structure has a matching + * of_match structure + * @ids: array of of device match structures to search in + * @dev: the of device structure to match against + * + * Used by a driver to check whether an of_device present in the + * system is in its list of supported devices. + */ +const struct of_device_id *of_match_device(const struct of_device_id *matches, + const struct of_device *dev) +{ + if (!dev->node) + return NULL; + while (matches->name[0] || matches->type[0] || matches->compatible[0]) { + int match = 1; + if (matches->name[0]) + match &= dev->node->name + && !strcmp(matches->name, dev->node->name); + if (matches->type[0]) + match &= dev->node->type + && !strcmp(matches->type, dev->node->type); + if (matches->compatible[0]) + match &= of_device_is_compatible(dev->node, + matches->compatible); + if (match) + return matches; + matches++; + } + return NULL; +} + +static int of_platform_bus_match(struct device *dev, struct device_driver *drv) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * of_drv = to_of_platform_driver(drv); + const struct of_device_id * matches = of_drv->match_table; + + if (!matches) + return 0; + + return of_match_device(matches, of_dev) != NULL; +} + +struct of_device *of_dev_get(struct of_device *dev) +{ + struct device *tmp; + + if (!dev) + return NULL; + tmp = get_device(&dev->dev); + if (tmp) + return to_of_device(tmp); + else + return NULL; +} + +void of_dev_put(struct of_device *dev) +{ + if (dev) + put_device(&dev->dev); +} + + +static int of_device_probe(struct device *dev) +{ + int error = -ENODEV; + struct of_platform_driver *drv; + struct of_device *of_dev; + const struct of_device_id *match; + + drv = to_of_platform_driver(dev->driver); + of_dev = to_of_device(dev); + + if (!drv->probe) + return error; + + of_dev_get(of_dev); + + match = of_match_device(drv->match_table, of_dev); + if (match) + error = drv->probe(of_dev, match); + if (error) + of_dev_put(of_dev); + + return error; +} + +static int of_device_remove(struct device *dev) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + + if (dev->driver && drv->remove) + drv->remove(of_dev); + return 0; +} + +static int of_device_suspend(struct device *dev, pm_message_t state) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->suspend) + error = drv->suspend(of_dev, state); + return error; +} + +static int of_device_resume(struct device * dev) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->resume) + error = drv->resume(of_dev); + return error; +} + +static int node_match(struct device *dev, void *data) +{ + struct of_device *op = to_of_device(dev); + struct device_node *dp = data; + + return (op->node == dp); +} + +struct of_device *of_find_device_by_node(struct device_node *dp) +{ + struct device *dev = bus_find_device(&of_bus_type, NULL, + dp, node_match); + + if (dev) + return to_of_device(dev); + + return NULL; +} +EXPORT_SYMBOL(of_find_device_by_node); + +#ifdef CONFIG_PCI +struct bus_type ebus_bus_type = { + .name = "ebus", + .match = of_platform_bus_match, + .probe = of_device_probe, + .remove = of_device_remove, + .suspend = of_device_suspend, + .resume = of_device_resume, +}; +EXPORT_SYMBOL(ebus_bus_type); +#endif + +#ifdef CONFIG_SBUS +struct bus_type sbus_bus_type = { + .name = "sbus", + .match = of_platform_bus_match, + .probe = of_device_probe, + .remove = of_device_remove, + .suspend = of_device_suspend, + .resume = of_device_resume, +}; +EXPORT_SYMBOL(sbus_bus_type); +#endif + +struct bus_type of_bus_type = { + .name = "of", + .match = of_platform_bus_match, + .probe = of_device_probe, + .remove = of_device_remove, + .suspend = of_device_suspend, + .resume = of_device_resume, +}; +EXPORT_SYMBOL(of_bus_type); + +static inline u64 of_read_addr(const u32 *cell, int size) +{ + u64 r = 0; + while (size--) + r = (r << 32) | *(cell++); + return r; +} + +static void __init get_cells(struct device_node *dp, + int *addrc, int *sizec) +{ + if (addrc) + *addrc = of_n_addr_cells(dp); + if (sizec) + *sizec = of_n_size_cells(dp); +} + +/* Max address size we deal with */ +#define OF_MAX_ADDR_CELLS 4 + +struct of_bus { + const char *name; + const char *addr_prop_name; + int (*match)(struct device_node *parent); + void (*count_cells)(struct device_node *child, + int *addrc, int *sizec); + int (*map)(u32 *addr, const u32 *range, + int na, int ns, int pna); + unsigned int (*get_flags)(u32 *addr); +}; + +/* + * Default translator (generic bus) + */ + +static void of_bus_default_count_cells(struct device_node *dev, + int *addrc, int *sizec) +{ + get_cells(dev, addrc, sizec); +} + +/* Make sure the least significant 64-bits are in-range. Even + * for 3 or 4 cell values it is a good enough approximation. + */ +static int of_out_of_range(const u32 *addr, const u32 *base, + const u32 *size, int na, int ns) +{ + u64 a = of_read_addr(addr, na); + u64 b = of_read_addr(base, na); + + if (a < b) + return 1; + + b += of_read_addr(size, ns); + if (a >= b) + return 1; + + return 0; +} + +static int of_bus_default_map(u32 *addr, const u32 *range, + int na, int ns, int pna) +{ + u32 result[OF_MAX_ADDR_CELLS]; + int i; + + if (ns > 2) { + printk("of_device: Cannot handle size cells (%d) > 2.", ns); + return -EINVAL; + } + + if (of_out_of_range(addr, range, range + na + pna, na, ns)) + return -EINVAL; + + /* Start with the parent range base. */ + memcpy(result, range + na, pna * 4); + + /* Add in the child address offset. */ + for (i = 0; i < na; i++) + result[pna - 1 - i] += + (addr[na - 1 - i] - + range[na - 1 - i]); + + memcpy(addr, result, pna * 4); + + return 0; +} + +static unsigned int of_bus_default_get_flags(u32 *addr) +{ + return IORESOURCE_MEM; +} + +/* + * PCI bus specific translator + */ + +static int of_bus_pci_match(struct device_node *np) +{ + if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) { + /* Do not do PCI specific frobbing if the + * PCI bridge lacks a ranges property. We + * want to pass it through up to the next + * parent as-is, not with the PCI translate + * method which chops off the top address cell. + */ + if (!of_find_property(np, "ranges", NULL)) + return 0; + + return 1; + } + + return 0; +} + +static void of_bus_pci_count_cells(struct device_node *np, + int *addrc, int *sizec) +{ + if (addrc) + *addrc = 3; + if (sizec) + *sizec = 2; +} + +static int of_bus_pci_map(u32 *addr, const u32 *range, + int na, int ns, int pna) +{ + u32 result[OF_MAX_ADDR_CELLS]; + int i; + + /* Check address type match */ + if ((addr[0] ^ range[0]) & 0x03000000) + return -EINVAL; + + if (of_out_of_range(addr + 1, range + 1, range + na + pna, + na - 1, ns)) + return -EINVAL; + + /* Start with the parent range base. */ + memcpy(result, range + na, pna * 4); + + /* Add in the child address offset, skipping high cell. */ + for (i = 0; i < na - 1; i++) + result[pna - 1 - i] += + (addr[na - 1 - i] - + range[na - 1 - i]); + + memcpy(addr, result, pna * 4); + + return 0; +} + +static unsigned int of_bus_pci_get_flags(u32 *addr) +{ + unsigned int flags = 0; + u32 w = addr[0]; + + switch((w >> 24) & 0x03) { + case 0x01: + flags |= IORESOURCE_IO; + case 0x02: /* 32 bits */ + case 0x03: /* 64 bits */ + flags |= IORESOURCE_MEM; + } + if (w & 0x40000000) + flags |= IORESOURCE_PREFETCH; + return flags; +} + +/* + * SBUS bus specific translator + */ + +static int of_bus_sbus_match(struct device_node *np) +{ + return !strcmp(np->name, "sbus") || + !strcmp(np->name, "sbi"); +} + +static void of_bus_sbus_count_cells(struct device_node *child, + int *addrc, int *sizec) +{ + if (addrc) + *addrc = 2; + if (sizec) + *sizec = 1; +} + +static int of_bus_sbus_map(u32 *addr, const u32 *range, int na, int ns, int pna) +{ + return of_bus_default_map(addr, range, na, ns, pna); +} + +static unsigned int of_bus_sbus_get_flags(u32 *addr) +{ + return IORESOURCE_MEM; +} + + +/* + * Array of bus specific translators + */ + +static struct of_bus of_busses[] = { + /* PCI */ + { + .name = "pci", + .addr_prop_name = "assigned-addresses", + .match = of_bus_pci_match, + .count_cells = of_bus_pci_count_cells, + .map = of_bus_pci_map, + .get_flags = of_bus_pci_get_flags, + }, + /* SBUS */ + { + .name = "sbus", + .addr_prop_name = "reg", + .match = of_bus_sbus_match, + .count_cells = of_bus_sbus_count_cells, + .map = of_bus_sbus_map, + .get_flags = of_bus_sbus_get_flags, + }, + /* Default */ + { + .name = "default", + .addr_prop_name = "reg", + .match = NULL, + .count_cells = of_bus_default_count_cells, + .map = of_bus_default_map, + .get_flags = of_bus_default_get_flags, + }, +}; + +static struct of_bus *of_match_bus(struct device_node *np) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(of_busses); i ++) + if (!of_busses[i].match || of_busses[i].match(np)) + return &of_busses[i]; + BUG(); + return NULL; +} + +static int __init build_one_resource(struct device_node *parent, + struct of_bus *bus, + struct of_bus *pbus, + u32 *addr, + int na, int ns, int pna) +{ + u32 *ranges; + unsigned int rlen; + int rone; + + ranges = of_get_property(parent, "ranges", &rlen); + if (ranges == NULL || rlen == 0) { + u32 result[OF_MAX_ADDR_CELLS]; + int i; + + memset(result, 0, pna * 4); + for (i = 0; i < na; i++) + result[pna - 1 - i] = + addr[na - 1 - i]; + + memcpy(addr, result, pna * 4); + return 0; + } + + /* Now walk through the ranges */ + rlen /= 4; + rone = na + pna + ns; + for (; rlen >= rone; rlen -= rone, ranges += rone) { + if (!bus->map(addr, ranges, na, ns, pna)) + return 0; + } + + return 1; +} + +static int of_resource_verbose; + +static void __init build_device_resources(struct of_device *op, + struct device *parent) +{ + struct of_device *p_op; + struct of_bus *bus; + int na, ns; + int index, num_reg; + void *preg; + + if (!parent) + return; + + p_op = to_of_device(parent); + bus = of_match_bus(p_op->node); + bus->count_cells(op->node, &na, &ns); + + preg = of_get_property(op->node, bus->addr_prop_name, &num_reg); + if (!preg || num_reg == 0) + return; + + /* Convert to num-cells. */ + num_reg /= 4; + + /* Conver to num-entries. */ + num_reg /= na + ns; + + for (index = 0; index < num_reg; index++) { + struct resource *r = &op->resource[index]; + u32 addr[OF_MAX_ADDR_CELLS]; + u32 *reg = (preg + (index * ((na + ns) * 4))); + struct device_node *dp = op->node; + struct device_node *pp = p_op->node; + struct of_bus *pbus; + u64 size, result = OF_BAD_ADDR; + unsigned long flags; + int dna, dns; + int pna, pns; + + size = of_read_addr(reg + na, ns); + flags = bus->get_flags(reg); + + memcpy(addr, reg, na * 4); + + /* If the immediate parent has no ranges property to apply, + * just use a 1<->1 mapping. + */ + if (of_find_property(pp, "ranges", NULL) == NULL) { + result = of_read_addr(addr, na); + goto build_res; + } + + dna = na; + dns = ns; + + while (1) { + dp = pp; + pp = dp->parent; + if (!pp) { + result = of_read_addr(addr, dna); + break; + } + + pbus = of_match_bus(pp); + pbus->count_cells(dp, &pna, &pns); + + if (build_one_resource(dp, bus, pbus, addr, + dna, dns, pna)) + break; + + dna = pna; + dns = pns; + bus = pbus; + } + + build_res: + memset(r, 0, sizeof(*r)); + + if (of_resource_verbose) + printk("%s reg[%d] -> %llx\n", + op->node->full_name, index, + result); + + if (result != OF_BAD_ADDR) { + r->start = result & 0xffffffff; + r->end = result + size - 1; + r->flags = flags | ((result >> 32ULL) & 0xffUL); + } else { + r->start = ~0UL; + r->end = ~0UL; + } + r->name = op->node->name; + } +} + +static struct of_device * __init scan_one_device(struct device_node *dp, + struct device *parent) +{ + struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); + struct linux_prom_irqs *intr; + int len, i; + + if (!op) + return NULL; + + op->node = dp; + + op->clock_freq = of_getintprop_default(dp, "clock-frequency", + (25*1000*1000)); + op->portid = of_getintprop_default(dp, "upa-portid", -1); + if (op->portid == -1) + op->portid = of_getintprop_default(dp, "portid", -1); + + intr = of_get_property(dp, "intr", &len); + if (intr) { + op->num_irqs = len / sizeof(struct linux_prom_irqs); + for (i = 0; i < op->num_irqs; i++) + op->irqs[i] = intr[i].pri; + } else { + unsigned int *irq = of_get_property(dp, "interrupts", &len); + + if (irq) { + op->num_irqs = len / sizeof(unsigned int); + for (i = 0; i < op->num_irqs; i++) + op->irqs[i] = irq[i]; + } else { + op->num_irqs = 0; + } + } + if (sparc_cpu_model == sun4d) { + static int pil_to_sbus[] = { + 0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0, + }; + struct device_node *io_unit, *sbi = dp->parent; + struct linux_prom_registers *regs; + int board, slot; + + while (sbi) { + if (!strcmp(sbi->name, "sbi")) + break; + + sbi = sbi->parent; + } + if (!sbi) + goto build_resources; + + regs = of_get_property(dp, "reg", NULL); + if (!regs) + goto build_resources; + + slot = regs->which_io; + + /* If SBI's parent is not io-unit or the io-unit lacks + * a "board#" property, something is very wrong. + */ + if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) { + printk("%s: Error, parent is not io-unit.\n", + sbi->full_name); + goto build_resources; + } + io_unit = sbi->parent; + board = of_getintprop_default(io_unit, "board#", -1); + if (board == -1) { + printk("%s: Error, lacks board# property.\n", + io_unit->full_name); + goto build_resources; + } + + for (i = 0; i < op->num_irqs; i++) { + int this_irq = op->irqs[i]; + int sbusl = pil_to_sbus[this_irq]; + + if (sbusl) + this_irq = (((board + 1) << 5) + + (sbusl << 2) + + slot); + + op->irqs[i] = this_irq; + } + } + +build_resources: + build_device_resources(op, parent); + + op->dev.parent = parent; + op->dev.bus = &of_bus_type; + if (!parent) + strcpy(op->dev.bus_id, "root"); + else + strcpy(op->dev.bus_id, dp->path_component_name); + + if (of_device_register(op)) { + printk("%s: Could not register of device.\n", + dp->full_name); + kfree(op); + op = NULL; + } + + return op; +} + +static void __init scan_tree(struct device_node *dp, struct device *parent) +{ + while (dp) { + struct of_device *op = scan_one_device(dp, parent); + + if (op) + scan_tree(dp->child, &op->dev); + + dp = dp->sibling; + } +} + +static void __init scan_of_devices(void) +{ + struct device_node *root = of_find_node_by_path("/"); + struct of_device *parent; + + parent = scan_one_device(root, NULL); + if (!parent) + return; + + scan_tree(root->child, &parent->dev); +} + +static int __init of_bus_driver_init(void) +{ + int err; + + err = bus_register(&of_bus_type); +#ifdef CONFIG_PCI + if (!err) + err = bus_register(&ebus_bus_type); +#endif +#ifdef CONFIG_SBUS + if (!err) + err = bus_register(&sbus_bus_type); +#endif + + if (!err) + scan_of_devices(); + + return err; +} + +postcore_initcall(of_bus_driver_init); + +static int __init of_debug(char *str) +{ + int val = 0; + + get_option(&str, &val); + if (val & 1) + of_resource_verbose = 1; + return 1; +} + +__setup("of_debug=", of_debug); + +int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) +{ + /* initialize common driver fields */ + drv->driver.name = drv->name; + drv->driver.bus = bus; + + /* register with core */ + return driver_register(&drv->driver); +} + +void of_unregister_driver(struct of_platform_driver *drv) +{ + driver_unregister(&drv->driver); +} + + +static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + return sprintf(buf, "%s", ofdev->node->full_name); +} + +static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL); + +/** + * of_release_dev - free an of device structure when all users of it are finished. + * @dev: device that's been disconnected + * + * Will be called only by the device core when all users of this of device are + * done. + */ +void of_release_dev(struct device *dev) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + + kfree(ofdev); +} + +int of_device_register(struct of_device *ofdev) +{ + int rc; + + BUG_ON(ofdev->node == NULL); + + rc = device_register(&ofdev->dev); + if (rc) + return rc; + + rc = device_create_file(&ofdev->dev, &dev_attr_devspec); + if (rc) + device_unregister(&ofdev->dev); + + return rc; +} + +void of_device_unregister(struct of_device *ofdev) +{ + device_remove_file(&ofdev->dev, &dev_attr_devspec); + device_unregister(&ofdev->dev); +} + +struct of_device* of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent, + struct bus_type *bus) +{ + struct of_device *dev; + + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return NULL; + memset(dev, 0, sizeof(*dev)); + + dev->dev.parent = parent; + dev->dev.bus = bus; + dev->dev.release = of_release_dev; + + strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); + + if (of_device_register(dev) != 0) { + kfree(dev); + return NULL; + } + + return dev; +} + +EXPORT_SYMBOL(of_match_device); +EXPORT_SYMBOL(of_register_driver); +EXPORT_SYMBOL(of_unregister_driver); +EXPORT_SYMBOL(of_device_register); +EXPORT_SYMBOL(of_device_unregister); +EXPORT_SYMBOL(of_dev_get); +EXPORT_SYMBOL(of_dev_put); +EXPORT_SYMBOL(of_platform_device_create); +EXPORT_SYMBOL(of_release_dev); diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c new file mode 100644 index 000000000..4ca9e5fc9 --- /dev/null +++ b/arch/sparc/kernel/prom.c @@ -0,0 +1,577 @@ +/* + * Procedures for creating, accessing and interpreting the device tree. + * + * Paul Mackerras August 1996. + * Copyright (C) 1996-2005 Paul Mackerras. + * + * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. + * {engebret|bergner}@us.ibm.com + * + * Adapted for sparc32 by David S. Miller davem@davemloft.net + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/bootmem.h> +#include <linux/module.h> + +#include <asm/prom.h> +#include <asm/oplib.h> + +static struct device_node *allnodes; + +/* use when traversing tree through the allnext, child, sibling, + * or parent members of struct device_node. + */ +static DEFINE_RWLOCK(devtree_lock); + +int of_device_is_compatible(struct device_node *device, const char *compat) +{ + const char* cp; + int cplen, l; + + cp = (char *) of_get_property(device, "compatible", &cplen); + if (cp == NULL) + return 0; + while (cplen > 0) { + if (strncmp(cp, compat, strlen(compat)) == 0) + return 1; + l = strlen(cp) + 1; + cp += l; + cplen -= l; + } + + return 0; +} +EXPORT_SYMBOL(of_device_is_compatible); + +struct device_node *of_get_parent(const struct device_node *node) +{ + struct device_node *np; + + if (!node) + return NULL; + + np = node->parent; + + return np; +} +EXPORT_SYMBOL(of_get_parent); + +struct device_node *of_get_next_child(const struct device_node *node, + struct device_node *prev) +{ + struct device_node *next; + + next = prev ? prev->sibling : node->child; + for (; next != 0; next = next->sibling) { + break; + } + + return next; +} +EXPORT_SYMBOL(of_get_next_child); + +struct device_node *of_find_node_by_path(const char *path) +{ + struct device_node *np = allnodes; + + for (; np != 0; np = np->allnext) { + if (np->full_name != 0 && strcmp(np->full_name, path) == 0) + break; + } + + return np; +} +EXPORT_SYMBOL(of_find_node_by_path); + +struct device_node *of_find_node_by_phandle(phandle handle) +{ + struct device_node *np; + + for (np = allnodes; np != 0; np = np->allnext) + if (np->node == handle) + break; + + return np; +} +EXPORT_SYMBOL(of_find_node_by_phandle); + +struct device_node *of_find_node_by_name(struct device_node *from, + const char *name) +{ + struct device_node *np; + + np = from ? from->allnext : allnodes; + for (; np != NULL; np = np->allnext) + if (np->name != NULL && strcmp(np->name, name) == 0) + break; + + return np; +} +EXPORT_SYMBOL(of_find_node_by_name); + +struct device_node *of_find_node_by_type(struct device_node *from, + const char *type) +{ + struct device_node *np; + + np = from ? from->allnext : allnodes; + for (; np != 0; np = np->allnext) + if (np->type != 0 && strcmp(np->type, type) == 0) + break; + + return np; +} +EXPORT_SYMBOL(of_find_node_by_type); + +struct device_node *of_find_compatible_node(struct device_node *from, + const char *type, const char *compatible) +{ + struct device_node *np; + + np = from ? from->allnext : allnodes; + for (; np != 0; np = np->allnext) { + if (type != NULL + && !(np->type != 0 && strcmp(np->type, type) == 0)) + continue; + if (of_device_is_compatible(np, compatible)) + break; + } + + return np; +} +EXPORT_SYMBOL(of_find_compatible_node); + +struct property *of_find_property(struct device_node *np, const char *name, + int *lenp) +{ + struct property *pp; + + for (pp = np->properties; pp != 0; pp = pp->next) { + if (strcmp(pp->name, name) == 0) { + if (lenp != 0) + *lenp = pp->length; + break; + } + } + return pp; +} +EXPORT_SYMBOL(of_find_property); + +/* + * Find a property with a given name for a given node + * and return the value. + */ +void *of_get_property(struct device_node *np, const char *name, int *lenp) +{ + struct property *pp = of_find_property(np,name,lenp); + return pp ? pp->value : NULL; +} +EXPORT_SYMBOL(of_get_property); + +int of_getintprop_default(struct device_node *np, const char *name, int def) +{ + struct property *prop; + int len; + + prop = of_find_property(np, name, &len); + if (!prop || len != 4) + return def; + + return *(int *) prop->value; +} +EXPORT_SYMBOL(of_getintprop_default); + +int of_n_addr_cells(struct device_node *np) +{ + int* ip; + do { + if (np->parent) + np = np->parent; + ip = of_get_property(np, "#address-cells", NULL); + if (ip != NULL) + return *ip; + } while (np->parent); + /* No #address-cells property for the root node, default to 2 */ + return 2; +} +EXPORT_SYMBOL(of_n_addr_cells); + +int of_n_size_cells(struct device_node *np) +{ + int* ip; + do { + if (np->parent) + np = np->parent; + ip = of_get_property(np, "#size-cells", NULL); + if (ip != NULL) + return *ip; + } while (np->parent); + /* No #size-cells property for the root node, default to 1 */ + return 1; +} +EXPORT_SYMBOL(of_n_size_cells); + +int of_set_property(struct device_node *dp, const char *name, void *val, int len) +{ + struct property **prevp; + void *new_val; + int err; + + new_val = kmalloc(len, GFP_KERNEL); + if (!new_val) + return -ENOMEM; + + memcpy(new_val, val, len); + + err = -ENODEV; + + write_lock(&devtree_lock); + prevp = &dp->properties; + while (*prevp) { + struct property *prop = *prevp; + + if (!strcmp(prop->name, name)) { + void *old_val = prop->value; + int ret; + + ret = prom_setprop(dp->node, name, val, len); + err = -EINVAL; + if (ret >= 0) { + prop->value = new_val; + prop->length = len; + + if (OF_IS_DYNAMIC(prop)) + kfree(old_val); + + OF_MARK_DYNAMIC(prop); + + err = 0; + } + break; + } + prevp = &(*prevp)->next; + } + write_unlock(&devtree_lock); + + /* XXX Upate procfs if necessary... */ + + return err; +} +EXPORT_SYMBOL(of_set_property); + +static unsigned int prom_early_allocated; + +static void * __init prom_early_alloc(unsigned long size) +{ + void *ret; + + ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL); + if (ret != NULL) + memset(ret, 0, size); + + prom_early_allocated += size; + + return ret; +} + +static int is_root_node(const struct device_node *dp) +{ + if (!dp) + return 0; + + return (dp->parent == NULL); +} + +/* The following routines deal with the black magic of fully naming a + * node. + * + * Certain well known named nodes are just the simple name string. + * + * Actual devices have an address specifier appended to the base name + * string, like this "foo@addr". The "addr" can be in any number of + * formats, and the platform plus the type of the node determine the + * format and how it is constructed. + * + * For children of the ROOT node, the naming convention is fixed and + * determined by whether this is a sun4u or sun4v system. + * + * For children of other nodes, it is bus type specific. So + * we walk up the tree until we discover a "device_type" property + * we recognize and we go from there. + */ +static void __init sparc32_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom_registers *regs; + struct property *rprop; + + rprop = of_find_property(dp, "reg", NULL); + if (!rprop) + return; + + regs = rprop->value; + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + regs->which_io, regs->phys_addr); +} + +/* "name@slot,offset" */ +static void __init sbus_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom_registers *regs; + struct property *prop; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + regs->which_io, + regs->phys_addr); +} + +/* "name@devnum[,func]" */ +static void __init pci_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom_pci_registers *regs; + struct property *prop; + unsigned int devfn; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + devfn = (regs->phys_hi >> 8) & 0xff; + if (devfn & 0x07) { + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + devfn >> 3, + devfn & 0x07); + } else { + sprintf(tmp_buf, "%s@%x", + dp->name, + devfn >> 3); + } +} + +/* "name@addrhi,addrlo" */ +static void __init ebus_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom_registers *regs; + struct property *prop; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + regs->which_io, regs->phys_addr); +} + +static void __init __build_path_component(struct device_node *dp, char *tmp_buf) +{ + struct device_node *parent = dp->parent; + + if (parent != NULL) { + if (!strcmp(parent->type, "pci") || + !strcmp(parent->type, "pciex")) + return pci_path_component(dp, tmp_buf); + if (!strcmp(parent->type, "sbus")) + return sbus_path_component(dp, tmp_buf); + if (!strcmp(parent->type, "ebus")) + return ebus_path_component(dp, tmp_buf); + + /* "isa" is handled with platform naming */ + } + + /* Use platform naming convention. */ + return sparc32_path_component(dp, tmp_buf); +} + +static char * __init build_path_component(struct device_node *dp) +{ + char tmp_buf[64], *n; + + tmp_buf[0] = '\0'; + __build_path_component(dp, tmp_buf); + if (tmp_buf[0] == '\0') + strcpy(tmp_buf, dp->name); + + n = prom_early_alloc(strlen(tmp_buf) + 1); + strcpy(n, tmp_buf); + + return n; +} + +static char * __init build_full_name(struct device_node *dp) +{ + int len, ourlen, plen; + char *n; + + plen = strlen(dp->parent->full_name); + ourlen = strlen(dp->path_component_name); + len = ourlen + plen + 2; + + n = prom_early_alloc(len); + strcpy(n, dp->parent->full_name); + if (!is_root_node(dp->parent)) { + strcpy(n + plen, "/"); + plen++; + } + strcpy(n + plen, dp->path_component_name); + + return n; +} + +static unsigned int unique_id; + +static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len) +{ + static struct property *tmp = NULL; + struct property *p; + int len; + const char *name; + + if (tmp) { + p = tmp; + memset(p, 0, sizeof(*p) + 32); + tmp = NULL; + } else { + p = prom_early_alloc(sizeof(struct property) + 32); + p->unique_id = unique_id++; + } + + p->name = (char *) (p + 1); + if (special_name) { + strcpy(p->name, special_name); + p->length = special_len; + p->value = prom_early_alloc(special_len); + memcpy(p->value, special_val, special_len); + } else { + if (prev == NULL) { + name = prom_firstprop(node, NULL); + } else { + name = prom_nextprop(node, prev, NULL); + } + if (strlen(name) == 0) { + tmp = p; + return NULL; + } + strcpy(p->name, name); + p->length = prom_getproplen(node, p->name); + if (p->length <= 0) { + p->length = 0; + } else { + p->value = prom_early_alloc(p->length + 1); + prom_getproperty(node, p->name, p->value, p->length); + ((unsigned char *)p->value)[p->length] = '\0'; + } + } + return p; +} + +static struct property * __init build_prop_list(phandle node) +{ + struct property *head, *tail; + + head = tail = build_one_prop(node, NULL, + ".node", &node, sizeof(node)); + + tail->next = build_one_prop(node, NULL, NULL, NULL, 0); + tail = tail->next; + while(tail) { + tail->next = build_one_prop(node, tail->name, + NULL, NULL, 0); + tail = tail->next; + } + + return head; +} + +static char * __init get_one_property(phandle node, char *name) +{ + char *buf = "<NULL>"; + int len; + + len = prom_getproplen(node, name); + if (len > 0) { + buf = prom_early_alloc(len); + len = prom_getproperty(node, name, buf, len); + } + + return buf; +} + +static struct device_node * __init create_node(phandle node) +{ + struct device_node *dp; + + if (!node) + return NULL; + + dp = prom_early_alloc(sizeof(*dp)); + dp->unique_id = unique_id++; + + kref_init(&dp->kref); + + dp->name = get_one_property(node, "name"); + dp->type = get_one_property(node, "device_type"); + dp->node = node; + + /* Build interrupts later... */ + + dp->properties = build_prop_list(node); + + return dp; +} + +static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp) +{ + struct device_node *dp; + + dp = create_node(node); + if (dp) { + *(*nextp) = dp; + *nextp = &dp->allnext; + + dp->parent = parent; + dp->path_component_name = build_path_component(dp); + dp->full_name = build_full_name(dp); + + dp->child = build_tree(dp, prom_getchild(node), nextp); + + dp->sibling = build_tree(parent, prom_getsibling(node), nextp); + } + + return dp; +} + +void __init prom_build_devicetree(void) +{ + struct device_node **nextp; + + allnodes = create_node(prom_root_node); + allnodes->path_component_name = ""; + allnodes->full_name = "/"; + + nextp = &allnodes->allnext; + allnodes->child = build_tree(allnodes, + prom_getchild(allnodes->node), + &nextp); + printk("PROM: Built device tree with %u bytes of memory.\n", + prom_early_allocated); +} diff --git a/arch/sparc/lib/iomap.c b/arch/sparc/lib/iomap.c new file mode 100644 index 000000000..54501c1ca --- /dev/null +++ b/arch/sparc/lib/iomap.c @@ -0,0 +1,48 @@ +/* + * Implement the sparc iomap interfaces + */ +#include <linux/pci.h> +#include <linux/module.h> +#include <asm/io.h> + +/* Create a virtual mapping cookie for an IO port range */ +void __iomem *ioport_map(unsigned long port, unsigned int nr) +{ + return (void __iomem *) (unsigned long) port; +} + +void ioport_unmap(void __iomem *addr) +{ + /* Nothing to do */ +} +EXPORT_SYMBOL(ioport_map); +EXPORT_SYMBOL(ioport_unmap); + +/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ +void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) +{ + unsigned long start = pci_resource_start(dev, bar); + unsigned long len = pci_resource_len(dev, bar); + unsigned long flags = pci_resource_flags(dev, bar); + + if (!len || !start) + return NULL; + if (maxlen && len > maxlen) + len = maxlen; + if (flags & IORESOURCE_IO) + return ioport_map(start, len); + if (flags & IORESOURCE_MEM) { + if (flags & IORESOURCE_CACHEABLE) + return ioremap(start, len); + return ioremap_nocache(start, len); + } + /* What? */ + return NULL; +} + +void pci_iounmap(struct pci_dev *dev, void __iomem * addr) +{ + /* nothing to do */ +} +EXPORT_SYMBOL(pci_iomap); +EXPORT_SYMBOL(pci_iounmap); diff --git a/arch/sparc64/kernel/audit.c b/arch/sparc64/kernel/audit.c new file mode 100644 index 000000000..aef19cc27 --- /dev/null +++ b/arch/sparc64/kernel/audit.c @@ -0,0 +1,66 @@ +#include <linux/init.h> +#include <linux/types.h> +#include <linux/audit.h> +#include <asm/unistd.h> + +static unsigned dir_class[] = { +#include <asm-generic/audit_dir_write.h> +~0U +}; + +static unsigned read_class[] = { +#include <asm-generic/audit_read.h> +~0U +}; + +static unsigned write_class[] = { +#include <asm-generic/audit_write.h> +~0U +}; + +static unsigned chattr_class[] = { +#include <asm-generic/audit_change_attr.h> +~0U +}; + +int audit_classify_syscall(int abi, unsigned syscall) +{ +#ifdef CONFIG_SPARC32_COMPAT + extern int sparc32_classify_syscall(unsigned); + if (abi == AUDIT_ARCH_SPARC) + return sparc32_classify_syscall(syscall); +#endif + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_socketcall: + return 4; + case __NR_execve: + return 5; + default: + return 0; + } +} + +static int __init audit_classes_init(void) +{ +#ifdef CONFIG_SPARC32_COMPAT + extern __u32 sparc32_dir_class[]; + extern __u32 sparc32_write_class[]; + extern __u32 sparc32_read_class[]; + extern __u32 sparc32_chattr_class[]; + audit_register_class(AUDIT_CLASS_WRITE_32, sparc32_write_class); + audit_register_class(AUDIT_CLASS_READ_32, sparc32_read_class); + audit_register_class(AUDIT_CLASS_DIR_WRITE_32, sparc32_dir_class); + audit_register_class(AUDIT_CLASS_CHATTR_32, sparc32_chattr_class); +#endif + audit_register_class(AUDIT_CLASS_WRITE, write_class); + audit_register_class(AUDIT_CLASS_READ, read_class); + audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); + audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); + return 0; +} + +__initcall(audit_classes_init); diff --git a/arch/sparc64/kernel/compat_audit.c b/arch/sparc64/kernel/compat_audit.c new file mode 100644 index 000000000..cca96c91b --- /dev/null +++ b/arch/sparc64/kernel/compat_audit.c @@ -0,0 +1,37 @@ +#include <asm-sparc/unistd.h> + +unsigned sparc32_dir_class[] = { +#include <asm-generic/audit_dir_write.h> +~0U +}; + +unsigned sparc32_chattr_class[] = { +#include <asm-generic/audit_change_attr.h> +~0U +}; + +unsigned sparc32_write_class[] = { +#include <asm-generic/audit_write.h> +~0U +}; + +unsigned sparc32_read_class[] = { +#include <asm-generic/audit_read.h> +~0U +}; + +int sparc32_classify_syscall(unsigned syscall) +{ + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_socketcall: + return 4; + case __NR_execve: + return 5; + default: + return 1; + } +} diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c new file mode 100644 index 000000000..8c7c5004d --- /dev/null +++ b/arch/sparc64/kernel/of_device.c @@ -0,0 +1,1032 @@ +#include <linux/string.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/slab.h> + +#include <asm/errno.h> +#include <asm/of_device.h> + +/** + * of_match_device - Tell if an of_device structure has a matching + * of_match structure + * @ids: array of of device match structures to search in + * @dev: the of device structure to match against + * + * Used by a driver to check whether an of_device present in the + * system is in its list of supported devices. + */ +const struct of_device_id *of_match_device(const struct of_device_id *matches, + const struct of_device *dev) +{ + if (!dev->node) + return NULL; + while (matches->name[0] || matches->type[0] || matches->compatible[0]) { + int match = 1; + if (matches->name[0]) + match &= dev->node->name + && !strcmp(matches->name, dev->node->name); + if (matches->type[0]) + match &= dev->node->type + && !strcmp(matches->type, dev->node->type); + if (matches->compatible[0]) + match &= of_device_is_compatible(dev->node, + matches->compatible); + if (match) + return matches; + matches++; + } + return NULL; +} + +static int of_platform_bus_match(struct device *dev, struct device_driver *drv) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * of_drv = to_of_platform_driver(drv); + const struct of_device_id * matches = of_drv->match_table; + + if (!matches) + return 0; + + return of_match_device(matches, of_dev) != NULL; +} + +struct of_device *of_dev_get(struct of_device *dev) +{ + struct device *tmp; + + if (!dev) + return NULL; + tmp = get_device(&dev->dev); + if (tmp) + return to_of_device(tmp); + else + return NULL; +} + +void of_dev_put(struct of_device *dev) +{ + if (dev) + put_device(&dev->dev); +} + + +static int of_device_probe(struct device *dev) +{ + int error = -ENODEV; + struct of_platform_driver *drv; + struct of_device *of_dev; + const struct of_device_id *match; + + drv = to_of_platform_driver(dev->driver); + of_dev = to_of_device(dev); + + if (!drv->probe) + return error; + + of_dev_get(of_dev); + + match = of_match_device(drv->match_table, of_dev); + if (match) + error = drv->probe(of_dev, match); + if (error) + of_dev_put(of_dev); + + return error; +} + +static int of_device_remove(struct device *dev) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + + if (dev->driver && drv->remove) + drv->remove(of_dev); + return 0; +} + +static int of_device_suspend(struct device *dev, pm_message_t state) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->suspend) + error = drv->suspend(of_dev, state); + return error; +} + +static int of_device_resume(struct device * dev) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->resume) + error = drv->resume(of_dev); + return error; +} + +void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name) +{ + unsigned long ret = res->start + offset; + + if (!request_region(ret, size, name)) + ret = 0; + + return (void __iomem *) ret; +} +EXPORT_SYMBOL(of_ioremap); + +void of_iounmap(void __iomem *base, unsigned long size) +{ + release_region((unsigned long) base, size); +} +EXPORT_SYMBOL(of_iounmap); + +static int node_match(struct device *dev, void *data) +{ + struct of_device *op = to_of_device(dev); + struct device_node *dp = data; + + return (op->node == dp); +} + +struct of_device *of_find_device_by_node(struct device_node *dp) +{ + struct device *dev = bus_find_device(&of_bus_type, NULL, + dp, node_match); + + if (dev) + return to_of_device(dev); + + return NULL; +} +EXPORT_SYMBOL(of_find_device_by_node); + +#ifdef CONFIG_PCI +struct bus_type isa_bus_type = { + .name = "isa", + .match = of_platform_bus_match, + .probe = of_device_probe, + .remove = of_device_remove, + .suspend = of_device_suspend, + .resume = of_device_resume, +}; +EXPORT_SYMBOL(isa_bus_type); + +struct bus_type ebus_bus_type = { + .name = "ebus", + .match = of_platform_bus_match, + .probe = of_device_probe, + .remove = of_device_remove, + .suspend = of_device_suspend, + .resume = of_device_resume, +}; +EXPORT_SYMBOL(ebus_bus_type); +#endif + +#ifdef CONFIG_SBUS +struct bus_type sbus_bus_type = { + .name = "sbus", + .match = of_platform_bus_match, + .probe = of_device_probe, + .remove = of_device_remove, + .suspend = of_device_suspend, + .resume = of_device_resume, +}; +EXPORT_SYMBOL(sbus_bus_type); +#endif + +struct bus_type of_bus_type = { + .name = "of", + .match = of_platform_bus_match, + .probe = of_device_probe, + .remove = of_device_remove, + .suspend = of_device_suspend, + .resume = of_device_resume, +}; +EXPORT_SYMBOL(of_bus_type); + +static inline u64 of_read_addr(const u32 *cell, int size) +{ + u64 r = 0; + while (size--) + r = (r << 32) | *(cell++); + return r; +} + +static void __init get_cells(struct device_node *dp, + int *addrc, int *sizec) +{ + if (addrc) + *addrc = of_n_addr_cells(dp); + if (sizec) + *sizec = of_n_size_cells(dp); +} + +/* Max address size we deal with */ +#define OF_MAX_ADDR_CELLS 4 + +struct of_bus { + const char *name; + const char *addr_prop_name; + int (*match)(struct device_node *parent); + void (*count_cells)(struct device_node *child, + int *addrc, int *sizec); + int (*map)(u32 *addr, const u32 *range, + int na, int ns, int pna); + unsigned int (*get_flags)(u32 *addr); +}; + +/* + * Default translator (generic bus) + */ + +static void of_bus_default_count_cells(struct device_node *dev, + int *addrc, int *sizec) +{ + get_cells(dev, addrc, sizec); +} + +/* Make sure the least significant 64-bits are in-range. Even + * for 3 or 4 cell values it is a good enough approximation. + */ +static int of_out_of_range(const u32 *addr, const u32 *base, + const u32 *size, int na, int ns) +{ + u64 a = of_read_addr(addr, na); + u64 b = of_read_addr(base, na); + + if (a < b) + return 1; + + b += of_read_addr(size, ns); + if (a >= b) + return 1; + + return 0; +} + +static int of_bus_default_map(u32 *addr, const u32 *range, + int na, int ns, int pna) +{ + u32 result[OF_MAX_ADDR_CELLS]; + int i; + + if (ns > 2) { + printk("of_device: Cannot handle size cells (%d) > 2.", ns); + return -EINVAL; + } + + if (of_out_of_range(addr, range, range + na + pna, na, ns)) + return -EINVAL; + + /* Start with the parent range base. */ + memcpy(result, range + na, pna * 4); + + /* Add in the child address offset. */ + for (i = 0; i < na; i++) + result[pna - 1 - i] += + (addr[na - 1 - i] - + range[na - 1 - i]); + + memcpy(addr, result, pna * 4); + + return 0; +} + +static unsigned int of_bus_default_get_flags(u32 *addr) +{ + return IORESOURCE_MEM; +} + +/* + * PCI bus specific translator + */ + +static int of_bus_pci_match(struct device_node *np) +{ + if (!strcmp(np->type, "pci") || !strcmp(np->type, "pciex")) { + /* Do not do PCI specific frobbing if the + * PCI bridge lacks a ranges property. We + * want to pass it through up to the next + * parent as-is, not with the PCI translate + * method which chops off the top address cell. + */ + if (!of_find_property(np, "ranges", NULL)) + return 0; + + return 1; + } + + return 0; +} + +static void of_bus_pci_count_cells(struct device_node *np, + int *addrc, int *sizec) +{ + if (addrc) + *addrc = 3; + if (sizec) + *sizec = 2; +} + +static int of_bus_pci_map(u32 *addr, const u32 *range, + int na, int ns, int pna) +{ + u32 result[OF_MAX_ADDR_CELLS]; + int i; + + /* Check address type match */ + if ((addr[0] ^ range[0]) & 0x03000000) + return -EINVAL; + + if (of_out_of_range(addr + 1, range + 1, range + na + pna, + na - 1, ns)) + return -EINVAL; + + /* Start with the parent range base. */ + memcpy(result, range + na, pna * 4); + + /* Add in the child address offset, skipping high cell. */ + for (i = 0; i < na - 1; i++) + result[pna - 1 - i] += + (addr[na - 1 - i] - + range[na - 1 - i]); + + memcpy(addr, result, pna * 4); + + return 0; +} + +static unsigned int of_bus_pci_get_flags(u32 *addr) +{ + unsigned int flags = 0; + u32 w = addr[0]; + + switch((w >> 24) & 0x03) { + case 0x01: + flags |= IORESOURCE_IO; + case 0x02: /* 32 bits */ + case 0x03: /* 64 bits */ + flags |= IORESOURCE_MEM; + } + if (w & 0x40000000) + flags |= IORESOURCE_PREFETCH; + return flags; +} + +/* + * SBUS bus specific translator + */ + +static int of_bus_sbus_match(struct device_node *np) +{ + return !strcmp(np->name, "sbus") || + !strcmp(np->name, "sbi"); +} + +static void of_bus_sbus_count_cells(struct device_node *child, + int *addrc, int *sizec) +{ + if (addrc) + *addrc = 2; + if (sizec) + *sizec = 1; +} + +/* + * FHC/Central bus specific translator. + * + * This is just needed to hard-code the address and size cell + * counts. 'fhc' and 'central' nodes lack the #address-cells and + * #size-cells properties, and if you walk to the root on such + * Enterprise boxes all you'll get is a #size-cells of 2 which is + * not what we want to use. + */ +static int of_bus_fhc_match(struct device_node *np) +{ + return !strcmp(np->name, "fhc") || + !strcmp(np->name, "central"); +} + +#define of_bus_fhc_count_cells of_bus_sbus_count_cells + +/* + * Array of bus specific translators + */ + +static struct of_bus of_busses[] = { + /* PCI */ + { + .name = "pci", + .addr_prop_name = "assigned-addresses", + .match = of_bus_pci_match, + .count_cells = of_bus_pci_count_cells, + .map = of_bus_pci_map, + .get_flags = of_bus_pci_get_flags, + }, + /* SBUS */ + { + .name = "sbus", + .addr_prop_name = "reg", + .match = of_bus_sbus_match, + .count_cells = of_bus_sbus_count_cells, + .map = of_bus_default_map, + .get_flags = of_bus_default_get_flags, + }, + /* FHC */ + { + .name = "fhc", + .addr_prop_name = "reg", + .match = of_bus_fhc_match, + .count_cells = of_bus_fhc_count_cells, + .map = of_bus_default_map, + .get_flags = of_bus_default_get_flags, + }, + /* Default */ + { + .name = "default", + .addr_prop_name = "reg", + .match = NULL, + .count_cells = of_bus_default_count_cells, + .map = of_bus_default_map, + .get_flags = of_bus_default_get_flags, + }, +}; + +static struct of_bus *of_match_bus(struct device_node *np) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(of_busses); i ++) + if (!of_busses[i].match || of_busses[i].match(np)) + return &of_busses[i]; + BUG(); + return NULL; +} + +static int __init build_one_resource(struct device_node *parent, + struct of_bus *bus, + struct of_bus *pbus, + u32 *addr, + int na, int ns, int pna) +{ + u32 *ranges; + unsigned int rlen; + int rone; + + ranges = of_get_property(parent, "ranges", &rlen); + if (ranges == NULL || rlen == 0) { + u32 result[OF_MAX_ADDR_CELLS]; + int i; + + memset(result, 0, pna * 4); + for (i = 0; i < na; i++) + result[pna - 1 - i] = + addr[na - 1 - i]; + + memcpy(addr, result, pna * 4); + return 0; + } + + /* Now walk through the ranges */ + rlen /= 4; + rone = na + pna + ns; + for (; rlen >= rone; rlen -= rone, ranges += rone) { + if (!bus->map(addr, ranges, na, ns, pna)) + return 0; + } + + return 1; +} + +static int __init use_1to1_mapping(struct device_node *pp) +{ + char *model; + + /* If this is on the PMU bus, don't try to translate it even + * if a ranges property exists. + */ + if (!strcmp(pp->name, "pmu")) + return 1; + + /* If we have a ranges property in the parent, use it. */ + if (of_find_property(pp, "ranges", NULL) != NULL) + return 0; + + /* If the parent is the dma node of an ISA bus, pass + * the translation up to the root. + */ + if (!strcmp(pp->name, "dma")) + return 0; + + /* Similarly for Simba PCI bridges. */ + model = of_get_property(pp, "model", NULL); + if (model && !strcmp(model, "SUNW,simba")) + return 0; + + return 1; +} + +static int of_resource_verbose; + +static void __init build_device_resources(struct of_device *op, + struct device *parent) +{ + struct of_device *p_op; + struct of_bus *bus; + int na, ns; + int index, num_reg; + void *preg; + + if (!parent) + return; + + p_op = to_of_device(parent); + bus = of_match_bus(p_op->node); + bus->count_cells(op->node, &na, &ns); + + preg = of_get_property(op->node, bus->addr_prop_name, &num_reg); + if (!preg || num_reg == 0) + return; + + /* Convert to num-cells. */ + num_reg /= 4; + + /* Convert to num-entries. */ + num_reg /= na + ns; + + /* Prevent overruning the op->resources[] array. */ + if (num_reg > PROMREG_MAX) { + printk(KERN_WARNING "%s: Too many regs (%d), " + "limiting to %d.\n", + op->node->full_name, num_reg, PROMREG_MAX); + num_reg = PROMREG_MAX; + } + + for (index = 0; index < num_reg; index++) { + struct resource *r = &op->resource[index]; + u32 addr[OF_MAX_ADDR_CELLS]; + u32 *reg = (preg + (index * ((na + ns) * 4))); + struct device_node *dp = op->node; + struct device_node *pp = p_op->node; + struct of_bus *pbus; + u64 size, result = OF_BAD_ADDR; + unsigned long flags; + int dna, dns; + int pna, pns; + + size = of_read_addr(reg + na, ns); + flags = bus->get_flags(reg); + + memcpy(addr, reg, na * 4); + + if (use_1to1_mapping(pp)) { + result = of_read_addr(addr, na); + goto build_res; + } + + dna = na; + dns = ns; + + while (1) { + dp = pp; + pp = dp->parent; + if (!pp) { + result = of_read_addr(addr, dna); + break; + } + + pbus = of_match_bus(pp); + pbus->count_cells(dp, &pna, &pns); + + if (build_one_resource(dp, bus, pbus, addr, + dna, dns, pna)) + break; + + dna = pna; + dns = pns; + bus = pbus; + } + + build_res: + memset(r, 0, sizeof(*r)); + + if (of_resource_verbose) + printk("%s reg[%d] -> %lx\n", + op->node->full_name, index, + result); + + if (result != OF_BAD_ADDR) { + if (tlb_type == hypervisor) + result &= 0x0fffffffffffffffUL; + + r->start = result; + r->end = result + size - 1; + r->flags = flags; + } else { + r->start = ~0UL; + r->end = ~0UL; + } + r->name = op->node->name; + } +} + +static struct device_node * __init +apply_interrupt_map(struct device_node *dp, struct device_node *pp, + u32 *imap, int imlen, u32 *imask, + unsigned int *irq_p) +{ + struct device_node *cp; + unsigned int irq = *irq_p; + struct of_bus *bus; + phandle handle; + u32 *reg; + int na, num_reg, i; + + bus = of_match_bus(pp); + bus->count_cells(dp, &na, NULL); + + reg = of_get_property(dp, "reg", &num_reg); + if (!reg || !num_reg) + return NULL; + + imlen /= ((na + 3) * 4); + handle = 0; + for (i = 0; i < imlen; i++) { + int j; + + for (j = 0; j < na; j++) { + if ((reg[j] & imask[j]) != imap[j]) + goto next; + } + if (imap[na] == irq) { + handle = imap[na + 1]; + irq = imap[na + 2]; + break; + } + + next: + imap += (na + 3); + } + if (i == imlen) { + /* Psycho and Sabre PCI controllers can have 'interrupt-map' + * properties that do not include the on-board device + * interrupts. Instead, the device's 'interrupts' property + * is already a fully specified INO value. + * + * Handle this by deciding that, if we didn't get a + * match in the parent's 'interrupt-map', and the + * parent is an IRQ translater, then use the parent as + * our IRQ controller. + */ + if (pp->irq_trans) + return pp; + + return NULL; + } + + *irq_p = irq; + cp = of_find_node_by_phandle(handle); + + return cp; +} + +static unsigned int __init pci_irq_swizzle(struct device_node *dp, + struct device_node *pp, + unsigned int irq) +{ + struct linux_prom_pci_registers *regs; + unsigned int devfn, slot, ret; + + if (irq < 1 || irq > 4) + return irq; + + regs = of_get_property(dp, "reg", NULL); + if (!regs) + return irq; + + devfn = (regs->phys_hi >> 8) & 0xff; + slot = (devfn >> 3) & 0x1f; + + ret = ((irq - 1 + (slot & 3)) & 3) + 1; + + return ret; +} + +static int of_irq_verbose; + +static unsigned int __init build_one_device_irq(struct of_device *op, + struct device *parent, + unsigned int irq) +{ + struct device_node *dp = op->node; + struct device_node *pp, *ip; + unsigned int orig_irq = irq; + + if (irq == 0xffffffff) + return irq; + + if (dp->irq_trans) { + irq = dp->irq_trans->irq_build(dp, irq, + dp->irq_trans->data); + + if (of_irq_verbose) + printk("%s: direct translate %x --> %x\n", + dp->full_name, orig_irq, irq); + + return irq; + } + + /* Something more complicated. Walk up to the root, applying + * interrupt-map or bus specific translations, until we hit + * an IRQ translator. + * + * If we hit a bus type or situation we cannot handle, we + * stop and assume that the original IRQ number was in a + * format which has special meaning to it's immediate parent. + */ + pp = dp->parent; + ip = NULL; + while (pp) { + void *imap, *imsk; + int imlen; + + imap = of_get_property(pp, "interrupt-map", &imlen); + imsk = of_get_property(pp, "interrupt-map-mask", NULL); + if (imap && imsk) { + struct device_node *iret; + int this_orig_irq = irq; + + iret = apply_interrupt_map(dp, pp, + imap, imlen, imsk, + &irq); + + if (of_irq_verbose) + printk("%s: Apply [%s:%x] imap --> [%s:%x]\n", + op->node->full_name, + pp->full_name, this_orig_irq, + (iret ? iret->full_name : "NULL"), irq); + + if (!iret) + break; + + if (iret->irq_trans) { + ip = iret; + break; + } + } else { + if (!strcmp(pp->type, "pci") || + !strcmp(pp->type, "pciex")) { + unsigned int this_orig_irq = irq; + + irq = pci_irq_swizzle(dp, pp, irq); + if (of_irq_verbose) + printk("%s: PCI swizzle [%s] " + "%x --> %x\n", + op->node->full_name, + pp->full_name, this_orig_irq, + irq); + + } + + if (pp->irq_trans) { + ip = pp; + break; + } + } + dp = pp; + pp = pp->parent; + } + if (!ip) + return orig_irq; + + irq = ip->irq_trans->irq_build(op->node, irq, + ip->irq_trans->data); + if (of_irq_verbose) + printk("%s: Apply IRQ trans [%s] %x --> %x\n", + op->node->full_name, ip->full_name, orig_irq, irq); + + return irq; +} + +static struct of_device * __init scan_one_device(struct device_node *dp, + struct device *parent) +{ + struct of_device *op = kzalloc(sizeof(*op), GFP_KERNEL); + unsigned int *irq; + int len, i; + + if (!op) + return NULL; + + op->node = dp; + + op->clock_freq = of_getintprop_default(dp, "clock-frequency", + (25*1000*1000)); + op->portid = of_getintprop_default(dp, "upa-portid", -1); + if (op->portid == -1) + op->portid = of_getintprop_default(dp, "portid", -1); + + irq = of_get_property(dp, "interrupts", &len); + if (irq) { + memcpy(op->irqs, irq, len); + op->num_irqs = len / 4; + } else { + op->num_irqs = 0; + } + + /* Prevent overruning the op->irqs[] array. */ + if (op->num_irqs > PROMINTR_MAX) { + printk(KERN_WARNING "%s: Too many irqs (%d), " + "limiting to %d.\n", + dp->full_name, op->num_irqs, PROMINTR_MAX); + op->num_irqs = PROMINTR_MAX; + } + + build_device_resources(op, parent); + for (i = 0; i < op->num_irqs; i++) + op->irqs[i] = build_one_device_irq(op, parent, op->irqs[i]); + + op->dev.parent = parent; + op->dev.bus = &of_bus_type; + if (!parent) + strcpy(op->dev.bus_id, "root"); + else + strcpy(op->dev.bus_id, dp->path_component_name); + + if (of_device_register(op)) { + printk("%s: Could not register of device.\n", + dp->full_name); + kfree(op); + op = NULL; + } + + return op; +} + +static void __init scan_tree(struct device_node *dp, struct device *parent) +{ + while (dp) { + struct of_device *op = scan_one_device(dp, parent); + + if (op) + scan_tree(dp->child, &op->dev); + + dp = dp->sibling; + } +} + +static void __init scan_of_devices(void) +{ + struct device_node *root = of_find_node_by_path("/"); + struct of_device *parent; + + parent = scan_one_device(root, NULL); + if (!parent) + return; + + scan_tree(root->child, &parent->dev); +} + +static int __init of_bus_driver_init(void) +{ + int err; + + err = bus_register(&of_bus_type); +#ifdef CONFIG_PCI + if (!err) + err = bus_register(&isa_bus_type); + if (!err) + err = bus_register(&ebus_bus_type); +#endif +#ifdef CONFIG_SBUS + if (!err) + err = bus_register(&sbus_bus_type); +#endif + + if (!err) + scan_of_devices(); + + return err; +} + +postcore_initcall(of_bus_driver_init); + +static int __init of_debug(char *str) +{ + int val = 0; + + get_option(&str, &val); + if (val & 1) + of_resource_verbose = 1; + if (val & 2) + of_irq_verbose = 1; + return 1; +} + +__setup("of_debug=", of_debug); + +int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) +{ + /* initialize common driver fields */ + drv->driver.name = drv->name; + drv->driver.bus = bus; + + /* register with core */ + return driver_register(&drv->driver); +} + +void of_unregister_driver(struct of_platform_driver *drv) +{ + driver_unregister(&drv->driver); +} + + +static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + return sprintf(buf, "%s", ofdev->node->full_name); +} + +static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL); + +/** + * of_release_dev - free an of device structure when all users of it are finished. + * @dev: device that's been disconnected + * + * Will be called only by the device core when all users of this of device are + * done. + */ +void of_release_dev(struct device *dev) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + + kfree(ofdev); +} + +int of_device_register(struct of_device *ofdev) +{ + int rc; + + BUG_ON(ofdev->node == NULL); + + rc = device_register(&ofdev->dev); + if (rc) + return rc; + + rc = device_create_file(&ofdev->dev, &dev_attr_devspec); + if (rc) + device_unregister(&ofdev->dev); + + return rc; +} + +void of_device_unregister(struct of_device *ofdev) +{ + device_remove_file(&ofdev->dev, &dev_attr_devspec); + device_unregister(&ofdev->dev); +} + +struct of_device* of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent, + struct bus_type *bus) +{ + struct of_device *dev; + + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return NULL; + memset(dev, 0, sizeof(*dev)); + + dev->dev.parent = parent; + dev->dev.bus = bus; + dev->dev.release = of_release_dev; + + strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); + + if (of_device_register(dev) != 0) { + kfree(dev); + return NULL; + } + + return dev; +} + +EXPORT_SYMBOL(of_match_device); +EXPORT_SYMBOL(of_register_driver); +EXPORT_SYMBOL(of_unregister_driver); +EXPORT_SYMBOL(of_device_register); +EXPORT_SYMBOL(of_device_unregister); +EXPORT_SYMBOL(of_dev_get); +EXPORT_SYMBOL(of_dev_put); +EXPORT_SYMBOL(of_platform_device_create); +EXPORT_SYMBOL(of_release_dev); diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c new file mode 100644 index 000000000..c60efb3cb --- /dev/null +++ b/arch/sparc64/kernel/prom.c @@ -0,0 +1,1577 @@ +/* + * Procedures for creating, accessing and interpreting the device tree. + * + * Paul Mackerras August 1996. + * Copyright (C) 1996-2005 Paul Mackerras. + * + * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. + * {engebret|bergner}@us.ibm.com + * + * Adapted for sparc64 by David S. Miller davem@davemloft.net + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/bootmem.h> +#include <linux/module.h> + +#include <asm/prom.h> +#include <asm/of_device.h> +#include <asm/oplib.h> +#include <asm/irq.h> +#include <asm/asi.h> +#include <asm/upa.h> + +static struct device_node *allnodes; + +/* use when traversing tree through the allnext, child, sibling, + * or parent members of struct device_node. + */ +static DEFINE_RWLOCK(devtree_lock); + +int of_device_is_compatible(struct device_node *device, const char *compat) +{ + const char* cp; + int cplen, l; + + cp = (char *) of_get_property(device, "compatible", &cplen); + if (cp == NULL) + return 0; + while (cplen > 0) { + if (strncmp(cp, compat, strlen(compat)) == 0) + return 1; + l = strlen(cp) + 1; + cp += l; + cplen -= l; + } + + return 0; +} +EXPORT_SYMBOL(of_device_is_compatible); + +struct device_node *of_get_parent(const struct device_node *node) +{ + struct device_node *np; + + if (!node) + return NULL; + + np = node->parent; + + return np; +} +EXPORT_SYMBOL(of_get_parent); + +struct device_node *of_get_next_child(const struct device_node *node, + struct device_node *prev) +{ + struct device_node *next; + + next = prev ? prev->sibling : node->child; + for (; next != 0; next = next->sibling) { + break; + } + + return next; +} +EXPORT_SYMBOL(of_get_next_child); + +struct device_node *of_find_node_by_path(const char *path) +{ + struct device_node *np = allnodes; + + for (; np != 0; np = np->allnext) { + if (np->full_name != 0 && strcmp(np->full_name, path) == 0) + break; + } + + return np; +} +EXPORT_SYMBOL(of_find_node_by_path); + +struct device_node *of_find_node_by_phandle(phandle handle) +{ + struct device_node *np; + + for (np = allnodes; np != 0; np = np->allnext) + if (np->node == handle) + break; + + return np; +} +EXPORT_SYMBOL(of_find_node_by_phandle); + +struct device_node *of_find_node_by_name(struct device_node *from, + const char *name) +{ + struct device_node *np; + + np = from ? from->allnext : allnodes; + for (; np != NULL; np = np->allnext) + if (np->name != NULL && strcmp(np->name, name) == 0) + break; + + return np; +} +EXPORT_SYMBOL(of_find_node_by_name); + +struct device_node *of_find_node_by_type(struct device_node *from, + const char *type) +{ + struct device_node *np; + + np = from ? from->allnext : allnodes; + for (; np != 0; np = np->allnext) + if (np->type != 0 && strcmp(np->type, type) == 0) + break; + + return np; +} +EXPORT_SYMBOL(of_find_node_by_type); + +struct device_node *of_find_compatible_node(struct device_node *from, + const char *type, const char *compatible) +{ + struct device_node *np; + + np = from ? from->allnext : allnodes; + for (; np != 0; np = np->allnext) { + if (type != NULL + && !(np->type != 0 && strcmp(np->type, type) == 0)) + continue; + if (of_device_is_compatible(np, compatible)) + break; + } + + return np; +} +EXPORT_SYMBOL(of_find_compatible_node); + +struct property *of_find_property(struct device_node *np, const char *name, + int *lenp) +{ + struct property *pp; + + for (pp = np->properties; pp != 0; pp = pp->next) { + if (strcmp(pp->name, name) == 0) { + if (lenp != 0) + *lenp = pp->length; + break; + } + } + return pp; +} +EXPORT_SYMBOL(of_find_property); + +/* + * Find a property with a given name for a given node + * and return the value. + */ +void *of_get_property(struct device_node *np, const char *name, int *lenp) +{ + struct property *pp = of_find_property(np,name,lenp); + return pp ? pp->value : NULL; +} +EXPORT_SYMBOL(of_get_property); + +int of_getintprop_default(struct device_node *np, const char *name, int def) +{ + struct property *prop; + int len; + + prop = of_find_property(np, name, &len); + if (!prop || len != 4) + return def; + + return *(int *) prop->value; +} +EXPORT_SYMBOL(of_getintprop_default); + +int of_n_addr_cells(struct device_node *np) +{ + int* ip; + do { + if (np->parent) + np = np->parent; + ip = of_get_property(np, "#address-cells", NULL); + if (ip != NULL) + return *ip; + } while (np->parent); + /* No #address-cells property for the root node, default to 2 */ + return 2; +} +EXPORT_SYMBOL(of_n_addr_cells); + +int of_n_size_cells(struct device_node *np) +{ + int* ip; + do { + if (np->parent) + np = np->parent; + ip = of_get_property(np, "#size-cells", NULL); + if (ip != NULL) + return *ip; + } while (np->parent); + /* No #size-cells property for the root node, default to 1 */ + return 1; +} +EXPORT_SYMBOL(of_n_size_cells); + +int of_set_property(struct device_node *dp, const char *name, void *val, int len) +{ + struct property **prevp; + void *new_val; + int err; + + new_val = kmalloc(len, GFP_KERNEL); + if (!new_val) + return -ENOMEM; + + memcpy(new_val, val, len); + + err = -ENODEV; + + write_lock(&devtree_lock); + prevp = &dp->properties; + while (*prevp) { + struct property *prop = *prevp; + + if (!strcmp(prop->name, name)) { + void *old_val = prop->value; + int ret; + + ret = prom_setprop(dp->node, name, val, len); + err = -EINVAL; + if (ret >= 0) { + prop->value = new_val; + prop->length = len; + + if (OF_IS_DYNAMIC(prop)) + kfree(old_val); + + OF_MARK_DYNAMIC(prop); + + err = 0; + } + break; + } + prevp = &(*prevp)->next; + } + write_unlock(&devtree_lock); + + /* XXX Upate procfs if necessary... */ + + return err; +} +EXPORT_SYMBOL(of_set_property); + +static unsigned int prom_early_allocated; + +static void * __init prom_early_alloc(unsigned long size) +{ + void *ret; + + ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL); + if (ret != NULL) + memset(ret, 0, size); + + prom_early_allocated += size; + + return ret; +} + +#ifdef CONFIG_PCI +/* PSYCHO interrupt mapping support. */ +#define PSYCHO_IMAP_A_SLOT0 0x0c00UL +#define PSYCHO_IMAP_B_SLOT0 0x0c20UL +static unsigned long psycho_pcislot_imap_offset(unsigned long ino) +{ + unsigned int bus = (ino & 0x10) >> 4; + unsigned int slot = (ino & 0x0c) >> 2; + + if (bus == 0) + return PSYCHO_IMAP_A_SLOT0 + (slot * 8); + else + return PSYCHO_IMAP_B_SLOT0 + (slot * 8); +} + +#define PSYCHO_IMAP_SCSI 0x1000UL +#define PSYCHO_IMAP_ETH 0x1008UL +#define PSYCHO_IMAP_BPP 0x1010UL +#define PSYCHO_IMAP_AU_REC 0x1018UL +#define PSYCHO_IMAP_AU_PLAY 0x1020UL +#define PSYCHO_IMAP_PFAIL 0x1028UL +#define PSYCHO_IMAP_KMS 0x1030UL +#define PSYCHO_IMAP_FLPY 0x1038UL +#define PSYCHO_IMAP_SHW 0x1040UL +#define PSYCHO_IMAP_KBD 0x1048UL +#define PSYCHO_IMAP_MS 0x1050UL +#define PSYCHO_IMAP_SER 0x1058UL +#define PSYCHO_IMAP_TIM0 0x1060UL +#define PSYCHO_IMAP_TIM1 0x1068UL +#define PSYCHO_IMAP_UE 0x1070UL +#define PSYCHO_IMAP_CE 0x1078UL +#define PSYCHO_IMAP_A_ERR 0x1080UL +#define PSYCHO_IMAP_B_ERR 0x1088UL +#define PSYCHO_IMAP_PMGMT 0x1090UL +#define PSYCHO_IMAP_GFX 0x1098UL +#define PSYCHO_IMAP_EUPA 0x10a0UL + +static unsigned long __psycho_onboard_imap_off[] = { +/*0x20*/ PSYCHO_IMAP_SCSI, +/*0x21*/ PSYCHO_IMAP_ETH, +/*0x22*/ PSYCHO_IMAP_BPP, +/*0x23*/ PSYCHO_IMAP_AU_REC, +/*0x24*/ PSYCHO_IMAP_AU_PLAY, +/*0x25*/ PSYCHO_IMAP_PFAIL, +/*0x26*/ PSYCHO_IMAP_KMS, +/*0x27*/ PSYCHO_IMAP_FLPY, +/*0x28*/ PSYCHO_IMAP_SHW, +/*0x29*/ PSYCHO_IMAP_KBD, +/*0x2a*/ PSYCHO_IMAP_MS, +/*0x2b*/ PSYCHO_IMAP_SER, +/*0x2c*/ PSYCHO_IMAP_TIM0, +/*0x2d*/ PSYCHO_IMAP_TIM1, +/*0x2e*/ PSYCHO_IMAP_UE, +/*0x2f*/ PSYCHO_IMAP_CE, +/*0x30*/ PSYCHO_IMAP_A_ERR, +/*0x31*/ PSYCHO_IMAP_B_ERR, +/*0x32*/ PSYCHO_IMAP_PMGMT, +/*0x33*/ PSYCHO_IMAP_GFX, +/*0x34*/ PSYCHO_IMAP_EUPA, +}; +#define PSYCHO_ONBOARD_IRQ_BASE 0x20 +#define PSYCHO_ONBOARD_IRQ_LAST 0x34 +#define psycho_onboard_imap_offset(__ino) \ + __psycho_onboard_imap_off[(__ino) - PSYCHO_ONBOARD_IRQ_BASE] + +#define PSYCHO_ICLR_A_SLOT0 0x1400UL +#define PSYCHO_ICLR_SCSI 0x1800UL + +#define psycho_iclr_offset(ino) \ + ((ino & 0x20) ? (PSYCHO_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \ + (PSYCHO_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3))) + +static unsigned int psycho_irq_build(struct device_node *dp, + unsigned int ino, + void *_data) +{ + unsigned long controller_regs = (unsigned long) _data; + unsigned long imap, iclr; + unsigned long imap_off, iclr_off; + int inofixup = 0; + + ino &= 0x3f; + if (ino < PSYCHO_ONBOARD_IRQ_BASE) { + /* PCI slot */ + imap_off = psycho_pcislot_imap_offset(ino); + } else { + /* Onboard device */ + if (ino > PSYCHO_ONBOARD_IRQ_LAST) { + prom_printf("psycho_irq_build: Wacky INO [%x]\n", ino); + prom_halt(); + } + imap_off = psycho_onboard_imap_offset(ino); + } + + /* Now build the IRQ bucket. */ + imap = controller_regs + imap_off; + imap += 4; + + iclr_off = psycho_iclr_offset(ino); + iclr = controller_regs + iclr_off; + iclr += 4; + + if ((ino & 0x20) == 0) + inofixup = ino & 0x03; + + return build_irq(inofixup, iclr, imap); +} + +static void psycho_irq_trans_init(struct device_node *dp) +{ + struct linux_prom64_registers *regs; + + dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); + dp->irq_trans->irq_build = psycho_irq_build; + + regs = of_get_property(dp, "reg", NULL); + dp->irq_trans->data = (void *) regs[2].phys_addr; +} + +#define sabre_read(__reg) \ +({ u64 __ret; \ + __asm__ __volatile__("ldxa [%1] %2, %0" \ + : "=r" (__ret) \ + : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ + : "memory"); \ + __ret; \ +}) + +struct sabre_irq_data { + unsigned long controller_regs; + unsigned int pci_first_busno; +}; +#define SABRE_CONFIGSPACE 0x001000000UL +#define SABRE_WRSYNC 0x1c20UL + +#define SABRE_CONFIG_BASE(CONFIG_SPACE) \ + (CONFIG_SPACE | (1UL << 24)) +#define SABRE_CONFIG_ENCODE(BUS, DEVFN, REG) \ + (((unsigned long)(BUS) << 16) | \ + ((unsigned long)(DEVFN) << 8) | \ + ((unsigned long)(REG))) + +/* When a device lives behind a bridge deeper in the PCI bus topology + * than APB, a special sequence must run to make sure all pending DMA + * transfers at the time of IRQ delivery are visible in the coherency + * domain by the cpu. This sequence is to perform a read on the far + * side of the non-APB bridge, then perform a read of Sabre's DMA + * write-sync register. + */ +static void sabre_wsync_handler(unsigned int ino, void *_arg1, void *_arg2) +{ + unsigned int phys_hi = (unsigned int) (unsigned long) _arg1; + struct sabre_irq_data *irq_data = _arg2; + unsigned long controller_regs = irq_data->controller_regs; + unsigned long sync_reg = controller_regs + SABRE_WRSYNC; + unsigned long config_space = controller_regs + SABRE_CONFIGSPACE; + unsigned int bus, devfn; + u16 _unused; + + config_space = SABRE_CONFIG_BASE(config_space); + + bus = (phys_hi >> 16) & 0xff; + devfn = (phys_hi >> 8) & 0xff; + + config_space |= SABRE_CONFIG_ENCODE(bus, devfn, 0x00); + + __asm__ __volatile__("membar #Sync\n\t" + "lduha [%1] %2, %0\n\t" + "membar #Sync" + : "=r" (_unused) + : "r" ((u16 *) config_space), + "i" (ASI_PHYS_BYPASS_EC_E_L) + : "memory"); + + sabre_read(sync_reg); +} + +#define SABRE_IMAP_A_SLOT0 0x0c00UL +#define SABRE_IMAP_B_SLOT0 0x0c20UL +#define SABRE_IMAP_SCSI 0x1000UL +#define SABRE_IMAP_ETH 0x1008UL +#define SABRE_IMAP_BPP 0x1010UL +#define SABRE_IMAP_AU_REC 0x1018UL +#define SABRE_IMAP_AU_PLAY 0x1020UL +#define SABRE_IMAP_PFAIL 0x1028UL +#define SABRE_IMAP_KMS 0x1030UL +#define SABRE_IMAP_FLPY 0x1038UL +#define SABRE_IMAP_SHW 0x1040UL +#define SABRE_IMAP_KBD 0x1048UL +#define SABRE_IMAP_MS 0x1050UL +#define SABRE_IMAP_SER 0x1058UL +#define SABRE_IMAP_UE 0x1070UL +#define SABRE_IMAP_CE 0x1078UL +#define SABRE_IMAP_PCIERR 0x1080UL +#define SABRE_IMAP_GFX 0x1098UL +#define SABRE_IMAP_EUPA 0x10a0UL +#define SABRE_ICLR_A_SLOT0 0x1400UL +#define SABRE_ICLR_B_SLOT0 0x1480UL +#define SABRE_ICLR_SCSI 0x1800UL +#define SABRE_ICLR_ETH 0x1808UL +#define SABRE_ICLR_BPP 0x1810UL +#define SABRE_ICLR_AU_REC 0x1818UL +#define SABRE_ICLR_AU_PLAY 0x1820UL +#define SABRE_ICLR_PFAIL 0x1828UL +#define SABRE_ICLR_KMS 0x1830UL +#define SABRE_ICLR_FLPY 0x1838UL +#define SABRE_ICLR_SHW 0x1840UL +#define SABRE_ICLR_KBD 0x1848UL +#define SABRE_ICLR_MS 0x1850UL +#define SABRE_ICLR_SER 0x1858UL +#define SABRE_ICLR_UE 0x1870UL +#define SABRE_ICLR_CE 0x1878UL +#define SABRE_ICLR_PCIERR 0x1880UL + +static unsigned long sabre_pcislot_imap_offset(unsigned long ino) +{ + unsigned int bus = (ino & 0x10) >> 4; + unsigned int slot = (ino & 0x0c) >> 2; + + if (bus == 0) + return SABRE_IMAP_A_SLOT0 + (slot * 8); + else + return SABRE_IMAP_B_SLOT0 + (slot * 8); +} + +static unsigned long __sabre_onboard_imap_off[] = { +/*0x20*/ SABRE_IMAP_SCSI, +/*0x21*/ SABRE_IMAP_ETH, +/*0x22*/ SABRE_IMAP_BPP, +/*0x23*/ SABRE_IMAP_AU_REC, +/*0x24*/ SABRE_IMAP_AU_PLAY, +/*0x25*/ SABRE_IMAP_PFAIL, +/*0x26*/ SABRE_IMAP_KMS, +/*0x27*/ SABRE_IMAP_FLPY, +/*0x28*/ SABRE_IMAP_SHW, +/*0x29*/ SABRE_IMAP_KBD, +/*0x2a*/ SABRE_IMAP_MS, +/*0x2b*/ SABRE_IMAP_SER, +/*0x2c*/ 0 /* reserved */, +/*0x2d*/ 0 /* reserved */, +/*0x2e*/ SABRE_IMAP_UE, +/*0x2f*/ SABRE_IMAP_CE, +/*0x30*/ SABRE_IMAP_PCIERR, +/*0x31*/ 0 /* reserved */, +/*0x32*/ 0 /* reserved */, +/*0x33*/ SABRE_IMAP_GFX, +/*0x34*/ SABRE_IMAP_EUPA, +}; +#define SABRE_ONBOARD_IRQ_BASE 0x20 +#define SABRE_ONBOARD_IRQ_LAST 0x30 +#define sabre_onboard_imap_offset(__ino) \ + __sabre_onboard_imap_off[(__ino) - SABRE_ONBOARD_IRQ_BASE] + +#define sabre_iclr_offset(ino) \ + ((ino & 0x20) ? (SABRE_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \ + (SABRE_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3))) + +static int sabre_device_needs_wsync(struct device_node *dp) +{ + struct device_node *parent = dp->parent; + char *parent_model, *parent_compat; + + /* This traversal up towards the root is meant to + * handle two cases: + * + * 1) non-PCI bus sitting under PCI, such as 'ebus' + * 2) the PCI controller interrupts themselves, which + * will use the sabre_irq_build but do not need + * the DMA synchronization handling + */ + while (parent) { + if (!strcmp(parent->type, "pci")) + break; + parent = parent->parent; + } + + if (!parent) + return 0; + + parent_model = of_get_property(parent, + "model", NULL); + if (parent_model && + (!strcmp(parent_model, "SUNW,sabre") || + !strcmp(parent_model, "SUNW,simba"))) + return 0; + + parent_compat = of_get_property(parent, + "compatible", NULL); + if (parent_compat && + (!strcmp(parent_compat, "pci108e,a000") || + !strcmp(parent_compat, "pci108e,a001"))) + return 0; + + return 1; +} + +static unsigned int sabre_irq_build(struct device_node *dp, + unsigned int ino, + void *_data) +{ + struct sabre_irq_data *irq_data = _data; + unsigned long controller_regs = irq_data->controller_regs; + struct linux_prom_pci_registers *regs; + unsigned long imap, iclr; + unsigned long imap_off, iclr_off; + int inofixup = 0; + int virt_irq; + + ino &= 0x3f; + if (ino < SABRE_ONBOARD_IRQ_BASE) { + /* PCI slot */ + imap_off = sabre_pcislot_imap_offset(ino); + } else { + /* onboard device */ + if (ino > SABRE_ONBOARD_IRQ_LAST) { + prom_printf("sabre_irq_build: Wacky INO [%x]\n", ino); + prom_halt(); + } + imap_off = sabre_onboard_imap_offset(ino); + } + + /* Now build the IRQ bucket. */ + imap = controller_regs + imap_off; + imap += 4; + + iclr_off = sabre_iclr_offset(ino); + iclr = controller_regs + iclr_off; + iclr += 4; + + if ((ino & 0x20) == 0) + inofixup = ino & 0x03; + + virt_irq = build_irq(inofixup, iclr, imap); + + /* If the parent device is a PCI<->PCI bridge other than + * APB, we have to install a pre-handler to ensure that + * all pending DMA is drained before the interrupt handler + * is run. + */ + regs = of_get_property(dp, "reg", NULL); + if (regs && sabre_device_needs_wsync(dp)) { + irq_install_pre_handler(virt_irq, + sabre_wsync_handler, + (void *) (long) regs->phys_hi, + (void *) irq_data); + } + + return virt_irq; +} + +static void sabre_irq_trans_init(struct device_node *dp) +{ + struct linux_prom64_registers *regs; + struct sabre_irq_data *irq_data; + u32 *busrange; + + dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); + dp->irq_trans->irq_build = sabre_irq_build; + + irq_data = prom_early_alloc(sizeof(struct sabre_irq_data)); + + regs = of_get_property(dp, "reg", NULL); + irq_data->controller_regs = regs[0].phys_addr; + + busrange = of_get_property(dp, "bus-range", NULL); + irq_data->pci_first_busno = busrange[0]; + + dp->irq_trans->data = irq_data; +} + +/* SCHIZO interrupt mapping support. Unlike Psycho, for this controller the + * imap/iclr registers are per-PBM. + */ +#define SCHIZO_IMAP_BASE 0x1000UL +#define SCHIZO_ICLR_BASE 0x1400UL + +static unsigned long schizo_imap_offset(unsigned long ino) +{ + return SCHIZO_IMAP_BASE + (ino * 8UL); +} + +static unsigned long schizo_iclr_offset(unsigned long ino) +{ + return SCHIZO_ICLR_BASE + (ino * 8UL); +} + +static unsigned long schizo_ino_to_iclr(unsigned long pbm_regs, + unsigned int ino) +{ + return pbm_regs + schizo_iclr_offset(ino) + 4; +} + +static unsigned long schizo_ino_to_imap(unsigned long pbm_regs, + unsigned int ino) +{ + return pbm_regs + schizo_imap_offset(ino) + 4; +} + +#define schizo_read(__reg) \ +({ u64 __ret; \ + __asm__ __volatile__("ldxa [%1] %2, %0" \ + : "=r" (__ret) \ + : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ + : "memory"); \ + __ret; \ +}) +#define schizo_write(__reg, __val) \ + __asm__ __volatile__("stxa %0, [%1] %2" \ + : /* no outputs */ \ + : "r" (__val), "r" (__reg), \ + "i" (ASI_PHYS_BYPASS_EC_E) \ + : "memory") + +static void tomatillo_wsync_handler(unsigned int ino, void *_arg1, void *_arg2) +{ + unsigned long sync_reg = (unsigned long) _arg2; + u64 mask = 1UL << (ino & IMAP_INO); + u64 val; + int limit; + + schizo_write(sync_reg, mask); + + limit = 100000; + val = 0; + while (--limit) { + val = schizo_read(sync_reg); + if (!(val & mask)) + break; + } + if (limit <= 0) { + printk("tomatillo_wsync_handler: DMA won't sync [%lx:%lx]\n", + val, mask); + } + + if (_arg1) { + static unsigned char cacheline[64] + __attribute__ ((aligned (64))); + + __asm__ __volatile__("rd %%fprs, %0\n\t" + "or %0, %4, %1\n\t" + "wr %1, 0x0, %%fprs\n\t" + "stda %%f0, [%5] %6\n\t" + "wr %0, 0x0, %%fprs\n\t" + "membar #Sync" + : "=&r" (mask), "=&r" (val) + : "0" (mask), "1" (val), + "i" (FPRS_FEF), "r" (&cacheline[0]), + "i" (ASI_BLK_COMMIT_P)); + } +} + +struct schizo_irq_data { + unsigned long pbm_regs; + unsigned long sync_reg; + u32 portid; + int chip_version; +}; + +static unsigned int schizo_irq_build(struct device_node *dp, + unsigned int ino, + void *_data) +{ + struct schizo_irq_data *irq_data = _data; + unsigned long pbm_regs = irq_data->pbm_regs; + unsigned long imap, iclr; + int ign_fixup; + int virt_irq; + int is_tomatillo; + + ino &= 0x3f; + + /* Now build the IRQ bucket. */ + imap = schizo_ino_to_imap(pbm_regs, ino); + iclr = schizo_ino_to_iclr(pbm_regs, ino); + + /* On Schizo, no inofixup occurs. This is because each + * INO has it's own IMAP register. On Psycho and Sabre + * there is only one IMAP register for each PCI slot even + * though four different INOs can be generated by each + * PCI slot. + * + * But, for JBUS variants (essentially, Tomatillo), we have + * to fixup the lowest bit of the interrupt group number. + */ + ign_fixup = 0; + + is_tomatillo = (irq_data->sync_reg != 0UL); + + if (is_tomatillo) { + if (irq_data->portid & 1) + ign_fixup = (1 << 6); + } + + virt_irq = build_irq(ign_fixup, iclr, imap); + + if (is_tomatillo) { + irq_install_pre_handler(virt_irq, + tomatillo_wsync_handler, + ((irq_data->chip_version <= 4) ? + (void *) 1 : (void *) 0), + (void *) irq_data->sync_reg); + } + + return virt_irq; +} + +static void schizo_irq_trans_init(struct device_node *dp) +{ + struct linux_prom64_registers *regs; + struct schizo_irq_data *irq_data; + + dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); + dp->irq_trans->irq_build = schizo_irq_build; + + irq_data = prom_early_alloc(sizeof(struct schizo_irq_data)); + + regs = of_get_property(dp, "reg", NULL); + dp->irq_trans->data = irq_data; + + irq_data->pbm_regs = regs[0].phys_addr; + irq_data->sync_reg = regs[3].phys_addr + 0x1a18UL; + irq_data->portid = of_getintprop_default(dp, "portid", 0); + irq_data->chip_version = of_getintprop_default(dp, "version#", 0); +} + +static unsigned int pci_sun4v_irq_build(struct device_node *dp, + unsigned int devino, + void *_data) +{ + u32 devhandle = (u32) (unsigned long) _data; + + return sun4v_build_irq(devhandle, devino); +} + +static void pci_sun4v_irq_trans_init(struct device_node *dp) +{ + struct linux_prom64_registers *regs; + + dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); + dp->irq_trans->irq_build = pci_sun4v_irq_build; + + regs = of_get_property(dp, "reg", NULL); + dp->irq_trans->data = (void *) (unsigned long) + ((regs->phys_addr >> 32UL) & 0x0fffffff); +} +#endif /* CONFIG_PCI */ + +#ifdef CONFIG_SBUS +/* INO number to IMAP register offset for SYSIO external IRQ's. + * This should conform to both Sunfire/Wildfire server and Fusion + * desktop designs. + */ +#define SYSIO_IMAP_SLOT0 0x2c04UL +#define SYSIO_IMAP_SLOT1 0x2c0cUL +#define SYSIO_IMAP_SLOT2 0x2c14UL +#define SYSIO_IMAP_SLOT3 0x2c1cUL +#define SYSIO_IMAP_SCSI 0x3004UL +#define SYSIO_IMAP_ETH 0x300cUL +#define SYSIO_IMAP_BPP 0x3014UL +#define SYSIO_IMAP_AUDIO 0x301cUL +#define SYSIO_IMAP_PFAIL 0x3024UL +#define SYSIO_IMAP_KMS 0x302cUL +#define SYSIO_IMAP_FLPY 0x3034UL +#define SYSIO_IMAP_SHW 0x303cUL +#define SYSIO_IMAP_KBD 0x3044UL +#define SYSIO_IMAP_MS 0x304cUL +#define SYSIO_IMAP_SER 0x3054UL +#define SYSIO_IMAP_TIM0 0x3064UL +#define SYSIO_IMAP_TIM1 0x306cUL +#define SYSIO_IMAP_UE 0x3074UL +#define SYSIO_IMAP_CE 0x307cUL +#define SYSIO_IMAP_SBERR 0x3084UL +#define SYSIO_IMAP_PMGMT 0x308cUL +#define SYSIO_IMAP_GFX 0x3094UL +#define SYSIO_IMAP_EUPA 0x309cUL + +#define bogon ((unsigned long) -1) +static unsigned long sysio_irq_offsets[] = { + /* SBUS Slot 0 --> 3, level 1 --> 7 */ + SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, + SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, SYSIO_IMAP_SLOT0, + SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, + SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, SYSIO_IMAP_SLOT1, + SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, + SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, SYSIO_IMAP_SLOT2, + SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, + SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, SYSIO_IMAP_SLOT3, + + /* Onboard devices (not relevant/used on SunFire). */ + SYSIO_IMAP_SCSI, + SYSIO_IMAP_ETH, + SYSIO_IMAP_BPP, + bogon, + SYSIO_IMAP_AUDIO, + SYSIO_IMAP_PFAIL, + bogon, + bogon, + SYSIO_IMAP_KMS, + SYSIO_IMAP_FLPY, + SYSIO_IMAP_SHW, + SYSIO_IMAP_KBD, + SYSIO_IMAP_MS, + SYSIO_IMAP_SER, + bogon, + bogon, + SYSIO_IMAP_TIM0, + SYSIO_IMAP_TIM1, + bogon, + bogon, + SYSIO_IMAP_UE, + SYSIO_IMAP_CE, + SYSIO_IMAP_SBERR, + SYSIO_IMAP_PMGMT, + SYSIO_IMAP_GFX, + SYSIO_IMAP_EUPA, +}; + +#undef bogon + +#define NUM_SYSIO_OFFSETS ARRAY_SIZE(sysio_irq_offsets) + +/* Convert Interrupt Mapping register pointer to associated + * Interrupt Clear register pointer, SYSIO specific version. + */ +#define SYSIO_ICLR_UNUSED0 0x3400UL +#define SYSIO_ICLR_SLOT0 0x340cUL +#define SYSIO_ICLR_SLOT1 0x344cUL +#define SYSIO_ICLR_SLOT2 0x348cUL +#define SYSIO_ICLR_SLOT3 0x34ccUL +static unsigned long sysio_imap_to_iclr(unsigned long imap) +{ + unsigned long diff = SYSIO_ICLR_UNUSED0 - SYSIO_IMAP_SLOT0; + return imap + diff; +} + +static unsigned int sbus_of_build_irq(struct device_node *dp, + unsigned int ino, + void *_data) +{ + unsigned long reg_base = (unsigned long) _data; + struct linux_prom_registers *regs; + unsigned long imap, iclr; + int sbus_slot = 0; + int sbus_level = 0; + + ino &= 0x3f; + + regs = of_get_property(dp, "reg", NULL); + if (regs) + sbus_slot = regs->which_io; + + if (ino < 0x20) + ino += (sbus_slot * 8); + + imap = sysio_irq_offsets[ino]; + if (imap == ((unsigned long)-1)) { + prom_printf("get_irq_translations: Bad SYSIO INO[%x]\n", + ino); + prom_halt(); + } + imap += reg_base; + + /* SYSIO inconsistency. For external SLOTS, we have to select + * the right ICLR register based upon the lower SBUS irq level + * bits. + */ + if (ino >= 0x20) { + iclr = sysio_imap_to_iclr(imap); + } else { + sbus_level = ino & 0x7; + + switch(sbus_slot) { + case 0: + iclr = reg_base + SYSIO_ICLR_SLOT0; + break; + case 1: + iclr = reg_base + SYSIO_ICLR_SLOT1; + break; + case 2: + iclr = reg_base + SYSIO_ICLR_SLOT2; + break; + default: + case 3: + iclr = reg_base + SYSIO_ICLR_SLOT3; + break; + }; + + iclr += ((unsigned long)sbus_level - 1UL) * 8UL; + } + return build_irq(sbus_level, iclr, imap); +} + +static void sbus_irq_trans_init(struct device_node *dp) +{ + struct linux_prom64_registers *regs; + + dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); + dp->irq_trans->irq_build = sbus_of_build_irq; + + regs = of_get_property(dp, "reg", NULL); + dp->irq_trans->data = (void *) (unsigned long) regs->phys_addr; +} +#endif /* CONFIG_SBUS */ + + +static unsigned int central_build_irq(struct device_node *dp, + unsigned int ino, + void *_data) +{ + struct device_node *central_dp = _data; + struct of_device *central_op = of_find_device_by_node(central_dp); + struct resource *res; + unsigned long imap, iclr; + u32 tmp; + + if (!strcmp(dp->name, "eeprom")) { + res = ¢ral_op->resource[5]; + } else if (!strcmp(dp->name, "zs")) { + res = ¢ral_op->resource[4]; + } else if (!strcmp(dp->name, "clock-board")) { + res = ¢ral_op->resource[3]; + } else { + return ino; + } + + imap = res->start + 0x00UL; + iclr = res->start + 0x10UL; + + /* Set the INO state to idle, and disable. */ + upa_writel(0, iclr); + upa_readl(iclr); + + tmp = upa_readl(imap); + tmp &= ~0x80000000; + upa_writel(tmp, imap); + + return build_irq(0, iclr, imap); +} + +static void central_irq_trans_init(struct device_node *dp) +{ + dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); + dp->irq_trans->irq_build = central_build_irq; + + dp->irq_trans->data = dp; +} + +struct irq_trans { + const char *name; + void (*init)(struct device_node *); +}; + +#ifdef CONFIG_PCI +static struct irq_trans pci_irq_trans_table[] = { + { "SUNW,sabre", sabre_irq_trans_init }, + { "pci108e,a000", sabre_irq_trans_init }, + { "pci108e,a001", sabre_irq_trans_init }, + { "SUNW,psycho", psycho_irq_trans_init }, + { "pci108e,8000", psycho_irq_trans_init }, + { "SUNW,schizo", schizo_irq_trans_init }, + { "pci108e,8001", schizo_irq_trans_init }, + { "SUNW,schizo+", schizo_irq_trans_init }, + { "pci108e,8002", schizo_irq_trans_init }, + { "SUNW,tomatillo", schizo_irq_trans_init }, + { "pci108e,a801", schizo_irq_trans_init }, + { "SUNW,sun4v-pci", pci_sun4v_irq_trans_init }, +}; +#endif + +static unsigned int sun4v_vdev_irq_build(struct device_node *dp, + unsigned int devino, + void *_data) +{ + u32 devhandle = (u32) (unsigned long) _data; + + return sun4v_build_irq(devhandle, devino); +} + +static void sun4v_vdev_irq_trans_init(struct device_node *dp) +{ + struct linux_prom64_registers *regs; + + dp->irq_trans = prom_early_alloc(sizeof(struct of_irq_controller)); + dp->irq_trans->irq_build = sun4v_vdev_irq_build; + + regs = of_get_property(dp, "reg", NULL); + dp->irq_trans->data = (void *) (unsigned long) + ((regs->phys_addr >> 32UL) & 0x0fffffff); +} + +static void irq_trans_init(struct device_node *dp) +{ +#ifdef CONFIG_PCI + const char *model; + int i; +#endif + +#ifdef CONFIG_PCI + model = of_get_property(dp, "model", NULL); + if (!model) + model = of_get_property(dp, "compatible", NULL); + if (model) { + for (i = 0; i < ARRAY_SIZE(pci_irq_trans_table); i++) { + struct irq_trans *t = &pci_irq_trans_table[i]; + + if (!strcmp(model, t->name)) + return t->init(dp); + } + } +#endif +#ifdef CONFIG_SBUS + if (!strcmp(dp->name, "sbus") || + !strcmp(dp->name, "sbi")) + return sbus_irq_trans_init(dp); +#endif + if (!strcmp(dp->name, "fhc") && + !strcmp(dp->parent->name, "central")) + return central_irq_trans_init(dp); + if (!strcmp(dp->name, "virtual-devices")) + return sun4v_vdev_irq_trans_init(dp); +} + +static int is_root_node(const struct device_node *dp) +{ + if (!dp) + return 0; + + return (dp->parent == NULL); +} + +/* The following routines deal with the black magic of fully naming a + * node. + * + * Certain well known named nodes are just the simple name string. + * + * Actual devices have an address specifier appended to the base name + * string, like this "foo@addr". The "addr" can be in any number of + * formats, and the platform plus the type of the node determine the + * format and how it is constructed. + * + * For children of the ROOT node, the naming convention is fixed and + * determined by whether this is a sun4u or sun4v system. + * + * For children of other nodes, it is bus type specific. So + * we walk up the tree until we discover a "device_type" property + * we recognize and we go from there. + * + * As an example, the boot device on my workstation has a full path: + * + * /pci@1e,600000/ide@d/disk@0,0:c + */ +static void __init sun4v_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom64_registers *regs; + struct property *rprop; + u32 high_bits, low_bits, type; + + rprop = of_find_property(dp, "reg", NULL); + if (!rprop) + return; + + regs = rprop->value; + if (!is_root_node(dp->parent)) { + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + (unsigned int) (regs->phys_addr >> 32UL), + (unsigned int) (regs->phys_addr & 0xffffffffUL)); + return; + } + + type = regs->phys_addr >> 60UL; + high_bits = (regs->phys_addr >> 32UL) & 0x0fffffffUL; + low_bits = (regs->phys_addr & 0xffffffffUL); + + if (type == 0 || type == 8) { + const char *prefix = (type == 0) ? "m" : "i"; + + if (low_bits) + sprintf(tmp_buf, "%s@%s%x,%x", + dp->name, prefix, + high_bits, low_bits); + else + sprintf(tmp_buf, "%s@%s%x", + dp->name, + prefix, + high_bits); + } else if (type == 12) { + sprintf(tmp_buf, "%s@%x", + dp->name, high_bits); + } +} + +static void __init sun4u_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom64_registers *regs; + struct property *prop; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + if (!is_root_node(dp->parent)) { + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + (unsigned int) (regs->phys_addr >> 32UL), + (unsigned int) (regs->phys_addr & 0xffffffffUL)); + return; + } + + prop = of_find_property(dp, "upa-portid", NULL); + if (!prop) + prop = of_find_property(dp, "portid", NULL); + if (prop) { + unsigned long mask = 0xffffffffUL; + + if (tlb_type >= cheetah) + mask = 0x7fffff; + + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + *(u32 *)prop->value, + (unsigned int) (regs->phys_addr & mask)); + } +} + +/* "name@slot,offset" */ +static void __init sbus_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom_registers *regs; + struct property *prop; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + regs->which_io, + regs->phys_addr); +} + +/* "name@devnum[,func]" */ +static void __init pci_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom_pci_registers *regs; + struct property *prop; + unsigned int devfn; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + devfn = (regs->phys_hi >> 8) & 0xff; + if (devfn & 0x07) { + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + devfn >> 3, + devfn & 0x07); + } else { + sprintf(tmp_buf, "%s@%x", + dp->name, + devfn >> 3); + } +} + +/* "name@UPA_PORTID,offset" */ +static void __init upa_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom64_registers *regs; + struct property *prop; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + prop = of_find_property(dp, "upa-portid", NULL); + if (!prop) + return; + + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + *(u32 *) prop->value, + (unsigned int) (regs->phys_addr & 0xffffffffUL)); +} + +/* "name@reg" */ +static void __init vdev_path_component(struct device_node *dp, char *tmp_buf) +{ + struct property *prop; + u32 *regs; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + sprintf(tmp_buf, "%s@%x", dp->name, *regs); +} + +/* "name@addrhi,addrlo" */ +static void __init ebus_path_component(struct device_node *dp, char *tmp_buf) +{ + struct linux_prom64_registers *regs; + struct property *prop; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + sprintf(tmp_buf, "%s@%x,%x", + dp->name, + (unsigned int) (regs->phys_addr >> 32UL), + (unsigned int) (regs->phys_addr & 0xffffffffUL)); +} + +/* "name@bus,addr" */ +static void __init i2c_path_component(struct device_node *dp, char *tmp_buf) +{ + struct property *prop; + u32 *regs; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + /* This actually isn't right... should look at the #address-cells + * property of the i2c bus node etc. etc. + */ + sprintf(tmp_buf, "%s@%x,%x", + dp->name, regs[0], regs[1]); +} + +/* "name@reg0[,reg1]" */ +static void __init usb_path_component(struct device_node *dp, char *tmp_buf) +{ + struct property *prop; + u32 *regs; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + if (prop->length == sizeof(u32) || regs[1] == 1) { + sprintf(tmp_buf, "%s@%x", + dp->name, regs[0]); + } else { + sprintf(tmp_buf, "%s@%x,%x", + dp->name, regs[0], regs[1]); + } +} + +/* "name@reg0reg1[,reg2reg3]" */ +static void __init ieee1394_path_component(struct device_node *dp, char *tmp_buf) +{ + struct property *prop; + u32 *regs; + + prop = of_find_property(dp, "reg", NULL); + if (!prop) + return; + + regs = prop->value; + + if (regs[2] || regs[3]) { + sprintf(tmp_buf, "%s@%08x%08x,%04x%08x", + dp->name, regs[0], regs[1], regs[2], regs[3]); + } else { + sprintf(tmp_buf, "%s@%08x%08x", + dp->name, regs[0], regs[1]); + } +} + +static void __init __build_path_component(struct device_node *dp, char *tmp_buf) +{ + struct device_node *parent = dp->parent; + + if (parent != NULL) { + if (!strcmp(parent->type, "pci") || + !strcmp(parent->type, "pciex")) + return pci_path_component(dp, tmp_buf); + if (!strcmp(parent->type, "sbus")) + return sbus_path_component(dp, tmp_buf); + if (!strcmp(parent->type, "upa")) + return upa_path_component(dp, tmp_buf); + if (!strcmp(parent->type, "ebus")) + return ebus_path_component(dp, tmp_buf); + if (!strcmp(parent->name, "usb") || + !strcmp(parent->name, "hub")) + return usb_path_component(dp, tmp_buf); + if (!strcmp(parent->type, "i2c")) + return i2c_path_component(dp, tmp_buf); + if (!strcmp(parent->type, "firewire")) + return ieee1394_path_component(dp, tmp_buf); + if (!strcmp(parent->type, "virtual-devices")) + return vdev_path_component(dp, tmp_buf); + + /* "isa" is handled with platform naming */ + } + + /* Use platform naming convention. */ + if (tlb_type == hypervisor) + return sun4v_path_component(dp, tmp_buf); + else + return sun4u_path_component(dp, tmp_buf); +} + +static char * __init build_path_component(struct device_node *dp) +{ + char tmp_buf[64], *n; + + tmp_buf[0] = '\0'; + __build_path_component(dp, tmp_buf); + if (tmp_buf[0] == '\0') + strcpy(tmp_buf, dp->name); + + n = prom_early_alloc(strlen(tmp_buf) + 1); + strcpy(n, tmp_buf); + + return n; +} + +static char * __init build_full_name(struct device_node *dp) +{ + int len, ourlen, plen; + char *n; + + plen = strlen(dp->parent->full_name); + ourlen = strlen(dp->path_component_name); + len = ourlen + plen + 2; + + n = prom_early_alloc(len); + strcpy(n, dp->parent->full_name); + if (!is_root_node(dp->parent)) { + strcpy(n + plen, "/"); + plen++; + } + strcpy(n + plen, dp->path_component_name); + + return n; +} + +static unsigned int unique_id; + +static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len) +{ + static struct property *tmp = NULL; + struct property *p; + + if (tmp) { + p = tmp; + memset(p, 0, sizeof(*p) + 32); + tmp = NULL; + } else { + p = prom_early_alloc(sizeof(struct property) + 32); + p->unique_id = unique_id++; + } + + p->name = (char *) (p + 1); + if (special_name) { + strcpy(p->name, special_name); + p->length = special_len; + p->value = prom_early_alloc(special_len); + memcpy(p->value, special_val, special_len); + } else { + if (prev == NULL) { + prom_firstprop(node, p->name); + } else { + prom_nextprop(node, prev, p->name); + } + if (strlen(p->name) == 0) { + tmp = p; + return NULL; + } + p->length = prom_getproplen(node, p->name); + if (p->length <= 0) { + p->length = 0; + } else { + p->value = prom_early_alloc(p->length + 1); + prom_getproperty(node, p->name, p->value, p->length); + ((unsigned char *)p->value)[p->length] = '\0'; + } + } + return p; +} + +static struct property * __init build_prop_list(phandle node) +{ + struct property *head, *tail; + + head = tail = build_one_prop(node, NULL, + ".node", &node, sizeof(node)); + + tail->next = build_one_prop(node, NULL, NULL, NULL, 0); + tail = tail->next; + while(tail) { + tail->next = build_one_prop(node, tail->name, + NULL, NULL, 0); + tail = tail->next; + } + + return head; +} + +static char * __init get_one_property(phandle node, const char *name) +{ + char *buf = "<NULL>"; + int len; + + len = prom_getproplen(node, name); + if (len > 0) { + buf = prom_early_alloc(len); + prom_getproperty(node, name, buf, len); + } + + return buf; +} + +static struct device_node * __init create_node(phandle node, struct device_node *parent) +{ + struct device_node *dp; + + if (!node) + return NULL; + + dp = prom_early_alloc(sizeof(*dp)); + dp->unique_id = unique_id++; + dp->parent = parent; + + kref_init(&dp->kref); + + dp->name = get_one_property(node, "name"); + dp->type = get_one_property(node, "device_type"); + dp->node = node; + + dp->properties = build_prop_list(node); + + irq_trans_init(dp); + + return dp; +} + +static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp) +{ + struct device_node *dp; + + dp = create_node(node, parent); + if (dp) { + *(*nextp) = dp; + *nextp = &dp->allnext; + + dp->path_component_name = build_path_component(dp); + dp->full_name = build_full_name(dp); + + dp->child = build_tree(dp, prom_getchild(node), nextp); + + dp->sibling = build_tree(parent, prom_getsibling(node), nextp); + } + + return dp; +} + +void __init prom_build_devicetree(void) +{ + struct device_node **nextp; + + allnodes = create_node(prom_root_node, NULL); + allnodes->path_component_name = ""; + allnodes->full_name = "/"; + + nextp = &allnodes->allnext; + allnodes->child = build_tree(allnodes, + prom_getchild(allnodes->node), + &nextp); + printk("PROM: Built device tree with %u bytes of memory.\n", + prom_early_allocated); +} diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c new file mode 100644 index 000000000..fc38a6d59 --- /dev/null +++ b/arch/um/kernel/exec.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/slab.h" +#include "linux/smp_lock.h" +#include "linux/ptrace.h" +#include "asm/ptrace.h" +#include "asm/pgtable.h" +#include "asm/tlbflush.h" +#include "asm/uaccess.h" +#include "user_util.h" +#include "kern_util.h" +#include "mem_user.h" +#include "kern.h" +#include "irq_user.h" +#include "tlb.h" +#include "os.h" +#include "choose-mode.h" +#include "mode_kern.h" + +void flush_thread(void) +{ + arch_flush_thread(¤t->thread.arch); + CHOOSE_MODE(flush_thread_tt(), flush_thread_skas()); +} + +void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) +{ + CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp); +} + +#ifdef CONFIG_TTY_LOG +extern void log_exec(char **argv, void *tty); +#endif + +static long execve1(char *file, char __user * __user *argv, + char __user *__user *env) +{ + long error; + +#ifdef CONFIG_TTY_LOG + task_lock(current); + log_exec(argv, current->signal->tty); + task_unlock(current); +#endif + error = do_execve(file, argv, env, ¤t->thread.regs); + if (error == 0){ + task_lock(current); + current->ptrace &= ~PT_DTRACE; +#ifdef SUBARCH_EXECVE1 + SUBARCH_EXECVE1(¤t->thread.regs.regs); +#endif + task_unlock(current); + set_cmdline(current_cmd()); + } + return(error); +} + +long um_execve(char *file, char __user *__user *argv, char __user *__user *env) +{ + long err; + + err = execve1(file, argv, env); + if(!err) + do_longjmp(current->thread.exec_buf, 1); + return(err); +} + +long sys_execve(char __user *file, char __user *__user *argv, + char __user *__user *env) +{ + long error; + char *filename; + + lock_kernel(); + filename = getname(file); + error = PTR_ERR(filename); + if (IS_ERR(filename)) goto out; + error = execve1(filename, argv, env); + putname(filename); + out: + unlock_kernel(); + return(error); +} diff --git a/arch/um/kernel/irq.c.orig b/arch/um/kernel/irq.c.orig new file mode 100644 index 000000000..f386d21d2 --- /dev/null +++ b/arch/um/kernel/irq.c.orig @@ -0,0 +1,474 @@ +/* + * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c: + * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar + */ + +#include "linux/kernel.h" +#include "linux/module.h" +#include "linux/smp.h" +#include "linux/kernel_stat.h" +#include "linux/interrupt.h" +#include "linux/random.h" +#include "linux/slab.h" +#include "linux/file.h" +#include "linux/proc_fs.h" +#include "linux/init.h" +#include "linux/seq_file.h" +#include "linux/profile.h" +#include "linux/hardirq.h" +#include "linux/vs_context.h" +#include "asm/irq.h" +#include "asm/hw_irq.h" +#include "asm/atomic.h" +#include "asm/signal.h" +#include "asm/system.h" +#include "asm/errno.h" +#include "asm/uaccess.h" +#include "user_util.h" +#include "kern_util.h" +#include "irq_user.h" +#include "irq_kern.h" +#include "os.h" +#include "sigio.h" +#include "misc_constants.h" + +/* + * Generic, controller-independent functions: + */ + +int show_interrupts(struct seq_file *p, void *v) +{ + int i = *(loff_t *) v, j; + struct irqaction * action; + unsigned long flags; + + if (i == 0) { + seq_printf(p, " "); + for_each_online_cpu(j) + seq_printf(p, "CPU%d ",j); + seq_putc(p, '\n'); + } + + if (i < NR_IRQS) { + spin_lock_irqsave(&irq_desc[i].lock, flags); + action = irq_desc[i].action; + if (!action) + goto skip; + seq_printf(p, "%3d: ",i); +#ifndef CONFIG_SMP + seq_printf(p, "%10u ", kstat_irqs(i)); +#else + for_each_online_cpu(j) + seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); +#endif + seq_printf(p, " %14s", irq_desc[i].chip->typename); + seq_printf(p, " %s", action->name); + + for (action=action->next; action; action = action->next) + seq_printf(p, ", %s", action->name); + + seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); + } else if (i == NR_IRQS) { + seq_putc(p, '\n'); + } + + return 0; +} + +struct irq_fd *active_fds = NULL; +static struct irq_fd **last_irq_ptr = &active_fds; + +extern void free_irqs(void); + +void sigio_handler(int sig, union uml_pt_regs *regs) +{ + struct irq_fd *irq_fd; + int n; + + if (smp_sigio_handler()) + return; + + while (1) { + n = os_waiting_for_events(active_fds); + if (n <= 0) { + if(n == -EINTR) continue; + else break; + } + + for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { + if (irq_fd->current_events != 0) { + irq_fd->current_events = 0; + do_IRQ(irq_fd->irq, regs); + } + } + } + + free_irqs(); +} + +static DEFINE_SPINLOCK(irq_lock); + +int activate_fd(int irq, int fd, int type, void *dev_id) +{ + struct pollfd *tmp_pfd; + struct irq_fd *new_fd, *irq_fd; + unsigned long flags; + int pid, events, err, n; + + pid = os_getpid(); + err = os_set_fd_async(fd, pid); + if (err < 0) + goto out; + + new_fd = um_kmalloc(sizeof(*new_fd)); + err = -ENOMEM; + if (new_fd == NULL) + goto out; + + if (type == IRQ_READ) + events = UM_POLLIN | UM_POLLPRI; + else + events = UM_POLLOUT; + *new_fd = ((struct irq_fd) { .next = NULL, + .id = dev_id, + .fd = fd, + .type = type, + .irq = irq, + .pid = pid, + .events = events, + .current_events = 0 } ); + + /* Critical section - locked by a spinlock because this stuff can + * be changed from interrupt handlers. The stuff above is done + * outside the lock because it allocates memory. + */ + + /* Actually, it only looks like it can be called from interrupt + * context. The culprit is reactivate_fd, which calls + * maybe_sigio_broken, which calls write_sigio_workaround, + * which calls activate_fd. However, write_sigio_workaround should + * only be called once, at boot time. That would make it clear that + * this is called only from process context, and can be locked with + * a semaphore. + */ + spin_lock_irqsave(&irq_lock, flags); + for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { + if ((irq_fd->fd == fd) && (irq_fd->type == type)) { + printk("Registering fd %d twice\n", fd); + printk("Irqs : %d, %d\n", irq_fd->irq, irq); + printk("Ids : 0x%p, 0x%p\n", irq_fd->id, dev_id); + goto out_unlock; + } + } + + /*-------------*/ + if (type == IRQ_WRITE) + fd = -1; + + tmp_pfd = NULL; + n = 0; + + while (1) { + n = os_create_pollfd(fd, events, tmp_pfd, n); + if (n == 0) + break; + + /* n > 0 + * It means we couldn't put new pollfd to current pollfds + * and tmp_fds is NULL or too small for new pollfds array. + * Needed size is equal to n as minimum. + * + * Here we have to drop the lock in order to call + * kmalloc, which might sleep. + * If something else came in and changed the pollfds array + * so we will not be able to put new pollfd struct to pollfds + * then we free the buffer tmp_fds and try again. + */ + spin_unlock_irqrestore(&irq_lock, flags); + kfree(tmp_pfd); + tmp_pfd = NULL; + + tmp_pfd = um_kmalloc(n); + if (tmp_pfd == NULL) + goto out_kfree; + + spin_lock_irqsave(&irq_lock, flags); + } + /*-------------*/ + + *last_irq_ptr = new_fd; + last_irq_ptr = &new_fd->next; + + spin_unlock_irqrestore(&irq_lock, flags); + + /* This calls activate_fd, so it has to be outside the critical + * section. + */ + maybe_sigio_broken(fd, (type == IRQ_READ)); + + return(0); + + out_unlock: + spin_unlock_irqrestore(&irq_lock, flags); + out_kfree: + kfree(new_fd); + out: + return(err); +} + +static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) +{ + unsigned long flags; + + spin_lock_irqsave(&irq_lock, flags); + os_free_irq_by_cb(test, arg, active_fds, &last_irq_ptr); + spin_unlock_irqrestore(&irq_lock, flags); +} + +struct irq_and_dev { + int irq; + void *dev; +}; + +static int same_irq_and_dev(struct irq_fd *irq, void *d) +{ + struct irq_and_dev *data = d; + + return ((irq->irq == data->irq) && (irq->id == data->dev)); +} + +void free_irq_by_irq_and_dev(unsigned int irq, void *dev) +{ + struct irq_and_dev data = ((struct irq_and_dev) { .irq = irq, + .dev = dev }); + + free_irq_by_cb(same_irq_and_dev, &data); +} + +static int same_fd(struct irq_fd *irq, void *fd) +{ + return (irq->fd == *((int *)fd)); +} + +void free_irq_by_fd(int fd) +{ + free_irq_by_cb(same_fd, &fd); +} + +static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) +{ + struct irq_fd *irq; + int i = 0; + int fdi; + + for (irq = active_fds; irq != NULL; irq = irq->next) { + if ((irq->fd == fd) && (irq->irq == irqnum)) + break; + i++; + } + if (irq == NULL) { + printk("find_irq_by_fd doesn't have descriptor %d\n", fd); + goto out; + } + fdi = os_get_pollfd(i); + if ((fdi != -1) && (fdi != fd)) { + printk("find_irq_by_fd - mismatch between active_fds and " + "pollfds, fd %d vs %d, need %d\n", irq->fd, + fdi, fd); + irq = NULL; + goto out; + } + *index_out = i; + out: + return irq; +} + +void reactivate_fd(int fd, int irqnum) +{ + struct irq_fd *irq; + unsigned long flags; + int i; + + spin_lock_irqsave(&irq_lock, flags); + irq = find_irq_by_fd(fd, irqnum, &i); + if (irq == NULL) { + spin_unlock_irqrestore(&irq_lock, flags); + return; + } + os_set_pollfd(i, irq->fd); + spin_unlock_irqrestore(&irq_lock, flags); + + /* This calls activate_fd, so it has to be outside the critical + * section. + */ + maybe_sigio_broken(fd, (irq->type == IRQ_READ)); +} + +void deactivate_fd(int fd, int irqnum) +{ + struct irq_fd *irq; + unsigned long flags; + int i; + + spin_lock_irqsave(&irq_lock, flags); + irq = find_irq_by_fd(fd, irqnum, &i); + if (irq == NULL) + goto out; + os_set_pollfd(i, -1); + out: + spin_unlock_irqrestore(&irq_lock, flags); +} + +int deactivate_all_fds(void) +{ + struct irq_fd *irq; + int err; + + for (irq = active_fds; irq != NULL; irq = irq->next) { + err = os_clear_fd_async(irq->fd); + if (err) + return err; + } + /* If there is a signal already queued, after unblocking ignore it */ + os_set_ioignore(); + + return 0; +} + +#ifdef CONFIG_MODE_TT +void forward_interrupts(int pid) +{ + struct irq_fd *irq; + unsigned long flags; + int err; + + spin_lock_irqsave(&irq_lock, flags); + for (irq = active_fds; irq != NULL; irq = irq->next) { + err = os_set_owner(irq->fd, pid); + if (err < 0) { + /* XXX Just remove the irq rather than + * print out an infinite stream of these + */ + printk("Failed to forward %d to pid %d, err = %d\n", + irq->fd, pid, -err); + } + + irq->pid = pid; + } + spin_unlock_irqrestore(&irq_lock, flags); +} +#endif + +/* + * do_IRQ handles all normal device IRQ's (the special + * SMP cross-CPU interrupts have their own specific + * handlers). + */ +unsigned int do_IRQ(int irq, union uml_pt_regs *regs) +{ + struct vx_info_save vxis; + + irq_enter(); + + __enter_vx_admin(&vxis); + __do_IRQ(irq, (struct pt_regs *)regs); + __leave_vx_admin(&vxis); + irq_exit(); + return 1; +} + +int um_request_irq(unsigned int irq, int fd, int type, + irqreturn_t (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, const char * devname, + void *dev_id) +{ + int err; + + err = request_irq(irq, handler, irqflags, devname, dev_id); + if (err) + return err; + + if (fd != -1) + err = activate_fd(irq, fd, type, dev_id); + return err; +} +EXPORT_SYMBOL(um_request_irq); +EXPORT_SYMBOL(reactivate_fd); + +/* hw_interrupt_type must define (startup || enable) && + * (shutdown || disable) && end */ +static void dummy(unsigned int irq) +{ +} + +/* This is used for everything else than the timer. */ +static struct hw_interrupt_type normal_irq_type = { + .typename = "SIGIO", + .release = free_irq_by_irq_and_dev, + .disable = dummy, + .enable = dummy, + .ack = dummy, + .end = dummy +}; + +static struct hw_interrupt_type SIGVTALRM_irq_type = { + .typename = "SIGVTALRM", + .release = free_irq_by_irq_and_dev, + .shutdown = dummy, /* never called */ + .disable = dummy, + .enable = dummy, + .ack = dummy, + .end = dummy +}; + +void __init init_IRQ(void) +{ + int i; + + irq_desc[TIMER_IRQ].status = IRQ_DISABLED; + irq_desc[TIMER_IRQ].action = NULL; + irq_desc[TIMER_IRQ].depth = 1; + irq_desc[TIMER_IRQ].chip = &SIGVTALRM_irq_type; + enable_irq(TIMER_IRQ); + for (i = 1; i < NR_IRQS; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].chip = &normal_irq_type; + enable_irq(i); + } +} + +int init_aio_irq(int irq, char *name, irqreturn_t (*handler)(int, void *, + struct pt_regs *)) +{ + int fds[2], err; + + err = os_pipe(fds, 1, 1); + if (err) { + printk("init_aio_irq - os_pipe failed, err = %d\n", -err); + goto out; + } + + err = um_request_irq(irq, fds[0], IRQ_READ, handler, + IRQF_DISABLED | IRQF_SAMPLE_RANDOM, name, + (void *) (long) fds[0]); + if (err) { + printk("init_aio_irq - : um_request_irq failed, err = %d\n", + err); + goto out_close; + } + + err = fds[1]; + goto out; + + out_close: + os_close_file(fds[0]); + os_close_file(fds[1]); + out: + return err; +} diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c new file mode 100644 index 000000000..0ad755ceb --- /dev/null +++ b/arch/um/kernel/sigio.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL + */ + +#include "linux/kernel.h" +#include "linux/list.h" +#include "linux/slab.h" +#include "linux/signal.h" +#include "linux/interrupt.h" +#include "init.h" +#include "sigio.h" +#include "irq_user.h" +#include "irq_kern.h" +#include "os.h" + +/* Protected by sigio_lock() called from write_sigio_workaround */ +static int sigio_irq_fd = -1; + +static irqreturn_t sigio_interrupt(int irq, void *data, struct pt_regs *unused) +{ + char c; + + os_read_file(sigio_irq_fd, &c, sizeof(c)); + reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ); + return(IRQ_HANDLED); +} + +int write_sigio_irq(int fd) +{ + int err; + + err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, + IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "write sigio", + NULL); + if(err){ + printk("write_sigio_irq : um_request_irq failed, err = %d\n", + err); + return(-1); + } + sigio_irq_fd = fd; + return(0); +} + +static DEFINE_SPINLOCK(sigio_spinlock); + +void sigio_lock(void) +{ + spin_lock(&sigio_spinlock); +} + +void sigio_unlock(void) +{ + spin_unlock(&sigio_spinlock); +} diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c new file mode 100644 index 000000000..2a32e5e8e --- /dev/null +++ b/arch/um/kernel/signal.c @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/stddef.h" +#include "linux/sys.h" +#include "linux/sched.h" +#include "linux/wait.h" +#include "linux/kernel.h" +#include "linux/smp_lock.h" +#include "linux/module.h" +#include "linux/slab.h" +#include "linux/tty.h" +#include "linux/binfmts.h" +#include "linux/ptrace.h" +#include "asm/signal.h" +#include "asm/uaccess.h" +#include "asm/unistd.h" +#include "user_util.h" +#include "asm/ucontext.h" +#include "kern_util.h" +#include "signal_kern.h" +#include "kern.h" +#include "frame_kern.h" +#include "sigcontext.h" +#include "mode.h" + +EXPORT_SYMBOL(block_signals); +EXPORT_SYMBOL(unblock_signals); + +#define _S(nr) (1<<((nr)-1)) + +#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) + +/* + * OK, we're invoking a handler + */ +static int handle_signal(struct pt_regs *regs, unsigned long signr, + struct k_sigaction *ka, siginfo_t *info, + sigset_t *oldset) +{ + unsigned long sp; + int err; + + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + + /* Did we come from a system call? */ + if(PT_REGS_SYSCALL_NR(regs) >= 0){ + /* If so, check system call restarting.. */ + switch(PT_REGS_SYSCALL_RET(regs)){ + case -ERESTART_RESTARTBLOCK: + case -ERESTARTNOHAND: + PT_REGS_SYSCALL_RET(regs) = -EINTR; + break; + + case -ERESTARTSYS: + if (!(ka->sa.sa_flags & SA_RESTART)) { + PT_REGS_SYSCALL_RET(regs) = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + PT_REGS_RESTART_SYSCALL(regs); + PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); + break; + } + } + + sp = PT_REGS_SP(regs); + if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) + sp = current->sas_ss_sp + current->sas_ss_size; + +#ifdef CONFIG_ARCH_HAS_SC_SIGNALS + if(!(ka->sa.sa_flags & SA_SIGINFO)) + err = setup_signal_stack_sc(sp, signr, ka, regs, oldset); + else +#endif + err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset); + + if(err){ + spin_lock_irq(¤t->sighand->siglock); + current->blocked = *oldset; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + force_sigsegv(signr, current); + } else { + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked, ¤t->blocked, + &ka->sa.sa_mask); + if(!(ka->sa.sa_flags & SA_NODEFER)) + sigaddset(¤t->blocked, signr); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } + + return err; +} + +static int kern_do_signal(struct pt_regs *regs) +{ + struct k_sigaction ka_copy; + siginfo_t info; + sigset_t *oldset; + int sig, handled_sig = 0; + + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + + while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){ + handled_sig = 1; + /* Whee! Actually deliver the signal. */ + if(!handle_signal(regs, sig, &ka_copy, &info, oldset)){ + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + break; + } + } + + /* Did we come from a system call? */ + if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){ + /* Restart the system call - no handlers present */ + switch(PT_REGS_SYSCALL_RET(regs)){ + case -ERESTARTNOHAND: + case -ERESTARTSYS: + case -ERESTARTNOINTR: + PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); + PT_REGS_RESTART_SYSCALL(regs); + break; + case -ERESTART_RESTARTBLOCK: + PT_REGS_ORIG_SYSCALL(regs) = __NR_restart_syscall; + PT_REGS_RESTART_SYSCALL(regs); + break; + } + } + + /* This closes a way to execute a system call on the host. If + * you set a breakpoint on a system call instruction and singlestep + * from it, the tracing thread used to PTRACE_SINGLESTEP the process + * rather than PTRACE_SYSCALL it, allowing the system call to execute + * on the host. The tracing thread will check this flag and + * PTRACE_SYSCALL if necessary. + */ + if(current->ptrace & PT_DTRACE) + current->thread.singlestep_syscall = + is_syscall(PT_REGS_IP(¤t->thread.regs)); + + /* if there's no signal to deliver, we just put the saved sigmask + * back */ + if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } + return(handled_sig); +} + +int do_signal(void) +{ + return(kern_do_signal(¤t->thread.regs)); +} + +/* + * Atomically swap in the new signal mask, and wait for a signal. + */ +long sys_sigsuspend(int history0, int history1, old_sigset_t mask) +{ + mask &= _BLOCKABLE; + spin_lock_irq(¤t->sighand->siglock); + current->saved_sigmask = current->blocked; + siginitset(¤t->blocked, mask); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; +} + +long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) +{ + return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs))); +} diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c new file mode 100644 index 000000000..8c90a63d9 --- /dev/null +++ b/arch/um/kernel/trap.c @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/kernel.h" +#include "asm/errno.h" +#include "linux/sched.h" +#include "linux/mm.h" +#include "linux/spinlock.h" +#include "linux/init.h" +#include "linux/ptrace.h" +#include "asm/semaphore.h" +#include "asm/pgtable.h" +#include "asm/pgalloc.h" +#include "asm/tlbflush.h" +#include "asm/a.out.h" +#include "asm/current.h" +#include "asm/irq.h" +#include "sysdep/sigcontext.h" +#include "user_util.h" +#include "kern_util.h" +#include "kern.h" +#include "chan_kern.h" +#include "mconsole_kern.h" +#include "mem.h" +#include "mem_kern.h" +#include "sysdep/sigcontext.h" +#include "sysdep/ptrace.h" +#include "os.h" +#ifdef CONFIG_MODE_SKAS +#include "skas.h" +#endif +#include "os.h" + +/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */ +int handle_page_fault(unsigned long address, unsigned long ip, + int is_write, int is_user, int *code_out) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + int err = -EFAULT; + + *code_out = SEGV_MAPERR; + + /* If the fault was during atomic operation, don't take the fault, just + * fail. */ + if (in_atomic()) + goto out_nosemaphore; + + down_read(&mm->mmap_sem); + vma = find_vma(mm, address); + if(!vma) + goto out; + else if(vma->vm_start <= address) + goto good_area; + else if(!(vma->vm_flags & VM_GROWSDOWN)) + goto out; + else if(is_user && !ARCH_IS_STACKGROW(address)) + goto out; + else if(expand_stack(vma, address)) + goto out; + +good_area: + *code_out = SEGV_ACCERR; + if(is_write && !(vma->vm_flags & VM_WRITE)) + goto out; + + /* Don't require VM_READ|VM_EXEC for write faults! */ + if(!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC))) + goto out; + + do { +survive: + switch (handle_mm_fault(mm, vma, address, is_write)){ + case VM_FAULT_MINOR: + current->min_flt++; + break; + case VM_FAULT_MAJOR: + current->maj_flt++; + break; + case VM_FAULT_SIGBUS: + err = -EACCES; + goto out; + case VM_FAULT_OOM: + err = -ENOMEM; + goto out_of_memory; + default: + BUG(); + } + pgd = pgd_offset(mm, address); + pud = pud_offset(pgd, address); + pmd = pmd_offset(pud, address); + pte = pte_offset_kernel(pmd, address); + } while(!pte_present(*pte)); + err = 0; + /* The below warning was added in place of + * pte_mkyoung(); if (is_write) pte_mkdirty(); + * If it's triggered, we'd see normally a hang here (a clean pte is + * marked read-only to emulate the dirty bit). + * However, the generic code can mark a PTE writable but clean on a + * concurrent read fault, triggering this harmlessly. So comment it out. + */ +#if 0 + WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte))); +#endif + flush_tlb_page(vma, address); +out: + up_read(&mm->mmap_sem); +out_nosemaphore: + return(err); + +/* + * We ran out of memory, or some other thing happened to us that made + * us unable to handle the page fault gracefully. + */ +out_of_memory: + if (current->pid == 1) { + up_read(&mm->mmap_sem); + yield(); + down_read(&mm->mmap_sem); + goto survive; + } + goto out; +} + +void segv_handler(int sig, union uml_pt_regs *regs) +{ + struct faultinfo * fi = UPT_FAULTINFO(regs); + + if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){ + bad_segv(*fi, UPT_IP(regs)); + return; + } + segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs); +} + +struct kern_handlers handlinfo_kern = { + .relay_signal = relay_signal, + .winch = winch, + .bus_handler = relay_signal, + .page_fault = segv_handler, + .sigio_handler = sigio_handler, + .timer_handler = timer_handler +}; +/* + * We give a *copy* of the faultinfo in the regs to segv. + * This must be done, since nesting SEGVs could overwrite + * the info in the regs. A pointer to the info then would + * give us bad data! + */ +unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) +{ + struct siginfo si; + void *catcher; + int err; + int is_write = FAULT_WRITE(fi); + unsigned long address = FAULT_ADDRESS(fi); + + if(!is_user && (address >= start_vm) && (address < end_vm)){ + flush_tlb_kernel_vm(); + return(0); + } + else if(current->mm == NULL) + panic("Segfault with no mm"); + + if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi)) + err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); + else { + err = -EFAULT; + /* A thread accessed NULL, we get a fault, but CR2 is invalid. + * This code is used in __do_copy_from_user() of TT mode. */ + address = 0; + } + + catcher = current->thread.fault_catcher; + if(!err) + return(0); + else if(catcher != NULL){ + current->thread.fault_addr = (void *) address; + do_longjmp(catcher, 1); + } + else if(current->thread.fault_addr != NULL) + panic("fault_addr set but no fault catcher"); + else if(!is_user && arch_fixup(ip, sc)) + return(0); + + if(!is_user) + panic("Kernel mode fault at addr 0x%lx, ip 0x%lx", + address, ip); + + if (err == -EACCES) { + si.si_signo = SIGBUS; + si.si_errno = 0; + si.si_code = BUS_ADRERR; + si.si_addr = (void __user *)address; + current->thread.arch.faultinfo = fi; + force_sig_info(SIGBUS, &si, current); + } else if (err == -ENOMEM) { + printk("VM: killing process %s\n", current->comm); + do_exit(SIGKILL); + } else { + BUG_ON(err != -EFAULT); + si.si_signo = SIGSEGV; + si.si_addr = (void __user *) address; + current->thread.arch.faultinfo = fi; + force_sig_info(SIGSEGV, &si, current); + } + return(0); +} + +void bad_segv(struct faultinfo fi, unsigned long ip) +{ + struct siginfo si; + + si.si_signo = SIGSEGV; + si.si_code = SEGV_ACCERR; + si.si_addr = (void __user *) FAULT_ADDRESS(fi); + current->thread.arch.faultinfo = fi; + force_sig_info(SIGSEGV, &si, current); +} + +void relay_signal(int sig, union uml_pt_regs *regs) +{ + if(arch_handle_signal(sig, regs)) return; + if(!UPT_IS_USER(regs)) + panic("Kernel mode signal %d", sig); + current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); + force_sig(sig, current); +} + +void bus_handler(int sig, union uml_pt_regs *regs) +{ + if(current->thread.fault_catcher != NULL) + do_longjmp(current->thread.fault_catcher, 1); + else relay_signal(sig, regs); +} + +void winch(int sig, union uml_pt_regs *regs) +{ + do_IRQ(WINCH_IRQ, regs); +} + +void trap_init(void) +{ +} diff --git a/arch/x86_64/ia32/audit.c b/arch/x86_64/ia32/audit.c new file mode 100644 index 000000000..92d7d0c8d --- /dev/null +++ b/arch/x86_64/ia32/audit.c @@ -0,0 +1,37 @@ +#include <asm-i386/unistd.h> + +unsigned ia32_dir_class[] = { +#include <asm-generic/audit_dir_write.h> +~0U +}; + +unsigned ia32_chattr_class[] = { +#include <asm-generic/audit_change_attr.h> +~0U +}; + +unsigned ia32_write_class[] = { +#include <asm-generic/audit_write.h> +~0U +}; + +unsigned ia32_read_class[] = { +#include <asm-generic/audit_read.h> +~0U +}; + +int ia32_classify_syscall(unsigned syscall) +{ + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_socketcall: + return 4; + case __NR_execve: + return 5; + default: + return 1; + } +} diff --git a/arch/x86_64/kernel/audit.c b/arch/x86_64/kernel/audit.c new file mode 100644 index 000000000..21f33387b --- /dev/null +++ b/arch/x86_64/kernel/audit.c @@ -0,0 +1,64 @@ +#include <linux/init.h> +#include <linux/types.h> +#include <linux/audit.h> +#include <asm/unistd.h> + +static unsigned dir_class[] = { +#include <asm-generic/audit_dir_write.h> +~0U +}; + +static unsigned read_class[] = { +#include <asm-generic/audit_read.h> +~0U +}; + +static unsigned write_class[] = { +#include <asm-generic/audit_write.h> +~0U +}; + +static unsigned chattr_class[] = { +#include <asm-generic/audit_change_attr.h> +~0U +}; + +int audit_classify_syscall(int abi, unsigned syscall) +{ +#ifdef CONFIG_IA32_EMULATION + extern int ia32_classify_syscall(unsigned); + if (abi == AUDIT_ARCH_I386) + return ia32_classify_syscall(syscall); +#endif + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_execve: + return 5; + default: + return 0; + } +} + +static int __init audit_classes_init(void) +{ +#ifdef CONFIG_IA32_EMULATION + extern __u32 ia32_dir_class[]; + extern __u32 ia32_write_class[]; + extern __u32 ia32_read_class[]; + extern __u32 ia32_chattr_class[]; + audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class); + audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class); + audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class); + audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class); +#endif + audit_register_class(AUDIT_CLASS_WRITE, write_class); + audit_register_class(AUDIT_CLASS_READ, read_class); + audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); + audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); + return 0; +} + +__initcall(audit_classes_init); diff --git a/arch/x86_64/kernel/irqflags-xen.c b/arch/x86_64/kernel/irqflags-xen.c new file mode 100644 index 000000000..e3b7ab5e6 --- /dev/null +++ b/arch/x86_64/kernel/irqflags-xen.c @@ -0,0 +1,100 @@ +#include <linux/module.h> +#include <linux/smp.h> +#include <asm/irqflags.h> +#include <asm/hypervisor.h> + +/* + * The use of 'barrier' in the following reflects their use as local-lock + * operations. Reentrancy must be prevented (e.g., __cli()) /before/ following + * critical operations are executed. All critical operations must complete + * /before/ reentrancy is permitted (e.g., __sti()). Alpha architecture also + * includes these barriers, for example. + */ + +unsigned long __raw_local_save_flags(void) +{ + struct vcpu_info *_vcpu; + unsigned long flags; + + preempt_disable(); + _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; + flags = _vcpu->evtchn_upcall_mask; + preempt_enable(); + + return flags; +} +EXPORT_SYMBOL(__raw_local_save_flags); + +void raw_local_irq_restore(unsigned long flags) +{ + struct vcpu_info *_vcpu; + preempt_disable(); + _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; + if ((_vcpu->evtchn_upcall_mask = flags) == 0) { + barrier(); /* unmask then check (avoid races) */ + if ( unlikely(_vcpu->evtchn_upcall_pending) ) + force_evtchn_callback(); + preempt_enable(); + } else + preempt_enable_no_resched(); +} +EXPORT_SYMBOL(raw_local_irq_restore); + +void raw_local_irq_disable(void) +{ + struct vcpu_info *_vcpu; + + preempt_disable(); + _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; + _vcpu->evtchn_upcall_mask = 1; + preempt_enable_no_resched(); +} +EXPORT_SYMBOL(raw_local_irq_disable); + +void raw_local_irq_enable(void) +{ + struct vcpu_info *_vcpu; + + preempt_disable(); + _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; + _vcpu->evtchn_upcall_mask = 0; + barrier(); /* unmask then check (avoid races) */ + if ( unlikely(_vcpu->evtchn_upcall_pending) ) + force_evtchn_callback(); + preempt_enable(); +} +EXPORT_SYMBOL(raw_local_irq_enable); + +/* + * For spinlocks, etc.: + */ + +unsigned long __raw_local_irq_save(void) +{ + struct vcpu_info *_vcpu; + unsigned long flags; + + preempt_disable(); + _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; + flags = _vcpu->evtchn_upcall_mask; + _vcpu->evtchn_upcall_mask = 1; + preempt_enable_no_resched(); + + return flags; +} +EXPORT_SYMBOL(__raw_local_irq_save); + +/* Cannot use preempt_enable() here as we would recurse in preempt_sched(). */ +int raw_irqs_disabled(void) +{ + struct vcpu_info *_vcpu; + int disabled; + + preempt_disable(); + _vcpu = &HYPERVISOR_shared_info->vcpu_info[__vcpu_id]; + disabled = (_vcpu->evtchn_upcall_mask != 0); + preempt_enable_no_resched(); + + return disabled; +} +EXPORT_SYMBOL(raw_irqs_disabled); diff --git a/arch/x86_64/kernel/k8.c b/arch/x86_64/kernel/k8.c new file mode 100644 index 000000000..6416682d3 --- /dev/null +++ b/arch/x86_64/kernel/k8.c @@ -0,0 +1,118 @@ +/* + * Shared support code for AMD K8 northbridges and derivates. + * Copyright 2006 Andi Kleen, SUSE Labs. Subject to GPLv2. + */ +#include <linux/gfp.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/spinlock.h> +#include <asm/k8.h> + +int num_k8_northbridges; +EXPORT_SYMBOL(num_k8_northbridges); + +static u32 *flush_words; + +struct pci_device_id k8_nb_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) }, + { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) }, + {} +}; +EXPORT_SYMBOL(k8_nb_ids); + +struct pci_dev **k8_northbridges; +EXPORT_SYMBOL(k8_northbridges); + +static struct pci_dev *next_k8_northbridge(struct pci_dev *dev) +{ + do { + dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); + if (!dev) + break; + } while (!pci_match_id(&k8_nb_ids[0], dev)); + return dev; +} + +int cache_k8_northbridges(void) +{ + int i; + struct pci_dev *dev; + if (num_k8_northbridges) + return 0; + + num_k8_northbridges = 0; + dev = NULL; + while ((dev = next_k8_northbridge(dev)) != NULL) + num_k8_northbridges++; + + k8_northbridges = kmalloc((num_k8_northbridges + 1) * sizeof(void *), + GFP_KERNEL); + if (!k8_northbridges) + return -ENOMEM; + + flush_words = kmalloc(num_k8_northbridges * sizeof(u32), GFP_KERNEL); + if (!flush_words) { + kfree(k8_northbridges); + return -ENOMEM; + } + + dev = NULL; + i = 0; + while ((dev = next_k8_northbridge(dev)) != NULL) { + k8_northbridges[i++] = dev; + pci_read_config_dword(dev, 0x9c, &flush_words[i]); + } + k8_northbridges[i] = NULL; + return 0; +} +EXPORT_SYMBOL_GPL(cache_k8_northbridges); + +/* Ignores subdevice/subvendor but as far as I can figure out + they're useless anyways */ +int __init early_is_k8_nb(u32 device) +{ + struct pci_device_id *id; + u32 vendor = device & 0xffff; + device >>= 16; + for (id = k8_nb_ids; id->vendor; id++) + if (vendor == id->vendor && device == id->device) + return 1; + return 0; +} + +void k8_flush_garts(void) +{ + int flushed, i; + unsigned long flags; + static DEFINE_SPINLOCK(gart_lock); + + /* Avoid races between AGP and IOMMU. In theory it's not needed + but I'm not sure if the hardware won't lose flush requests + when another is pending. This whole thing is so expensive anyways + that it doesn't matter to serialize more. -AK */ + spin_lock_irqsave(&gart_lock, flags); + flushed = 0; + for (i = 0; i < num_k8_northbridges; i++) { + pci_write_config_dword(k8_northbridges[i], 0x9c, + flush_words[i]|1); + flushed++; + } + for (i = 0; i < num_k8_northbridges; i++) { + u32 w; + /* Make sure the hardware actually executed the flush*/ + for (;;) { + pci_read_config_dword(k8_northbridges[i], + 0x9c, &w); + if (!(w & 1)) + break; + cpu_relax(); + } + } + spin_unlock_irqrestore(&gart_lock, flags); + if (!flushed) + printk("nothing to flush?\n"); +} +EXPORT_SYMBOL_GPL(k8_flush_garts); + diff --git a/arch/x86_64/kernel/pci-calgary.c b/arch/x86_64/kernel/pci-calgary.c new file mode 100644 index 000000000..61ffebb79 --- /dev/null +++ b/arch/x86_64/kernel/pci-calgary.c @@ -0,0 +1,1039 @@ +/* + * Derived from arch/powerpc/kernel/iommu.c + * + * Copyright (C) IBM Corporation, 2006 + * + * Author: Jon Mason <jdmason@us.ibm.com> + * Author: Muli Ben-Yehuda <muli@il.ibm.com> + + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/mm.h> +#include <linux/spinlock.h> +#include <linux/string.h> +#include <linux/dma-mapping.h> +#include <linux/init.h> +#include <linux/bitops.h> +#include <linux/pci_ids.h> +#include <linux/pci.h> +#include <linux/delay.h> +#include <asm/proto.h> +#include <asm/calgary.h> +#include <asm/tce.h> +#include <asm/pci-direct.h> +#include <asm/system.h> +#include <asm/dma.h> + +#define PCI_DEVICE_ID_IBM_CALGARY 0x02a1 +#define PCI_VENDOR_DEVICE_ID_CALGARY \ + (PCI_VENDOR_ID_IBM | PCI_DEVICE_ID_IBM_CALGARY << 16) + +/* we need these for register space address calculation */ +#define START_ADDRESS 0xfe000000 +#define CHASSIS_BASE 0 +#define ONE_BASED_CHASSIS_NUM 1 + +/* register offsets inside the host bridge space */ +#define PHB_CSR_OFFSET 0x0110 +#define PHB_PLSSR_OFFSET 0x0120 +#define PHB_CONFIG_RW_OFFSET 0x0160 +#define PHB_IOBASE_BAR_LOW 0x0170 +#define PHB_IOBASE_BAR_HIGH 0x0180 +#define PHB_MEM_1_LOW 0x0190 +#define PHB_MEM_1_HIGH 0x01A0 +#define PHB_IO_ADDR_SIZE 0x01B0 +#define PHB_MEM_1_SIZE 0x01C0 +#define PHB_MEM_ST_OFFSET 0x01D0 +#define PHB_AER_OFFSET 0x0200 +#define PHB_CONFIG_0_HIGH 0x0220 +#define PHB_CONFIG_0_LOW 0x0230 +#define PHB_CONFIG_0_END 0x0240 +#define PHB_MEM_2_LOW 0x02B0 +#define PHB_MEM_2_HIGH 0x02C0 +#define PHB_MEM_2_SIZE_HIGH 0x02D0 +#define PHB_MEM_2_SIZE_LOW 0x02E0 +#define PHB_DOSHOLE_OFFSET 0x08E0 + +/* PHB_CONFIG_RW */ +#define PHB_TCE_ENABLE 0x20000000 +#define PHB_SLOT_DISABLE 0x1C000000 +#define PHB_DAC_DISABLE 0x01000000 +#define PHB_MEM2_ENABLE 0x00400000 +#define PHB_MCSR_ENABLE 0x00100000 +/* TAR (Table Address Register) */ +#define TAR_SW_BITS 0x0000ffffffff800fUL +#define TAR_VALID 0x0000000000000008UL +/* CSR (Channel/DMA Status Register) */ +#define CSR_AGENT_MASK 0xffe0ffff + +#define MAX_NUM_OF_PHBS 8 /* how many PHBs in total? */ +#define MAX_NUM_CHASSIS 8 /* max number of chassis */ +#define MAX_PHB_BUS_NUM (MAX_NUM_OF_PHBS * MAX_NUM_CHASSIS * 2) /* max dev->bus->number */ +#define PHBS_PER_CALGARY 4 + +/* register offsets in Calgary's internal register space */ +static const unsigned long tar_offsets[] = { + 0x0580 /* TAR0 */, + 0x0588 /* TAR1 */, + 0x0590 /* TAR2 */, + 0x0598 /* TAR3 */ +}; + +static const unsigned long split_queue_offsets[] = { + 0x4870 /* SPLIT QUEUE 0 */, + 0x5870 /* SPLIT QUEUE 1 */, + 0x6870 /* SPLIT QUEUE 2 */, + 0x7870 /* SPLIT QUEUE 3 */ +}; + +static const unsigned long phb_offsets[] = { + 0x8000 /* PHB0 */, + 0x9000 /* PHB1 */, + 0xA000 /* PHB2 */, + 0xB000 /* PHB3 */ +}; + +static char bus_to_phb[MAX_PHB_BUS_NUM]; +void* tce_table_kva[MAX_PHB_BUS_NUM]; +unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED; +static int translate_empty_slots __read_mostly = 0; +static int calgary_detected __read_mostly = 0; + +/* + * the bitmap of PHBs the user requested that we disable + * translation on. + */ +static DECLARE_BITMAP(translation_disabled, MAX_PHB_BUS_NUM); + +static void tce_cache_blast(struct iommu_table *tbl); + +/* enable this to stress test the chip's TCE cache */ +#ifdef CONFIG_IOMMU_DEBUG +static inline void tce_cache_blast_stress(struct iommu_table *tbl) +{ + tce_cache_blast(tbl); +} +#else +static inline void tce_cache_blast_stress(struct iommu_table *tbl) +{ +} +#endif /* BLAST_TCE_CACHE_ON_UNMAP */ + +static inline unsigned int num_dma_pages(unsigned long dma, unsigned int dmalen) +{ + unsigned int npages; + + npages = PAGE_ALIGN(dma + dmalen) - (dma & PAGE_MASK); + npages >>= PAGE_SHIFT; + + return npages; +} + +static inline int translate_phb(struct pci_dev* dev) +{ + int disabled = test_bit(dev->bus->number, translation_disabled); + return !disabled; +} + +static void iommu_range_reserve(struct iommu_table *tbl, + unsigned long start_addr, unsigned int npages) +{ + unsigned long index; + unsigned long end; + + index = start_addr >> PAGE_SHIFT; + + /* bail out if we're asked to reserve a region we don't cover */ + if (index >= tbl->it_size) + return; + + end = index + npages; + if (end > tbl->it_size) /* don't go off the table */ + end = tbl->it_size; + + while (index < end) { + if (test_bit(index, tbl->it_map)) + printk(KERN_ERR "Calgary: entry already allocated at " + "0x%lx tbl %p dma 0x%lx npages %u\n", + index, tbl, start_addr, npages); + ++index; + } + set_bit_string(tbl->it_map, start_addr >> PAGE_SHIFT, npages); +} + +static unsigned long iommu_range_alloc(struct iommu_table *tbl, + unsigned int npages) +{ + unsigned long offset; + + BUG_ON(npages == 0); + + offset = find_next_zero_string(tbl->it_map, tbl->it_hint, + tbl->it_size, npages); + if (offset == ~0UL) { + tce_cache_blast(tbl); + offset = find_next_zero_string(tbl->it_map, 0, + tbl->it_size, npages); + if (offset == ~0UL) { + printk(KERN_WARNING "Calgary: IOMMU full.\n"); + if (panic_on_overflow) + panic("Calgary: fix the allocator.\n"); + else + return bad_dma_address; + } + } + + set_bit_string(tbl->it_map, offset, npages); + tbl->it_hint = offset + npages; + BUG_ON(tbl->it_hint > tbl->it_size); + + return offset; +} + +static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *vaddr, + unsigned int npages, int direction) +{ + unsigned long entry, flags; + dma_addr_t ret = bad_dma_address; + + spin_lock_irqsave(&tbl->it_lock, flags); + + entry = iommu_range_alloc(tbl, npages); + + if (unlikely(entry == bad_dma_address)) + goto error; + + /* set the return dma address */ + ret = (entry << PAGE_SHIFT) | ((unsigned long)vaddr & ~PAGE_MASK); + + /* put the TCEs in the HW table */ + tce_build(tbl, entry, npages, (unsigned long)vaddr & PAGE_MASK, + direction); + + spin_unlock_irqrestore(&tbl->it_lock, flags); + + return ret; + +error: + spin_unlock_irqrestore(&tbl->it_lock, flags); + printk(KERN_WARNING "Calgary: failed to allocate %u pages in " + "iommu %p\n", npages, tbl); + return bad_dma_address; +} + +static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, + unsigned int npages) +{ + unsigned long entry; + unsigned long i; + + entry = dma_addr >> PAGE_SHIFT; + + BUG_ON(entry + npages > tbl->it_size); + + tce_free(tbl, entry, npages); + + for (i = 0; i < npages; ++i) { + if (!test_bit(entry + i, tbl->it_map)) + printk(KERN_ERR "Calgary: bit is off at 0x%lx " + "tbl %p dma 0x%Lx entry 0x%lx npages %u\n", + entry + i, tbl, dma_addr, entry, npages); + } + + __clear_bit_string(tbl->it_map, entry, npages); + + tce_cache_blast_stress(tbl); +} + +static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, + unsigned int npages) +{ + unsigned long flags; + + spin_lock_irqsave(&tbl->it_lock, flags); + + __iommu_free(tbl, dma_addr, npages); + + spin_unlock_irqrestore(&tbl->it_lock, flags); +} + +static void __calgary_unmap_sg(struct iommu_table *tbl, + struct scatterlist *sglist, int nelems, int direction) +{ + while (nelems--) { + unsigned int npages; + dma_addr_t dma = sglist->dma_address; + unsigned int dmalen = sglist->dma_length; + + if (dmalen == 0) + break; + + npages = num_dma_pages(dma, dmalen); + __iommu_free(tbl, dma, npages); + sglist++; + } +} + +void calgary_unmap_sg(struct device *dev, struct scatterlist *sglist, + int nelems, int direction) +{ + unsigned long flags; + struct iommu_table *tbl = to_pci_dev(dev)->bus->self->sysdata; + + if (!translate_phb(to_pci_dev(dev))) + return; + + spin_lock_irqsave(&tbl->it_lock, flags); + + __calgary_unmap_sg(tbl, sglist, nelems, direction); + + spin_unlock_irqrestore(&tbl->it_lock, flags); +} + +static int calgary_nontranslate_map_sg(struct device* dev, + struct scatterlist *sg, int nelems, int direction) +{ + int i; + + for (i = 0; i < nelems; i++ ) { + struct scatterlist *s = &sg[i]; + BUG_ON(!s->page); + s->dma_address = virt_to_bus(page_address(s->page) +s->offset); + s->dma_length = s->length; + } + return nelems; +} + +int calgary_map_sg(struct device *dev, struct scatterlist *sg, + int nelems, int direction) +{ + struct iommu_table *tbl = to_pci_dev(dev)->bus->self->sysdata; + unsigned long flags; + unsigned long vaddr; + unsigned int npages; + unsigned long entry; + int i; + + if (!translate_phb(to_pci_dev(dev))) + return calgary_nontranslate_map_sg(dev, sg, nelems, direction); + + spin_lock_irqsave(&tbl->it_lock, flags); + + for (i = 0; i < nelems; i++ ) { + struct scatterlist *s = &sg[i]; + BUG_ON(!s->page); + + vaddr = (unsigned long)page_address(s->page) + s->offset; + npages = num_dma_pages(vaddr, s->length); + + entry = iommu_range_alloc(tbl, npages); + if (entry == bad_dma_address) { + /* makes sure unmap knows to stop */ + s->dma_length = 0; + goto error; + } + + s->dma_address = (entry << PAGE_SHIFT) | s->offset; + + /* insert into HW table */ + tce_build(tbl, entry, npages, vaddr & PAGE_MASK, + direction); + + s->dma_length = s->length; + } + + spin_unlock_irqrestore(&tbl->it_lock, flags); + + return nelems; +error: + __calgary_unmap_sg(tbl, sg, nelems, direction); + for (i = 0; i < nelems; i++) { + sg[i].dma_address = bad_dma_address; + sg[i].dma_length = 0; + } + spin_unlock_irqrestore(&tbl->it_lock, flags); + return 0; +} + +dma_addr_t calgary_map_single(struct device *dev, void *vaddr, + size_t size, int direction) +{ + dma_addr_t dma_handle = bad_dma_address; + unsigned long uaddr; + unsigned int npages; + struct iommu_table *tbl = to_pci_dev(dev)->bus->self->sysdata; + + uaddr = (unsigned long)vaddr; + npages = num_dma_pages(uaddr, size); + + if (translate_phb(to_pci_dev(dev))) + dma_handle = iommu_alloc(tbl, vaddr, npages, direction); + else + dma_handle = virt_to_bus(vaddr); + + return dma_handle; +} + +void calgary_unmap_single(struct device *dev, dma_addr_t dma_handle, + size_t size, int direction) +{ + struct iommu_table *tbl = to_pci_dev(dev)->bus->self->sysdata; + unsigned int npages; + + if (!translate_phb(to_pci_dev(dev))) + return; + + npages = num_dma_pages(dma_handle, size); + iommu_free(tbl, dma_handle, npages); +} + +void* calgary_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t flag) +{ + void *ret = NULL; + dma_addr_t mapping; + unsigned int npages, order; + struct iommu_table *tbl; + + tbl = to_pci_dev(dev)->bus->self->sysdata; + + size = PAGE_ALIGN(size); /* size rounded up to full pages */ + npages = size >> PAGE_SHIFT; + order = get_order(size); + + /* alloc enough pages (and possibly more) */ + ret = (void *)__get_free_pages(flag, order); + if (!ret) + goto error; + memset(ret, 0, size); + + if (translate_phb(to_pci_dev(dev))) { + /* set up tces to cover the allocated range */ + mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL); + if (mapping == bad_dma_address) + goto free; + + *dma_handle = mapping; + } else /* non translated slot */ + *dma_handle = virt_to_bus(ret); + + return ret; + +free: + free_pages((unsigned long)ret, get_order(size)); + ret = NULL; +error: + return ret; +} + +static struct dma_mapping_ops calgary_dma_ops = { + .alloc_coherent = calgary_alloc_coherent, + .map_single = calgary_map_single, + .unmap_single = calgary_unmap_single, + .map_sg = calgary_map_sg, + .unmap_sg = calgary_unmap_sg, +}; + +static inline int busno_to_phbid(unsigned char num) +{ + return bus_to_phb[num]; +} + +static inline unsigned long split_queue_offset(unsigned char num) +{ + size_t idx = busno_to_phbid(num); + + return split_queue_offsets[idx]; +} + +static inline unsigned long tar_offset(unsigned char num) +{ + size_t idx = busno_to_phbid(num); + + return tar_offsets[idx]; +} + +static inline unsigned long phb_offset(unsigned char num) +{ + size_t idx = busno_to_phbid(num); + + return phb_offsets[idx]; +} + +static inline void __iomem* calgary_reg(void __iomem *bar, unsigned long offset) +{ + unsigned long target = ((unsigned long)bar) | offset; + return (void __iomem*)target; +} + +static void tce_cache_blast(struct iommu_table *tbl) +{ + u64 val; + u32 aer; + int i = 0; + void __iomem *bbar = tbl->bbar; + void __iomem *target; + + /* disable arbitration on the bus */ + target = calgary_reg(bbar, phb_offset(tbl->it_busno) | PHB_AER_OFFSET); + aer = readl(target); + writel(0, target); + + /* read plssr to ensure it got there */ + target = calgary_reg(bbar, phb_offset(tbl->it_busno) | PHB_PLSSR_OFFSET); + val = readl(target); + + /* poll split queues until all DMA activity is done */ + target = calgary_reg(bbar, split_queue_offset(tbl->it_busno)); + do { + val = readq(target); + i++; + } while ((val & 0xff) != 0xff && i < 100); + if (i == 100) + printk(KERN_WARNING "Calgary: PCI bus not quiesced, " + "continuing anyway\n"); + + /* invalidate TCE cache */ + target = calgary_reg(bbar, tar_offset(tbl->it_busno)); + writeq(tbl->tar_val, target); + + /* enable arbitration */ + target = calgary_reg(bbar, phb_offset(tbl->it_busno) | PHB_AER_OFFSET); + writel(aer, target); + (void)readl(target); /* flush */ +} + +static void __init calgary_reserve_mem_region(struct pci_dev *dev, u64 start, + u64 limit) +{ + unsigned int numpages; + + limit = limit | 0xfffff; + limit++; + + numpages = ((limit - start) >> PAGE_SHIFT); + iommu_range_reserve(dev->sysdata, start, numpages); +} + +static void __init calgary_reserve_peripheral_mem_1(struct pci_dev *dev) +{ + void __iomem *target; + u64 low, high, sizelow; + u64 start, limit; + struct iommu_table *tbl = dev->sysdata; + unsigned char busnum = dev->bus->number; + void __iomem *bbar = tbl->bbar; + + /* peripheral MEM_1 region */ + target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_1_LOW); + low = be32_to_cpu(readl(target)); + target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_1_HIGH); + high = be32_to_cpu(readl(target)); + target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_1_SIZE); + sizelow = be32_to_cpu(readl(target)); + + start = (high << 32) | low; + limit = sizelow; + + calgary_reserve_mem_region(dev, start, limit); +} + +static void __init calgary_reserve_peripheral_mem_2(struct pci_dev *dev) +{ + void __iomem *target; + u32 val32; + u64 low, high, sizelow, sizehigh; + u64 start, limit; + struct iommu_table *tbl = dev->sysdata; + unsigned char busnum = dev->bus->number; + void __iomem *bbar = tbl->bbar; + + /* is it enabled? */ + target = calgary_reg(bbar, phb_offset(busnum) | PHB_CONFIG_RW_OFFSET); + val32 = be32_to_cpu(readl(target)); + if (!(val32 & PHB_MEM2_ENABLE)) + return; + + target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_2_LOW); + low = be32_to_cpu(readl(target)); + target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_2_HIGH); + high = be32_to_cpu(readl(target)); + target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_2_SIZE_LOW); + sizelow = be32_to_cpu(readl(target)); + target = calgary_reg(bbar, phb_offset(busnum) | PHB_MEM_2_SIZE_HIGH); + sizehigh = be32_to_cpu(readl(target)); + + start = (high << 32) | low; + limit = (sizehigh << 32) | sizelow; + + calgary_reserve_mem_region(dev, start, limit); +} + +/* + * some regions of the IO address space do not get translated, so we + * must not give devices IO addresses in those regions. The regions + * are the 640KB-1MB region and the two PCI peripheral memory holes. + * Reserve all of them in the IOMMU bitmap to avoid giving them out + * later. + */ +static void __init calgary_reserve_regions(struct pci_dev *dev) +{ + unsigned int npages; + void __iomem *bbar; + unsigned char busnum; + u64 start; + struct iommu_table *tbl = dev->sysdata; + + bbar = tbl->bbar; + busnum = dev->bus->number; + + /* reserve bad_dma_address in case it's a legal address */ + iommu_range_reserve(tbl, bad_dma_address, 1); + + /* avoid the BIOS/VGA first 640KB-1MB region */ + start = (640 * 1024); + npages = ((1024 - 640) * 1024) >> PAGE_SHIFT; + iommu_range_reserve(tbl, start, npages); + + /* reserve the two PCI peripheral memory regions in IO space */ + calgary_reserve_peripheral_mem_1(dev); + calgary_reserve_peripheral_mem_2(dev); +} + +static int __init calgary_setup_tar(struct pci_dev *dev, void __iomem *bbar) +{ + u64 val64; + u64 table_phys; + void __iomem *target; + int ret; + struct iommu_table *tbl; + + /* build TCE tables for each PHB */ + ret = build_tce_table(dev, bbar); + if (ret) + return ret; + + calgary_reserve_regions(dev); + + /* set TARs for each PHB */ + target = calgary_reg(bbar, tar_offset(dev->bus->number)); + val64 = be64_to_cpu(readq(target)); + + /* zero out all TAR bits under sw control */ + val64 &= ~TAR_SW_BITS; + + tbl = dev->sysdata; + table_phys = (u64)__pa(tbl->it_base); + val64 |= table_phys; + + BUG_ON(specified_table_size > TCE_TABLE_SIZE_8M); + val64 |= (u64) specified_table_size; + + tbl->tar_val = cpu_to_be64(val64); + writeq(tbl->tar_val, target); + readq(target); /* flush */ + + return 0; +} + +static void __init calgary_free_tar(struct pci_dev *dev) +{ + u64 val64; + struct iommu_table *tbl = dev->sysdata; + void __iomem *target; + + target = calgary_reg(tbl->bbar, tar_offset(dev->bus->number)); + val64 = be64_to_cpu(readq(target)); + val64 &= ~TAR_SW_BITS; + writeq(cpu_to_be64(val64), target); + readq(target); /* flush */ + + kfree(tbl); + dev->sysdata = NULL; +} + +static void calgary_watchdog(unsigned long data) +{ + struct pci_dev *dev = (struct pci_dev *)data; + struct iommu_table *tbl = dev->sysdata; + void __iomem *bbar = tbl->bbar; + u32 val32; + void __iomem *target; + + target = calgary_reg(bbar, phb_offset(tbl->it_busno) | PHB_CSR_OFFSET); + val32 = be32_to_cpu(readl(target)); + + /* If no error, the agent ID in the CSR is not valid */ + if (val32 & CSR_AGENT_MASK) { + printk(KERN_EMERG "calgary_watchdog: DMA error on bus %d, " + "CSR = %#x\n", dev->bus->number, val32); + writel(0, target); + + /* Disable bus that caused the error */ + target = calgary_reg(bbar, phb_offset(tbl->it_busno) | + PHB_CONFIG_RW_OFFSET); + val32 = be32_to_cpu(readl(target)); + val32 |= PHB_SLOT_DISABLE; + writel(cpu_to_be32(val32), target); + readl(target); /* flush */ + } else { + /* Reset the timer */ + mod_timer(&tbl->watchdog_timer, jiffies + 2 * HZ); + } +} + +static void __init calgary_enable_translation(struct pci_dev *dev) +{ + u32 val32; + unsigned char busnum; + void __iomem *target; + void __iomem *bbar; + struct iommu_table *tbl; + + busnum = dev->bus->number; + tbl = dev->sysdata; + bbar = tbl->bbar; + + /* enable TCE in PHB Config Register */ + target = calgary_reg(bbar, phb_offset(busnum) | PHB_CONFIG_RW_OFFSET); + val32 = be32_to_cpu(readl(target)); + val32 |= PHB_TCE_ENABLE | PHB_DAC_DISABLE | PHB_MCSR_ENABLE; + + printk(KERN_INFO "Calgary: enabling translation on PHB %d\n", busnum); + printk(KERN_INFO "Calgary: errant DMAs will now be prevented on this " + "bus.\n"); + + writel(cpu_to_be32(val32), target); + readl(target); /* flush */ + + init_timer(&tbl->watchdog_timer); + tbl->watchdog_timer.function = &calgary_watchdog; + tbl->watchdog_timer.data = (unsigned long)dev; + mod_timer(&tbl->watchdog_timer, jiffies); +} + +static void __init calgary_disable_translation(struct pci_dev *dev) +{ + u32 val32; + unsigned char busnum; + void __iomem *target; + void __iomem *bbar; + struct iommu_table *tbl; + + busnum = dev->bus->number; + tbl = dev->sysdata; + bbar = tbl->bbar; + + /* disable TCE in PHB Config Register */ + target = calgary_reg(bbar, phb_offset(busnum) | PHB_CONFIG_RW_OFFSET); + val32 = be32_to_cpu(readl(target)); + val32 &= ~(PHB_TCE_ENABLE | PHB_DAC_DISABLE | PHB_MCSR_ENABLE); + + printk(KERN_INFO "Calgary: disabling translation on PHB %d!\n", busnum); + writel(cpu_to_be32(val32), target); + readl(target); /* flush */ + + del_timer_sync(&tbl->watchdog_timer); +} + +static inline unsigned int __init locate_register_space(struct pci_dev *dev) +{ + int rionodeid; + u32 address; + + /* + * Each Calgary has four busses. The first four busses (first Calgary) + * have RIO node ID 2, then the next four (second Calgary) have RIO + * node ID 3, the next four (third Calgary) have node ID 2 again, etc. + * We use a gross hack - relying on the dev->bus->number ordering, + * modulo 14 - to decide which Calgary a given bus is on. Busses 0, 1, + * 2 and 4 are on the first Calgary (id 2), 6, 8, a and c are on the + * second (id 3), and then it repeats modulo 14. + */ + rionodeid = (dev->bus->number % 14 > 4) ? 3 : 2; + /* + * register space address calculation as follows: + * FE0MB-8MB*OneBasedChassisNumber+1MB*(RioNodeId-ChassisBase) + * ChassisBase is always zero for x366/x260/x460 + * RioNodeId is 2 for first Calgary, 3 for second Calgary + */ + address = START_ADDRESS - + (0x800000 * (ONE_BASED_CHASSIS_NUM + dev->bus->number / 14)) + + (0x100000) * (rionodeid - CHASSIS_BASE); + return address; +} + +static int __init calgary_init_one_nontraslated(struct pci_dev *dev) +{ + dev->sysdata = NULL; + dev->bus->self = dev; + + return 0; +} + +static int __init calgary_init_one(struct pci_dev *dev) +{ + u32 address; + void __iomem *bbar; + int ret; + + address = locate_register_space(dev); + /* map entire 1MB of Calgary config space */ + bbar = ioremap_nocache(address, 1024 * 1024); + if (!bbar) { + ret = -ENODATA; + goto done; + } + + ret = calgary_setup_tar(dev, bbar); + if (ret) + goto iounmap; + + dev->bus->self = dev; + calgary_enable_translation(dev); + + return 0; + +iounmap: + iounmap(bbar); +done: + return ret; +} + +static int __init calgary_init(void) +{ + int i, ret = -ENODEV; + struct pci_dev *dev = NULL; + + for (i = 0; i < MAX_PHB_BUS_NUM; i++) { + dev = pci_get_device(PCI_VENDOR_ID_IBM, + PCI_DEVICE_ID_IBM_CALGARY, + dev); + if (!dev) + break; + if (!translate_phb(dev)) { + calgary_init_one_nontraslated(dev); + continue; + } + if (!tce_table_kva[dev->bus->number] && !translate_empty_slots) { + pci_dev_put(dev); + continue; + } + ret = calgary_init_one(dev); + if (ret) + goto error; + } + + return ret; + +error: + for (i--; i >= 0; i--) { + dev = pci_find_device_reverse(PCI_VENDOR_ID_IBM, + PCI_DEVICE_ID_IBM_CALGARY, + dev); + if (!translate_phb(dev)) { + pci_dev_put(dev); + continue; + } + if (!tce_table_kva[dev->bus->number] && !translate_empty_slots) + continue; + calgary_disable_translation(dev); + calgary_free_tar(dev); + pci_dev_put(dev); + } + + return ret; +} + +static inline int __init determine_tce_table_size(u64 ram) +{ + int ret; + + if (specified_table_size != TCE_TABLE_SIZE_UNSPECIFIED) + return specified_table_size; + + /* + * Table sizes are from 0 to 7 (TCE_TABLE_SIZE_64K to + * TCE_TABLE_SIZE_8M). Table size 0 has 8K entries and each + * larger table size has twice as many entries, so shift the + * max ram address by 13 to divide by 8K and then look at the + * order of the result to choose between 0-7. + */ + ret = get_order(ram >> 13); + if (ret > TCE_TABLE_SIZE_8M) + ret = TCE_TABLE_SIZE_8M; + + return ret; +} + +void __init detect_calgary(void) +{ + u32 val; + int bus; + void *tbl; + int calgary_found = 0; + int phb = -1; + + /* + * if the user specified iommu=off or iommu=soft or we found + * another HW IOMMU already, bail out. + */ + if (swiotlb || no_iommu || iommu_detected) + return; + + specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE); + + for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) { + int dev; + + tce_table_kva[bus] = NULL; + bus_to_phb[bus] = -1; + + if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY) + continue; + + /* + * There are 4 PHBs per Calgary chip. Set phb to which phb (0-3) + * it is connected to releative to the clagary chip. + */ + phb = (phb + 1) % PHBS_PER_CALGARY; + + if (test_bit(bus, translation_disabled)) { + printk(KERN_INFO "Calgary: translation is disabled for " + "PHB 0x%x\n", bus); + /* skip this phb, don't allocate a tbl for it */ + continue; + } + /* + * Scan the slots of the PCI bus to see if there is a device present. + * The parent bus will be the zero-ith device, so start at 1. + */ + for (dev = 1; dev < 8; dev++) { + val = read_pci_config(bus, dev, 0, 0); + if (val != 0xffffffff || translate_empty_slots) { + tbl = alloc_tce_table(); + if (!tbl) + goto cleanup; + tce_table_kva[bus] = tbl; + bus_to_phb[bus] = phb; + calgary_found = 1; + break; + } + } + } + + if (calgary_found) { + iommu_detected = 1; + calgary_detected = 1; + printk(KERN_INFO "PCI-DMA: Calgary IOMMU detected. " + "TCE table spec is %d.\n", specified_table_size); + } + return; + +cleanup: + for (--bus; bus >= 0; --bus) + if (tce_table_kva[bus]) + free_tce_table(tce_table_kva[bus]); +} + +int __init calgary_iommu_init(void) +{ + int ret; + + if (no_iommu || swiotlb) + return -ENODEV; + + if (!calgary_detected) + return -ENODEV; + + /* ok, we're trying to use Calgary - let's roll */ + printk(KERN_INFO "PCI-DMA: Using Calgary IOMMU\n"); + + ret = calgary_init(); + if (ret) { + printk(KERN_ERR "PCI-DMA: Calgary init failed %d, " + "falling back to no_iommu\n", ret); + if (end_pfn > MAX_DMA32_PFN) + printk(KERN_ERR "WARNING more than 4GB of memory, " + "32bit PCI may malfunction.\n"); + return ret; + } + + force_iommu = 1; + dma_ops = &calgary_dma_ops; + + return 0; +} + +static int __init calgary_parse_options(char *p) +{ + unsigned int bridge; + size_t len; + char* endp; + + while (*p) { + if (!strncmp(p, "64k", 3)) + specified_table_size = TCE_TABLE_SIZE_64K; + else if (!strncmp(p, "128k", 4)) + specified_table_size = TCE_TABLE_SIZE_128K; + else if (!strncmp(p, "256k", 4)) + specified_table_size = TCE_TABLE_SIZE_256K; + else if (!strncmp(p, "512k", 4)) + specified_table_size = TCE_TABLE_SIZE_512K; + else if (!strncmp(p, "1M", 2)) + specified_table_size = TCE_TABLE_SIZE_1M; + else if (!strncmp(p, "2M", 2)) + specified_table_size = TCE_TABLE_SIZE_2M; + else if (!strncmp(p, "4M", 2)) + specified_table_size = TCE_TABLE_SIZE_4M; + else if (!strncmp(p, "8M", 2)) + specified_table_size = TCE_TABLE_SIZE_8M; + + len = strlen("translate_empty_slots"); + if (!strncmp(p, "translate_empty_slots", len)) + translate_empty_slots = 1; + + len = strlen("disable"); + if (!strncmp(p, "disable", len)) { + p += len; + if (*p == '=') + ++p; + if (*p == '\0') + break; + bridge = simple_strtol(p, &endp, 0); + if (p == endp) + break; + + if (bridge < MAX_PHB_BUS_NUM) { + printk(KERN_INFO "Calgary: disabling " + "translation for PHB 0x%x\n", bridge); + set_bit(bridge, translation_disabled); + } + } + + p = strpbrk(p, ","); + if (!p) + break; + + p++; /* skip ',' */ + } + return 1; +} +__setup("calgary=", calgary_parse_options); diff --git a/arch/x86_64/kernel/stacktrace.c b/arch/x86_64/kernel/stacktrace.c new file mode 100644 index 000000000..6026b31d0 --- /dev/null +++ b/arch/x86_64/kernel/stacktrace.c @@ -0,0 +1,55 @@ +/* + * arch/x86_64/kernel/stacktrace.c + * + * Stack trace management functions + * + * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + */ +#include <linux/sched.h> +#include <linux/stacktrace.h> +#include <linux/module.h> +#include <asm/stacktrace.h> + +static void save_stack_warning(void *data, char *msg) +{ +} + +static void +save_stack_warning_symbol(void *data, char *msg, unsigned long symbol) +{ +} + +static int save_stack_stack(void *data, char *name) +{ + struct stack_trace *trace = (struct stack_trace *)data; + return trace->all_contexts ? 0 : -1; +} + +static void save_stack_address(void *data, unsigned long addr) +{ + struct stack_trace *trace = (struct stack_trace *)data; + if (trace->skip > 0) { + trace->skip--; + return; + } + if (trace->nr_entries < trace->max_entries - 1) + trace->entries[trace->nr_entries++] = addr; +} + +static struct stacktrace_ops save_stack_ops = { + .warning = save_stack_warning, + .warning_symbol = save_stack_warning_symbol, + .stack = save_stack_stack, + .address = save_stack_address, +}; + +/* + * Save stack-backtrace addresses into a stack_trace buffer. + */ +void save_stack_trace(struct stack_trace *trace, struct task_struct *task) +{ + dump_trace(task, NULL, NULL, &save_stack_ops, trace); + trace->entries[trace->nr_entries++] = ULONG_MAX; +} +EXPORT_SYMBOL(save_stack_trace); + diff --git a/arch/x86_64/kernel/tce.c b/arch/x86_64/kernel/tce.c new file mode 100644 index 000000000..1affe8cab --- /dev/null +++ b/arch/x86_64/kernel/tce.c @@ -0,0 +1,201 @@ +/* + * Derived from arch/powerpc/platforms/pseries/iommu.c + * + * Copyright (C) IBM Corporation, 2006 + * + * Author: Jon Mason <jdmason@us.ibm.com> + * Author: Muli Ben-Yehuda <muli@il.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/mm.h> +#include <linux/spinlock.h> +#include <linux/string.h> +#include <linux/pci.h> +#include <linux/dma-mapping.h> +#include <linux/bootmem.h> +#include <asm/tce.h> +#include <asm/calgary.h> +#include <asm/proto.h> + +/* flush a tce at 'tceaddr' to main memory */ +static inline void flush_tce(void* tceaddr) +{ + /* a single tce can't cross a cache line */ + if (cpu_has_clflush) + asm volatile("clflush (%0)" :: "r" (tceaddr)); + else + asm volatile("wbinvd":::"memory"); +} + +void tce_build(struct iommu_table *tbl, unsigned long index, + unsigned int npages, unsigned long uaddr, int direction) +{ + u64* tp; + u64 t; + u64 rpn; + + t = (1 << TCE_READ_SHIFT); + if (direction != DMA_TO_DEVICE) + t |= (1 << TCE_WRITE_SHIFT); + + tp = ((u64*)tbl->it_base) + index; + + while (npages--) { + rpn = (virt_to_bus((void*)uaddr)) >> PAGE_SHIFT; + t &= ~TCE_RPN_MASK; + t |= (rpn << TCE_RPN_SHIFT); + + *tp = cpu_to_be64(t); + flush_tce(tp); + + uaddr += PAGE_SIZE; + tp++; + } +} + +void tce_free(struct iommu_table *tbl, long index, unsigned int npages) +{ + u64* tp; + + tp = ((u64*)tbl->it_base) + index; + + while (npages--) { + *tp = cpu_to_be64(0); + flush_tce(tp); + tp++; + } +} + +static inline unsigned int table_size_to_number_of_entries(unsigned char size) +{ + /* + * size is the order of the table, 0-7 + * smallest table is 8K entries, so shift result by 13 to + * multiply by 8K + */ + return (1 << size) << 13; +} + +static int tce_table_setparms(struct pci_dev *dev, struct iommu_table *tbl) +{ + unsigned int bitmapsz; + unsigned long bmppages; + int ret; + + tbl->it_busno = dev->bus->number; + + /* set the tce table size - measured in entries */ + tbl->it_size = table_size_to_number_of_entries(specified_table_size); + + tbl->it_base = (unsigned long)tce_table_kva[dev->bus->number]; + if (!tbl->it_base) { + printk(KERN_ERR "Calgary: iommu_table_setparms: " + "no table allocated?!\n"); + ret = -ENOMEM; + goto done; + } + + /* + * number of bytes needed for the bitmap size in number of + * entries; we need one bit per entry + */ + bitmapsz = tbl->it_size / BITS_PER_BYTE; + bmppages = __get_free_pages(GFP_KERNEL, get_order(bitmapsz)); + if (!bmppages) { + printk(KERN_ERR "Calgary: cannot allocate bitmap\n"); + ret = -ENOMEM; + goto done; + } + + tbl->it_map = (unsigned long*)bmppages; + + memset(tbl->it_map, 0, bitmapsz); + + tbl->it_hint = 0; + + spin_lock_init(&tbl->it_lock); + + return 0; + +done: + return ret; +} + +int build_tce_table(struct pci_dev *dev, void __iomem *bbar) +{ + struct iommu_table *tbl; + int ret; + + if (dev->sysdata) { + printk(KERN_ERR "Calgary: dev %p has sysdata %p\n", + dev, dev->sysdata); + BUG(); + } + + tbl = kzalloc(sizeof(struct iommu_table), GFP_KERNEL); + if (!tbl) { + printk(KERN_ERR "Calgary: error allocating iommu_table\n"); + ret = -ENOMEM; + goto done; + } + + ret = tce_table_setparms(dev, tbl); + if (ret) + goto free_tbl; + + tce_free(tbl, 0, tbl->it_size); + + tbl->bbar = bbar; + + /* + * NUMA is already using the bus's sysdata pointer, so we use + * the bus's pci_dev's sysdata instead. + */ + dev->sysdata = tbl; + + return 0; + +free_tbl: + kfree(tbl); +done: + return ret; +} + +void* alloc_tce_table(void) +{ + unsigned int size; + + size = table_size_to_number_of_entries(specified_table_size); + size *= TCE_ENTRY_SIZE; + + return __alloc_bootmem_low(size, size, 0); +} + +void free_tce_table(void *tbl) +{ + unsigned int size; + + if (!tbl) + return; + + size = table_size_to_number_of_entries(specified_table_size); + size *= TCE_ENTRY_SIZE; + + free_bootmem(__pa(tbl), size); +} diff --git a/arch/x86_64/lib/rwlock.S b/arch/x86_64/lib/rwlock.S new file mode 100644 index 000000000..0cde1f807 --- /dev/null +++ b/arch/x86_64/lib/rwlock.S @@ -0,0 +1,38 @@ +/* Slow paths of read/write spinlocks. */ + +#include <linux/linkage.h> +#include <asm/rwlock.h> +#include <asm/alternative-asm.i> +#include <asm/dwarf2.h> + +/* rdi: pointer to rwlock_t */ +ENTRY(__write_lock_failed) + CFI_STARTPROC + LOCK_PREFIX + addl $RW_LOCK_BIAS,(%rdi) +1: rep + nop + cmpl $RW_LOCK_BIAS,(%rdi) + jne 1b + LOCK_PREFIX + subl $RW_LOCK_BIAS,(%rdi) + jnz __write_lock_failed + ret + CFI_ENDPROC +END(__write_lock_failed) + +/* rdi: pointer to rwlock_t */ +ENTRY(__read_lock_failed) + CFI_STARTPROC + LOCK_PREFIX + incl (%rdi) +1: rep + nop + cmpl $1,(%rdi) + js 1b + LOCK_PREFIX + decl (%rdi) + js __read_lock_failed + ret + CFI_ENDPROC +END(__read_lock_failed) diff --git a/configs/kernel-2.6.18-i586-smp.config b/configs/kernel-2.6.18-i586-smp.config new file mode 100644 index 000000000..224fc97d5 --- /dev/null +++ b/configs/kernel-2.6.18-i586-smp.config @@ -0,0 +1,3368 @@ +# i386 +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:39 2006 +# +CONFIG_X86_32=y +CONFIG_GENERIC_TIME=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_X86=y +CONFIG_MMU=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_DMI=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Processor type and features +# +CONFIG_SMP=y +CONFIG_X86_PC=y +# CONFIG_X86_XEN is not set +# CONFIG_X86_ELAN is not set +# CONFIG_X86_VOYAGER is not set +# CONFIG_X86_NUMAQ is not set +# CONFIG_X86_SUMMIT is not set +# CONFIG_X86_BIGSMP is not set +# CONFIG_X86_VISWS is not set +# CONFIG_X86_GENERICARCH is not set +# CONFIG_X86_ES7000 is not set +# CONFIG_M386 is not set +# CONFIG_M486 is not set +CONFIG_M586=y +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set +# CONFIG_M686 is not set +# CONFIG_MPENTIUMII is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MEFFICEON is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MGEODEGX1 is not set +# CONFIG_MGEODE_LX is not set +# CONFIG_MCYRIXIII is not set +# CONFIG_MVIAC3_2 is not set +CONFIG_X86_GENERIC=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_XADD=y +CONFIG_X86_L1_CACHE_SHIFT=7 +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_X86_PPRO_FENCE=y +CONFIG_X86_F00F_BUG=y +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_INVLPG=y +CONFIG_X86_BSWAP=y +CONFIG_X86_POPAD_OK=y +CONFIG_X86_CMPXCHG64=y +CONFIG_X86_ALIGNMENT_16=y +CONFIG_X86_INTEL_USERCOPY=y +CONFIG_HPET_TIMER=y +CONFIG_HPET_EMULATE_RTC=y +CONFIG_NR_CPUS=2 +CONFIG_SCHED_SMT=y +CONFIG_SCHED_MC=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_X86_LOCAL_APIC=y +CONFIG_X86_APIC_AUTO=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_MCE=y +# CONFIG_X86_MCE_NONFATAL is not set +# CONFIG_X86_MCE_P4THERMAL is not set +CONFIG_VM86=y +# CONFIG_TOSHIBA is not set +# CONFIG_I8K is not set +# CONFIG_X86_REBOOTFIXUPS is not set +# CONFIG_MICROCODE is not set +CONFIG_X86_MSR=m +CONFIG_X86_CPUID=m +# CONFIG_SWIOTLB is not set + +# +# Firmware Drivers +# +CONFIG_EDD=m +CONFIG_EFI_VARS=y +# CONFIG_DELL_RBU is not set +# CONFIG_DCDBAS is not set +# CONFIG_NOHIGHMEM is not set +CONFIG_HIGHMEM4G=y +# CONFIG_HIGHMEM64G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_HIGHMEM=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_SPARSEMEM_STATIC=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_RESOURCES_64BIT=y +CONFIG_HIGHPTE=y +# CONFIG_MATH_EMULATION is not set +CONFIG_MTRR=y +CONFIG_EFI=y +# CONFIG_IRQBALANCE is not set +CONFIG_BOOT_IOREMAP=y +CONFIG_REGPARM=y +# CONFIG_SECCOMP is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_KEXEC=y +# CONFIG_CRASH_DUMP is not set +CONFIG_PHYSICAL_START=0x400000 +CONFIG_HOTPLUG_CPU=y +# CONFIG_COMPAT_VDSO is not set +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y + +# +# Power management options (ACPI, APM) +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +CONFIG_SOFTWARE_SUSPEND=y +CONFIG_PM_STD_PARTITION="" +CONFIG_SUSPEND_SMP=y + +# +# ACPI (Advanced Configuration and Power Interface) Support +# +CONFIG_ACPI=y +CONFIG_ACPI_SLEEP=y +CONFIG_ACPI_SLEEP_PROC_FS=y +# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set +CONFIG_ACPI_AC=m +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_VIDEO=m +# CONFIG_ACPI_HOTKEY is not set +CONFIG_ACPI_FAN=y +CONFIG_ACPI_DOCK=m +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_THERMAL=y +# CONFIG_ACPI_ASUS is not set +# CONFIG_ACPI_IBM is not set +# CONFIG_ACPI_TOSHIBA is not set +CONFIG_ACPI_BLACKLIST_YEAR=1999 +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_EC=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_X86_PM_TIMER=y +CONFIG_ACPI_CONTAINER=y +CONFIG_ACPI_SBS=m + +# +# APM (Advanced Power Management) BIOS Support +# +CONFIG_APM=y +# CONFIG_APM_IGNORE_USER_SUSPEND is not set +# CONFIG_APM_DO_ENABLE is not set +CONFIG_APM_CPU_IDLE=y +# CONFIG_APM_DISPLAY_BLANK is not set +CONFIG_APM_RTC_IS_GMT=y +# CONFIG_APM_ALLOW_INTS is not set +# CONFIG_APM_REAL_MODE_POWER_OFF is not set + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=m +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m + +# +# CPUFreq processor drivers +# +CONFIG_X86_ACPI_CPUFREQ=m +# CONFIG_X86_POWERNOW_K6 is not set +# CONFIG_X86_POWERNOW_K7 is not set +# CONFIG_X86_POWERNOW_K8 is not set +# CONFIG_X86_GX_SUSPMOD is not set +# CONFIG_X86_SPEEDSTEP_CENTRINO is not set +# CONFIG_X86_SPEEDSTEP_ICH is not set +# CONFIG_X86_SPEEDSTEP_SMI is not set +# CONFIG_X86_P4_CLOCKMOD is not set +# CONFIG_X86_CPUFREQ_NFORCE2 is not set +CONFIG_X86_LONGRUN=y +# CONFIG_X86_LONGHAUL is not set + +# +# shared options +# +# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set +# CONFIG_X86_SPEEDSTEP_LIB is not set + +# +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# +CONFIG_PCI=y +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GOMMCONFIG is not set +# CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOXEN_FE is not set +CONFIG_PCI_GOANY=y +CONFIG_PCI_BIOS=y +CONFIG_PCI_DIRECT=y +CONFIG_PCI_MMCONFIG=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCI_MSI=y +# CONFIG_PCI_DEBUG is not set +CONFIG_ISA_DMA_API=y +CONFIG_ISA=y +# CONFIG_EISA is not set +# CONFIG_MCA is not set +# CONFIG_SCx200 is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +CONFIG_PCMCIA_PROBE=y +CONFIG_PCCARD_NONSTATIC=y + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +# CONFIG_LTPC is not set +# CONFIG_COPS is not set +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_TOSHIBA_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PNC2000 is not set +CONFIG_MTD_SC520CDP=m +CONFIG_MTD_NETSC520=m +CONFIG_MTD_TS5500=m +# CONFIG_MTD_SBC_GXX is not set +# CONFIG_MTD_AMD76XROM is not set +# CONFIG_MTD_ICHXROM is not set +CONFIG_MTD_SCB2_FLASH=m +# CONFIG_MTD_NETtel is not set +# CONFIG_MTD_DILNETPC is not set +# CONFIG_MTD_L440GX is not set +CONFIG_MTD_PCI=m +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_ECC_SMC=y +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_CS553X=m +CONFIG_MTD_NAND_NANDSIM=m + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_ISAPNP=y +# CONFIG_PNPBIOS is not set +CONFIG_PNPACPI=y + +# +# Block devices +# +CONFIG_BLK_DEV_FD=m +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_CMD640=y +CONFIG_BLK_DEV_CMD640_ENHANCED=y +CONFIG_BLK_DEV_IDEPNP=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_RZ1000=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +CONFIG_BLK_DEV_AMD74XX=y +CONFIG_BLK_DEV_ATIIXP=y +CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_TRIFLEX=y +# CONFIG_BLK_DEV_CY82C693 is not set +CONFIG_BLK_DEV_CS5520=y +CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_CS5535=y +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +CONFIG_BLK_DEV_SIS5513=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +# CONFIG_IDE_CHIPSETS is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +# CONFIG_SCSI_7000FASST is not set +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AHA152X=m +CONFIG_SCSI_AHA1542=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +# CONFIG_SCSI_DPT_I2O is not set +CONFIG_SCSI_ADVANSYS=m +# CONFIG_SCSI_IN2000 is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +CONFIG_SCSI_BUSLOGIC=m +# CONFIG_SCSI_OMIT_FLASHPOINT is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_SCSI_GDTH=m +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +# CONFIG_SCSI_NCR53C406A is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +# CONFIG_SCSI_SYM53C416 is not set +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DC390T=m +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set + +# +# Device Drivers +# +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m + +# +# I2O device support +# +CONFIG_I2O=m +# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_CONFIG=m +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_BUS=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_NET_SB1000=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +# CONFIG_EL1 is not set +# CONFIG_EL2 is not set +# CONFIG_ELPLUS is not set +# CONFIG_EL16 is not set +CONFIG_EL3=m +# CONFIG_3C515 is not set +CONFIG_VORTEX=m +CONFIG_TYPHOON=m +# CONFIG_LANCE is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +CONFIG_ULTRA=m +# CONFIG_SMC9194 is not set +# CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +CONFIG_NET_ISA=y +# CONFIG_E2100 is not set +CONFIG_EWRK3=m +# CONFIG_EEXPRESS is not set +# CONFIG_EEXPRESS_PRO is not set +# CONFIG_HPLAN_PLUS is not set +# CONFIG_HPLAN is not set +# CONFIG_LP486E is not set +# CONFIG_ETH16I is not set +CONFIG_NE2000=m +# CONFIG_ZNET is not set +# CONFIG_SEEQ8005 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_CS89x0 is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_TLAN=m +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y +CONFIG_NET_POCKET=y +CONFIG_ATP=m +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +# CONFIG_IBMTR is not set +CONFIG_IBMOL=m +CONFIG_IBMLS=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set +# CONFIG_SMCTR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +# CONFIG_ARLAN is not set +# CONFIG_WAVELAN is not set +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +# CONFIG_IPW2200_DEBUG is not set +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_BCM43XX=m +CONFIG_BCM43XX_DEBUG=y +CONFIG_BCM43XX_DMA=y +CONFIG_BCM43XX_PIO=y +CONFIG_BCM43XX_DMA_AND_PIO_MODE=y +# CONFIG_BCM43XX_DMA_MODE is not set +# CONFIG_BCM43XX_PIO_MODE is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_IBMTR=m + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_NICSTAR=m +# CONFIG_ATM_NICSTAR_USE_SUNI is not set +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +# CONFIG_ATM_IA is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +# CONFIG_HISAX_16_0 is not set +CONFIG_HISAX_16_3=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +# CONFIG_HISAX_AVM_A1 is not set +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +# CONFIG_HISAX_IX1MICROR2 is not set +CONFIG_HISAX_DIEHLDIVA=y +# CONFIG_HISAX_ASUSCOM is not set +# CONFIG_HISAX_TELEINT is not set +# CONFIG_HISAX_HFCS is not set +CONFIG_HISAX_SEDLBAUER=y +# CONFIG_HISAX_SPORTSTER is not set +# CONFIG_HISAX_MIC is not set +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +# CONFIG_HISAX_ISURF is not set +# CONFIG_HISAX_HSTSAPHIR is not set +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_HDLC=y + +# +# Active 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 + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m + +# +# Active Eicon DIVA Server cards +# +CONFIG_CAPI_EICON=y +CONFIG_ISDN_DIVAS=m +CONFIG_ISDN_DIVAS_BRIPCI=y +CONFIG_ISDN_DIVAS_PRIPCI=y +CONFIG_ISDN_DIVAS_DIVACAPI=m +CONFIG_ISDN_DIVAS_USERIDI=m +CONFIG_ISDN_DIVAS_MAINT=m + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_WISTRON_BTNS=m +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_ESPSERIAL is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y +# CONFIG_SERIAL_8250_FOURPORT is not set +# CONFIG_SERIAL_8250_ACCENT is not set +# CONFIG_SERIAL_8250_BOCA is not set +# CONFIG_SERIAL_8250_HUB6 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_CRASH=m +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +# CONFIG_SC520_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +CONFIG_IBMASR=m +# CONFIG_WAFER_WDT is not set +CONFIG_I6300ESB_WDT=m +CONFIG_I8XX_TCO=m +# CONFIG_SC1200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_SBC8360_WDT is not set +# CONFIG_CPU5_WDT is not set +CONFIG_W83627HF_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_MACHZ_WDT=m +# CONFIG_SBC_EPX_C3_WATCHDOG is not set + +# +# ISA-based Watchdog Cards +# +# CONFIG_PCWATCHDOG is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_WDT is not set + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_AMD=m +CONFIG_HW_RANDOM_GEODE=m +CONFIG_HW_RANDOM_VIA=m +CONFIG_NVRAM=y +CONFIG_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_SONYPI is not set + +# +# Ftape, the floppy tape device driver +# +CONFIG_AGP=y +CONFIG_AGP_ALI=y +# CONFIG_AGP_ATI is not set +# CONFIG_AGP_AMD is not set +# CONFIG_AGP_AMD64 is not set +CONFIG_AGP_INTEL=y +# CONFIG_AGP_NVIDIA is not set +CONFIG_AGP_SIS=y +# CONFIG_AGP_SWORKS is not set +CONFIG_AGP_VIA=y +CONFIG_AGP_EFFICEON=y +CONFIG_DRM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I810=m +CONFIG_DRM_I830=m +CONFIG_DRM_I915=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +CONFIG_MWAVE=m +CONFIG_PC8736x_GPIO=m +CONFIG_NSC_GPIO=m +CONFIG_CS5535_GPIO=m +# CONFIG_RAW_DRIVER is not set +CONFIG_HPET=y +# CONFIG_HPET_RTC_IRQ is not set +# CONFIG_HPET_MMAP is not set +CONFIG_HANGCHECK_TIMER=m + +# +# TPM devices +# +CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m +CONFIG_TCG_NSC=m +CONFIG_TCG_ATMEL=m +CONFIG_TCG_INFINEON=m +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI1563=m +CONFIG_I2C_ALI15X3=m +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +CONFIG_I2C_I801=m +CONFIG_I2C_I810=m +CONFIG_I2C_PIIX4=m +CONFIG_I2C_ISA=m +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_SCx200_ACB is not set +CONFIG_I2C_SIS5595=m +CONFIG_I2C_SIS630=m +CONFIG_I2C_SIS96X=m +CONFIG_I2C_STUB=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +# CONFIG_SENSORS_HDAPS is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# +# CONFIG_IBM_ASM is not set + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y + +# +# Video Capture Adapters +# + +# +# Video Capture Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +# CONFIG_VIDEO_PMS is not set +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_24XXX=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set + +# +# Radio Adapters +# +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_RADIO_GEMTEK is not set +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_RADIO_SF16FMR2 is not set +# CONFIG_RADIO_TERRATEC is not set +# CONFIG_RADIO_TRUST is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set +CONFIG_USB_DSBR=m + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m + +# +# Miscellaneous devices +# +CONFIG_DVB_PLL=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6421=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_VIDEOBUF=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ARC is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +CONFIG_FB_VGA16=m +CONFIG_FB_VESA=y +# CONFIG_FB_IMAC is not set +# CONFIG_FB_HGA is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_I810=m +CONFIG_FB_I810_GTF=y +CONFIG_FB_I810_I2C=y +CONFIG_FB_INTEL=m +# CONFIG_FB_INTEL_DEBUG is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=m +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_SIS is not set +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_CYBLA=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_GEODE is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_VIDEO_SELECT=y +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_RTCTIMER=m +CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_OPL4_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_MPU401=m + +# +# ISA devices +# +CONFIG_SND_CS4231_LIB=m +CONFIG_SND_ADLIB=m +# CONFIG_SND_AD1816A is not set +# CONFIG_SND_AD1848 is not set +# CONFIG_SND_ALS100 is not set +# CONFIG_SND_AZT2320 is not set +# CONFIG_SND_CMI8330 is not set +# CONFIG_SND_CS4231 is not set +# CONFIG_SND_CS4232 is not set +CONFIG_SND_CS4236=m +# CONFIG_SND_DT019X is not set +# CONFIG_SND_ES968 is not set +# CONFIG_SND_ES1688 is not set +CONFIG_SND_ES18XX=m +# CONFIG_SND_GUSCLASSIC is not set +# CONFIG_SND_GUSEXTREME is not set +# CONFIG_SND_GUSMAX is not set +# CONFIG_SND_INTERWAVE is not set +# CONFIG_SND_INTERWAVE_STB is not set +CONFIG_SND_OPL3SA2=m +# CONFIG_SND_OPTI92X_AD1848 is not set +# CONFIG_SND_OPTI92X_CS4231 is not set +# CONFIG_SND_OPTI93X is not set +CONFIG_SND_MIRO=m +# CONFIG_SND_SB8 is not set +CONFIG_SND_SB16=m +CONFIG_SND_SBAWE=m +# CONFIG_SND_SB16_CSP is not set +# CONFIG_SND_SGALAXY is not set +# CONFIG_SND_SSCAPE is not set +# CONFIG_SND_WAVEFRONT is not set + +# +# PCI devices +# +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_CS5535AUDIO=m +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +CONFIG_USB_HIDINPUT_POWERBOOK=y +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +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_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_WBSD=m + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# +CONFIG_EDAC=y + +# +# Reporting subsystems +# +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_AMD76X=m +CONFIG_EDAC_E7XXX=m +CONFIG_EDAC_E752X=m +CONFIG_EDAC_I82875P=m +CONFIG_EDAC_I82860=m +CONFIG_EDAC_K8=m +CONFIG_EDAC_R82600=m +CONFIG_EDAC_POLL=y + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_HIGHMEM=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FRAME_POINTER is not set +CONFIG_UNWIND_INFO=y +CONFIG_STACK_UNWIND=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_EARLY_PRINTK=y +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_DEBUG_STACK_USAGE=y + +# +# Page alloc debug is incompatible with Software Suspend on i386 +# +CONFIG_DEBUG_RODATA=y +CONFIG_4KSTACKS=y +CONFIG_X86_FIND_SMP_CONFIG=y +CONFIG_X86_MPPARSE=y +CONFIG_DOUBLEFAULT=y + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_586=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# +CONFIG_CRYPTO_DEV_PADLOCK=m +CONFIG_CRYPTO_DEV_PADLOCK_AES=y + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_X86_SMP=y +CONFIG_X86_HT=y +CONFIG_X86_BIOS_REBOOT=y +CONFIG_X86_TRAMPOLINE=y +CONFIG_KTIME_SCALAR=y diff --git a/configs/kernel-2.6.18-i586.config b/configs/kernel-2.6.18-i586.config new file mode 100644 index 000000000..906c52ba2 --- /dev/null +++ b/configs/kernel-2.6.18-i586.config @@ -0,0 +1,3357 @@ +# i386 +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:39 2006 +# +CONFIG_X86_32=y +CONFIG_GENERIC_TIME=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_X86=y +CONFIG_MMU=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_DMI=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Processor type and features +# +# CONFIG_SMP is not set +CONFIG_X86_PC=y +# CONFIG_X86_XEN is not set +# CONFIG_X86_ELAN is not set +# CONFIG_X86_VOYAGER is not set +# CONFIG_X86_NUMAQ is not set +# CONFIG_X86_SUMMIT is not set +# CONFIG_X86_BIGSMP is not set +# CONFIG_X86_VISWS is not set +# CONFIG_X86_GENERICARCH is not set +# CONFIG_X86_ES7000 is not set +# CONFIG_M386 is not set +# CONFIG_M486 is not set +CONFIG_M586=y +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set +# CONFIG_M686 is not set +# CONFIG_MPENTIUMII is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MEFFICEON is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MGEODEGX1 is not set +# CONFIG_MGEODE_LX is not set +# CONFIG_MCYRIXIII is not set +# CONFIG_MVIAC3_2 is not set +CONFIG_X86_GENERIC=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_XADD=y +CONFIG_X86_L1_CACHE_SHIFT=7 +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_X86_PPRO_FENCE=y +CONFIG_X86_F00F_BUG=y +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_INVLPG=y +CONFIG_X86_BSWAP=y +CONFIG_X86_POPAD_OK=y +CONFIG_X86_CMPXCHG64=y +CONFIG_X86_ALIGNMENT_16=y +CONFIG_X86_INTEL_USERCOPY=y +CONFIG_HPET_TIMER=y +CONFIG_HPET_EMULATE_RTC=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +# CONFIG_X86_UP_APIC is not set +CONFIG_X86_MCE=y +# CONFIG_X86_MCE_NONFATAL is not set +CONFIG_VM86=y +# CONFIG_TOSHIBA is not set +# CONFIG_I8K is not set +# CONFIG_X86_REBOOTFIXUPS is not set +# CONFIG_MICROCODE is not set +CONFIG_X86_MSR=m +CONFIG_X86_CPUID=m +# CONFIG_SWIOTLB is not set + +# +# Firmware Drivers +# +CONFIG_EDD=m +CONFIG_EFI_VARS=y +# CONFIG_DELL_RBU is not set +# CONFIG_DCDBAS is not set +# CONFIG_NOHIGHMEM is not set +CONFIG_HIGHMEM4G=y +# CONFIG_HIGHMEM64G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_HIGHMEM=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_SPARSEMEM_STATIC=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_RESOURCES_64BIT=y +CONFIG_HIGHPTE=y +# CONFIG_MATH_EMULATION is not set +CONFIG_MTRR=y +CONFIG_EFI=y +CONFIG_BOOT_IOREMAP=y +CONFIG_REGPARM=y +# CONFIG_SECCOMP is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_KEXEC=y +# CONFIG_CRASH_DUMP is not set +CONFIG_PHYSICAL_START=0x400000 +# CONFIG_COMPAT_VDSO is not set +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y + +# +# Power management options (ACPI, APM) +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +CONFIG_SOFTWARE_SUSPEND=y +CONFIG_PM_STD_PARTITION="" + +# +# ACPI (Advanced Configuration and Power Interface) Support +# +CONFIG_ACPI=y +CONFIG_ACPI_SLEEP=y +CONFIG_ACPI_SLEEP_PROC_FS=y +# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set +CONFIG_ACPI_AC=m +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_VIDEO=m +# CONFIG_ACPI_HOTKEY is not set +CONFIG_ACPI_FAN=y +CONFIG_ACPI_DOCK=m +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_THERMAL=y +# CONFIG_ACPI_ASUS is not set +# CONFIG_ACPI_IBM is not set +# CONFIG_ACPI_TOSHIBA is not set +CONFIG_ACPI_BLACKLIST_YEAR=1999 +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_EC=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_X86_PM_TIMER=y +CONFIG_ACPI_CONTAINER=m +CONFIG_ACPI_SBS=m + +# +# APM (Advanced Power Management) BIOS Support +# +CONFIG_APM=y +# CONFIG_APM_IGNORE_USER_SUSPEND is not set +# CONFIG_APM_DO_ENABLE is not set +CONFIG_APM_CPU_IDLE=y +# CONFIG_APM_DISPLAY_BLANK is not set +CONFIG_APM_RTC_IS_GMT=y +# CONFIG_APM_ALLOW_INTS is not set +# CONFIG_APM_REAL_MODE_POWER_OFF is not set + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=m +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m + +# +# CPUFreq processor drivers +# +CONFIG_X86_ACPI_CPUFREQ=m +CONFIG_X86_POWERNOW_K6=m +# CONFIG_X86_POWERNOW_K7 is not set +# CONFIG_X86_POWERNOW_K8 is not set +# CONFIG_X86_GX_SUSPMOD is not set +# CONFIG_X86_SPEEDSTEP_CENTRINO is not set +# CONFIG_X86_SPEEDSTEP_ICH is not set +# CONFIG_X86_SPEEDSTEP_SMI is not set +# CONFIG_X86_P4_CLOCKMOD is not set +# CONFIG_X86_CPUFREQ_NFORCE2 is not set +CONFIG_X86_LONGRUN=y +# CONFIG_X86_LONGHAUL is not set + +# +# shared options +# +# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set +# CONFIG_X86_SPEEDSTEP_LIB is not set + +# +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# +CONFIG_PCI=y +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GOMMCONFIG is not set +# CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOXEN_FE is not set +CONFIG_PCI_GOANY=y +CONFIG_PCI_BIOS=y +CONFIG_PCI_DIRECT=y +CONFIG_PCI_MMCONFIG=y +CONFIG_PCIEPORTBUS=y +# CONFIG_PCI_DEBUG is not set +CONFIG_ISA_DMA_API=y +CONFIG_ISA=y +# CONFIG_EISA is not set +# CONFIG_MCA is not set +# CONFIG_SCx200 is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +CONFIG_PCMCIA_PROBE=y +CONFIG_PCCARD_NONSTATIC=y + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +# CONFIG_LTPC is not set +# CONFIG_COPS is not set +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# +CONFIG_IRPORT_SIR=m + +# +# Old Serial dongle support +# +# CONFIG_DONGLE_OLD is not set + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_TOSHIBA_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PNC2000 is not set +CONFIG_MTD_SC520CDP=m +CONFIG_MTD_NETSC520=m +CONFIG_MTD_TS5500=m +# CONFIG_MTD_SBC_GXX is not set +# CONFIG_MTD_AMD76XROM is not set +# CONFIG_MTD_ICHXROM is not set +CONFIG_MTD_SCB2_FLASH=m +# CONFIG_MTD_NETtel is not set +# CONFIG_MTD_DILNETPC is not set +# CONFIG_MTD_L440GX is not set +CONFIG_MTD_PCI=m +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_ECC_SMC=y +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_CS553X=m +CONFIG_MTD_NAND_NANDSIM=m + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_ISAPNP=y +# CONFIG_PNPBIOS is not set +CONFIG_PNPACPI=y + +# +# Block devices +# +CONFIG_BLK_DEV_FD=m +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_CMD640=y +CONFIG_BLK_DEV_CMD640_ENHANCED=y +CONFIG_BLK_DEV_IDEPNP=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_RZ1000=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +CONFIG_BLK_DEV_AMD74XX=y +CONFIG_BLK_DEV_ATIIXP=y +CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_TRIFLEX=y +# CONFIG_BLK_DEV_CY82C693 is not set +CONFIG_BLK_DEV_CS5520=y +CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_CS5535=y +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +CONFIG_BLK_DEV_SIS5513=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +# CONFIG_IDE_CHIPSETS is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +# CONFIG_SCSI_7000FASST is not set +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AHA152X=m +CONFIG_SCSI_AHA1542=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +# CONFIG_SCSI_DPT_I2O is not set +CONFIG_SCSI_ADVANSYS=m +# CONFIG_SCSI_IN2000 is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +CONFIG_SCSI_BUSLOGIC=m +# CONFIG_SCSI_OMIT_FLASHPOINT is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_SCSI_GDTH=m +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +# CONFIG_SCSI_NCR53C406A is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +# CONFIG_SCSI_SYM53C416 is not set +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DC390T=m +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set + +# +# Device Drivers +# +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m + +# +# I2O device support +# +CONFIG_I2O=m +# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_CONFIG=m +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_BUS=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_NET_SB1000=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +# CONFIG_EL1 is not set +# CONFIG_EL2 is not set +# CONFIG_ELPLUS is not set +# CONFIG_EL16 is not set +CONFIG_EL3=m +# CONFIG_3C515 is not set +CONFIG_VORTEX=m +CONFIG_TYPHOON=m +# CONFIG_LANCE is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +CONFIG_ULTRA=m +# CONFIG_SMC9194 is not set +# CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +# CONFIG_PCMCIA_XIRTULIP is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +CONFIG_NET_ISA=y +# CONFIG_E2100 is not set +CONFIG_EWRK3=m +# CONFIG_EEXPRESS is not set +# CONFIG_EEXPRESS_PRO is not set +# CONFIG_HPLAN_PLUS is not set +# CONFIG_HPLAN is not set +# CONFIG_LP486E is not set +# CONFIG_ETH16I is not set +CONFIG_NE2000=m +# CONFIG_ZNET is not set +# CONFIG_SEEQ8005 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_CS89x0 is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_TLAN=m +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y +CONFIG_NET_POCKET=y +CONFIG_ATP=m +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +# CONFIG_IBMTR is not set +CONFIG_IBMOL=m +CONFIG_IBMLS=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set +# CONFIG_SMCTR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +# CONFIG_ARLAN is not set +# CONFIG_WAVELAN is not set +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +# CONFIG_IPW2200_DEBUG is not set +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_BCM43XX=m +CONFIG_BCM43XX_DEBUG=y +CONFIG_BCM43XX_DMA=y +CONFIG_BCM43XX_PIO=y +CONFIG_BCM43XX_DMA_AND_PIO_MODE=y +# CONFIG_BCM43XX_DMA_MODE is not set +# CONFIG_BCM43XX_PIO_MODE is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_IBMTR=m + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_NICSTAR=m +# CONFIG_ATM_NICSTAR_USE_SUNI is not set +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +# CONFIG_ATM_IA is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DRV_LOOP=m +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +# CONFIG_HISAX_16_0 is not set +CONFIG_HISAX_16_3=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +# CONFIG_HISAX_AVM_A1 is not set +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +# CONFIG_HISAX_IX1MICROR2 is not set +CONFIG_HISAX_DIEHLDIVA=y +# CONFIG_HISAX_ASUSCOM is not set +# CONFIG_HISAX_TELEINT is not set +# CONFIG_HISAX_HFCS is not set +CONFIG_HISAX_SEDLBAUER=y +# CONFIG_HISAX_SPORTSTER is not set +# CONFIG_HISAX_MIC is not set +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +# CONFIG_HISAX_ISURF is not set +# CONFIG_HISAX_HSTSAPHIR is not set +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_HDLC=y + +# +# Active 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_HYSDN=m +CONFIG_HYSDN_CAPI=y + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m + +# +# Active Eicon DIVA Server cards +# +CONFIG_CAPI_EICON=y +CONFIG_ISDN_DIVAS=m +CONFIG_ISDN_DIVAS_BRIPCI=y +CONFIG_ISDN_DIVAS_PRIPCI=y +CONFIG_ISDN_DIVAS_DIVACAPI=m +CONFIG_ISDN_DIVAS_USERIDI=m +CONFIG_ISDN_DIVAS_MAINT=m + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_WISTRON_BTNS=m +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_ESPSERIAL is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y +# CONFIG_SERIAL_8250_FOURPORT is not set +# CONFIG_SERIAL_8250_ACCENT is not set +# CONFIG_SERIAL_8250_BOCA is not set +# CONFIG_SERIAL_8250_HUB6 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_CRASH=m +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +# CONFIG_SC520_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +CONFIG_IBMASR=m +# CONFIG_WAFER_WDT is not set +CONFIG_I6300ESB_WDT=m +CONFIG_I8XX_TCO=m +# CONFIG_SC1200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_SBC8360_WDT is not set +# CONFIG_CPU5_WDT is not set +CONFIG_W83627HF_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_MACHZ_WDT=m +# CONFIG_SBC_EPX_C3_WATCHDOG is not set + +# +# ISA-based Watchdog Cards +# +# CONFIG_PCWATCHDOG is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_WDT is not set + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_AMD=m +CONFIG_HW_RANDOM_GEODE=m +CONFIG_HW_RANDOM_VIA=m +CONFIG_NVRAM=y +CONFIG_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_SONYPI is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +CONFIG_AGP=y +CONFIG_AGP_ALI=y +# CONFIG_AGP_ATI is not set +# CONFIG_AGP_AMD is not set +# CONFIG_AGP_AMD64 is not set +CONFIG_AGP_INTEL=y +# CONFIG_AGP_NVIDIA is not set +CONFIG_AGP_SIS=y +# CONFIG_AGP_SWORKS is not set +CONFIG_AGP_VIA=y +CONFIG_AGP_EFFICEON=y +CONFIG_DRM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I810=m +CONFIG_DRM_I830=m +CONFIG_DRM_I915=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +CONFIG_MWAVE=m +CONFIG_PC8736x_GPIO=m +CONFIG_NSC_GPIO=m +CONFIG_CS5535_GPIO=m +# CONFIG_RAW_DRIVER is not set +CONFIG_HPET=y +# CONFIG_HPET_RTC_IRQ is not set +# CONFIG_HPET_MMAP is not set +CONFIG_HANGCHECK_TIMER=m + +# +# TPM devices +# +CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m +CONFIG_TCG_NSC=m +CONFIG_TCG_ATMEL=m +CONFIG_TCG_INFINEON=m +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI1563=m +CONFIG_I2C_ALI15X3=m +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +# CONFIG_I2C_ELEKTOR is not set +CONFIG_I2C_I801=m +CONFIG_I2C_I810=m +CONFIG_I2C_PIIX4=m +CONFIG_I2C_ISA=m +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_SCx200_ACB is not set +CONFIG_I2C_SIS5595=m +CONFIG_I2C_SIS630=m +CONFIG_I2C_SIS96X=m +CONFIG_I2C_STUB=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +# CONFIG_SENSORS_HDAPS is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# +# CONFIG_IBM_ASM is not set + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y + +# +# Video Capture Adapters +# + +# +# Video Capture Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +# CONFIG_VIDEO_PMS is not set +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_24XXX=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set + +# +# Radio Adapters +# +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_RADIO_GEMTEK is not set +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_RADIO_SF16FMR2 is not set +# CONFIG_RADIO_TERRATEC is not set +# CONFIG_RADIO_TRUST is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set +CONFIG_USB_DSBR=m + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m + +# +# Miscellaneous devices +# +CONFIG_DVB_PLL=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6421=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_VIDEOBUF=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ARC is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +CONFIG_FB_VGA16=m +CONFIG_FB_VESA=y +# CONFIG_FB_IMAC is not set +# CONFIG_FB_HGA is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_I810=m +CONFIG_FB_I810_GTF=y +CONFIG_FB_I810_I2C=y +CONFIG_FB_INTEL=m +# CONFIG_FB_INTEL_DEBUG is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=m +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_SIS is not set +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_CYBLA=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_GEODE is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_VIDEO_SELECT=y +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_RTCTIMER=m +CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_OPL4_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_MPU401=m + +# +# ISA devices +# +CONFIG_SND_CS4231_LIB=m +CONFIG_SND_ADLIB=m +# CONFIG_SND_AD1816A is not set +# CONFIG_SND_AD1848 is not set +# CONFIG_SND_ALS100 is not set +# CONFIG_SND_AZT2320 is not set +# CONFIG_SND_CMI8330 is not set +# CONFIG_SND_CS4231 is not set +# CONFIG_SND_CS4232 is not set +CONFIG_SND_CS4236=m +# CONFIG_SND_DT019X is not set +# CONFIG_SND_ES968 is not set +# CONFIG_SND_ES1688 is not set +CONFIG_SND_ES18XX=m +# CONFIG_SND_GUSCLASSIC is not set +# CONFIG_SND_GUSEXTREME is not set +# CONFIG_SND_GUSMAX is not set +# CONFIG_SND_INTERWAVE is not set +# CONFIG_SND_INTERWAVE_STB is not set +CONFIG_SND_OPL3SA2=m +# CONFIG_SND_OPTI92X_AD1848 is not set +# CONFIG_SND_OPTI92X_CS4231 is not set +# CONFIG_SND_OPTI93X is not set +CONFIG_SND_MIRO=m +# CONFIG_SND_SB8 is not set +CONFIG_SND_SB16=m +CONFIG_SND_SBAWE=m +# CONFIG_SND_SB16_CSP is not set +# CONFIG_SND_SGALAXY is not set +# CONFIG_SND_SSCAPE is not set +# CONFIG_SND_WAVEFRONT is not set + +# +# PCI devices +# +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_CS5535AUDIO=m +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +CONFIG_USB_HIDINPUT_POWERBOOK=y +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +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_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_WBSD=m + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# +CONFIG_EDAC=y + +# +# Reporting subsystems +# +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_AMD76X=m +CONFIG_EDAC_E7XXX=m +CONFIG_EDAC_E752X=m +CONFIG_EDAC_I82875P=m +CONFIG_EDAC_I82860=m +CONFIG_EDAC_K8=m +CONFIG_EDAC_R82600=m +CONFIG_EDAC_POLL=y + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_HIGHMEM=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FRAME_POINTER is not set +CONFIG_UNWIND_INFO=y +CONFIG_STACK_UNWIND=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_EARLY_PRINTK=y +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_DEBUG_STACK_USAGE=y + +# +# Page alloc debug is incompatible with Software Suspend on i386 +# +CONFIG_DEBUG_RODATA=y +CONFIG_4KSTACKS=y +CONFIG_DOUBLEFAULT=y + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_586=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# +CONFIG_CRYPTO_DEV_PADLOCK=m +CONFIG_CRYPTO_DEV_PADLOCK_AES=y + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_X86_BIOS_REBOOT=y +CONFIG_KTIME_SCALAR=y diff --git a/configs/kernel-2.6.18-i686-kdump.config b/configs/kernel-2.6.18-i686-kdump.config new file mode 100644 index 000000000..8e2ca42b6 --- /dev/null +++ b/configs/kernel-2.6.18-i686-kdump.config @@ -0,0 +1,3413 @@ +# i386 +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:39 2006 +# +CONFIG_X86_32=y +CONFIG_GENERIC_TIME=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_X86=y +CONFIG_MMU=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_DMI=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Processor type and features +# +# CONFIG_SMP is not set +CONFIG_X86_PC=y +# CONFIG_X86_XEN is not set +# CONFIG_X86_ELAN is not set +# CONFIG_X86_VOYAGER is not set +# CONFIG_X86_NUMAQ is not set +# CONFIG_X86_SUMMIT is not set +# CONFIG_X86_BIGSMP is not set +# CONFIG_X86_VISWS is not set +# CONFIG_X86_GENERICARCH is not set +# CONFIG_X86_ES7000 is not set +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set +CONFIG_M686=y +# CONFIG_MPENTIUMII is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MEFFICEON is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MGEODEGX1 is not set +# CONFIG_MGEODE_LX is not set +# CONFIG_MCYRIXIII is not set +# CONFIG_MVIAC3_2 is not set +CONFIG_X86_GENERIC=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_XADD=y +CONFIG_X86_L1_CACHE_SHIFT=7 +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_X86_PPRO_FENCE=y +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_INVLPG=y +CONFIG_X86_BSWAP=y +CONFIG_X86_POPAD_OK=y +CONFIG_X86_CMPXCHG64=y +CONFIG_X86_GOOD_APIC=y +CONFIG_X86_INTEL_USERCOPY=y +CONFIG_X86_USE_PPRO_CHECKSUM=y +CONFIG_X86_TSC=y +CONFIG_HPET_TIMER=y +CONFIG_HPET_EMULATE_RTC=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_X86_UP_APIC=y +CONFIG_X86_UP_IOAPIC=y +CONFIG_X86_LOCAL_APIC=y +CONFIG_X86_APIC_AUTO=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_MCE=y +# CONFIG_X86_MCE_NONFATAL is not set +CONFIG_X86_MCE_P4THERMAL=y +CONFIG_VM86=y +CONFIG_TOSHIBA=m +CONFIG_I8K=m +# CONFIG_X86_REBOOTFIXUPS is not set +CONFIG_MICROCODE=m +CONFIG_X86_MSR=m +CONFIG_X86_CPUID=m +# CONFIG_SWIOTLB is not set + +# +# Firmware Drivers +# +CONFIG_EDD=m +CONFIG_EFI_VARS=y +CONFIG_DELL_RBU=m +CONFIG_DCDBAS=m +# CONFIG_NOHIGHMEM is not set +# CONFIG_HIGHMEM4G is not set +CONFIG_HIGHMEM64G=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_HIGHMEM=y +CONFIG_X86_PAE=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_SPARSEMEM_STATIC=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_RESOURCES_64BIT=y +CONFIG_HIGHPTE=y +# CONFIG_MATH_EMULATION is not set +CONFIG_MTRR=y +CONFIG_EFI=y +CONFIG_BOOT_IOREMAP=y +CONFIG_REGPARM=y +# CONFIG_SECCOMP is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_KEXEC=y +CONFIG_CRASH_DUMP=y +CONFIG_PHYSICAL_START=0x1000000 +# CONFIG_COMPAT_VDSO is not set +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y + +# +# Power management options (ACPI, APM) +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set + +# +# ACPI (Advanced Configuration and Power Interface) Support +# +CONFIG_ACPI=y +CONFIG_ACPI_SLEEP=y +CONFIG_ACPI_SLEEP_PROC_FS=y +# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set +CONFIG_ACPI_AC=m +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_VIDEO=m +# CONFIG_ACPI_HOTKEY is not set +CONFIG_ACPI_FAN=y +CONFIG_ACPI_DOCK=m +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_ASUS=m +CONFIG_ACPI_IBM=m +CONFIG_ACPI_TOSHIBA=m +CONFIG_ACPI_BLACKLIST_YEAR=1999 +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_EC=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_X86_PM_TIMER=y +CONFIG_ACPI_CONTAINER=m +CONFIG_ACPI_SBS=m + +# +# APM (Advanced Power Management) BIOS Support +# +CONFIG_APM=y +# CONFIG_APM_IGNORE_USER_SUSPEND is not set +# CONFIG_APM_DO_ENABLE is not set +CONFIG_APM_CPU_IDLE=y +# CONFIG_APM_DISPLAY_BLANK is not set +CONFIG_APM_RTC_IS_GMT=y +# CONFIG_APM_ALLOW_INTS is not set +# CONFIG_APM_REAL_MODE_POWER_OFF is not set + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m + +# +# CPUFreq processor drivers +# +CONFIG_X86_ACPI_CPUFREQ=m +# CONFIG_X86_POWERNOW_K6 is not set +CONFIG_X86_POWERNOW_K7=y +CONFIG_X86_POWERNOW_K7_ACPI=y +CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_POWERNOW_K8_ACPI=y +# CONFIG_X86_GX_SUSPMOD is not set +CONFIG_X86_SPEEDSTEP_CENTRINO=y +CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y +CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y +CONFIG_X86_SPEEDSTEP_ICH=y +CONFIG_X86_SPEEDSTEP_SMI=y +CONFIG_X86_P4_CLOCKMOD=m +# CONFIG_X86_CPUFREQ_NFORCE2 is not set +CONFIG_X86_LONGRUN=y +# CONFIG_X86_LONGHAUL is not set + +# +# shared options +# +# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set +CONFIG_X86_SPEEDSTEP_LIB=y +# CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set + +# +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# +CONFIG_PCI=y +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GOMMCONFIG is not set +# CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOXEN_FE is not set +CONFIG_PCI_GOANY=y +CONFIG_PCI_BIOS=y +CONFIG_PCI_DIRECT=y +CONFIG_PCI_MMCONFIG=y +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=m +# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set +CONFIG_PCI_MSI=y +# CONFIG_PCI_DEBUG is not set +CONFIG_ISA_DMA_API=y +CONFIG_ISA=y +# CONFIG_EISA is not set +# CONFIG_MCA is not set +# CONFIG_SCx200 is not set +CONFIG_K8_NB=y + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +CONFIG_PCMCIA_PROBE=y +CONFIG_PCCARD_NONSTATIC=y + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_FAKE=m +CONFIG_HOTPLUG_PCI_COMPAQ=m +# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set +CONFIG_HOTPLUG_PCI_IBM=m +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +# CONFIG_LTPC is not set +# CONFIG_COPS is not set +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# +CONFIG_IRPORT_SIR=m + +# +# Old Serial dongle support +# +# CONFIG_DONGLE_OLD is not set + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_TOSHIBA_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PNC2000 is not set +CONFIG_MTD_SC520CDP=m +CONFIG_MTD_NETSC520=m +CONFIG_MTD_TS5500=m +# CONFIG_MTD_SBC_GXX is not set +# CONFIG_MTD_AMD76XROM is not set +# CONFIG_MTD_ICHXROM is not set +CONFIG_MTD_SCB2_FLASH=m +# CONFIG_MTD_NETtel is not set +# CONFIG_MTD_DILNETPC is not set +# CONFIG_MTD_L440GX is not set +CONFIG_MTD_PCI=m +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_ECC_SMC=y +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_CS553X=m +CONFIG_MTD_NAND_NANDSIM=m + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_ISAPNP=y +# CONFIG_PNPBIOS is not set +CONFIG_PNPACPI=y + +# +# Block devices +# +CONFIG_BLK_DEV_FD=m +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_CMD640=y +CONFIG_BLK_DEV_CMD640_ENHANCED=y +CONFIG_BLK_DEV_IDEPNP=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_RZ1000=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +CONFIG_BLK_DEV_AMD74XX=y +CONFIG_BLK_DEV_ATIIXP=y +CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_TRIFLEX=y +# CONFIG_BLK_DEV_CY82C693 is not set +CONFIG_BLK_DEV_CS5520=y +CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_CS5535=y +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +CONFIG_BLK_DEV_SIS5513=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +# CONFIG_IDE_CHIPSETS is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +# CONFIG_SCSI_7000FASST is not set +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AHA152X=m +CONFIG_SCSI_AHA1542=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +# CONFIG_SCSI_DPT_I2O is not set +CONFIG_SCSI_ADVANSYS=m +# CONFIG_SCSI_IN2000 is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +CONFIG_SCSI_BUSLOGIC=m +# CONFIG_SCSI_OMIT_FLASHPOINT is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_SCSI_GDTH=m +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +# CONFIG_SCSI_NCR53C406A is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +# CONFIG_SCSI_SYM53C416 is not set +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DC390T=m +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set + +# +# Device Drivers +# +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m + +# +# I2O device support +# +CONFIG_I2O=m +# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_EXT_ADAPTEC_DMA64=y +CONFIG_I2O_CONFIG=m +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_BUS=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_NET_SB1000=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +# CONFIG_EL1 is not set +# CONFIG_EL2 is not set +# CONFIG_ELPLUS is not set +# CONFIG_EL16 is not set +CONFIG_EL3=m +# CONFIG_3C515 is not set +CONFIG_VORTEX=m +CONFIG_TYPHOON=m +# CONFIG_LANCE is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +CONFIG_ULTRA=m +# CONFIG_SMC9194 is not set +# CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +# CONFIG_PCMCIA_XIRTULIP is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +CONFIG_NET_ISA=y +# CONFIG_E2100 is not set +CONFIG_EWRK3=m +# CONFIG_EEXPRESS is not set +# CONFIG_EEXPRESS_PRO is not set +# CONFIG_HPLAN_PLUS is not set +# CONFIG_HPLAN is not set +# CONFIG_LP486E is not set +# CONFIG_ETH16I is not set +CONFIG_NE2000=m +# CONFIG_ZNET is not set +# CONFIG_SEEQ8005 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_CS89x0 is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_TLAN=m +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y +CONFIG_NET_POCKET=y +CONFIG_ATP=m +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +# CONFIG_IBMTR is not set +CONFIG_IBMOL=m +CONFIG_IBMLS=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set +# CONFIG_SMCTR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +# CONFIG_ARLAN is not set +# CONFIG_WAVELAN is not set +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +# CONFIG_IPW2200_DEBUG is not set +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_BCM43XX=m +CONFIG_BCM43XX_DEBUG=y +CONFIG_BCM43XX_DMA=y +CONFIG_BCM43XX_PIO=y +CONFIG_BCM43XX_DMA_AND_PIO_MODE=y +# CONFIG_BCM43XX_DMA_MODE is not set +# CONFIG_BCM43XX_PIO_MODE is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_IBMTR=m + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_NICSTAR=m +# CONFIG_ATM_NICSTAR_USE_SUNI is not set +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +# CONFIG_ATM_IA is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DRV_LOOP=m +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +# CONFIG_HISAX_16_0 is not set +CONFIG_HISAX_16_3=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +# CONFIG_HISAX_AVM_A1 is not set +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +# CONFIG_HISAX_IX1MICROR2 is not set +CONFIG_HISAX_DIEHLDIVA=y +# CONFIG_HISAX_ASUSCOM is not set +# CONFIG_HISAX_TELEINT is not set +# CONFIG_HISAX_HFCS is not set +CONFIG_HISAX_SEDLBAUER=y +# CONFIG_HISAX_SPORTSTER is not set +# CONFIG_HISAX_MIC is not set +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +# CONFIG_HISAX_ISURF is not set +# CONFIG_HISAX_HSTSAPHIR is not set +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_HDLC=y + +# +# Active 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_HYSDN=m +CONFIG_HYSDN_CAPI=y + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m + +# +# Active Eicon DIVA Server cards +# +CONFIG_CAPI_EICON=y +CONFIG_ISDN_DIVAS=m +CONFIG_ISDN_DIVAS_BRIPCI=y +CONFIG_ISDN_DIVAS_PRIPCI=y +CONFIG_ISDN_DIVAS_DIVACAPI=m +CONFIG_ISDN_DIVAS_USERIDI=m +CONFIG_ISDN_DIVAS_MAINT=m + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_WISTRON_BTNS=m +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_ESPSERIAL is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y +# CONFIG_SERIAL_8250_FOURPORT is not set +# CONFIG_SERIAL_8250_ACCENT is not set +# CONFIG_SERIAL_8250_BOCA is not set +# CONFIG_SERIAL_8250_HUB6 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_CRASH=m +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +# CONFIG_SC520_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +CONFIG_IBMASR=m +# CONFIG_WAFER_WDT is not set +CONFIG_I6300ESB_WDT=m +CONFIG_I8XX_TCO=m +# CONFIG_SC1200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_SBC8360_WDT is not set +# CONFIG_CPU5_WDT is not set +CONFIG_W83627HF_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_MACHZ_WDT=m +# CONFIG_SBC_EPX_C3_WATCHDOG is not set + +# +# ISA-based Watchdog Cards +# +# CONFIG_PCWATCHDOG is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_WDT is not set + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_AMD=m +CONFIG_HW_RANDOM_GEODE=m +CONFIG_HW_RANDOM_VIA=m +CONFIG_NVRAM=y +CONFIG_RTC=y +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set +CONFIG_SONYPI=m + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +CONFIG_AGP=y +CONFIG_AGP_ALI=y +CONFIG_AGP_ATI=y +CONFIG_AGP_AMD=y +CONFIG_AGP_AMD64=y +CONFIG_AGP_INTEL=y +CONFIG_AGP_NVIDIA=y +CONFIG_AGP_SIS=y +CONFIG_AGP_SWORKS=y +CONFIG_AGP_VIA=y +CONFIG_AGP_EFFICEON=y +CONFIG_DRM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I810=m +CONFIG_DRM_I830=m +CONFIG_DRM_I915=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +CONFIG_MWAVE=m +CONFIG_PC8736x_GPIO=m +CONFIG_NSC_GPIO=m +CONFIG_CS5535_GPIO=m +# CONFIG_RAW_DRIVER is not set +CONFIG_HPET=y +# CONFIG_HPET_RTC_IRQ is not set +# CONFIG_HPET_MMAP is not set +CONFIG_HANGCHECK_TIMER=m + +# +# TPM devices +# +CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m +CONFIG_TCG_NSC=m +CONFIG_TCG_ATMEL=m +CONFIG_TCG_INFINEON=m +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI1563=m +CONFIG_I2C_ALI15X3=m +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +# CONFIG_I2C_ELEKTOR is not set +CONFIG_I2C_I801=m +CONFIG_I2C_I810=m +CONFIG_I2C_PIIX4=m +CONFIG_I2C_ISA=m +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_SCx200_ACB is not set +CONFIG_I2C_SIS5595=m +CONFIG_I2C_SIS630=m +CONFIG_I2C_SIS96X=m +CONFIG_I2C_STUB=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y + +# +# Hardware Monitoring support +# +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_HDAPS=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# +CONFIG_IBM_ASM=m + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y + +# +# Video Capture Adapters +# + +# +# Video Capture Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +# CONFIG_VIDEO_PMS is not set +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_MEYE=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_24XXX=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set + +# +# Radio Adapters +# +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_RADIO_GEMTEK is not set +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_RADIO_SF16FMR2 is not set +# CONFIG_RADIO_TERRATEC is not set +# CONFIG_RADIO_TRUST is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set +CONFIG_USB_DSBR=m + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m + +# +# Miscellaneous devices +# +CONFIG_DVB_PLL=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6421=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_VIDEOBUF=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ARC is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +CONFIG_FB_VGA16=m +CONFIG_FB_VESA=y +# CONFIG_FB_IMAC is not set +# CONFIG_FB_HGA is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_I810=m +CONFIG_FB_I810_GTF=y +CONFIG_FB_I810_I2C=y +CONFIG_FB_INTEL=m +# CONFIG_FB_INTEL_DEBUG is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=m +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_SIS is not set +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_CYBLA=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_GEODE is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_VIDEO_SELECT=y +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_RTCTIMER=m +CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_OPL4_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_MPU401=m + +# +# ISA devices +# +CONFIG_SND_CS4231_LIB=m +CONFIG_SND_ADLIB=m +# CONFIG_SND_AD1816A is not set +# CONFIG_SND_AD1848 is not set +# CONFIG_SND_ALS100 is not set +# CONFIG_SND_AZT2320 is not set +# CONFIG_SND_CMI8330 is not set +# CONFIG_SND_CS4231 is not set +# CONFIG_SND_CS4232 is not set +CONFIG_SND_CS4236=m +# CONFIG_SND_DT019X is not set +# CONFIG_SND_ES968 is not set +# CONFIG_SND_ES1688 is not set +CONFIG_SND_ES18XX=m +# CONFIG_SND_GUSCLASSIC is not set +# CONFIG_SND_GUSEXTREME is not set +# CONFIG_SND_GUSMAX is not set +# CONFIG_SND_INTERWAVE is not set +# CONFIG_SND_INTERWAVE_STB is not set +CONFIG_SND_OPL3SA2=m +# CONFIG_SND_OPTI92X_AD1848 is not set +# CONFIG_SND_OPTI92X_CS4231 is not set +# CONFIG_SND_OPTI93X is not set +CONFIG_SND_MIRO=m +# CONFIG_SND_SB8 is not set +CONFIG_SND_SB16=m +CONFIG_SND_SBAWE=m +# CONFIG_SND_SB16_CSP is not set +# CONFIG_SND_SGALAXY is not set +# CONFIG_SND_SSCAPE is not set +# CONFIG_SND_WAVEFRONT is not set + +# +# PCI devices +# +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_CS5535AUDIO=m +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +CONFIG_USB_HIDINPUT_POWERBOOK=y +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +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_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_WBSD=m + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_ISER=m + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# +CONFIG_EDAC=y + +# +# Reporting subsystems +# +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_AMD76X=m +CONFIG_EDAC_E7XXX=m +CONFIG_EDAC_E752X=m +CONFIG_EDAC_I82875P=m +CONFIG_EDAC_I82860=m +CONFIG_EDAC_K8=m +CONFIG_EDAC_R82600=m +CONFIG_EDAC_POLL=y + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_VMCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_HIGHMEM=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FRAME_POINTER is not set +CONFIG_UNWIND_INFO=y +CONFIG_STACK_UNWIND=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_EARLY_PRINTK=y +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_DEBUG_STACK_USAGE=y +CONFIG_DEBUG_RODATA=y +CONFIG_4KSTACKS=y +CONFIG_X86_FIND_SMP_CONFIG=y +CONFIG_X86_MPPARSE=y +CONFIG_DOUBLEFAULT=y + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_586=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# +CONFIG_CRYPTO_DEV_PADLOCK=m +CONFIG_CRYPTO_DEV_PADLOCK_AES=y + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_X86_BIOS_REBOOT=y +CONFIG_KTIME_SCALAR=y diff --git a/configs/kernel-2.6.18-i686-smp.config b/configs/kernel-2.6.18-i686-smp.config new file mode 100644 index 000000000..00cc6b483 --- /dev/null +++ b/configs/kernel-2.6.18-i686-smp.config @@ -0,0 +1,3414 @@ +# i386 +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:40 2006 +# +CONFIG_X86_32=y +CONFIG_GENERIC_TIME=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_X86=y +CONFIG_MMU=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_DMI=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Processor type and features +# +CONFIG_SMP=y +# CONFIG_X86_PC is not set +# CONFIG_X86_XEN is not set +# CONFIG_X86_ELAN is not set +# CONFIG_X86_VOYAGER is not set +# CONFIG_X86_NUMAQ is not set +# CONFIG_X86_SUMMIT is not set +# CONFIG_X86_BIGSMP is not set +# CONFIG_X86_VISWS is not set +CONFIG_X86_GENERICARCH=y +# CONFIG_X86_ES7000 is not set +CONFIG_X86_CYCLONE_TIMER=y +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set +CONFIG_M686=y +# CONFIG_MPENTIUMII is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MEFFICEON is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MGEODEGX1 is not set +# CONFIG_MGEODE_LX is not set +# CONFIG_MCYRIXIII is not set +# CONFIG_MVIAC3_2 is not set +CONFIG_X86_GENERIC=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_XADD=y +CONFIG_X86_L1_CACHE_SHIFT=7 +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_X86_PPRO_FENCE=y +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_INVLPG=y +CONFIG_X86_BSWAP=y +CONFIG_X86_POPAD_OK=y +CONFIG_X86_CMPXCHG64=y +CONFIG_X86_GOOD_APIC=y +CONFIG_X86_INTEL_USERCOPY=y +CONFIG_X86_USE_PPRO_CHECKSUM=y +CONFIG_X86_TSC=y +CONFIG_HPET_TIMER=y +CONFIG_HPET_EMULATE_RTC=y +CONFIG_NR_CPUS=32 +CONFIG_SCHED_SMT=y +CONFIG_SCHED_MC=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_X86_LOCAL_APIC=y +CONFIG_X86_APIC_AUTO=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_MCE=y +# CONFIG_X86_MCE_NONFATAL is not set +CONFIG_X86_MCE_P4THERMAL=y +CONFIG_VM86=y +CONFIG_TOSHIBA=m +CONFIG_I8K=m +# CONFIG_X86_REBOOTFIXUPS is not set +CONFIG_MICROCODE=m +CONFIG_X86_MSR=m +CONFIG_X86_CPUID=m +# CONFIG_SWIOTLB is not set + +# +# Firmware Drivers +# +CONFIG_EDD=m +CONFIG_EFI_VARS=y +CONFIG_DELL_RBU=m +CONFIG_DCDBAS=m +# CONFIG_NOHIGHMEM is not set +# CONFIG_HIGHMEM4G is not set +CONFIG_HIGHMEM64G=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_HIGHMEM=y +CONFIG_X86_PAE=y +# CONFIG_NUMA is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_RESOURCES_64BIT=y +CONFIG_HIGHPTE=y +# CONFIG_MATH_EMULATION is not set +CONFIG_MTRR=y +CONFIG_EFI=y +# CONFIG_IRQBALANCE is not set +CONFIG_BOOT_IOREMAP=y +CONFIG_REGPARM=y +# CONFIG_SECCOMP is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_KEXEC=y +# CONFIG_CRASH_DUMP is not set +CONFIG_PHYSICAL_START=0x400000 +CONFIG_HOTPLUG_CPU=y +# CONFIG_COMPAT_VDSO is not set +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y + +# +# Power management options (ACPI, APM) +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +CONFIG_SUSPEND_SMP=y + +# +# ACPI (Advanced Configuration and Power Interface) Support +# +CONFIG_ACPI=y +CONFIG_ACPI_SLEEP=y +CONFIG_ACPI_SLEEP_PROC_FS=y +# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set +CONFIG_ACPI_AC=m +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_VIDEO=m +# CONFIG_ACPI_HOTKEY is not set +CONFIG_ACPI_FAN=y +CONFIG_ACPI_DOCK=m +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_ASUS=m +CONFIG_ACPI_IBM=m +CONFIG_ACPI_TOSHIBA=m +CONFIG_ACPI_BLACKLIST_YEAR=1999 +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_EC=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_X86_PM_TIMER=y +CONFIG_ACPI_CONTAINER=y +CONFIG_ACPI_SBS=m + +# +# APM (Advanced Power Management) BIOS Support +# +CONFIG_APM=y +# CONFIG_APM_IGNORE_USER_SUSPEND is not set +# CONFIG_APM_DO_ENABLE is not set +CONFIG_APM_CPU_IDLE=y +# CONFIG_APM_DISPLAY_BLANK is not set +CONFIG_APM_RTC_IS_GMT=y +# CONFIG_APM_ALLOW_INTS is not set +# CONFIG_APM_REAL_MODE_POWER_OFF is not set + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m + +# +# CPUFreq processor drivers +# +CONFIG_X86_ACPI_CPUFREQ=m +# CONFIG_X86_POWERNOW_K6 is not set +CONFIG_X86_POWERNOW_K7=y +CONFIG_X86_POWERNOW_K7_ACPI=y +CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_POWERNOW_K8_ACPI=y +# CONFIG_X86_GX_SUSPMOD is not set +CONFIG_X86_SPEEDSTEP_CENTRINO=y +CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y +CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y +CONFIG_X86_SPEEDSTEP_ICH=y +CONFIG_X86_SPEEDSTEP_SMI=y +CONFIG_X86_P4_CLOCKMOD=m +# CONFIG_X86_CPUFREQ_NFORCE2 is not set +CONFIG_X86_LONGRUN=y +# CONFIG_X86_LONGHAUL is not set + +# +# shared options +# +# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set +CONFIG_X86_SPEEDSTEP_LIB=y +# CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set + +# +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# +CONFIG_PCI=y +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GOMMCONFIG is not set +# CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOXEN_FE is not set +CONFIG_PCI_GOANY=y +CONFIG_PCI_BIOS=y +CONFIG_PCI_DIRECT=y +CONFIG_PCI_MMCONFIG=y +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=m +# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set +CONFIG_PCI_MSI=y +# CONFIG_PCI_DEBUG is not set +CONFIG_ISA_DMA_API=y +CONFIG_ISA=y +# CONFIG_EISA is not set +# CONFIG_MCA is not set +# CONFIG_SCx200 is not set +CONFIG_K8_NB=y + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +CONFIG_PCMCIA_PROBE=y +CONFIG_PCCARD_NONSTATIC=y + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_FAKE=m +CONFIG_HOTPLUG_PCI_COMPAQ=m +# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set +CONFIG_HOTPLUG_PCI_IBM=m +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +# CONFIG_LTPC is not set +# CONFIG_COPS is not set +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_TOSHIBA_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PNC2000 is not set +CONFIG_MTD_SC520CDP=m +CONFIG_MTD_NETSC520=m +CONFIG_MTD_TS5500=m +# CONFIG_MTD_SBC_GXX is not set +# CONFIG_MTD_AMD76XROM is not set +# CONFIG_MTD_ICHXROM is not set +CONFIG_MTD_SCB2_FLASH=m +# CONFIG_MTD_NETtel is not set +# CONFIG_MTD_DILNETPC is not set +# CONFIG_MTD_L440GX is not set +CONFIG_MTD_PCI=m +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_ECC_SMC=y +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_CS553X=m +CONFIG_MTD_NAND_NANDSIM=m + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_ISAPNP=y +# CONFIG_PNPBIOS is not set +CONFIG_PNPACPI=y + +# +# Block devices +# +CONFIG_BLK_DEV_FD=m +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_CMD640=y +CONFIG_BLK_DEV_CMD640_ENHANCED=y +CONFIG_BLK_DEV_IDEPNP=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_RZ1000=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +CONFIG_BLK_DEV_AMD74XX=y +CONFIG_BLK_DEV_ATIIXP=y +CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_TRIFLEX=y +# CONFIG_BLK_DEV_CY82C693 is not set +CONFIG_BLK_DEV_CS5520=y +CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_CS5535=y +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +CONFIG_BLK_DEV_SIS5513=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +# CONFIG_IDE_CHIPSETS is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +# CONFIG_SCSI_7000FASST is not set +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AHA152X=m +CONFIG_SCSI_AHA1542=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +# CONFIG_SCSI_DPT_I2O is not set +CONFIG_SCSI_ADVANSYS=m +# CONFIG_SCSI_IN2000 is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +CONFIG_SCSI_BUSLOGIC=m +# CONFIG_SCSI_OMIT_FLASHPOINT is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_SCSI_GDTH=m +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +# CONFIG_SCSI_NCR53C406A is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +# CONFIG_SCSI_SYM53C416 is not set +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DC390T=m +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set + +# +# Device Drivers +# +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m + +# +# I2O device support +# +CONFIG_I2O=m +# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_EXT_ADAPTEC_DMA64=y +CONFIG_I2O_CONFIG=m +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_BUS=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_NET_SB1000=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +# CONFIG_EL1 is not set +# CONFIG_EL2 is not set +# CONFIG_ELPLUS is not set +# CONFIG_EL16 is not set +CONFIG_EL3=m +# CONFIG_3C515 is not set +CONFIG_VORTEX=m +CONFIG_TYPHOON=m +# CONFIG_LANCE is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +CONFIG_ULTRA=m +# CONFIG_SMC9194 is not set +# CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +CONFIG_NET_ISA=y +# CONFIG_E2100 is not set +CONFIG_EWRK3=m +# CONFIG_EEXPRESS is not set +# CONFIG_EEXPRESS_PRO is not set +# CONFIG_HPLAN_PLUS is not set +# CONFIG_HPLAN is not set +# CONFIG_LP486E is not set +# CONFIG_ETH16I is not set +CONFIG_NE2000=m +# CONFIG_ZNET is not set +# CONFIG_SEEQ8005 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_CS89x0 is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_TLAN=m +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y +CONFIG_NET_POCKET=y +CONFIG_ATP=m +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +# CONFIG_IBMTR is not set +CONFIG_IBMOL=m +CONFIG_IBMLS=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set +# CONFIG_SMCTR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +# CONFIG_ARLAN is not set +# CONFIG_WAVELAN is not set +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +# CONFIG_IPW2200_DEBUG is not set +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_BCM43XX=m +CONFIG_BCM43XX_DEBUG=y +CONFIG_BCM43XX_DMA=y +CONFIG_BCM43XX_PIO=y +CONFIG_BCM43XX_DMA_AND_PIO_MODE=y +# CONFIG_BCM43XX_DMA_MODE is not set +# CONFIG_BCM43XX_PIO_MODE is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_IBMTR=m + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_NICSTAR=m +# CONFIG_ATM_NICSTAR_USE_SUNI is not set +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +# CONFIG_ATM_IA is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +# CONFIG_HISAX_16_0 is not set +CONFIG_HISAX_16_3=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +# CONFIG_HISAX_AVM_A1 is not set +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +# CONFIG_HISAX_IX1MICROR2 is not set +CONFIG_HISAX_DIEHLDIVA=y +# CONFIG_HISAX_ASUSCOM is not set +# CONFIG_HISAX_TELEINT is not set +# CONFIG_HISAX_HFCS is not set +CONFIG_HISAX_SEDLBAUER=y +# CONFIG_HISAX_SPORTSTER is not set +# CONFIG_HISAX_MIC is not set +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +# CONFIG_HISAX_ISURF is not set +# CONFIG_HISAX_HSTSAPHIR is not set +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_HDLC=y + +# +# Active 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 + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m + +# +# Active Eicon DIVA Server cards +# +CONFIG_CAPI_EICON=y +CONFIG_ISDN_DIVAS=m +CONFIG_ISDN_DIVAS_BRIPCI=y +CONFIG_ISDN_DIVAS_PRIPCI=y +CONFIG_ISDN_DIVAS_DIVACAPI=m +CONFIG_ISDN_DIVAS_USERIDI=m +CONFIG_ISDN_DIVAS_MAINT=m + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_WISTRON_BTNS=m +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_ESPSERIAL is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y +# CONFIG_SERIAL_8250_FOURPORT is not set +# CONFIG_SERIAL_8250_ACCENT is not set +# CONFIG_SERIAL_8250_BOCA is not set +# CONFIG_SERIAL_8250_HUB6 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_CRASH=m +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +# CONFIG_SC520_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +CONFIG_IBMASR=m +# CONFIG_WAFER_WDT is not set +CONFIG_I6300ESB_WDT=m +CONFIG_I8XX_TCO=m +# CONFIG_SC1200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_SBC8360_WDT is not set +# CONFIG_CPU5_WDT is not set +CONFIG_W83627HF_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_MACHZ_WDT=m +# CONFIG_SBC_EPX_C3_WATCHDOG is not set + +# +# ISA-based Watchdog Cards +# +# CONFIG_PCWATCHDOG is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_WDT is not set + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_AMD=m +CONFIG_HW_RANDOM_GEODE=m +CONFIG_HW_RANDOM_VIA=m +CONFIG_NVRAM=y +CONFIG_RTC=y +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set +CONFIG_SONYPI=m + +# +# Ftape, the floppy tape device driver +# +CONFIG_AGP=y +CONFIG_AGP_ALI=y +CONFIG_AGP_ATI=y +CONFIG_AGP_AMD=y +CONFIG_AGP_AMD64=y +CONFIG_AGP_INTEL=y +CONFIG_AGP_NVIDIA=y +CONFIG_AGP_SIS=y +CONFIG_AGP_SWORKS=y +CONFIG_AGP_VIA=y +CONFIG_AGP_EFFICEON=y +CONFIG_DRM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I810=m +CONFIG_DRM_I830=m +CONFIG_DRM_I915=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +CONFIG_MWAVE=m +CONFIG_PC8736x_GPIO=m +CONFIG_NSC_GPIO=m +CONFIG_CS5535_GPIO=m +# CONFIG_RAW_DRIVER is not set +CONFIG_HPET=y +# CONFIG_HPET_RTC_IRQ is not set +# CONFIG_HPET_MMAP is not set +CONFIG_HANGCHECK_TIMER=m + +# +# TPM devices +# +CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m +CONFIG_TCG_NSC=m +CONFIG_TCG_ATMEL=m +CONFIG_TCG_INFINEON=m +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI1563=m +CONFIG_I2C_ALI15X3=m +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +CONFIG_I2C_I801=m +CONFIG_I2C_I810=m +CONFIG_I2C_PIIX4=m +CONFIG_I2C_ISA=m +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_SCx200_ACB is not set +CONFIG_I2C_SIS5595=m +CONFIG_I2C_SIS630=m +CONFIG_I2C_SIS96X=m +CONFIG_I2C_STUB=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y + +# +# Hardware Monitoring support +# +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_HDAPS=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# +CONFIG_IBM_ASM=m + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y + +# +# Video Capture Adapters +# + +# +# Video Capture Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +# CONFIG_VIDEO_PMS is not set +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_MEYE=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_24XXX=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set + +# +# Radio Adapters +# +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_RADIO_GEMTEK is not set +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_RADIO_SF16FMR2 is not set +# CONFIG_RADIO_TERRATEC is not set +# CONFIG_RADIO_TRUST is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set +CONFIG_USB_DSBR=m + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m + +# +# Miscellaneous devices +# +CONFIG_DVB_PLL=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6421=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_VIDEOBUF=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ARC is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +CONFIG_FB_VGA16=m +CONFIG_FB_VESA=y +# CONFIG_FB_IMAC is not set +# CONFIG_FB_HGA is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_I810=m +CONFIG_FB_I810_GTF=y +CONFIG_FB_I810_I2C=y +CONFIG_FB_INTEL=m +# CONFIG_FB_INTEL_DEBUG is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=m +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_SIS is not set +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_CYBLA=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_GEODE is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_VIDEO_SELECT=y +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_RTCTIMER=m +CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_OPL4_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_MPU401=m + +# +# ISA devices +# +CONFIG_SND_CS4231_LIB=m +CONFIG_SND_ADLIB=m +# CONFIG_SND_AD1816A is not set +# CONFIG_SND_AD1848 is not set +# CONFIG_SND_ALS100 is not set +# CONFIG_SND_AZT2320 is not set +# CONFIG_SND_CMI8330 is not set +# CONFIG_SND_CS4231 is not set +# CONFIG_SND_CS4232 is not set +CONFIG_SND_CS4236=m +# CONFIG_SND_DT019X is not set +# CONFIG_SND_ES968 is not set +# CONFIG_SND_ES1688 is not set +CONFIG_SND_ES18XX=m +# CONFIG_SND_GUSCLASSIC is not set +# CONFIG_SND_GUSEXTREME is not set +# CONFIG_SND_GUSMAX is not set +# CONFIG_SND_INTERWAVE is not set +# CONFIG_SND_INTERWAVE_STB is not set +CONFIG_SND_OPL3SA2=m +# CONFIG_SND_OPTI92X_AD1848 is not set +# CONFIG_SND_OPTI92X_CS4231 is not set +# CONFIG_SND_OPTI93X is not set +CONFIG_SND_MIRO=m +# CONFIG_SND_SB8 is not set +CONFIG_SND_SB16=m +CONFIG_SND_SBAWE=m +# CONFIG_SND_SB16_CSP is not set +# CONFIG_SND_SGALAXY is not set +# CONFIG_SND_SSCAPE is not set +# CONFIG_SND_WAVEFRONT is not set + +# +# PCI devices +# +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_CS5535AUDIO=m +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +CONFIG_USB_HIDINPUT_POWERBOOK=y +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +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_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_WBSD=m + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_ISER=m + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# +CONFIG_EDAC=y + +# +# Reporting subsystems +# +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_AMD76X=m +CONFIG_EDAC_E7XXX=m +CONFIG_EDAC_E752X=m +CONFIG_EDAC_I82875P=m +CONFIG_EDAC_I82860=m +CONFIG_EDAC_K8=m +CONFIG_EDAC_R82600=m +CONFIG_EDAC_POLL=y + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_HIGHMEM=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FRAME_POINTER is not set +CONFIG_UNWIND_INFO=y +CONFIG_STACK_UNWIND=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_EARLY_PRINTK=y +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_DEBUG_STACK_USAGE=y +CONFIG_DEBUG_RODATA=y +CONFIG_4KSTACKS=y +CONFIG_X86_FIND_SMP_CONFIG=y +CONFIG_X86_MPPARSE=y +CONFIG_DOUBLEFAULT=y + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_586=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# +CONFIG_CRYPTO_DEV_PADLOCK=m +CONFIG_CRYPTO_DEV_PADLOCK_AES=y + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_X86_SMP=y +CONFIG_X86_HT=y +CONFIG_X86_BIOS_REBOOT=y +CONFIG_X86_TRAMPOLINE=y +CONFIG_KTIME_SCALAR=y diff --git a/configs/kernel-2.6.18-i686-xen.config b/configs/kernel-2.6.18-i686-xen.config new file mode 100644 index 000000000..b6af8017a --- /dev/null +++ b/configs/kernel-2.6.18-i686-xen.config @@ -0,0 +1,3260 @@ +# i386 +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:40 2006 +# +CONFIG_X86_32=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_X86=y +CONFIG_MMU=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_DMI=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Processor type and features +# +CONFIG_SMP=y +# CONFIG_X86_PC is not set +CONFIG_X86_XEN=y +# CONFIG_X86_ELAN is not set +# CONFIG_X86_VOYAGER is not set +# CONFIG_X86_NUMAQ is not set +# CONFIG_X86_SUMMIT is not set +# CONFIG_X86_BIGSMP is not set +# CONFIG_X86_VISWS is not set +# CONFIG_X86_GENERICARCH is not set +# CONFIG_X86_ES7000 is not set +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set +CONFIG_M686=y +# CONFIG_MPENTIUMII is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MEFFICEON is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MGEODEGX1 is not set +# CONFIG_MGEODE_LX is not set +# CONFIG_MCYRIXIII is not set +# CONFIG_MVIAC3_2 is not set +CONFIG_X86_GENERIC=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_XADD=y +CONFIG_X86_L1_CACHE_SHIFT=7 +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_X86_PPRO_FENCE=y +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_INVLPG=y +CONFIG_X86_BSWAP=y +CONFIG_X86_POPAD_OK=y +CONFIG_X86_CMPXCHG64=y +CONFIG_X86_GOOD_APIC=y +CONFIG_X86_INTEL_USERCOPY=y +CONFIG_X86_USE_PPRO_CHECKSUM=y +CONFIG_NR_CPUS=32 +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_X86_LOCAL_APIC=y +CONFIG_X86_APIC_AUTO=y +CONFIG_X86_IO_APIC=y +CONFIG_VM86=y +CONFIG_TOSHIBA=m +CONFIG_I8K=m +# CONFIG_X86_REBOOTFIXUPS is not set +CONFIG_MICROCODE=y +CONFIG_X86_CPUID=m +CONFIG_SWIOTLB=y + +# +# Firmware Drivers +# +CONFIG_DELL_RBU=m +CONFIG_DCDBAS=m +# CONFIG_NOHIGHMEM is not set +# CONFIG_HIGHMEM4G is not set +CONFIG_HIGHMEM64G=y +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_HIGHMEM=y +CONFIG_X86_PAE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_RESOURCES_64BIT=y +CONFIG_MTRR=y +CONFIG_REGPARM=y +# CONFIG_SECCOMP is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_CRASH_DUMP is not set +CONFIG_PHYSICAL_START=0x400000 +CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y + +# +# Power management options (ACPI, APM) +# +CONFIG_PM=y + +# +# ACPI (Advanced Configuration and Power Interface) Support +# +CONFIG_ACPI=y +CONFIG_ACPI_AC=m +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_VIDEO=m +# CONFIG_ACPI_HOTKEY is not set +CONFIG_ACPI_FAN=y +CONFIG_ACPI_DOCK=m +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_ASUS=m +CONFIG_ACPI_IBM=m +CONFIG_ACPI_TOSHIBA=m +CONFIG_ACPI_BLACKLIST_YEAR=1999 +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_EC=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_ACPI_CONTAINER=y +CONFIG_ACPI_SBS=m + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m + +# +# CPUFreq processor drivers +# +CONFIG_X86_ACPI_CPUFREQ=m +# CONFIG_X86_POWERNOW_K6 is not set +CONFIG_X86_POWERNOW_K7=y +CONFIG_X86_POWERNOW_K7_ACPI=y +CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_POWERNOW_K8_ACPI=y +# CONFIG_X86_GX_SUSPMOD is not set +CONFIG_X86_SPEEDSTEP_CENTRINO=y +CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y +CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y +CONFIG_X86_SPEEDSTEP_ICH=y +CONFIG_X86_SPEEDSTEP_SMI=y +CONFIG_X86_P4_CLOCKMOD=m +# CONFIG_X86_CPUFREQ_NFORCE2 is not set +CONFIG_X86_LONGRUN=y +# CONFIG_X86_LONGHAUL is not set + +# +# shared options +# +# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set +CONFIG_X86_SPEEDSTEP_LIB=y +# CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set + +# +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# +CONFIG_PCI=y +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GOMMCONFIG is not set +# CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOXEN_FE is not set +CONFIG_PCI_GOANY=y +CONFIG_PCI_DIRECT=y +CONFIG_PCI_MMCONFIG=y +CONFIG_XEN_PCIDEV_FRONTEND=y +# CONFIG_XEN_PCIDEV_FE_DEBUG is not set +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=m +# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set +# CONFIG_PCI_DEBUG is not set +CONFIG_ISA_DMA_API=y +# CONFIG_SCx200 is not set +CONFIG_K8_NB=y + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +CONFIG_PCCARD_NONSTATIC=y + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_FAKE=m +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_TOSHIBA_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PNC2000 is not set +CONFIG_MTD_SC520CDP=m +CONFIG_MTD_NETSC520=m +CONFIG_MTD_TS5500=m +# CONFIG_MTD_SBC_GXX is not set +# CONFIG_MTD_AMD76XROM is not set +# CONFIG_MTD_ICHXROM is not set +CONFIG_MTD_SCB2_FLASH=m +# CONFIG_MTD_NETtel is not set +# CONFIG_MTD_DILNETPC is not set +# CONFIG_MTD_L440GX is not set +CONFIG_MTD_PCI=m +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_ECC_SMC=y +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_NANDSIM=m + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_PNPACPI=y + +# +# Block devices +# +CONFIG_BLK_DEV_FD=m +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_CMD640=y +CONFIG_BLK_DEV_CMD640_ENHANCED=y +CONFIG_BLK_DEV_IDEPNP=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_RZ1000=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +CONFIG_BLK_DEV_AMD74XX=y +CONFIG_BLK_DEV_ATIIXP=y +CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_TRIFLEX=y +# CONFIG_BLK_DEV_CY82C693 is not set +CONFIG_BLK_DEV_CS5520=y +CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_CS5535=y +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +CONFIG_BLK_DEV_SIS5513=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +# CONFIG_SCSI_DPT_I2O is not set +CONFIG_SCSI_ADVANSYS=m +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +CONFIG_SCSI_BUSLOGIC=m +# CONFIG_SCSI_OMIT_FLASHPOINT is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DC390T=m +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set + +# +# Device Drivers +# +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m + +# +# I2O device support +# +CONFIG_I2O=m +# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_EXT_ADAPTEC_DMA64=y +CONFIG_I2O_CONFIG=m +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_BUS=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_NET_SB1000=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +CONFIG_VORTEX=m +CONFIG_TYPHOON=m + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_TLAN=m +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y +CONFIG_NET_POCKET=y +CONFIG_ATP=m +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +CONFIG_IBMOL=m +CONFIG_IBMLS=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +# CONFIG_IPW2200_DEBUG is not set +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_BCM43XX=m +CONFIG_BCM43XX_DEBUG=y +CONFIG_BCM43XX_DMA=y +CONFIG_BCM43XX_PIO=y +CONFIG_BCM43XX_DMA_AND_PIO_MODE=y +# CONFIG_BCM43XX_DMA_MODE is not set +# CONFIG_BCM43XX_PIO_MODE is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_IBMTR=m + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_NICSTAR=m +# CONFIG_ATM_NICSTAR_USE_SUNI is not set +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +# CONFIG_ATM_IA is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +CONFIG_HISAX_16_3=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_HDLC=y + +# +# Active cards +# + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m + +# +# Active Eicon DIVA Server cards +# +CONFIG_CAPI_EICON=y +CONFIG_ISDN_DIVAS=m +CONFIG_ISDN_DIVAS_BRIPCI=y +CONFIG_ISDN_DIVAS_PRIPCI=y +CONFIG_ISDN_DIVAS_DIVACAPI=m +CONFIG_ISDN_DIVAS_USERIDI=m +CONFIG_ISDN_DIVAS_MAINT=m + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_WISTRON_BTNS=m +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=m +CONFIG_SERIAL_8250_PCI=m +CONFIG_SERIAL_8250_PNP=m +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=m +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_CRASH=m +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +# CONFIG_SC520_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +CONFIG_IBMASR=m +# CONFIG_WAFER_WDT is not set +CONFIG_I6300ESB_WDT=m +CONFIG_I8XX_TCO=m +# CONFIG_SC1200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_SBC8360_WDT is not set +# CONFIG_CPU5_WDT is not set +CONFIG_W83627HF_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_MACHZ_WDT=m +# CONFIG_SBC_EPX_C3_WATCHDOG is not set + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_AMD=m +CONFIG_HW_RANDOM_GEODE=m +CONFIG_HW_RANDOM_VIA=m +CONFIG_NVRAM=y +CONFIG_RTC=y +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set +CONFIG_SONYPI=m + +# +# Ftape, the floppy tape device driver +# +CONFIG_AGP=y +CONFIG_AGP_ALI=y +CONFIG_AGP_ATI=y +CONFIG_AGP_AMD=y +CONFIG_AGP_AMD64=y +CONFIG_AGP_INTEL=y +CONFIG_AGP_NVIDIA=y +CONFIG_AGP_SIS=y +CONFIG_AGP_SWORKS=y +CONFIG_AGP_VIA=y +CONFIG_AGP_EFFICEON=y +CONFIG_DRM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I810=m +CONFIG_DRM_I830=m +CONFIG_DRM_I915=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +CONFIG_MWAVE=m +CONFIG_PC8736x_GPIO=m +CONFIG_NSC_GPIO=m +CONFIG_CS5535_GPIO=m +# CONFIG_RAW_DRIVER is not set +CONFIG_HPET=y +# CONFIG_HPET_RTC_IRQ is not set +# CONFIG_HPET_MMAP is not set +CONFIG_HANGCHECK_TIMER=m + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI1563=m +CONFIG_I2C_ALI15X3=m +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +CONFIG_I2C_I801=m +CONFIG_I2C_I810=m +CONFIG_I2C_PIIX4=m +CONFIG_I2C_ISA=m +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_SCx200_ACB is not set +CONFIG_I2C_SIS5595=m +CONFIG_I2C_SIS630=m +CONFIG_I2C_SIS96X=m +CONFIG_I2C_STUB=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y + +# +# Hardware Monitoring support +# +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_HDAPS=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# +CONFIG_IBM_ASM=m + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y + +# +# Video Capture Adapters +# + +# +# Video Capture Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_MEYE=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_24XXX=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set + +# +# Radio Adapters +# +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +CONFIG_USB_DSBR=m + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m + +# +# Miscellaneous devices +# +CONFIG_DVB_PLL=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6421=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_VIDEOBUF=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ARC is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +CONFIG_FB_VGA16=m +CONFIG_FB_VESA=y +# CONFIG_FB_HGA is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_I810=m +CONFIG_FB_I810_GTF=y +CONFIG_FB_I810_I2C=y +CONFIG_FB_INTEL=m +# CONFIG_FB_INTEL_DEBUG is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=m +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_SIS is not set +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_CYBLA=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_GEODE is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_VIDEO_SELECT=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_RTCTIMER=m +CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_MPU401=m + +# +# PCI devices +# +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_CS5535AUDIO=m +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +CONFIG_USB_HIDINPUT_POWERBOOK=y +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +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_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_WBSD=m + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_ISER=m + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# +CONFIG_EDAC=y + +# +# Reporting subsystems +# +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_AMD76X=m +CONFIG_EDAC_E7XXX=m +CONFIG_EDAC_E752X=m +CONFIG_EDAC_I82875P=m +CONFIG_EDAC_I82860=m +CONFIG_EDAC_K8=m +CONFIG_EDAC_R82600=m +CONFIG_EDAC_POLL=y + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_HIGHMEM=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FRAME_POINTER is not set +CONFIG_UNWIND_INFO=y +CONFIG_STACK_UNWIND=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_EARLY_PRINTK=y +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_DEBUG_STACK_USAGE=y +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_DEBUG_RODATA=y +CONFIG_4KSTACKS=y +CONFIG_X86_FIND_SMP_CONFIG=y +CONFIG_X86_MPPARSE=y + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_586=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# +CONFIG_CRYPTO_DEV_PADLOCK=m +CONFIG_CRYPTO_DEV_PADLOCK_AES=y +CONFIG_XEN=y +CONFIG_XEN_INTERFACE_VERSION=0x00030203 + +# +# XEN +# +CONFIG_XEN_PRIVILEGED_GUEST=y +# CONFIG_XEN_UNPRIVILEGED_GUEST is not set +CONFIG_XEN_PRIVCMD=y +CONFIG_XEN_XENBUS_DEV=y +CONFIG_XEN_BACKEND=y +CONFIG_XEN_BLKDEV_BACKEND=m +CONFIG_XEN_BLKDEV_TAP=m +CONFIG_XEN_NETDEV_BACKEND=m +# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set +CONFIG_XEN_NETDEV_LOOPBACK=m +CONFIG_XEN_PCIDEV_BACKEND=m +CONFIG_XEN_PCIDEV_BACKEND_VPCI=y +# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set +# CONFIG_XEN_PCIDEV_BE_DEBUG is not set +# CONFIG_XEN_TPMDEV_BACKEND is not set +CONFIG_XEN_BLKDEV_FRONTEND=m +CONFIG_XEN_NETDEV_FRONTEND=m +CONFIG_XEN_FRAMEBUFFER=y +CONFIG_XEN_KEYBOARD=y +CONFIG_XEN_SCRUB_PAGES=y +# CONFIG_XEN_DISABLE_SERIAL is not set +CONFIG_XEN_SYSFS=y +CONFIG_XEN_COMPAT_030002_AND_LATER=y +# CONFIG_XEN_COMPAT_LATEST_ONLY is not set +CONFIG_XEN_COMPAT_030002=y +CONFIG_HAVE_ARCH_ALLOC_SKB=y +CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y +CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y +CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_UTIL=y +CONFIG_XEN_BALLOON=y +CONFIG_XEN_DEVMEM=y +CONFIG_XEN_SKBUFF=y +CONFIG_XEN_REBOOT=y +CONFIG_XEN_SMPBOOT=y + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_X86_SMP=y +CONFIG_X86_BIOS_REBOOT=y +CONFIG_X86_TRAMPOLINE=y +CONFIG_X86_NO_TSS=y +CONFIG_X86_NO_IDT=y +CONFIG_KTIME_SCALAR=y diff --git a/configs/kernel-2.6.18-i686-xen0.config b/configs/kernel-2.6.18-i686-xen0.config new file mode 100644 index 000000000..c6fe1ef9d --- /dev/null +++ b/configs/kernel-2.6.18-i686-xen0.config @@ -0,0 +1,3258 @@ +# i386 +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:40 2006 +# +CONFIG_X86_32=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_X86=y +CONFIG_MMU=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_DMI=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Processor type and features +# +CONFIG_SMP=y +# CONFIG_X86_PC is not set +CONFIG_X86_XEN=y +# CONFIG_X86_ELAN is not set +# CONFIG_X86_VOYAGER is not set +# CONFIG_X86_NUMAQ is not set +# CONFIG_X86_SUMMIT is not set +# CONFIG_X86_BIGSMP is not set +# CONFIG_X86_VISWS is not set +# CONFIG_X86_GENERICARCH is not set +# CONFIG_X86_ES7000 is not set +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set +CONFIG_M686=y +# CONFIG_MPENTIUMII is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MEFFICEON is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MGEODEGX1 is not set +# CONFIG_MGEODE_LX is not set +# CONFIG_MCYRIXIII is not set +# CONFIG_MVIAC3_2 is not set +CONFIG_X86_GENERIC=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_XADD=y +CONFIG_X86_L1_CACHE_SHIFT=7 +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_X86_PPRO_FENCE=y +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_INVLPG=y +CONFIG_X86_BSWAP=y +CONFIG_X86_POPAD_OK=y +CONFIG_X86_CMPXCHG64=y +CONFIG_X86_GOOD_APIC=y +CONFIG_X86_INTEL_USERCOPY=y +CONFIG_X86_USE_PPRO_CHECKSUM=y +CONFIG_NR_CPUS=32 +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_X86_LOCAL_APIC=y +CONFIG_X86_APIC_AUTO=y +CONFIG_X86_IO_APIC=y +CONFIG_VM86=y +CONFIG_TOSHIBA=m +CONFIG_I8K=m +# CONFIG_X86_REBOOTFIXUPS is not set +CONFIG_MICROCODE=y +CONFIG_X86_CPUID=m +CONFIG_SWIOTLB=y + +# +# Firmware Drivers +# +CONFIG_DELL_RBU=m +CONFIG_DCDBAS=m +# CONFIG_NOHIGHMEM is not set +CONFIG_HIGHMEM4G=y +# CONFIG_HIGHMEM64G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_HIGHMEM=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_RESOURCES_64BIT=y +CONFIG_MTRR=y +CONFIG_REGPARM=y +# CONFIG_SECCOMP is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_CRASH_DUMP is not set +CONFIG_PHYSICAL_START=0x400000 +CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y + +# +# Power management options (ACPI, APM) +# +CONFIG_PM=y + +# +# ACPI (Advanced Configuration and Power Interface) Support +# +CONFIG_ACPI=y +CONFIG_ACPI_AC=m +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_VIDEO=m +# CONFIG_ACPI_HOTKEY is not set +CONFIG_ACPI_FAN=y +CONFIG_ACPI_DOCK=m +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_ASUS=m +CONFIG_ACPI_IBM=m +CONFIG_ACPI_TOSHIBA=m +CONFIG_ACPI_BLACKLIST_YEAR=1999 +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_EC=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_ACPI_CONTAINER=y +CONFIG_ACPI_SBS=m + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m + +# +# CPUFreq processor drivers +# +CONFIG_X86_ACPI_CPUFREQ=m +# CONFIG_X86_POWERNOW_K6 is not set +CONFIG_X86_POWERNOW_K7=y +CONFIG_X86_POWERNOW_K7_ACPI=y +CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_POWERNOW_K8_ACPI=y +# CONFIG_X86_GX_SUSPMOD is not set +CONFIG_X86_SPEEDSTEP_CENTRINO=y +CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y +CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y +CONFIG_X86_SPEEDSTEP_ICH=y +CONFIG_X86_SPEEDSTEP_SMI=y +CONFIG_X86_P4_CLOCKMOD=m +# CONFIG_X86_CPUFREQ_NFORCE2 is not set +CONFIG_X86_LONGRUN=y +# CONFIG_X86_LONGHAUL is not set + +# +# shared options +# +# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set +CONFIG_X86_SPEEDSTEP_LIB=y +# CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set + +# +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# +CONFIG_PCI=y +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GOMMCONFIG is not set +# CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOXEN_FE is not set +CONFIG_PCI_GOANY=y +CONFIG_PCI_DIRECT=y +CONFIG_PCI_MMCONFIG=y +CONFIG_XEN_PCIDEV_FRONTEND=y +# CONFIG_XEN_PCIDEV_FE_DEBUG is not set +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=m +# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set +# CONFIG_PCI_DEBUG is not set +CONFIG_ISA_DMA_API=y +# CONFIG_SCx200 is not set +CONFIG_K8_NB=y + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +CONFIG_PCCARD_NONSTATIC=y + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_FAKE=m +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_TOSHIBA_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PNC2000 is not set +CONFIG_MTD_SC520CDP=m +CONFIG_MTD_NETSC520=m +CONFIG_MTD_TS5500=m +# CONFIG_MTD_SBC_GXX is not set +# CONFIG_MTD_AMD76XROM is not set +# CONFIG_MTD_ICHXROM is not set +CONFIG_MTD_SCB2_FLASH=m +# CONFIG_MTD_NETtel is not set +# CONFIG_MTD_DILNETPC is not set +# CONFIG_MTD_L440GX is not set +CONFIG_MTD_PCI=m +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_ECC_SMC=y +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_NANDSIM=m + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_PNPACPI=y + +# +# Block devices +# +CONFIG_BLK_DEV_FD=m +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_CMD640=y +CONFIG_BLK_DEV_CMD640_ENHANCED=y +CONFIG_BLK_DEV_IDEPNP=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_RZ1000=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +CONFIG_BLK_DEV_AMD74XX=y +CONFIG_BLK_DEV_ATIIXP=y +CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_TRIFLEX=y +# CONFIG_BLK_DEV_CY82C693 is not set +CONFIG_BLK_DEV_CS5520=y +CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_CS5535=y +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +CONFIG_BLK_DEV_SIS5513=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +# CONFIG_SCSI_DPT_I2O is not set +CONFIG_SCSI_ADVANSYS=m +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +CONFIG_SCSI_BUSLOGIC=m +# CONFIG_SCSI_OMIT_FLASHPOINT is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DC390T=m +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set + +# +# Device Drivers +# +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m + +# +# I2O device support +# +CONFIG_I2O=m +# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_CONFIG=m +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_BUS=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_NET_SB1000=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +CONFIG_VORTEX=m +CONFIG_TYPHOON=m + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_TLAN=m +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y +CONFIG_NET_POCKET=y +CONFIG_ATP=m +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +CONFIG_IBMOL=m +CONFIG_IBMLS=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +# CONFIG_IPW2200_DEBUG is not set +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_BCM43XX=m +CONFIG_BCM43XX_DEBUG=y +CONFIG_BCM43XX_DMA=y +CONFIG_BCM43XX_PIO=y +CONFIG_BCM43XX_DMA_AND_PIO_MODE=y +# CONFIG_BCM43XX_DMA_MODE is not set +# CONFIG_BCM43XX_PIO_MODE is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_IBMTR=m + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_NICSTAR=m +# CONFIG_ATM_NICSTAR_USE_SUNI is not set +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +# CONFIG_ATM_IA is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +CONFIG_HISAX_16_3=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_HDLC=y + +# +# Active cards +# + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m + +# +# Active Eicon DIVA Server cards +# +CONFIG_CAPI_EICON=y +CONFIG_ISDN_DIVAS=m +CONFIG_ISDN_DIVAS_BRIPCI=y +CONFIG_ISDN_DIVAS_PRIPCI=y +CONFIG_ISDN_DIVAS_DIVACAPI=m +CONFIG_ISDN_DIVAS_USERIDI=m +CONFIG_ISDN_DIVAS_MAINT=m + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_WISTRON_BTNS=m +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=m +CONFIG_SERIAL_8250_PCI=m +CONFIG_SERIAL_8250_PNP=m +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=m +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_CRASH=m +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +# CONFIG_SC520_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +CONFIG_IBMASR=m +# CONFIG_WAFER_WDT is not set +CONFIG_I6300ESB_WDT=m +CONFIG_I8XX_TCO=m +# CONFIG_SC1200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_SBC8360_WDT is not set +# CONFIG_CPU5_WDT is not set +CONFIG_W83627HF_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_MACHZ_WDT=m +# CONFIG_SBC_EPX_C3_WATCHDOG is not set + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_AMD=m +CONFIG_HW_RANDOM_GEODE=m +CONFIG_HW_RANDOM_VIA=m +CONFIG_NVRAM=y +CONFIG_RTC=y +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set +CONFIG_SONYPI=m + +# +# Ftape, the floppy tape device driver +# +CONFIG_AGP=y +CONFIG_AGP_ALI=y +CONFIG_AGP_ATI=y +CONFIG_AGP_AMD=y +CONFIG_AGP_AMD64=y +CONFIG_AGP_INTEL=y +CONFIG_AGP_NVIDIA=y +CONFIG_AGP_SIS=y +CONFIG_AGP_SWORKS=y +CONFIG_AGP_VIA=y +CONFIG_AGP_EFFICEON=y +CONFIG_DRM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I810=m +CONFIG_DRM_I830=m +CONFIG_DRM_I915=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +CONFIG_MWAVE=m +CONFIG_PC8736x_GPIO=m +CONFIG_NSC_GPIO=m +CONFIG_CS5535_GPIO=m +# CONFIG_RAW_DRIVER is not set +CONFIG_HPET=y +# CONFIG_HPET_RTC_IRQ is not set +# CONFIG_HPET_MMAP is not set +CONFIG_HANGCHECK_TIMER=m + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI1563=m +CONFIG_I2C_ALI15X3=m +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +CONFIG_I2C_I801=m +CONFIG_I2C_I810=m +CONFIG_I2C_PIIX4=m +CONFIG_I2C_ISA=m +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_SCx200_ACB is not set +CONFIG_I2C_SIS5595=m +CONFIG_I2C_SIS630=m +CONFIG_I2C_SIS96X=m +CONFIG_I2C_STUB=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y + +# +# Hardware Monitoring support +# +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_HDAPS=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# +CONFIG_IBM_ASM=m + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y + +# +# Video Capture Adapters +# + +# +# Video Capture Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_MEYE=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_24XXX=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set + +# +# Radio Adapters +# +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +CONFIG_USB_DSBR=m + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m + +# +# Miscellaneous devices +# +CONFIG_DVB_PLL=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6421=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_VIDEOBUF=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ARC is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +CONFIG_FB_VGA16=m +CONFIG_FB_VESA=y +# CONFIG_FB_HGA is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_I810=m +CONFIG_FB_I810_GTF=y +CONFIG_FB_I810_I2C=y +CONFIG_FB_INTEL=m +# CONFIG_FB_INTEL_DEBUG is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=m +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_SIS is not set +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_CYBLA=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_GEODE is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_VIDEO_SELECT=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_RTCTIMER=m +CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_MPU401=m + +# +# PCI devices +# +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_CS5535AUDIO=m +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +CONFIG_USB_HIDINPUT_POWERBOOK=y +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +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_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_WBSD=m + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_ISER=m + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# +CONFIG_EDAC=y + +# +# Reporting subsystems +# +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_AMD76X=m +CONFIG_EDAC_E7XXX=m +CONFIG_EDAC_E752X=m +CONFIG_EDAC_I82875P=m +CONFIG_EDAC_I82860=m +CONFIG_EDAC_K8=m +CONFIG_EDAC_R82600=m +CONFIG_EDAC_POLL=y + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_HIGHMEM=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FRAME_POINTER is not set +CONFIG_UNWIND_INFO=y +CONFIG_STACK_UNWIND=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_EARLY_PRINTK=y +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_DEBUG_STACK_USAGE=y +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_DEBUG_RODATA=y +CONFIG_4KSTACKS=y +CONFIG_X86_FIND_SMP_CONFIG=y +CONFIG_X86_MPPARSE=y + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_586=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# +CONFIG_CRYPTO_DEV_PADLOCK=m +CONFIG_CRYPTO_DEV_PADLOCK_AES=y +CONFIG_XEN=y +CONFIG_XEN_INTERFACE_VERSION=0x00030203 + +# +# XEN +# +CONFIG_XEN_PRIVILEGED_GUEST=y +# CONFIG_XEN_UNPRIVILEGED_GUEST is not set +CONFIG_XEN_PRIVCMD=y +CONFIG_XEN_XENBUS_DEV=y +CONFIG_XEN_BACKEND=y +CONFIG_XEN_BLKDEV_BACKEND=y +CONFIG_XEN_BLKDEV_TAP=m +CONFIG_XEN_NETDEV_BACKEND=y +# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set +CONFIG_XEN_NETDEV_LOOPBACK=y +CONFIG_XEN_PCIDEV_BACKEND=m +CONFIG_XEN_PCIDEV_BACKEND_VPCI=y +# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set +# CONFIG_XEN_PCIDEV_BE_DEBUG is not set +# CONFIG_XEN_TPMDEV_BACKEND is not set +CONFIG_XEN_BLKDEV_FRONTEND=m +CONFIG_XEN_NETDEV_FRONTEND=m +CONFIG_XEN_FRAMEBUFFER=y +CONFIG_XEN_KEYBOARD=y +CONFIG_XEN_SCRUB_PAGES=y +# CONFIG_XEN_DISABLE_SERIAL is not set +CONFIG_XEN_SYSFS=y +CONFIG_XEN_COMPAT_030002_AND_LATER=y +# CONFIG_XEN_COMPAT_LATEST_ONLY is not set +CONFIG_XEN_COMPAT_030002=y +CONFIG_HAVE_ARCH_ALLOC_SKB=y +CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y +CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y +CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_UTIL=y +CONFIG_XEN_BALLOON=y +CONFIG_XEN_DEVMEM=y +CONFIG_XEN_SKBUFF=y +CONFIG_XEN_REBOOT=y +CONFIG_XEN_SMPBOOT=y + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_X86_SMP=y +CONFIG_X86_BIOS_REBOOT=y +CONFIG_X86_TRAMPOLINE=y +CONFIG_X86_NO_TSS=y +CONFIG_X86_NO_IDT=y +CONFIG_KTIME_SCALAR=y diff --git a/configs/kernel-2.6.18-i686-xenU.config b/configs/kernel-2.6.18-i686-xenU.config new file mode 100644 index 000000000..309644b0c --- /dev/null +++ b/configs/kernel-2.6.18-i686-xenU.config @@ -0,0 +1,1635 @@ +# i386 +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:40 2006 +# +CONFIG_X86_32=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_X86=y +CONFIG_MMU=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_DMI=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Processor type and features +# +CONFIG_SMP=y +# CONFIG_X86_PC is not set +CONFIG_X86_XEN=y +# CONFIG_X86_ELAN is not set +# CONFIG_X86_VOYAGER is not set +# CONFIG_X86_NUMAQ is not set +# CONFIG_X86_SUMMIT is not set +# CONFIG_X86_BIGSMP is not set +# CONFIG_X86_VISWS is not set +# CONFIG_X86_GENERICARCH is not set +# CONFIG_X86_ES7000 is not set +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set +CONFIG_M686=y +# CONFIG_MPENTIUMII is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MEFFICEON is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MGEODEGX1 is not set +# CONFIG_MGEODE_LX is not set +# CONFIG_MCYRIXIII is not set +# CONFIG_MVIAC3_2 is not set +CONFIG_X86_GENERIC=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_XADD=y +CONFIG_X86_L1_CACHE_SHIFT=7 +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_X86_PPRO_FENCE=y +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_INVLPG=y +CONFIG_X86_BSWAP=y +CONFIG_X86_POPAD_OK=y +CONFIG_X86_CMPXCHG64=y +CONFIG_X86_GOOD_APIC=y +CONFIG_X86_INTEL_USERCOPY=y +CONFIG_X86_USE_PPRO_CHECKSUM=y +CONFIG_NR_CPUS=32 +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_VM86=y +# CONFIG_TOSHIBA is not set +CONFIG_I8K=m +# CONFIG_X86_REBOOTFIXUPS is not set +CONFIG_X86_CPUID=m +CONFIG_SWIOTLB=y + +# +# Firmware Drivers +# +CONFIG_DELL_RBU=m +CONFIG_DCDBAS=m +# CONFIG_NOHIGHMEM is not set +CONFIG_HIGHMEM4G=y +# CONFIG_HIGHMEM64G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_HIGHMEM=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_RESOURCES_64BIT=y +CONFIG_REGPARM=y +# CONFIG_SECCOMP is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_CRASH_DUMP is not set +CONFIG_PHYSICAL_START=0x400000 +CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y + +# +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# +# CONFIG_PCI is not set +CONFIG_ISA_DMA_API=y +# CONFIG_SCx200 is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +# CONFIG_PCMCIA is not set + +# +# PC-card bridges +# + +# +# PCI Hotplug Support +# + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=m +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +# CONFIG_DONGLE is not set + +# +# Old SIR device drivers +# + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VIA_FIR=m +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=m +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +CONFIG_BLK_DEV_FD=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_CMD640=y +CONFIG_BLK_DEV_CMD640_ENHANCED=y +# CONFIG_IDE_ARM is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_SCSI_SATA=m +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_WISTRON_BTNS=m +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINKMP=m +CONFIG_N_HDLC=m +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_CRASH=m + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_SC520_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +CONFIG_IBMASR=m +# CONFIG_WAFER_WDT is not set +# CONFIG_SC1200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_SBC8360_WDT is not set +# CONFIG_CPU5_WDT is not set +CONFIG_W83627HF_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_MACHZ_WDT=m +# CONFIG_SBC_EPX_C3_WATCHDOG is not set +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_VIA=m +CONFIG_NVRAM=y +CONFIG_RTC=y +CONFIG_DTLK=m +CONFIG_R3964=m + +# +# Ftape, the floppy tape device driver +# +# CONFIG_MWAVE is not set +CONFIG_PC8736x_GPIO=m +CONFIG_NSC_GPIO=m +# CONFIG_CS5535_GPIO is not set +# CONFIG_RAW_DRIVER is not set +CONFIG_HANGCHECK_TIMER=m + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +CONFIG_FB_TILEBLITTING=y +# CONFIG_FB_ARC is not set +CONFIG_FB_VGA16=m +CONFIG_FB_VESA=y +# CONFIG_FB_HGA is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_VIDEO_SELECT=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +# CONFIG_SND is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# +# CONFIG_EDAC is not set + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_DS1742=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_HIGHMEM=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FRAME_POINTER is not set +CONFIG_UNWIND_INFO=y +CONFIG_STACK_UNWIND=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_EARLY_PRINTK=y +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_DEBUG_STACK_USAGE=y +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_DEBUG_RODATA=y +CONFIG_4KSTACKS=y + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_586=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# +# CONFIG_CRYPTO_DEV_PADLOCK is not set +CONFIG_XEN=y +CONFIG_XEN_INTERFACE_VERSION=0x00030203 + +# +# XEN +# +# CONFIG_XEN_PRIVILEGED_GUEST is not set +CONFIG_XEN_UNPRIVILEGED_GUEST=y +CONFIG_XEN_PRIVCMD=y +CONFIG_XEN_XENBUS_DEV=y +CONFIG_XEN_BACKEND=y +# CONFIG_XEN_BLKDEV_BACKEND is not set +CONFIG_XEN_BLKDEV_TAP=m +# CONFIG_XEN_NETDEV_BACKEND is not set +# CONFIG_XEN_TPMDEV_BACKEND is not set +CONFIG_XEN_BLKDEV_FRONTEND=y +CONFIG_XEN_NETDEV_FRONTEND=m +CONFIG_XEN_FRAMEBUFFER=y +CONFIG_XEN_KEYBOARD=y +CONFIG_XEN_SCRUB_PAGES=y +CONFIG_XEN_DISABLE_SERIAL=y +CONFIG_XEN_SYSFS=y +CONFIG_XEN_COMPAT_030002_AND_LATER=y +# CONFIG_XEN_COMPAT_LATEST_ONLY is not set +CONFIG_XEN_COMPAT_030002=y +CONFIG_HAVE_ARCH_ALLOC_SKB=y +CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y +CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y +CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_UTIL=y +CONFIG_XEN_BALLOON=y +CONFIG_XEN_DEVMEM=y +CONFIG_XEN_SKBUFF=y +CONFIG_XEN_REBOOT=y +CONFIG_XEN_SMPBOOT=y + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_X86_SMP=y +CONFIG_X86_BIOS_REBOOT=y +CONFIG_X86_TRAMPOLINE=y +CONFIG_X86_NO_TSS=y +CONFIG_X86_NO_IDT=y +CONFIG_KTIME_SCALAR=y diff --git a/configs/kernel-2.6.18-i686.config b/configs/kernel-2.6.18-i686.config new file mode 100644 index 000000000..96690dc15 --- /dev/null +++ b/configs/kernel-2.6.18-i686.config @@ -0,0 +1,3416 @@ +# i386 +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:41 2006 +# +CONFIG_X86_32=y +CONFIG_GENERIC_TIME=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_X86=y +CONFIG_MMU=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_DMI=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Processor type and features +# +# CONFIG_SMP is not set +CONFIG_X86_PC=y +# CONFIG_X86_XEN is not set +# CONFIG_X86_ELAN is not set +# CONFIG_X86_VOYAGER is not set +# CONFIG_X86_NUMAQ is not set +# CONFIG_X86_SUMMIT is not set +# CONFIG_X86_BIGSMP is not set +# CONFIG_X86_VISWS is not set +# CONFIG_X86_GENERICARCH is not set +# CONFIG_X86_ES7000 is not set +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set +CONFIG_M686=y +# CONFIG_MPENTIUMII is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MEFFICEON is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MGEODEGX1 is not set +# CONFIG_MGEODE_LX is not set +# CONFIG_MCYRIXIII is not set +# CONFIG_MVIAC3_2 is not set +CONFIG_X86_GENERIC=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_XADD=y +CONFIG_X86_L1_CACHE_SHIFT=7 +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_X86_PPRO_FENCE=y +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_INVLPG=y +CONFIG_X86_BSWAP=y +CONFIG_X86_POPAD_OK=y +CONFIG_X86_CMPXCHG64=y +CONFIG_X86_GOOD_APIC=y +CONFIG_X86_INTEL_USERCOPY=y +CONFIG_X86_USE_PPRO_CHECKSUM=y +CONFIG_X86_TSC=y +CONFIG_HPET_TIMER=y +CONFIG_HPET_EMULATE_RTC=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_X86_UP_APIC=y +CONFIG_X86_UP_IOAPIC=y +CONFIG_X86_LOCAL_APIC=y +CONFIG_X86_APIC_AUTO=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_MCE=y +# CONFIG_X86_MCE_NONFATAL is not set +CONFIG_X86_MCE_P4THERMAL=y +CONFIG_VM86=y +CONFIG_TOSHIBA=m +CONFIG_I8K=m +# CONFIG_X86_REBOOTFIXUPS is not set +CONFIG_MICROCODE=m +CONFIG_X86_MSR=m +CONFIG_X86_CPUID=m +# CONFIG_SWIOTLB is not set + +# +# Firmware Drivers +# +CONFIG_EDD=m +CONFIG_EFI_VARS=y +CONFIG_DELL_RBU=m +CONFIG_DCDBAS=m +# CONFIG_NOHIGHMEM is not set +CONFIG_HIGHMEM4G=y +# CONFIG_HIGHMEM64G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_HIGHMEM=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_SPARSEMEM_STATIC=y +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_RESOURCES_64BIT=y +CONFIG_HIGHPTE=y +# CONFIG_MATH_EMULATION is not set +CONFIG_MTRR=y +CONFIG_EFI=y +CONFIG_BOOT_IOREMAP=y +CONFIG_REGPARM=y +# CONFIG_SECCOMP is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_KEXEC=y +# CONFIG_CRASH_DUMP is not set +CONFIG_PHYSICAL_START=0x400000 +# CONFIG_COMPAT_VDSO is not set +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y + +# +# Power management options (ACPI, APM) +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +CONFIG_SOFTWARE_SUSPEND=y +CONFIG_PM_STD_PARTITION="" + +# +# ACPI (Advanced Configuration and Power Interface) Support +# +CONFIG_ACPI=y +CONFIG_ACPI_SLEEP=y +CONFIG_ACPI_SLEEP_PROC_FS=y +# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set +CONFIG_ACPI_AC=m +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_VIDEO=m +# CONFIG_ACPI_HOTKEY is not set +CONFIG_ACPI_FAN=y +CONFIG_ACPI_DOCK=m +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_ASUS=m +CONFIG_ACPI_IBM=m +CONFIG_ACPI_TOSHIBA=m +CONFIG_ACPI_BLACKLIST_YEAR=1999 +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_EC=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_X86_PM_TIMER=y +CONFIG_ACPI_CONTAINER=m +CONFIG_ACPI_SBS=m + +# +# APM (Advanced Power Management) BIOS Support +# +CONFIG_APM=y +# CONFIG_APM_IGNORE_USER_SUSPEND is not set +# CONFIG_APM_DO_ENABLE is not set +CONFIG_APM_CPU_IDLE=y +# CONFIG_APM_DISPLAY_BLANK is not set +CONFIG_APM_RTC_IS_GMT=y +# CONFIG_APM_ALLOW_INTS is not set +# CONFIG_APM_REAL_MODE_POWER_OFF is not set + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m + +# +# CPUFreq processor drivers +# +CONFIG_X86_ACPI_CPUFREQ=m +# CONFIG_X86_POWERNOW_K6 is not set +CONFIG_X86_POWERNOW_K7=y +CONFIG_X86_POWERNOW_K7_ACPI=y +CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_POWERNOW_K8_ACPI=y +# CONFIG_X86_GX_SUSPMOD is not set +CONFIG_X86_SPEEDSTEP_CENTRINO=y +CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y +CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y +CONFIG_X86_SPEEDSTEP_ICH=y +CONFIG_X86_SPEEDSTEP_SMI=y +CONFIG_X86_P4_CLOCKMOD=m +# CONFIG_X86_CPUFREQ_NFORCE2 is not set +CONFIG_X86_LONGRUN=y +# CONFIG_X86_LONGHAUL is not set + +# +# shared options +# +# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set +CONFIG_X86_SPEEDSTEP_LIB=y +# CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK is not set + +# +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# +CONFIG_PCI=y +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GOMMCONFIG is not set +# CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOXEN_FE is not set +CONFIG_PCI_GOANY=y +CONFIG_PCI_BIOS=y +CONFIG_PCI_DIRECT=y +CONFIG_PCI_MMCONFIG=y +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=m +# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set +CONFIG_PCI_MSI=y +# CONFIG_PCI_DEBUG is not set +CONFIG_ISA_DMA_API=y +CONFIG_ISA=y +# CONFIG_EISA is not set +# CONFIG_MCA is not set +# CONFIG_SCx200 is not set +CONFIG_K8_NB=y + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +CONFIG_PCMCIA_PROBE=y +CONFIG_PCCARD_NONSTATIC=y + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_FAKE=m +CONFIG_HOTPLUG_PCI_COMPAQ=m +# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set +CONFIG_HOTPLUG_PCI_IBM=m +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_MISC=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +# CONFIG_LTPC is not set +# CONFIG_COPS is not set +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# +CONFIG_IRPORT_SIR=m + +# +# Old Serial dongle support +# +# CONFIG_DONGLE_OLD is not set + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_TOSHIBA_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PNC2000 is not set +CONFIG_MTD_SC520CDP=m +CONFIG_MTD_NETSC520=m +CONFIG_MTD_TS5500=m +# CONFIG_MTD_SBC_GXX is not set +# CONFIG_MTD_AMD76XROM is not set +# CONFIG_MTD_ICHXROM is not set +CONFIG_MTD_SCB2_FLASH=m +# CONFIG_MTD_NETtel is not set +# CONFIG_MTD_DILNETPC is not set +# CONFIG_MTD_L440GX is not set +CONFIG_MTD_PCI=m +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_ECC_SMC=y +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_CS553X=m +CONFIG_MTD_NAND_NANDSIM=m + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_ISAPNP=y +# CONFIG_PNPBIOS is not set +CONFIG_PNPACPI=y + +# +# Block devices +# +CONFIG_BLK_DEV_FD=m +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_CMD640=y +CONFIG_BLK_DEV_CMD640_ENHANCED=y +CONFIG_BLK_DEV_IDEPNP=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_RZ1000=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +CONFIG_BLK_DEV_AMD74XX=y +CONFIG_BLK_DEV_ATIIXP=y +CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_TRIFLEX=y +# CONFIG_BLK_DEV_CY82C693 is not set +CONFIG_BLK_DEV_CS5520=y +CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_CS5535=y +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +CONFIG_BLK_DEV_SIS5513=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +# CONFIG_IDE_CHIPSETS is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +# CONFIG_SCSI_7000FASST is not set +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AHA152X=m +CONFIG_SCSI_AHA1542=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +# CONFIG_SCSI_DPT_I2O is not set +CONFIG_SCSI_ADVANSYS=m +# CONFIG_SCSI_IN2000 is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +CONFIG_SCSI_BUSLOGIC=m +# CONFIG_SCSI_OMIT_FLASHPOINT is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_SCSI_GDTH=m +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +# CONFIG_SCSI_NCR53C406A is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +# CONFIG_SCSI_SYM53C416 is not set +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DC390T=m +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_ULTRASTOR is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set + +# +# Device Drivers +# +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m + +# +# I2O device support +# +CONFIG_I2O=m +# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_CONFIG=m +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_BUS=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_NET_SB1000=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +# CONFIG_EL1 is not set +# CONFIG_EL2 is not set +# CONFIG_ELPLUS is not set +# CONFIG_EL16 is not set +CONFIG_EL3=m +# CONFIG_3C515 is not set +CONFIG_VORTEX=m +CONFIG_TYPHOON=m +# CONFIG_LANCE is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +CONFIG_ULTRA=m +# CONFIG_SMC9194 is not set +# CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +# CONFIG_PCMCIA_XIRTULIP is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +CONFIG_NET_ISA=y +# CONFIG_E2100 is not set +CONFIG_EWRK3=m +# CONFIG_EEXPRESS is not set +# CONFIG_EEXPRESS_PRO is not set +# CONFIG_HPLAN_PLUS is not set +# CONFIG_HPLAN is not set +# CONFIG_LP486E is not set +# CONFIG_ETH16I is not set +CONFIG_NE2000=m +# CONFIG_ZNET is not set +# CONFIG_SEEQ8005 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_CS89x0 is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_TLAN=m +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y +CONFIG_NET_POCKET=y +CONFIG_ATP=m +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +# CONFIG_IBMTR is not set +CONFIG_IBMOL=m +CONFIG_IBMLS=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set +# CONFIG_SMCTR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +# CONFIG_ARLAN is not set +# CONFIG_WAVELAN is not set +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +# CONFIG_IPW2200_DEBUG is not set +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_BCM43XX=m +CONFIG_BCM43XX_DEBUG=y +CONFIG_BCM43XX_DMA=y +CONFIG_BCM43XX_PIO=y +CONFIG_BCM43XX_DMA_AND_PIO_MODE=y +# CONFIG_BCM43XX_DMA_MODE is not set +# CONFIG_BCM43XX_PIO_MODE is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_IBMTR=m + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_NICSTAR=m +# CONFIG_ATM_NICSTAR_USE_SUNI is not set +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +# CONFIG_ATM_IA is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DRV_LOOP=m +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +# CONFIG_HISAX_16_0 is not set +CONFIG_HISAX_16_3=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +# CONFIG_HISAX_AVM_A1 is not set +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +# CONFIG_HISAX_IX1MICROR2 is not set +CONFIG_HISAX_DIEHLDIVA=y +# CONFIG_HISAX_ASUSCOM is not set +# CONFIG_HISAX_TELEINT is not set +# CONFIG_HISAX_HFCS is not set +CONFIG_HISAX_SEDLBAUER=y +# CONFIG_HISAX_SPORTSTER is not set +# CONFIG_HISAX_MIC is not set +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +# CONFIG_HISAX_ISURF is not set +# CONFIG_HISAX_HSTSAPHIR is not set +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_HDLC=y + +# +# Active 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_HYSDN=m +CONFIG_HYSDN_CAPI=y + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m + +# +# Active Eicon DIVA Server cards +# +CONFIG_CAPI_EICON=y +CONFIG_ISDN_DIVAS=m +CONFIG_ISDN_DIVAS_BRIPCI=y +CONFIG_ISDN_DIVAS_PRIPCI=y +CONFIG_ISDN_DIVAS_DIVACAPI=m +CONFIG_ISDN_DIVAS_USERIDI=m +CONFIG_ISDN_DIVAS_MAINT=m + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_WISTRON_BTNS=m +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_ESPSERIAL is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y +# CONFIG_SERIAL_8250_FOURPORT is not set +# CONFIG_SERIAL_8250_ACCENT is not set +# CONFIG_SERIAL_8250_BOCA is not set +# CONFIG_SERIAL_8250_HUB6 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_CRASH=m +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +# CONFIG_SC520_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +CONFIG_IBMASR=m +# CONFIG_WAFER_WDT is not set +CONFIG_I6300ESB_WDT=m +CONFIG_I8XX_TCO=m +# CONFIG_SC1200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_SBC8360_WDT is not set +# CONFIG_CPU5_WDT is not set +CONFIG_W83627HF_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_MACHZ_WDT=m +# CONFIG_SBC_EPX_C3_WATCHDOG is not set + +# +# ISA-based Watchdog Cards +# +# CONFIG_PCWATCHDOG is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_WDT is not set + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_AMD=m +CONFIG_HW_RANDOM_GEODE=m +CONFIG_HW_RANDOM_VIA=m +CONFIG_NVRAM=y +CONFIG_RTC=y +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set +CONFIG_SONYPI=m + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +CONFIG_AGP=y +CONFIG_AGP_ALI=y +CONFIG_AGP_ATI=y +CONFIG_AGP_AMD=y +CONFIG_AGP_AMD64=y +CONFIG_AGP_INTEL=y +CONFIG_AGP_NVIDIA=y +CONFIG_AGP_SIS=y +CONFIG_AGP_SWORKS=y +CONFIG_AGP_VIA=y +CONFIG_AGP_EFFICEON=y +CONFIG_DRM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I810=m +CONFIG_DRM_I830=m +CONFIG_DRM_I915=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +CONFIG_MWAVE=m +CONFIG_PC8736x_GPIO=m +CONFIG_NSC_GPIO=m +CONFIG_CS5535_GPIO=m +# CONFIG_RAW_DRIVER is not set +CONFIG_HPET=y +# CONFIG_HPET_RTC_IRQ is not set +# CONFIG_HPET_MMAP is not set +CONFIG_HANGCHECK_TIMER=m + +# +# TPM devices +# +CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m +CONFIG_TCG_NSC=m +CONFIG_TCG_ATMEL=m +CONFIG_TCG_INFINEON=m +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI1563=m +CONFIG_I2C_ALI15X3=m +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +# CONFIG_I2C_ELEKTOR is not set +CONFIG_I2C_I801=m +CONFIG_I2C_I810=m +CONFIG_I2C_PIIX4=m +CONFIG_I2C_ISA=m +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_SCx200_ACB is not set +CONFIG_I2C_SIS5595=m +CONFIG_I2C_SIS630=m +CONFIG_I2C_SIS96X=m +CONFIG_I2C_STUB=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y + +# +# Hardware Monitoring support +# +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_HDAPS=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# +CONFIG_IBM_ASM=m + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y + +# +# Video Capture Adapters +# + +# +# Video Capture Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +# CONFIG_VIDEO_PMS is not set +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_MEYE=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_24XXX=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set + +# +# Radio Adapters +# +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_RADIO_GEMTEK is not set +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_RADIO_SF16FMR2 is not set +# CONFIG_RADIO_TERRATEC is not set +# CONFIG_RADIO_TRUST is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set +CONFIG_USB_DSBR=m + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m + +# +# Miscellaneous devices +# +CONFIG_DVB_PLL=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6421=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_VIDEOBUF=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ARC is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +CONFIG_FB_VGA16=m +CONFIG_FB_VESA=y +# CONFIG_FB_IMAC is not set +# CONFIG_FB_HGA is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_I810=m +CONFIG_FB_I810_GTF=y +CONFIG_FB_I810_I2C=y +CONFIG_FB_INTEL=m +# CONFIG_FB_INTEL_DEBUG is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=m +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_SIS is not set +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_CYBLA=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_GEODE is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_VIDEO_SELECT=y +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_RTCTIMER=m +CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_OPL4_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_MPU401=m + +# +# ISA devices +# +CONFIG_SND_CS4231_LIB=m +CONFIG_SND_ADLIB=m +# CONFIG_SND_AD1816A is not set +# CONFIG_SND_AD1848 is not set +# CONFIG_SND_ALS100 is not set +# CONFIG_SND_AZT2320 is not set +# CONFIG_SND_CMI8330 is not set +# CONFIG_SND_CS4231 is not set +# CONFIG_SND_CS4232 is not set +CONFIG_SND_CS4236=m +# CONFIG_SND_DT019X is not set +# CONFIG_SND_ES968 is not set +# CONFIG_SND_ES1688 is not set +CONFIG_SND_ES18XX=m +# CONFIG_SND_GUSCLASSIC is not set +# CONFIG_SND_GUSEXTREME is not set +# CONFIG_SND_GUSMAX is not set +# CONFIG_SND_INTERWAVE is not set +# CONFIG_SND_INTERWAVE_STB is not set +CONFIG_SND_OPL3SA2=m +# CONFIG_SND_OPTI92X_AD1848 is not set +# CONFIG_SND_OPTI92X_CS4231 is not set +# CONFIG_SND_OPTI93X is not set +CONFIG_SND_MIRO=m +# CONFIG_SND_SB8 is not set +CONFIG_SND_SB16=m +CONFIG_SND_SBAWE=m +# CONFIG_SND_SB16_CSP is not set +# CONFIG_SND_SGALAXY is not set +# CONFIG_SND_SSCAPE is not set +# CONFIG_SND_WAVEFRONT is not set + +# +# PCI devices +# +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_CS5535AUDIO=m +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +CONFIG_USB_HIDINPUT_POWERBOOK=y +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +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_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_WBSD=m + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_ISER=m + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# +CONFIG_EDAC=y + +# +# Reporting subsystems +# +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_AMD76X=m +CONFIG_EDAC_E7XXX=m +CONFIG_EDAC_E752X=m +CONFIG_EDAC_I82875P=m +CONFIG_EDAC_I82860=m +CONFIG_EDAC_K8=m +CONFIG_EDAC_R82600=m +CONFIG_EDAC_POLL=y + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_HIGHMEM=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FRAME_POINTER is not set +CONFIG_UNWIND_INFO=y +CONFIG_STACK_UNWIND=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_EARLY_PRINTK=y +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_DEBUG_STACK_USAGE=y + +# +# Page alloc debug is incompatible with Software Suspend on i386 +# +CONFIG_DEBUG_RODATA=y +CONFIG_4KSTACKS=y +CONFIG_X86_FIND_SMP_CONFIG=y +CONFIG_X86_MPPARSE=y +CONFIG_DOUBLEFAULT=y + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_586=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# +CONFIG_CRYPTO_DEV_PADLOCK=m +CONFIG_CRYPTO_DEV_PADLOCK_AES=y + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_X86_BIOS_REBOOT=y +CONFIG_KTIME_SCALAR=y diff --git a/configs/kernel-2.6.18-ia64-xen.config b/configs/kernel-2.6.18-ia64-xen.config new file mode 100644 index 000000000..7fea409eb --- /dev/null +++ b/configs/kernel-2.6.18-ia64-xen.config @@ -0,0 +1,2883 @@ +# ia64 +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:41 2006 +# +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_BLK_DEV_IO_TRACE=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Processor type and features +# +CONFIG_IA64=y +CONFIG_64BIT=y +CONFIG_MMU=y +CONFIG_SWIOTLB=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_TIME_INTERPOLATION=y +CONFIG_DMI=y +CONFIG_EFI=y +CONFIG_GENERIC_IOMAP=y +CONFIG_XEN=y +CONFIG_XEN_IA64_VDSO_PARAVIRT=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_DMA_IS_DMA32=y +CONFIG_AUDIT_ARCH=y +# CONFIG_IA64_GENERIC is not set +CONFIG_IA64_DIG=y +# CONFIG_IA64_HP_ZX1 is not set +# CONFIG_IA64_HP_ZX1_SWIOTLB is not set +# CONFIG_IA64_SGI_SN2 is not set +# CONFIG_IA64_HP_SIM is not set +# CONFIG_ITANIUM is not set +CONFIG_MCKINLEY=y +# CONFIG_IA64_PAGE_SIZE_4KB is not set +# CONFIG_IA64_PAGE_SIZE_8KB is not set +CONFIG_IA64_PAGE_SIZE_16KB=y +# CONFIG_IA64_PAGE_SIZE_64KB is not set +CONFIG_PGTABLE_3=y +# CONFIG_PGTABLE_4 is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_IA64_L1_CACHE_SHIFT=7 +CONFIG_IA64_CYCLONE=y +CONFIG_IOSAPIC=y +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_SMP=y +CONFIG_NR_CPUS=1024 +CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_SCHED_SMT=y +# CONFIG_PERMIT_BSP_REMOVE is not set +# CONFIG_PREEMPT is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_RESOURCES_64BIT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_DISCONTIGMEM_ENABLE=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +# CONFIG_VIRTUAL_MEM_MAP is not set +# CONFIG_IA32_SUPPORT is not set +CONFIG_IA64_MCA_RECOVERY=m +CONFIG_PERFMON=y +CONFIG_IA64_PALINFO=y + +# +# Firmware Drivers +# +CONFIG_EFI_VARS=y +CONFIG_EFI_PCDP=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y + +# +# Power management and ACPI +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set + +# +# ACPI (Advanced Configuration and Power Interface) Support +# +CONFIG_ACPI=y +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_FAN=y +# CONFIG_ACPI_DOCK is not set +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_BLACKLIST_YEAR=0 +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_EC=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_ACPI_CONTAINER=y + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=m +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m + +# +# CPUFreq processor drivers +# +CONFIG_IA64_ACPI_CPUFREQ=m + +# +# Bus options (PCI, PCMCIA) +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_XEN_PCIDEV_FRONTEND=y +# CONFIG_XEN_PCIDEV_FE_DEBUG is not set +CONFIG_PCIEPORTBUS=y +# CONFIG_HOTPLUG_PCI_PCIE is not set +# CONFIG_PCI_DEBUG is not set + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_FAKE=m +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +# CONFIG_HOTPLUG_PCI_CPCI is not set +CONFIG_HOTPLUG_PCI_SHPC=m +CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE=y + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +CONFIG_PCCARD_NONSTATIC=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +CONFIG_IEEE80211_DEBUG=y +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_PNPACPI=y + +# +# Block devices +# +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_IDE_MAX_HWIFS=4 +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPNP=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_TRIFLEX=y +# CONFIG_BLK_DEV_CY82C693 is not set +CONFIG_BLK_DEV_CS5520=y +CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DC390T=m +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_PCMCIA_FDOMAIN is not set +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set + +# +# Device Drivers +# +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_NET_SB1000=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +CONFIG_VORTEX=m +CONFIG_TYPHOON=m + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y +CONFIG_NET_POCKET=y +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +CONFIG_IBMOL=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +CONFIG_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +# CONFIG_BCM43XX is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +CONFIG_HISAX_16_3=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_HDLC=y + +# +# Active cards +# + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m + +# +# Active Eicon DIVA Server cards +# +# CONFIG_CAPI_EICON is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=m +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_CRASH is not set +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +CONFIG_I8XX_TCO=m + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +# CONFIG_HW_RANDOM is not set +CONFIG_EFI_RTC=y +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +CONFIG_AGP=y +CONFIG_AGP_SIS=y +CONFIG_AGP_VIA=y +CONFIG_AGP_I460=y +CONFIG_DRM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +# CONFIG_RAW_DRIVER is not set +# CONFIG_HPET is not set +CONFIG_HANGCHECK_TIMER=m + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_ISA=m +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +CONFIG_I2C_STUB=m +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y + +# +# Hardware Monitoring support +# +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y + +# +# Video Capture Adapters +# + +# +# Video Capture Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_24XXX=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set + +# +# Radio Adapters +# +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +CONFIG_USB_DSBR=m + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m + +# +# Miscellaneous devices +# +CONFIG_DVB_PLL=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6421=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_VIDEOBUF=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=m +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_MPU401=m + +# +# PCI devices +# +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +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_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_ISER=m + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_IRQ_PER_CPU=y + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_IA64_GRANULE_16MB is not set +CONFIG_IA64_GRANULE_64MB=y +# CONFIG_IA64_PRINT_HAZARDS is not set +# CONFIG_DISABLE_VHPT is not set +# CONFIG_IA64_DEBUG_CMPXCHG is not set +# CONFIG_IA64_DEBUG_IRQ is not set + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# +# CONFIG_XEN_UTIL is not set +CONFIG_HAVE_ARCH_ALLOC_SKB=y +CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y +CONFIG_XEN_BALLOON=y +CONFIG_XEN_SKBUFF=y +# CONFIG_XEN_DEVMEM is not set +CONFIG_XEN_REBOOT=y +# CONFIG_XEN_SMPBOOT is not set +CONFIG_XEN_INTERFACE_VERSION=0x00030203 + +# +# XEN +# +CONFIG_XEN_PRIVILEGED_GUEST=y +# CONFIG_XEN_UNPRIVILEGED_GUEST is not set +CONFIG_XEN_PRIVCMD=y +CONFIG_XEN_XENBUS_DEV=y +CONFIG_XEN_BACKEND=y +CONFIG_XEN_BLKDEV_BACKEND=m +# CONFIG_XEN_BLKDEV_TAP is not set +CONFIG_XEN_NETDEV_BACKEND=m +# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set +CONFIG_XEN_NETDEV_LOOPBACK=m +# CONFIG_XEN_PCIDEV_BACKEND is not set +# CONFIG_XEN_TPMDEV_BACKEND is not set +CONFIG_XEN_BLKDEV_FRONTEND=m +CONFIG_XEN_NETDEV_FRONTEND=m +CONFIG_XEN_FRAMEBUFFER=y +CONFIG_XEN_KEYBOARD=y +CONFIG_XEN_SCRUB_PAGES=y +CONFIG_XEN_DISABLE_SERIAL=y +CONFIG_XEN_SYSFS=y +CONFIG_XEN_COMPAT_030002_AND_LATER=y +# CONFIG_XEN_COMPAT_LATEST_ONLY is not set +CONFIG_XEN_COMPAT_030002=y +CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y +CONFIG_NO_IDLE_HZ=y diff --git a/configs/kernel-2.6.18-ia64.config b/configs/kernel-2.6.18-ia64.config new file mode 100644 index 000000000..e6c8653c4 --- /dev/null +++ b/configs/kernel-2.6.18-ia64.config @@ -0,0 +1,2902 @@ +# ia64 +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:41 2006 +# +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_BLK_DEV_IO_TRACE=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Processor type and features +# +CONFIG_IA64=y +CONFIG_64BIT=y +CONFIG_MMU=y +CONFIG_SWIOTLB=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_TIME_INTERPOLATION=y +CONFIG_DMI=y +CONFIG_EFI=y +CONFIG_GENERIC_IOMAP=y +# CONFIG_XEN is not set +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_IA64_UNCACHED_ALLOCATOR=y +CONFIG_DMA_IS_DMA32=y +CONFIG_AUDIT_ARCH=y +CONFIG_IA64_GENERIC=y +# CONFIG_IA64_DIG is not set +# CONFIG_IA64_HP_ZX1 is not set +# CONFIG_IA64_HP_ZX1_SWIOTLB is not set +# CONFIG_IA64_SGI_SN2 is not set +# CONFIG_IA64_HP_SIM is not set +# CONFIG_ITANIUM is not set +CONFIG_MCKINLEY=y +# CONFIG_IA64_PAGE_SIZE_4KB is not set +# CONFIG_IA64_PAGE_SIZE_8KB is not set +CONFIG_IA64_PAGE_SIZE_16KB=y +# CONFIG_IA64_PAGE_SIZE_64KB is not set +CONFIG_PGTABLE_3=y +# CONFIG_PGTABLE_4 is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_IA64_L1_CACHE_SHIFT=7 +CONFIG_IA64_CYCLONE=y +CONFIG_IOSAPIC=y +CONFIG_IA64_SGI_SN_XP=y +CONFIG_FORCE_MAX_ZONEORDER=17 +CONFIG_SMP=y +CONFIG_NR_CPUS=1024 +CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_SCHED_SMT=y +# CONFIG_PERMIT_BSP_REMOVE is not set +# CONFIG_PREEMPT is not set +CONFIG_SELECT_MEMORY_MODEL=y +# CONFIG_FLATMEM_MANUAL is not set +# CONFIG_DISCONTIGMEM_MANUAL is not set +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_NEED_MULTIPLE_NODES=y +CONFIG_HAVE_MEMORY_PRESENT=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_MEMORY_HOTPLUG=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_MIGRATION=y +CONFIG_RESOURCES_64BIT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_DISCONTIGMEM_ENABLE=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y +CONFIG_NUMA=y +CONFIG_NODES_SHIFT=8 +CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y +CONFIG_HAVE_ARCH_NODEDATA_EXTENSION=y +# CONFIG_IA32_SUPPORT is not set +CONFIG_IA64_MCA_RECOVERY=m +CONFIG_PERFMON=y +CONFIG_IA64_PALINFO=y +CONFIG_SGI_SN=y + +# +# SN Devices +# +CONFIG_SGI_IOC4=y +CONFIG_SGI_IOC3=m + +# +# Firmware Drivers +# +CONFIG_EFI_VARS=y +CONFIG_EFI_PCDP=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y + +# +# Power management and ACPI +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set + +# +# ACPI (Advanced Configuration and Power Interface) Support +# +CONFIG_ACPI=y +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_FAN=y +# CONFIG_ACPI_DOCK is not set +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_NUMA=y +CONFIG_ACPI_BLACKLIST_YEAR=0 +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_EC=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_ACPI_CONTAINER=y +CONFIG_ACPI_HOTPLUG_MEMORY=y + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=m +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m + +# +# CPUFreq processor drivers +# +CONFIG_IA64_ACPI_CPUFREQ=m + +# +# Bus options (PCI, PCMCIA) +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCIEPORTBUS=y +# CONFIG_HOTPLUG_PCI_PCIE is not set +CONFIG_PCI_MSI=y +# CONFIG_PCI_DEBUG is not set + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_FAKE=m +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +# CONFIG_HOTPLUG_PCI_CPCI is not set +CONFIG_HOTPLUG_PCI_SHPC=m +CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE=y +CONFIG_HOTPLUG_PCI_SGI=m + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +CONFIG_PCCARD_NONSTATIC=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +CONFIG_IEEE80211_DEBUG=y +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_PNPACPI=y + +# +# Block devices +# +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_IDE_MAX_HWIFS=4 +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPNP=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_TRIFLEX=y +# CONFIG_BLK_DEV_CY82C693 is not set +CONFIG_BLK_DEV_CS5520=y +CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SGIIOC4=y +CONFIG_BLK_DEV_SIIMAGE=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DC390T=m +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_PCMCIA_FDOMAIN is not set +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set + +# +# Device Drivers +# +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_NET_SB1000=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +CONFIG_VORTEX=m +CONFIG_TYPHOON=m + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y +CONFIG_NET_POCKET=y +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +CONFIG_IBMOL=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +CONFIG_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +# CONFIG_BCM43XX is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +CONFIG_HISAX_16_3=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_HDLC=y + +# +# Active cards +# + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m + +# +# Active Eicon DIVA Server cards +# +# CONFIG_CAPI_EICON is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set +CONFIG_SGI_SNSC=y +CONFIG_SGI_TIOCX=y +CONFIG_SGI_MBCS=m + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=16 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_SGI_L1_CONSOLE=y +CONFIG_SERIAL_JSM=m +CONFIG_SERIAL_SGI_IOC4=m +CONFIG_SERIAL_SGI_IOC3=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_CRASH is not set +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +CONFIG_I8XX_TCO=m + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +# CONFIG_HW_RANDOM is not set +CONFIG_EFI_RTC=y +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +CONFIG_AGP=y +CONFIG_AGP_SIS=y +CONFIG_AGP_VIA=y +CONFIG_AGP_I460=y +CONFIG_AGP_HP_ZX1=y +CONFIG_AGP_SGI_TIOCA=y +CONFIG_DRM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +# CONFIG_RAW_DRIVER is not set +# CONFIG_HPET is not set +CONFIG_HANGCHECK_TIMER=m +CONFIG_MMTIMER=y + +# +# TPM devices +# +CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m +CONFIG_TCG_NSC=m +CONFIG_TCG_ATMEL=m +# CONFIG_TCG_INFINEON is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_ISA=m +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +CONFIG_I2C_STUB=m +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y + +# +# Hardware Monitoring support +# +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y + +# +# Video Capture Adapters +# + +# +# Video Capture Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_24XXX=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set + +# +# Radio Adapters +# +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +CONFIG_USB_DSBR=m + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m + +# +# Miscellaneous devices +# +CONFIG_DVB_PLL=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6421=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_VIDEOBUF=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=m +CONFIG_FB_CFB_COPYAREA=m +CONFIG_FB_CFB_IMAGEBLIT=m +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=m +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_SIS is not set +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_MPU401=m + +# +# PCI devices +# +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +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_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_IPATH_CORE=m +CONFIG_INFINIBAND_IPATH=m +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_ISER=m + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_IRQ_PER_CPU=y + +# +# HP Simulator drivers +# +# CONFIG_HP_SIMETH is not set +# CONFIG_HP_SIMSERIAL is not set +# CONFIG_HP_SIMSCSI is not set + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_IA64_GRANULE_16MB=y +# CONFIG_IA64_GRANULE_64MB is not set +# CONFIG_IA64_PRINT_HAZARDS is not set +# CONFIG_DISABLE_VHPT is not set +# CONFIG_IA64_DEBUG_CMPXCHG is not set +# CONFIG_IA64_DEBUG_IRQ is not set + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# diff --git a/configs/kernel-2.6.18-ppc-smp.config b/configs/kernel-2.6.18-ppc-smp.config new file mode 100644 index 000000000..66147ea3d --- /dev/null +++ b/configs/kernel-2.6.18-ppc-smp.config @@ -0,0 +1,3204 @@ +# powerpc +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:41 2006 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_IRQ_PER_CPU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +CONFIG_GENERIC_TBSYNC=y +CONFIG_AUDIT_ARCH=y +# CONFIG_DEFAULT_UIMAGE is not set + +# +# Processor support +# +CONFIG_CLASSIC32=y +# CONFIG_PPC_52xx is not set +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +# CONFIG_PPC_85xx is not set +# CONFIG_PPC_86xx is not set +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +CONFIG_6xx=y +CONFIG_PPC_FPU=y +CONFIG_ALTIVEC=y +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Platform support +# +CONFIG_PPC_MULTIPLATFORM=y +# CONFIG_PPC_ISERIES is not set +# CONFIG_EMBEDDED6xx is not set +# CONFIG_APUS is not set +CONFIG_PPC_CHRP=y +CONFIG_PPC_PMAC=y +# CONFIG_PPC_CELL is not set +# CONFIG_PPC_CELL_NATIVE is not set +# CONFIG_UDBG_RTAS_CONSOLE is not set +# CONFIG_MAMBO is not set +CONFIG_PPC_RTAS=y +# CONFIG_RTAS_ERROR_LOGGING is not set +# CONFIG_RTAS_PROC is not set +# CONFIG_MMIO_NVRAM is not set +CONFIG_PPC_MPC106=y +# CONFIG_PPC_970_NAP is not set +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_PMAC=y +# CONFIG_PPC601_SYNC_FIX is not set +CONFIG_TAU=y +# CONFIG_TAU_INT is not set +CONFIG_TAU_AVERAGE=y +# CONFIG_WANT_EARLY_SERIAL is not set +CONFIG_MPIC=y + +# +# Kernel options +# +CONFIG_HIGHMEM=y +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +# CONFIG_HOTPLUG_CPU is not set +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +# CONFIG_KEXEC is not set +CONFIG_IRQ_ALL_CPUS=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_RESOURCES_64BIT=y +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +# CONFIG_SECCOMP is not set +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_ISA=y +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_MPIC_WEIRD is not set +CONFIG_PPC_I8259=y +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCIEPORTBUS=y +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +CONFIG_PCMCIA_PROBE=y +CONFIG_PCCARD_NONSTATIC=y + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +CONFIG_ADVANCED_OPTIONS=y +# CONFIG_HIGHMEM_START_BOOL is not set +CONFIG_HIGHMEM_START=0xfe000000 +# CONFIG_LOWMEM_SIZE_BOOL is not set +CONFIG_LOWMEM_SIZE=0x30000000 +# CONFIG_KERNEL_START_BOOL is not set +CONFIG_KERNEL_START=0xc0000000 +# CONFIG_TASK_SIZE_BOOL is not set +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +# CONFIG_LTPC is not set +# CONFIG_COPS is not set +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_TOSHIBA_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +CONFIG_IEEE80211_DEBUG=y +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PCI=m +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_ECC_SMC=y +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_NANDSIM=m + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_ISAPNP=y + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_MAC_FLOPPY=m +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +# CONFIG_BLK_CPQ_DA is not set +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPNP=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_SL82C105=m +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_TRIFLEX=y +# CONFIG_BLK_DEV_CY82C693 is not set +CONFIG_BLK_DEV_CS5520=y +CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +CONFIG_BLK_DEV_IDE_PMAC=y +CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y +CONFIG_BLK_DEV_IDEDMA_PMAC=y +# CONFIG_IDE_ARM is not set +# CONFIG_IDE_CHIPSETS is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +# CONFIG_SCSI_7000FASST is not set +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AHA152X=m +# CONFIG_SCSI_AHA1542 is not set +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_IN2000 is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +CONFIG_SCSI_GDTH=m +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +# CONFIG_SCSI_NCR53C406A is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +# CONFIG_SCSI_SYM53C416 is not set +CONFIG_SCSI_DC395x=m +# 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=m +CONFIG_SCSI_MESH_SYNC_RATE=5 +CONFIG_SCSI_MESH_RESET_DELAY_MS=4000 +CONFIG_SCSI_MAC53C94=m + +# +# PCMCIA SCSI adapter support +# +CONFIG_PCMCIA_AHA152X=m +# CONFIG_PCMCIA_FDOMAIN is not set +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set + +# +# Device Drivers +# +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +CONFIG_ADB=y +CONFIG_ADB_CUDA=y +CONFIG_ADB_PMU=y +CONFIG_ADB_PMU_LED=y +CONFIG_ADB_PMU_LED_IDE=y +CONFIG_PMAC_APM_EMU=y +CONFIG_PMAC_MEDIABAY=y +CONFIG_PMAC_BACKLIGHT=y +# CONFIG_PMAC_BACKLIGHT_LEGACY is not set +CONFIG_ADB_MACIO=y +CONFIG_INPUT_ADBHID=y +CONFIG_MAC_EMUMOUSEBTN=y +CONFIG_THERM_WINDTUNNEL=m +CONFIG_THERM_ADT746X=m +CONFIG_WINDFARM=y +# CONFIG_ANSLCD is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_NET_SB1000=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_MACE=m +# CONFIG_MACE_AAUI_PORT is not set +CONFIG_BMAC=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +# CONFIG_EL1 is not set +# CONFIG_EL2 is not set +# CONFIG_ELPLUS is not set +# CONFIG_EL16 is not set +CONFIG_EL3=m +# CONFIG_3C515 is not set +CONFIG_VORTEX=m +CONFIG_TYPHOON=m +# CONFIG_LANCE is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +CONFIG_ULTRA=m +# CONFIG_SMC9194 is not set +# CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +CONFIG_NET_ISA=y +# CONFIG_E2100 is not set +CONFIG_EWRK3=m +# CONFIG_EEXPRESS is not set +# CONFIG_EEXPRESS_PRO is not set +# CONFIG_HPLAN_PLUS is not set +# CONFIG_HPLAN is not set +# CONFIG_LP486E is not set +# CONFIG_ETH16I is not set +CONFIG_NE2000=m +# CONFIG_ZNET is not set +# CONFIG_SEEQ8005 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_CS89x0 is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_TLAN=m +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y +CONFIG_NET_POCKET=y +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m +CONFIG_MV643XX_ETH=m +CONFIG_MV643XX_ETH_0=y +CONFIG_MV643XX_ETH_1=y +CONFIG_MV643XX_ETH_2=y + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +# CONFIG_IBMTR is not set +CONFIG_IBMOL=m +CONFIG_IBMLS=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set +# CONFIG_SMCTR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +# CONFIG_ARLAN is not set +# CONFIG_WAVELAN is not set +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_APPLE_AIRPORT=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_BCM43XX=m +CONFIG_BCM43XX_DEBUG=y +CONFIG_BCM43XX_DMA=y +CONFIG_BCM43XX_PIO=y +CONFIG_BCM43XX_DMA_AND_PIO_MODE=y +# CONFIG_BCM43XX_DMA_MODE is not set +# CONFIG_BCM43XX_PIO_MODE is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_IBMTR=m + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +# CONFIG_ATM_FIRESTREAM is not set +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_NICSTAR=m +# CONFIG_ATM_NICSTAR_USE_SUNI is not set +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +# CONFIG_ATM_AMBASSADOR is not set +# CONFIG_ATM_HORIZON is not set +# CONFIG_ATM_IA is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +# CONFIG_HISAX_16_0 is not set +CONFIG_HISAX_16_3=y +CONFIG_HISAX_S0BOX=y +# CONFIG_HISAX_AVM_A1 is not set +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +# CONFIG_HISAX_IX1MICROR2 is not set +CONFIG_HISAX_DIEHLDIVA=y +# CONFIG_HISAX_ASUSCOM is not set +# CONFIG_HISAX_TELEINT is not set +# CONFIG_HISAX_HFCS is not set +CONFIG_HISAX_SEDLBAUER=y +# CONFIG_HISAX_SPORTSTER is not set +# CONFIG_HISAX_MIC is not set +CONFIG_HISAX_NICCY=y +# CONFIG_HISAX_ISURF is not set +# CONFIG_HISAX_HSTSAPHIR is not set +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_HDLC=y + +# +# Active cards +# +# CONFIG_ISDN_DRV_ICN is not set +# CONFIG_ISDN_DRV_SC is not set +# CONFIG_ISDN_DRV_ACT2000 is not set + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m + +# +# Active Eicon DIVA Server cards +# +CONFIG_CAPI_EICON=y +CONFIG_ISDN_DIVAS=m +CONFIG_ISDN_DIVAS_BRIPCI=y +CONFIG_ISDN_DIVAS_PRIPCI=y +CONFIG_ISDN_DIVAS_DIVACAPI=m +CONFIG_ISDN_DIVAS_USERIDI=m +CONFIG_ISDN_DIVAS_MAINT=m + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_ESPSERIAL is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y +# CONFIG_SERIAL_8250_FOURPORT is not set +# CONFIG_SERIAL_8250_ACCENT is not set +# CONFIG_SERIAL_8250_BOCA is not set +# CONFIG_SERIAL_8250_HUB6 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_PMACZILOG=m +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_CRASH is not set +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m +# CONFIG_HVC_RTAS is not set + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +CONFIG_WATCHDOG_RTAS=m + +# +# ISA-based Watchdog Cards +# +# CONFIG_PCWATCHDOG is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_WDT is not set + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_HW_RANDOM=y +CONFIG_NVRAM=y +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +CONFIG_AGP=y +CONFIG_AGP_SIS=y +CONFIG_AGP_VIA=y +CONFIG_AGP_UNINORTH=y +CONFIG_DRM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +CONFIG_TCG_TPM=m +CONFIG_TCG_ATMEL=m +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +CONFIG_I2C_HYDRA=m +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_ISA=m +CONFIG_I2C_POWERMAC=y +CONFIG_I2C_MPC=m +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +CONFIG_I2C_STUB=m +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_M41T00=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y + +# +# Hardware Monitoring support +# +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y + +# +# Video Capture Adapters +# + +# +# Video Capture Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +# CONFIG_VIDEO_PMS is not set +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +# CONFIG_VIDEO_STRADIS is not set +# CONFIG_VIDEO_ZORAN is not set +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_24XXX=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set + +# +# Radio Adapters +# +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_RADIO_GEMTEK is not set +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_RADIO_SF16FMR2 is not set +# CONFIG_RADIO_TERRATEC is not set +# CONFIG_RADIO_TRUST is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set +CONFIG_USB_DSBR=m + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m + +# +# Miscellaneous devices +# +CONFIG_DVB_PLL=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6421=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_VIDEOBUF=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_MACMODES=y +CONFIG_FB_BACKLIGHT=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_OF=y +# CONFIG_FB_CONTROL is not set +CONFIG_FB_PLATINUM=y +CONFIG_FB_VALKYRIE=y +CONFIG_FB_CT65550=y +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_VGA16 is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_NVIDIA_BACKLIGHT=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_RIVA_BACKLIGHT=y +CONFIG_FB_MATROX=y +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_RADEON=y +CONFIG_FB_RADEON_I2C=y +CONFIG_FB_RADEON_BACKLIGHT=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=y +CONFIG_FB_ATY128_BACKLIGHT=y +CONFIG_FB_ATY=y +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_ATY_BACKLIGHT=y +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_SIS is not set +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m +CONFIG_DMASOUND_PMAC=m +CONFIG_DMASOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_OPL4_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_MPU401=m + +# +# ISA devices +# +CONFIG_SND_CS4231_LIB=m +CONFIG_SND_ADLIB=m +# CONFIG_SND_AD1816A is not set +# CONFIG_SND_AD1848 is not set +# CONFIG_SND_ALS100 is not set +# CONFIG_SND_AZT2320 is not set +# CONFIG_SND_CMI8330 is not set +# CONFIG_SND_CS4231 is not set +# CONFIG_SND_CS4232 is not set +CONFIG_SND_CS4236=m +# CONFIG_SND_DT019X is not set +# CONFIG_SND_ES968 is not set +# CONFIG_SND_ES1688 is not set +# CONFIG_SND_ES18XX is not set +# CONFIG_SND_GUSCLASSIC is not set +# CONFIG_SND_GUSEXTREME is not set +# CONFIG_SND_GUSMAX is not set +# CONFIG_SND_INTERWAVE is not set +# CONFIG_SND_INTERWAVE_STB is not set +CONFIG_SND_OPL3SA2=m +# CONFIG_SND_OPTI92X_AD1848 is not set +# CONFIG_SND_OPTI92X_CS4231 is not set +# CONFIG_SND_OPTI93X is not set +CONFIG_SND_MIRO=m +# CONFIG_SND_SB8 is not set +CONFIG_SND_SB16=m +CONFIG_SND_SBAWE=m +# CONFIG_SND_SGALAXY is not set +# CONFIG_SND_SSCAPE is not set +# CONFIG_SND_WAVEFRONT is not set + +# +# PCI devices +# +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# ALSA PowerMac devices +# +CONFIG_SND_POWERMAC=m +CONFIG_SND_POWERMAC_AUTO_DRC=y + +# +# Apple Onboard Audio driver +# +CONFIG_SND_AOA=m +CONFIG_SND_AOA_FABRIC_LAYOUT=m +CONFIG_SND_AOA_ONYX=m +CONFIG_SND_AOA_TAS=m +CONFIG_SND_AOA_TOONIE=m +CONFIG_SND_AOA_SOUNDBUS=m +CONFIG_SND_AOA_SOUNDBUS_I2S=m + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +CONFIG_USB_HIDINPUT_POWERBOOK=y +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +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_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_WBSD=m + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_ISER=m + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_HIGHMEM=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUGGER=y +CONFIG_XMON=y +CONFIG_XMON_DEFAULT=y +# CONFIG_BDI_SWITCH is not set +CONFIG_BOOTX_TEXT=y +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# diff --git a/configs/kernel-2.6.18-ppc.config b/configs/kernel-2.6.18-ppc.config new file mode 100644 index 000000000..1db169fcf --- /dev/null +++ b/configs/kernel-2.6.18-ppc.config @@ -0,0 +1,3208 @@ +# powerpc +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:41 2006 +# +# CONFIG_PPC64 is not set +CONFIG_PPC32=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_IRQ_PER_CPU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_NVRAM=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +# CONFIG_GENERIC_TBSYNC is not set +CONFIG_AUDIT_ARCH=y +# CONFIG_DEFAULT_UIMAGE is not set + +# +# Processor support +# +CONFIG_CLASSIC32=y +# CONFIG_PPC_52xx is not set +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +# CONFIG_PPC_85xx is not set +# CONFIG_PPC_86xx is not set +# CONFIG_40x is not set +# CONFIG_44x is not set +# CONFIG_8xx is not set +# CONFIG_E200 is not set +CONFIG_6xx=y +CONFIG_PPC_FPU=y +CONFIG_ALTIVEC=y +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +# CONFIG_SMP is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Platform support +# +CONFIG_PPC_MULTIPLATFORM=y +# CONFIG_PPC_ISERIES is not set +# CONFIG_EMBEDDED6xx is not set +# CONFIG_APUS is not set +CONFIG_PPC_CHRP=y +CONFIG_PPC_PMAC=y +# CONFIG_PPC_CELL is not set +# CONFIG_PPC_CELL_NATIVE is not set +# CONFIG_UDBG_RTAS_CONSOLE is not set +# CONFIG_MAMBO is not set +CONFIG_PPC_RTAS=y +# CONFIG_RTAS_ERROR_LOGGING is not set +# CONFIG_RTAS_PROC is not set +# CONFIG_MMIO_NVRAM is not set +CONFIG_PPC_MPC106=y +# CONFIG_PPC_970_NAP is not set +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_PMAC=y +# CONFIG_PPC601_SYNC_FIX is not set +CONFIG_TAU=y +# CONFIG_TAU_INT is not set +CONFIG_TAU_AVERAGE=y +# CONFIG_WANT_EARLY_SERIAL is not set +CONFIG_MPIC=y + +# +# Kernel options +# +CONFIG_HIGHMEM=y +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +# CONFIG_KEXEC is not set +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_RESOURCES_64BIT=y +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +CONFIG_SOFTWARE_SUSPEND=y +CONFIG_PM_STD_PARTITION="" +# CONFIG_SECCOMP is not set +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_ISA=y +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_MPIC_WEIRD is not set +CONFIG_PPC_I8259=y +CONFIG_PPC_INDIRECT_PCI=y +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCIEPORTBUS=y +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +CONFIG_PCMCIA_PROBE=y +CONFIG_PCCARD_NONSTATIC=y + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Advanced setup +# +CONFIG_ADVANCED_OPTIONS=y +# CONFIG_HIGHMEM_START_BOOL is not set +CONFIG_HIGHMEM_START=0xfe000000 +# CONFIG_LOWMEM_SIZE_BOOL is not set +CONFIG_LOWMEM_SIZE=0x30000000 +# CONFIG_KERNEL_START_BOOL is not set +CONFIG_KERNEL_START=0xc0000000 +# CONFIG_TASK_SIZE_BOOL is not set +CONFIG_TASK_SIZE=0x80000000 +CONFIG_BOOT_LOAD=0x00800000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +# CONFIG_LTPC is not set +# CONFIG_COPS is not set +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# +CONFIG_IRPORT_SIR=m + +# +# Old Serial dongle support +# +# CONFIG_DONGLE_OLD is not set + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_TOSHIBA_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +CONFIG_IEEE80211_DEBUG=y +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PCI=m +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_ECC_SMC=y +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_NANDSIM=m + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_ISAPNP=y + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_MAC_FLOPPY=m +# CONFIG_BLK_DEV_XD is not set +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +# CONFIG_BLK_CPQ_DA is not set +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPNP=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_SL82C105=m +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_TRIFLEX=y +# CONFIG_BLK_DEV_CY82C693 is not set +CONFIG_BLK_DEV_CS5520=y +CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +CONFIG_BLK_DEV_IDE_PMAC=y +CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y +CONFIG_BLK_DEV_IDEDMA_PMAC=y +# CONFIG_IDE_ARM is not set +# CONFIG_IDE_CHIPSETS is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +# CONFIG_SCSI_7000FASST is not set +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AHA152X=m +# CONFIG_SCSI_AHA1542 is not set +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_IN2000 is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +CONFIG_SCSI_GDTH=m +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +# CONFIG_SCSI_NCR53C406A is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +# CONFIG_SCSI_SYM53C416 is not set +CONFIG_SCSI_DC395x=m +# 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=m +CONFIG_SCSI_MESH_SYNC_RATE=5 +CONFIG_SCSI_MESH_RESET_DELAY_MS=4000 +CONFIG_SCSI_MAC53C94=m + +# +# PCMCIA SCSI adapter support +# +CONFIG_PCMCIA_AHA152X=m +# CONFIG_PCMCIA_FDOMAIN is not set +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set + +# +# Device Drivers +# +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +CONFIG_ADB=y +CONFIG_ADB_CUDA=y +CONFIG_ADB_PMU=y +CONFIG_ADB_PMU_LED=y +CONFIG_ADB_PMU_LED_IDE=y +CONFIG_PMAC_APM_EMU=y +CONFIG_PMAC_MEDIABAY=y +CONFIG_PMAC_BACKLIGHT=y +# CONFIG_PMAC_BACKLIGHT_LEGACY is not set +CONFIG_ADB_MACIO=y +CONFIG_INPUT_ADBHID=y +CONFIG_MAC_EMUMOUSEBTN=y +CONFIG_THERM_WINDTUNNEL=m +CONFIG_THERM_ADT746X=m +CONFIG_WINDFARM=y +# CONFIG_ANSLCD is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_NET_SB1000=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_MACE=m +# CONFIG_MACE_AAUI_PORT is not set +CONFIG_BMAC=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +# CONFIG_EL1 is not set +# CONFIG_EL2 is not set +# CONFIG_ELPLUS is not set +# CONFIG_EL16 is not set +CONFIG_EL3=m +# CONFIG_3C515 is not set +CONFIG_VORTEX=m +CONFIG_TYPHOON=m +# CONFIG_LANCE is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +CONFIG_ULTRA=m +# CONFIG_SMC9194 is not set +# CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +# CONFIG_PCMCIA_XIRTULIP is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +CONFIG_NET_ISA=y +# CONFIG_E2100 is not set +CONFIG_EWRK3=m +# CONFIG_EEXPRESS is not set +# CONFIG_EEXPRESS_PRO is not set +# CONFIG_HPLAN_PLUS is not set +# CONFIG_HPLAN is not set +# CONFIG_LP486E is not set +# CONFIG_ETH16I is not set +CONFIG_NE2000=m +# CONFIG_ZNET is not set +# CONFIG_SEEQ8005 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_CS89x0 is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_TLAN=m +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y +CONFIG_NET_POCKET=y +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m +CONFIG_MV643XX_ETH=m +CONFIG_MV643XX_ETH_0=y +CONFIG_MV643XX_ETH_1=y +CONFIG_MV643XX_ETH_2=y + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +# CONFIG_IBMTR is not set +CONFIG_IBMOL=m +CONFIG_IBMLS=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set +# CONFIG_SMCTR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +# CONFIG_ARLAN is not set +# CONFIG_WAVELAN is not set +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_APPLE_AIRPORT=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_BCM43XX=m +CONFIG_BCM43XX_DEBUG=y +CONFIG_BCM43XX_DMA=y +CONFIG_BCM43XX_PIO=y +CONFIG_BCM43XX_DMA_AND_PIO_MODE=y +# CONFIG_BCM43XX_DMA_MODE is not set +# CONFIG_BCM43XX_PIO_MODE is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_IBMTR=m + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +# CONFIG_ATM_FIRESTREAM is not set +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_NICSTAR=m +# CONFIG_ATM_NICSTAR_USE_SUNI is not set +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +# CONFIG_ATM_AMBASSADOR is not set +# CONFIG_ATM_HORIZON is not set +# CONFIG_ATM_IA is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DRV_LOOP=m +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +# CONFIG_HISAX_16_0 is not set +CONFIG_HISAX_16_3=y +CONFIG_HISAX_S0BOX=y +# CONFIG_HISAX_AVM_A1 is not set +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +# CONFIG_HISAX_IX1MICROR2 is not set +CONFIG_HISAX_DIEHLDIVA=y +# CONFIG_HISAX_ASUSCOM is not set +# CONFIG_HISAX_TELEINT is not set +# CONFIG_HISAX_HFCS is not set +CONFIG_HISAX_SEDLBAUER=y +# CONFIG_HISAX_SPORTSTER is not set +# CONFIG_HISAX_MIC is not set +CONFIG_HISAX_NICCY=y +# CONFIG_HISAX_ISURF is not set +# CONFIG_HISAX_HSTSAPHIR is not set +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_HDLC=y + +# +# Active cards +# +# CONFIG_ISDN_DRV_ICN is not set +# CONFIG_ISDN_DRV_SC is not set +# CONFIG_ISDN_DRV_ACT2000 is not set +CONFIG_HYSDN=m +CONFIG_HYSDN_CAPI=y + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m + +# +# Active Eicon DIVA Server cards +# +CONFIG_CAPI_EICON=y +CONFIG_ISDN_DIVAS=m +CONFIG_ISDN_DIVAS_BRIPCI=y +CONFIG_ISDN_DIVAS_PRIPCI=y +CONFIG_ISDN_DIVAS_DIVACAPI=m +CONFIG_ISDN_DIVAS_USERIDI=m +CONFIG_ISDN_DIVAS_MAINT=m + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_ESPSERIAL is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y +# CONFIG_SERIAL_8250_FOURPORT is not set +# CONFIG_SERIAL_8250_ACCENT is not set +# CONFIG_SERIAL_8250_BOCA is not set +# CONFIG_SERIAL_8250_HUB6 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_PMACZILOG=m +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_CRASH is not set +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m +# CONFIG_HVC_RTAS is not set + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +CONFIG_WATCHDOG_RTAS=m + +# +# ISA-based Watchdog Cards +# +# CONFIG_PCWATCHDOG is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_WDT is not set + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_HW_RANDOM=y +CONFIG_NVRAM=y +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +CONFIG_AGP=y +CONFIG_AGP_SIS=y +CONFIG_AGP_VIA=y +CONFIG_AGP_UNINORTH=y +CONFIG_DRM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +# CONFIG_RAW_DRIVER is not set + +# +# TPM devices +# +CONFIG_TCG_TPM=m +CONFIG_TCG_ATMEL=m +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_ELEKTOR is not set +CONFIG_I2C_HYDRA=m +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_ISA=m +CONFIG_I2C_POWERMAC=y +CONFIG_I2C_MPC=m +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +CONFIG_I2C_STUB=m +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_M41T00=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y + +# +# Hardware Monitoring support +# +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y + +# +# Video Capture Adapters +# + +# +# Video Capture Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +# CONFIG_VIDEO_PMS is not set +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +# CONFIG_VIDEO_STRADIS is not set +# CONFIG_VIDEO_ZORAN is not set +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_24XXX=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set + +# +# Radio Adapters +# +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_RADIO_GEMTEK is not set +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_RADIO_SF16FMR2 is not set +# CONFIG_RADIO_TERRATEC is not set +# CONFIG_RADIO_TRUST is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set +CONFIG_USB_DSBR=m + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m + +# +# Miscellaneous devices +# +CONFIG_DVB_PLL=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6421=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_VIDEOBUF=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_MACMODES=y +CONFIG_FB_BACKLIGHT=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_OF=y +# CONFIG_FB_CONTROL is not set +CONFIG_FB_PLATINUM=y +CONFIG_FB_VALKYRIE=y +CONFIG_FB_CT65550=y +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_VGA16 is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_NVIDIA_BACKLIGHT=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_RIVA_BACKLIGHT=y +CONFIG_FB_MATROX=y +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_RADEON=y +CONFIG_FB_RADEON_I2C=y +CONFIG_FB_RADEON_BACKLIGHT=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=y +CONFIG_FB_ATY128_BACKLIGHT=y +CONFIG_FB_ATY=y +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_ATY_BACKLIGHT=y +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_SIS is not set +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m +CONFIG_DMASOUND_PMAC=m +CONFIG_DMASOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_OPL4_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_MPU401=m + +# +# ISA devices +# +CONFIG_SND_CS4231_LIB=m +CONFIG_SND_ADLIB=m +# CONFIG_SND_AD1816A is not set +# CONFIG_SND_AD1848 is not set +# CONFIG_SND_ALS100 is not set +# CONFIG_SND_AZT2320 is not set +# CONFIG_SND_CMI8330 is not set +# CONFIG_SND_CS4231 is not set +# CONFIG_SND_CS4232 is not set +CONFIG_SND_CS4236=m +# CONFIG_SND_DT019X is not set +# CONFIG_SND_ES968 is not set +# CONFIG_SND_ES1688 is not set +# CONFIG_SND_ES18XX is not set +# CONFIG_SND_GUSCLASSIC is not set +# CONFIG_SND_GUSEXTREME is not set +# CONFIG_SND_GUSMAX is not set +# CONFIG_SND_INTERWAVE is not set +# CONFIG_SND_INTERWAVE_STB is not set +CONFIG_SND_OPL3SA2=m +# CONFIG_SND_OPTI92X_AD1848 is not set +# CONFIG_SND_OPTI92X_CS4231 is not set +# CONFIG_SND_OPTI93X is not set +CONFIG_SND_MIRO=m +# CONFIG_SND_SB8 is not set +CONFIG_SND_SB16=m +CONFIG_SND_SBAWE=m +# CONFIG_SND_SGALAXY is not set +# CONFIG_SND_SSCAPE is not set +# CONFIG_SND_WAVEFRONT is not set + +# +# PCI devices +# +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# ALSA PowerMac devices +# +CONFIG_SND_POWERMAC=m +CONFIG_SND_POWERMAC_AUTO_DRC=y + +# +# Apple Onboard Audio driver +# +CONFIG_SND_AOA=m +CONFIG_SND_AOA_FABRIC_LAYOUT=m +CONFIG_SND_AOA_ONYX=m +CONFIG_SND_AOA_TAS=m +CONFIG_SND_AOA_TOONIE=m +CONFIG_SND_AOA_SOUNDBUS=m +CONFIG_SND_AOA_SOUNDBUS_I2S=m + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +CONFIG_USB_HIDINPUT_POWERBOOK=y +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +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_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_WBSD=m + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_ISER=m + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_HIGHMEM=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUGGER=y +CONFIG_XMON=y +CONFIG_XMON_DEFAULT=y +# CONFIG_BDI_SWITCH is not set +CONFIG_BOOTX_TEXT=y +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# diff --git a/configs/kernel-2.6.18-ppc64-kdump.config b/configs/kernel-2.6.18-ppc64-kdump.config new file mode 100644 index 000000000..aba782700 --- /dev/null +++ b/configs/kernel-2.6.18-ppc64-kdump.config @@ -0,0 +1,3039 @@ +# powerpc +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:42 2006 +# +CONFIG_PPC64=y +CONFIG_64BIT=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_IRQ_PER_CPU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +CONFIG_GENERIC_TBSYNC=y +CONFIG_AUDIT_ARCH=y +# CONFIG_DEFAULT_UIMAGE is not set + +# +# Processor support +# +# CONFIG_POWER4_ONLY is not set +CONFIG_POWER3=y +CONFIG_POWER4=y +CONFIG_PPC_FPU=y +CONFIG_ALTIVEC=y +CONFIG_PPC_STD_MMU=y +CONFIG_VIRT_CPU_ACCOUNTING=y +CONFIG_SMP=y +CONFIG_NR_CPUS=128 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_BLK_DEV_IO_TRACE=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Platform support +# +CONFIG_PPC_MULTIPLATFORM=y +# CONFIG_PPC_ISERIES is not set +# CONFIG_EMBEDDED6xx is not set +# CONFIG_APUS is not set +CONFIG_PPC_PSERIES=y +CONFIG_PPC_PMAC=y +CONFIG_PPC_PMAC64=y +# CONFIG_PPC_MAPLE is not set +CONFIG_PPC_CELL=y +CONFIG_PPC_CELL_NATIVE=y +CONFIG_PPC_IBM_CELL_BLADE=y +CONFIG_UDBG_RTAS_CONSOLE=y +CONFIG_MAMBO=y +CONFIG_MAMBO_DISK=m +CONFIG_MAMBO_NET=m +CONFIG_XICS=y +CONFIG_U3_DART=y +CONFIG_PPC_RTAS=y +CONFIG_RTAS_ERROR_LOGGING=y +CONFIG_RTAS_PROC=y +CONFIG_RTAS_FLASH=y +CONFIG_MMIO_NVRAM=y +CONFIG_MPIC_BROKEN_U3=y +CONFIG_IBMVIO=y +CONFIG_IBMEBUS=y +# CONFIG_PPC_MPC106 is not set +CONFIG_PPC_970_NAP=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_PMAC64=y +# CONFIG_WANT_EARLY_SERIAL is not set +CONFIG_MPIC=y + +# +# Cell Broadband Engine options +# +CONFIG_SPU_FS=m +CONFIG_SPU_BASE=y +CONFIG_SPUFS_MMAP=y +CONFIG_CBE_RAS=y + +# +# Kernel options +# +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_FORCE_MAX_ZONEORDER=9 +CONFIG_IOMMU_VMERGE=y +CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_KEXEC=y +CONFIG_CRASH_DUMP=y +CONFIG_IRQ_ALL_CPUS=y +CONFIG_PPC_SPLPAR=y +CONFIG_EEH=y +CONFIG_SCANLOG=y +CONFIG_LPARCFG=y +CONFIG_NUMA=y +CONFIG_NODES_SHIFT=4 +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_SELECT_MEMORY_MODEL=y +# CONFIG_FLATMEM_MANUAL is not set +# CONFIG_DISCONTIGMEM_MANUAL is not set +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_NEED_MULTIPLE_NODES=y +CONFIG_HAVE_MEMORY_PRESENT=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_MEMORY_HOTPLUG=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_MIGRATION=y +CONFIG_RESOURCES_64BIT=y +CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y +CONFIG_ARCH_MEMORY_PROBE=y +CONFIG_NODES_SPAN_OTHER_NODES=y +CONFIG_PPC_64K_PAGES=y +CONFIG_SCHED_SMT=y +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +# CONFIG_SECCOMP is not set +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_MPIC_WEIRD is not set +CONFIG_PPC_I8259=y +# CONFIG_PPC_INDIRECT_PCI is not set +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCIEPORTBUS=y +# CONFIG_HOTPLUG_PCI_PCIE is not set +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +CONFIG_PCCARD_NONSTATIC=y + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_FAKE=m +# CONFIG_HOTPLUG_PCI_CPCI is not set +CONFIG_HOTPLUG_PCI_SHPC=m +CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE=y +CONFIG_HOTPLUG_PCI_RPA=m +CONFIG_HOTPLUG_PCI_RPA_DLPAR=m +CONFIG_KERNEL_START=0xc000000000000000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +CONFIG_IEEE80211_DEBUG=y +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PCI=m +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_ECC_SMC=y +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_NANDSIM=m + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# + +# +# Block devices +# +CONFIG_BLK_DEV_FD=m +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +# CONFIG_BLK_CPQ_DA is not set +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_SL82C105=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +CONFIG_BLK_DEV_AMD74XX=y +CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_TRIFLEX=y +# CONFIG_BLK_DEV_CY82C693 is not set +CONFIG_BLK_DEV_CS5520=y +CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +CONFIG_BLK_DEV_IDE_PMAC=y +CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y +CONFIG_BLK_DEV_IDEDMA_PMAC=y +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_IPS=m +CONFIG_SCSI_IBMVSCSI=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +CONFIG_SCSI_IPR=m +CONFIG_SCSI_IPR_TRACE=y +CONFIG_SCSI_IPR_DUMP=y +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +CONFIG_SCSI_DC395x=m +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_PCMCIA_FDOMAIN is not set +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set + +# +# Device Drivers +# +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +CONFIG_ADB_PMU=y +CONFIG_ADB_PMU_LED=y +CONFIG_ADB_PMU_LED_IDE=y +CONFIG_PMAC_SMU=y +CONFIG_THERM_PM72=y +CONFIG_WINDFARM=y +CONFIG_WINDFARM_PM81=y +CONFIG_WINDFARM_PM91=y +CONFIG_WINDFARM_PM112=y + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +CONFIG_VORTEX=m +CONFIG_TYPHOON=m + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +# CONFIG_HP100 is not set +CONFIG_IBMVETH=m +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y +CONFIG_NET_POCKET=y +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m +CONFIG_SPIDER_NET=m +# CONFIG_MV643XX_ETH is not set + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +CONFIG_IBMOL=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_APPLE_AIRPORT=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_BCM43XX=m +CONFIG_BCM43XX_DEBUG=y +CONFIG_BCM43XX_DMA=y +CONFIG_BCM43XX_PIO=y +CONFIG_BCM43XX_DMA_AND_PIO_MODE=y +# CONFIG_BCM43XX_DMA_MODE is not set +# CONFIG_BCM43XX_PIO_MODE is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +# CONFIG_ATM_FIRESTREAM is not set +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +# CONFIG_ATM_AMBASSADOR is not set +# CONFIG_ATM_HORIZON is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +CONFIG_HISAX_16_3=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_HDLC=y + +# +# Active cards +# + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m + +# +# Active Eicon DIVA Server cards +# +CONFIG_CAPI_EICON=y +CONFIG_ISDN_DIVAS=m +CONFIG_ISDN_DIVAS_BRIPCI=y +CONFIG_ISDN_DIVAS_PRIPCI=y +CONFIG_ISDN_DIVAS_DIVACAPI=m +CONFIG_ISDN_DIVAS_USERIDI=m +CONFIG_ISDN_DIVAS_MAINT=m + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_PCSPKR is not set +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_PMACZILOG=m +CONFIG_SERIAL_ICOM=m +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_CRASH is not set +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m +CONFIG_HVC_DRIVER=y +CONFIG_HVC_CONSOLE=y +CONFIG_HVC_RTAS=y +CONFIG_HVCS=m + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +CONFIG_WATCHDOG_RTAS=m + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_HW_RANDOM=y +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +CONFIG_AGP=y +CONFIG_AGP_SIS=y +CONFIG_AGP_VIA=y +CONFIG_AGP_UNINORTH=y +CONFIG_DRM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +# CONFIG_RAW_DRIVER is not set +CONFIG_HANGCHECK_TIMER=m + +# +# TPM devices +# +CONFIG_TCG_TPM=m +CONFIG_TCG_ATMEL=m +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_ISA=m +CONFIG_I2C_POWERMAC=y +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +CONFIG_I2C_STUB=m +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y + +# +# Hardware Monitoring support +# +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y + +# +# Video Capture Adapters +# + +# +# Video Capture Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_24XXX=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set + +# +# Radio Adapters +# +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +CONFIG_USB_DSBR=m + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m + +# +# Miscellaneous devices +# +CONFIG_DVB_PLL=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6421=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_VIDEOBUF=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_MACMODES=y +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_OF=y +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_VGA16 is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_RADEON=y +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_SIS is not set +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_MPU401=m + +# +# PCI devices +# +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# ALSA PowerMac devices +# +CONFIG_SND_POWERMAC=m +CONFIG_SND_POWERMAC_AUTO_DRC=y + +# +# Apple Onboard Audio driver +# +CONFIG_SND_AOA=m +CONFIG_SND_AOA_FABRIC_LAYOUT=m +CONFIG_SND_AOA_ONYX=m +CONFIG_SND_AOA_TAS=m +CONFIG_SND_AOA_TOONIE=m +CONFIG_SND_AOA_SOUNDBUS=m +CONFIG_SND_AOA_SOUNDBUS_I2S=m + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +CONFIG_USB_HIDINPUT_POWERBOOK=y +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +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_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_WBSD=m + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_ISER=m + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_VMCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_DEBUG_STACK_USAGE=y +CONFIG_DEBUGGER=y +CONFIG_XMON=y +CONFIG_XMON_DEFAULT=y +CONFIG_IRQSTACKS=y +CONFIG_BOOTX_TEXT=y +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set +CONFIG_KEYS_COMPAT=y + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# diff --git a/configs/kernel-2.6.18-ppc64.config b/configs/kernel-2.6.18-ppc64.config new file mode 100644 index 000000000..7b31ef807 --- /dev/null +++ b/configs/kernel-2.6.18-ppc64.config @@ -0,0 +1,3038 @@ +# powerpc +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:42 2006 +# +CONFIG_PPC64=y +CONFIG_64BIT=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_IRQ_PER_CPU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +CONFIG_PPC_UDBG_16550=y +CONFIG_GENERIC_TBSYNC=y +CONFIG_AUDIT_ARCH=y +# CONFIG_DEFAULT_UIMAGE is not set + +# +# Processor support +# +# CONFIG_POWER4_ONLY is not set +CONFIG_POWER3=y +CONFIG_POWER4=y +CONFIG_PPC_FPU=y +CONFIG_ALTIVEC=y +CONFIG_PPC_STD_MMU=y +CONFIG_VIRT_CPU_ACCOUNTING=y +CONFIG_SMP=y +CONFIG_NR_CPUS=128 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_BLK_DEV_IO_TRACE=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Platform support +# +CONFIG_PPC_MULTIPLATFORM=y +# CONFIG_PPC_ISERIES is not set +# CONFIG_EMBEDDED6xx is not set +# CONFIG_APUS is not set +CONFIG_PPC_PSERIES=y +CONFIG_PPC_PMAC=y +CONFIG_PPC_PMAC64=y +# CONFIG_PPC_MAPLE is not set +CONFIG_PPC_CELL=y +CONFIG_PPC_CELL_NATIVE=y +CONFIG_PPC_IBM_CELL_BLADE=y +CONFIG_UDBG_RTAS_CONSOLE=y +CONFIG_MAMBO=y +CONFIG_MAMBO_DISK=m +CONFIG_MAMBO_NET=m +CONFIG_XICS=y +CONFIG_U3_DART=y +CONFIG_PPC_RTAS=y +CONFIG_RTAS_ERROR_LOGGING=y +CONFIG_RTAS_PROC=y +CONFIG_RTAS_FLASH=y +CONFIG_MMIO_NVRAM=y +CONFIG_MPIC_BROKEN_U3=y +CONFIG_IBMVIO=y +CONFIG_IBMEBUS=y +# CONFIG_PPC_MPC106 is not set +CONFIG_PPC_970_NAP=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_PMAC64=y +# CONFIG_WANT_EARLY_SERIAL is not set +CONFIG_MPIC=y + +# +# Cell Broadband Engine options +# +CONFIG_SPU_FS=m +CONFIG_SPU_BASE=y +CONFIG_SPUFS_MMAP=y +CONFIG_CBE_RAS=y + +# +# Kernel options +# +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_FORCE_MAX_ZONEORDER=9 +CONFIG_IOMMU_VMERGE=y +CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_KEXEC=y +# CONFIG_CRASH_DUMP is not set +CONFIG_IRQ_ALL_CPUS=y +CONFIG_PPC_SPLPAR=y +CONFIG_EEH=y +CONFIG_SCANLOG=y +CONFIG_LPARCFG=y +CONFIG_NUMA=y +CONFIG_NODES_SHIFT=4 +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_SELECT_MEMORY_MODEL=y +# CONFIG_FLATMEM_MANUAL is not set +# CONFIG_DISCONTIGMEM_MANUAL is not set +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_NEED_MULTIPLE_NODES=y +CONFIG_HAVE_MEMORY_PRESENT=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_MEMORY_HOTPLUG=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_MIGRATION=y +CONFIG_RESOURCES_64BIT=y +CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y +CONFIG_ARCH_MEMORY_PROBE=y +CONFIG_NODES_SPAN_OTHER_NODES=y +CONFIG_PPC_64K_PAGES=y +CONFIG_SCHED_SMT=y +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +# CONFIG_SECCOMP is not set +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_MPIC_WEIRD is not set +CONFIG_PPC_I8259=y +# CONFIG_PPC_INDIRECT_PCI is not set +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCIEPORTBUS=y +# CONFIG_HOTPLUG_PCI_PCIE is not set +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +CONFIG_PCCARD_NONSTATIC=y + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_FAKE=m +# CONFIG_HOTPLUG_PCI_CPCI is not set +CONFIG_HOTPLUG_PCI_SHPC=m +CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE=y +CONFIG_HOTPLUG_PCI_RPA=m +CONFIG_HOTPLUG_PCI_RPA_DLPAR=m +CONFIG_KERNEL_START=0xc000000000000000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +CONFIG_IEEE80211_DEBUG=y +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_PCI=m +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_ECC_SMC=y +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_NANDSIM=m + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# + +# +# Block devices +# +CONFIG_BLK_DEV_FD=m +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +# CONFIG_BLK_CPQ_DA is not set +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_SL82C105=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +CONFIG_BLK_DEV_AMD74XX=y +CONFIG_BLK_DEV_CMD64X=y +CONFIG_BLK_DEV_TRIFLEX=y +# CONFIG_BLK_DEV_CY82C693 is not set +CONFIG_BLK_DEV_CS5520=y +CONFIG_BLK_DEV_CS5530=y +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +CONFIG_BLK_DEV_IDE_PMAC=y +CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y +CONFIG_BLK_DEV_IDEDMA_PMAC=y +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_IPS=m +CONFIG_SCSI_IBMVSCSI=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +CONFIG_SCSI_IPR=m +CONFIG_SCSI_IPR_TRACE=y +CONFIG_SCSI_IPR_DUMP=y +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +CONFIG_SCSI_DC395x=m +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_PCMCIA_FDOMAIN is not set +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set + +# +# Device Drivers +# +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +CONFIG_ADB_PMU=y +CONFIG_ADB_PMU_LED=y +CONFIG_ADB_PMU_LED_IDE=y +CONFIG_PMAC_SMU=y +CONFIG_THERM_PM72=y +CONFIG_WINDFARM=y +CONFIG_WINDFARM_PM81=y +CONFIG_WINDFARM_PM91=y +CONFIG_WINDFARM_PM112=y + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +CONFIG_VORTEX=m +CONFIG_TYPHOON=m + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +# CONFIG_HP100 is not set +CONFIG_IBMVETH=m +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y +CONFIG_NET_POCKET=y +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m +CONFIG_SPIDER_NET=m +# CONFIG_MV643XX_ETH is not set + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +CONFIG_IBMOL=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_APPLE_AIRPORT=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_BCM43XX=m +CONFIG_BCM43XX_DEBUG=y +CONFIG_BCM43XX_DMA=y +CONFIG_BCM43XX_PIO=y +CONFIG_BCM43XX_DMA_AND_PIO_MODE=y +# CONFIG_BCM43XX_DMA_MODE is not set +# CONFIG_BCM43XX_PIO_MODE is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +# CONFIG_ATM_FIRESTREAM is not set +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +# CONFIG_ATM_AMBASSADOR is not set +# CONFIG_ATM_HORIZON is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +CONFIG_HISAX_16_3=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_HDLC=y + +# +# Active cards +# + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m + +# +# Active Eicon DIVA Server cards +# +CONFIG_CAPI_EICON=y +CONFIG_ISDN_DIVAS=m +CONFIG_ISDN_DIVAS_BRIPCI=y +CONFIG_ISDN_DIVAS_PRIPCI=y +CONFIG_ISDN_DIVAS_DIVACAPI=m +CONFIG_ISDN_DIVAS_USERIDI=m +CONFIG_ISDN_DIVAS_MAINT=m + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_PCSPKR is not set +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_PMACZILOG=m +CONFIG_SERIAL_ICOM=m +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_CRASH is not set +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m +CONFIG_HVC_DRIVER=y +CONFIG_HVC_CONSOLE=y +CONFIG_HVC_RTAS=y +CONFIG_HVCS=m + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +CONFIG_WATCHDOG_RTAS=m + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_HW_RANDOM=y +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +CONFIG_AGP=y +CONFIG_AGP_SIS=y +CONFIG_AGP_VIA=y +CONFIG_AGP_UNINORTH=y +CONFIG_DRM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +# CONFIG_RAW_DRIVER is not set +CONFIG_HANGCHECK_TIMER=m + +# +# TPM devices +# +CONFIG_TCG_TPM=m +CONFIG_TCG_ATMEL=m +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_ISA=m +CONFIG_I2C_POWERMAC=y +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +CONFIG_I2C_STUB=m +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y + +# +# Hardware Monitoring support +# +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y + +# +# Video Capture Adapters +# + +# +# Video Capture Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_24XXX=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set + +# +# Radio Adapters +# +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +CONFIG_USB_DSBR=m + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m + +# +# Miscellaneous devices +# +CONFIG_DVB_PLL=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6421=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_VIDEOBUF=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +CONFIG_FB_MACMODES=y +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_OF=y +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_VGA16 is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_RADEON=y +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_SIS is not set +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_MPU401=m + +# +# PCI devices +# +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# ALSA PowerMac devices +# +CONFIG_SND_POWERMAC=m +CONFIG_SND_POWERMAC_AUTO_DRC=y + +# +# Apple Onboard Audio driver +# +CONFIG_SND_AOA=m +CONFIG_SND_AOA_FABRIC_LAYOUT=m +CONFIG_SND_AOA_ONYX=m +CONFIG_SND_AOA_TAS=m +CONFIG_SND_AOA_TOONIE=m +CONFIG_SND_AOA_SOUNDBUS=m +CONFIG_SND_AOA_SOUNDBUS_I2S=m + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +CONFIG_USB_HIDINPUT_POWERBOOK=y +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +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_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_WBSD=m + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_ISER=m + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_DEBUG_STACK_USAGE=y +CONFIG_DEBUGGER=y +CONFIG_XMON=y +CONFIG_XMON_DEFAULT=y +CONFIG_IRQSTACKS=y +CONFIG_BOOTX_TEXT=y +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set +CONFIG_KEYS_COMPAT=y + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# diff --git a/configs/kernel-2.6.18-ppc64iseries.config b/configs/kernel-2.6.18-ppc64iseries.config new file mode 100644 index 000000000..ffeabee01 --- /dev/null +++ b/configs/kernel-2.6.18-ppc64iseries.config @@ -0,0 +1,1586 @@ +# powerpc +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:42 2006 +# +CONFIG_PPC64=y +CONFIG_64BIT=y +CONFIG_PPC_MERGE=y +CONFIG_MMU=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_IRQ_PER_CPU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_PPC=y +CONFIG_EARLY_PRINTK=y +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_PPC_OF=y +# CONFIG_PPC_UDBG_16550 is not set +# CONFIG_GENERIC_TBSYNC is not set +CONFIG_AUDIT_ARCH=y +# CONFIG_DEFAULT_UIMAGE is not set + +# +# Processor support +# +# CONFIG_POWER4_ONLY is not set +CONFIG_POWER3=y +CONFIG_POWER4=y +CONFIG_PPC_FPU=y +CONFIG_ALTIVEC=y +CONFIG_PPC_STD_MMU=y +CONFIG_VIRT_CPU_ACCOUNTING=y +CONFIG_SMP=y +CONFIG_NR_CPUS=128 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_BLK_DEV_IO_TRACE=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Platform support +# +# CONFIG_PPC_MULTIPLATFORM is not set +CONFIG_PPC_ISERIES=y +# CONFIG_EMBEDDED6xx is not set +# CONFIG_APUS is not set +# CONFIG_PPC_CELL is not set +# CONFIG_PPC_CELL_NATIVE is not set +# CONFIG_UDBG_RTAS_CONSOLE is not set +# CONFIG_MAMBO is not set +# CONFIG_PPC_RTAS is not set +# CONFIG_MMIO_NVRAM is not set +CONFIG_IBMVIO=y +# CONFIG_PPC_MPC106 is not set +# CONFIG_PPC_970_NAP is not set +# CONFIG_CPU_FREQ is not set +# CONFIG_WANT_EARLY_SERIAL is not set +# CONFIG_MPIC is not set + +# +# Kernel options +# +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_FORCE_MAX_ZONEORDER=9 +CONFIG_IOMMU_VMERGE=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_IRQ_ALL_CPUS=y +CONFIG_LPARCFG=y +# CONFIG_NUMA is not set +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_RESOURCES_64BIT=y +CONFIG_PPC_64K_PAGES=y +# CONFIG_SCHED_SMT is not set +CONFIG_PROC_DEVICETREE=y +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +# CONFIG_SECCOMP is not set +CONFIG_ISA_DMA_API=y + +# +# Bus options +# +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_MPIC_WEIRD is not set +# CONFIG_PPC_I8259 is not set +# CONFIG_PPC_INDIRECT_PCI is not set +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCIEPORTBUS=y +# CONFIG_HOTPLUG_PCI_PCIE is not set +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +# CONFIG_HOTPLUG_PCI_FAKE is not set +# CONFIG_HOTPLUG_PCI_CPCI is not set +CONFIG_HOTPLUG_PCI_SHPC=m +CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE=y +CONFIG_KERNEL_START=0xc000000000000000 + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +# CONFIG_ATM is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +# CONFIG_SCSI_3W_9XXX is not set +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +# CONFIG_SCSI_SATA is not set +CONFIG_SCSI_HPTIOP=m +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +CONFIG_SCSI_GDTH=m +# CONFIG_SCSI_IPS is not set +CONFIG_SCSI_IBMVSCSI=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +CONFIG_SCSI_DC395x=m +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Macintosh device drivers +# +# CONFIG_WINDFARM is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +# CONFIG_SUNGEM is not set +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +# CONFIG_VORTEX is not set +CONFIG_TYPHOON=m + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +# CONFIG_FEALNX is not set +CONFIG_NATSEMI=m +# CONFIG_NE2K_PCI is not set +CONFIG_8139CP=m +# CONFIG_8139TOO is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +# CONFIG_DL2K is not set +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +# CONFIG_R8169 is not set +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +CONFIG_IBMOL=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set +CONFIG_ISERIES_VETH=m +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=m +CONFIG_SERIAL_ICOM=m +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_CRASH is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y +CONFIG_HW_RANDOM=y +CONFIG_GEN_RTC=y +# CONFIG_GEN_RTC_X is not set +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +CONFIG_HANGCHECK_TIMER=m + +# +# TPM devices +# +CONFIG_TCG_TPM=m +CONFIG_TCG_ATMEL=m +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +# CONFIG_INFINIBAND is not set + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_DS1742=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +# CONFIG_INTEL_IOATDMA is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# iSeries device drivers +# +CONFIG_VIOCONS=y +CONFIG_VIODASD=m +CONFIG_VIOCD=m +CONFIG_VIOTAPE=m +CONFIG_VIOPATH=y + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_STACKOVERFLOW=y +CONFIG_DEBUG_STACK_USAGE=y +CONFIG_DEBUGGER=y +CONFIG_IRQSTACKS=y +# CONFIG_PPC_EARLY_DEBUG is not set + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set +CONFIG_KEYS_COMPAT=y + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# diff --git a/configs/kernel-2.6.18-s390.config b/configs/kernel-2.6.18-s390.config new file mode 100644 index 000000000..971ecd194 --- /dev/null +++ b/configs/kernel-2.6.18-s390.config @@ -0,0 +1,1133 @@ +# s390 +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:42 2006 +# +CONFIG_MMU=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_S390=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Base setup +# + +# +# Processor type and features +# +# CONFIG_64BIT is not set +CONFIG_32BIT=y +CONFIG_SMP=y +CONFIG_NR_CPUS=32 +CONFIG_HOTPLUG_CPU=y +CONFIG_DEFAULT_MIGRATION_COST=1000000 +CONFIG_MATHEMU=y +CONFIG_AUDIT_ARCH=y + +# +# Code generation options +# +CONFIG_MARCH_G5=y +# CONFIG_MARCH_Z900 is not set +# CONFIG_MARCH_Z990 is not set +CONFIG_PACK_STACK=y +# CONFIG_SMALL_STACK is not set +CONFIG_CHECK_STACK=y +CONFIG_STACK_GUARD=256 +# CONFIG_WARN_STACK is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_RESOURCES_64BIT=y + +# +# I/O subsystem configuration +# +CONFIG_MACHCHK_WARNING=y +CONFIG_QDIO=m +# CONFIG_QDIO_PERF_STATS is not set +# CONFIG_QDIO_DEBUG is not set + +# +# Misc +# +# CONFIG_PREEMPT is not set +CONFIG_IPL=y +# CONFIG_IPL_TAPE is not set +CONFIG_IPL_VM=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +# CONFIG_PROCESS_DEBUG is not set +CONFIG_PFAULT=y +# CONFIG_SHARED_KERNEL is not set +CONFIG_CMM=m +CONFIG_CMM_PROC=y +CONFIG_CMM_IUCV=y +CONFIG_VIRT_TIMER=y +CONFIG_VIRT_CPU_ACCOUNTING=y +CONFIG_APPLDATA_BASE=y +CONFIG_APPLDATA_MEM=m +CONFIG_APPLDATA_OS=m +CONFIG_APPLDATA_NET_SUM=m +CONFIG_NO_IDLE_HZ=y +CONFIG_NO_IDLE_HZ_INIT=y +CONFIG_S390_HYPFS_FS=y +CONFIG_KEXEC=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +# CONFIG_PCMCIA is not set + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +CONFIG_SYS_HYPERVISOR=y + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DEBUG is not set +CONFIG_ZFCP=m +CONFIG_CCW=y + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set + +# +# S/390 block device drivers +# +CONFIG_BLK_DEV_XPRAM=m +CONFIG_DCSSBLK=m +CONFIG_DASD=m +CONFIG_DASD_PROFILE=y +CONFIG_DASD_ECKD=m +CONFIG_DASD_FBA=m +CONFIG_DASD_DIAG=m +CONFIG_DASD_EER=y +# CONFIG_ATA_OVER_ETH is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Character device drivers +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=2048 +CONFIG_HANGCHECK_TIMER=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +CONFIG_ZVM_WATCHDOG=m + +# +# S/390 character device drivers +# +CONFIG_TN3270=y +CONFIG_TN3270_TTY=y +CONFIG_TN3270_FS=m +CONFIG_TN3270_CONSOLE=y +CONFIG_TN3215=y +CONFIG_TN3215_CONSOLE=y +CONFIG_CCW_CONSOLE=y +CONFIG_SCLP=y +CONFIG_SCLP_TTY=y +CONFIG_SCLP_CONSOLE=y +CONFIG_SCLP_VT220_TTY=y +CONFIG_SCLP_VT220_CONSOLE=y +CONFIG_SCLP_CPI=m +CONFIG_S390_TAPE=m + +# +# S/390 tape interface support +# +CONFIG_S390_TAPE_BLOCK=y + +# +# S/390 tape hardware support +# +CONFIG_S390_TAPE_34XX=m +CONFIG_S390_TAPE_3590=m +CONFIG_VMLOGRDR=m +CONFIG_VMCP=m +CONFIG_MONREADER=m + +# +# Cryptographic devices +# +CONFIG_Z90CRYPT=m + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m + +# +# PHY device support +# + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# +CONFIG_TR=y + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m + +# +# S/390 network device drivers +# +CONFIG_LCS=m +CONFIG_CTC=m +CONFIG_IUCV=m +CONFIG_NETIUCV=m +CONFIG_SMSGIUCV=m +# CONFIG_CLAW is not set +CONFIG_QETH=m + +# +# Gigabit Ethernet default settings +# +CONFIG_QETH_IPV6=y +CONFIG_QETH_VLAN=y +CONFIG_CCWGROUP=m +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +CONFIG_AMIGA_PARTITION=y +# CONFIG_ATARI_PARTITION is not set +CONFIG_IBM_PARTITION=y +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Profiling support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_DETECT_SOFTLOCKUP is not set +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FRAME_POINTER is not set +CONFIG_UNWIND_INFO=y +# CONFIG_FORCED_INLINING is not set +# CONFIG_BOOT_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_S390=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA256_S390=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_DES_S390=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_S390=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y diff --git a/configs/kernel-2.6.18-s390x.config b/configs/kernel-2.6.18-s390x.config new file mode 100644 index 000000000..6340b1bce --- /dev/null +++ b/configs/kernel-2.6.18-s390x.config @@ -0,0 +1,1131 @@ +# s390 +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:42 2006 +# +CONFIG_MMU=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_S390=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_BLK_DEV_IO_TRACE=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Base setup +# + +# +# Processor type and features +# +CONFIG_64BIT=y +CONFIG_SMP=y +CONFIG_NR_CPUS=64 +CONFIG_HOTPLUG_CPU=y +CONFIG_DEFAULT_MIGRATION_COST=1000000 +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_AUDIT_ARCH=y + +# +# Code generation options +# +# CONFIG_MARCH_G5 is not set +CONFIG_MARCH_Z900=y +# CONFIG_MARCH_Z990 is not set +CONFIG_PACK_STACK=y +# CONFIG_SMALL_STACK is not set +CONFIG_CHECK_STACK=y +CONFIG_STACK_GUARD=256 +# CONFIG_WARN_STACK is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_RESOURCES_64BIT=y + +# +# I/O subsystem configuration +# +CONFIG_MACHCHK_WARNING=y +CONFIG_QDIO=m +# CONFIG_QDIO_PERF_STATS is not set +# CONFIG_QDIO_DEBUG is not set + +# +# Misc +# +# CONFIG_PREEMPT is not set +CONFIG_IPL=y +# CONFIG_IPL_TAPE is not set +CONFIG_IPL_VM=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +# CONFIG_PROCESS_DEBUG is not set +CONFIG_PFAULT=y +# CONFIG_SHARED_KERNEL is not set +CONFIG_CMM=m +CONFIG_CMM_PROC=y +CONFIG_CMM_IUCV=y +CONFIG_VIRT_TIMER=y +CONFIG_VIRT_CPU_ACCOUNTING=y +CONFIG_APPLDATA_BASE=y +CONFIG_APPLDATA_MEM=m +CONFIG_APPLDATA_OS=m +CONFIG_APPLDATA_NET_SUM=m +CONFIG_NO_IDLE_HZ=y +CONFIG_NO_IDLE_HZ_INIT=y +CONFIG_S390_HYPFS_FS=y +CONFIG_KEXEC=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +# CONFIG_PCMCIA is not set + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +CONFIG_SYS_HYPERVISOR=y + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_DEBUG is not set +CONFIG_ZFCP=m +CONFIG_CCW=y + +# +# Block devices +# +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_CDROM_PKTCDVD is not set + +# +# S/390 block device drivers +# +CONFIG_BLK_DEV_XPRAM=m +CONFIG_DCSSBLK=m +CONFIG_DASD=m +CONFIG_DASD_PROFILE=y +CONFIG_DASD_ECKD=m +CONFIG_DASD_FBA=m +CONFIG_DASD_DIAG=m +CONFIG_DASD_EER=y +# CONFIG_ATA_OVER_ETH is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Character device drivers +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=2048 +CONFIG_HANGCHECK_TIMER=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +CONFIG_ZVM_WATCHDOG=m + +# +# S/390 character device drivers +# +CONFIG_TN3270=y +CONFIG_TN3270_TTY=y +CONFIG_TN3270_FS=m +CONFIG_TN3270_CONSOLE=y +CONFIG_TN3215=y +CONFIG_TN3215_CONSOLE=y +CONFIG_CCW_CONSOLE=y +CONFIG_SCLP=y +CONFIG_SCLP_TTY=y +CONFIG_SCLP_CONSOLE=y +CONFIG_SCLP_VT220_TTY=y +CONFIG_SCLP_VT220_CONSOLE=y +CONFIG_SCLP_CPI=m +CONFIG_S390_TAPE=m + +# +# S/390 tape interface support +# +CONFIG_S390_TAPE_BLOCK=y + +# +# S/390 tape hardware support +# +CONFIG_S390_TAPE_34XX=m +CONFIG_S390_TAPE_3590=m +CONFIG_VMLOGRDR=m +CONFIG_VMCP=m +CONFIG_MONREADER=m + +# +# Cryptographic devices +# +CONFIG_Z90CRYPT=m + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m + +# +# PHY device support +# + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# +CONFIG_TR=y + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m + +# +# S/390 network device drivers +# +CONFIG_LCS=m +CONFIG_CTC=m +CONFIG_IUCV=m +CONFIG_NETIUCV=m +CONFIG_SMSGIUCV=m +# CONFIG_CLAW is not set +CONFIG_QETH=m + +# +# Gigabit Ethernet default settings +# +CONFIG_QETH_IPV6=y +CONFIG_QETH_VLAN=y +CONFIG_CCWGROUP=m +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +CONFIG_AMIGA_PARTITION=y +# CONFIG_ATARI_PARTITION is not set +CONFIG_IBM_PARTITION=y +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Profiling support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_DETECT_SOFTLOCKUP is not set +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FRAME_POINTER is not set +CONFIG_UNWIND_INFO=y +# CONFIG_FORCED_INLINING is not set +# CONFIG_BOOT_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_S390=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA256_S390=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_DES_S390=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_S390=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y diff --git a/configs/kernel-2.6.18-x86_64-kdump.config b/configs/kernel-2.6.18-x86_64-kdump.config new file mode 100644 index 000000000..e62073eff --- /dev/null +++ b/configs/kernel-2.6.18-x86_64-kdump.config @@ -0,0 +1,3136 @@ +# x86_64 +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:42 2006 +# +CONFIG_X86_64=y +CONFIG_64BIT=y +CONFIG_X86=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_X86_CMPXCHG=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_DMI=y +CONFIG_AUDIT_ARCH=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Processor type and features +# +CONFIG_X86_PC=y +# CONFIG_X86_VSMP is not set +# CONFIG_MK8 is not set +# CONFIG_MPSC is not set +CONFIG_GENERIC_CPU=y +# CONFIG_X86_64_XEN is not set +CONFIG_X86_L1_CACHE_BYTES=128 +CONFIG_X86_L1_CACHE_SHIFT=7 +CONFIG_X86_INTERNODE_CACHE_BYTES=128 +CONFIG_X86_TSC=y +CONFIG_X86_GOOD_APIC=y +CONFIG_MICROCODE=m +CONFIG_X86_MSR=y +CONFIG_X86_CPUID=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_LOCAL_APIC=y +CONFIG_MTRR=y +# CONFIG_SMP is not set +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +# CONFIG_FLATMEM_MANUAL is not set +# CONFIG_DISCONTIGMEM_MANUAL is not set +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_HAVE_MEMORY_PRESENT=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPARSEMEM_EXTREME=y + +# +# Memory hotplug is currently incompatible with Software Suspend +# +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_RESOURCES_64BIT=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_HPET_TIMER=y +CONFIG_HPET_EMULATE_RTC=y +CONFIG_IOMMU=y +CONFIG_CALGARY_IOMMU=y +CONFIG_SWIOTLB=y +CONFIG_X86_MCE=y +CONFIG_X86_MCE_INTEL=y +CONFIG_X86_MCE_AMD=y +CONFIG_KEXEC=y +CONFIG_CRASH_DUMP=y +CONFIG_PHYSICAL_START=0x1000000 +# CONFIG_SECCOMP is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_REORDER=y +CONFIG_K8_NB=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_ISA_DMA_API=y + +# +# Power management options +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +CONFIG_SOFTWARE_SUSPEND=y +CONFIG_PM_STD_PARTITION="" + +# +# ACPI (Advanced Configuration and Power Interface) Support +# +CONFIG_ACPI=y +CONFIG_ACPI_SLEEP=y +CONFIG_ACPI_SLEEP_PROC_FS=y +# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set +CONFIG_ACPI_AC=m +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_VIDEO=m +# CONFIG_ACPI_HOTKEY is not set +CONFIG_ACPI_FAN=y +CONFIG_ACPI_DOCK=m +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_ASUS=m +CONFIG_ACPI_IBM=m +CONFIG_ACPI_TOSHIBA=m +CONFIG_ACPI_BLACKLIST_YEAR=0 +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_EC=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_X86_PM_TIMER=y +CONFIG_ACPI_CONTAINER=m +CONFIG_ACPI_SBS=m + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m + +# +# CPUFreq processor drivers +# +CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_POWERNOW_K8_ACPI=y +CONFIG_X86_SPEEDSTEP_CENTRINO=y +CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y +CONFIG_X86_ACPI_CPUFREQ=m + +# +# shared options +# +# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set +# CONFIG_X86_SPEEDSTEP_LIB is not set + +# +# Bus options (PCI etc.) +# +CONFIG_PCI=y +CONFIG_PCI_DIRECT=y +CONFIG_PCI_MMCONFIG=y +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=m +# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set +# CONFIG_PCI_MSI is not set +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +CONFIG_PCCARD_NONSTATIC=y + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_FAKE=m +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +# CONFIG_HOTPLUG_PCI_CPCI is not set +CONFIG_HOTPLUG_PCI_SHPC=m +# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set + +# +# Executable file formats / Emulations +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_IA32_EMULATION=y +# CONFIG_IA32_AOUT is not set +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# +CONFIG_IRPORT_SIR=m + +# +# Old Serial dongle support +# +# CONFIG_DONGLE_OLD is not set + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PNC2000 is not set +CONFIG_MTD_SC520CDP=m +CONFIG_MTD_NETSC520=m +CONFIG_MTD_TS5500=m +# CONFIG_MTD_SBC_GXX is not set +# CONFIG_MTD_AMD76XROM is not set +# CONFIG_MTD_ICHXROM is not set +CONFIG_MTD_SCB2_FLASH=m +# CONFIG_MTD_NETtel is not set +# CONFIG_MTD_DILNETPC is not set +# CONFIG_MTD_L440GX is not set +CONFIG_MTD_PCI=m +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_ECC_SMC=y +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_NANDSIM=m + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_PNPACPI=y + +# +# Block devices +# +CONFIG_BLK_DEV_FD=m +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_CMD640 is not set +CONFIG_BLK_DEV_IDEPNP=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_RZ1000 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +CONFIG_BLK_DEV_AMD74XX=y +CONFIG_BLK_DEV_ATIIXP=y +CONFIG_BLK_DEV_CMD64X=y +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +CONFIG_BLK_DEV_SIS5513=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +CONFIG_SCSI_BUSLOGIC=m +# CONFIG_SCSI_OMIT_FLASHPOINT is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DC390T=m +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_PCMCIA_FDOMAIN is not set +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set + +# +# Device Drivers +# +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m + +# +# I2O device support +# +CONFIG_I2O=m +# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_EXT_ADAPTEC_DMA64=y +CONFIG_I2O_CONFIG=m +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_BUS=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_NET_SB1000=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +CONFIG_VORTEX=m +CONFIG_TYPHOON=m + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +# CONFIG_PCMCIA_XIRTULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y +CONFIG_NET_POCKET=y +CONFIG_ATP=m +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +CONFIG_IBMOL=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +# CONFIG_IPW2200_DEBUG is not set +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_BCM43XX=m +CONFIG_BCM43XX_DEBUG=y +CONFIG_BCM43XX_DMA=y +CONFIG_BCM43XX_PIO=y +CONFIG_BCM43XX_DMA_AND_PIO_MODE=y +# CONFIG_BCM43XX_DMA_MODE is not set +# CONFIG_BCM43XX_PIO_MODE is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DRV_LOOP=m +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +CONFIG_HISAX_16_3=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_HDLC=y + +# +# Active cards +# +CONFIG_HYSDN=m +CONFIG_HYSDN_CAPI=y + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m + +# +# Active Eicon DIVA Server cards +# +# CONFIG_CAPI_EICON is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_CRASH=m +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +# CONFIG_SC520_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +CONFIG_IBMASR=m +# CONFIG_WAFER_WDT is not set +CONFIG_I6300ESB_WDT=m +CONFIG_I8XX_TCO=m +# CONFIG_SC1200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_SBC8360_WDT is not set +# CONFIG_CPU5_WDT is not set +CONFIG_W83627HF_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_MACHZ_WDT=m +# CONFIG_SBC_EPX_C3_WATCHDOG is not set + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_AMD=m +# CONFIG_HW_RANDOM_GEODE is not set +CONFIG_NVRAM=y +CONFIG_RTC=y +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +CONFIG_AGP=y +CONFIG_AGP_AMD64=y +CONFIG_AGP_INTEL=y +CONFIG_AGP_SIS=y +CONFIG_AGP_VIA=y +CONFIG_DRM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I810=m +CONFIG_DRM_I830=m +CONFIG_DRM_I915=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +CONFIG_MWAVE=m +CONFIG_PC8736x_GPIO=m +CONFIG_NSC_GPIO=m +# CONFIG_RAW_DRIVER is not set +CONFIG_HPET=y +# CONFIG_HPET_RTC_IRQ is not set +# CONFIG_HPET_MMAP is not set +CONFIG_HANGCHECK_TIMER=m + +# +# TPM devices +# +CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m +CONFIG_TCG_NSC=m +CONFIG_TCG_ATMEL=m +CONFIG_TCG_INFINEON=m +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +CONFIG_I2C_I801=m +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_ISA=m +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +CONFIG_I2C_SIS96X=m +CONFIG_I2C_STUB=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y + +# +# Hardware Monitoring support +# +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_HDAPS=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# +# CONFIG_IBM_ASM is not set + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y + +# +# Video Capture Adapters +# + +# +# Video Capture Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_24XXX=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set + +# +# Radio Adapters +# +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +CONFIG_USB_DSBR=m + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m + +# +# Miscellaneous devices +# +CONFIG_DVB_PLL=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6421=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_VIDEOBUF=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ARC is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +CONFIG_FB_VGA16=m +CONFIG_FB_VESA=y +# CONFIG_FB_HGA is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_INTEL=m +# CONFIG_FB_INTEL_DEBUG is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=m +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_SIS is not set +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_GEODE is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_VIDEO_SELECT=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_RTCTIMER=m +CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_MPU401=m + +# +# PCI devices +# +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +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_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_WBSD=m + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_ISER=m + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# +CONFIG_EDAC=y + +# +# Reporting subsystems +# +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_E752X=m +CONFIG_EDAC_K8=m +CONFIG_EDAC_POLL=y + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=m + +# +# Firmware Drivers +# +CONFIG_EDD=m +CONFIG_DELL_RBU=m +CONFIG_DCDBAS=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_VMCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FRAME_POINTER is not set +CONFIG_UNWIND_INFO=y +CONFIG_STACK_UNWIND=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_RODATA=y +# CONFIG_IOMMU_DEBUG is not set +CONFIG_DEBUG_STACKOVERFLOW=y +# CONFIG_DEBUG_STACK_USAGE is not set + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_X86_64=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y diff --git a/configs/kernel-2.6.18-x86_64-xen.config b/configs/kernel-2.6.18-x86_64-xen.config new file mode 100644 index 000000000..b4a0c30c0 --- /dev/null +++ b/configs/kernel-2.6.18-x86_64-xen.config @@ -0,0 +1,3144 @@ +# x86_64 +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:43 2006 +# +CONFIG_X86_64=y +CONFIG_64BIT=y +CONFIG_X86=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_X86_CMPXCHG=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_DMI=y +CONFIG_AUDIT_ARCH=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Processor type and features +# +CONFIG_X86_PC=y +# CONFIG_X86_VSMP is not set +# CONFIG_MK8 is not set +# CONFIG_MPSC is not set +CONFIG_GENERIC_CPU=y +CONFIG_X86_64_XEN=y +CONFIG_X86_NO_TSS=y +CONFIG_X86_NO_IDT=y +CONFIG_X86_L1_CACHE_BYTES=128 +CONFIG_X86_L1_CACHE_SHIFT=7 +CONFIG_X86_INTERNODE_CACHE_BYTES=128 +CONFIG_X86_GOOD_APIC=y +CONFIG_MICROCODE=y +CONFIG_X86_MSR=y +CONFIG_X86_CPUID=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_XEN_GENAPIC=y +CONFIG_X86_LOCAL_APIC=y +CONFIG_MTRR=y +CONFIG_SMP=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_RESOURCES_64BIT=y +CONFIG_NR_CPUS=8 +CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_CALGARY_IOMMU=y +CONFIG_SWIOTLB=y +# CONFIG_CRASH_DUMP is not set +CONFIG_PHYSICAL_START=0x200000 +# CONFIG_SECCOMP is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_REORDER=y +CONFIG_K8_NB=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_ISA_DMA_API=y +CONFIG_GENERIC_PENDING_IRQ=y + +# +# Power management options +# +CONFIG_PM=y + +# +# ACPI (Advanced Configuration and Power Interface) Support +# +CONFIG_ACPI=y +CONFIG_ACPI_AC=m +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_VIDEO=m +# CONFIG_ACPI_HOTKEY is not set +CONFIG_ACPI_FAN=y +CONFIG_ACPI_DOCK=m +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_ASUS=m +CONFIG_ACPI_IBM=m +CONFIG_ACPI_TOSHIBA=m +CONFIG_ACPI_BLACKLIST_YEAR=0 +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_EC=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_ACPI_CONTAINER=y +CONFIG_ACPI_SBS=m + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m + +# +# CPUFreq processor drivers +# +CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_POWERNOW_K8_ACPI=y +CONFIG_X86_SPEEDSTEP_CENTRINO=y +CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y +CONFIG_X86_ACPI_CPUFREQ=m + +# +# shared options +# +# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set +# CONFIG_X86_SPEEDSTEP_LIB is not set + +# +# Bus options (PCI etc.) +# +CONFIG_PCI=y +CONFIG_PCI_DIRECT=y +# CONFIG_PCI_MMCONFIG is not set +CONFIG_XEN_PCIDEV_FRONTEND=y +# CONFIG_XEN_PCIDEV_FE_DEBUG is not set +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=m +# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +CONFIG_PCCARD_NONSTATIC=y + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_FAKE=m +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +# CONFIG_HOTPLUG_PCI_CPCI is not set +CONFIG_HOTPLUG_PCI_SHPC=m +# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set + +# +# Executable file formats / Emulations +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_IA32_EMULATION=y +# CONFIG_IA32_AOUT is not set +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PNC2000 is not set +CONFIG_MTD_SC520CDP=m +CONFIG_MTD_NETSC520=m +CONFIG_MTD_TS5500=m +# CONFIG_MTD_SBC_GXX is not set +# CONFIG_MTD_AMD76XROM is not set +# CONFIG_MTD_ICHXROM is not set +CONFIG_MTD_SCB2_FLASH=m +# CONFIG_MTD_NETtel is not set +# CONFIG_MTD_DILNETPC is not set +# CONFIG_MTD_L440GX is not set +CONFIG_MTD_PCI=m +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_ECC_SMC=y +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_NANDSIM=m + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_PNPACPI=y + +# +# Block devices +# +CONFIG_BLK_DEV_FD=m +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_CMD640 is not set +CONFIG_BLK_DEV_IDEPNP=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_RZ1000 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +CONFIG_BLK_DEV_AMD74XX=y +CONFIG_BLK_DEV_ATIIXP=y +CONFIG_BLK_DEV_CMD64X=y +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +CONFIG_BLK_DEV_SIS5513=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +CONFIG_SCSI_BUSLOGIC=m +# CONFIG_SCSI_OMIT_FLASHPOINT is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DC390T=m +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_PCMCIA_FDOMAIN is not set +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set + +# +# Device Drivers +# +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m + +# +# I2O device support +# +CONFIG_I2O=m +# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_EXT_ADAPTEC_DMA64=y +CONFIG_I2O_CONFIG=m +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_BUS=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_NET_SB1000=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +CONFIG_VORTEX=m +CONFIG_TYPHOON=m + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y +CONFIG_NET_POCKET=y +CONFIG_ATP=m +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +CONFIG_IBMOL=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +# CONFIG_IPW2200_DEBUG is not set +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_BCM43XX=m +CONFIG_BCM43XX_DEBUG=y +CONFIG_BCM43XX_DMA=y +CONFIG_BCM43XX_PIO=y +CONFIG_BCM43XX_DMA_AND_PIO_MODE=y +# CONFIG_BCM43XX_DMA_MODE is not set +# CONFIG_BCM43XX_PIO_MODE is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +CONFIG_HISAX_16_3=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_HDLC=y + +# +# Active cards +# + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m + +# +# Active Eicon DIVA Server cards +# +# CONFIG_CAPI_EICON is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=m +CONFIG_SERIAL_8250_PCI=m +CONFIG_SERIAL_8250_PNP=m +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=m +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_CRASH=m +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +# CONFIG_SC520_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +CONFIG_IBMASR=m +# CONFIG_WAFER_WDT is not set +CONFIG_I6300ESB_WDT=m +CONFIG_I8XX_TCO=m +# CONFIG_SC1200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_SBC8360_WDT is not set +# CONFIG_CPU5_WDT is not set +CONFIG_W83627HF_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_MACHZ_WDT=m +# CONFIG_SBC_EPX_C3_WATCHDOG is not set + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_AMD=m +# CONFIG_HW_RANDOM_GEODE is not set +CONFIG_NVRAM=y +CONFIG_RTC=y +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +CONFIG_AGP=y +CONFIG_AGP_AMD64=y +CONFIG_AGP_INTEL=y +CONFIG_AGP_SIS=y +CONFIG_AGP_VIA=y +CONFIG_DRM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I810=m +CONFIG_DRM_I830=m +CONFIG_DRM_I915=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +CONFIG_MWAVE=m +CONFIG_PC8736x_GPIO=m +CONFIG_NSC_GPIO=m +# CONFIG_RAW_DRIVER is not set +CONFIG_HPET=y +# CONFIG_HPET_RTC_IRQ is not set +# CONFIG_HPET_MMAP is not set +CONFIG_HANGCHECK_TIMER=m + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +CONFIG_I2C_I801=m +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_ISA=m +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +CONFIG_I2C_SIS96X=m +CONFIG_I2C_STUB=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y + +# +# Hardware Monitoring support +# +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_HDAPS=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# +# CONFIG_IBM_ASM is not set + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y + +# +# Video Capture Adapters +# + +# +# Video Capture Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_24XXX=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set + +# +# Radio Adapters +# +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +CONFIG_USB_DSBR=m + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m + +# +# Miscellaneous devices +# +CONFIG_DVB_PLL=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6421=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_VIDEOBUF=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ARC is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +CONFIG_FB_VGA16=m +CONFIG_FB_VESA=y +# CONFIG_FB_HGA is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_INTEL=m +# CONFIG_FB_INTEL_DEBUG is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=m +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_SIS is not set +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_GEODE is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_VIDEO_SELECT=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_RTCTIMER=m +CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_MPU401=m + +# +# PCI devices +# +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +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_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_WBSD=m + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_ISER=m + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# +CONFIG_EDAC=y + +# +# Reporting subsystems +# +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_E752X=m +CONFIG_EDAC_K8=m +CONFIG_EDAC_POLL=y + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=m + +# +# Firmware Drivers +# +CONFIG_DELL_RBU=m +CONFIG_DCDBAS=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FRAME_POINTER is not set +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_RODATA=y +CONFIG_DEBUG_STACKOVERFLOW=y +# CONFIG_DEBUG_STACK_USAGE is not set + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_X86_64=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# +CONFIG_XEN=y +CONFIG_XEN_INTERFACE_VERSION=0x00030203 + +# +# XEN +# +CONFIG_XEN_PRIVILEGED_GUEST=y +# CONFIG_XEN_UNPRIVILEGED_GUEST is not set +CONFIG_XEN_PRIVCMD=y +CONFIG_XEN_XENBUS_DEV=y +CONFIG_XEN_BACKEND=y +CONFIG_XEN_BLKDEV_BACKEND=m +CONFIG_XEN_BLKDEV_TAP=m +CONFIG_XEN_NETDEV_BACKEND=m +# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set +CONFIG_XEN_NETDEV_LOOPBACK=m +CONFIG_XEN_PCIDEV_BACKEND=m +CONFIG_XEN_PCIDEV_BACKEND_VPCI=y +# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set +# CONFIG_XEN_PCIDEV_BE_DEBUG is not set +# CONFIG_XEN_TPMDEV_BACKEND is not set +CONFIG_XEN_BLKDEV_FRONTEND=m +CONFIG_XEN_NETDEV_FRONTEND=m +CONFIG_XEN_FRAMEBUFFER=y +CONFIG_XEN_KEYBOARD=y +CONFIG_XEN_SCRUB_PAGES=y +# CONFIG_XEN_DISABLE_SERIAL is not set +CONFIG_XEN_SYSFS=y +CONFIG_XEN_COMPAT_030002_AND_LATER=y +# CONFIG_XEN_COMPAT_LATEST_ONLY is not set +CONFIG_XEN_COMPAT_030002=y +CONFIG_HAVE_ARCH_ALLOC_SKB=y +CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y +CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y +CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_UTIL=y +CONFIG_XEN_BALLOON=y +CONFIG_XEN_DEVMEM=y +CONFIG_XEN_SKBUFF=y +CONFIG_XEN_REBOOT=y +CONFIG_XEN_SMPBOOT=y + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y diff --git a/configs/kernel-2.6.18-x86_64-xen0.config b/configs/kernel-2.6.18-x86_64-xen0.config new file mode 100644 index 000000000..25d6f9044 --- /dev/null +++ b/configs/kernel-2.6.18-x86_64-xen0.config @@ -0,0 +1,3144 @@ +# x86_64 +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:43 2006 +# +CONFIG_X86_64=y +CONFIG_64BIT=y +CONFIG_X86=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_X86_CMPXCHG=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_DMI=y +CONFIG_AUDIT_ARCH=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Processor type and features +# +CONFIG_X86_PC=y +# CONFIG_X86_VSMP is not set +# CONFIG_MK8 is not set +# CONFIG_MPSC is not set +CONFIG_GENERIC_CPU=y +CONFIG_X86_64_XEN=y +CONFIG_X86_NO_TSS=y +CONFIG_X86_NO_IDT=y +CONFIG_X86_L1_CACHE_BYTES=128 +CONFIG_X86_L1_CACHE_SHIFT=7 +CONFIG_X86_INTERNODE_CACHE_BYTES=128 +CONFIG_X86_GOOD_APIC=y +CONFIG_MICROCODE=y +CONFIG_X86_MSR=y +CONFIG_X86_CPUID=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_XEN_GENAPIC=y +CONFIG_X86_LOCAL_APIC=y +CONFIG_MTRR=y +CONFIG_SMP=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_RESOURCES_64BIT=y +CONFIG_NR_CPUS=8 +CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_CALGARY_IOMMU=y +CONFIG_SWIOTLB=y +# CONFIG_CRASH_DUMP is not set +CONFIG_PHYSICAL_START=0x200000 +# CONFIG_SECCOMP is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_REORDER=y +CONFIG_K8_NB=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_ISA_DMA_API=y +CONFIG_GENERIC_PENDING_IRQ=y + +# +# Power management options +# +CONFIG_PM=y + +# +# ACPI (Advanced Configuration and Power Interface) Support +# +CONFIG_ACPI=y +CONFIG_ACPI_AC=m +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_VIDEO=m +# CONFIG_ACPI_HOTKEY is not set +CONFIG_ACPI_FAN=y +CONFIG_ACPI_DOCK=m +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_ASUS=m +CONFIG_ACPI_IBM=m +CONFIG_ACPI_TOSHIBA=m +CONFIG_ACPI_BLACKLIST_YEAR=0 +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_EC=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_ACPI_CONTAINER=y +CONFIG_ACPI_SBS=m + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m + +# +# CPUFreq processor drivers +# +CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_POWERNOW_K8_ACPI=y +CONFIG_X86_SPEEDSTEP_CENTRINO=y +CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y +CONFIG_X86_ACPI_CPUFREQ=m + +# +# shared options +# +# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set +# CONFIG_X86_SPEEDSTEP_LIB is not set + +# +# Bus options (PCI etc.) +# +CONFIG_PCI=y +CONFIG_PCI_DIRECT=y +# CONFIG_PCI_MMCONFIG is not set +CONFIG_XEN_PCIDEV_FRONTEND=y +# CONFIG_XEN_PCIDEV_FE_DEBUG is not set +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=m +# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +CONFIG_PCCARD_NONSTATIC=y + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_FAKE=m +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +# CONFIG_HOTPLUG_PCI_CPCI is not set +CONFIG_HOTPLUG_PCI_SHPC=m +# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set + +# +# Executable file formats / Emulations +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_IA32_EMULATION=y +# CONFIG_IA32_AOUT is not set +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PNC2000 is not set +CONFIG_MTD_SC520CDP=m +CONFIG_MTD_NETSC520=m +CONFIG_MTD_TS5500=m +# CONFIG_MTD_SBC_GXX is not set +# CONFIG_MTD_AMD76XROM is not set +# CONFIG_MTD_ICHXROM is not set +CONFIG_MTD_SCB2_FLASH=m +# CONFIG_MTD_NETtel is not set +# CONFIG_MTD_DILNETPC is not set +# CONFIG_MTD_L440GX is not set +CONFIG_MTD_PCI=m +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_ECC_SMC=y +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_NANDSIM=m + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_PNPACPI=y + +# +# Block devices +# +CONFIG_BLK_DEV_FD=m +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_CMD640 is not set +CONFIG_BLK_DEV_IDEPNP=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_RZ1000 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +CONFIG_BLK_DEV_AMD74XX=y +CONFIG_BLK_DEV_ATIIXP=y +CONFIG_BLK_DEV_CMD64X=y +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +CONFIG_BLK_DEV_SIS5513=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +CONFIG_SCSI_BUSLOGIC=m +# CONFIG_SCSI_OMIT_FLASHPOINT is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DC390T=m +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_PCMCIA_FDOMAIN is not set +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set + +# +# Device Drivers +# +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m + +# +# I2O device support +# +CONFIG_I2O=m +# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_EXT_ADAPTEC_DMA64=y +CONFIG_I2O_CONFIG=m +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_BUS=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_NET_SB1000=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +CONFIG_VORTEX=m +CONFIG_TYPHOON=m + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y +CONFIG_NET_POCKET=y +CONFIG_ATP=m +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +CONFIG_IBMOL=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +# CONFIG_IPW2200_DEBUG is not set +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_BCM43XX=m +CONFIG_BCM43XX_DEBUG=y +CONFIG_BCM43XX_DMA=y +CONFIG_BCM43XX_PIO=y +CONFIG_BCM43XX_DMA_AND_PIO_MODE=y +# CONFIG_BCM43XX_DMA_MODE is not set +# CONFIG_BCM43XX_PIO_MODE is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +CONFIG_HISAX_16_3=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_HDLC=y + +# +# Active cards +# + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m + +# +# Active Eicon DIVA Server cards +# +# CONFIG_CAPI_EICON is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=m +CONFIG_SERIAL_8250_PCI=m +CONFIG_SERIAL_8250_PNP=m +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=m +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_CRASH=m +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +# CONFIG_SC520_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +CONFIG_IBMASR=m +# CONFIG_WAFER_WDT is not set +CONFIG_I6300ESB_WDT=m +CONFIG_I8XX_TCO=m +# CONFIG_SC1200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_SBC8360_WDT is not set +# CONFIG_CPU5_WDT is not set +CONFIG_W83627HF_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_MACHZ_WDT=m +# CONFIG_SBC_EPX_C3_WATCHDOG is not set + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_AMD=m +# CONFIG_HW_RANDOM_GEODE is not set +CONFIG_NVRAM=y +CONFIG_RTC=y +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +CONFIG_AGP=y +CONFIG_AGP_AMD64=y +CONFIG_AGP_INTEL=y +CONFIG_AGP_SIS=y +CONFIG_AGP_VIA=y +CONFIG_DRM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I810=m +CONFIG_DRM_I830=m +CONFIG_DRM_I915=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +CONFIG_MWAVE=m +CONFIG_PC8736x_GPIO=m +CONFIG_NSC_GPIO=m +# CONFIG_RAW_DRIVER is not set +CONFIG_HPET=y +# CONFIG_HPET_RTC_IRQ is not set +# CONFIG_HPET_MMAP is not set +CONFIG_HANGCHECK_TIMER=m + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +CONFIG_I2C_I801=m +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_ISA=m +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +CONFIG_I2C_SIS96X=m +CONFIG_I2C_STUB=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y + +# +# Hardware Monitoring support +# +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_HDAPS=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# +# CONFIG_IBM_ASM is not set + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y + +# +# Video Capture Adapters +# + +# +# Video Capture Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_24XXX=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set + +# +# Radio Adapters +# +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +CONFIG_USB_DSBR=m + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m + +# +# Miscellaneous devices +# +CONFIG_DVB_PLL=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6421=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_VIDEOBUF=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ARC is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +CONFIG_FB_VGA16=m +CONFIG_FB_VESA=y +# CONFIG_FB_HGA is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_INTEL=m +# CONFIG_FB_INTEL_DEBUG is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=m +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_SIS is not set +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_GEODE is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_VIDEO_SELECT=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_RTCTIMER=m +CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_MPU401=m + +# +# PCI devices +# +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +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_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_WBSD=m + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_ISER=m + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# +CONFIG_EDAC=y + +# +# Reporting subsystems +# +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_E752X=m +CONFIG_EDAC_K8=m +CONFIG_EDAC_POLL=y + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=m + +# +# Firmware Drivers +# +CONFIG_DELL_RBU=m +CONFIG_DCDBAS=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FRAME_POINTER is not set +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_RODATA=y +CONFIG_DEBUG_STACKOVERFLOW=y +# CONFIG_DEBUG_STACK_USAGE is not set + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_X86_64=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# +CONFIG_XEN=y +CONFIG_XEN_INTERFACE_VERSION=0x00030203 + +# +# XEN +# +CONFIG_XEN_PRIVILEGED_GUEST=y +# CONFIG_XEN_UNPRIVILEGED_GUEST is not set +CONFIG_XEN_PRIVCMD=y +CONFIG_XEN_XENBUS_DEV=y +CONFIG_XEN_BACKEND=y +CONFIG_XEN_BLKDEV_BACKEND=y +CONFIG_XEN_BLKDEV_TAP=m +CONFIG_XEN_NETDEV_BACKEND=y +# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set +CONFIG_XEN_NETDEV_LOOPBACK=y +CONFIG_XEN_PCIDEV_BACKEND=m +CONFIG_XEN_PCIDEV_BACKEND_VPCI=y +# CONFIG_XEN_PCIDEV_BACKEND_PASS is not set +# CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set +# CONFIG_XEN_PCIDEV_BE_DEBUG is not set +# CONFIG_XEN_TPMDEV_BACKEND is not set +CONFIG_XEN_BLKDEV_FRONTEND=m +CONFIG_XEN_NETDEV_FRONTEND=m +CONFIG_XEN_FRAMEBUFFER=y +CONFIG_XEN_KEYBOARD=y +CONFIG_XEN_SCRUB_PAGES=y +# CONFIG_XEN_DISABLE_SERIAL is not set +CONFIG_XEN_SYSFS=y +CONFIG_XEN_COMPAT_030002_AND_LATER=y +# CONFIG_XEN_COMPAT_LATEST_ONLY is not set +CONFIG_XEN_COMPAT_030002=y +CONFIG_HAVE_ARCH_ALLOC_SKB=y +CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y +CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y +CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_UTIL=y +CONFIG_XEN_BALLOON=y +CONFIG_XEN_DEVMEM=y +CONFIG_XEN_SKBUFF=y +CONFIG_XEN_REBOOT=y +CONFIG_XEN_SMPBOOT=y + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y diff --git a/configs/kernel-2.6.18-x86_64-xenU.config b/configs/kernel-2.6.18-x86_64-xenU.config new file mode 100644 index 000000000..78ffb6490 --- /dev/null +++ b/configs/kernel-2.6.18-x86_64-xenU.config @@ -0,0 +1,1581 @@ +# x86_64 +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:43 2006 +# +CONFIG_X86_64=y +CONFIG_64BIT=y +CONFIG_X86=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_X86_CMPXCHG=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_DMI=y +CONFIG_AUDIT_ARCH=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Processor type and features +# +CONFIG_X86_PC=y +# CONFIG_X86_VSMP is not set +# CONFIG_MK8 is not set +# CONFIG_MPSC is not set +CONFIG_GENERIC_CPU=y +CONFIG_X86_64_XEN=y +CONFIG_X86_NO_TSS=y +CONFIG_X86_NO_IDT=y +CONFIG_X86_L1_CACHE_BYTES=128 +CONFIG_X86_L1_CACHE_SHIFT=7 +CONFIG_X86_INTERNODE_CACHE_BYTES=128 +CONFIG_X86_GOOD_APIC=y +# CONFIG_MICROCODE is not set +CONFIG_X86_MSR=y +CONFIG_X86_CPUID=y +CONFIG_X86_XEN_GENAPIC=y +CONFIG_SMP=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_RESOURCES_64BIT=y +CONFIG_NR_CPUS=8 +CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_SWIOTLB=y +# CONFIG_CRASH_DUMP is not set +CONFIG_PHYSICAL_START=0x200000 +# CONFIG_SECCOMP is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_REORDER=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_ISA_DMA_API=y +CONFIG_GENERIC_PENDING_IRQ=y + +# +# Bus options (PCI etc.) +# +# CONFIG_PCI is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +# CONFIG_PCMCIA is not set + +# +# PC-card bridges +# + +# +# PCI Hotplug Support +# + +# +# Executable file formats / Emulations +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_IA32_EMULATION=y +# CONFIG_IA32_AOUT is not set +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=m +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +# CONFIG_DONGLE is not set + +# +# Old SIR device drivers +# + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VIA_FIR=m +# CONFIG_BT is not set +# CONFIG_IEEE80211 is not set +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=m +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +CONFIG_BLK_DEV_FD=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_IDE_ARM is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_SCSI_SATA=m +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# + +# +# I2O device support +# + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m + +# +# PHY device support +# +# CONFIG_PHYLIB is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINKMP=m +CONFIG_N_HDLC=m +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_CRASH=m + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_SC520_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +CONFIG_IBMASR=m +# CONFIG_WAFER_WDT is not set +# CONFIG_SC1200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_SBC8360_WDT is not set +# CONFIG_CPU5_WDT is not set +CONFIG_W83627HF_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_MACHZ_WDT=m +# CONFIG_SBC_EPX_C3_WATCHDOG is not set +CONFIG_HW_RANDOM=y +CONFIG_NVRAM=y +CONFIG_RTC=y +CONFIG_DTLK=m +CONFIG_R3964=m + +# +# Ftape, the floppy tape device driver +# +# CONFIG_MWAVE is not set +CONFIG_PC8736x_GPIO=m +CONFIG_NSC_GPIO=m +# CONFIG_RAW_DRIVER is not set +CONFIG_HANGCHECK_TIMER=m + +# +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Hardware Monitoring support +# +# CONFIG_HWMON is not set +# CONFIG_HWMON_VID is not set + +# +# Misc devices +# + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_V4L2=y + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +CONFIG_FB_TILEBLITTING=y +# CONFIG_FB_ARC is not set +CONFIG_FB_VGA16=m +CONFIG_FB_VESA=y +# CONFIG_FB_HGA is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_VIDEO_SELECT=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +# CONFIG_SND is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set +# CONFIG_USB_ARCH_HAS_EHCI is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# +# CONFIG_EDAC is not set + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_DS1742=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# + +# +# Firmware Drivers +# +CONFIG_DELL_RBU=m +CONFIG_DCDBAS=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FRAME_POINTER is not set +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_RODATA=y +CONFIG_DEBUG_STACKOVERFLOW=y +# CONFIG_DEBUG_STACK_USAGE is not set + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_X86_64=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# +CONFIG_XEN=y +CONFIG_XEN_INTERFACE_VERSION=0x00030203 + +# +# XEN +# +# CONFIG_XEN_PRIVILEGED_GUEST is not set +CONFIG_XEN_UNPRIVILEGED_GUEST=y +CONFIG_XEN_PRIVCMD=y +CONFIG_XEN_XENBUS_DEV=y +CONFIG_XEN_BACKEND=y +# CONFIG_XEN_BLKDEV_BACKEND is not set +CONFIG_XEN_BLKDEV_TAP=m +# CONFIG_XEN_NETDEV_BACKEND is not set +# CONFIG_XEN_TPMDEV_BACKEND is not set +CONFIG_XEN_BLKDEV_FRONTEND=y +CONFIG_XEN_NETDEV_FRONTEND=m +CONFIG_XEN_FRAMEBUFFER=y +CONFIG_XEN_KEYBOARD=y +CONFIG_XEN_SCRUB_PAGES=y +CONFIG_XEN_DISABLE_SERIAL=y +CONFIG_XEN_SYSFS=y +CONFIG_XEN_COMPAT_030002_AND_LATER=y +# CONFIG_XEN_COMPAT_LATEST_ONLY is not set +CONFIG_XEN_COMPAT_030002=y +CONFIG_HAVE_ARCH_ALLOC_SKB=y +CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y +CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y +CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_UTIL=y +CONFIG_XEN_BALLOON=y +CONFIG_XEN_DEVMEM=y +CONFIG_XEN_SKBUFF=y +CONFIG_XEN_REBOOT=y +CONFIG_XEN_SMPBOOT=y + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y diff --git a/configs/kernel-2.6.18-x86_64.config b/configs/kernel-2.6.18-x86_64.config new file mode 100644 index 000000000..16135f6c2 --- /dev/null +++ b/configs/kernel-2.6.18-x86_64.config @@ -0,0 +1,3150 @@ +# x86_64 +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.18.2-rc1 +# Mon Nov 13 09:44:43 2006 +# +CONFIG_X86_64=y +CONFIG_64BIT=y +CONFIG_X86=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_SEMAPHORE_SLEEPERS=y +CONFIG_MMU=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_X86_CMPXCHG=y +CONFIG_EARLY_PRINTK=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_IOMAP=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_DMI=y +CONFIG_AUDIT_ARCH=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 + +# +# General setup +# +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +# CONFIG_IKCONFIG is not set +CONFIG_CPUSETS=y +CONFIG_RELAY=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_EMBEDDED is not set +CONFIG_UID16=y +CONFIG_SYSCTL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_KALLSYMS_EXTRA_PASS=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SHMEM=y +CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_SLOB is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_KMOD=y +CONFIG_STOP_MACHINE=y + +# +# Process debugging support +# +CONFIG_UTRACE=y +CONFIG_PTRACE=y + +# +# Block layer +# +CONFIG_LBD=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LSF=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# Processor type and features +# +CONFIG_X86_PC=y +# CONFIG_X86_VSMP is not set +# CONFIG_MK8 is not set +# CONFIG_MPSC is not set +CONFIG_GENERIC_CPU=y +# CONFIG_X86_64_XEN is not set +CONFIG_X86_L1_CACHE_BYTES=128 +CONFIG_X86_L1_CACHE_SHIFT=7 +CONFIG_X86_INTERNODE_CACHE_BYTES=128 +CONFIG_X86_TSC=y +CONFIG_X86_GOOD_APIC=y +CONFIG_MICROCODE=m +CONFIG_X86_MSR=y +CONFIG_X86_CPUID=y +CONFIG_X86_HT=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_LOCAL_APIC=y +CONFIG_MTRR=y +CONFIG_SMP=y +CONFIG_SCHED_SMT=y +CONFIG_SCHED_MC=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y +CONFIG_NUMA=y +CONFIG_K8_NUMA=y +CONFIG_NODES_SHIFT=6 +CONFIG_X86_64_ACPI_NUMA=y +# CONFIG_NUMA_EMU is not set +CONFIG_ARCH_DISCONTIGMEM_ENABLE=y +CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_SELECT_MEMORY_MODEL=y +# CONFIG_FLATMEM_MANUAL is not set +# CONFIG_DISCONTIGMEM_MANUAL is not set +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_NEED_MULTIPLE_NODES=y +CONFIG_HAVE_MEMORY_PRESENT=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPARSEMEM_EXTREME=y + +# +# Memory hotplug is currently incompatible with Software Suspend +# +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_MIGRATION=y +CONFIG_RESOURCES_64BIT=y +CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y +CONFIG_NR_CPUS=255 +CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_HPET_TIMER=y +CONFIG_HPET_EMULATE_RTC=y +CONFIG_IOMMU=y +CONFIG_CALGARY_IOMMU=y +CONFIG_SWIOTLB=y +CONFIG_X86_MCE=y +CONFIG_X86_MCE_INTEL=y +CONFIG_X86_MCE_AMD=y +CONFIG_KEXEC=y +# CONFIG_CRASH_DUMP is not set +CONFIG_PHYSICAL_START=0x200000 +# CONFIG_SECCOMP is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_REORDER=y +CONFIG_K8_NB=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_ISA_DMA_API=y +CONFIG_GENERIC_PENDING_IRQ=y + +# +# Power management options +# +CONFIG_PM=y +CONFIG_PM_LEGACY=y +# CONFIG_PM_DEBUG is not set +CONFIG_SOFTWARE_SUSPEND=y +CONFIG_PM_STD_PARTITION="" +CONFIG_SUSPEND_SMP=y + +# +# ACPI (Advanced Configuration and Power Interface) Support +# +CONFIG_ACPI=y +CONFIG_ACPI_SLEEP=y +CONFIG_ACPI_SLEEP_PROC_FS=y +# CONFIG_ACPI_SLEEP_PROC_SLEEP is not set +CONFIG_ACPI_AC=m +CONFIG_ACPI_BATTERY=m +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_VIDEO=m +# CONFIG_ACPI_HOTKEY is not set +CONFIG_ACPI_FAN=y +CONFIG_ACPI_DOCK=m +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_NUMA=y +CONFIG_ACPI_ASUS=m +CONFIG_ACPI_IBM=m +CONFIG_ACPI_TOSHIBA=m +CONFIG_ACPI_BLACKLIST_YEAR=0 +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_EC=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_SYSTEM=y +CONFIG_X86_PM_TIMER=y +CONFIG_ACPI_CONTAINER=y +CONFIG_ACPI_SBS=m + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_DEBUG=y +CONFIG_CPU_FREQ_STAT=m +CONFIG_CPU_FREQ_STAT_DETAILS=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=m +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m + +# +# CPUFreq processor drivers +# +CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_POWERNOW_K8_ACPI=y +CONFIG_X86_SPEEDSTEP_CENTRINO=y +CONFIG_X86_SPEEDSTEP_CENTRINO_ACPI=y +CONFIG_X86_ACPI_CPUFREQ=m + +# +# shared options +# +# CONFIG_X86_ACPI_CPUFREQ_PROC_INTF is not set +# CONFIG_X86_SPEEDSTEP_LIB is not set + +# +# Bus options (PCI etc.) +# +CONFIG_PCI=y +CONFIG_PCI_DIRECT=y +CONFIG_PCI_MMCONFIG=y +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=m +# CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set +CONFIG_PCI_MSI=y +# CONFIG_PCI_DEBUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y +CONFIG_CARDBUS=y + +# +# PC-card bridges +# +CONFIG_YENTA=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +CONFIG_PCCARD_NONSTATIC=y + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +CONFIG_HOTPLUG_PCI_FAKE=m +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +# CONFIG_HOTPLUG_PCI_CPCI is not set +CONFIG_HOTPLUG_PCI_SHPC=m +# CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set + +# +# Executable file formats / Emulations +# +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_IA32_EMULATION=y +# CONFIG_IA32_AOUT is not set +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_NETDEBUG is not set +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +CONFIG_XFRM=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_FWMARK=y +CONFIG_IP_ROUTE_MULTIPATH=y +# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set +CONFIG_IP_ROUTE_VERBOSE=y +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_DIAG=m +CONFIG_INET_TCP_DIAG=m +CONFIG_TCP_CONG_ADVANCED=y + +# +# TCP congestion control +# +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m + +# +# IP: Virtual Server Configuration +# +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_TAB_BITS=12 + +# +# IPVS transport protocol load balancing support +# +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y + +# +# IPVS scheduler +# +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m + +# +# IPVS application helper +# +CONFIG_IP_VS_FTP=m +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_IPV6_TUNNEL=m +CONFIG_NETWORK_SECMARK=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m + +# +# IP: Netfilter Configuration +# +CONFIG_IP_NF_CONNTRACK=m +CONFIG_IP_NF_CT_ACCT=y +CONFIG_IP_NF_CONNTRACK_MARK=y +CONFIG_IP_NF_CONNTRACK_SECMARK=y +CONFIG_IP_NF_CONNTRACK_EVENTS=y +CONFIG_IP_NF_CONNTRACK_NETLINK=m +CONFIG_IP_NF_CT_PROTO_SCTP=m +CONFIG_IP_NF_FTP=m +CONFIG_IP_NF_IRC=m +CONFIG_IP_NF_NETBIOS_NS=m +CONFIG_IP_NF_TFTP=m +CONFIG_IP_NF_AMANDA=m +CONFIG_IP_NF_PPTP=m +CONFIG_IP_NF_H323=m +CONFIG_IP_NF_SIP=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MATCH_IPRANGE=m +CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_DSCP=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_MATCH_OWNER=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_HASHLIMIT=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_NF_TARGET_TCPMSS=m +CONFIG_IP_NF_NAT=m +CONFIG_IP_NF_NAT_NEEDED=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m +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_NAT_AMANDA=m +CONFIG_IP_NF_NAT_PPTP=m +CONFIG_IP_NF_NAT_H323=m +CONFIG_IP_NF_NAT_SIP=m +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_TTL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m + +# +# IPv6: Netfilter Configuration (EXPERIMENTAL) +# +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_OWNER=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_RAW=m + +# +# DECnet: Netfilter Configuration +# +# CONFIG_DECNET_NF_GRABULATOR is not set + +# +# Bridge: Netfilter Configuration +# +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_ULOG=m + +# +# DCCP Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_IP_DCCP_ACKVEC=y + +# +# DCCP CCIDs Configuration (EXPERIMENTAL) +# +CONFIG_IP_DCCP_CCID2=m +CONFIG_IP_DCCP_CCID3=m +CONFIG_IP_DCCP_TFRC_LIB=m + +# +# DCCP Kernel Hacking +# +# CONFIG_IP_DCCP_DEBUG is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y + +# +# TIPC Configuration (EXPERIMENTAL) +# +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +# CONFIG_ATM_MPOA is not set +CONFIG_ATM_BR2684=m +# CONFIG_ATM_BR2684_IPFILTER is not set +CONFIG_BRIDGE=m +CONFIG_VLAN_8021Q=m +CONFIG_DECNET=m +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_IPDDP_DECAP=y +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +CONFIG_WAN_ROUTER=m + +# +# QoS and/or fair queueing +# +CONFIG_NET_SCHED=y +# CONFIG_NET_SCH_CLK_JIFFIES is not set +CONFIG_NET_SCH_CLK_GETTIMEOFDAY=y +# CONFIG_NET_SCH_CLK_CPU is not set + +# +# Queueing/Scheduling +# +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_INGRESS=m + +# +# Classification +# +CONFIG_NET_CLS=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_CLS_IND=y +CONFIG_NET_ESTIMATOR=y + +# +# Network testing +# +CONFIG_NET_PKTGEN=m +# CONFIG_NET_TCPPROBE is not set +# CONFIG_HAMRADIO is not set +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +CONFIG_IRTTY_SIR=m + +# +# Dongle support +# +CONFIG_DONGLE=y +CONFIG_ESI_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_LITELINK_DONGLE=m +CONFIG_MA600_DONGLE=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_MCP2120_DONGLE=m +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_ACT200L_DONGLE=m + +# +# Old SIR device drivers +# + +# +# Old Serial dongle support +# + +# +# FIR device drivers +# +CONFIG_USB_IRDA=m +CONFIG_SIGMATEL_FIR=m +CONFIG_NSC_FIR=m +CONFIG_WINBOND_FIR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_ALI_FIR=m +CONFIG_VLSI_FIR=m +CONFIG_VIA_FIR=m +CONFIG_MCS_FIR=m +CONFIG_BT=m +CONFIG_BT_L2CAP=m +CONFIG_BT_SCO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HIDP=m + +# +# Bluetooth device drivers +# +CONFIG_BT_HCIUSB=m +CONFIG_BT_HCIUSB_SCO=y +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIVHCI=m +CONFIG_IEEE80211=m +# CONFIG_IEEE80211_DEBUG is not set +CONFIG_IEEE80211_CRYPT_WEP=m +CONFIG_IEEE80211_CRYPT_CCMP=m +CONFIG_IEEE80211_CRYPT_TKIP=m +CONFIG_IEEE80211_SOFTMAC=m +CONFIG_IEEE80211_SOFTMAC_DEBUG=y +CONFIG_TUX=m + +# +# TUX options +# +CONFIG_TUX_EXTCGI=y +CONFIG_TUX_EXTENDED_LOG=y +# CONFIG_TUX_DEBUG is not set +CONFIG_WIRELESS_EXT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set + +# +# Connector - unified userspace <-> kernelspace linker +# +CONFIG_CONNECTOR=y +CONFIG_PROC_EVENTS=y + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=m +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=m +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +CONFIG_MTD_CMDLINE_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_BLOCK_RO=m +CONFIG_FTL=m +CONFIG_NFTL=m +CONFIG_NFTL_RW=y +CONFIG_INFTL=m +CONFIG_RFD_FTL=m + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_GEN_PROBE=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_RAM=m +CONFIG_MTD_ROM=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PNC2000 is not set +CONFIG_MTD_SC520CDP=m +CONFIG_MTD_NETSC520=m +CONFIG_MTD_TS5500=m +# CONFIG_MTD_SBC_GXX is not set +# CONFIG_MTD_AMD76XROM is not set +# CONFIG_MTD_ICHXROM is not set +CONFIG_MTD_SCB2_FLASH=m +# CONFIG_MTD_NETtel is not set +# CONFIG_MTD_DILNETPC is not set +# CONFIG_MTD_L440GX is not set +CONFIG_MTD_PCI=m +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +CONFIG_MTD_MTDRAM=m +CONFIG_MTDRAM_TOTAL_SIZE=4096 +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTD_BLOCK2MTD=m + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +CONFIG_MTD_NAND=m +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NAND_ECC_SMC=y +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_NANDSIM=m + +# +# OneNAND Flash Device Drivers +# +# CONFIG_MTD_ONENAND is not set + +# +# Parallel port support +# +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_SERIAL=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_PCMCIA=m +CONFIG_PARPORT_NOT_PC=y +# CONFIG_PARPORT_GSC is not set +# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_1284=y + +# +# Plug and Play support +# +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set + +# +# Protocols +# +CONFIG_PNPACPI=y + +# +# Block devices +# +CONFIG_BLK_DEV_FD=m +CONFIG_PARIDE=m +CONFIG_PARIDE_PARPORT=m + +# +# Parallel IDE high-level drivers +# +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PT=m +CONFIG_PARIDE_PG=m + +# +# Parallel IDE protocol modules +# +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_EPAT=m +CONFIG_PARIDE_EPATC8=y +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_CISS_SCSI_TAPE=y +CONFIG_BLK_DEV_DAC960=m +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_UB=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_CDROM_PKTCDVD=m +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_ATA_OVER_ETH=m + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDE_SATA is not set +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +CONFIG_BLK_DEV_IDECS=m +CONFIG_BLK_DEV_IDECD=m +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +CONFIG_IDE_TASK_IOCTL=y + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_CMD640 is not set +CONFIG_BLK_DEV_IDEPNP=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_RZ1000 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_AEC62XX=y +CONFIG_BLK_DEV_ALI15X3=y +# CONFIG_WDC_ALI15X3 is not set +CONFIG_BLK_DEV_AMD74XX=y +CONFIG_BLK_DEV_ATIIXP=y +CONFIG_BLK_DEV_CMD64X=y +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +CONFIG_BLK_DEV_HPT34X=y +# CONFIG_HPT34X_AUTODMA is not set +CONFIG_BLK_DEV_HPT366=y +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_BLK_DEV_IT821X=y +# CONFIG_BLK_DEV_NS87415 is not set +CONFIG_BLK_DEV_PDC202XX_OLD=y +# CONFIG_PDC202XX_BURST is not set +CONFIG_BLK_DEV_PDC202XX_NEW=y +CONFIG_BLK_DEV_SVWKS=y +CONFIG_BLK_DEV_SIIMAGE=y +CONFIG_BLK_DEV_SIS5513=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +CONFIG_BLK_DEV_VIA82CXXX=y +# CONFIG_IDE_ARM is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_RAID_ATTRS=m +CONFIG_SCSI=m +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=m +CONFIG_CHR_DEV_ST=m +CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=m +CONFIG_CHR_DEV_SCH=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y + +# +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_ISCSI_ATTRS=m +CONFIG_SCSI_SAS_ATTRS=m + +# +# SCSI low-level drivers +# +CONFIG_ISCSI_TCP=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +CONFIG_AIC7XXX_DEBUG_MASK=0 +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC7XXX_OLD=m +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_SATA=m +CONFIG_SCSI_SATA_AHCI=m +CONFIG_SCSI_SATA_SVW=m +CONFIG_SCSI_ATA_PIIX=m +CONFIG_SCSI_SATA_MV=m +CONFIG_SCSI_SATA_NV=m +CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_SATA_QSTOR=m +CONFIG_SCSI_SATA_PROMISE=m +CONFIG_SCSI_SATA_SX4=m +CONFIG_SCSI_SATA_SIL=m +CONFIG_SCSI_SATA_SIL24=m +CONFIG_SCSI_SATA_SIS=m +CONFIG_SCSI_SATA_ULI=m +CONFIG_SCSI_SATA_VIA=m +CONFIG_SCSI_SATA_VITESSE=m +CONFIG_SCSI_SATA_INTEL_COMBINED=y +CONFIG_SCSI_BUSLOGIC=m +# CONFIG_SCSI_OMIT_FLASHPOINT is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_IMM=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +# CONFIG_SCSI_IPR is not set +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_LPFC=m +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DC390T=m +# CONFIG_SCSI_DEBUG is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_PCMCIA_FDOMAIN is not set +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MD_RAID5_RESHAPE=y +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m + +# +# IEEE 1394 (FireWire) support +# +CONFIG_IEEE1394=m + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y +CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y +CONFIG_IEEE1394_CONFIG_ROM_IP1394=y +# CONFIG_IEEE1394_EXPORT_FULL_API is not set + +# +# Device Drivers +# +CONFIG_IEEE1394_PCILYNX=m +CONFIG_IEEE1394_OHCI1394=m + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=m + +# +# I2O device support +# +CONFIG_I2O=m +# CONFIG_I2O_LCT_NOTIFY_ON_CHANGES is not set +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_EXT_ADAPTEC_DMA64=y +CONFIG_I2O_CONFIG=m +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_BUS=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_SCSI=m +CONFIG_I2O_PROC=m + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_IFB=m +CONFIG_DUMMY=m +CONFIG_BONDING=m +CONFIG_EQUALIZER=m +CONFIG_TUN=m +CONFIG_NET_SB1000=m + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set + +# +# PHY device support +# +CONFIG_PHYLIB=m + +# +# MII PHY device drivers +# +CONFIG_MARVELL_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_LXT_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_SMSC_PHY=m +CONFIG_FIXED_PHY=m +CONFIG_FIXED_MII_10_FDX=y +CONFIG_FIXED_MII_100_FDX=y + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=m +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NET_VENDOR_3COM=y +CONFIG_VORTEX=m +CONFIG_TYPHOON=m + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +CONFIG_TULIP_MMIO=y +# CONFIG_TULIP_NAPI is not set +CONFIG_DE4X5=m +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=m +CONFIG_AMD8111_ETH=m +CONFIG_AMD8111E_NAPI=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADAPTEC_STARFIRE_NAPI=y +CONFIG_B44=m +CONFIG_FORCEDETH=m +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NE2K_PCI=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +CONFIG_8139TOO_8129=y +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_SIS900=m +CONFIG_EPIC100=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_RHINE_NAPI=y +CONFIG_NET_POCKET=y +CONFIG_ATP=m +CONFIG_DE600=m +CONFIG_DE620=m + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set +CONFIG_NS83820=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_R8169=m +CONFIG_R8169_NAPI=y +CONFIG_R8169_VLAN=y +CONFIG_SIS190=m +CONFIG_SKGE=m +CONFIG_SKY2=m +# CONFIG_SK98LIN is not set +CONFIG_VIA_VELOCITY=m +CONFIG_TIGON3=m +CONFIG_BNX2=m + +# +# Ethernet (10000 Mbit) +# +CONFIG_CHELSIO_T1=m +CONFIG_IXGB=m +CONFIG_IXGB_NAPI=y +CONFIG_S2IO=m +CONFIG_S2IO_NAPI=y +CONFIG_MYRI10GE=m + +# +# Token Ring devices +# +CONFIG_TR=y +CONFIG_IBMOL=m +CONFIG_3C359=m +# CONFIG_TMS380TR is not set + +# +# Wireless LAN (non-hamradio) +# +CONFIG_NET_RADIO=y +CONFIG_NET_WIRELESS_RTNETLINK=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set +CONFIG_PCMCIA_WAVELAN=m +CONFIG_PCMCIA_NETWAVE=m + +# +# Wireless 802.11 Frequency Hopping cards support +# +# CONFIG_PCMCIA_RAYCS is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +CONFIG_IPW2100=m +CONFIG_IPW2100_MONITOR=y +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2200=m +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +# CONFIG_IPW2200_DEBUG is not set +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_ATMEL=m +CONFIG_PCI_ATMEL=m + +# +# Wireless 802.11b Pcmcia/Cardbus cards support +# +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_WL3501=m + +# +# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support +# +CONFIG_PRISM54=m +CONFIG_USB_ZD1201=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m +CONFIG_BCM43XX=m +CONFIG_BCM43XX_DEBUG=y +CONFIG_BCM43XX_DMA=y +CONFIG_BCM43XX_PIO=y +CONFIG_BCM43XX_DMA_AND_PIO_MODE=y +# CONFIG_BCM43XX_DMA_MODE is not set +# CONFIG_BCM43XX_PIO_MODE is not set +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_NET_WIRELESS=y + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_AXNET=m + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# ATM drivers +# +# CONFIG_ATM_DUMMY is not set +CONFIG_ATM_TCP=m +CONFIG_ATM_LANAI=m +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +# CONFIG_ATM_ZATM is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_FORE200E_MAYBE=m +# CONFIG_ATM_FORE200E_PCA is not set +CONFIG_ATM_HE=m +# CONFIG_ATM_HE_USE_SUNI is not set +CONFIG_FDDI=y +# CONFIG_DEFXX is not set +CONFIG_SKFP=m +# CONFIG_HIPPI is not set +CONFIG_PLIP=m +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_MPPE=m +CONFIG_PPPOE=m +CONFIG_PPPOATM=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +# CONFIG_SLIP_MODE_SLIP6 is not set +CONFIG_NET_FC=y +# CONFIG_SHAPER is not set +CONFIG_NETCONSOLE=m +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_RX is not set +CONFIG_NETPOLL_TRAP=y +CONFIG_NET_POLL_CONTROLLER=y + +# +# ISDN subsystem +# +CONFIG_ISDN=m + +# +# Old ISDN4Linux +# +CONFIG_ISDN_I4L=m +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_MPP=y +CONFIG_IPPP_FILTER=y +# CONFIG_ISDN_PPP_BSDCOMP is not set +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_TTY_FAX=y + +# +# ISDN feature submodules +# +CONFIG_ISDN_DIVERSION=m + +# +# ISDN4Linux hardware drivers +# + +# +# Passive cards +# +CONFIG_ISDN_DRV_HISAX=m + +# +# D-channel protocol features +# +CONFIG_HISAX_EURO=y +CONFIG_DE_AOC=y +CONFIG_HISAX_NO_SENDCOMPLETE=y +CONFIG_HISAX_NO_LLC=y +CONFIG_HISAX_NO_KEYPAD=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_MAX_CARDS=8 + +# +# HiSax supported cards +# +CONFIG_HISAX_16_3=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NICCY=y +CONFIG_HISAX_BKM_A4T=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_W6692=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_ENTERNOW_PCI=y +# CONFIG_HISAX_DEBUG is not set + +# +# HiSax PCMCIA card service modules +# +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_TELES_CS=m + +# +# HiSax sub driver modules +# +CONFIG_HISAX_ST5481=m +# CONFIG_HISAX_HFCUSB is not set +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_HDLC=y + +# +# Active cards +# + +# +# Siemens Gigaset +# +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_GIGASET_BASE=m +CONFIG_GIGASET_M105=m +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_UNDOCREQ is not set + +# +# CAPI subsystem +# +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIDRV=m + +# +# CAPI hardware drivers +# + +# +# Active AVM cards +# +CONFIG_CAPI_AVM=y +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_C4=m + +# +# Active Eicon DIVA Server cards +# +# CONFIG_CAPI_EICON is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_UINPUT=m + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PARKBD is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_RAW=m +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +CONFIG_CYCLADES=m +# CONFIG_CYZ_INTR is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_GT=m +CONFIG_N_HDLC=m +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_CS=m +CONFIG_SERIAL_8250_NR_UARTS=32 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_8250_DETECT_IRQ=y +CONFIG_SERIAL_8250_RSA=y + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_JSM=m +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_CRASH=m +CONFIG_PRINTER=m +CONFIG_LP_CONSOLE=y +CONFIG_PPDEV=m +CONFIG_TIPAR=m + +# +# IPMI +# +CONFIG_IPMI_HANDLER=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPMI_POWEROFF=m + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +CONFIG_SOFT_WATCHDOG=m +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +CONFIG_ALIM1535_WDT=m +CONFIG_ALIM7101_WDT=m +# CONFIG_SC520_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +CONFIG_IBMASR=m +# CONFIG_WAFER_WDT is not set +CONFIG_I6300ESB_WDT=m +CONFIG_I8XX_TCO=m +# CONFIG_SC1200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_SBC8360_WDT is not set +# CONFIG_CPU5_WDT is not set +CONFIG_W83627HF_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_MACHZ_WDT=m +# CONFIG_SBC_EPX_C3_WATCHDOG is not set + +# +# PCI-based Watchdog Cards +# +CONFIG_PCIPCWATCHDOG=m +CONFIG_WDTPCI=m +CONFIG_WDT_501_PCI=y + +# +# USB-based Watchdog Cards +# +CONFIG_USBPCWATCHDOG=m +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_AMD=m +# CONFIG_HW_RANDOM_GEODE is not set +CONFIG_NVRAM=y +CONFIG_RTC=y +CONFIG_DTLK=m +CONFIG_R3964=m +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +CONFIG_AGP=y +CONFIG_AGP_AMD64=y +CONFIG_AGP_INTEL=y +CONFIG_AGP_SIS=y +CONFIG_AGP_VIA=y +CONFIG_DRM=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_I810=m +CONFIG_DRM_I830=m +CONFIG_DRM_I915=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_DRM_VIA=m +CONFIG_DRM_SAVAGE=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +CONFIG_MWAVE=m +CONFIG_PC8736x_GPIO=m +CONFIG_NSC_GPIO=m +# CONFIG_RAW_DRIVER is not set +CONFIG_HPET=y +# CONFIG_HPET_RTC_IRQ is not set +# CONFIG_HPET_MMAP is not set +CONFIG_HANGCHECK_TIMER=m + +# +# TPM devices +# +CONFIG_TCG_TPM=m +CONFIG_TCG_TIS=m +CONFIG_TCG_NSC=m +CONFIG_TCG_ATMEL=m +CONFIG_TCG_INFINEON=m +# CONFIG_TELCLOCK is not set + +# +# I2C support +# +CONFIG_I2C=m +CONFIG_I2C_CHARDEV=m + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +CONFIG_I2C_I801=m +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +CONFIG_I2C_ISA=m +CONFIG_I2C_NFORCE2=m +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +CONFIG_I2C_PROSAVAGE=m +CONFIG_I2C_SAVAGE4=m +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +CONFIG_I2C_SIS96X=m +CONFIG_I2C_STUB=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m +CONFIG_I2C_VOODOO3=m +CONFIG_I2C_PCA_ISA=m + +# +# Miscellaneous I2C Chip support +# +CONFIG_SENSORS_DS1337=m +CONFIG_SENSORS_DS1374=m +CONFIG_SENSORS_EEPROM=m +CONFIG_SENSORS_PCF8574=m +CONFIG_SENSORS_PCA9539=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_MAX6875=m +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# +# Dallas's 1-wire bus +# +CONFIG_W1=m +CONFIG_W1_CON=y + +# +# 1-wire Bus Masters +# +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m + +# +# 1-wire Slaves +# +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y + +# +# Hardware Monitoring support +# +CONFIG_HWMON=m +CONFIG_HWMON_VID=m +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_FSCHER=m +CONFIG_SENSORS_FSCPOS=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_HDAPS=m +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Misc devices +# +# CONFIG_IBM_ASM is not set + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y + +# +# Video Capture Adapters +# + +# +# Video Capture Adapters +# +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_SAA5246A=m +CONFIG_VIDEO_SAA5249=m +CONFIG_TUNER_3036=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_DVB_ALL_FRONTENDS=y +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_DPC=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_DVB_ALL_FRONTENDS=y + +# +# Encoders and Decoders +# +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m + +# +# V4L USB devices +# +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_24XXX=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_USB_VICAM=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_KONICAWC=m +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_ET61X251=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_USB_W9968CF=m +CONFIG_USB_OV511=m +CONFIG_USB_SE401=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STV680=m +CONFIG_USB_ZC0301=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set + +# +# Radio Adapters +# +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MAESTRO=m +CONFIG_USB_DSBR=m + +# +# Digital Video Broadcasting Devices +# +CONFIG_DVB=y +CONFIG_DVB_CORE=m + +# +# Supported SAA7146 based PCI Adapters +# +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_PATCH=m + +# +# Supported USB Adapters +# +CONFIG_DVB_USB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_DIBUSB_MB=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_CXUSB=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_CINERGYT2=m +CONFIG_DVB_CINERGYT2_TUNING=y +CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT=32 +CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE=512 +CONFIG_DVB_CINERGYT2_QUERY_INTERVAL=250 +CONFIG_DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE=y +CONFIG_DVB_CINERGYT2_RC_QUERY_INTERVAL=100 + +# +# Supported FlexCopII (B2C2) Adapters +# +CONFIG_DVB_B2C2_FLEXCOP=m +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set + +# +# Supported BT878 Adapters +# +CONFIG_DVB_BT8XX=m + +# +# Supported Pluto2 Adapters +# +CONFIG_DVB_PLUTO2=m + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# + +# +# DVB-S (satellite) frontends +# +CONFIG_DVB_STV0299=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_MT312=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_S5H1420=m + +# +# DVB-T (terrestrial) frontends +# +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_L64781=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_MT352=m +CONFIG_DVB_ZL10353=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m + +# +# DVB-C (cable) frontends +# +CONFIG_DVB_VES1820=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_STV0297=m + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +CONFIG_DVB_NXT200X=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_LGDT330X=m + +# +# Miscellaneous devices +# +CONFIG_DVB_PLL=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_ISL6421=m +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_VIDEOBUF=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_BUF=m +CONFIG_VIDEO_BUF_DVB=m +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_USB_DABUSB=m + +# +# Graphics support +# +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_CIRRUS=m +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ARC is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +CONFIG_FB_VGA16=m +CONFIG_FB_VESA=y +# CONFIG_FB_HGA is not set +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_RIVA=m +# CONFIG_FB_RIVA_I2C is not set +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_INTEL=m +# CONFIG_FB_INTEL_DEBUG is not set +CONFIG_FB_MATROX=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MULTIHEAD=y +CONFIG_FB_RADEON=m +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_ATY128=m +CONFIG_FB_ATY=m +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_SAVAGE=m +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SAVAGE_ACCEL=y +# CONFIG_FB_SIS is not set +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_KYRO=m +CONFIG_FB_3DFX=m +CONFIG_FB_3DFX_ACCEL=y +CONFIG_FB_VOODOO1=m +CONFIG_FB_TRIDENT=m +CONFIG_FB_TRIDENT_ACCEL=y +# CONFIG_FB_GEODE is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +CONFIG_VGACON_SOFT_SCROLLBACK=y +CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 +CONFIG_VIDEO_SELECT=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_CLASS_DEVICE=m +CONFIG_BACKLIGHT_DEVICE=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_DEVICE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_TIMER=m +CONFIG_SND_PCM=m +CONFIG_SND_HWDEP=m +CONFIG_SND_RAWMIDI=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_RTCTIMER=m +CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_MPU401_UART=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_BUS=m +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_MPU401=m + +# +# PCI devices +# +CONFIG_SND_AD1889=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_ALI5451=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_KORG1212=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_TRIDENT=m +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m + +# +# USB devices +# +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_USX2Y=m + +# +# PCMCIA devices +# +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_SPLIT_ISO=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_CS=m + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_LIBUSUAL=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_AIPTEK=m +CONFIG_USB_WACOM=m +CONFIG_USB_ACECAD=m +CONFIG_USB_KBTAB=m +CONFIG_USB_POWERMATE=m +CONFIG_USB_TOUCHSCREEN=m +CONFIG_USB_TOUCHSCREEN_EGALAX=y +CONFIG_USB_TOUCHSCREEN_PANJIT=y +CONFIG_USB_TOUCHSCREEN_3M=y +CONFIG_USB_TOUCHSCREEN_ITM=y +# CONFIG_USB_YEALINK is not set +CONFIG_USB_XPAD=m +CONFIG_USB_ATI_REMOTE=m +CONFIG_USB_ATI_REMOTE2=m +CONFIG_USB_KEYSPAN_REMOTE=m +CONFIG_USB_APPLETOUCH=m + +# +# USB Imaging devices +# +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m + +# +# USB Network Adapters +# +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_USBNET=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_NET_ZAURUS=m +CONFIG_USB_MON=y + +# +# USB port drivers +# +CONFIG_USB_USS720=m + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_AIRPRIME=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP2101=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +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_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_AUERSWALD=m +CONFIG_USB_RIO500=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_LED=m +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +CONFIG_USB_PHIDGETKIT=m +CONFIG_USB_PHIDGETSERVO=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_SISUSBVGA_CON=y +CONFIG_USB_LD=m +CONFIG_USB_TEST=m + +# +# USB DSL modem support +# +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +CONFIG_MMC=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_WBSD=m + +# +# LED devices +# +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_IDE_DISK=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m + +# +# InfiniBand support +# +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +CONFIG_IPATH_CORE=m +CONFIG_INFINIBAND_IPATH=m +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_DEBUG=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_ISER=m + +# +# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) +# +CONFIG_EDAC=y + +# +# Reporting subsystems +# +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_MM_EDAC=m +CONFIG_EDAC_E752X=m +CONFIG_EDAC_K8=m +CONFIG_EDAC_POLL=y + +# +# Real Time Clock +# +CONFIG_RTC_LIB=m +CONFIG_RTC_CLASS=m + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set + +# +# RTC drivers +# +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_RS5C372=m +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_V3020=m + +# +# DMA Engine support +# +CONFIG_DMA_ENGINE=y + +# +# DMA Clients +# +CONFIG_NET_DMA=y + +# +# DMA Devices +# +CONFIG_INTEL_IOATDMA=m + +# +# Firmware Drivers +# +CONFIG_EDD=m +CONFIG_DELL_RBU=m +CONFIG_DCDBAS=m + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XIP=y +CONFIG_FS_XIP=y +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +CONFIG_XFS_QUOTA=y +CONFIG_XFS_SECURITY=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_XFS_RT is not set +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_QUOTA=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +CONFIG_DNOTIFY=y +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m +CONFIG_FUSE_FS=m + +# +# Caches +# +CONFIG_FSCACHE=m + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_CACHEFILES=m +CONFIG_CACHEFILES_DEBUG=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_RAMFS=y +CONFIG_CONFIGFS_FS=m + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +CONFIG_AFFS_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BFS_FS=m +CONFIG_EFS_FS=m +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +CONFIG_JFFS2_SUMMARY=y +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +# CONFIG_SQUASHFS_VMALLOC is not set +CONFIG_VXFS_FS=m +# CONFIG_HPFS_FS is not set +CONFIG_QNX4FS_FS=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +# CONFIG_UFS_DEBUG is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPCSEC_GSS_SPKM3=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_EXPERIMENTAL is not set +CONFIG_NCP_FS=m +CONFIG_NCPFS_PACKET_SIGNING=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_STRONG=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_SMALLDOS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_EXTRAS=y +CONFIG_CODA_FS=m +# CONFIG_CODA_FS_OLD_API is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=m + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# 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_LDM_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Instrumentation Support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_KERNEL=y +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_LIST=y +# CONFIG_FRAME_POINTER is not set +CONFIG_UNWIND_INFO=y +CONFIG_STACK_UNWIND=y +# CONFIG_FORCED_INLINING is not set +CONFIG_BOOT_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_DEBUG_RODATA=y +# CONFIG_IOMMU_DEBUG is not set +CONFIG_DEBUG_STACKOVERFLOW=y +# CONFIG_DEBUG_STACK_USAGE is not set + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY_ROOTPLUG is not set +# CONFIG_SECURITY_SECLVL is not set +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT is not set +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_X86_64=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIGNATURE=y +CONFIG_CRYPTO_SIGNATURE_DSA=y +CONFIG_CRYPTO_MPILIB=y + +# +# Hardware crypto devices +# + +# +# Library routines +# +CONFIG_CRC_CCITT=m +CONFIG_CRC16=m +CONFIG_CRC32=y +CONFIG_LIBCRC32C=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=m +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_PLIST=y diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c new file mode 100644 index 000000000..a01ce6700 --- /dev/null +++ b/drivers/acpi/cm_sbs.c @@ -0,0 +1,113 @@ +/* + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/acpi.h> +#include <linux/types.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#include <acpi/acpi_bus.h> +#include <acpi/acpi_drivers.h> +#include <acpi/acmacros.h> +#include <acpi/actypes.h> +#include <acpi/acutils.h> + +ACPI_MODULE_NAME("cm_sbs") +#define ACPI_AC_CLASS "ac_adapter" +#define ACPI_BATTERY_CLASS "battery" +#define ACPI_SBS_COMPONENT 0x00080000 +#define _COMPONENT ACPI_SBS_COMPONENT +static struct proc_dir_entry *acpi_ac_dir; +static struct proc_dir_entry *acpi_battery_dir; + +static DEFINE_MUTEX(cm_sbs_mutex); + +static int lock_ac_dir_cnt; +static int lock_battery_dir_cnt; + +struct proc_dir_entry *acpi_lock_ac_dir(void) +{ + mutex_lock(&cm_sbs_mutex); + if (!acpi_ac_dir) + acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir); + if (acpi_ac_dir) { + lock_ac_dir_cnt++; + } else { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Cannot create %s\n", ACPI_AC_CLASS)); + } + mutex_unlock(&cm_sbs_mutex); + return acpi_ac_dir; +} +EXPORT_SYMBOL(acpi_lock_ac_dir); + +void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir_param) +{ + mutex_lock(&cm_sbs_mutex); + if (acpi_ac_dir_param) + lock_ac_dir_cnt--; + if (lock_ac_dir_cnt == 0 && acpi_ac_dir_param && acpi_ac_dir) { + remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); + acpi_ac_dir = 0; + } + mutex_unlock(&cm_sbs_mutex); +} +EXPORT_SYMBOL(acpi_unlock_ac_dir); + +struct proc_dir_entry *acpi_lock_battery_dir(void) +{ + mutex_lock(&cm_sbs_mutex); + if (!acpi_battery_dir) { + acpi_battery_dir = + proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir); + } + if (acpi_battery_dir) { + lock_battery_dir_cnt++; + } else { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Cannot create %s\n", ACPI_BATTERY_CLASS)); + } + mutex_unlock(&cm_sbs_mutex); + return acpi_battery_dir; +} +EXPORT_SYMBOL(acpi_lock_battery_dir); + +void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param) +{ + mutex_lock(&cm_sbs_mutex); + if (acpi_battery_dir_param) + lock_battery_dir_cnt--; + if (lock_battery_dir_cnt == 0 && acpi_battery_dir_param + && acpi_battery_dir) { + remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); + acpi_battery_dir = 0; + } + mutex_unlock(&cm_sbs_mutex); + return; +} +EXPORT_SYMBOL(acpi_unlock_battery_dir); + +static int __init acpi_cm_sbs_init(void) +{ + return 0; +} +subsys_initcall(acpi_cm_sbs_init); diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c new file mode 100644 index 000000000..578b99b71 --- /dev/null +++ b/drivers/acpi/dock.c @@ -0,0 +1,739 @@ +/* + * dock.c - ACPI dock station driver + * + * Copyright (C) 2006 Kristen Carlson Accardi <kristen.c.accardi@intel.com> + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/notifier.h> +#include <acpi/acpi_bus.h> +#include <acpi/acpi_drivers.h> + +#define ACPI_DOCK_DRIVER_NAME "ACPI Dock Station Driver" + +ACPI_MODULE_NAME("dock") +MODULE_AUTHOR("Kristen Carlson Accardi"); +MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_NAME); +MODULE_LICENSE("GPL"); + +static struct atomic_notifier_head dock_notifier_list; + +struct dock_station { + acpi_handle handle; + unsigned long last_dock_time; + u32 flags; + spinlock_t dd_lock; + spinlock_t hp_lock; + struct list_head dependent_devices; + struct list_head hotplug_devices; +}; + +struct dock_dependent_device { + struct list_head list; + struct list_head hotplug_list; + acpi_handle handle; + acpi_notify_handler handler; + void *context; +}; + +#define DOCK_DOCKING 0x00000001 +#define DOCK_EVENT 3 +#define UNDOCK_EVENT 2 + +static struct dock_station *dock_station; + +/***************************************************************************** + * Dock Dependent device functions * + *****************************************************************************/ +/** + * alloc_dock_dependent_device - allocate and init a dependent device + * @handle: the acpi_handle of the dependent device + * + * Allocate memory for a dependent device structure for a device referenced + * by the acpi handle + */ +static struct dock_dependent_device * +alloc_dock_dependent_device(acpi_handle handle) +{ + struct dock_dependent_device *dd; + + dd = kzalloc(sizeof(*dd), GFP_KERNEL); + if (dd) { + dd->handle = handle; + INIT_LIST_HEAD(&dd->list); + INIT_LIST_HEAD(&dd->hotplug_list); + } + return dd; +} + +/** + * add_dock_dependent_device - associate a device with the dock station + * @ds: The dock station + * @dd: The dependent device + * + * Add the dependent device to the dock's dependent device list. + */ +static void +add_dock_dependent_device(struct dock_station *ds, + struct dock_dependent_device *dd) +{ + spin_lock(&ds->dd_lock); + list_add_tail(&dd->list, &ds->dependent_devices); + spin_unlock(&ds->dd_lock); +} + +/** + * dock_add_hotplug_device - associate a hotplug handler with the dock station + * @ds: The dock station + * @dd: The dependent device struct + * + * Add the dependent device to the dock's hotplug device list + */ +static void +dock_add_hotplug_device(struct dock_station *ds, + struct dock_dependent_device *dd) +{ + spin_lock(&ds->hp_lock); + list_add_tail(&dd->hotplug_list, &ds->hotplug_devices); + spin_unlock(&ds->hp_lock); +} + +/** + * dock_del_hotplug_device - remove a hotplug handler from the dock station + * @ds: The dock station + * @dd: the dependent device struct + * + * Delete the dependent device from the dock's hotplug device list + */ +static void +dock_del_hotplug_device(struct dock_station *ds, + struct dock_dependent_device *dd) +{ + spin_lock(&ds->hp_lock); + list_del(&dd->hotplug_list); + spin_unlock(&ds->hp_lock); +} + +/** + * find_dock_dependent_device - get a device dependent on this dock + * @ds: the dock station + * @handle: the acpi_handle of the device we want + * + * iterate over the dependent device list for this dock. If the + * dependent device matches the handle, return. + */ +static struct dock_dependent_device * +find_dock_dependent_device(struct dock_station *ds, acpi_handle handle) +{ + struct dock_dependent_device *dd; + + spin_lock(&ds->dd_lock); + list_for_each_entry(dd, &ds->dependent_devices, list) { + if (handle == dd->handle) { + spin_unlock(&ds->dd_lock); + return dd; + } + } + spin_unlock(&ds->dd_lock); + return NULL; +} + +/***************************************************************************** + * Dock functions * + *****************************************************************************/ +/** + * is_dock - see if a device is a dock station + * @handle: acpi handle of the device + * + * If an acpi object has a _DCK method, then it is by definition a dock + * station, so return true. + */ +static int is_dock(acpi_handle handle) +{ + acpi_status status; + acpi_handle tmp; + + status = acpi_get_handle(handle, "_DCK", &tmp); + if (ACPI_FAILURE(status)) + return 0; + return 1; +} + +/** + * is_dock_device - see if a device is on a dock station + * @handle: acpi handle of the device + * + * If this device is either the dock station itself, + * or is a device dependent on the dock station, then it + * is a dock device + */ +int is_dock_device(acpi_handle handle) +{ + if (!dock_station) + return 0; + + if (is_dock(handle) || find_dock_dependent_device(dock_station, handle)) + return 1; + + return 0; +} + +EXPORT_SYMBOL_GPL(is_dock_device); + +/** + * dock_present - see if the dock station is present. + * @ds: the dock station + * + * execute the _STA method. note that present does not + * imply that we are docked. + */ +static int dock_present(struct dock_station *ds) +{ + unsigned long sta; + acpi_status status; + + if (ds) { + status = acpi_evaluate_integer(ds->handle, "_STA", NULL, &sta); + if (ACPI_SUCCESS(status) && sta) + return 1; + } + return 0; +} + + + +/** + * dock_create_acpi_device - add new devices to acpi + * @handle - handle of the device to add + * + * This function will create a new acpi_device for the given + * handle if one does not exist already. This should cause + * acpi to scan for drivers for the given devices, and call + * matching driver's add routine. + * + * Returns a pointer to the acpi_device corresponding to the handle. + */ +static struct acpi_device * dock_create_acpi_device(acpi_handle handle) +{ + struct acpi_device *device = NULL; + struct acpi_device *parent_device; + acpi_handle parent; + int ret; + + if (acpi_bus_get_device(handle, &device)) { + /* + * no device created for this object, + * so we should create one. + */ + acpi_get_parent(handle, &parent); + if (acpi_bus_get_device(parent, &parent_device)) + parent_device = NULL; + + ret = acpi_bus_add(&device, parent_device, handle, + ACPI_BUS_TYPE_DEVICE); + if (ret) { + pr_debug("error adding bus, %x\n", + -ret); + return NULL; + } + } + return device; +} + +/** + * dock_remove_acpi_device - remove the acpi_device struct from acpi + * @handle - the handle of the device to remove + * + * Tell acpi to remove the acpi_device. This should cause any loaded + * driver to have it's remove routine called. + */ +static void dock_remove_acpi_device(acpi_handle handle) +{ + struct acpi_device *device; + int ret; + + if (!acpi_bus_get_device(handle, &device)) { + ret = acpi_bus_trim(device, 1); + if (ret) + pr_debug("error removing bus, %x\n", -ret); + } +} + + +/** + * hotplug_dock_devices - insert or remove devices on the dock station + * @ds: the dock station + * @event: either bus check or eject request + * + * Some devices on the dock station need to have drivers called + * to perform hotplug operations after a dock event has occurred. + * Traverse the list of dock devices that have registered a + * hotplug handler, and call the handler. + */ +static void hotplug_dock_devices(struct dock_station *ds, u32 event) +{ + struct dock_dependent_device *dd; + + spin_lock(&ds->hp_lock); + + /* + * First call driver specific hotplug functions + */ + list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) { + if (dd->handler) + dd->handler(dd->handle, event, dd->context); + } + + /* + * Now make sure that an acpi_device is created for each + * dependent device, or removed if this is an eject request. + * This will cause acpi_drivers to be stopped/started if they + * exist + */ + list_for_each_entry(dd, &ds->dependent_devices, list) { + if (event == ACPI_NOTIFY_EJECT_REQUEST) + dock_remove_acpi_device(dd->handle); + else + dock_create_acpi_device(dd->handle); + } + spin_unlock(&ds->hp_lock); +} + +static void dock_event(struct dock_station *ds, u32 event, int num) +{ + /* + * we don't do events until someone tells me that + * they would like to have them. + */ +} + +/** + * eject_dock - respond to a dock eject request + * @ds: the dock station + * + * This is called after _DCK is called, to execute the dock station's + * _EJ0 method. + */ +static void eject_dock(struct dock_station *ds) +{ + struct acpi_object_list arg_list; + union acpi_object arg; + acpi_status status; + acpi_handle tmp; + + /* all dock devices should have _EJ0, but check anyway */ + status = acpi_get_handle(ds->handle, "_EJ0", &tmp); + if (ACPI_FAILURE(status)) { + pr_debug("No _EJ0 support for dock device\n"); + return; + } + + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = 1; + + if (ACPI_FAILURE(acpi_evaluate_object(ds->handle, "_EJ0", + &arg_list, NULL))) + pr_debug("Failed to evaluate _EJ0!\n"); +} + +/** + * handle_dock - handle a dock event + * @ds: the dock station + * @dock: to dock, or undock - that is the question + * + * Execute the _DCK method in response to an acpi event + */ +static void handle_dock(struct dock_station *ds, int dock) +{ + acpi_status status; + struct acpi_object_list arg_list; + union acpi_object arg; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + + acpi_get_name(ds->handle, ACPI_FULL_PATHNAME, &name_buffer); + obj = name_buffer.pointer; + + printk(KERN_INFO PREFIX "%s\n", dock ? "docking" : "undocking"); + + /* _DCK method has one argument */ + arg_list.count = 1; + arg_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = dock; + status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer); + if (ACPI_FAILURE(status)) + pr_debug("%s: failed to execute _DCK\n", obj->string.pointer); + kfree(buffer.pointer); + kfree(name_buffer.pointer); +} + +static inline void dock(struct dock_station *ds) +{ + handle_dock(ds, 1); +} + +static inline void undock(struct dock_station *ds) +{ + handle_dock(ds, 0); +} + +static inline void begin_dock(struct dock_station *ds) +{ + ds->flags |= DOCK_DOCKING; +} + +static inline void complete_dock(struct dock_station *ds) +{ + ds->flags &= ~(DOCK_DOCKING); + ds->last_dock_time = jiffies; +} + +/** + * dock_in_progress - see if we are in the middle of handling a dock event + * @ds: the dock station + * + * Sometimes while docking, false dock events can be sent to the driver + * because good connections aren't made or some other reason. Ignore these + * if we are in the middle of doing something. + */ +static int dock_in_progress(struct dock_station *ds) +{ + if ((ds->flags & DOCK_DOCKING) || + time_before(jiffies, (ds->last_dock_time + HZ))) + return 1; + return 0; +} + +/** + * register_dock_notifier - add yourself to the dock notifier list + * @nb: the callers notifier block + * + * If a driver wishes to be notified about dock events, they can + * use this function to put a notifier block on the dock notifier list. + * this notifier call chain will be called after a dock event, but + * before hotplugging any new devices. + */ +int register_dock_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&dock_notifier_list, nb); +} + +EXPORT_SYMBOL_GPL(register_dock_notifier); + +/** + * unregister_dock_notifier - remove yourself from the dock notifier list + * @nb: the callers notifier block + */ +void unregister_dock_notifier(struct notifier_block *nb) +{ + atomic_notifier_chain_unregister(&dock_notifier_list, nb); +} + +EXPORT_SYMBOL_GPL(unregister_dock_notifier); + +/** + * register_hotplug_dock_device - register a hotplug function + * @handle: the handle of the device + * @handler: the acpi_notifier_handler to call after docking + * @context: device specific data + * + * If a driver would like to perform a hotplug operation after a dock + * event, they can register an acpi_notifiy_handler to be called by + * the dock driver after _DCK is executed. + */ +int +register_hotplug_dock_device(acpi_handle handle, acpi_notify_handler handler, + void *context) +{ + struct dock_dependent_device *dd; + + if (!dock_station) + return -ENODEV; + + /* + * make sure this handle is for a device dependent on the dock, + * this would include the dock station itself + */ + dd = find_dock_dependent_device(dock_station, handle); + if (dd) { + dd->handler = handler; + dd->context = context; + dock_add_hotplug_device(dock_station, dd); + return 0; + } + + return -EINVAL; +} + +EXPORT_SYMBOL_GPL(register_hotplug_dock_device); + +/** + * unregister_hotplug_dock_device - remove yourself from the hotplug list + * @handle: the acpi handle of the device + */ +void unregister_hotplug_dock_device(acpi_handle handle) +{ + struct dock_dependent_device *dd; + + if (!dock_station) + return; + + dd = find_dock_dependent_device(dock_station, handle); + if (dd) + dock_del_hotplug_device(dock_station, dd); +} + +EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); + +/** + * dock_notify - act upon an acpi dock notification + * @handle: the dock station handle + * @event: the acpi event + * @data: our driver data struct + * + * If we are notified to dock, then check to see if the dock is + * present and then dock. Notify all drivers of the dock event, + * and then hotplug and devices that may need hotplugging. For undock + * check to make sure the dock device is still present, then undock + * and hotremove all the devices that may need removing. + */ +static void dock_notify(acpi_handle handle, u32 event, void *data) +{ + struct dock_station *ds = (struct dock_station *)data; + + switch (event) { + case ACPI_NOTIFY_BUS_CHECK: + if (!dock_in_progress(ds) && dock_present(ds)) { + begin_dock(ds); + dock(ds); + if (!dock_present(ds)) { + printk(KERN_ERR PREFIX "Unable to dock!\n"); + break; + } + atomic_notifier_call_chain(&dock_notifier_list, + event, NULL); + hotplug_dock_devices(ds, event); + complete_dock(ds); + dock_event(ds, event, DOCK_EVENT); + } + break; + case ACPI_NOTIFY_DEVICE_CHECK: + /* + * According to acpi spec 3.0a, if a DEVICE_CHECK notification + * is sent and _DCK is present, it is assumed to mean an + * undock request. This notify routine will only be called + * for objects defining _DCK, so we will fall through to eject + * request here. However, we will pass an eject request through + * to the driver who wish to hotplug. + */ + case ACPI_NOTIFY_EJECT_REQUEST: + if (!dock_in_progress(ds) && dock_present(ds)) { + /* + * here we need to generate the undock + * event prior to actually doing the undock + * so that the device struct still exists. + */ + dock_event(ds, event, UNDOCK_EVENT); + hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST); + undock(ds); + eject_dock(ds); + if (dock_present(ds)) + printk(KERN_ERR PREFIX "Unable to undock!\n"); + } + break; + default: + printk(KERN_ERR PREFIX "Unknown dock event %d\n", event); + } +} + +/** + * find_dock_devices - find devices on the dock station + * @handle: the handle of the device we are examining + * @lvl: unused + * @context: the dock station private data + * @rv: unused + * + * This function is called by acpi_walk_namespace. It will + * check to see if an object has an _EJD method. If it does, then it + * will see if it is dependent on the dock station. + */ +static acpi_status +find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + acpi_status status; + acpi_handle tmp; + struct dock_station *ds = (struct dock_station *)context; + struct dock_dependent_device *dd; + + status = acpi_bus_get_ejd(handle, &tmp); + if (ACPI_FAILURE(status)) + return AE_OK; + + if (tmp == ds->handle) { + dd = alloc_dock_dependent_device(handle); + if (dd) + add_dock_dependent_device(ds, dd); + } + + return AE_OK; +} + +/** + * dock_add - add a new dock station + * @handle: the dock station handle + * + * allocated and initialize a new dock station device. Find all devices + * that are on the dock station, and register for dock event notifications. + */ +static int dock_add(acpi_handle handle) +{ + int ret; + acpi_status status; + struct dock_dependent_device *dd; + + /* allocate & initialize the dock_station private data */ + dock_station = kzalloc(sizeof(*dock_station), GFP_KERNEL); + if (!dock_station) + return -ENOMEM; + dock_station->handle = handle; + dock_station->last_dock_time = jiffies - HZ; + INIT_LIST_HEAD(&dock_station->dependent_devices); + INIT_LIST_HEAD(&dock_station->hotplug_devices); + spin_lock_init(&dock_station->dd_lock); + spin_lock_init(&dock_station->hp_lock); + ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); + + /* Find dependent devices */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, find_dock_devices, dock_station, + NULL); + + /* add the dock station as a device dependent on itself */ + dd = alloc_dock_dependent_device(handle); + if (!dd) { + kfree(dock_station); + return -ENOMEM; + } + add_dock_dependent_device(dock_station, dd); + + /* register for dock events */ + status = acpi_install_notify_handler(dock_station->handle, + ACPI_SYSTEM_NOTIFY, + dock_notify, dock_station); + + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "Error installing notify handler\n"); + ret = -ENODEV; + goto dock_add_err; + } + + printk(KERN_INFO PREFIX "%s \n", ACPI_DOCK_DRIVER_NAME); + + return 0; + +dock_add_err: + kfree(dock_station); + kfree(dd); + return ret; +} + +/** + * dock_remove - free up resources related to the dock station + */ +static int dock_remove(void) +{ + struct dock_dependent_device *dd, *tmp; + acpi_status status; + + if (!dock_station) + return 0; + + /* remove dependent devices */ + list_for_each_entry_safe(dd, tmp, &dock_station->dependent_devices, + list) + kfree(dd); + + /* remove dock notify handler */ + status = acpi_remove_notify_handler(dock_station->handle, + ACPI_SYSTEM_NOTIFY, + dock_notify); + if (ACPI_FAILURE(status)) + printk(KERN_ERR "Error removing notify handler\n"); + + /* free dock station memory */ + kfree(dock_station); + return 0; +} + +/** + * find_dock - look for a dock station + * @handle: acpi handle of a device + * @lvl: unused + * @context: counter of dock stations found + * @rv: unused + * + * This is called by acpi_walk_namespace to look for dock stations. + */ +static acpi_status +find_dock(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + int *count = (int *)context; + acpi_status status = AE_OK; + + if (is_dock(handle)) { + if (dock_add(handle) >= 0) { + (*count)++; + status = AE_CTRL_TERMINATE; + } + } + return status; +} + +static int __init dock_init(void) +{ + int num = 0; + + dock_station = NULL; + + /* look for a dock station */ + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, find_dock, &num, NULL); + + if (!num) + return -ENODEV; + + return 0; +} + +static void __exit dock_exit(void) +{ + dock_remove(); +} + +postcore_initcall(dock_init); +module_exit(dock_exit); diff --git a/drivers/acpi/i2c_ec.c b/drivers/acpi/i2c_ec.c new file mode 100644 index 000000000..6809c283e --- /dev/null +++ b/drivers/acpi/i2c_ec.c @@ -0,0 +1,406 @@ +/* + * SMBus driver for ACPI Embedded Controller ($Revision: 1.3 $) + * + * Copyright (c) 2002, 2005 Ducrot Bruno + * Copyright (c) 2005 Rich Townsend (tiny hacks & tweaks) + * + * 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 version 2. + */ + +#include <linux/version.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/kernel.h> +#include <linux/stddef.h> +#include <linux/sched.h> +#include <linux/init.h> +#include <linux/i2c.h> +#include <linux/acpi.h> +#include <linux/delay.h> + +#include "i2c_ec.h" + +#define xudelay(t) udelay(t) +#define xmsleep(t) msleep(t) + +#define ACPI_EC_HC_COMPONENT 0x00080000 +#define ACPI_EC_HC_CLASS "ec_hc_smbus" +#define ACPI_EC_HC_HID "ACPI0001" +#define ACPI_EC_HC_DRIVER_NAME "ACPI EC HC smbus driver" +#define ACPI_EC_HC_DEVICE_NAME "EC HC smbus" + +#define _COMPONENT ACPI_EC_HC_COMPONENT + +ACPI_MODULE_NAME("acpi_smbus") + +static int acpi_ec_hc_add(struct acpi_device *device); +static int acpi_ec_hc_remove(struct acpi_device *device, int type); + +static struct acpi_driver acpi_ec_hc_driver = { + .name = ACPI_EC_HC_DRIVER_NAME, + .class = ACPI_EC_HC_CLASS, + .ids = ACPI_EC_HC_HID, + .ops = { + .add = acpi_ec_hc_add, + .remove = acpi_ec_hc_remove, + }, +}; + +/* Various bit mask for EC_SC (R) */ +#define OBF 0x01 +#define IBF 0x02 +#define CMD 0x08 +#define BURST 0x10 +#define SCI_EVT 0x20 +#define SMI_EVT 0x40 + +/* Commands for EC_SC (W) */ +#define RD_EC 0x80 +#define WR_EC 0x81 +#define BE_EC 0x82 +#define BD_EC 0x83 +#define QR_EC 0x84 + +/* + * ACPI 2.0 chapter 13 SMBus 2.0 EC register model + */ + +#define ACPI_EC_SMB_PRTCL 0x00 /* protocol, PEC */ +#define ACPI_EC_SMB_STS 0x01 /* status */ +#define ACPI_EC_SMB_ADDR 0x02 /* address */ +#define ACPI_EC_SMB_CMD 0x03 /* command */ +#define ACPI_EC_SMB_DATA 0x04 /* 32 data registers */ +#define ACPI_EC_SMB_BCNT 0x24 /* number of data bytes */ +#define ACPI_EC_SMB_ALRM_A 0x25 /* alarm address */ +#define ACPI_EC_SMB_ALRM_D 0x26 /* 2 bytes alarm data */ + +#define ACPI_EC_SMB_STS_DONE 0x80 +#define ACPI_EC_SMB_STS_ALRM 0x40 +#define ACPI_EC_SMB_STS_RES 0x20 +#define ACPI_EC_SMB_STS_STATUS 0x1f + +#define ACPI_EC_SMB_STATUS_OK 0x00 +#define ACPI_EC_SMB_STATUS_FAIL 0x07 +#define ACPI_EC_SMB_STATUS_DNAK 0x10 +#define ACPI_EC_SMB_STATUS_DERR 0x11 +#define ACPI_EC_SMB_STATUS_CMD_DENY 0x12 +#define ACPI_EC_SMB_STATUS_UNKNOWN 0x13 +#define ACPI_EC_SMB_STATUS_ACC_DENY 0x17 +#define ACPI_EC_SMB_STATUS_TIMEOUT 0x18 +#define ACPI_EC_SMB_STATUS_NOTSUP 0x19 +#define ACPI_EC_SMB_STATUS_BUSY 0x1A +#define ACPI_EC_SMB_STATUS_PEC 0x1F + +#define ACPI_EC_SMB_PRTCL_WRITE 0x00 +#define ACPI_EC_SMB_PRTCL_READ 0x01 +#define ACPI_EC_SMB_PRTCL_QUICK 0x02 +#define ACPI_EC_SMB_PRTCL_BYTE 0x04 +#define ACPI_EC_SMB_PRTCL_BYTE_DATA 0x06 +#define ACPI_EC_SMB_PRTCL_WORD_DATA 0x08 +#define ACPI_EC_SMB_PRTCL_BLOCK_DATA 0x0a +#define ACPI_EC_SMB_PRTCL_PROC_CALL 0x0c +#define ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL 0x0d +#define ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA 0x4a +#define ACPI_EC_SMB_PRTCL_PEC 0x80 + +/* Length of pre/post transaction sleep (msec) */ +#define ACPI_EC_SMB_TRANSACTION_SLEEP 1 +#define ACPI_EC_SMB_ACCESS_SLEEP1 1 +#define ACPI_EC_SMB_ACCESS_SLEEP2 10 + +static int acpi_ec_smb_read(struct acpi_ec_smbus *smbus, u8 address, u8 * data) +{ + u8 val; + int err; + + err = ec_read(smbus->base + address, &val); + if (!err) { + *data = val; + } + xmsleep(ACPI_EC_SMB_TRANSACTION_SLEEP); + return (err); +} + +static int acpi_ec_smb_write(struct acpi_ec_smbus *smbus, u8 address, u8 data) +{ + int err; + + err = ec_write(smbus->base + address, data); + return (err); +} + +static int +acpi_ec_smb_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, + char read_write, u8 command, int size, + union i2c_smbus_data *data) +{ + struct acpi_ec_smbus *smbus = adap->algo_data; + unsigned char protocol, len = 0, pec, temp[2] = { 0, 0 }; + int i; + + if (read_write == I2C_SMBUS_READ) { + protocol = ACPI_EC_SMB_PRTCL_READ; + } else { + protocol = ACPI_EC_SMB_PRTCL_WRITE; + } + pec = (flags & I2C_CLIENT_PEC) ? ACPI_EC_SMB_PRTCL_PEC : 0; + + switch (size) { + + case I2C_SMBUS_QUICK: + protocol |= ACPI_EC_SMB_PRTCL_QUICK; + read_write = I2C_SMBUS_WRITE; + break; + + case I2C_SMBUS_BYTE: + if (read_write == I2C_SMBUS_WRITE) { + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte); + } + protocol |= ACPI_EC_SMB_PRTCL_BYTE; + break; + + case I2C_SMBUS_BYTE_DATA: + acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); + if (read_write == I2C_SMBUS_WRITE) { + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->byte); + } + protocol |= ACPI_EC_SMB_PRTCL_BYTE_DATA; + break; + + case I2C_SMBUS_WORD_DATA: + acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); + if (read_write == I2C_SMBUS_WRITE) { + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word); + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1, + data->word >> 8); + } + protocol |= ACPI_EC_SMB_PRTCL_WORD_DATA | pec; + break; + + case I2C_SMBUS_BLOCK_DATA: + acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); + if (read_write == I2C_SMBUS_WRITE) { + len = min_t(u8, data->block[0], 32); + acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len); + for (i = 0; i < len; i++) + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i, + data->block[i + 1]); + } + protocol |= ACPI_EC_SMB_PRTCL_BLOCK_DATA | pec; + break; + + case I2C_SMBUS_I2C_BLOCK_DATA: + len = min_t(u8, data->block[0], 32); + acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); + acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len); + if (read_write == I2C_SMBUS_WRITE) { + for (i = 0; i < len; i++) { + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i, + data->block[i + 1]); + } + } + protocol |= ACPI_EC_SMB_PRTCL_I2C_BLOCK_DATA; + break; + + case I2C_SMBUS_PROC_CALL: + acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA, data->word); + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + 1, data->word >> 8); + protocol = ACPI_EC_SMB_PRTCL_PROC_CALL | pec; + read_write = I2C_SMBUS_READ; + break; + + case I2C_SMBUS_BLOCK_PROC_CALL: + protocol |= pec; + len = min_t(u8, data->block[0], 31); + acpi_ec_smb_write(smbus, ACPI_EC_SMB_CMD, command); + acpi_ec_smb_write(smbus, ACPI_EC_SMB_BCNT, len); + for (i = 0; i < len; i++) + acpi_ec_smb_write(smbus, ACPI_EC_SMB_DATA + i, + data->block[i + 1]); + protocol = ACPI_EC_SMB_PRTCL_BLOCK_PROC_CALL | pec; + read_write = I2C_SMBUS_READ; + break; + + default: + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "EC SMBus adapter: " + "Unsupported transaction %d\n", size)); + return (-1); + } + + acpi_ec_smb_write(smbus, ACPI_EC_SMB_ADDR, addr << 1); + acpi_ec_smb_write(smbus, ACPI_EC_SMB_PRTCL, protocol); + + acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0); + + if (~temp[0] & ACPI_EC_SMB_STS_DONE) { + xudelay(500); + acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0); + } + if (~temp[0] & ACPI_EC_SMB_STS_DONE) { + xmsleep(ACPI_EC_SMB_ACCESS_SLEEP2); + acpi_ec_smb_read(smbus, ACPI_EC_SMB_STS, temp + 0); + } + if ((~temp[0] & ACPI_EC_SMB_STS_DONE) + || (temp[0] & ACPI_EC_SMB_STS_STATUS)) { + return (-1); + } + + if (read_write == I2C_SMBUS_WRITE) { + return (0); + } + + switch (size) { + + case I2C_SMBUS_BYTE: + case I2C_SMBUS_BYTE_DATA: + acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, &data->byte); + break; + + case I2C_SMBUS_WORD_DATA: + case I2C_SMBUS_PROC_CALL: + acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA, temp + 0); + acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + 1, temp + 1); + data->word = (temp[1] << 8) | temp[0]; + break; + + case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_BLOCK_PROC_CALL: + len = 0; + acpi_ec_smb_read(smbus, ACPI_EC_SMB_BCNT, &len); + len = min_t(u8, len, 32); + case I2C_SMBUS_I2C_BLOCK_DATA: + for (i = 0; i < len; i++) + acpi_ec_smb_read(smbus, ACPI_EC_SMB_DATA + i, + data->block + i + 1); + data->block[0] = len; + break; + } + + return (0); +} + +static u32 acpi_ec_smb_func(struct i2c_adapter *adapter) +{ + + return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA | + I2C_FUNC_SMBUS_PROC_CALL | + I2C_FUNC_SMBUS_BLOCK_PROC_CALL | + I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC); +} + +static struct i2c_algorithm acpi_ec_smbus_algorithm = { + .smbus_xfer = acpi_ec_smb_access, + .functionality = acpi_ec_smb_func, +}; + +static int acpi_ec_hc_add(struct acpi_device *device) +{ + int status; + unsigned long val; + struct acpi_ec_hc *ec_hc; + struct acpi_ec_smbus *smbus; + + if (!device) { + return -EINVAL; + } + + ec_hc = kmalloc(sizeof(struct acpi_ec_hc), GFP_KERNEL); + if (!ec_hc) { + return -ENOMEM; + } + memset(ec_hc, 0, sizeof(struct acpi_ec_hc)); + + smbus = kmalloc(sizeof(struct acpi_ec_smbus), GFP_KERNEL); + if (!smbus) { + kfree(ec_hc); + return -ENOMEM; + } + memset(smbus, 0, sizeof(struct acpi_ec_smbus)); + + ec_hc->handle = device->handle; + strcpy(acpi_device_name(device), ACPI_EC_HC_DEVICE_NAME); + strcpy(acpi_device_class(device), ACPI_EC_HC_CLASS); + acpi_driver_data(device) = ec_hc; + + status = acpi_evaluate_integer(ec_hc->handle, "_EC", NULL, &val); + if (ACPI_FAILURE(status)) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Error obtaining _EC\n")); + kfree(ec_hc); + kfree(smbus); + return -EIO; + } + + smbus->ec = acpi_driver_data(device->parent); + smbus->base = (val & 0xff00ull) >> 8; + smbus->alert = val & 0xffull; + + smbus->adapter.owner = THIS_MODULE; + smbus->adapter.algo = &acpi_ec_smbus_algorithm; + smbus->adapter.algo_data = smbus; + + if (i2c_add_adapter(&smbus->adapter)) { + ACPI_DEBUG_PRINT((ACPI_DB_WARN, + "EC SMBus adapter: Failed to register adapter\n")); + kfree(smbus); + kfree(ec_hc); + return -EIO; + } + + ec_hc->smbus = smbus; + + printk(KERN_INFO PREFIX "%s [%s]\n", + acpi_device_name(device), acpi_device_bid(device)); + + return AE_OK; +} + +static int acpi_ec_hc_remove(struct acpi_device *device, int type) +{ + struct acpi_ec_hc *ec_hc; + + if (!device) { + return -EINVAL; + } + ec_hc = acpi_driver_data(device); + + i2c_del_adapter(&ec_hc->smbus->adapter); + kfree(ec_hc->smbus); + kfree(ec_hc); + + return AE_OK; +} + +static int __init acpi_ec_hc_init(void) +{ + int result; + + result = acpi_bus_register_driver(&acpi_ec_hc_driver); + if (result < 0) { + return -ENODEV; + } + return 0; +} + +static void __exit acpi_ec_hc_exit(void) +{ + acpi_bus_unregister_driver(&acpi_ec_hc_driver); +} + +struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device) +{ + return ((struct acpi_ec_hc *)acpi_driver_data(device->parent)); +} + +EXPORT_SYMBOL(acpi_get_ec_hc); + +module_init(acpi_ec_hc_init); +module_exit(acpi_ec_hc_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Ducrot Bruno"); +MODULE_DESCRIPTION("ACPI EC SMBus driver"); diff --git a/drivers/acpi/i2c_ec.h b/drivers/acpi/i2c_ec.h new file mode 100644 index 000000000..7c53fb732 --- /dev/null +++ b/drivers/acpi/i2c_ec.h @@ -0,0 +1,23 @@ +/* + * SMBus driver for ACPI Embedded Controller ($Revision: 1.2 $) + * + * Copyright (c) 2002, 2005 Ducrot Bruno + * + * 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 version 2. + */ + +struct acpi_ec_smbus { + struct i2c_adapter adapter; + union acpi_ec *ec; + int base; + int alert; +}; + +struct acpi_ec_hc { + acpi_handle handle; + struct acpi_ec_smbus *smbus; +}; + +struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device); diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c new file mode 100644 index 000000000..62bef0b3b --- /dev/null +++ b/drivers/acpi/sbs.c @@ -0,0 +1,1769 @@ +/* + * acpi_sbs.c - ACPI Smart Battery System Driver ($Revision: 1.16 $) + * + * Copyright (c) 2005 Rich Townsend <rhdt@bartol.udel.edu> + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kernel.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#include <asm/uaccess.h> +#include <linux/acpi.h> +#include <linux/i2c.h> +#include <linux/delay.h> + +#include "i2c_ec.h" + +#define DEF_CAPACITY_UNIT 3 +#define MAH_CAPACITY_UNIT 1 +#define MWH_CAPACITY_UNIT 2 +#define CAPACITY_UNIT DEF_CAPACITY_UNIT + +#define REQUEST_UPDATE_MODE 1 +#define QUEUE_UPDATE_MODE 2 + +#define DATA_TYPE_COMMON 0 +#define DATA_TYPE_INFO 1 +#define DATA_TYPE_STATE 2 +#define DATA_TYPE_ALARM 3 +#define DATA_TYPE_AC_STATE 4 + +extern struct proc_dir_entry *acpi_lock_ac_dir(void); +extern struct proc_dir_entry *acpi_lock_battery_dir(void); +extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); +extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); + +#define ACPI_SBS_COMPONENT 0x00080000 +#define ACPI_SBS_CLASS "sbs" +#define ACPI_AC_CLASS "ac_adapter" +#define ACPI_BATTERY_CLASS "battery" +#define ACPI_SBS_HID "ACPI0002" +#define ACPI_SBS_DRIVER_NAME "ACPI Smart Battery System Driver" +#define ACPI_SBS_DEVICE_NAME "Smart Battery System" +#define ACPI_SBS_FILE_INFO "info" +#define ACPI_SBS_FILE_STATE "state" +#define ACPI_SBS_FILE_ALARM "alarm" +#define ACPI_BATTERY_DIR_NAME "BAT%i" +#define ACPI_AC_DIR_NAME "AC0" +#define ACPI_SBC_SMBUS_ADDR 0x9 +#define ACPI_SBSM_SMBUS_ADDR 0xa +#define ACPI_SB_SMBUS_ADDR 0xb +#define ACPI_SBS_AC_NOTIFY_STATUS 0x80 +#define ACPI_SBS_BATTERY_NOTIFY_STATUS 0x80 +#define ACPI_SBS_BATTERY_NOTIFY_INFO 0x81 + +#define _COMPONENT ACPI_SBS_COMPONENT + +#define MAX_SBS_BAT 4 +#define MAX_SMBUS_ERR 1 + +ACPI_MODULE_NAME("acpi_sbs"); + +MODULE_AUTHOR("Rich Townsend"); +MODULE_DESCRIPTION("Smart Battery System ACPI interface driver"); +MODULE_LICENSE("GPL"); + +static struct semaphore sbs_sem; + +#define UPDATE_MODE QUEUE_UPDATE_MODE +/* REQUEST_UPDATE_MODE QUEUE_UPDATE_MODE */ +#define UPDATE_INFO_MODE 0 +#define UPDATE_TIME 60 +#define UPDATE_TIME2 0 + +static int capacity_mode = CAPACITY_UNIT; +static int update_mode = UPDATE_MODE; +static int update_info_mode = UPDATE_INFO_MODE; +static int update_time = UPDATE_TIME; +static int update_time2 = UPDATE_TIME2; + +module_param(capacity_mode, int, CAPACITY_UNIT); +module_param(update_mode, int, UPDATE_MODE); +module_param(update_info_mode, int, UPDATE_INFO_MODE); +module_param(update_time, int, UPDATE_TIME); +module_param(update_time2, int, UPDATE_TIME2); + +static int acpi_sbs_add(struct acpi_device *device); +static int acpi_sbs_remove(struct acpi_device *device, int type); +static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus); +static void acpi_sbs_update_queue(void *data); + +static struct acpi_driver acpi_sbs_driver = { + .name = ACPI_SBS_DRIVER_NAME, + .class = ACPI_SBS_CLASS, + .ids = ACPI_SBS_HID, + .ops = { + .add = acpi_sbs_add, + .remove = acpi_sbs_remove, + }, +}; + +struct acpi_battery_info { + int capacity_mode; + s16 full_charge_capacity; + s16 design_capacity; + s16 design_voltage; + int vscale; + int ipscale; + s16 serial_number; + char manufacturer_name[I2C_SMBUS_BLOCK_MAX + 3]; + char device_name[I2C_SMBUS_BLOCK_MAX + 3]; + char device_chemistry[I2C_SMBUS_BLOCK_MAX + 3]; +}; + +struct acpi_battery_state { + s16 voltage; + s16 amperage; + s16 remaining_capacity; + s16 average_time_to_empty; + s16 average_time_to_full; + s16 battery_status; +}; + +struct acpi_battery_alarm { + s16 remaining_capacity; +}; + +struct acpi_battery { + int alive; + int battery_present; + int id; + int init_state; + struct acpi_sbs *sbs; + struct acpi_battery_info info; + struct acpi_battery_state state; + struct acpi_battery_alarm alarm; + struct proc_dir_entry *battery_entry; +}; + +struct acpi_sbs { + acpi_handle handle; + struct acpi_device *device; + struct acpi_ec_smbus *smbus; + int sbsm_present; + int sbsm_batteries_supported; + int ac_present; + struct proc_dir_entry *ac_entry; + struct acpi_battery battery[MAX_SBS_BAT]; + int update_info_mode; + int zombie; + int update_time; + int update_time2; + struct timer_list update_timer; +}; + +static void acpi_update_delay(struct acpi_sbs *sbs); +static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type); + +/* -------------------------------------------------------------------------- + SMBus Communication + -------------------------------------------------------------------------- */ + +static void acpi_battery_smbus_err_handler(struct acpi_ec_smbus *smbus) +{ + union i2c_smbus_data data; + int result = 0; + char *err_str; + int err_number; + + data.word = 0; + + result = smbus->adapter.algo-> + smbus_xfer(&smbus->adapter, + ACPI_SB_SMBUS_ADDR, + 0, I2C_SMBUS_READ, 0x16, I2C_SMBUS_BLOCK_DATA, &data); + + err_number = (data.word & 0x000f); + + switch (data.word & 0x000f) { + case 0x0000: + err_str = "unexpected bus error"; + break; + case 0x0001: + err_str = "busy"; + break; + case 0x0002: + err_str = "reserved command"; + break; + case 0x0003: + err_str = "unsupported command"; + break; + case 0x0004: + err_str = "access denied"; + break; + case 0x0005: + err_str = "overflow/underflow"; + break; + case 0x0006: + err_str = "bad size"; + break; + case 0x0007: + err_str = "unknown error"; + break; + default: + err_str = "unrecognized error"; + } + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "%s: ret %i, err %i\n", err_str, result, err_number)); +} + +static int +acpi_sbs_smbus_read_word(struct acpi_ec_smbus *smbus, int addr, int func, + u16 * word, + void (*err_handler) (struct acpi_ec_smbus * smbus)) +{ + union i2c_smbus_data data; + int result = 0; + int i; + + if (err_handler == NULL) { + err_handler = acpi_battery_smbus_err_handler; + } + + for (i = 0; i < MAX_SMBUS_ERR; i++) { + result = + smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0, + I2C_SMBUS_READ, func, + I2C_SMBUS_WORD_DATA, &data); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "try %i: smbus->adapter.algo->smbus_xfer() failed\n", + i)); + if (err_handler) { + err_handler(smbus); + } + } else { + *word = data.word; + break; + } + } + + return result; +} + +static int +acpi_sbs_smbus_read_str(struct acpi_ec_smbus *smbus, int addr, int func, + char *str, + void (*err_handler) (struct acpi_ec_smbus * smbus)) +{ + union i2c_smbus_data data; + int result = 0; + int i; + + if (err_handler == NULL) { + err_handler = acpi_battery_smbus_err_handler; + } + + for (i = 0; i < MAX_SMBUS_ERR; i++) { + result = + smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0, + I2C_SMBUS_READ, func, + I2C_SMBUS_BLOCK_DATA, + &data); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "try %i: smbus->adapter.algo->smbus_xfer() failed\n", + i)); + if (err_handler) { + err_handler(smbus); + } + } else { + strncpy(str, (const char *)data.block + 1, + data.block[0]); + str[data.block[0]] = 0; + break; + } + } + + return result; +} + +static int +acpi_sbs_smbus_write_word(struct acpi_ec_smbus *smbus, int addr, int func, + int word, + void (*err_handler) (struct acpi_ec_smbus * smbus)) +{ + union i2c_smbus_data data; + int result = 0; + int i; + + if (err_handler == NULL) { + err_handler = acpi_battery_smbus_err_handler; + } + + data.word = word; + + for (i = 0; i < MAX_SMBUS_ERR; i++) { + result = + smbus->adapter.algo->smbus_xfer(&smbus->adapter, addr, 0, + I2C_SMBUS_WRITE, func, + I2C_SMBUS_WORD_DATA, &data); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "try %i: smbus->adapter.algo" + "->smbus_xfer() failed\n", i)); + if (err_handler) { + err_handler(smbus); + } + } else { + break; + } + } + + return result; +} + +/* -------------------------------------------------------------------------- + Smart Battery System Management + -------------------------------------------------------------------------- */ + +/* Smart Battery */ + +static int acpi_sbs_generate_event(struct acpi_device *device, + int event, int state, char *bid, char *class) +{ + char bid_saved[5]; + char class_saved[20]; + int result = 0; + + strcpy(bid_saved, acpi_device_bid(device)); + strcpy(class_saved, acpi_device_class(device)); + + strcpy(acpi_device_bid(device), bid); + strcpy(acpi_device_class(device), class); + + result = acpi_bus_generate_event(device, event, state); + + strcpy(acpi_device_bid(device), bid_saved); + strcpy(acpi_device_class(device), class_saved); + + return result; +} + +static int acpi_battery_get_present(struct acpi_battery *battery) +{ + s16 state; + int result = 0; + int is_present = 0; + + result = acpi_sbs_smbus_read_word(battery->sbs->smbus, + ACPI_SBSM_SMBUS_ADDR, 0x01, + &state, NULL); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed")); + } + if (!result) { + is_present = (state & 0x000f) & (1 << battery->id); + } + battery->battery_present = is_present; + + return result; +} + +static int acpi_battery_is_present(struct acpi_battery *battery) +{ + return (battery->battery_present); +} + +static int acpi_ac_is_present(struct acpi_sbs *sbs) +{ + return (sbs->ac_present); +} + +static int acpi_battery_select(struct acpi_battery *battery) +{ + struct acpi_ec_smbus *smbus = battery->sbs->smbus; + int result = 0; + s16 state; + int foo; + + if (battery->sbs->sbsm_present) { + + /* Take special care not to knobble other nibbles of + * state (aka selector_state), since + * it causes charging to halt on SBSELs */ + + result = + acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01, + &state, NULL); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed\n")); + goto end; + } + + foo = (state & 0x0fff) | (1 << (battery->id + 12)); + result = + acpi_sbs_smbus_write_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x01, + foo, NULL); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_write_word() failed\n")); + goto end; + } + } + + end: + return result; +} + +static int acpi_sbsm_get_info(struct acpi_sbs *sbs) +{ + struct acpi_ec_smbus *smbus = sbs->smbus; + int result = 0; + s16 battery_system_info; + + result = acpi_sbs_smbus_read_word(smbus, ACPI_SBSM_SMBUS_ADDR, 0x04, + &battery_system_info, NULL); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed\n")); + goto end; + } + + sbs->sbsm_batteries_supported = battery_system_info & 0x000f; + + end: + + return result; +} + +static int acpi_battery_get_info(struct acpi_battery *battery) +{ + struct acpi_ec_smbus *smbus = battery->sbs->smbus; + int result = 0; + s16 battery_mode; + s16 specification_info; + + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03, + &battery_mode, + &acpi_battery_smbus_err_handler); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed\n")); + goto end; + } + battery->info.capacity_mode = (battery_mode & 0x8000) >> 15; + + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x10, + &battery->info.full_charge_capacity, + &acpi_battery_smbus_err_handler); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed\n")); + goto end; + } + + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x18, + &battery->info.design_capacity, + &acpi_battery_smbus_err_handler); + + if (result) { + goto end; + } + + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x19, + &battery->info.design_voltage, + &acpi_battery_smbus_err_handler); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed\n")); + goto end; + } + + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1a, + &specification_info, + &acpi_battery_smbus_err_handler); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed\n")); + goto end; + } + + switch ((specification_info & 0x0f00) >> 8) { + case 1: + battery->info.vscale = 10; + break; + case 2: + battery->info.vscale = 100; + break; + case 3: + battery->info.vscale = 1000; + break; + default: + battery->info.vscale = 1; + } + + switch ((specification_info & 0xf000) >> 12) { + case 1: + battery->info.ipscale = 10; + break; + case 2: + battery->info.ipscale = 100; + break; + case 3: + battery->info.ipscale = 1000; + break; + default: + battery->info.ipscale = 1; + } + + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x1c, + &battery->info.serial_number, + &acpi_battery_smbus_err_handler); + if (result) { + goto end; + } + + result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x20, + battery->info.manufacturer_name, + &acpi_battery_smbus_err_handler); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_str() failed\n")); + goto end; + } + + result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x21, + battery->info.device_name, + &acpi_battery_smbus_err_handler); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_str() failed\n")); + goto end; + } + + result = acpi_sbs_smbus_read_str(smbus, ACPI_SB_SMBUS_ADDR, 0x22, + battery->info.device_chemistry, + &acpi_battery_smbus_err_handler); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_str() failed\n")); + goto end; + } + + end: + return result; +} + +static void acpi_update_delay(struct acpi_sbs *sbs) +{ + if (sbs->zombie) { + return; + } + if (sbs->update_time2 > 0) { + msleep(sbs->update_time2 * 1000); + } +} + +static int acpi_battery_get_state(struct acpi_battery *battery) +{ + struct acpi_ec_smbus *smbus = battery->sbs->smbus; + int result = 0; + + acpi_update_delay(battery->sbs); + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x09, + &battery->state.voltage, + &acpi_battery_smbus_err_handler); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed\n")); + goto end; + } + + acpi_update_delay(battery->sbs); + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0a, + &battery->state.amperage, + &acpi_battery_smbus_err_handler); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed\n")); + goto end; + } + + acpi_update_delay(battery->sbs); + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x0f, + &battery->state.remaining_capacity, + &acpi_battery_smbus_err_handler); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed\n")); + goto end; + } + + acpi_update_delay(battery->sbs); + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x12, + &battery->state.average_time_to_empty, + &acpi_battery_smbus_err_handler); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed\n")); + goto end; + } + + acpi_update_delay(battery->sbs); + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x13, + &battery->state.average_time_to_full, + &acpi_battery_smbus_err_handler); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed\n")); + goto end; + } + + acpi_update_delay(battery->sbs); + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x16, + &battery->state.battery_status, + &acpi_battery_smbus_err_handler); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed\n")); + goto end; + } + + acpi_update_delay(battery->sbs); + + end: + return result; +} + +static int acpi_battery_get_alarm(struct acpi_battery *battery) +{ + struct acpi_ec_smbus *smbus = battery->sbs->smbus; + int result = 0; + + result = acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01, + &battery->alarm.remaining_capacity, + &acpi_battery_smbus_err_handler); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed\n")); + goto end; + } + + acpi_update_delay(battery->sbs); + + end: + + return result; +} + +static int acpi_battery_set_alarm(struct acpi_battery *battery, + unsigned long alarm) +{ + struct acpi_ec_smbus *smbus = battery->sbs->smbus; + int result = 0; + s16 battery_mode; + int foo; + + result = acpi_battery_select(battery); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_select() failed\n")); + goto end; + } + + /* If necessary, enable the alarm */ + + if (alarm > 0) { + result = + acpi_sbs_smbus_read_word(smbus, ACPI_SB_SMBUS_ADDR, 0x03, + &battery_mode, + &acpi_battery_smbus_err_handler); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed\n")); + goto end; + } + + result = + acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01, + battery_mode & 0xbfff, + &acpi_battery_smbus_err_handler); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_write_word() failed\n")); + goto end; + } + } + + foo = alarm / (battery->info.capacity_mode ? 10 : 1); + result = acpi_sbs_smbus_write_word(smbus, ACPI_SB_SMBUS_ADDR, 0x01, + foo, + &acpi_battery_smbus_err_handler); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_write_word() failed\n")); + goto end; + } + + end: + + return result; +} + +static int acpi_battery_set_mode(struct acpi_battery *battery) +{ + int result = 0; + s16 battery_mode; + + if (capacity_mode == DEF_CAPACITY_UNIT) { + goto end; + } + + result = acpi_sbs_smbus_read_word(battery->sbs->smbus, + ACPI_SB_SMBUS_ADDR, 0x03, + &battery_mode, NULL); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed\n")); + goto end; + } + + if (capacity_mode == MAH_CAPACITY_UNIT) { + battery_mode &= 0x7fff; + } else { + battery_mode |= 0x8000; + } + result = acpi_sbs_smbus_write_word(battery->sbs->smbus, + ACPI_SB_SMBUS_ADDR, 0x03, + battery_mode, NULL); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_write_word() failed\n")); + goto end; + } + + result = acpi_sbs_smbus_read_word(battery->sbs->smbus, + ACPI_SB_SMBUS_ADDR, 0x03, + &battery_mode, NULL); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed\n")); + goto end; + } + + end: + return result; +} + +static int acpi_battery_init(struct acpi_battery *battery) +{ + int result = 0; + + result = acpi_battery_select(battery); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_init() failed\n")); + goto end; + } + + result = acpi_battery_set_mode(battery); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_set_mode() failed\n")); + goto end; + } + + result = acpi_battery_get_info(battery); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_get_info() failed\n")); + goto end; + } + + result = acpi_battery_get_state(battery); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_get_state() failed\n")); + goto end; + } + + result = acpi_battery_get_alarm(battery); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_get_alarm() failed\n")); + goto end; + } + + end: + return result; +} + +static int acpi_ac_get_present(struct acpi_sbs *sbs) +{ + struct acpi_ec_smbus *smbus = sbs->smbus; + int result = 0; + s16 charger_status; + + result = acpi_sbs_smbus_read_word(smbus, ACPI_SBC_SMBUS_ADDR, 0x13, + &charger_status, NULL); + + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_smbus_read_word() failed\n")); + goto end; + } + + sbs->ac_present = (charger_status & 0x8000) >> 15; + + end: + + return result; +} + +/* -------------------------------------------------------------------------- + FS Interface (/proc/acpi) + -------------------------------------------------------------------------- */ + +/* Generic Routines */ + +static int +acpi_sbs_generic_add_fs(struct proc_dir_entry **dir, + struct proc_dir_entry *parent_dir, + char *dir_name, + struct file_operations *info_fops, + struct file_operations *state_fops, + struct file_operations *alarm_fops, void *data) +{ + struct proc_dir_entry *entry = NULL; + + if (!*dir) { + *dir = proc_mkdir(dir_name, parent_dir); + if (!*dir) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "proc_mkdir() failed\n")); + return -ENODEV; + } + (*dir)->owner = THIS_MODULE; + } + + /* 'info' [R] */ + if (info_fops) { + entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir); + if (!entry) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "create_proc_entry() failed\n")); + } else { + entry->proc_fops = info_fops; + entry->data = data; + entry->owner = THIS_MODULE; + } + } + + /* 'state' [R] */ + if (state_fops) { + entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir); + if (!entry) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "create_proc_entry() failed\n")); + } else { + entry->proc_fops = state_fops; + entry->data = data; + entry->owner = THIS_MODULE; + } + } + + /* 'alarm' [R/W] */ + if (alarm_fops) { + entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir); + if (!entry) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "create_proc_entry() failed\n")); + } else { + entry->proc_fops = alarm_fops; + entry->data = data; + entry->owner = THIS_MODULE; + } + } + + return 0; +} + +static void +acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir, + struct proc_dir_entry *parent_dir) +{ + + if (*dir) { + remove_proc_entry(ACPI_SBS_FILE_INFO, *dir); + remove_proc_entry(ACPI_SBS_FILE_STATE, *dir); + remove_proc_entry(ACPI_SBS_FILE_ALARM, *dir); + remove_proc_entry((*dir)->name, parent_dir); + *dir = NULL; + } + +} + +/* Smart Battery Interface */ + +static struct proc_dir_entry *acpi_battery_dir = NULL; + +static int acpi_battery_read_info(struct seq_file *seq, void *offset) +{ + struct acpi_battery *battery = (struct acpi_battery *)seq->private; + int cscale; + int result = 0; + + if (battery->sbs->zombie) { + return -ENODEV; + } + + down(&sbs_sem); + + if (update_mode == REQUEST_UPDATE_MODE) { + result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_INFO); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_update_run() failed\n")); + } + } + + if (acpi_battery_is_present(battery)) { + seq_printf(seq, "present: yes\n"); + } else { + seq_printf(seq, "present: no\n"); + goto end; + } + + if (battery->info.capacity_mode) { + cscale = battery->info.vscale * battery->info.ipscale; + } else { + cscale = battery->info.ipscale; + } + seq_printf(seq, "design capacity: %i%s", + battery->info.design_capacity * cscale, + battery->info.capacity_mode ? "0 mWh\n" : " mAh\n"); + + seq_printf(seq, "last full capacity: %i%s", + battery->info.full_charge_capacity * cscale, + battery->info.capacity_mode ? "0 mWh\n" : " mAh\n"); + + seq_printf(seq, "battery technology: rechargeable\n"); + + seq_printf(seq, "design voltage: %i mV\n", + battery->info.design_voltage * battery->info.vscale); + + seq_printf(seq, "design capacity warning: unknown\n"); + seq_printf(seq, "design capacity low: unknown\n"); + seq_printf(seq, "capacity granularity 1: unknown\n"); + seq_printf(seq, "capacity granularity 2: unknown\n"); + + seq_printf(seq, "model number: %s\n", + battery->info.device_name); + + seq_printf(seq, "serial number: %i\n", + battery->info.serial_number); + + seq_printf(seq, "battery type: %s\n", + battery->info.device_chemistry); + + seq_printf(seq, "OEM info: %s\n", + battery->info.manufacturer_name); + + end: + + up(&sbs_sem); + + return result; +} + +static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_battery_read_info, PDE(inode)->data); +} + +static int acpi_battery_read_state(struct seq_file *seq, void *offset) +{ + struct acpi_battery *battery = (struct acpi_battery *)seq->private; + int result = 0; + int cscale; + int foo; + + if (battery->sbs->zombie) { + return -ENODEV; + } + + down(&sbs_sem); + + if (update_mode == REQUEST_UPDATE_MODE) { + result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_STATE); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_update_run() failed\n")); + } + } + + if (acpi_battery_is_present(battery)) { + seq_printf(seq, "present: yes\n"); + } else { + seq_printf(seq, "present: no\n"); + goto end; + } + + if (battery->info.capacity_mode) { + cscale = battery->info.vscale * battery->info.ipscale; + } else { + cscale = battery->info.ipscale; + } + + if (battery->state.battery_status & 0x0010) { + seq_printf(seq, "capacity state: critical\n"); + } else { + seq_printf(seq, "capacity state: ok\n"); + } + if (battery->state.amperage < 0) { + seq_printf(seq, "charging state: discharging\n"); + foo = battery->state.remaining_capacity * cscale * 60 / + (battery->state.average_time_to_empty == 0 ? 1 : + battery->state.average_time_to_empty); + seq_printf(seq, "present rate: %i%s\n", + foo, battery->info.capacity_mode ? "0 mW" : " mA"); + } else if (battery->state.amperage > 0) { + seq_printf(seq, "charging state: charging\n"); + foo = (battery->info.full_charge_capacity - + battery->state.remaining_capacity) * cscale * 60 / + (battery->state.average_time_to_full == 0 ? 1 : + battery->state.average_time_to_full); + seq_printf(seq, "present rate: %i%s\n", + foo, battery->info.capacity_mode ? "0 mW" : " mA"); + } else { + seq_printf(seq, "charging state: charged\n"); + seq_printf(seq, "present rate: 0 %s\n", + battery->info.capacity_mode ? "mW" : "mA"); + } + + seq_printf(seq, "remaining capacity: %i%s", + battery->state.remaining_capacity * cscale, + battery->info.capacity_mode ? "0 mWh\n" : " mAh\n"); + + seq_printf(seq, "present voltage: %i mV\n", + battery->state.voltage * battery->info.vscale); + + end: + + up(&sbs_sem); + + return result; +} + +static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_battery_read_state, PDE(inode)->data); +} + +static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) +{ + struct acpi_battery *battery = (struct acpi_battery *)seq->private; + int result = 0; + int cscale; + + if (battery->sbs->zombie) { + return -ENODEV; + } + + down(&sbs_sem); + + if (update_mode == REQUEST_UPDATE_MODE) { + result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_ALARM); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_update_run() failed\n")); + } + } + + if (!acpi_battery_is_present(battery)) { + seq_printf(seq, "present: no\n"); + goto end; + } + + if (battery->info.capacity_mode) { + cscale = battery->info.vscale * battery->info.ipscale; + } else { + cscale = battery->info.ipscale; + } + + seq_printf(seq, "alarm: "); + if (battery->alarm.remaining_capacity) { + seq_printf(seq, "%i%s", + battery->alarm.remaining_capacity * cscale, + battery->info.capacity_mode ? "0 mWh\n" : " mAh\n"); + } else { + seq_printf(seq, "disabled\n"); + } + + end: + + up(&sbs_sem); + + return result; +} + +static ssize_t +acpi_battery_write_alarm(struct file *file, const char __user * buffer, + size_t count, loff_t * ppos) +{ + struct seq_file *seq = (struct seq_file *)file->private_data; + struct acpi_battery *battery = (struct acpi_battery *)seq->private; + char alarm_string[12] = { '\0' }; + int result, old_alarm, new_alarm; + + if (battery->sbs->zombie) { + return -ENODEV; + } + + down(&sbs_sem); + + if (!acpi_battery_is_present(battery)) { + result = -ENODEV; + goto end; + } + + if (count > sizeof(alarm_string) - 1) { + result = -EINVAL; + goto end; + } + + if (copy_from_user(alarm_string, buffer, count)) { + result = -EFAULT; + goto end; + } + + alarm_string[count] = 0; + + old_alarm = battery->alarm.remaining_capacity; + new_alarm = simple_strtoul(alarm_string, NULL, 0); + + result = acpi_battery_set_alarm(battery, new_alarm); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_set_alarm() failed\n")); + (void)acpi_battery_set_alarm(battery, old_alarm); + goto end; + } + result = acpi_battery_get_alarm(battery); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_get_alarm() failed\n")); + (void)acpi_battery_set_alarm(battery, old_alarm); + goto end; + } + + end: + up(&sbs_sem); + + if (result) { + return result; + } else { + return count; + } +} + +static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_battery_read_alarm, PDE(inode)->data); +} + +static struct file_operations acpi_battery_info_fops = { + .open = acpi_battery_info_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static struct file_operations acpi_battery_state_fops = { + .open = acpi_battery_state_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static struct file_operations acpi_battery_alarm_fops = { + .open = acpi_battery_alarm_open_fs, + .read = seq_read, + .write = acpi_battery_write_alarm, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +/* Legacy AC Adapter Interface */ + +static struct proc_dir_entry *acpi_ac_dir = NULL; + +static int acpi_ac_read_state(struct seq_file *seq, void *offset) +{ + struct acpi_sbs *sbs = (struct acpi_sbs *)seq->private; + int result; + + if (sbs->zombie) { + return -ENODEV; + } + + down(&sbs_sem); + + if (update_mode == REQUEST_UPDATE_MODE) { + result = acpi_sbs_update_run(sbs, DATA_TYPE_AC_STATE); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_update_run() failed\n")); + } + } + + seq_printf(seq, "state: %s\n", + sbs->ac_present ? "on-line" : "off-line"); + + up(&sbs_sem); + + return 0; +} + +static int acpi_ac_state_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_ac_read_state, PDE(inode)->data); +} + +static struct file_operations acpi_ac_state_fops = { + .open = acpi_ac_state_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +/* -------------------------------------------------------------------------- + Driver Interface + -------------------------------------------------------------------------- */ + +/* Smart Battery */ + +static int acpi_battery_add(struct acpi_sbs *sbs, int id) +{ + int is_present; + int result; + char dir_name[32]; + struct acpi_battery *battery; + + battery = &sbs->battery[id]; + + battery->alive = 0; + + battery->init_state = 0; + battery->id = id; + battery->sbs = sbs; + + result = acpi_battery_select(battery); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_select() failed\n")); + goto end; + } + + result = acpi_battery_get_present(battery); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_get_present() failed\n")); + goto end; + } + + is_present = acpi_battery_is_present(battery); + + if (is_present) { + result = acpi_battery_init(battery); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_init() failed\n")); + goto end; + } + battery->init_state = 1; + } + + (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); + + result = acpi_sbs_generic_add_fs(&battery->battery_entry, + acpi_battery_dir, + dir_name, + &acpi_battery_info_fops, + &acpi_battery_state_fops, + &acpi_battery_alarm_fops, battery); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_generic_add_fs() failed\n")); + goto end; + } + battery->alive = 1; + + end: + return result; +} + +static void acpi_battery_remove(struct acpi_sbs *sbs, int id) +{ + + if (sbs->battery[id].battery_entry) { + acpi_sbs_generic_remove_fs(&(sbs->battery[id].battery_entry), + acpi_battery_dir); + } +} + +static int acpi_ac_add(struct acpi_sbs *sbs) +{ + int result; + + result = acpi_ac_get_present(sbs); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_ac_get_present() failed\n")); + goto end; + } + + result = acpi_sbs_generic_add_fs(&sbs->ac_entry, + acpi_ac_dir, + ACPI_AC_DIR_NAME, + NULL, &acpi_ac_state_fops, NULL, sbs); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_generic_add_fs() failed\n")); + goto end; + } + + end: + + return result; +} + +static void acpi_ac_remove(struct acpi_sbs *sbs) +{ + + if (sbs->ac_entry) { + acpi_sbs_generic_remove_fs(&sbs->ac_entry, acpi_ac_dir); + } +} + +static void acpi_sbs_update_queue_run(unsigned long data) +{ + acpi_os_execute(OSL_GPE_HANDLER, acpi_sbs_update_queue, (void *)data); +} + +static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type) +{ + struct acpi_battery *battery; + int result = 0; + int old_ac_present; + int old_battery_present; + int new_ac_present; + int new_battery_present; + int id; + char dir_name[32]; + int do_battery_init, do_ac_init; + s16 old_remaining_capacity; + + if (sbs->zombie) { + goto end; + } + + old_ac_present = acpi_ac_is_present(sbs); + + result = acpi_ac_get_present(sbs); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_ac_get_present() failed\n")); + } + + new_ac_present = acpi_ac_is_present(sbs); + + do_ac_init = (old_ac_present != new_ac_present); + + if (data_type == DATA_TYPE_AC_STATE) { + goto end; + } + + for (id = 0; id < MAX_SBS_BAT; id++) { + battery = &sbs->battery[id]; + if (battery->alive == 0) { + continue; + } + + old_remaining_capacity = battery->state.remaining_capacity; + + old_battery_present = acpi_battery_is_present(battery); + + result = acpi_battery_select(battery); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_select() failed\n")); + } + if (sbs->zombie) { + goto end; + } + + result = acpi_battery_get_present(battery); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_get_present() failed\n")); + } + if (sbs->zombie) { + goto end; + } + + new_battery_present = acpi_battery_is_present(battery); + + do_battery_init = ((old_battery_present != new_battery_present) + && new_battery_present); + + if (sbs->zombie) { + goto end; + } + if (do_ac_init || do_battery_init || + update_info_mode || sbs->update_info_mode) { + if (sbs->update_info_mode) { + sbs->update_info_mode = 0; + } else { + sbs->update_info_mode = 1; + } + result = acpi_battery_init(battery); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_init() " + "failed\n")); + } + } + if (data_type == DATA_TYPE_INFO) { + continue; + } + + if (sbs->zombie) { + goto end; + } + if (new_battery_present) { + result = acpi_battery_get_alarm(battery); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_get_alarm() " + "failed\n")); + } + if (data_type == DATA_TYPE_ALARM) { + continue; + } + + result = acpi_battery_get_state(battery); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_get_state() " + "failed\n")); + } + } + if (sbs->zombie) { + goto end; + } + if (data_type != DATA_TYPE_COMMON) { + continue; + } + + if (old_battery_present != new_battery_present) { + (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); + result = acpi_sbs_generate_event(sbs->device, + ACPI_SBS_BATTERY_NOTIFY_STATUS, + new_battery_present, + dir_name, + ACPI_BATTERY_CLASS); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_generate_event() " + "failed\n")); + } + } + if (old_remaining_capacity != battery->state.remaining_capacity) { + (void)sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); + result = acpi_sbs_generate_event(sbs->device, + ACPI_SBS_BATTERY_NOTIFY_STATUS, + new_battery_present, + dir_name, + ACPI_BATTERY_CLASS); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_generate_event() failed\n")); + } + } + + } + if (sbs->zombie) { + goto end; + } + if (data_type != DATA_TYPE_COMMON) { + goto end; + } + + if (old_ac_present != new_ac_present) { + result = acpi_sbs_generate_event(sbs->device, + ACPI_SBS_AC_NOTIFY_STATUS, + new_ac_present, + ACPI_AC_DIR_NAME, + ACPI_AC_CLASS); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_generate_event() failed\n")); + } + } + + end: + return result; +} + +static void acpi_sbs_update_queue(void *data) +{ + struct acpi_sbs *sbs = data; + unsigned long delay = -1; + int result; + + if (sbs->zombie) { + goto end; + } + + result = acpi_sbs_update_run(sbs, DATA_TYPE_COMMON); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_update_run() failed\n")); + } + + if (sbs->zombie) { + goto end; + } + + if (update_mode == REQUEST_UPDATE_MODE) { + goto end; + } + + delay = jiffies + HZ * update_time; + sbs->update_timer.data = (unsigned long)data; + sbs->update_timer.function = acpi_sbs_update_queue_run; + sbs->update_timer.expires = delay; + add_timer(&sbs->update_timer); + end: + ; +} + +static int acpi_sbs_add(struct acpi_device *device) +{ + struct acpi_sbs *sbs = NULL; + struct acpi_ec_hc *ec_hc = NULL; + int result, remove_result = 0; + unsigned long sbs_obj; + int id, cnt; + acpi_status status = AE_OK; + + sbs = kmalloc(sizeof(struct acpi_sbs), GFP_KERNEL); + if (!sbs) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "kmalloc() failed\n")); + return -ENOMEM; + } + memset(sbs, 0, sizeof(struct acpi_sbs)); + + cnt = 0; + while (cnt < 10) { + cnt++; + ec_hc = acpi_get_ec_hc(device); + if (ec_hc) { + break; + } + msleep(1000); + } + + if (!ec_hc) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_get_ec_hc() failed: " + "NO driver found for EC HC SMBus\n")); + result = -ENODEV; + goto end; + } + + sbs->device = device; + sbs->smbus = ec_hc->smbus; + + strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); + strcpy(acpi_device_class(device), ACPI_SBS_CLASS); + acpi_driver_data(device) = sbs; + + sbs->update_time = 0; + sbs->update_time2 = 0; + + result = acpi_ac_add(sbs); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "acpi_ac_add() failed\n")); + goto end; + } + result = acpi_evaluate_integer(device->handle, "_SBS", NULL, &sbs_obj); + if (ACPI_FAILURE(result)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_evaluate_integer() failed\n")); + result = -EIO; + goto end; + } + + if (sbs_obj > 0) { + result = acpi_sbsm_get_info(sbs); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbsm_get_info() failed\n")); + goto end; + } + sbs->sbsm_present = 1; + } + if (sbs->sbsm_present == 0) { + result = acpi_battery_add(sbs, 0); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_add() failed\n")); + goto end; + } + } else { + for (id = 0; id < MAX_SBS_BAT; id++) { + if ((sbs->sbsm_batteries_supported & (1 << id))) { + result = acpi_battery_add(sbs, id); + if (result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_battery_add() " + "failed\n")); + goto end; + } + } + } + } + + sbs->handle = device->handle; + + init_timer(&sbs->update_timer); + if (update_mode == QUEUE_UPDATE_MODE) { + status = acpi_os_execute(OSL_GPE_HANDLER, + acpi_sbs_update_queue, (void *)sbs); + if (status != AE_OK) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_os_execute() failed\n")); + } + } + sbs->update_time = update_time; + sbs->update_time2 = update_time2; + + printk(KERN_INFO PREFIX "%s [%s]\n", + acpi_device_name(device), acpi_device_bid(device)); + + end: + if (result) { + remove_result = acpi_sbs_remove(device, 0); + if (remove_result) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_sbs_remove() failed\n")); + } + } + + return result; +} + +int acpi_sbs_remove(struct acpi_device *device, int type) +{ + struct acpi_sbs *sbs = (struct acpi_sbs *)acpi_driver_data(device); + int id; + + if (!device || !sbs) { + return -EINVAL; + } + + sbs->zombie = 1; + sbs->update_time = 0; + sbs->update_time2 = 0; + del_timer_sync(&sbs->update_timer); + acpi_os_wait_events_complete(NULL); + del_timer_sync(&sbs->update_timer); + + for (id = 0; id < MAX_SBS_BAT; id++) { + acpi_battery_remove(sbs, id); + } + + acpi_ac_remove(sbs); + + kfree(sbs); + + return 0; +} + +static int __init acpi_sbs_init(void) +{ + int result = 0; + + if (acpi_disabled) + return -ENODEV; + + init_MUTEX(&sbs_sem); + + if (capacity_mode != DEF_CAPACITY_UNIT + && capacity_mode != MAH_CAPACITY_UNIT + && capacity_mode != MWH_CAPACITY_UNIT) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "acpi_sbs_init: " + "invalid capacity_mode = %d\n", + capacity_mode)); + return -EINVAL; + } + + acpi_ac_dir = acpi_lock_ac_dir(); + if (!acpi_ac_dir) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_lock_ac_dir() failed\n")); + return -ENODEV; + } + + acpi_battery_dir = acpi_lock_battery_dir(); + if (!acpi_battery_dir) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_lock_battery_dir() failed\n")); + return -ENODEV; + } + + result = acpi_bus_register_driver(&acpi_sbs_driver); + if (result < 0) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "acpi_bus_register_driver() failed\n")); + return -ENODEV; + } + + return 0; +} + +static void __exit acpi_sbs_exit(void) +{ + + acpi_bus_unregister_driver(&acpi_sbs_driver); + + acpi_unlock_ac_dir(acpi_ac_dir); + acpi_ac_dir = NULL; + acpi_unlock_battery_dir(acpi_battery_dir); + acpi_battery_dir = NULL; + + return; +} + +module_init(acpi_sbs_init); +module_exit(acpi_sbs_exit); diff --git a/drivers/base/hypervisor.c b/drivers/base/hypervisor.c new file mode 100644 index 000000000..0c85e9d6a --- /dev/null +++ b/drivers/base/hypervisor.c @@ -0,0 +1,19 @@ +/* + * hypervisor.c - /sys/hypervisor subsystem. + * + * This file is released under the GPLv2 + * + */ + +#include <linux/kobject.h> +#include <linux/device.h> + +#include "base.h" + +decl_subsys(hypervisor, NULL, NULL); +EXPORT_SYMBOL_GPL(hypervisor_subsys); + +int __init hypervisor_init(void) +{ + return subsystem_register(&hypervisor_subsys); +} diff --git a/drivers/base/isa.c b/drivers/base/isa.c new file mode 100644 index 000000000..d2222397a --- /dev/null +++ b/drivers/base/isa.c @@ -0,0 +1,180 @@ +/* + * ISA bus. + */ + +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/isa.h> + +static struct device isa_bus = { + .bus_id = "isa" +}; + +struct isa_dev { + struct device dev; + struct device *next; + unsigned int id; +}; + +#define to_isa_dev(x) container_of((x), struct isa_dev, dev) + +static int isa_bus_match(struct device *dev, struct device_driver *driver) +{ + struct isa_driver *isa_driver = to_isa_driver(driver); + + if (dev->platform_data == isa_driver) { + if (!isa_driver->match || + isa_driver->match(dev, to_isa_dev(dev)->id)) + return 1; + dev->platform_data = NULL; + } + return 0; +} + +static int isa_bus_probe(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->probe) + return isa_driver->probe(dev, to_isa_dev(dev)->id); + + return 0; +} + +static int isa_bus_remove(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->remove) + return isa_driver->remove(dev, to_isa_dev(dev)->id); + + return 0; +} + +static void isa_bus_shutdown(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->shutdown) + isa_driver->shutdown(dev, to_isa_dev(dev)->id); +} + +static int isa_bus_suspend(struct device *dev, pm_message_t state) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->suspend) + return isa_driver->suspend(dev, to_isa_dev(dev)->id, state); + + return 0; +} + +static int isa_bus_resume(struct device *dev) +{ + struct isa_driver *isa_driver = dev->platform_data; + + if (isa_driver->resume) + return isa_driver->resume(dev, to_isa_dev(dev)->id); + + return 0; +} + +static struct bus_type isa_bus_type = { + .name = "isa", + .match = isa_bus_match, + .probe = isa_bus_probe, + .remove = isa_bus_remove, + .shutdown = isa_bus_shutdown, + .suspend = isa_bus_suspend, + .resume = isa_bus_resume +}; + +static void isa_dev_release(struct device *dev) +{ + kfree(to_isa_dev(dev)); +} + +void isa_unregister_driver(struct isa_driver *isa_driver) +{ + struct device *dev = isa_driver->devices; + + while (dev) { + struct device *tmp = to_isa_dev(dev)->next; + device_unregister(dev); + dev = tmp; + } + driver_unregister(&isa_driver->driver); +} +EXPORT_SYMBOL_GPL(isa_unregister_driver); + +int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev) +{ + int error; + unsigned int id; + + isa_driver->driver.bus = &isa_bus_type; + isa_driver->devices = NULL; + + error = driver_register(&isa_driver->driver); + if (error) + return error; + + for (id = 0; id < ndev; id++) { + struct isa_dev *isa_dev; + + isa_dev = kzalloc(sizeof *isa_dev, GFP_KERNEL); + if (!isa_dev) { + error = -ENOMEM; + break; + } + + isa_dev->dev.parent = &isa_bus; + isa_dev->dev.bus = &isa_bus_type; + + snprintf(isa_dev->dev.bus_id, BUS_ID_SIZE, "%s.%u", + isa_driver->driver.name, id); + + isa_dev->dev.platform_data = isa_driver; + isa_dev->dev.release = isa_dev_release; + isa_dev->id = id; + + error = device_register(&isa_dev->dev); + if (error) { + put_device(&isa_dev->dev); + break; + } + + if (isa_dev->dev.platform_data) { + isa_dev->next = isa_driver->devices; + isa_driver->devices = &isa_dev->dev; + } else + device_unregister(&isa_dev->dev); + } + + if (!error && !isa_driver->devices) + error = -ENODEV; + + if (error) + isa_unregister_driver(isa_driver); + + return error; +} +EXPORT_SYMBOL_GPL(isa_register_driver); + +static int __init isa_bus_init(void) +{ + int error; + + error = bus_register(&isa_bus_type); + if (!error) { + error = device_register(&isa_bus); + if (error) + bus_unregister(&isa_bus_type); + } + return error; +} + +device_initcall(isa_bus_init); diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c new file mode 100644 index 000000000..a9ab30fef --- /dev/null +++ b/drivers/base/power/trace.c @@ -0,0 +1,228 @@ +/* + * drivers/base/power/trace.c + * + * Copyright (C) 2006 Linus Torvalds + * + * Trace facility for suspend/resume problems, when none of the + * devices may be working. + */ + +#include <linux/resume-trace.h> +#include <linux/rtc.h> + +#include <asm/rtc.h> + +#include "power.h" + +/* + * Horrid, horrid, horrid. + * + * It turns out that the _only_ piece of hardware that actually + * keeps its value across a hard boot (and, more importantly, the + * POST init sequence) is literally the realtime clock. + * + * Never mind that an RTC chip has 114 bytes (and often a whole + * other bank of an additional 128 bytes) of nice SRAM that is + * _designed_ to keep data - the POST will clear it. So we literally + * can just use the few bytes of actual time data, which means that + * we're really limited. + * + * It means, for example, that we can't use the seconds at all + * (since the time between the hang and the boot might be more + * than a minute), and we'd better not depend on the low bits of + * the minutes either. + * + * There are the wday fields etc, but I wouldn't guarantee those + * are dependable either. And if the date isn't valid, either the + * hw or POST will do strange things. + * + * So we're left with: + * - year: 0-99 + * - month: 0-11 + * - day-of-month: 1-28 + * - hour: 0-23 + * - min: (0-30)*2 + * + * Giving us a total range of 0-16128000 (0xf61800), ie less + * than 24 bits of actual data we can save across reboots. + * + * And if your box can't boot in less than three minutes, + * you're screwed. + * + * Now, almost 24 bits of data is pitifully small, so we need + * to be pretty dense if we want to use it for anything nice. + * What we do is that instead of saving off nice readable info, + * we save off _hashes_ of information that we can hopefully + * regenerate after the reboot. + * + * In particular, this means that we might be unlucky, and hit + * a case where we have a hash collision, and we end up not + * being able to tell for certain exactly which case happened. + * But that's hopefully unlikely. + * + * What we do is to take the bits we can fit, and split them + * into three parts (16*997*1009 = 16095568), and use the values + * for: + * - 0-15: user-settable + * - 0-996: file + line number + * - 0-1008: device + */ +#define USERHASH (16) +#define FILEHASH (997) +#define DEVHASH (1009) + +#define DEVSEED (7919) + +static unsigned int dev_hash_value; + +static int set_magic_time(unsigned int user, unsigned int file, unsigned int device) +{ + unsigned int n = user + USERHASH*(file + FILEHASH*device); + + // June 7th, 2006 + static struct rtc_time time = { + .tm_sec = 0, + .tm_min = 0, + .tm_hour = 0, + .tm_mday = 7, + .tm_mon = 5, // June - counting from zero + .tm_year = 106, + .tm_wday = 3, + .tm_yday = 160, + .tm_isdst = 1 + }; + + time.tm_year = (n % 100); + n /= 100; + time.tm_mon = (n % 12); + n /= 12; + time.tm_mday = (n % 28) + 1; + n /= 28; + time.tm_hour = (n % 24); + n /= 24; + time.tm_min = (n % 20) * 3; + n /= 20; + set_rtc_time(&time); + return n ? -1 : 0; +} + +static unsigned int read_magic_time(void) +{ + struct rtc_time time; + unsigned int val; + + get_rtc_time(&time); + printk("Time: %2d:%02d:%02d Date: %02d/%02d/%02d\n", + time.tm_hour, time.tm_min, time.tm_sec, + time.tm_mon, time.tm_mday, time.tm_year); + val = time.tm_year; /* 100 years */ + if (val > 100) + val -= 100; + val += time.tm_mon * 100; /* 12 months */ + val += (time.tm_mday-1) * 100 * 12; /* 28 month-days */ + val += time.tm_hour * 100 * 12 * 28; /* 24 hours */ + val += (time.tm_min / 3) * 100 * 12 * 28 * 24; /* 20 3-minute intervals */ + return val; +} + +/* + * This is just the sdbm hash function with a user-supplied + * seed and final size parameter. + */ +static unsigned int hash_string(unsigned int seed, const char *data, unsigned int mod) +{ + unsigned char c; + while ((c = *data++) != 0) { + seed = (seed << 16) + (seed << 6) - seed + c; + } + return seed % mod; +} + +void set_trace_device(struct device *dev) +{ + dev_hash_value = hash_string(DEVSEED, dev->bus_id, DEVHASH); +} + +/* + * We could just take the "tracedata" index into the .tracedata + * section instead. Generating a hash of the data gives us a + * chance to work across kernel versions, and perhaps more + * importantly it also gives us valid/invalid check (ie we will + * likely not give totally bogus reports - if the hash matches, + * it's not any guarantee, but it's a high _likelihood_ that + * the match is valid). + */ +void generate_resume_trace(void *tracedata, unsigned int user) +{ + unsigned short lineno = *(unsigned short *)tracedata; + const char *file = *(const char **)(tracedata + 2); + unsigned int user_hash_value, file_hash_value; + + user_hash_value = user % USERHASH; + file_hash_value = hash_string(lineno, file, FILEHASH); + set_magic_time(user_hash_value, file_hash_value, dev_hash_value); +} + +extern char __tracedata_start, __tracedata_end; +static int show_file_hash(unsigned int value) +{ + int match; + char *tracedata; + + match = 0; + for (tracedata = &__tracedata_start ; tracedata < &__tracedata_end ; tracedata += 6) { + unsigned short lineno = *(unsigned short *)tracedata; + const char *file = *(const char **)(tracedata + 2); + unsigned int hash = hash_string(lineno, file, FILEHASH); + if (hash != value) + continue; + printk(" hash matches %s:%u\n", file, lineno); + match++; + } + return match; +} + +static int show_dev_hash(unsigned int value) +{ + int match = 0; + struct list_head * entry = dpm_active.prev; + + while (entry != &dpm_active) { + struct device * dev = to_device(entry); + unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH); + if (hash == value) { + printk(" hash matches device %s\n", dev->bus_id); + match++; + } + entry = entry->prev; + } + return match; +} + +static unsigned int hash_value_early_read; + +static int early_resume_init(void) +{ + hash_value_early_read = read_magic_time(); + return 0; +} + +static int late_resume_init(void) +{ + unsigned int val = hash_value_early_read; + unsigned int user, file, dev; + + user = val % USERHASH; + val = val / USERHASH; + file = val % FILEHASH; + val = val / FILEHASH; + dev = val /* % DEVHASH */; + + printk(" Magic number: %d:%d:%d\n", user, file, dev); + show_file_hash(file); + show_dev_hash(dev); + return 0; +} + +core_initcall(early_resume_init); +late_initcall(late_resume_init); diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig new file mode 100644 index 000000000..9f7635f75 --- /dev/null +++ b/drivers/char/hw_random/Kconfig @@ -0,0 +1,90 @@ +# +# Hardware Random Number Generator (RNG) configuration +# + +config HW_RANDOM + bool "Hardware Random Number Generator Core support" + default y + ---help--- + Hardware Random Number Generator Core infrastructure. + + If unsure, say Y. + +config HW_RANDOM_INTEL + tristate "Intel HW Random Number Generator support" + depends on HW_RANDOM && (X86 || IA64) && PCI + default y + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on Intel i8xx-based motherboards. + + To compile this driver as a module, choose M here: the + module will be called intel-rng. + + If unsure, say Y. + +config HW_RANDOM_AMD + tristate "AMD HW Random Number Generator support" + depends on HW_RANDOM && X86 && PCI + default y + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on AMD 76x-based motherboards. + + To compile this driver as a module, choose M here: the + module will be called amd-rng. + + If unsure, say Y. + +config HW_RANDOM_GEODE + tristate "AMD Geode HW Random Number Generator support" + depends on HW_RANDOM && X86 && PCI + default y + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on the AMD Geode LX. + + To compile this driver as a module, choose M here: the + module will be called geode-rng. + + If unsure, say Y. + +config HW_RANDOM_VIA + tristate "VIA HW Random Number Generator support" + depends on HW_RANDOM && X86_32 + default y + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on VIA based motherboards. + + To compile this driver as a module, choose M here: the + module will be called via-rng. + + If unsure, say Y. + +config HW_RANDOM_IXP4XX + tristate "Intel IXP4xx NPU HW Random Number Generator support" + depends on HW_RANDOM && ARCH_IXP4XX + default y + ---help--- + This driver provides kernel-side support for the Random + Number Generator hardware found on the Intel IXP4xx NPU. + + To compile this driver as a module, choose M here: the + module will be called ixp4xx-rng. + + If unsure, say Y. + +config HW_RANDOM_OMAP + tristate "OMAP Random Number Generator support" + depends on HW_RANDOM && (ARCH_OMAP16XX || ARCH_OMAP24XX) + default y + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on OMAP16xx and OMAP24xx multimedia + processors. + + To compile this driver as a module, choose M here: the + module will be called omap-rng. + + If unsure, say Y. diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile new file mode 100644 index 000000000..e263ae96f --- /dev/null +++ b/drivers/char/hw_random/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for HW Random Number Generator (RNG) device drivers. +# + +obj-$(CONFIG_HW_RANDOM) += core.o +obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o +obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o +obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o +obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o +obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o +obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c new file mode 100644 index 000000000..71e4e0f3f --- /dev/null +++ b/drivers/char/hw_random/amd-rng.c @@ -0,0 +1,152 @@ +/* + * RNG driver for AMD RNGs + * + * Copyright 2005 (c) MontaVista Software, Inc. + * + * with the majority of the code coming from: + * + * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) + * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com> + * + * derived from + * + * Hardware driver for the AMD 768 Random Number Generator (RNG) + * (c) Copyright 2001 Red Hat Inc <alan@redhat.com> + * + * derived from + * + * Hardware driver for Intel i810 Random Number Generator (RNG) + * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com> + * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/hw_random.h> +#include <asm/io.h> + + +#define PFX KBUILD_MODNAME ": " + + +/* + * Data for PCI driver interface + * + * This data only exists for exporting the supported + * PCI ids via MODULE_DEVICE_TABLE. We do not actually + * register a pci_driver, because someone else might one day + * want to register another driver on the same PCI id. + */ +static const struct pci_device_id pci_tbl[] = { + { 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { 0x1022, 0x746b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { 0, }, /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, pci_tbl); + +static struct pci_dev *amd_pdev; + + +static int amd_rng_data_present(struct hwrng *rng) +{ + u32 pmbase = (u32)rng->priv; + + return !!(inl(pmbase + 0xF4) & 1); +} + +static int amd_rng_data_read(struct hwrng *rng, u32 *data) +{ + u32 pmbase = (u32)rng->priv; + + *data = inl(pmbase + 0xF0); + + return 4; +} + +static int amd_rng_init(struct hwrng *rng) +{ + u8 rnen; + + pci_read_config_byte(amd_pdev, 0x40, &rnen); + rnen |= (1 << 7); /* RNG on */ + pci_write_config_byte(amd_pdev, 0x40, rnen); + + pci_read_config_byte(amd_pdev, 0x41, &rnen); + rnen |= (1 << 7); /* PMIO enable */ + pci_write_config_byte(amd_pdev, 0x41, rnen); + + return 0; +} + +static void amd_rng_cleanup(struct hwrng *rng) +{ + u8 rnen; + + pci_read_config_byte(amd_pdev, 0x40, &rnen); + rnen &= ~(1 << 7); /* RNG off */ + pci_write_config_byte(amd_pdev, 0x40, rnen); +} + + +static struct hwrng amd_rng = { + .name = "amd", + .init = amd_rng_init, + .cleanup = amd_rng_cleanup, + .data_present = amd_rng_data_present, + .data_read = amd_rng_data_read, +}; + + +static int __init mod_init(void) +{ + int err = -ENODEV; + struct pci_dev *pdev = NULL; + const struct pci_device_id *ent; + u32 pmbase; + + for_each_pci_dev(pdev) { + ent = pci_match_id(pci_tbl, pdev); + if (ent) + goto found; + } + /* Device not found. */ + goto out; + +found: + err = pci_read_config_dword(pdev, 0x58, &pmbase); + if (err) + goto out; + err = -EIO; + pmbase &= 0x0000FF00; + if (pmbase == 0) + goto out; + amd_rng.priv = (unsigned long)pmbase; + amd_pdev = pdev; + + printk(KERN_INFO "AMD768 RNG detected\n"); + err = hwrng_register(&amd_rng); + if (err) { + printk(KERN_ERR PFX "RNG registering failed (%d)\n", + err); + goto out; + } +out: + return err; +} + +static void __exit mod_exit(void) +{ + hwrng_unregister(&amd_rng); +} + +subsys_initcall(mod_init); +module_exit(mod_exit); + +MODULE_AUTHOR("The Linux Kernel team"); +MODULE_DESCRIPTION("H/W RNG driver for AMD chipsets"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c new file mode 100644 index 000000000..154a81d32 --- /dev/null +++ b/drivers/char/hw_random/core.c @@ -0,0 +1,354 @@ +/* + Added support for the AMD Geode LX RNG + (c) Copyright 2004-2005 Advanced Micro Devices, Inc. + + derived from + + Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) + (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com> + + derived from + + Hardware driver for the AMD 768 Random Number Generator (RNG) + (c) Copyright 2001 Red Hat Inc <alan@redhat.com> + + derived from + + Hardware driver for Intel i810 Random Number Generator (RNG) + Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com> + Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com> + + Added generic RNG API + Copyright 2006 Michael Buesch <mbuesch@freenet.de> + Copyright 2005 (c) MontaVista Software, Inc. + + Please read Documentation/hw_random.txt for details on use. + + ---------------------------------------------------------- + This software may be used and distributed according to the terms + of the GNU General Public License, incorporated herein by reference. + + */ + + +#include <linux/device.h> +#include <linux/hw_random.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/fs.h> +#include <linux/init.h> +#include <linux/miscdevice.h> +#include <linux/delay.h> +#include <asm/uaccess.h> + + +#define RNG_MODULE_NAME "hw_random" +#define PFX RNG_MODULE_NAME ": " +#define RNG_MISCDEV_MINOR 183 /* official */ + + +static struct hwrng *current_rng; +static LIST_HEAD(rng_list); +static DEFINE_MUTEX(rng_mutex); + + +static inline int hwrng_init(struct hwrng *rng) +{ + if (!rng->init) + return 0; + return rng->init(rng); +} + +static inline void hwrng_cleanup(struct hwrng *rng) +{ + if (rng && rng->cleanup) + rng->cleanup(rng); +} + +static inline int hwrng_data_present(struct hwrng *rng) +{ + if (!rng->data_present) + return 1; + return rng->data_present(rng); +} + +static inline int hwrng_data_read(struct hwrng *rng, u32 *data) +{ + return rng->data_read(rng, data); +} + + +static int rng_dev_open(struct inode *inode, struct file *filp) +{ + /* enforce read-only access to this chrdev */ + if ((filp->f_mode & FMODE_READ) == 0) + return -EINVAL; + if (filp->f_mode & FMODE_WRITE) + return -EINVAL; + return 0; +} + +static ssize_t rng_dev_read(struct file *filp, char __user *buf, + size_t size, loff_t *offp) +{ + u32 data; + ssize_t ret = 0; + int i, err = 0; + int data_present; + int bytes_read; + + while (size) { + err = -ERESTARTSYS; + if (mutex_lock_interruptible(&rng_mutex)) + goto out; + if (!current_rng) { + mutex_unlock(&rng_mutex); + err = -ENODEV; + goto out; + } + if (filp->f_flags & O_NONBLOCK) { + data_present = hwrng_data_present(current_rng); + } else { + /* Some RNG require some time between data_reads to gather + * new entropy. Poll it. + */ + for (i = 0; i < 20; i++) { + data_present = hwrng_data_present(current_rng); + if (data_present) + break; + udelay(10); + } + } + bytes_read = 0; + if (data_present) + bytes_read = hwrng_data_read(current_rng, &data); + mutex_unlock(&rng_mutex); + + err = -EAGAIN; + if (!bytes_read && (filp->f_flags & O_NONBLOCK)) + goto out; + + err = -EFAULT; + while (bytes_read && size) { + if (put_user((u8)data, buf++)) + goto out; + size--; + ret++; + bytes_read--; + data >>= 8; + } + + if (need_resched()) + schedule_timeout_interruptible(1); + err = -ERESTARTSYS; + if (signal_pending(current)) + goto out; + } +out: + return ret ? : err; +} + + +static const struct file_operations rng_chrdev_ops = { + .owner = THIS_MODULE, + .open = rng_dev_open, + .read = rng_dev_read, +}; + +static struct miscdevice rng_miscdev = { + .minor = RNG_MISCDEV_MINOR, + .name = RNG_MODULE_NAME, + .fops = &rng_chrdev_ops, +}; + + +static ssize_t hwrng_attr_current_store(struct class_device *class, + const char *buf, size_t len) +{ + int err; + struct hwrng *rng; + + err = mutex_lock_interruptible(&rng_mutex); + if (err) + return -ERESTARTSYS; + err = -ENODEV; + list_for_each_entry(rng, &rng_list, list) { + if (strcmp(rng->name, buf) == 0) { + if (rng == current_rng) { + err = 0; + break; + } + err = hwrng_init(rng); + if (err) + break; + hwrng_cleanup(current_rng); + current_rng = rng; + err = 0; + break; + } + } + mutex_unlock(&rng_mutex); + + return err ? : len; +} + +static ssize_t hwrng_attr_current_show(struct class_device *class, + char *buf) +{ + int err; + ssize_t ret; + const char *name = "none"; + + err = mutex_lock_interruptible(&rng_mutex); + if (err) + return -ERESTARTSYS; + if (current_rng) + name = current_rng->name; + ret = snprintf(buf, PAGE_SIZE, "%s\n", name); + mutex_unlock(&rng_mutex); + + return ret; +} + +static ssize_t hwrng_attr_available_show(struct class_device *class, + char *buf) +{ + int err; + ssize_t ret = 0; + struct hwrng *rng; + + err = mutex_lock_interruptible(&rng_mutex); + if (err) + return -ERESTARTSYS; + buf[0] = '\0'; + list_for_each_entry(rng, &rng_list, list) { + strncat(buf, rng->name, PAGE_SIZE - ret - 1); + ret += strlen(rng->name); + strncat(buf, " ", PAGE_SIZE - ret - 1); + ret++; + } + strncat(buf, "\n", PAGE_SIZE - ret - 1); + ret++; + mutex_unlock(&rng_mutex); + + return ret; +} + +static CLASS_DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR, + hwrng_attr_current_show, + hwrng_attr_current_store); +static CLASS_DEVICE_ATTR(rng_available, S_IRUGO, + hwrng_attr_available_show, + NULL); + + +static void unregister_miscdev(void) +{ + class_device_remove_file(rng_miscdev.class, + &class_device_attr_rng_available); + class_device_remove_file(rng_miscdev.class, + &class_device_attr_rng_current); + misc_deregister(&rng_miscdev); +} + +static int register_miscdev(void) +{ + int err; + + err = misc_register(&rng_miscdev); + if (err) + goto out; + err = class_device_create_file(rng_miscdev.class, + &class_device_attr_rng_current); + if (err) + goto err_misc_dereg; + err = class_device_create_file(rng_miscdev.class, + &class_device_attr_rng_available); + if (err) + goto err_remove_current; +out: + return err; + +err_remove_current: + class_device_remove_file(rng_miscdev.class, + &class_device_attr_rng_current); +err_misc_dereg: + misc_deregister(&rng_miscdev); + goto out; +} + +int hwrng_register(struct hwrng *rng) +{ + int must_register_misc; + int err = -EINVAL; + struct hwrng *old_rng, *tmp; + + if (rng->name == NULL || + rng->data_read == NULL) + goto out; + + mutex_lock(&rng_mutex); + + /* Must not register two RNGs with the same name. */ + err = -EEXIST; + list_for_each_entry(tmp, &rng_list, list) { + if (strcmp(tmp->name, rng->name) == 0) + goto out_unlock; + } + + must_register_misc = (current_rng == NULL); + old_rng = current_rng; + if (!old_rng) { + err = hwrng_init(rng); + if (err) + goto out_unlock; + current_rng = rng; + } + err = 0; + if (must_register_misc) { + err = register_miscdev(); + if (err) { + if (!old_rng) { + hwrng_cleanup(rng); + current_rng = NULL; + } + goto out_unlock; + } + } + INIT_LIST_HEAD(&rng->list); + list_add_tail(&rng->list, &rng_list); +out_unlock: + mutex_unlock(&rng_mutex); +out: + return err; +} +EXPORT_SYMBOL_GPL(hwrng_register); + +void hwrng_unregister(struct hwrng *rng) +{ + int err; + + mutex_lock(&rng_mutex); + + list_del(&rng->list); + if (current_rng == rng) { + hwrng_cleanup(rng); + if (list_empty(&rng_list)) { + current_rng = NULL; + } else { + current_rng = list_entry(rng_list.prev, struct hwrng, list); + err = hwrng_init(current_rng); + if (err) + current_rng = NULL; + } + } + if (list_empty(&rng_list)) + unregister_miscdev(); + + mutex_unlock(&rng_mutex); +} +EXPORT_SYMBOL_GPL(hwrng_unregister); + + +MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c new file mode 100644 index 000000000..d37ced0d1 --- /dev/null +++ b/drivers/char/hw_random/geode-rng.c @@ -0,0 +1,132 @@ +/* + * RNG driver for AMD Geode RNGs + * + * Copyright 2005 (c) MontaVista Software, Inc. + * + * with the majority of the code coming from: + * + * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) + * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com> + * + * derived from + * + * Hardware driver for the AMD 768 Random Number Generator (RNG) + * (c) Copyright 2001 Red Hat Inc <alan@redhat.com> + * + * derived from + * + * Hardware driver for Intel i810 Random Number Generator (RNG) + * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com> + * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/hw_random.h> +#include <asm/io.h> + + +#define PFX KBUILD_MODNAME ": " + +#define GEODE_RNG_DATA_REG 0x50 +#define GEODE_RNG_STATUS_REG 0x54 + +/* + * Data for PCI driver interface + * + * This data only exists for exporting the supported + * PCI ids via MODULE_DEVICE_TABLE. We do not actually + * register a pci_driver, because someone else might one day + * want to register another driver on the same PCI id. + */ +static const struct pci_device_id pci_tbl[] = { + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, + { 0, }, /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, pci_tbl); + + +static int geode_rng_data_read(struct hwrng *rng, u32 *data) +{ + void __iomem *mem = (void __iomem *)rng->priv; + + *data = readl(mem + GEODE_RNG_DATA_REG); + + return 4; +} + +static int geode_rng_data_present(struct hwrng *rng) +{ + void __iomem *mem = (void __iomem *)rng->priv; + + return !!(readl(mem + GEODE_RNG_STATUS_REG)); +} + + +static struct hwrng geode_rng = { + .name = "geode", + .data_present = geode_rng_data_present, + .data_read = geode_rng_data_read, +}; + + +static int __init mod_init(void) +{ + int err = -ENODEV; + struct pci_dev *pdev = NULL; + const struct pci_device_id *ent; + void __iomem *mem; + unsigned long rng_base; + + for_each_pci_dev(pdev) { + ent = pci_match_id(pci_tbl, pdev); + if (ent) + goto found; + } + /* Device not found. */ + goto out; + +found: + rng_base = pci_resource_start(pdev, 0); + if (rng_base == 0) + goto out; + err = -ENOMEM; + mem = ioremap(rng_base, 0x58); + if (!mem) + goto out; + geode_rng.priv = (unsigned long)mem; + + printk(KERN_INFO "AMD Geode RNG detected\n"); + err = hwrng_register(&geode_rng); + if (err) { + printk(KERN_ERR PFX "RNG registering failed (%d)\n", + err); + goto err_unmap; + } +out: + return err; + +err_unmap: + iounmap(mem); + goto out; +} + +static void __exit mod_exit(void) +{ + void __iomem *mem = (void __iomem *)geode_rng.priv; + + hwrng_unregister(&geode_rng); + iounmap(mem); +} + +subsys_initcall(mod_init); +module_exit(mod_exit); + +MODULE_DESCRIPTION("H/W RNG driver for AMD Geode LX CPUs"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c new file mode 100644 index 000000000..8efbc9c0e --- /dev/null +++ b/drivers/char/hw_random/intel-rng.c @@ -0,0 +1,357 @@ +/* + * RNG driver for Intel RNGs + * + * Copyright 2005 (c) MontaVista Software, Inc. + * + * with the majority of the code coming from: + * + * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) + * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com> + * + * derived from + * + * Hardware driver for the AMD 768 Random Number Generator (RNG) + * (c) Copyright 2001 Red Hat Inc <alan@redhat.com> + * + * derived from + * + * Hardware driver for Intel i810 Random Number Generator (RNG) + * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com> + * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/hw_random.h> +#include <asm/io.h> + + +#define PFX KBUILD_MODNAME ": " + +/* + * RNG registers + */ +#define INTEL_RNG_HW_STATUS 0 +#define INTEL_RNG_PRESENT 0x40 +#define INTEL_RNG_ENABLED 0x01 +#define INTEL_RNG_STATUS 1 +#define INTEL_RNG_DATA_PRESENT 0x01 +#define INTEL_RNG_DATA 2 + +/* + * Magic address at which Intel PCI bridges locate the RNG + */ +#define INTEL_RNG_ADDR 0xFFBC015F +#define INTEL_RNG_ADDR_LEN 3 + +/* + * LPC bridge PCI config space registers + */ +#define FWH_DEC_EN1_REG_OLD 0xe3 +#define FWH_DEC_EN1_REG_NEW 0xd9 /* high byte of 16-bit register */ +#define FWH_F8_EN_MASK 0x80 + +#define BIOS_CNTL_REG_OLD 0x4e +#define BIOS_CNTL_REG_NEW 0xdc +#define BIOS_CNTL_WRITE_ENABLE_MASK 0x01 +#define BIOS_CNTL_LOCK_ENABLE_MASK 0x02 + +/* + * Magic address at which Intel Firmware Hubs get accessed + */ +#define INTEL_FWH_ADDR 0xffff0000 +#define INTEL_FWH_ADDR_LEN 2 + +/* + * Intel Firmware Hub command codes (write to any address inside the device) + */ +#define INTEL_FWH_RESET_CMD 0xff /* aka READ_ARRAY */ +#define INTEL_FWH_READ_ID_CMD 0x90 + +/* + * Intel Firmware Hub Read ID command result addresses + */ +#define INTEL_FWH_MANUFACTURER_CODE_ADDRESS 0x000000 +#define INTEL_FWH_DEVICE_CODE_ADDRESS 0x000001 + +/* + * Intel Firmware Hub Read ID command result values + */ +#define INTEL_FWH_MANUFACTURER_CODE 0x89 +#define INTEL_FWH_DEVICE_CODE_8M 0xac +#define INTEL_FWH_DEVICE_CODE_4M 0xad + +/* + * Data for PCI driver interface + * + * This data only exists for exporting the supported + * PCI ids via MODULE_DEVICE_TABLE. We do not actually + * register a pci_driver, because someone else might one day + * want to register another driver on the same PCI id. + */ +static const struct pci_device_id pci_tbl[] = { +/* AA + { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ + { 0x8086, 0x2410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AA */ +/* AB + { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ + { 0x8086, 0x2420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* AB */ +/* ?? + { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ +/* BAM, CAM, DBM, FBM, GxM + { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ + { 0x8086, 0x244c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BAM */ + { 0x8086, 0x248c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CAM */ + { 0x8086, 0x24cc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DBM */ + { 0x8086, 0x2641, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* FBM */ + { 0x8086, 0x27b9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM */ + { 0x8086, 0x27bd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* GxM DH */ +/* BA, CA, DB, Ex, 6300, Fx, 631x/632x, Gx + { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ + { 0x8086, 0x2440, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* BA */ + { 0x8086, 0x2480, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* CA */ + { 0x8086, 0x24c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* DB */ + { 0x8086, 0x24d0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Ex */ + { 0x8086, 0x25a1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 6300 */ + { 0x8086, 0x2640, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Fx */ + { 0x8086, 0x2670, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2671, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2672, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2673, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2674, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2675, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2676, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2677, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2678, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x2679, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x267a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x267b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x267c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x267d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x267e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x267f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* 631x/632x */ + { 0x8086, 0x27b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Gx */ +/* E + { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, */ + { 0x8086, 0x2450, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* E */ + { 0, }, /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, pci_tbl); + + +static inline u8 hwstatus_get(void __iomem *mem) +{ + return readb(mem + INTEL_RNG_HW_STATUS); +} + +static inline u8 hwstatus_set(void __iomem *mem, + u8 hw_status) +{ + writeb(hw_status, mem + INTEL_RNG_HW_STATUS); + return hwstatus_get(mem); +} + +static int intel_rng_data_present(struct hwrng *rng) +{ + void __iomem *mem = (void __iomem *)rng->priv; + + return !!(readb(mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT); +} + +static int intel_rng_data_read(struct hwrng *rng, u32 *data) +{ + void __iomem *mem = (void __iomem *)rng->priv; + + *data = readb(mem + INTEL_RNG_DATA); + + return 1; +} + +static int intel_rng_init(struct hwrng *rng) +{ + void __iomem *mem = (void __iomem *)rng->priv; + u8 hw_status; + int err = -EIO; + + hw_status = hwstatus_get(mem); + /* turn RNG h/w on, if it's off */ + if ((hw_status & INTEL_RNG_ENABLED) == 0) + hw_status = hwstatus_set(mem, hw_status | INTEL_RNG_ENABLED); + if ((hw_status & INTEL_RNG_ENABLED) == 0) { + printk(KERN_ERR PFX "cannot enable RNG, aborting\n"); + goto out; + } + err = 0; +out: + return err; +} + +static void intel_rng_cleanup(struct hwrng *rng) +{ + void __iomem *mem = (void __iomem *)rng->priv; + u8 hw_status; + + hw_status = hwstatus_get(mem); + if (hw_status & INTEL_RNG_ENABLED) + hwstatus_set(mem, hw_status & ~INTEL_RNG_ENABLED); + else + printk(KERN_WARNING PFX "unusual: RNG already disabled\n"); +} + + +static struct hwrng intel_rng = { + .name = "intel", + .init = intel_rng_init, + .cleanup = intel_rng_cleanup, + .data_present = intel_rng_data_present, + .data_read = intel_rng_data_read, +}; + + +#ifdef CONFIG_SMP +static char __initdata waitflag; + +static void __init intel_init_wait(void *unused) +{ + while (waitflag) + cpu_relax(); +} +#endif + +static int __init mod_init(void) +{ + int err = -ENODEV; + unsigned i; + struct pci_dev *dev = NULL; + void __iomem *mem; + unsigned long flags; + u8 bios_cntl_off, fwh_dec_en1_off; + u8 bios_cntl_val = 0xff, fwh_dec_en1_val = 0xff; + u8 hw_status, mfc, dvc; + + for (i = 0; !dev && pci_tbl[i].vendor; ++i) + dev = pci_get_device(pci_tbl[i].vendor, pci_tbl[i].device, NULL); + + if (!dev) + goto out; /* Device not found. */ + + /* Check for Intel 82802 */ + if (dev->device < 0x2640) { + fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD; + bios_cntl_off = BIOS_CNTL_REG_OLD; + } else { + fwh_dec_en1_off = FWH_DEC_EN1_REG_NEW; + bios_cntl_off = BIOS_CNTL_REG_NEW; + } + + pci_read_config_byte(dev, fwh_dec_en1_off, &fwh_dec_en1_val); + pci_read_config_byte(dev, bios_cntl_off, &bios_cntl_val); + + mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN); + if (mem == NULL) { + pci_dev_put(dev); + err = -EBUSY; + goto out; + } + + /* + * Since the BIOS code/data is going to disappear from its normal + * location with the Read ID command, all activity on the system + * must be stopped until the state is back to normal. + */ +#ifdef CONFIG_SMP + set_mb(waitflag, 1); + if (smp_call_function(intel_init_wait, NULL, 1, 0) != 0) { + set_mb(waitflag, 0); + pci_dev_put(dev); + printk(KERN_ERR PFX "cannot run on all processors\n"); + err = -EAGAIN; + goto err_unmap; + } +#endif + local_irq_save(flags); + + if (!(fwh_dec_en1_val & FWH_F8_EN_MASK)) + pci_write_config_byte(dev, + fwh_dec_en1_off, + fwh_dec_en1_val | FWH_F8_EN_MASK); + if (!(bios_cntl_val & + (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))) + pci_write_config_byte(dev, + bios_cntl_off, + bios_cntl_val | BIOS_CNTL_WRITE_ENABLE_MASK); + + writeb(INTEL_FWH_RESET_CMD, mem); + writeb(INTEL_FWH_READ_ID_CMD, mem); + mfc = readb(mem + INTEL_FWH_MANUFACTURER_CODE_ADDRESS); + dvc = readb(mem + INTEL_FWH_DEVICE_CODE_ADDRESS); + writeb(INTEL_FWH_RESET_CMD, mem); + + if (!(bios_cntl_val & + (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))) + pci_write_config_byte(dev, bios_cntl_off, bios_cntl_val); + if (!(fwh_dec_en1_val & FWH_F8_EN_MASK)) + pci_write_config_byte(dev, fwh_dec_en1_off, fwh_dec_en1_val); + + local_irq_restore(flags); +#ifdef CONFIG_SMP + /* Tell other CPUs to resume. */ + set_mb(waitflag, 0); +#endif + + iounmap(mem); + pci_dev_put(dev); + + if (mfc != INTEL_FWH_MANUFACTURER_CODE || + (dvc != INTEL_FWH_DEVICE_CODE_8M && + dvc != INTEL_FWH_DEVICE_CODE_4M)) { + printk(KERN_ERR PFX "FWH not detected\n"); + err = -ENODEV; + goto out; + } + + err = -ENOMEM; + mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN); + if (!mem) + goto out; + intel_rng.priv = (unsigned long)mem; + + /* Check for Random Number Generator */ + err = -ENODEV; + hw_status = hwstatus_get(mem); + if ((hw_status & INTEL_RNG_PRESENT) == 0) + goto err_unmap; + + printk(KERN_INFO "Intel 82802 RNG detected\n"); + err = hwrng_register(&intel_rng); + if (err) { + printk(KERN_ERR PFX "RNG registering failed (%d)\n", + err); + goto err_unmap; + } +out: + return err; + +err_unmap: + iounmap(mem); + goto out; +} + +static void __exit mod_exit(void) +{ + void __iomem *mem = (void __iomem *)intel_rng.priv; + + hwrng_unregister(&intel_rng); + iounmap(mem); +} + +subsys_initcall(mod_init); +module_exit(mod_exit); + +MODULE_DESCRIPTION("H/W RNG driver for Intel chipsets"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/hw_random/ixp4xx-rng.c b/drivers/char/hw_random/ixp4xx-rng.c new file mode 100644 index 000000000..7f7615b11 --- /dev/null +++ b/drivers/char/hw_random/ixp4xx-rng.c @@ -0,0 +1,72 @@ +/* + * drivers/char/rng/ixp4xx-rng.c + * + * RNG driver for Intel IXP4xx family of NPUs + * + * Author: Deepak Saxena <dsaxena@plexity.net> + * + * Copyright 2005 (c) MontaVista Software, Inc. + * + * Fixes by Michael Buesch + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/init.h> +#include <linux/bitops.h> +#include <linux/hw_random.h> + +#include <asm/io.h> +#include <asm/hardware.h> + + +static int ixp4xx_rng_data_read(struct hwrng *rng, u32 *buffer) +{ + void __iomem * rng_base = (void __iomem *)rng->priv; + + *buffer = __raw_readl(rng_base); + + return 4; +} + +static struct hwrng ixp4xx_rng_ops = { + .name = "ixp4xx", + .data_read = ixp4xx_rng_data_read, +}; + +static int __init ixp4xx_rng_init(void) +{ + void __iomem * rng_base; + int err; + + rng_base = ioremap(0x70002100, 4); + if (!rng_base) + return -ENOMEM; + ixp4xx_rng_ops.priv = (unsigned long)rng_base; + err = hwrng_register(&ixp4xx_rng_ops); + if (err) + iounmap(rng_base); + + return err; +} + +static void __exit ixp4xx_rng_exit(void) +{ + void __iomem * rng_base = (void __iomem *)ixp4xx_rng_ops.priv; + + hwrng_unregister(&ixp4xx_rng_ops); + iounmap(rng_base); +} + +subsys_initcall(ixp4xx_rng_init); +module_exit(ixp4xx_rng_exit); + +MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>"); +MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver for IXP4xx"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c new file mode 100644 index 000000000..a01d796d1 --- /dev/null +++ b/drivers/char/hw_random/omap-rng.c @@ -0,0 +1,205 @@ +/* + * driver/char/hw_random/omap-rng.c + * + * RNG driver for TI OMAP CPU family + * + * Author: Deepak Saxena <dsaxena@plexity.net> + * + * Copyright 2005 (c) MontaVista Software, Inc. + * + * Mostly based on original driver: + * + * Copyright (C) 2005 Nokia Corporation + * Author: Juha Yrj��<juha.yrjola@nokia.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + * TODO: + * + * - Make status updated be interrupt driven so we don't poll + * + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/random.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/hw_random.h> + +#include <asm/io.h> + +#define RNG_OUT_REG 0x00 /* Output register */ +#define RNG_STAT_REG 0x04 /* Status register + [0] = STAT_BUSY */ +#define RNG_ALARM_REG 0x24 /* Alarm register + [7:0] = ALARM_COUNTER */ +#define RNG_CONFIG_REG 0x28 /* Configuration register + [11:6] = RESET_COUNT + [5:3] = RING2_DELAY + [2:0] = RING1_DELAY */ +#define RNG_REV_REG 0x3c /* Revision register + [7:0] = REV_NB */ +#define RNG_MASK_REG 0x40 /* Mask and reset register + [2] = IT_EN + [1] = SOFTRESET + [0] = AUTOIDLE */ +#define RNG_SYSSTATUS 0x44 /* System status + [0] = RESETDONE */ + +static void __iomem *rng_base; +static struct clk *rng_ick; +static struct platform_device *rng_dev; + +static u32 omap_rng_read_reg(int reg) +{ + return __raw_readl(rng_base + reg); +} + +static void omap_rng_write_reg(int reg, u32 val) +{ + __raw_writel(val, rng_base + reg); +} + +/* REVISIT: Does the status bit really work on 16xx? */ +static int omap_rng_data_present(struct hwrng *rng) +{ + return omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1; +} + +static int omap_rng_data_read(struct hwrng *rng, u32 *data) +{ + *data = omap_rng_read_reg(RNG_OUT_REG); + + return 4; +} + +static struct hwrng omap_rng_ops = { + .name = "omap", + .data_present = omap_rng_data_present, + .data_read = omap_rng_data_read, +}; + +static int __init omap_rng_probe(struct platform_device *pdev) +{ + struct resource *res, *mem; + int ret; + + /* + * A bit ugly, and it will never actually happen but there can + * be only one RNG and this catches any bork + */ + BUG_ON(rng_dev); + + if (cpu_is_omap24xx()) { + rng_ick = clk_get(NULL, "rng_ick"); + if (IS_ERR(rng_ick)) { + dev_err(&pdev->dev, "Could not get rng_ick\n"); + ret = PTR_ERR(rng_ick); + return ret; + } else + clk_enable(rng_ick); + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (!res) + return -ENOENT; + + mem = request_mem_region(res->start, res->end - res->start + 1, + pdev->name); + if (mem == NULL) + return -EBUSY; + + dev_set_drvdata(&pdev->dev, mem); + rng_base = (u32 __iomem *)io_p2v(res->start); + + ret = hwrng_register(&omap_rng_ops); + if (ret) { + release_resource(mem); + rng_base = NULL; + return ret; + } + + dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n", + omap_rng_read_reg(RNG_REV_REG)); + omap_rng_write_reg(RNG_MASK_REG, 0x1); + + rng_dev = pdev; + + return 0; +} + +static int __exit omap_rng_remove(struct platform_device *pdev) +{ + struct resource *mem = dev_get_drvdata(&pdev->dev); + + hwrng_unregister(&omap_rng_ops); + + omap_rng_write_reg(RNG_MASK_REG, 0x0); + + if (cpu_is_omap24xx()) { + clk_disable(rng_ick); + clk_put(rng_ick); + } + + release_resource(mem); + rng_base = NULL; + + return 0; +} + +#ifdef CONFIG_PM + +static int omap_rng_suspend(struct platform_device *pdev, pm_message_t message) +{ + omap_rng_write_reg(RNG_MASK_REG, 0x0); + return 0; +} + +static int omap_rng_resume(struct platform_device *pdev) +{ + omap_rng_write_reg(RNG_MASK_REG, 0x1); + return 0; +} + +#else + +#define omap_rng_suspend NULL +#define omap_rng_resume NULL + +#endif + + +static struct platform_driver omap_rng_driver = { + .driver = { + .name = "omap_rng", + .owner = THIS_MODULE, + }, + .probe = omap_rng_probe, + .remove = __exit_p(omap_rng_remove), + .suspend = omap_rng_suspend, + .resume = omap_rng_resume +}; + +static int __init omap_rng_init(void) +{ + if (!cpu_is_omap16xx() && !cpu_is_omap24xx()) + return -ENODEV; + + return platform_driver_register(&omap_rng_driver); +} + +static void __exit omap_rng_exit(void) +{ + platform_driver_unregister(&omap_rng_driver); +} + +module_init(omap_rng_init); +module_exit(omap_rng_exit); + +MODULE_AUTHOR("Deepak Saxena (and others)"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c new file mode 100644 index 000000000..0e786b617 --- /dev/null +++ b/drivers/char/hw_random/via-rng.c @@ -0,0 +1,183 @@ +/* + * RNG driver for VIA RNGs + * + * Copyright 2005 (c) MontaVista Software, Inc. + * + * with the majority of the code coming from: + * + * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) + * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com> + * + * derived from + * + * Hardware driver for the AMD 768 Random Number Generator (RNG) + * (c) Copyright 2001 Red Hat Inc <alan@redhat.com> + * + * derived from + * + * Hardware driver for Intel i810 Random Number Generator (RNG) + * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com> + * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/hw_random.h> +#include <asm/io.h> +#include <asm/msr.h> +#include <asm/cpufeature.h> + + +#define PFX KBUILD_MODNAME ": " + + +enum { + VIA_STRFILT_CNT_SHIFT = 16, + VIA_STRFILT_FAIL = (1 << 15), + VIA_STRFILT_ENABLE = (1 << 14), + VIA_RAWBITS_ENABLE = (1 << 13), + VIA_RNG_ENABLE = (1 << 6), + VIA_XSTORE_CNT_MASK = 0x0F, + + VIA_RNG_CHUNK_8 = 0x00, /* 64 rand bits, 64 stored bits */ + VIA_RNG_CHUNK_4 = 0x01, /* 32 rand bits, 32 stored bits */ + VIA_RNG_CHUNK_4_MASK = 0xFFFFFFFF, + VIA_RNG_CHUNK_2 = 0x02, /* 16 rand bits, 32 stored bits */ + VIA_RNG_CHUNK_2_MASK = 0xFFFF, + VIA_RNG_CHUNK_1 = 0x03, /* 8 rand bits, 32 stored bits */ + VIA_RNG_CHUNK_1_MASK = 0xFF, +}; + +/* + * Investigate using the 'rep' prefix to obtain 32 bits of random data + * in one insn. The upside is potentially better performance. The + * downside is that the instruction becomes no longer atomic. Due to + * this, just like familiar issues with /dev/random itself, the worst + * case of a 'rep xstore' could potentially pause a cpu for an + * unreasonably long time. In practice, this condition would likely + * only occur when the hardware is failing. (or so we hope :)) + * + * Another possible performance boost may come from simply buffering + * until we have 4 bytes, thus returning a u32 at a time, + * instead of the current u8-at-a-time. + */ + +static inline u32 xstore(u32 *addr, u32 edx_in) +{ + u32 eax_out; + + asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */" + :"=m"(*addr), "=a"(eax_out) + :"D"(addr), "d"(edx_in)); + + return eax_out; +} + +static int via_rng_data_present(struct hwrng *rng) +{ + u32 bytes_out; + u32 *via_rng_datum = (u32 *)(&rng->priv); + + /* We choose the recommended 1-byte-per-instruction RNG rate, + * for greater randomness at the expense of speed. Larger + * values 2, 4, or 8 bytes-per-instruction yield greater + * speed at lesser randomness. + * + * If you change this to another VIA_CHUNK_n, you must also + * change the ->n_bytes values in rng_vendor_ops[] tables. + * VIA_CHUNK_8 requires further code changes. + * + * A copy of MSR_VIA_RNG is placed in eax_out when xstore + * completes. + */ + + *via_rng_datum = 0; /* paranoia, not really necessary */ + bytes_out = xstore(via_rng_datum, VIA_RNG_CHUNK_1); + bytes_out &= VIA_XSTORE_CNT_MASK; + if (bytes_out == 0) + return 0; + return 1; +} + +static int via_rng_data_read(struct hwrng *rng, u32 *data) +{ + u32 via_rng_datum = (u32)rng->priv; + + *data = via_rng_datum; + + return 1; +} + +static int via_rng_init(struct hwrng *rng) +{ + u32 lo, hi, old_lo; + + /* Control the RNG via MSR. Tread lightly and pay very close + * close attention to values written, as the reserved fields + * are documented to be "undefined and unpredictable"; but it + * does not say to write them as zero, so I make a guess that + * we restore the values we find in the register. + */ + rdmsr(MSR_VIA_RNG, lo, hi); + + old_lo = lo; + lo &= ~(0x7f << VIA_STRFILT_CNT_SHIFT); + lo &= ~VIA_XSTORE_CNT_MASK; + lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE); + lo |= VIA_RNG_ENABLE; + + if (lo != old_lo) + wrmsr(MSR_VIA_RNG, lo, hi); + + /* perhaps-unnecessary sanity check; remove after testing if + unneeded */ + rdmsr(MSR_VIA_RNG, lo, hi); + if ((lo & VIA_RNG_ENABLE) == 0) { + printk(KERN_ERR PFX "cannot enable VIA C3 RNG, aborting\n"); + return -ENODEV; + } + + return 0; +} + + +static struct hwrng via_rng = { + .name = "via", + .init = via_rng_init, + .data_present = via_rng_data_present, + .data_read = via_rng_data_read, +}; + + +static int __init mod_init(void) +{ + int err; + + if (!cpu_has_xstore) + return -ENODEV; + printk(KERN_INFO "VIA RNG detected\n"); + err = hwrng_register(&via_rng); + if (err) { + printk(KERN_ERR PFX "RNG registering failed (%d)\n", + err); + goto out; + } +out: + return err; +} + +static void __exit mod_exit(void) +{ + hwrng_unregister(&via_rng); +} + +subsys_initcall(mod_init); +module_exit(mod_exit); + +MODULE_DESCRIPTION("H/W RNG driver for VIA chipsets"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/nsc_gpio.c b/drivers/char/nsc_gpio.c new file mode 100644 index 000000000..4d47d79bc --- /dev/null +++ b/drivers/char/nsc_gpio.c @@ -0,0 +1,139 @@ +/* linux/drivers/char/nsc_gpio.c + + National Semiconductor common GPIO device-file/VFS methods. + Allows a user space process to control the GPIO pins. + + Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> + Copyright (c) 2005 Jim Cromie <jim.cromie@gmail.com> +*/ + +#include <linux/fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/nsc_gpio.h> +#include <linux/platform_device.h> +#include <asm/uaccess.h> +#include <asm/io.h> + +#define NAME "nsc_gpio" + +void nsc_gpio_dump(struct nsc_gpio_ops *amp, unsigned index) +{ + /* retrieve current config w/o changing it */ + u32 config = amp->gpio_config(index, ~0, 0); + + /* user requested via 'v' command, so its INFO */ + dev_info(amp->dev, "io%02u: 0x%04x %s %s %s %s %s %s %s\tio:%d/%d\n", + index, config, + (config & 1) ? "OE" : "TS", /* output-enabled/tristate */ + (config & 2) ? "PP" : "OD", /* push pull / open drain */ + (config & 4) ? "PUE" : "PUD", /* pull up enabled/disabled */ + (config & 8) ? "LOCKED" : "", /* locked / unlocked */ + (config & 16) ? "LEVEL" : "EDGE",/* level/edge input */ + (config & 32) ? "HI" : "LO", /* trigger on rise/fall edge */ + (config & 64) ? "DEBOUNCE" : "", /* debounce */ + + amp->gpio_get(index), amp->gpio_current(index)); +} + +ssize_t nsc_gpio_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) +{ + unsigned m = iminor(file->f_dentry->d_inode); + struct nsc_gpio_ops *amp = file->private_data; + struct device *dev = amp->dev; + size_t i; + int err = 0; + + for (i = 0; i < len; ++i) { + char c; + if (get_user(c, data + i)) + return -EFAULT; + switch (c) { + case '0': + amp->gpio_set(m, 0); + break; + case '1': + amp->gpio_set(m, 1); + break; + case 'O': + dev_dbg(dev, "GPIO%d output enabled\n", m); + amp->gpio_config(m, ~1, 1); + break; + case 'o': + dev_dbg(dev, "GPIO%d output disabled\n", m); + amp->gpio_config(m, ~1, 0); + break; + case 'T': + dev_dbg(dev, "GPIO%d output is push pull\n", m); + amp->gpio_config(m, ~2, 2); + break; + case 't': + dev_dbg(dev, "GPIO%d output is open drain\n", m); + amp->gpio_config(m, ~2, 0); + break; + case 'P': + dev_dbg(dev, "GPIO%d pull up enabled\n", m); + amp->gpio_config(m, ~4, 4); + break; + case 'p': + dev_dbg(dev, "GPIO%d pull up disabled\n", m); + amp->gpio_config(m, ~4, 0); + break; + case 'v': + /* View Current pin settings */ + amp->gpio_dump(amp, m); + break; + case '\n': + /* end of settings string, do nothing */ + break; + default: + dev_err(dev, "io%2d bad setting: chr<0x%2x>\n", + m, (int)c); + err++; + } + } + if (err) + return -EINVAL; /* full string handled, report error */ + + return len; +} + +ssize_t nsc_gpio_read(struct file *file, char __user * buf, + size_t len, loff_t * ppos) +{ + unsigned m = iminor(file->f_dentry->d_inode); + int value; + struct nsc_gpio_ops *amp = file->private_data; + + value = amp->gpio_get(m); + if (put_user(value ? '1' : '0', buf)) + return -EFAULT; + + return 1; +} + +/* common file-ops routines for both scx200_gpio and pc87360_gpio */ +EXPORT_SYMBOL(nsc_gpio_write); +EXPORT_SYMBOL(nsc_gpio_read); +EXPORT_SYMBOL(nsc_gpio_dump); + +static int __init nsc_gpio_init(void) +{ + printk(KERN_DEBUG NAME " initializing\n"); + return 0; +} + +static void __exit nsc_gpio_cleanup(void) +{ + printk(KERN_DEBUG NAME " cleanup\n"); +} + +module_init(nsc_gpio_init); +module_exit(nsc_gpio_cleanup); + +MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com>"); +MODULE_DESCRIPTION("NatSemi GPIO Common Methods"); +MODULE_LICENSE("GPL"); diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c new file mode 100644 index 000000000..84e5a6863 --- /dev/null +++ b/drivers/char/pc8736x_gpio.c @@ -0,0 +1,357 @@ +/* linux/drivers/char/pc8736x_gpio.c + + National Semiconductor PC8736x GPIO driver. Allows a user space + process to play with the GPIO pins. + + Copyright (c) 2005,2006 Jim Cromie <jim.cromie@gmail.com> + + adapted from linux/drivers/char/scx200_gpio.c + Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>, +*/ + +#include <linux/fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/cdev.h> +#include <linux/io.h> +#include <linux/ioport.h> +#include <linux/mutex.h> +#include <linux/nsc_gpio.h> +#include <linux/platform_device.h> +#include <asm/uaccess.h> + +#define DEVNAME "pc8736x_gpio" + +MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com>"); +MODULE_DESCRIPTION("NatSemi/Winbond PC-8736x GPIO Pin Driver"); +MODULE_LICENSE("GPL"); + +static int major; /* default to dynamic major */ +module_param(major, int, 0); +MODULE_PARM_DESC(major, "Major device number"); + +static DEFINE_MUTEX(pc8736x_gpio_config_lock); +static unsigned pc8736x_gpio_base; +static u8 pc8736x_gpio_shadow[4]; + +#define SIO_BASE1 0x2E /* 1st command-reg to check */ +#define SIO_BASE2 0x4E /* alt command-reg to check */ + +#define SIO_SID 0x20 /* SuperI/O ID Register */ +#define SIO_SID_VALUE 0xe9 /* Expected value in SuperI/O ID Register */ + +#define SIO_CF1 0x21 /* chip config, bit0 is chip enable */ + +#define PC8736X_GPIO_RANGE 16 /* ioaddr range */ +#define PC8736X_GPIO_CT 32 /* minors matching 4 8 bit ports */ + +#define SIO_UNIT_SEL 0x7 /* unit select reg */ +#define SIO_UNIT_ACT 0x30 /* unit enable */ +#define SIO_GPIO_UNIT 0x7 /* unit number of GPIO */ +#define SIO_VLM_UNIT 0x0D +#define SIO_TMS_UNIT 0x0E + +/* config-space addrs to read/write each unit's runtime addr */ +#define SIO_BASE_HADDR 0x60 +#define SIO_BASE_LADDR 0x61 + +/* GPIO config-space pin-control addresses */ +#define SIO_GPIO_PIN_SELECT 0xF0 +#define SIO_GPIO_PIN_CONFIG 0xF1 +#define SIO_GPIO_PIN_EVENT 0xF2 + +static unsigned char superio_cmd = 0; +static unsigned char selected_device = 0xFF; /* bogus start val */ + +/* GPIO port runtime access, functionality */ +static int port_offset[] = { 0, 4, 8, 10 }; /* non-uniform offsets ! */ +/* static int event_capable[] = { 1, 1, 0, 0 }; ports 2,3 are hobbled */ + +#define PORT_OUT 0 +#define PORT_IN 1 +#define PORT_EVT_EN 2 +#define PORT_EVT_STST 3 + +static struct platform_device *pdev; /* use in dev_*() */ + +static inline void superio_outb(int addr, int val) +{ + outb_p(addr, superio_cmd); + outb_p(val, superio_cmd + 1); +} + +static inline int superio_inb(int addr) +{ + outb_p(addr, superio_cmd); + return inb_p(superio_cmd + 1); +} + +static int pc8736x_superio_present(void) +{ + /* try the 2 possible values, read a hardware reg to verify */ + superio_cmd = SIO_BASE1; + if (superio_inb(SIO_SID) == SIO_SID_VALUE) + return superio_cmd; + + superio_cmd = SIO_BASE2; + if (superio_inb(SIO_SID) == SIO_SID_VALUE) + return superio_cmd; + + return 0; +} + +static void device_select(unsigned devldn) +{ + superio_outb(SIO_UNIT_SEL, devldn); + selected_device = devldn; +} + +static void select_pin(unsigned iminor) +{ + /* select GPIO port/pin from device minor number */ + device_select(SIO_GPIO_UNIT); + superio_outb(SIO_GPIO_PIN_SELECT, + ((iminor << 1) & 0xF0) | (iminor & 0x7)); +} + +static inline u32 pc8736x_gpio_configure_fn(unsigned index, u32 mask, u32 bits, + u32 func_slct) +{ + u32 config, new_config; + + mutex_lock(&pc8736x_gpio_config_lock); + + device_select(SIO_GPIO_UNIT); + select_pin(index); + + /* read current config value */ + config = superio_inb(func_slct); + + /* set new config */ + new_config = (config & mask) | bits; + superio_outb(func_slct, new_config); + + mutex_unlock(&pc8736x_gpio_config_lock); + + return config; +} + +static u32 pc8736x_gpio_configure(unsigned index, u32 mask, u32 bits) +{ + return pc8736x_gpio_configure_fn(index, mask, bits, + SIO_GPIO_PIN_CONFIG); +} + +static int pc8736x_gpio_get(unsigned minor) +{ + int port, bit, val; + + port = minor >> 3; + bit = minor & 7; + val = inb_p(pc8736x_gpio_base + port_offset[port] + PORT_IN); + val >>= bit; + val &= 1; + + dev_dbg(&pdev->dev, "_gpio_get(%d from %x bit %d) == val %d\n", + minor, pc8736x_gpio_base + port_offset[port] + PORT_IN, bit, + val); + + return val; +} + +static void pc8736x_gpio_set(unsigned minor, int val) +{ + int port, bit, curval; + + minor &= 0x1f; + port = minor >> 3; + bit = minor & 7; + curval = inb_p(pc8736x_gpio_base + port_offset[port] + PORT_OUT); + + dev_dbg(&pdev->dev, "addr:%x cur:%x bit-pos:%d cur-bit:%x + new:%d -> bit-new:%d\n", + pc8736x_gpio_base + port_offset[port] + PORT_OUT, + curval, bit, (curval & ~(1 << bit)), val, (val << bit)); + + val = (curval & ~(1 << bit)) | (val << bit); + + dev_dbg(&pdev->dev, "gpio_set(minor:%d port:%d bit:%d)" + " %2x -> %2x\n", minor, port, bit, curval, val); + + outb_p(val, pc8736x_gpio_base + port_offset[port] + PORT_OUT); + + curval = inb_p(pc8736x_gpio_base + port_offset[port] + PORT_OUT); + val = inb_p(pc8736x_gpio_base + port_offset[port] + PORT_IN); + + dev_dbg(&pdev->dev, "wrote %x, read: %x\n", curval, val); + pc8736x_gpio_shadow[port] = val; +} + +static void pc8736x_gpio_set_high(unsigned index) +{ + pc8736x_gpio_set(index, 1); +} + +static void pc8736x_gpio_set_low(unsigned index) +{ + pc8736x_gpio_set(index, 0); +} + +static int pc8736x_gpio_current(unsigned minor) +{ + int port, bit; + minor &= 0x1f; + port = minor >> 3; + bit = minor & 7; + return ((pc8736x_gpio_shadow[port] >> bit) & 0x01); +} + +static void pc8736x_gpio_change(unsigned index) +{ + pc8736x_gpio_set(index, !pc8736x_gpio_current(index)); +} + +static struct nsc_gpio_ops pc8736x_gpio_ops = { + .owner = THIS_MODULE, + .gpio_config = pc8736x_gpio_configure, + .gpio_dump = nsc_gpio_dump, + .gpio_get = pc8736x_gpio_get, + .gpio_set = pc8736x_gpio_set, + .gpio_change = pc8736x_gpio_change, + .gpio_current = pc8736x_gpio_current +}; + +static int pc8736x_gpio_open(struct inode *inode, struct file *file) +{ + unsigned m = iminor(inode); + file->private_data = &pc8736x_gpio_ops; + + dev_dbg(&pdev->dev, "open %d\n", m); + + if (m >= PC8736X_GPIO_CT) + return -EINVAL; + return nonseekable_open(inode, file); +} + +static const struct file_operations pc8736x_gpio_fileops = { + .owner = THIS_MODULE, + .open = pc8736x_gpio_open, + .write = nsc_gpio_write, + .read = nsc_gpio_read, +}; + +static void __init pc8736x_init_shadow(void) +{ + int port; + + /* read the current values driven on the GPIO signals */ + for (port = 0; port < 4; ++port) + pc8736x_gpio_shadow[port] + = inb_p(pc8736x_gpio_base + port_offset[port] + + PORT_OUT); + +} + +static struct cdev pc8736x_gpio_cdev; + +static int __init pc8736x_gpio_init(void) +{ + int rc; + dev_t devid; + + pdev = platform_device_alloc(DEVNAME, 0); + if (!pdev) + return -ENOMEM; + + rc = platform_device_add(pdev); + if (rc) { + rc = -ENODEV; + goto undo_platform_dev_alloc; + } + dev_info(&pdev->dev, "NatSemi pc8736x GPIO Driver Initializing\n"); + + if (!pc8736x_superio_present()) { + rc = -ENODEV; + dev_err(&pdev->dev, "no device found\n"); + goto undo_platform_dev_add; + } + pc8736x_gpio_ops.dev = &pdev->dev; + + /* Verify that chip and it's GPIO unit are both enabled. + My BIOS does this, so I take minimum action here + */ + rc = superio_inb(SIO_CF1); + if (!(rc & 0x01)) { + rc = -ENODEV; + dev_err(&pdev->dev, "device not enabled\n"); + goto undo_platform_dev_add; + } + device_select(SIO_GPIO_UNIT); + if (!superio_inb(SIO_UNIT_ACT)) { + rc = -ENODEV; + dev_err(&pdev->dev, "GPIO unit not enabled\n"); + goto undo_platform_dev_add; + } + + /* read the GPIO unit base addr that chip responds to */ + pc8736x_gpio_base = (superio_inb(SIO_BASE_HADDR) << 8 + | superio_inb(SIO_BASE_LADDR)); + + if (!request_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE, DEVNAME)) { + rc = -ENODEV; + dev_err(&pdev->dev, "GPIO ioport %x busy\n", + pc8736x_gpio_base); + goto undo_platform_dev_add; + } + dev_info(&pdev->dev, "GPIO ioport %x reserved\n", pc8736x_gpio_base); + + if (major) { + devid = MKDEV(major, 0); + rc = register_chrdev_region(devid, PC8736X_GPIO_CT, DEVNAME); + } else { + rc = alloc_chrdev_region(&devid, 0, PC8736X_GPIO_CT, DEVNAME); + major = MAJOR(devid); + } + + if (rc < 0) { + dev_err(&pdev->dev, "register-chrdev failed: %d\n", rc); + goto undo_request_region; + } + if (!major) { + major = rc; + dev_dbg(&pdev->dev, "got dynamic major %d\n", major); + } + + pc8736x_init_shadow(); + + /* ignore minor errs, and succeed */ + cdev_init(&pc8736x_gpio_cdev, &pc8736x_gpio_fileops); + cdev_add(&pc8736x_gpio_cdev, devid, PC8736X_GPIO_CT); + + return 0; + +undo_request_region: + release_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE); +undo_platform_dev_add: + platform_device_del(pdev); +undo_platform_dev_alloc: + platform_device_put(pdev); + + return rc; +} + +static void __exit pc8736x_gpio_cleanup(void) +{ + dev_dbg(&pdev->dev, "cleanup\n"); + + cdev_del(&pc8736x_gpio_cdev); + unregister_chrdev_region(MKDEV(major,0), PC8736X_GPIO_CT); + release_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE); + + platform_device_del(pdev); + platform_device_put(pdev); +} + +module_init(pc8736x_gpio_init); +module_exit(pc8736x_gpio_cleanup); diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile new file mode 100644 index 000000000..a52225470 --- /dev/null +++ b/drivers/clocksource/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o +obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o +obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c new file mode 100644 index 000000000..7ad3be8c0 --- /dev/null +++ b/drivers/clocksource/acpi_pm.c @@ -0,0 +1,177 @@ +/* + * linux/drivers/clocksource/acpi_pm.c + * + * This file contains the ACPI PM based clocksource. + * + * This code was largely moved from the i386 timer_pm.c file + * which was (C) Dominik Brodowski <linux@brodo.de> 2003 + * and contained the following comments: + * + * Driver to use the Power Management Timer (PMTMR) available in some + * southbridges as primary timing source for the Linux kernel. + * + * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c, + * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4. + * + * This file is licensed under the GPL v2. + */ + +#include <linux/clocksource.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <asm/io.h> + +/* Number of PMTMR ticks expected during calibration run */ +#define PMTMR_TICKS_PER_SEC 3579545 + +/* + * The I/O port the PMTMR resides at. + * The location is detected during setup_arch(), + * in arch/i386/acpi/boot.c + */ +u32 pmtmr_ioport __read_mostly; + +#define ACPI_PM_MASK CLOCKSOURCE_MASK(24) /* limit it to 24 bits */ + +static inline u32 read_pmtmr(void) +{ + /* mask the output to 24 bits */ + return inl(pmtmr_ioport) & ACPI_PM_MASK; +} + +static cycle_t acpi_pm_read_verified(void) +{ + u32 v1 = 0, v2 = 0, v3 = 0; + + /* + * It has been reported that because of various broken + * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM clock + * source is not latched, you must read it multiple + * times to ensure a safe value is read: + */ + do { + v1 = read_pmtmr(); + v2 = read_pmtmr(); + v3 = read_pmtmr(); + } while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) + || (v3 > v1 && v3 < v2)); + + return (cycle_t)v2; +} + +static cycle_t acpi_pm_read(void) +{ + return (cycle_t)read_pmtmr(); +} + +static struct clocksource clocksource_acpi_pm = { + .name = "acpi_pm", + .rating = 200, + .read = acpi_pm_read, + .mask = (cycle_t)ACPI_PM_MASK, + .mult = 0, /*to be caluclated*/ + .shift = 22, + .is_continuous = 1, +}; + + +#ifdef CONFIG_PCI +static int acpi_pm_good; +static int __init acpi_pm_good_setup(char *__str) +{ + acpi_pm_good = 1; + return 1; +} +__setup("acpi_pm_good", acpi_pm_good_setup); + +static inline void acpi_pm_need_workaround(void) +{ + clocksource_acpi_pm.read = acpi_pm_read_verified; + clocksource_acpi_pm.rating = 110; +} + +/* + * PIIX4 Errata: + * + * The power management timer may return improper results when read. + * Although the timer value settles properly after incrementing, + * while incrementing there is a 3 ns window every 69.8 ns where the + * timer value is indeterminate (a 4.2% chance that the data will be + * incorrect when read). As a result, the ACPI free running count up + * timer specification is violated due to erroneous reads. + */ +static void __devinit acpi_pm_check_blacklist(struct pci_dev *dev) +{ + u8 rev; + + if (acpi_pm_good) + return; + + pci_read_config_byte(dev, PCI_REVISION_ID, &rev); + /* the bug has been fixed in PIIX4M */ + if (rev < 3) { + printk(KERN_WARNING "* Found PM-Timer Bug on the chipset." + " Due to workarounds for a bug,\n" + "* this clock source is slow. Consider trying" + " other clock sources\n"); + + acpi_pm_need_workaround(); + } +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, + acpi_pm_check_blacklist); + +static void __devinit acpi_pm_check_graylist(struct pci_dev *dev) +{ + if (acpi_pm_good) + return; + + printk(KERN_WARNING "* The chipset may have PM-Timer Bug. Due to" + " workarounds for a bug,\n" + "* this clock source is slow. If you are sure your timer" + " does not have\n" + "* this bug, please use \"acpi_pm_good\" to disable the" + " workaround\n"); + + acpi_pm_need_workaround(); +} +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, + acpi_pm_check_graylist); +#endif + + +static int __init init_acpi_pm_clocksource(void) +{ + u32 value1, value2; + unsigned int i; + + if (!pmtmr_ioport) + return -ENODEV; + + clocksource_acpi_pm.mult = clocksource_hz2mult(PMTMR_TICKS_PER_SEC, + clocksource_acpi_pm.shift); + + /* "verify" this timing source: */ + value1 = read_pmtmr(); + for (i = 0; i < 10000; i++) { + value2 = read_pmtmr(); + if (value2 == value1) + continue; + if (value2 > value1) + goto pm_good; + if ((value2 < value1) && ((value2) < 0xFFF)) + goto pm_good; + printk(KERN_INFO "PM-Timer had inconsistent results:" + " 0x%#x, 0x%#x - aborting.\n", value1, value2); + return -EINVAL; + } + printk(KERN_INFO "PM-Timer had no reasonable result:" + " 0x%#x - aborting.\n", value1); + return -ENODEV; + +pm_good: + return clocksource_register(&clocksource_acpi_pm); +} + +module_init(init_acpi_pm_clocksource); diff --git a/drivers/clocksource/cyclone.c b/drivers/clocksource/cyclone.c new file mode 100644 index 000000000..bf4d3d50d --- /dev/null +++ b/drivers/clocksource/cyclone.c @@ -0,0 +1,119 @@ +#include <linux/clocksource.h> +#include <linux/string.h> +#include <linux/errno.h> +#include <linux/timex.h> +#include <linux/init.h> + +#include <asm/pgtable.h> +#include <asm/io.h> + +#include "mach_timer.h" + +#define CYCLONE_CBAR_ADDR 0xFEB00CD0 /* base address ptr */ +#define CYCLONE_PMCC_OFFSET 0x51A0 /* offset to control register */ +#define CYCLONE_MPCS_OFFSET 0x51A8 /* offset to select register */ +#define CYCLONE_MPMC_OFFSET 0x51D0 /* offset to count register */ +#define CYCLONE_TIMER_FREQ 99780000 /* 100Mhz, but not really */ +#define CYCLONE_TIMER_MASK CLOCKSOURCE_MASK(32) /* 32 bit mask */ + +int use_cyclone = 0; +static void __iomem *cyclone_ptr; + +static cycle_t read_cyclone(void) +{ + return (cycle_t)readl(cyclone_ptr); +} + +static struct clocksource clocksource_cyclone = { + .name = "cyclone", + .rating = 250, + .read = read_cyclone, + .mask = CYCLONE_TIMER_MASK, + .mult = 10, + .shift = 0, + .is_continuous = 1, +}; + +static int __init init_cyclone_clocksource(void) +{ + unsigned long base; /* saved value from CBAR */ + unsigned long offset; + u32 __iomem* volatile cyclone_timer; /* Cyclone MPMC0 register */ + u32 __iomem* reg; + int i; + + /* make sure we're on a summit box: */ + if (!use_cyclone) + return -ENODEV; + + printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n"); + + /* find base address: */ + offset = CYCLONE_CBAR_ADDR; + reg = ioremap_nocache(offset, sizeof(reg)); + if (!reg) { + printk(KERN_ERR "Summit chipset: Could not find valid CBAR register.\n"); + return -ENODEV; + } + /* even on 64bit systems, this is only 32bits: */ + base = readl(reg); + if (!base) { + printk(KERN_ERR "Summit chipset: Could not find valid CBAR value.\n"); + return -ENODEV; + } + iounmap(reg); + + /* setup PMCC: */ + offset = base + CYCLONE_PMCC_OFFSET; + reg = ioremap_nocache(offset, sizeof(reg)); + if (!reg) { + printk(KERN_ERR "Summit chipset: Could not find valid PMCC register.\n"); + return -ENODEV; + } + writel(0x00000001,reg); + iounmap(reg); + + /* setup MPCS: */ + offset = base + CYCLONE_MPCS_OFFSET; + reg = ioremap_nocache(offset, sizeof(reg)); + if (!reg) { + printk(KERN_ERR "Summit chipset: Could not find valid MPCS register.\n"); + return -ENODEV; + } + writel(0x00000001,reg); + iounmap(reg); + + /* map in cyclone_timer: */ + offset = base + CYCLONE_MPMC_OFFSET; + cyclone_timer = ioremap_nocache(offset, sizeof(u64)); + if (!cyclone_timer) { + printk(KERN_ERR "Summit chipset: Could not find valid MPMC register.\n"); + return -ENODEV; + } + + /* quick test to make sure its ticking: */ + for (i = 0; i < 3; i++){ + u32 old = readl(cyclone_timer); + int stall = 100; + + while (stall--) + barrier(); + + if (readl(cyclone_timer) == old) { + printk(KERN_ERR "Summit chipset: Counter not counting! DISABLED\n"); + iounmap(cyclone_timer); + cyclone_timer = NULL; + return -ENODEV; + } + } + cyclone_ptr = cyclone_timer; + + /* sort out mult/shift values: */ + clocksource_cyclone.shift = 22; + clocksource_cyclone.mult = clocksource_hz2mult(CYCLONE_TIMER_FREQ, + clocksource_cyclone.shift); + + return clocksource_register(&clocksource_cyclone); +} + +module_init(init_cyclone_clocksource); diff --git a/drivers/clocksource/scx200_hrt.c b/drivers/clocksource/scx200_hrt.c new file mode 100644 index 000000000..22915cc46 --- /dev/null +++ b/drivers/clocksource/scx200_hrt.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2006 Jim Cromie + * + * This is a clocksource driver for the Geode SCx200's 1 or 27 MHz + * high-resolution timer. The Geode SC-1100 (at least) has a buggy + * time stamp counter (TSC), which loses time unless 'idle=poll' is + * given as a boot-arg. In its absence, the Generic Timekeeping code + * will detect and de-rate the bad TSC, allowing this timer to take + * over timekeeping duties. + * + * Based on work by John Stultz, and Ted Phelps (in a 2.6.12-rc6 patch) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + */ + +#include <linux/clocksource.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/scx200.h> + +#define NAME "scx200_hrt" + +static int mhz27; +module_param(mhz27, int, 0); /* load time only */ +MODULE_PARM_DESC(mhz27, "count at 27.0 MHz (default is 1.0 MHz)"); + +static int ppm; +module_param(ppm, int, 0); /* load time only */ +MODULE_PARM_DESC(ppm, "+-adjust to actual XO freq (ppm)"); + +/* HiRes Timer configuration register address */ +#define SCx200_TMCNFG_OFFSET (SCx200_TIMER_OFFSET + 5) + +/* and config settings */ +#define HR_TMEN (1 << 0) /* timer interrupt enable */ +#define HR_TMCLKSEL (1 << 1) /* 1|0 counts at 27|1 MHz */ +#define HR_TM27MPD (1 << 2) /* 1 turns off input clock (power-down) */ + +/* The base timer frequency, * 27 if selected */ +#define HRT_FREQ 1000000 + +static cycle_t read_hrt(void) +{ + /* Read the timer value */ + return (cycle_t) inl(scx200_cb_base + SCx200_TIMER_OFFSET); +} + +#define HRT_SHIFT_1 22 +#define HRT_SHIFT_27 26 + +static struct clocksource cs_hrt = { + .name = "scx200_hrt", + .rating = 250, + .read = read_hrt, + .mask = CLOCKSOURCE_MASK(32), + .is_continuous = 1, + /* mult, shift are set based on mhz27 flag */ +}; + +static int __init init_hrt_clocksource(void) +{ + /* Make sure scx200 has initialized the configuration block */ + if (!scx200_cb_present()) + return -ENODEV; + + /* Reserve the timer's ISA io-region for ourselves */ + if (!request_region(scx200_cb_base + SCx200_TIMER_OFFSET, + SCx200_TIMER_SIZE, + "NatSemi SCx200 High-Resolution Timer")) { + printk(KERN_WARNING NAME ": unable to lock timer region\n"); + return -ENODEV; + } + + /* write timer config */ + outb(HR_TMEN | (mhz27 ? HR_TMCLKSEL : 0), + scx200_cb_base + SCx200_TMCNFG_OFFSET); + + if (mhz27) { + cs_hrt.shift = HRT_SHIFT_27; + cs_hrt.mult = clocksource_hz2mult((HRT_FREQ + ppm) * 27, + cs_hrt.shift); + } else { + cs_hrt.shift = HRT_SHIFT_1; + cs_hrt.mult = clocksource_hz2mult(HRT_FREQ + ppm, + cs_hrt.shift); + } + printk(KERN_INFO "enabling scx200 high-res timer (%s MHz +%d ppm)\n", + mhz27 ? "27":"1", ppm); + + return clocksource_register(&cs_hrt); +} + +module_init(init_hrt_clocksource); + +MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com>"); +MODULE_DESCRIPTION("clocksource on SCx200 HiRes Timer"); +MODULE_LICENSE("GPL"); diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig new file mode 100644 index 000000000..30d021d1a --- /dev/null +++ b/drivers/dma/Kconfig @@ -0,0 +1,34 @@ +# +# DMA engine configuration +# + +menu "DMA Engine support" + +config DMA_ENGINE + bool "Support for DMA engines" + ---help--- + DMA engines offload copy operations from the CPU to dedicated + hardware, allowing the copies to happen asynchronously. + +comment "DMA Clients" + +config NET_DMA + bool "Network: TCP receive copy offload" + depends on DMA_ENGINE && NET + default y + ---help--- + This enables the use of DMA engines in the network stack to + offload receive copy-to-user operations, freeing CPU cycles. + Since this is the main user of the DMA engine, it should be enabled; + say Y here. + +comment "DMA Devices" + +config INTEL_IOATDMA + tristate "Intel I/OAT DMA support" + depends on DMA_ENGINE && PCI + default m + ---help--- + Enable support for the Intel(R) I/OAT DMA engine. + +endmenu diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile new file mode 100644 index 000000000..bdcfdbdb1 --- /dev/null +++ b/drivers/dma/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_DMA_ENGINE) += dmaengine.o +obj-$(CONFIG_NET_DMA) += iovlock.o +obj-$(CONFIG_INTEL_IOATDMA) += ioatdma.o diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c new file mode 100644 index 000000000..152780442 --- /dev/null +++ b/drivers/dma/dmaengine.c @@ -0,0 +1,412 @@ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + +/* + * This code implements the DMA subsystem. It provides a HW-neutral interface + * for other kernel code to use asynchronous memory copy capabilities, + * if present, and allows different HW DMA drivers to register as providing + * this capability. + * + * Due to the fact we are accelerating what is already a relatively fast + * operation, the code goes to great lengths to avoid additional overhead, + * such as locking. + * + * LOCKING: + * + * The subsystem keeps two global lists, dma_device_list and dma_client_list. + * Both of these are protected by a mutex, dma_list_mutex. + * + * Each device has a channels list, which runs unlocked but is never modified + * once the device is registered, it's just setup by the driver. + * + * Each client has a channels list, it's only modified under the client->lock + * and in an RCU callback, so it's safe to read under rcu_read_lock(). + * + * Each device has a kref, which is initialized to 1 when the device is + * registered. A kref_put is done for each class_device registered. When the + * class_device is released, the coresponding kref_put is done in the release + * method. Every time one of the device's channels is allocated to a client, + * a kref_get occurs. When the channel is freed, the coresponding kref_put + * happens. The device's release function does a completion, so + * unregister_device does a remove event, class_device_unregister, a kref_put + * for the first reference, then waits on the completion for all other + * references to finish. + * + * Each channel has an open-coded implementation of Rusty Russell's "bigref," + * with a kref and a per_cpu local_t. A single reference is set when on an + * ADDED event, and removed with a REMOVE event. Net DMA client takes an + * extra reference per outstanding transaction. The relase function does a + * kref_put on the device. -ChrisL + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/device.h> +#include <linux/dmaengine.h> +#include <linux/hardirq.h> +#include <linux/spinlock.h> +#include <linux/percpu.h> +#include <linux/rcupdate.h> +#include <linux/mutex.h> + +static DEFINE_MUTEX(dma_list_mutex); +static LIST_HEAD(dma_device_list); +static LIST_HEAD(dma_client_list); + +/* --- sysfs implementation --- */ + +static ssize_t show_memcpy_count(struct class_device *cd, char *buf) +{ + struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev); + unsigned long count = 0; + int i; + + for_each_possible_cpu(i) + count += per_cpu_ptr(chan->local, i)->memcpy_count; + + return sprintf(buf, "%lu\n", count); +} + +static ssize_t show_bytes_transferred(struct class_device *cd, char *buf) +{ + struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev); + unsigned long count = 0; + int i; + + for_each_possible_cpu(i) + count += per_cpu_ptr(chan->local, i)->bytes_transferred; + + return sprintf(buf, "%lu\n", count); +} + +static ssize_t show_in_use(struct class_device *cd, char *buf) +{ + struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev); + + return sprintf(buf, "%d\n", (chan->client ? 1 : 0)); +} + +static struct class_device_attribute dma_class_attrs[] = { + __ATTR(memcpy_count, S_IRUGO, show_memcpy_count, NULL), + __ATTR(bytes_transferred, S_IRUGO, show_bytes_transferred, NULL), + __ATTR(in_use, S_IRUGO, show_in_use, NULL), + __ATTR_NULL +}; + +static void dma_async_device_cleanup(struct kref *kref); + +static void dma_class_dev_release(struct class_device *cd) +{ + struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev); + kref_put(&chan->device->refcount, dma_async_device_cleanup); +} + +static struct class dma_devclass = { + .name = "dma", + .class_dev_attrs = dma_class_attrs, + .release = dma_class_dev_release, +}; + +/* --- client and device registration --- */ + +/** + * dma_client_chan_alloc - try to allocate a channel to a client + * @client: &dma_client + * + * Called with dma_list_mutex held. + */ +static struct dma_chan *dma_client_chan_alloc(struct dma_client *client) +{ + struct dma_device *device; + struct dma_chan *chan; + unsigned long flags; + int desc; /* allocated descriptor count */ + + /* Find a channel, any DMA engine will do */ + list_for_each_entry(device, &dma_device_list, global_node) { + list_for_each_entry(chan, &device->channels, device_node) { + if (chan->client) + continue; + + desc = chan->device->device_alloc_chan_resources(chan); + if (desc >= 0) { + kref_get(&device->refcount); + kref_init(&chan->refcount); + chan->slow_ref = 0; + INIT_RCU_HEAD(&chan->rcu); + chan->client = client; + spin_lock_irqsave(&client->lock, flags); + list_add_tail_rcu(&chan->client_node, + &client->channels); + spin_unlock_irqrestore(&client->lock, flags); + return chan; + } + } + } + + return NULL; +} + +/** + * dma_chan_cleanup - release a DMA channel's resources + * @kref: kernel reference structure that contains the DMA channel device + */ +void dma_chan_cleanup(struct kref *kref) +{ + struct dma_chan *chan = container_of(kref, struct dma_chan, refcount); + chan->device->device_free_chan_resources(chan); + chan->client = NULL; + kref_put(&chan->device->refcount, dma_async_device_cleanup); +} + +static void dma_chan_free_rcu(struct rcu_head *rcu) +{ + struct dma_chan *chan = container_of(rcu, struct dma_chan, rcu); + int bias = 0x7FFFFFFF; + int i; + for_each_possible_cpu(i) + bias -= local_read(&per_cpu_ptr(chan->local, i)->refcount); + atomic_sub(bias, &chan->refcount.refcount); + kref_put(&chan->refcount, dma_chan_cleanup); +} + +static void dma_client_chan_free(struct dma_chan *chan) +{ + atomic_add(0x7FFFFFFF, &chan->refcount.refcount); + chan->slow_ref = 1; + call_rcu(&chan->rcu, dma_chan_free_rcu); +} + +/** + * dma_chans_rebalance - reallocate channels to clients + * + * When the number of DMA channel in the system changes, + * channels need to be rebalanced among clients. + */ +static void dma_chans_rebalance(void) +{ + struct dma_client *client; + struct dma_chan *chan; + unsigned long flags; + + mutex_lock(&dma_list_mutex); + + list_for_each_entry(client, &dma_client_list, global_node) { + while (client->chans_desired > client->chan_count) { + chan = dma_client_chan_alloc(client); + if (!chan) + break; + client->chan_count++; + client->event_callback(client, + chan, + DMA_RESOURCE_ADDED); + } + while (client->chans_desired < client->chan_count) { + spin_lock_irqsave(&client->lock, flags); + chan = list_entry(client->channels.next, + struct dma_chan, + client_node); + list_del_rcu(&chan->client_node); + spin_unlock_irqrestore(&client->lock, flags); + client->chan_count--; + client->event_callback(client, + chan, + DMA_RESOURCE_REMOVED); + dma_client_chan_free(chan); + } + } + + mutex_unlock(&dma_list_mutex); +} + +/** + * dma_async_client_register - allocate and register a &dma_client + * @event_callback: callback for notification of channel addition/removal + */ +struct dma_client *dma_async_client_register(dma_event_callback event_callback) +{ + struct dma_client *client; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return NULL; + + INIT_LIST_HEAD(&client->channels); + spin_lock_init(&client->lock); + client->chans_desired = 0; + client->chan_count = 0; + client->event_callback = event_callback; + + mutex_lock(&dma_list_mutex); + list_add_tail(&client->global_node, &dma_client_list); + mutex_unlock(&dma_list_mutex); + + return client; +} + +/** + * dma_async_client_unregister - unregister a client and free the &dma_client + * @client: &dma_client to free + * + * Force frees any allocated DMA channels, frees the &dma_client memory + */ +void dma_async_client_unregister(struct dma_client *client) +{ + struct dma_chan *chan; + + if (!client) + return; + + rcu_read_lock(); + list_for_each_entry_rcu(chan, &client->channels, client_node) + dma_client_chan_free(chan); + rcu_read_unlock(); + + mutex_lock(&dma_list_mutex); + list_del(&client->global_node); + mutex_unlock(&dma_list_mutex); + + kfree(client); + dma_chans_rebalance(); +} + +/** + * dma_async_client_chan_request - request DMA channels + * @client: &dma_client + * @number: count of DMA channels requested + * + * Clients call dma_async_client_chan_request() to specify how many + * DMA channels they need, 0 to free all currently allocated. + * The resulting allocations/frees are indicated to the client via the + * event callback. + */ +void dma_async_client_chan_request(struct dma_client *client, + unsigned int number) +{ + client->chans_desired = number; + dma_chans_rebalance(); +} + +/** + * dma_async_device_register - registers DMA devices found + * @device: &dma_device + */ +int dma_async_device_register(struct dma_device *device) +{ + static int id; + int chancnt = 0; + struct dma_chan* chan; + + if (!device) + return -ENODEV; + + init_completion(&device->done); + kref_init(&device->refcount); + device->dev_id = id++; + + /* represent channels in sysfs. Probably want devs too */ + list_for_each_entry(chan, &device->channels, device_node) { + chan->local = alloc_percpu(typeof(*chan->local)); + if (chan->local == NULL) + continue; + + chan->chan_id = chancnt++; + chan->class_dev.class = &dma_devclass; + chan->class_dev.dev = NULL; + snprintf(chan->class_dev.class_id, BUS_ID_SIZE, "dma%dchan%d", + device->dev_id, chan->chan_id); + + kref_get(&device->refcount); + class_device_register(&chan->class_dev); + } + + mutex_lock(&dma_list_mutex); + list_add_tail(&device->global_node, &dma_device_list); + mutex_unlock(&dma_list_mutex); + + dma_chans_rebalance(); + + return 0; +} + +/** + * dma_async_device_cleanup - function called when all references are released + * @kref: kernel reference object + */ +static void dma_async_device_cleanup(struct kref *kref) +{ + struct dma_device *device; + + device = container_of(kref, struct dma_device, refcount); + complete(&device->done); +} + +/** + * dma_async_device_unregister - unregisters DMA devices + * @device: &dma_device + */ +void dma_async_device_unregister(struct dma_device *device) +{ + struct dma_chan *chan; + unsigned long flags; + + mutex_lock(&dma_list_mutex); + list_del(&device->global_node); + mutex_unlock(&dma_list_mutex); + + list_for_each_entry(chan, &device->channels, device_node) { + if (chan->client) { + spin_lock_irqsave(&chan->client->lock, flags); + list_del(&chan->client_node); + chan->client->chan_count--; + spin_unlock_irqrestore(&chan->client->lock, flags); + chan->client->event_callback(chan->client, + chan, + DMA_RESOURCE_REMOVED); + dma_client_chan_free(chan); + } + class_device_unregister(&chan->class_dev); + } + dma_chans_rebalance(); + + kref_put(&device->refcount, dma_async_device_cleanup); + wait_for_completion(&device->done); +} + +static int __init dma_bus_init(void) +{ + mutex_init(&dma_list_mutex); + return class_register(&dma_devclass); +} + +subsys_initcall(dma_bus_init); + +EXPORT_SYMBOL(dma_async_client_register); +EXPORT_SYMBOL(dma_async_client_unregister); +EXPORT_SYMBOL(dma_async_client_chan_request); +EXPORT_SYMBOL(dma_async_memcpy_buf_to_buf); +EXPORT_SYMBOL(dma_async_memcpy_buf_to_pg); +EXPORT_SYMBOL(dma_async_memcpy_pg_to_pg); +EXPORT_SYMBOL(dma_async_memcpy_complete); +EXPORT_SYMBOL(dma_async_memcpy_issue_pending); +EXPORT_SYMBOL(dma_async_device_register); +EXPORT_SYMBOL(dma_async_device_unregister); +EXPORT_SYMBOL(dma_chan_cleanup); diff --git a/drivers/dma/ioatdma.c b/drivers/dma/ioatdma.c new file mode 100644 index 000000000..dbd4d6c36 --- /dev/null +++ b/drivers/dma/ioatdma.c @@ -0,0 +1,841 @@ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + +/* + * This driver supports an Intel I/OAT DMA engine, which does asynchronous + * copy operations. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/interrupt.h> +#include <linux/dmaengine.h> +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include "ioatdma.h" +#include "ioatdma_io.h" +#include "ioatdma_registers.h" +#include "ioatdma_hw.h" + +#define to_ioat_chan(chan) container_of(chan, struct ioat_dma_chan, common) +#define to_ioat_device(dev) container_of(dev, struct ioat_device, common) +#define to_ioat_desc(lh) container_of(lh, struct ioat_desc_sw, node) + +/* internal functions */ +static int __devinit ioat_probe(struct pci_dev *pdev, const struct pci_device_id *ent); +static void __devexit ioat_remove(struct pci_dev *pdev); + +static int enumerate_dma_channels(struct ioat_device *device) +{ + u8 xfercap_scale; + u32 xfercap; + int i; + struct ioat_dma_chan *ioat_chan; + + device->common.chancnt = ioatdma_read8(device, IOAT_CHANCNT_OFFSET); + xfercap_scale = ioatdma_read8(device, IOAT_XFERCAP_OFFSET); + xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale)); + + for (i = 0; i < device->common.chancnt; i++) { + ioat_chan = kzalloc(sizeof(*ioat_chan), GFP_KERNEL); + if (!ioat_chan) { + device->common.chancnt = i; + break; + } + + ioat_chan->device = device; + ioat_chan->reg_base = device->reg_base + (0x80 * (i + 1)); + ioat_chan->xfercap = xfercap; + spin_lock_init(&ioat_chan->cleanup_lock); + spin_lock_init(&ioat_chan->desc_lock); + INIT_LIST_HEAD(&ioat_chan->free_desc); + INIT_LIST_HEAD(&ioat_chan->used_desc); + /* This should be made common somewhere in dmaengine.c */ + ioat_chan->common.device = &device->common; + ioat_chan->common.client = NULL; + list_add_tail(&ioat_chan->common.device_node, + &device->common.channels); + } + return device->common.chancnt; +} + +static struct ioat_desc_sw *ioat_dma_alloc_descriptor( + struct ioat_dma_chan *ioat_chan, + int flags) +{ + struct ioat_dma_descriptor *desc; + struct ioat_desc_sw *desc_sw; + struct ioat_device *ioat_device; + dma_addr_t phys; + + ioat_device = to_ioat_device(ioat_chan->common.device); + desc = pci_pool_alloc(ioat_device->dma_pool, flags, &phys); + if (unlikely(!desc)) + return NULL; + + desc_sw = kzalloc(sizeof(*desc_sw), flags); + if (unlikely(!desc_sw)) { + pci_pool_free(ioat_device->dma_pool, desc, phys); + return NULL; + } + + memset(desc, 0, sizeof(*desc)); + desc_sw->hw = desc; + desc_sw->phys = phys; + + return desc_sw; +} + +#define INITIAL_IOAT_DESC_COUNT 128 + +static void ioat_start_null_desc(struct ioat_dma_chan *ioat_chan); + +/* returns the actual number of allocated descriptors */ +static int ioat_dma_alloc_chan_resources(struct dma_chan *chan) +{ + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + struct ioat_desc_sw *desc = NULL; + u16 chanctrl; + u32 chanerr; + int i; + LIST_HEAD(tmp_list); + + /* + * In-use bit automatically set by reading chanctrl + * If 0, we got it, if 1, someone else did + */ + chanctrl = ioatdma_chan_read16(ioat_chan, IOAT_CHANCTRL_OFFSET); + if (chanctrl & IOAT_CHANCTRL_CHANNEL_IN_USE) + return -EBUSY; + + /* Setup register to interrupt and write completion status on error */ + chanctrl = IOAT_CHANCTRL_CHANNEL_IN_USE | + IOAT_CHANCTRL_ERR_INT_EN | + IOAT_CHANCTRL_ANY_ERR_ABORT_EN | + IOAT_CHANCTRL_ERR_COMPLETION_EN; + ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl); + + chanerr = ioatdma_chan_read32(ioat_chan, IOAT_CHANERR_OFFSET); + if (chanerr) { + printk("IOAT: CHANERR = %x, clearing\n", chanerr); + ioatdma_chan_write32(ioat_chan, IOAT_CHANERR_OFFSET, chanerr); + } + + /* Allocate descriptors */ + for (i = 0; i < INITIAL_IOAT_DESC_COUNT; i++) { + desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL); + if (!desc) { + printk(KERN_ERR "IOAT: Only %d initial descriptors\n", i); + break; + } + list_add_tail(&desc->node, &tmp_list); + } + spin_lock_bh(&ioat_chan->desc_lock); + list_splice(&tmp_list, &ioat_chan->free_desc); + spin_unlock_bh(&ioat_chan->desc_lock); + + /* allocate a completion writeback area */ + /* doing 2 32bit writes to mmio since 1 64b write doesn't work */ + ioat_chan->completion_virt = + pci_pool_alloc(ioat_chan->device->completion_pool, + GFP_KERNEL, + &ioat_chan->completion_addr); + memset(ioat_chan->completion_virt, 0, + sizeof(*ioat_chan->completion_virt)); + ioatdma_chan_write32(ioat_chan, IOAT_CHANCMP_OFFSET_LOW, + ((u64) ioat_chan->completion_addr) & 0x00000000FFFFFFFF); + ioatdma_chan_write32(ioat_chan, IOAT_CHANCMP_OFFSET_HIGH, + ((u64) ioat_chan->completion_addr) >> 32); + + ioat_start_null_desc(ioat_chan); + return i; +} + +static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan); + +static void ioat_dma_free_chan_resources(struct dma_chan *chan) +{ + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + struct ioat_device *ioat_device = to_ioat_device(chan->device); + struct ioat_desc_sw *desc, *_desc; + u16 chanctrl; + int in_use_descs = 0; + + ioat_dma_memcpy_cleanup(ioat_chan); + + ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_RESET); + + spin_lock_bh(&ioat_chan->desc_lock); + list_for_each_entry_safe(desc, _desc, &ioat_chan->used_desc, node) { + in_use_descs++; + list_del(&desc->node); + pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys); + kfree(desc); + } + list_for_each_entry_safe(desc, _desc, &ioat_chan->free_desc, node) { + list_del(&desc->node); + pci_pool_free(ioat_device->dma_pool, desc->hw, desc->phys); + kfree(desc); + } + spin_unlock_bh(&ioat_chan->desc_lock); + + pci_pool_free(ioat_device->completion_pool, + ioat_chan->completion_virt, + ioat_chan->completion_addr); + + /* one is ok since we left it on there on purpose */ + if (in_use_descs > 1) + printk(KERN_ERR "IOAT: Freeing %d in use descriptors!\n", + in_use_descs - 1); + + ioat_chan->last_completion = ioat_chan->completion_addr = 0; + + /* Tell hw the chan is free */ + chanctrl = ioatdma_chan_read16(ioat_chan, IOAT_CHANCTRL_OFFSET); + chanctrl &= ~IOAT_CHANCTRL_CHANNEL_IN_USE; + ioatdma_chan_write16(ioat_chan, IOAT_CHANCTRL_OFFSET, chanctrl); +} + +/** + * do_ioat_dma_memcpy - actual function that initiates a IOAT DMA transaction + * @ioat_chan: IOAT DMA channel handle + * @dest: DMA destination address + * @src: DMA source address + * @len: transaction length in bytes + */ + +static dma_cookie_t do_ioat_dma_memcpy(struct ioat_dma_chan *ioat_chan, + dma_addr_t dest, + dma_addr_t src, + size_t len) +{ + struct ioat_desc_sw *first; + struct ioat_desc_sw *prev; + struct ioat_desc_sw *new; + dma_cookie_t cookie; + LIST_HEAD(new_chain); + u32 copy; + size_t orig_len; + dma_addr_t orig_src, orig_dst; + unsigned int desc_count = 0; + unsigned int append = 0; + + if (!ioat_chan || !dest || !src) + return -EFAULT; + + if (!len) + return ioat_chan->common.cookie; + + orig_len = len; + orig_src = src; + orig_dst = dest; + + first = NULL; + prev = NULL; + + spin_lock_bh(&ioat_chan->desc_lock); + + while (len) { + if (!list_empty(&ioat_chan->free_desc)) { + new = to_ioat_desc(ioat_chan->free_desc.next); + list_del(&new->node); + } else { + /* try to get another desc */ + new = ioat_dma_alloc_descriptor(ioat_chan, GFP_ATOMIC); + /* will this ever happen? */ + /* TODO add upper limit on these */ + BUG_ON(!new); + } + + copy = min((u32) len, ioat_chan->xfercap); + + new->hw->size = copy; + new->hw->ctl = 0; + new->hw->src_addr = src; + new->hw->dst_addr = dest; + new->cookie = 0; + + /* chain together the physical address list for the HW */ + if (!first) + first = new; + else + prev->hw->next = (u64) new->phys; + + prev = new; + + len -= copy; + dest += copy; + src += copy; + + list_add_tail(&new->node, &new_chain); + desc_count++; + } + new->hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS; + new->hw->next = 0; + + /* cookie incr and addition to used_list must be atomic */ + + cookie = ioat_chan->common.cookie; + cookie++; + if (cookie < 0) + cookie = 1; + ioat_chan->common.cookie = new->cookie = cookie; + + pci_unmap_addr_set(new, src, orig_src); + pci_unmap_addr_set(new, dst, orig_dst); + pci_unmap_len_set(new, src_len, orig_len); + pci_unmap_len_set(new, dst_len, orig_len); + + /* write address into NextDescriptor field of last desc in chain */ + to_ioat_desc(ioat_chan->used_desc.prev)->hw->next = first->phys; + list_splice_init(&new_chain, ioat_chan->used_desc.prev); + + ioat_chan->pending += desc_count; + if (ioat_chan->pending >= 20) { + append = 1; + ioat_chan->pending = 0; + } + + spin_unlock_bh(&ioat_chan->desc_lock); + + if (append) + ioatdma_chan_write8(ioat_chan, + IOAT_CHANCMD_OFFSET, + IOAT_CHANCMD_APPEND); + return cookie; +} + +/** + * ioat_dma_memcpy_buf_to_buf - wrapper that takes src & dest bufs + * @chan: IOAT DMA channel handle + * @dest: DMA destination address + * @src: DMA source address + * @len: transaction length in bytes + */ + +static dma_cookie_t ioat_dma_memcpy_buf_to_buf(struct dma_chan *chan, + void *dest, + void *src, + size_t len) +{ + dma_addr_t dest_addr; + dma_addr_t src_addr; + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + + dest_addr = pci_map_single(ioat_chan->device->pdev, + dest, len, PCI_DMA_FROMDEVICE); + src_addr = pci_map_single(ioat_chan->device->pdev, + src, len, PCI_DMA_TODEVICE); + + return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len); +} + +/** + * ioat_dma_memcpy_buf_to_pg - wrapper, copying from a buf to a page + * @chan: IOAT DMA channel handle + * @page: pointer to the page to copy to + * @offset: offset into that page + * @src: DMA source address + * @len: transaction length in bytes + */ + +static dma_cookie_t ioat_dma_memcpy_buf_to_pg(struct dma_chan *chan, + struct page *page, + unsigned int offset, + void *src, + size_t len) +{ + dma_addr_t dest_addr; + dma_addr_t src_addr; + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + + dest_addr = pci_map_page(ioat_chan->device->pdev, + page, offset, len, PCI_DMA_FROMDEVICE); + src_addr = pci_map_single(ioat_chan->device->pdev, + src, len, PCI_DMA_TODEVICE); + + return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len); +} + +/** + * ioat_dma_memcpy_pg_to_pg - wrapper, copying between two pages + * @chan: IOAT DMA channel handle + * @dest_pg: pointer to the page to copy to + * @dest_off: offset into that page + * @src_pg: pointer to the page to copy from + * @src_off: offset into that page + * @len: transaction length in bytes. This is guaranteed not to make a copy + * across a page boundary. + */ + +static dma_cookie_t ioat_dma_memcpy_pg_to_pg(struct dma_chan *chan, + struct page *dest_pg, + unsigned int dest_off, + struct page *src_pg, + unsigned int src_off, + size_t len) +{ + dma_addr_t dest_addr; + dma_addr_t src_addr; + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + + dest_addr = pci_map_page(ioat_chan->device->pdev, + dest_pg, dest_off, len, PCI_DMA_FROMDEVICE); + src_addr = pci_map_page(ioat_chan->device->pdev, + src_pg, src_off, len, PCI_DMA_TODEVICE); + + return do_ioat_dma_memcpy(ioat_chan, dest_addr, src_addr, len); +} + +/** + * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended descriptors to hw + * @chan: DMA channel handle + */ + +static void ioat_dma_memcpy_issue_pending(struct dma_chan *chan) +{ + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + + if (ioat_chan->pending != 0) { + ioat_chan->pending = 0; + ioatdma_chan_write8(ioat_chan, + IOAT_CHANCMD_OFFSET, + IOAT_CHANCMD_APPEND); + } +} + +static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *chan) +{ + unsigned long phys_complete; + struct ioat_desc_sw *desc, *_desc; + dma_cookie_t cookie = 0; + + prefetch(chan->completion_virt); + + if (!spin_trylock(&chan->cleanup_lock)) + return; + + /* The completion writeback can happen at any time, + so reads by the driver need to be atomic operations + The descriptor physical addresses are limited to 32-bits + when the CPU can only do a 32-bit mov */ + +#if (BITS_PER_LONG == 64) + phys_complete = + chan->completion_virt->full & IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR; +#else + phys_complete = chan->completion_virt->low & IOAT_LOW_COMPLETION_MASK; +#endif + + if ((chan->completion_virt->full & IOAT_CHANSTS_DMA_TRANSFER_STATUS) == + IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED) { + printk("IOAT: Channel halted, chanerr = %x\n", + ioatdma_chan_read32(chan, IOAT_CHANERR_OFFSET)); + + /* TODO do something to salvage the situation */ + } + + if (phys_complete == chan->last_completion) { + spin_unlock(&chan->cleanup_lock); + return; + } + + spin_lock_bh(&chan->desc_lock); + list_for_each_entry_safe(desc, _desc, &chan->used_desc, node) { + + /* + * Incoming DMA requests may use multiple descriptors, due to + * exceeding xfercap, perhaps. If so, only the last one will + * have a cookie, and require unmapping. + */ + if (desc->cookie) { + cookie = desc->cookie; + + /* yes we are unmapping both _page and _single alloc'd + regions with unmap_page. Is this *really* that bad? + */ + pci_unmap_page(chan->device->pdev, + pci_unmap_addr(desc, dst), + pci_unmap_len(desc, dst_len), + PCI_DMA_FROMDEVICE); + pci_unmap_page(chan->device->pdev, + pci_unmap_addr(desc, src), + pci_unmap_len(desc, src_len), + PCI_DMA_TODEVICE); + } + + if (desc->phys != phys_complete) { + /* a completed entry, but not the last, so cleanup */ + list_del(&desc->node); + list_add_tail(&desc->node, &chan->free_desc); + } else { + /* last used desc. Do not remove, so we can append from + it, but don't look at it next time, either */ + desc->cookie = 0; + + /* TODO check status bits? */ + break; + } + } + + spin_unlock_bh(&chan->desc_lock); + + chan->last_completion = phys_complete; + if (cookie != 0) + chan->completed_cookie = cookie; + + spin_unlock(&chan->cleanup_lock); +} + +/** + * ioat_dma_is_complete - poll the status of a IOAT DMA transaction + * @chan: IOAT DMA channel handle + * @cookie: DMA transaction identifier + * @done: if not %NULL, updated with last completed transaction + * @used: if not %NULL, updated with last used transaction + */ + +static enum dma_status ioat_dma_is_complete(struct dma_chan *chan, + dma_cookie_t cookie, + dma_cookie_t *done, + dma_cookie_t *used) +{ + struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); + dma_cookie_t last_used; + dma_cookie_t last_complete; + enum dma_status ret; + + last_used = chan->cookie; + last_complete = ioat_chan->completed_cookie; + + if (done) + *done= last_complete; + if (used) + *used = last_used; + + ret = dma_async_is_complete(cookie, last_complete, last_used); + if (ret == DMA_SUCCESS) + return ret; + + ioat_dma_memcpy_cleanup(ioat_chan); + + last_used = chan->cookie; + last_complete = ioat_chan->completed_cookie; + + if (done) + *done= last_complete; + if (used) + *used = last_used; + + return dma_async_is_complete(cookie, last_complete, last_used); +} + +/* PCI API */ + +static struct pci_device_id ioat_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT) }, + { 0, } +}; + +static struct pci_driver ioat_pci_drv = { + .name = "ioatdma", + .id_table = ioat_pci_tbl, + .probe = ioat_probe, + .remove = __devexit_p(ioat_remove), +}; + +static irqreturn_t ioat_do_interrupt(int irq, void *data, struct pt_regs *regs) +{ + struct ioat_device *instance = data; + unsigned long attnstatus; + u8 intrctrl; + + intrctrl = ioatdma_read8(instance, IOAT_INTRCTRL_OFFSET); + + if (!(intrctrl & IOAT_INTRCTRL_MASTER_INT_EN)) + return IRQ_NONE; + + if (!(intrctrl & IOAT_INTRCTRL_INT_STATUS)) { + ioatdma_write8(instance, IOAT_INTRCTRL_OFFSET, intrctrl); + return IRQ_NONE; + } + + attnstatus = ioatdma_read32(instance, IOAT_ATTNSTATUS_OFFSET); + + printk(KERN_ERR "ioatdma error: interrupt! status %lx\n", attnstatus); + + ioatdma_write8(instance, IOAT_INTRCTRL_OFFSET, intrctrl); + return IRQ_HANDLED; +} + +static void ioat_start_null_desc(struct ioat_dma_chan *ioat_chan) +{ + struct ioat_desc_sw *desc; + + spin_lock_bh(&ioat_chan->desc_lock); + + if (!list_empty(&ioat_chan->free_desc)) { + desc = to_ioat_desc(ioat_chan->free_desc.next); + list_del(&desc->node); + } else { + /* try to get another desc */ + spin_unlock_bh(&ioat_chan->desc_lock); + desc = ioat_dma_alloc_descriptor(ioat_chan, GFP_KERNEL); + spin_lock_bh(&ioat_chan->desc_lock); + /* will this ever happen? */ + BUG_ON(!desc); + } + + desc->hw->ctl = IOAT_DMA_DESCRIPTOR_NUL; + desc->hw->next = 0; + + list_add_tail(&desc->node, &ioat_chan->used_desc); + spin_unlock_bh(&ioat_chan->desc_lock); + +#if (BITS_PER_LONG == 64) + ioatdma_chan_write64(ioat_chan, IOAT_CHAINADDR_OFFSET, desc->phys); +#else + ioatdma_chan_write32(ioat_chan, + IOAT_CHAINADDR_OFFSET_LOW, + (u32) desc->phys); + ioatdma_chan_write32(ioat_chan, IOAT_CHAINADDR_OFFSET_HIGH, 0); +#endif + ioatdma_chan_write8(ioat_chan, IOAT_CHANCMD_OFFSET, IOAT_CHANCMD_START); +} + +/* + * Perform a IOAT transaction to verify the HW works. + */ +#define IOAT_TEST_SIZE 2000 + +static int ioat_self_test(struct ioat_device *device) +{ + int i; + u8 *src; + u8 *dest; + struct dma_chan *dma_chan; + dma_cookie_t cookie; + int err = 0; + + src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, SLAB_KERNEL); + if (!src) + return -ENOMEM; + dest = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, SLAB_KERNEL); + if (!dest) { + kfree(src); + return -ENOMEM; + } + + /* Fill in src buffer */ + for (i = 0; i < IOAT_TEST_SIZE; i++) + src[i] = (u8)i; + + /* Start copy, using first DMA channel */ + dma_chan = container_of(device->common.channels.next, + struct dma_chan, + device_node); + if (ioat_dma_alloc_chan_resources(dma_chan) < 1) { + err = -ENODEV; + goto out; + } + + cookie = ioat_dma_memcpy_buf_to_buf(dma_chan, dest, src, IOAT_TEST_SIZE); + ioat_dma_memcpy_issue_pending(dma_chan); + msleep(1); + + if (ioat_dma_is_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) { + printk(KERN_ERR "ioatdma: Self-test copy timed out, disabling\n"); + err = -ENODEV; + goto free_resources; + } + if (memcmp(src, dest, IOAT_TEST_SIZE)) { + printk(KERN_ERR "ioatdma: Self-test copy failed compare, disabling\n"); + err = -ENODEV; + goto free_resources; + } + +free_resources: + ioat_dma_free_chan_resources(dma_chan); +out: + kfree(src); + kfree(dest); + return err; +} + +static int __devinit ioat_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + int err; + unsigned long mmio_start, mmio_len; + void *reg_base; + struct ioat_device *device; + + err = pci_enable_device(pdev); + if (err) + goto err_enable_device; + + err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); + if (err) + err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (err) + goto err_set_dma_mask; + + err = pci_request_regions(pdev, ioat_pci_drv.name); + if (err) + goto err_request_regions; + + mmio_start = pci_resource_start(pdev, 0); + mmio_len = pci_resource_len(pdev, 0); + + reg_base = ioremap(mmio_start, mmio_len); + if (!reg_base) { + err = -ENOMEM; + goto err_ioremap; + } + + device = kzalloc(sizeof(*device), GFP_KERNEL); + if (!device) { + err = -ENOMEM; + goto err_kzalloc; + } + + /* DMA coherent memory pool for DMA descriptor allocations */ + device->dma_pool = pci_pool_create("dma_desc_pool", pdev, + sizeof(struct ioat_dma_descriptor), 64, 0); + if (!device->dma_pool) { + err = -ENOMEM; + goto err_dma_pool; + } + + device->completion_pool = pci_pool_create("completion_pool", pdev, sizeof(u64), SMP_CACHE_BYTES, SMP_CACHE_BYTES); + if (!device->completion_pool) { + err = -ENOMEM; + goto err_completion_pool; + } + + device->pdev = pdev; + pci_set_drvdata(pdev, device); +#ifdef CONFIG_PCI_MSI + if (pci_enable_msi(pdev) == 0) { + device->msi = 1; + } else { + device->msi = 0; + } +#endif + err = request_irq(pdev->irq, &ioat_do_interrupt, IRQF_SHARED, "ioat", + device); + if (err) + goto err_irq; + + device->reg_base = reg_base; + + ioatdma_write8(device, IOAT_INTRCTRL_OFFSET, IOAT_INTRCTRL_MASTER_INT_EN); + pci_set_master(pdev); + + INIT_LIST_HEAD(&device->common.channels); + enumerate_dma_channels(device); + + device->common.device_alloc_chan_resources = ioat_dma_alloc_chan_resources; + device->common.device_free_chan_resources = ioat_dma_free_chan_resources; + device->common.device_memcpy_buf_to_buf = ioat_dma_memcpy_buf_to_buf; + device->common.device_memcpy_buf_to_pg = ioat_dma_memcpy_buf_to_pg; + device->common.device_memcpy_pg_to_pg = ioat_dma_memcpy_pg_to_pg; + device->common.device_memcpy_complete = ioat_dma_is_complete; + device->common.device_memcpy_issue_pending = ioat_dma_memcpy_issue_pending; + printk(KERN_INFO "Intel(R) I/OAT DMA Engine found, %d channels\n", + device->common.chancnt); + + err = ioat_self_test(device); + if (err) + goto err_self_test; + + dma_async_device_register(&device->common); + + return 0; + +err_self_test: +err_irq: + pci_pool_destroy(device->completion_pool); +err_completion_pool: + pci_pool_destroy(device->dma_pool); +err_dma_pool: + kfree(device); +err_kzalloc: + iounmap(reg_base); +err_ioremap: + pci_release_regions(pdev); +err_request_regions: +err_set_dma_mask: + pci_disable_device(pdev); +err_enable_device: + return err; +} + +static void __devexit ioat_remove(struct pci_dev *pdev) +{ + struct ioat_device *device; + struct dma_chan *chan, *_chan; + struct ioat_dma_chan *ioat_chan; + + device = pci_get_drvdata(pdev); + dma_async_device_unregister(&device->common); + + free_irq(device->pdev->irq, device); +#ifdef CONFIG_PCI_MSI + if (device->msi) + pci_disable_msi(device->pdev); +#endif + pci_pool_destroy(device->dma_pool); + pci_pool_destroy(device->completion_pool); + iounmap(device->reg_base); + pci_release_regions(pdev); + pci_disable_device(pdev); + list_for_each_entry_safe(chan, _chan, &device->common.channels, device_node) { + ioat_chan = to_ioat_chan(chan); + list_del(&chan->device_node); + kfree(ioat_chan); + } + kfree(device); +} + +/* MODULE API */ +MODULE_VERSION("1.7"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Intel Corporation"); + +static int __init ioat_init_module(void) +{ + /* it's currently unsafe to unload this module */ + /* if forced, worst case is that rmmod hangs */ + __unsafe(THIS_MODULE); + + return pci_register_driver(&ioat_pci_drv); +} + +module_init(ioat_init_module); + +static void __exit ioat_exit_module(void) +{ + pci_unregister_driver(&ioat_pci_drv); +} + +module_exit(ioat_exit_module); diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h new file mode 100644 index 000000000..a5d3b3644 --- /dev/null +++ b/drivers/dma/ioatdma.h @@ -0,0 +1,125 @@ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ +#ifndef IOATDMA_H +#define IOATDMA_H + +#include <linux/dmaengine.h> +#include "ioatdma_hw.h" +#include <linux/init.h> +#include <linux/dmapool.h> +#include <linux/cache.h> +#include <linux/pci_ids.h> + +#define IOAT_LOW_COMPLETION_MASK 0xffffffc0 + +extern struct list_head dma_device_list; +extern struct list_head dma_client_list; + +/** + * struct ioat_device - internal representation of a IOAT device + * @pdev: PCI-Express device + * @reg_base: MMIO register space base address + * @dma_pool: for allocating DMA descriptors + * @common: embedded struct dma_device + * @msi: Message Signaled Interrupt number + */ + +struct ioat_device { + struct pci_dev *pdev; + void *reg_base; + struct pci_pool *dma_pool; + struct pci_pool *completion_pool; + + struct dma_device common; + u8 msi; +}; + +/** + * struct ioat_dma_chan - internal representation of a DMA channel + * @device: + * @reg_base: + * @sw_in_use: + * @completion: + * @completion_low: + * @completion_high: + * @completed_cookie: last cookie seen completed on cleanup + * @cookie: value of last cookie given to client + * @last_completion: + * @xfercap: + * @desc_lock: + * @free_desc: + * @used_desc: + * @resource: + * @device_node: + */ + +struct ioat_dma_chan { + + void *reg_base; + + dma_cookie_t completed_cookie; + unsigned long last_completion; + + u32 xfercap; /* XFERCAP register value expanded out */ + + spinlock_t cleanup_lock; + spinlock_t desc_lock; + struct list_head free_desc; + struct list_head used_desc; + + int pending; + + struct ioat_device *device; + struct dma_chan common; + + dma_addr_t completion_addr; + union { + u64 full; /* HW completion writeback */ + struct { + u32 low; + u32 high; + }; + } *completion_virt; +}; + +/* wrapper around hardware descriptor format + additional software fields */ + +/** + * struct ioat_desc_sw - wrapper around hardware descriptor + * @hw: hardware DMA descriptor + * @node: + * @cookie: + * @phys: + */ + +struct ioat_desc_sw { + struct ioat_dma_descriptor *hw; + struct list_head node; + dma_cookie_t cookie; + dma_addr_t phys; + DECLARE_PCI_UNMAP_ADDR(src) + DECLARE_PCI_UNMAP_LEN(src_len) + DECLARE_PCI_UNMAP_ADDR(dst) + DECLARE_PCI_UNMAP_LEN(dst_len) +}; + +#endif /* IOATDMA_H */ + diff --git a/drivers/dma/ioatdma_hw.h b/drivers/dma/ioatdma_hw.h new file mode 100644 index 000000000..4d7a12880 --- /dev/null +++ b/drivers/dma/ioatdma_hw.h @@ -0,0 +1,52 @@ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ +#ifndef _IOAT_HW_H_ +#define _IOAT_HW_H_ + +/* PCI Configuration Space Values */ +#define IOAT_PCI_VID 0x8086 +#define IOAT_PCI_DID 0x1A38 +#define IOAT_PCI_RID 0x00 +#define IOAT_PCI_SVID 0x8086 +#define IOAT_PCI_SID 0x8086 +#define IOAT_VER 0x12 /* Version 1.2 */ + +struct ioat_dma_descriptor { + uint32_t size; + uint32_t ctl; + uint64_t src_addr; + uint64_t dst_addr; + uint64_t next; + uint64_t rsv1; + uint64_t rsv2; + uint64_t user1; + uint64_t user2; +}; + +#define IOAT_DMA_DESCRIPTOR_CTL_INT_GN 0x00000001 +#define IOAT_DMA_DESCRIPTOR_CTL_SRC_SN 0x00000002 +#define IOAT_DMA_DESCRIPTOR_CTL_DST_SN 0x00000004 +#define IOAT_DMA_DESCRIPTOR_CTL_CP_STS 0x00000008 +#define IOAT_DMA_DESCRIPTOR_CTL_FRAME 0x00000010 +#define IOAT_DMA_DESCRIPTOR_NUL 0x00000020 +#define IOAT_DMA_DESCRIPTOR_OPCODE 0xFF000000 + +#endif diff --git a/drivers/dma/ioatdma_io.h b/drivers/dma/ioatdma_io.h new file mode 100644 index 000000000..c0b4bf66c --- /dev/null +++ b/drivers/dma/ioatdma_io.h @@ -0,0 +1,118 @@ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ +#ifndef IOATDMA_IO_H +#define IOATDMA_IO_H + +#include <asm/io.h> + +/* + * device and per-channel MMIO register read and write functions + * this is a lot of anoying inline functions, but it's typesafe + */ + +static inline u8 ioatdma_read8(struct ioat_device *device, + unsigned int offset) +{ + return readb(device->reg_base + offset); +} + +static inline u16 ioatdma_read16(struct ioat_device *device, + unsigned int offset) +{ + return readw(device->reg_base + offset); +} + +static inline u32 ioatdma_read32(struct ioat_device *device, + unsigned int offset) +{ + return readl(device->reg_base + offset); +} + +static inline void ioatdma_write8(struct ioat_device *device, + unsigned int offset, u8 value) +{ + writeb(value, device->reg_base + offset); +} + +static inline void ioatdma_write16(struct ioat_device *device, + unsigned int offset, u16 value) +{ + writew(value, device->reg_base + offset); +} + +static inline void ioatdma_write32(struct ioat_device *device, + unsigned int offset, u32 value) +{ + writel(value, device->reg_base + offset); +} + +static inline u8 ioatdma_chan_read8(struct ioat_dma_chan *chan, + unsigned int offset) +{ + return readb(chan->reg_base + offset); +} + +static inline u16 ioatdma_chan_read16(struct ioat_dma_chan *chan, + unsigned int offset) +{ + return readw(chan->reg_base + offset); +} + +static inline u32 ioatdma_chan_read32(struct ioat_dma_chan *chan, + unsigned int offset) +{ + return readl(chan->reg_base + offset); +} + +static inline void ioatdma_chan_write8(struct ioat_dma_chan *chan, + unsigned int offset, u8 value) +{ + writeb(value, chan->reg_base + offset); +} + +static inline void ioatdma_chan_write16(struct ioat_dma_chan *chan, + unsigned int offset, u16 value) +{ + writew(value, chan->reg_base + offset); +} + +static inline void ioatdma_chan_write32(struct ioat_dma_chan *chan, + unsigned int offset, u32 value) +{ + writel(value, chan->reg_base + offset); +} + +#if (BITS_PER_LONG == 64) +static inline u64 ioatdma_chan_read64(struct ioat_dma_chan *chan, + unsigned int offset) +{ + return readq(chan->reg_base + offset); +} + +static inline void ioatdma_chan_write64(struct ioat_dma_chan *chan, + unsigned int offset, u64 value) +{ + writeq(value, chan->reg_base + offset); +} +#endif + +#endif /* IOATDMA_IO_H */ + diff --git a/drivers/dma/ioatdma_registers.h b/drivers/dma/ioatdma_registers.h new file mode 100644 index 000000000..a30c73490 --- /dev/null +++ b/drivers/dma/ioatdma_registers.h @@ -0,0 +1,126 @@ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ +#ifndef _IOAT_REGISTERS_H_ +#define _IOAT_REGISTERS_H_ + + +/* MMIO Device Registers */ +#define IOAT_CHANCNT_OFFSET 0x00 /* 8-bit */ + +#define IOAT_XFERCAP_OFFSET 0x01 /* 8-bit */ +#define IOAT_XFERCAP_4KB 12 +#define IOAT_XFERCAP_8KB 13 +#define IOAT_XFERCAP_16KB 14 +#define IOAT_XFERCAP_32KB 15 +#define IOAT_XFERCAP_32GB 0 + +#define IOAT_GENCTRL_OFFSET 0x02 /* 8-bit */ +#define IOAT_GENCTRL_DEBUG_EN 0x01 + +#define IOAT_INTRCTRL_OFFSET 0x03 /* 8-bit */ +#define IOAT_INTRCTRL_MASTER_INT_EN 0x01 /* Master Interrupt Enable */ +#define IOAT_INTRCTRL_INT_STATUS 0x02 /* ATTNSTATUS -or- Channel Int */ +#define IOAT_INTRCTRL_INT 0x04 /* INT_STATUS -and- MASTER_INT_EN */ + +#define IOAT_ATTNSTATUS_OFFSET 0x04 /* Each bit is a channel */ + +#define IOAT_VER_OFFSET 0x08 /* 8-bit */ +#define IOAT_VER_MAJOR_MASK 0xF0 +#define IOAT_VER_MINOR_MASK 0x0F +#define GET_IOAT_VER_MAJOR(x) ((x) & IOAT_VER_MAJOR_MASK) +#define GET_IOAT_VER_MINOR(x) ((x) & IOAT_VER_MINOR_MASK) + +#define IOAT_PERPORTOFFSET_OFFSET 0x0A /* 16-bit */ + +#define IOAT_INTRDELAY_OFFSET 0x0C /* 16-bit */ +#define IOAT_INTRDELAY_INT_DELAY_MASK 0x3FFF /* Interrupt Delay Time */ +#define IOAT_INTRDELAY_COALESE_SUPPORT 0x8000 /* Interrupt Coalesing Supported */ + +#define IOAT_DEVICE_STATUS_OFFSET 0x0E /* 16-bit */ +#define IOAT_DEVICE_STATUS_DEGRADED_MODE 0x0001 + + +#define IOAT_CHANNEL_MMIO_SIZE 0x80 /* Each Channel MMIO space is this size */ + +/* DMA Channel Registers */ +#define IOAT_CHANCTRL_OFFSET 0x00 /* 16-bit Channel Control Register */ +#define IOAT_CHANCTRL_CHANNEL_PRIORITY_MASK 0xF000 +#define IOAT_CHANCTRL_CHANNEL_IN_USE 0x0100 +#define IOAT_CHANCTRL_DESCRIPTOR_ADDR_SNOOP_CONTROL 0x0020 +#define IOAT_CHANCTRL_ERR_INT_EN 0x0010 +#define IOAT_CHANCTRL_ANY_ERR_ABORT_EN 0x0008 +#define IOAT_CHANCTRL_ERR_COMPLETION_EN 0x0004 +#define IOAT_CHANCTRL_INT_DISABLE 0x0001 + +#define IOAT_DMA_COMP_OFFSET 0x02 /* 16-bit DMA channel compatability */ +#define IOAT_DMA_COMP_V1 0x0001 /* Compatability with DMA version 1 */ + +#define IOAT_CHANSTS_OFFSET 0x04 /* 64-bit Channel Status Register */ +#define IOAT_CHANSTS_OFFSET_LOW 0x04 +#define IOAT_CHANSTS_OFFSET_HIGH 0x08 +#define IOAT_CHANSTS_COMPLETED_DESCRIPTOR_ADDR 0xFFFFFFFFFFFFFFC0UL +#define IOAT_CHANSTS_SOFT_ERR 0x0000000000000010 +#define IOAT_CHANSTS_DMA_TRANSFER_STATUS 0x0000000000000007 +#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_ACTIVE 0x0 +#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_DONE 0x1 +#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_SUSPENDED 0x2 +#define IOAT_CHANSTS_DMA_TRANSFER_STATUS_HALTED 0x3 + +#define IOAT_CHAINADDR_OFFSET 0x0C /* 64-bit Descriptor Chain Address Register */ +#define IOAT_CHAINADDR_OFFSET_LOW 0x0C +#define IOAT_CHAINADDR_OFFSET_HIGH 0x10 + +#define IOAT_CHANCMD_OFFSET 0x14 /* 8-bit DMA Channel Command Register */ +#define IOAT_CHANCMD_RESET 0x20 +#define IOAT_CHANCMD_RESUME 0x10 +#define IOAT_CHANCMD_ABORT 0x08 +#define IOAT_CHANCMD_SUSPEND 0x04 +#define IOAT_CHANCMD_APPEND 0x02 +#define IOAT_CHANCMD_START 0x01 + +#define IOAT_CHANCMP_OFFSET 0x18 /* 64-bit Channel Completion Address Register */ +#define IOAT_CHANCMP_OFFSET_LOW 0x18 +#define IOAT_CHANCMP_OFFSET_HIGH 0x1C + +#define IOAT_CDAR_OFFSET 0x20 /* 64-bit Current Descriptor Address Register */ +#define IOAT_CDAR_OFFSET_LOW 0x20 +#define IOAT_CDAR_OFFSET_HIGH 0x24 + +#define IOAT_CHANERR_OFFSET 0x28 /* 32-bit Channel Error Register */ +#define IOAT_CHANERR_DMA_TRANSFER_SRC_ADDR_ERR 0x0001 +#define IOAT_CHANERR_DMA_TRANSFER_DEST_ADDR_ERR 0x0002 +#define IOAT_CHANERR_NEXT_DESCRIPTOR_ADDR_ERR 0x0004 +#define IOAT_CHANERR_NEXT_DESCRIPTOR_ALIGNMENT_ERR 0x0008 +#define IOAT_CHANERR_CHAIN_ADDR_VALUE_ERR 0x0010 +#define IOAT_CHANERR_CHANCMD_ERR 0x0020 +#define IOAT_CHANERR_CHIPSET_UNCORRECTABLE_DATA_INTEGRITY_ERR 0x0040 +#define IOAT_CHANERR_DMA_UNCORRECTABLE_DATA_INTEGRITY_ERR 0x0080 +#define IOAT_CHANERR_READ_DATA_ERR 0x0100 +#define IOAT_CHANERR_WRITE_DATA_ERR 0x0200 +#define IOAT_CHANERR_DESCRIPTOR_CONTROL_ERR 0x0400 +#define IOAT_CHANERR_DESCRIPTOR_LENGTH_ERR 0x0800 +#define IOAT_CHANERR_COMPLETION_ADDR_ERR 0x1000 +#define IOAT_CHANERR_INT_CONFIGURATION_ERR 0x2000 +#define IOAT_CHANERR_SOFT_ERR 0x4000 + +#define IOAT_CHANERR_MASK_OFFSET 0x2C /* 32-bit Channel Error Register */ + +#endif /* _IOAT_REGISTERS_H_ */ diff --git a/drivers/dma/iovlock.c b/drivers/dma/iovlock.c new file mode 100644 index 000000000..d637555a8 --- /dev/null +++ b/drivers/dma/iovlock.c @@ -0,0 +1,301 @@ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + * Portions based on net/core/datagram.c and copyrighted by their authors. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + +/* + * This code allows the net stack to make use of a DMA engine for + * skb to iovec copies. + */ + +#include <linux/dmaengine.h> +#include <linux/pagemap.h> +#include <net/tcp.h> /* for memcpy_toiovec */ +#include <asm/io.h> +#include <asm/uaccess.h> + +static int num_pages_spanned(struct iovec *iov) +{ + return + ((PAGE_ALIGN((unsigned long)iov->iov_base + iov->iov_len) - + ((unsigned long)iov->iov_base & PAGE_MASK)) >> PAGE_SHIFT); +} + +/* + * Pin down all the iovec pages needed for len bytes. + * Return a struct dma_pinned_list to keep track of pages pinned down. + * + * We are allocating a single chunk of memory, and then carving it up into + * 3 sections, the latter 2 whose size depends on the number of iovecs and the + * total number of pages, respectively. + */ +struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) +{ + struct dma_pinned_list *local_list; + struct page **pages; + int i; + int ret; + int nr_iovecs = 0; + int iovec_len_used = 0; + int iovec_pages_used = 0; + long err; + + /* don't pin down non-user-based iovecs */ + if (segment_eq(get_fs(), KERNEL_DS)) + return NULL; + + /* determine how many iovecs/pages there are, up front */ + do { + iovec_len_used += iov[nr_iovecs].iov_len; + iovec_pages_used += num_pages_spanned(&iov[nr_iovecs]); + nr_iovecs++; + } while (iovec_len_used < len); + + /* single kmalloc for pinned list, page_list[], and the page arrays */ + local_list = kmalloc(sizeof(*local_list) + + (nr_iovecs * sizeof (struct dma_page_list)) + + (iovec_pages_used * sizeof (struct page*)), GFP_KERNEL); + if (!local_list) { + err = -ENOMEM; + goto out; + } + + /* list of pages starts right after the page list array */ + pages = (struct page **) &local_list->page_list[nr_iovecs]; + + for (i = 0; i < nr_iovecs; i++) { + struct dma_page_list *page_list = &local_list->page_list[i]; + + len -= iov[i].iov_len; + + if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len)) { + err = -EFAULT; + goto unpin; + } + + page_list->nr_pages = num_pages_spanned(&iov[i]); + page_list->base_address = iov[i].iov_base; + + page_list->pages = pages; + pages += page_list->nr_pages; + + /* pin pages down */ + down_read(¤t->mm->mmap_sem); + ret = get_user_pages( + current, + current->mm, + (unsigned long) iov[i].iov_base, + page_list->nr_pages, + 1, /* write */ + 0, /* force */ + page_list->pages, + NULL); + up_read(¤t->mm->mmap_sem); + + if (ret != page_list->nr_pages) { + err = -ENOMEM; + goto unpin; + } + + local_list->nr_iovecs = i + 1; + } + + return local_list; + +unpin: + dma_unpin_iovec_pages(local_list); +out: + return ERR_PTR(err); +} + +void dma_unpin_iovec_pages(struct dma_pinned_list *pinned_list) +{ + int i, j; + + if (!pinned_list) + return; + + for (i = 0; i < pinned_list->nr_iovecs; i++) { + struct dma_page_list *page_list = &pinned_list->page_list[i]; + for (j = 0; j < page_list->nr_pages; j++) { + set_page_dirty_lock(page_list->pages[j]); + page_cache_release(page_list->pages[j]); + } + } + + kfree(pinned_list); +} + +static dma_cookie_t dma_memcpy_to_kernel_iovec(struct dma_chan *chan, struct + iovec *iov, unsigned char *kdata, size_t len) +{ + dma_cookie_t dma_cookie = 0; + + while (len > 0) { + if (iov->iov_len) { + int copy = min_t(unsigned int, iov->iov_len, len); + dma_cookie = dma_async_memcpy_buf_to_buf( + chan, + iov->iov_base, + kdata, + copy); + kdata += copy; + len -= copy; + iov->iov_len -= copy; + iov->iov_base += copy; + } + iov++; + } + + return dma_cookie; +} + +/* + * We have already pinned down the pages we will be using in the iovecs. + * Each entry in iov array has corresponding entry in pinned_list->page_list. + * Using array indexing to keep iov[] and page_list[] in sync. + * Initial elements in iov array's iov->iov_len will be 0 if already copied into + * by another call. + * iov array length remaining guaranteed to be bigger than len. + */ +dma_cookie_t dma_memcpy_to_iovec(struct dma_chan *chan, struct iovec *iov, + struct dma_pinned_list *pinned_list, unsigned char *kdata, size_t len) +{ + int iov_byte_offset; + int copy; + dma_cookie_t dma_cookie = 0; + int iovec_idx; + int page_idx; + + if (!chan) + return memcpy_toiovec(iov, kdata, len); + + /* -> kernel copies (e.g. smbfs) */ + if (!pinned_list) + return dma_memcpy_to_kernel_iovec(chan, iov, kdata, len); + + iovec_idx = 0; + while (iovec_idx < pinned_list->nr_iovecs) { + struct dma_page_list *page_list; + + /* skip already used-up iovecs */ + while (!iov[iovec_idx].iov_len) + iovec_idx++; + + page_list = &pinned_list->page_list[iovec_idx]; + + iov_byte_offset = ((unsigned long)iov[iovec_idx].iov_base & ~PAGE_MASK); + page_idx = (((unsigned long)iov[iovec_idx].iov_base & PAGE_MASK) + - ((unsigned long)page_list->base_address & PAGE_MASK)) >> PAGE_SHIFT; + + /* break up copies to not cross page boundary */ + while (iov[iovec_idx].iov_len) { + copy = min_t(int, PAGE_SIZE - iov_byte_offset, len); + copy = min_t(int, copy, iov[iovec_idx].iov_len); + + dma_cookie = dma_async_memcpy_buf_to_pg(chan, + page_list->pages[page_idx], + iov_byte_offset, + kdata, + copy); + + len -= copy; + iov[iovec_idx].iov_len -= copy; + iov[iovec_idx].iov_base += copy; + + if (!len) + return dma_cookie; + + kdata += copy; + iov_byte_offset = 0; + page_idx++; + } + iovec_idx++; + } + + /* really bad if we ever run out of iovecs */ + BUG(); + return -EFAULT; +} + +dma_cookie_t dma_memcpy_pg_to_iovec(struct dma_chan *chan, struct iovec *iov, + struct dma_pinned_list *pinned_list, struct page *page, + unsigned int offset, size_t len) +{ + int iov_byte_offset; + int copy; + dma_cookie_t dma_cookie = 0; + int iovec_idx; + int page_idx; + int err; + + /* this needs as-yet-unimplemented buf-to-buff, so punt. */ + /* TODO: use dma for this */ + if (!chan || !pinned_list) { + u8 *vaddr = kmap(page); + err = memcpy_toiovec(iov, vaddr + offset, len); + kunmap(page); + return err; + } + + iovec_idx = 0; + while (iovec_idx < pinned_list->nr_iovecs) { + struct dma_page_list *page_list; + + /* skip already used-up iovecs */ + while (!iov[iovec_idx].iov_len) + iovec_idx++; + + page_list = &pinned_list->page_list[iovec_idx]; + + iov_byte_offset = ((unsigned long)iov[iovec_idx].iov_base & ~PAGE_MASK); + page_idx = (((unsigned long)iov[iovec_idx].iov_base & PAGE_MASK) + - ((unsigned long)page_list->base_address & PAGE_MASK)) >> PAGE_SHIFT; + + /* break up copies to not cross page boundary */ + while (iov[iovec_idx].iov_len) { + copy = min_t(int, PAGE_SIZE - iov_byte_offset, len); + copy = min_t(int, copy, iov[iovec_idx].iov_len); + + dma_cookie = dma_async_memcpy_pg_to_pg(chan, + page_list->pages[page_idx], + iov_byte_offset, + page, + offset, + copy); + + len -= copy; + iov[iovec_idx].iov_len -= copy; + iov[iovec_idx].iov_base += copy; + + if (!len) + return dma_cookie; + + offset += copy; + iov_byte_offset = 0; + page_idx++; + } + iovec_idx++; + } + + /* really bad if we ever run out of iovecs */ + BUG(); + return -EFAULT; +} diff --git a/drivers/edac/k8_edac.c b/drivers/edac/k8_edac.c new file mode 100644 index 000000000..d55f112cc --- /dev/null +++ b/drivers/edac/k8_edac.c @@ -0,0 +1,1881 @@ +/* + * AMD K8 class Memory Controller kernel module + * + * This file may be distributed under the terms of the + * GNU General Public License. + * + * Written by Thayne Harbaugh Linux Networx (http://lnxi.com) + * + * Changes by Douglas "norsk" Thompson <norsk5@xmission.com>: + * - K8 CPU Revision D and greater support + * + * Changes by Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>: + * - Module largely rewritten, with new (and hopefully correct) + * code for dealing with node and chip select interleaving, various + * code cleanup, and bug fixes + * - Added support for memory hoisting using DRAM hole address + * register + * + * This module is based on the following document (available from + * http://www.amd.com/): + * + * Title: BIOS and Kernel Developer's Guide for AMD Athlon 64 and AMD + * Opteron Processors + * AMD publication #: 26094 + * Revision: 3.26 + * + * Unless otherwise stated, section numbers mentioned in the comments below + * refer to this document. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/pci_ids.h> +#include <linux/slab.h> +#include <asm/mmzone.h> +#include "edac_mc.h" + +#define k8_printk(level, fmt, arg...) \ + edac_printk(level, "k8", fmt, ##arg) + +#define k8_mc_printk(mci, level, fmt, arg...) \ + edac_mc_chipset_printk(mci, level, "k8", fmt, ##arg) + +/* Throughout the comments in this code, the terms SysAddr, DramAddr, and + * InputAddr are used. These terms come directly from the k8 documentation + * (AMD publication #26094). They are defined as follows: + * + * SysAddr: + * This is a physical address generated by a CPU core or a device + * doing DMA. If generated by a CPU core, a SysAddr is the result of + * a virtual to physical address translation by the CPU core's address + * translation mechanism (MMU). + * + * DramAddr: + * A DramAddr is derived from a SysAddr by subtracting an offset that + * depends on which node the SysAddr maps to and whether the SysAddr + * is within a range affected by memory hoisting. The DRAM Base + * (section 3.4.4.1) and DRAM Limit (section 3.4.4.2) registers + * determine which node a SysAddr maps to. + * + * If the DRAM Hole Address Register (DHAR) is enabled and the SysAddr + * is within the range of addresses specified by this register, then + * a value x from the DHAR is subtracted from the SysAddr to produce a + * DramAddr. Here, x represents the base address for the node that + * the SysAddr maps to plus an offset due to memory hoisting. See + * section 3.4.8 and the comments in get_dram_hole_info() and + * sys_addr_to_dram_addr() below for more information. + * + * If the SysAddr is not affected by the DHAR then a value y is + * subtracted from the SysAddr to produce a DramAddr. Here, y is the + * base address for the node that the SysAddr maps to. See section + * 3.4.4 and the comments in sys_addr_to_dram_addr() below for more + * information. + * + * InputAddr: + * A DramAddr is translated to an InputAddr before being passed to the + * memory controller for the node that the DramAddr is associated + * with. The memory controller then maps the InputAddr to a csrow. + * If node interleaving is not in use, then the InputAddr has the same + * value as the DramAddr. Otherwise, the InputAddr is produced by + * discarding the bits used for node interleaving from the DramAddr. + * See section 3.4.4 for more information. + * + * The memory controller for a given node uses its DRAM CS Base and + * DRAM CS Mask registers to map an InputAddr to a csrow. See + * sections 3.5.4 and 3.5.5 for more information. + */ + +/* + * Alter this version for the K8 module when modifications are made + */ +#define EDAC_K8_VERSION " Ver: 2.0.0 " __DATE__ +#define EDAC_MOD_STR "k8_edac" + +#ifndef PCI_DEVICE_ID_AMD_OPT_0_HT +#define PCI_DEVICE_ID_AMD_OPT_0_HT 0x1100 +#endif /* PCI_DEVICE_ID_AMD_OPT_0_HT */ + +#ifndef PCI_DEVICE_ID_AMD_OPT_1_ADDRMAP +#define PCI_DEVICE_ID_AMD_OPT_1_ADDRMAP 0x1101 +#endif /* PCI_DEVICE_ID_AMD_OPT_1_ADDRMAP */ + +#ifndef PCI_DEVICE_ID_AMD_OPT_2_MEMCTL +#define PCI_DEVICE_ID_AMD_OPT_2_MEMCTL 0x1102 +#endif /* PCI_DEVICE_ID_AMD_OPT_2_MEMCTL */ + +#ifndef PCI_DEVICE_ID_AMD_OPT_3_MISCCTL +#define PCI_DEVICE_ID_AMD_OPT_3_MISCCTL 0x1103 +#endif /* PCI_DEVICE_ID_AMD_OPT_3_MISCCTL */ + +/* Extended Model from CPUID, for CPU Revision numbers */ +#define OPTERON_CPU_LE_REV_C 0 +#define OPTERON_CPU_REV_D 1 +#define OPTERON_CPU_REV_E 2 + +#define K8_NR_CSROWS 8 +#define MAX_K8_NODES 8 + +/* K8 register addresses - device 0 function 1 - Address Map */ +#define K8_DBR 0x40 /* DRAM Base Register (8 x 32b + * interlaced with K8_DLR) + * + * 31:16 DRAM Base addr 39:24 + * 15:11 reserved + * 10:8 interleave enable + * 7:2 reserved + * 1 write enable + * 0 read enable + */ + +#define K8_DLR 0x44 /* DRAM Limit Register (8 x 32b + * interlaced with K8_DBR) + * + * 31:16 DRAM Limit addr 32:24 + * 15:11 reserved + * 10:8 interleave select + * 7:3 reserved + * 2:0 destination node ID + */ + +#define K8_DHAR 0xf0 /* DRAM Hole Address Register + * + * 31:24 DramHoleBase + * 23:16 reserved + * 15:8 DramHoleOffset + * 7:1 reserved + * 0 DramHoleValid + */ + +/* K8 register addresses - device 0 function 2 - DRAM controller */ +#define K8_DCSB 0x40 /* DRAM Chip-Select Base (8 x 32b) + * + * 31:21 Base addr high 35:25 + * 20:16 reserved + * 15:9 Base addr low 19:13 (interlvd) + * 8:1 reserved + * 0 chip-select bank enable + */ + +#define K8_DCSM 0x60 /* DRAM Chip-Select Mask (8 x 32b) + * + * 31:30 reserved + * 29:21 addr mask high 33:25 + * 20:16 reserved + * 15:9 addr mask low 19:13 + * 8:0 reserved + */ + +/* selects bits 29-21 and 15-9 from DCSM */ +#define DCSM_MASK_BITS 0x3fe0fe00 + +#define K8_DBAM 0x80 /* DRAM Base Addr Mapping (32b) */ + +#define K8_DCL 0x90 /* DRAM configuration low reg (32b) + * + * 31:28 reserved + * 27:25 Bypass Max: 000b=respect + * 24 Dissable receivers - no sockets + * 23:20 x4 DIMMS + * 19 32byte chunks + * 18 Unbuffered + * 17 ECC enabled + * 16 128/64 bit (dual/single chan) + * 15:14 R/W Queue bypass count + * 13 Self refresh + * 12 exit self refresh + * 11 mem clear status + * 10 DRAM enable + * 9 reserved + * 8 DRAM init + * 7:4 reserved + * 3 dis DQS hysteresis + * 2 QFC enabled + * 1 DRAM drive strength + * 0 Digital Locked Loop disable + */ + +/* K8 register addresses - device 0 function 3 - Misc Control */ +#define K8_NBCTL 0x40 /* MCA NB Control (32b) + * + * 1 MCA UE Reporting + * 0 MCA CE Reporting + */ + +#define K8_NBCFG 0x44 /* MCA NB Config (32b) + * + * 23 Chip-kill x4 ECC enable + * 22 ECC enable + * 1 CPU ECC enable + */ + +#define K8_NBSL 0x48 /* MCA NB Status Low (32b) + * + * 31:24 Syndrome 15:8 chip-kill x4 + * 23:20 reserved + * 19:16 Extended err code + * 15:0 Err code + */ + +#define K8_NBSH 0x4C /* MCA NB Status High (32b) + * + * 31 Err valid + * 30 Err overflow + * 29 Uncorrected err + * 28 Err enable + * 27 Misc err reg valid + * 26 Err addr valid + * 25 proc context corrupt + * 24:23 reserved + * 22:15 Syndrome 7:0 + * 14 CE + * 13 UE + * 12:9 reserved + * 8 err found by scrubber + * 7 reserved + * 6:4 Hyper-transport link number + * 3:2 reserved + * 1 Err CPU 1 + * 0 Err CPU 0 + */ + +#define K8_NBSH_VALID_BIT BIT(31) + +#define K8_NBEAL 0x50 /* MCA NB err addr low (32b) + * + * 31:3 Err addr low 31:3 + * 2:0 reserved + */ + +#define K8_NBEAH 0x54 /* MCA NB err addr high (32b) + * + * 31:8 reserved + * 7:0 Err addr high 39:32 + */ + +#define K8_NBCAP 0xE8 /* MCA NB capabilities (32b) + * + * 31:9 reserved + * 4 S4ECD4ED capable + * 3 SECDED capable + */ + + /* MSR's */ + + /* + * K8_MSR_MCxCTL (64b) + * (0x400,404,408,40C,410) + * 63 Enable reporting source 63 + * . + * . + * . + * 2 Enable error source 2 + * 1 Enable error source 1 + * 0 Enable error source 0 + */ + + /* + * K8_MSR_MCxSTAT (64b) + * (0x401,405,409,40D,411) + * 63 Error valid + * 62 Status overflow + * 61 UE + * 60 Enabled error condition + * 59 Misc register valid (not used) + * 58 Err addr register valid + * 57 Processor context corrupt + * 56:32 Other information + * 31:16 Model specific error code + * 15:0 MCA err code + */ + + /* + * K8_MSR_MCxADDR (64b) + * (0x402,406,40A,40E,412) + * 63:48 reserved + * 47:0 Address + */ + + /* + * K8_MSR_MCxMISC (64b) + * (0x403,407,40B,40F,413) + * Unused on Athlon64 and K8 + */ + +#define K8_MSR_MCGCTL 0x017b /* Machine Chk Global report ctl (64b) + * + * 31:5 reserved + * 4 North Bridge + * 3 Load/Store + * 2 Bus Unit + * 1 Instruction Cache + * 0 Data Cache + */ + +#define K8_MSR_MC4CTL 0x0410 /* North Bridge Check report ctl (64b) */ +#define K8_MSR_MC4STAT 0x0411 /* North Bridge status (64b) */ +#define K8_MSR_MC4ADDR 0x0412 /* North Bridge Address (64b) */ + +static inline int MCI_TO_NODE_ID(struct mem_ctl_info *mci) +{ + return PCI_SLOT(to_pci_dev(mci->dev)->devfn) - 0x18; +} + +/* Ugly hack that allows module to compile when built as part of a 32-bit + * kernel. Just in case anyone wants to run a 32-bit kernel on their Opteron. + */ +#ifndef MAXNODE +#define MAXNODE 8 +#endif + +/* Each entry holds the CPU revision of all CPU cores for the given node. */ +static int k8_node_revision_table[MAXNODE] = { 0 }; + +static inline int node_rev(int node_id) +{ + return k8_node_revision_table[node_id]; +} + +static void store_node_revision(void *param) +{ + int node_id, revision; + + /* Multiple CPU cores on the same node will all write their revision + * number to the same array entry. This is ok. For a given node, all + * CPU cores are on the same piece of silicon and share the same + * revision number. + */ + node_id = (cpuid_ebx(1) >> 24) & 0x07; + revision = (cpuid_eax(1) >> 16) & 0x0f; + k8_node_revision_table[node_id] = revision; +} + +/* Initialize k8_node_revision_table. */ +static void build_node_revision_table(void) +{ + static int initialized = 0; + + if (initialized) + return; + + on_each_cpu(store_node_revision, NULL, 1, 1); + initialized = 1; +} + +enum k8_chips { + OPTERON = 0, +}; + +struct k8_pvt { + struct pci_dev *addr_map; + struct pci_dev *misc_ctl; + + int node_id; /* ID of this node */ + + /* The values of these registers will remain constant so we might as + * well cache them here. + */ + u32 dcl; + u32 dbr[MAX_K8_NODES]; + u32 dlr[MAX_K8_NODES]; + u32 nbcap; + u32 dcsb[K8_NR_CSROWS]; + u32 dcsm[K8_NR_CSROWS]; + u32 dhar; + u32 dbam; +}; + +struct k8_error_info_regs { + u32 nbsh; + u32 nbsl; + u32 nbeah; + u32 nbeal; +}; + +struct k8_error_info { + struct k8_error_info_regs error_info; + u32 nbcfg; + int race_condition_detected; +}; + +struct k8_dev_info { + const char *ctl_name; + u16 addr_map; + u16 misc_ctl; +}; + +static const struct k8_dev_info k8_devs[] = { + [OPTERON] = { + .ctl_name = "Athlon64/Opteron", + .addr_map = PCI_DEVICE_ID_AMD_OPT_1_ADDRMAP, + .misc_ctl = PCI_DEVICE_ID_AMD_OPT_3_MISCCTL}, +}; + +static struct pci_dev * pci_get_related_function(unsigned int vendor, + unsigned int device, struct pci_dev *related) +{ + struct pci_dev *dev; + + dev = NULL; + + while ((dev = pci_get_device(vendor, device, dev)) != NULL) { + if ((dev->bus->number == related->bus->number) && + (PCI_SLOT(dev->devfn) == PCI_SLOT(related->devfn))) + break; + } + + return dev; +} + +/* FIXME - stolen from msr.c - the calls in msr.c could be exported */ +struct msr_command { + int cpu; + int err; + u32 reg; + u32 data[2]; +}; + +static void smp_wrmsr(void *cmd_block) +{ + struct msr_command *cmd = cmd_block; + wrmsr(cmd->reg, cmd->data[0], cmd->data[1]); +} + +static void smp_rdmsr(void *cmd_block) +{ + struct msr_command *cmd = cmd_block; + rdmsr(cmd->reg, cmd->data[0], cmd->data[1]); +} + +static void do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx) +{ + struct msr_command cmd; + + cmd.cpu = raw_smp_processor_id(); + cmd.reg = reg; + cmd.data[0] = eax; + cmd.data[1] = edx; + on_each_cpu(smp_wrmsr, &cmd, 1, 1); +} + +static void do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx) +{ + struct msr_command cmd; + + cmd.cpu = raw_smp_processor_id(); + cmd.reg = reg; + on_each_cpu(smp_rdmsr, &cmd, 1, 1); + *eax = cmd.data[0]; + *edx = cmd.data[1]; +} + +/* + * FIXME - This is a large chunk of memory to suck up just to decode the + * syndrome. It would be nice to discover a pattern in the syndromes that + * could be used to quickly identify the channel. The big problems with + * this table is memory usage, lookup speed (could sort and binary search), + * correctness (there could be a transcription error). A zero in any nibble + * for a syndrom is always channel 0, but that only decodes some of the + * syndromes. Can anyone find any other patterns? + * + * The comment in the left column is the nibble that is in error. The least + * significant nibble of the syndrome is the mask for the bits that are + * in error (need to be toggled) for the particular nibble. + */ +#define SYNDROME_TABLE_SIZE 270 +static const unsigned long syndromes_chan0[SYNDROME_TABLE_SIZE] = { + /*0 */ 0xe821, 0x7c32, 0x9413, 0xbb44, 0x5365, 0xc776, 0x2f57, + 0xdd88, 0x35a9, 0xa1ba, 0x499b, 0x66cc, 0x8eed, 0x1afe, 0xf2df, + /*1 */ 0x5d31, 0xa612, 0xfb23, 0x9584, 0xc8b5, 0x3396, 0x6ea7, + 0xeac8, 0xb7f9, 0x4cda, 0x11eb, 0x7f4c, 0x227d, 0xd95e, 0x846f, + /*2 */ 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + /*3 */ 0x2021, 0x3032, 0x1013, 0x4044, 0x6065, 0x7076, 0x5057, + 0x8088, 0xa0a9, 0xb0ba, 0x909b, 0xc0cc, 0xe0ed, 0xf0fe, 0xd0df, + /*4 */ 0x5041, 0xa082, 0xf0c3, 0x9054, 0xc015, 0x30d6, 0x6097, + 0xe0a8, 0xb0e9, 0x402a, 0x106b, 0x70fc, 0x20bd, 0xd07e, 0x803f, + /*5 */ 0xbe21, 0xd732, 0x6913, 0x2144, 0x9f65, 0xf676, 0x4857, + 0x3288, 0x8ca9, 0xe5ba, 0x5b9b, 0x13cc, 0xaded, 0xc4fe, 0x7adf, + /*6 */ 0x4951, 0x8ea2, 0xc7f3, 0x5394, 0x1ac5, 0xdd36, 0x9467, + 0xa1e8, 0xe8b9, 0x2f4a, 0x661b, 0xf27c, 0xbb2d, 0x7cde, 0x358f, + /*7 */ 0x74e1, 0x9872, 0xec93, 0xd6b4, 0xa255, 0x4ec6, 0x3a27, + 0x6bd8, 0x1f39, 0xf3aa, 0x874b, 0xbd6c, 0xc98d, 0x251e, 0x51ff, + /*8 */ 0x15c1, 0x2a42, 0x3f83, 0xcef4, 0xdb35, 0xe4b6, 0xf177, + 0x4758, 0x5299, 0x6d1a, 0x78db, 0x89ac, 0x9c6d, 0xa3ee, 0xb62f, + /*9 */ 0x3d01, 0x1602, 0x2b03, 0x8504, 0xb805, 0x9306, 0xae07, + 0xca08, 0xf709, 0xdc0a, 0xe10b, 0x4f0c, 0x720d, 0x590e, 0x640f, + /*a */ 0x9801, 0xec02, 0x7403, 0x6b04, 0xf305, 0x8706, 0x1f07, + 0xbd08, 0x2509, 0x510a, 0xc90b, 0xd60c, 0x4e0d, 0x3a0e, 0xa20f, + /*b */ 0xd131, 0x6212, 0xb323, 0x3884, 0xe9b5, 0x5a96, 0x8ba7, + 0x1cc8, 0xcdf9, 0x7eda, 0xafeb, 0x244c, 0xf57d, 0x465e, 0x976f, + /*c */ 0xe1d1, 0x7262, 0x93b3, 0xb834, 0x59e5, 0xca56, 0x2b87, + 0xdc18, 0x3dc9, 0xae7a, 0x4fab, 0x542c, 0x85fd, 0x164e, 0xf79f, + /*d */ 0x6051, 0xb0a2, 0xd0f3, 0x1094, 0x70c5, 0xa036, 0xc067, + 0x20e8, 0x40b9, 0x904a, 0x601b, 0x307c, 0x502d, 0x80de, 0xe08f, + /*e */ 0xa4c1, 0xf842, 0x5c83, 0xe6f4, 0x4235, 0x1eb6, 0xba77, + 0x7b58, 0xdf99, 0x831a, 0x27db, 0x9dac, 0x396d, 0x65ee, 0xc12f, + /*f */ 0x11c1, 0x2242, 0x3383, 0xc8f4, 0xd935, 0xeab6, 0xfb77, + 0x4c58, 0x5d99, 0x6e1a, 0x7fdb, 0x84ac, 0x9562, 0xa6ee, 0xb72f, + + /*20 */ 0xbe01, 0xd702, 0x6903, 0x2104, 0x9f05, 0xf606, 0x4807, + 0x3208, 0x8c09, 0xe50a, 0x5b0b, 0x130c, 0xad0d, 0xc40e, 0x7a0f, + /*21 */ 0x4101, 0x8202, 0xc303, 0x5804, 0x1905, 0xda06, 0x9b07, + 0xac08, 0xed09, 0x2e0a, 0x6f0b, 0x640c, 0xb50d, 0x760e, 0x370f +}; + +static const unsigned long syndromes_chan1[SYNDROME_TABLE_SIZE] = { + /*10 */ 0x45d1, 0x8a62, 0xcfb3, 0x5e34, 0x1be5, 0xd456, 0x9187, + 0xa718, 0xe2c9, 0x2d7a, 0x68ab, 0xf92c, 0xbcfd, 0x734e, 0x369f, + /*11 */ 0x63e1, 0xb172, 0xd293, 0x14b4, 0x7755, 0xa5c6, 0xc627, + 0x28d8, 0x4b39, 0x99aa, 0xfa4b, 0x3c6c, 0x5f8d, 0x8d1e, 0xeeff, + /*12 */ 0xb741, 0xd982, 0x6ec3, 0x2254, 0x9515, 0xfbd6, 0x4c97, + 0x33a8, 0x84e9, 0xea2a, 0x5d6b, 0x11fc, 0xa6bd, 0xc87e, 0x7f3f, + /*13 */ 0xdd41, 0x6682, 0xbbc3, 0x3554, 0xe815, 0x53d6, 0xce97, + 0x1aa8, 0xc7e9, 0x7c2a, 0xa1fb, 0x2ffc, 0xf2bd, 0x497e, 0x943f, + /*14 */ 0x2bd1, 0x3d62, 0x16b3, 0x4f34, 0x64e5, 0x7256, 0x5987, + 0x8518, 0xaec9, 0xb87a, 0x93ab, 0xca2c, 0xe1fd, 0xf74e, 0xdc9f, + /*15 */ 0x83c1, 0xc142, 0x4283, 0xa4f4, 0x2735, 0x65b6, 0xe677, + 0xf858, 0x7b99, 0x391a, 0xbadb, 0x5cac, 0xdf6d, 0x9dee, 0x1e2f, + /*16 */ 0x8fd1, 0xc562, 0x4ab3, 0xa934, 0x26e5, 0x6c56, 0xe387, + 0xfe18, 0x71c9, 0x3b7a, 0xb4ab, 0x572c, 0xd8fd, 0x924e, 0x1d9f, + /*17 */ 0x4791, 0x89e2, 0xce73, 0x5264, 0x15f5, 0xdb86, 0x9c17, + 0xa3b8, 0xe429, 0x2a5a, 0x6dcb, 0xf1dc, 0xb64d, 0x783e, 0x3faf, + /*18 */ 0x5781, 0xa9c2, 0xfe43, 0x92a4, 0xc525, 0x3b66, 0x6ce7, + 0xe3f8, 0xb479, 0x4a3a, 0x1dbb, 0x715c, 0x26dd, 0xd89e, 0x8f1f, + /*19 */ 0xbf41, 0xd582, 0x6ac3, 0x2954, 0x9615, 0xfcd6, 0x4397, + 0x3ea8, 0x81e9, 0xeb2a, 0x546b, 0x17fc, 0xa8bd, 0xc27e, 0x7d3f, + /*1a */ 0x9891, 0xe1e2, 0x7273, 0x6464, 0xf7f5, 0x8586, 0x1617, + 0xb8b8, 0x2b29, 0x595a, 0xcacb, 0xdcdc, 0x4f4d, 0x3d3e, 0xaeaf, + /*1b */ 0xcce1, 0x4472, 0x8893, 0xfdb4, 0x3f55, 0xb9c6, 0x7527, + 0x56d8, 0x9a39, 0x12aa, 0xde4b, 0xab6c, 0x678d, 0xef1e, 0x23ff, + /*1c */ 0xa761, 0xf9b2, 0x5ed3, 0xe214, 0x4575, 0x1ba6, 0xbcc7, + 0x7328, 0xd449, 0x8a9a, 0x2dfb, 0x913c, 0x365d, 0x688e, 0xcfef, + /*1d */ 0xff61, 0x55b2, 0xaad3, 0x7914, 0x8675, 0x2ca6, 0xd3c7, + 0x9e28, 0x6149, 0xcb9a, 0x34fb, 0xe73c, 0x185d, 0xb28e, 0x4def, + /*1e */ 0x5451, 0xa8a2, 0xfcf3, 0x9694, 0xc2c5, 0x3e36, 0x6a67, + 0xebe8, 0xbfb9, 0x434a, 0x171b, 0x7d7c, 0x292d, 0xd5de, 0x818f, + /*1f */ 0x6fc1, 0xb542, 0xda83, 0x19f4, 0x7635, 0xacb6, 0xc377, + 0x2e58, 0x4199, 0x9b1a, 0xf4db, 0x37ac, 0x586d, 0x82ee, 0xed2f, + + /*22 */ 0xc441, 0x4882, 0x8cc3, 0xf654, 0x3215, 0xbed6, 0x7a97, + 0x5ba8, 0x9fe9, 0x132a, 0xd76b, 0xadfc, 0x69bd, 0xe57e, 0x213f, + /*23 */ 0x7621, 0x9b32, 0xed13, 0xda44, 0xac65, 0x4176, 0x3757, + 0x6f88, 0x19a9, 0xf4ba, 0x829b, 0xb5cc, 0xc3ed, 0x2efe, 0x58df +}; + +static int chan_from_chipkill_syndrome(unsigned long syndrome) +{ + int i; + + debugf0("%s()\n", __func__); + + for (i = 0; i < SYNDROME_TABLE_SIZE; i++) { + if (syndromes_chan0[i] == syndrome) + return 0; + if (syndromes_chan1[i] == syndrome) + return 1; + } + + debugf0("%s(): syndrome(%lx) not found\n", __func__, syndrome); + return -1; +} + +static const char *tt_msgs[] = { /* transaction type */ + "inst", + "data", + "generic", + "reserved" +}; + +static const char *ll_msgs[] = { /* cache level */ + "0", + "1", + "2", + "generic" +}; + +static const char *memtt_msgs[] = { + "generic", + "generic read", + "generic write", + "data read", + "data write", + "inst fetch", + "prefetch", + "evict", + "snoop", + "unknown error 9", + "unknown error 10", + "unknown error 11", + "unknown error 12", + "unknown error 13", + "unknown error 14", + "unknown error 15" +}; + +static const char *pp_msgs[] = { /* participating processor */ + "local node origin", + "local node response", + "local node observed", + "generic" +}; + +static const char *to_msgs[] = { + "no timeout", + "timed out" +}; + +static const char *ii_msgs[] = { /* memory or i/o */ + "mem access", + "reserved", + "i/o access", + "generic" +}; + +static const char *ext_msgs[] = { /* extended error */ + "ECC error", + "CRC error", + "sync error", + "mst abort", + "tgt abort", + "GART error", + "RMW error", + "watchdog error", + "ECC chipkill x4 error", + "unknown error 9", + "unknown error 10", + "unknown error 11", + "unknown error 12", + "unknown error 13", + "unknown error 14", + "unknown error 15" +}; + +static const char *htlink_msgs[] = { + "none", + "1", + "2", + "1 2", + "3", + "1 3", + "2 3", + "1 2 3" +}; + +static inline u64 base_from_dcsb(u32 dcsb) +{ + /* 0xffe0fe00 selects bits 31-21 and 15-9 of a DRAM CS Base Address + * Register (section 3.5.4). Shifting the bits left 4 puts them in + * their proper bit positions of 35-25 and 19-13. + */ + return ((u64) (dcsb & 0xffe0fe00)) << 4; +} + +static u64 mask_from_dcsm(u32 dcsm) +{ + u64 dcsm_bits, other_bits; + + /* Extract bits bits 29-21 and 15-9 from DCSM (section 3.5.5). */ + dcsm_bits = dcsm & DCSM_MASK_BITS; + + /* Set all bits except bits 33-25 and 19-13. */ + other_bits = DCSM_MASK_BITS; + other_bits = ~(other_bits << 4); + + /* The extracted bits from DCSM belong in the spaces represented by + * the cleared bits in other_bits. + */ + return (dcsm_bits << 4) | other_bits; +} + +/* In *base and *limit, pass back the full 40-bit base and limit physical + * addresses for the node given by node_id. This information is obtained from + * DRAM Base (section 3.4.4.1) and DRAM Limit (section 3.4.4.2) registers. The + * base and limit addresses are of type SysAddr, as defined at the start of + * section 3.4.4 (p. 70). They are the lowest and highest physical addresses + * in the address range they represent. + */ +static void get_base_and_limit(struct k8_pvt *pvt, int node_id, + u64 *base, u64 *limit) +{ + *base = ((u64) (pvt->dbr[node_id] & 0xffff0000)) << 8; + + /* Since the limit represents the highest address in the range, we + * must set its lowest 24 bits to 1. + */ + *limit = (((u64) (pvt->dlr[node_id] & 0xffff0000)) << 8) | 0xffffff; +} + +/* Return 1 if the SysAddr given by sys_addr matches the base/limit associated + * with node_id + */ +static int base_limit_match(struct k8_pvt *pvt, u64 sys_addr, int node_id) +{ + u64 base, limit, addr; + + get_base_and_limit(pvt, node_id, &base, &limit); + + /* The k8 treats this as a 40-bit value. However, bits 63-40 will be + * all ones if the most significant implemented address bit is 1. + * Here we discard bits 63-40. See section 3.4.2 of AMD publication + * 24592: AMD x86-64 Architecture Programmer's Manual Volume 1 + * Application Programming. + */ + addr = sys_addr & 0x000000ffffffffffull; + + return (addr >= base) && (addr <= limit); +} + +/* Attempt to map a SysAddr to a node. On success, return a pointer to the + * mem_ctl_info structure for the node that the SysAddr maps to. On failure, + * return NULL. + */ +static struct mem_ctl_info * find_mc_by_sys_addr(struct mem_ctl_info *mci, + u64 sys_addr) +{ + struct k8_pvt *pvt; + int node_id; + u32 intlv_en, bits; + + /* Here we use the DRAM Base (section 3.4.4.1) and DRAM Limit (section + * 3.4.4.2) registers to map the SysAddr to a node ID. + */ + + pvt = mci->pvt_info; + + /* The value of this field should be the same for all DRAM Base + * registers. Therefore we arbitrarily choose to read it from the + * register for node 0. + */ + intlv_en = pvt->dbr[0] & (0x07 << 8); + + if (intlv_en == 0) { /* node interleaving is disabled */ + debugf2("%s(): node interleaving disabled\n", __func__); + for (node_id = 0; ; ) { + if (base_limit_match(pvt, sys_addr, node_id)) + break; + + if (++node_id == MAX_K8_NODES) { + debugf2("%s(): sys_addr 0x%lx " + "does not match any node\n", __func__, + (unsigned long) sys_addr); + return NULL; + } + } + + goto found; + } + + if (unlikely((intlv_en != (0x01 << 8)) && + (intlv_en != (0x03 << 8)) && + (intlv_en != (0x07 << 8)))) { + k8_printk(KERN_WARNING, + "%s(): junk value of 0x%x extracted from IntlvEn " + "field of DRAM Base Register for node 0: This " + "probably indicates a BIOS bug.\n", __func__, + intlv_en); + return NULL; + } + + /* If we get this far, node interleaving is enabled. */ + debugf2("%s(): node interleaving enabled\n", __func__); + bits = (((u32) sys_addr) >> 12) & intlv_en; + + for (node_id = 0; ; ) { + if ((pvt->dlr[node_id] & intlv_en) == bits) + break; /* intlv_sel field matches */ + + if (++node_id == MAX_K8_NODES) { + debugf2("%s(): sys_addr 0x%lx does not match any " + "node\n", __func__, (unsigned long) sys_addr); + return NULL; + } + } + + /* sanity test for sys_addr */ + if (unlikely(!base_limit_match(pvt, sys_addr, node_id))) { + k8_printk(KERN_WARNING, + "%s(): sys_addr 0x%lx falls outside base/limit " + "address range for node %d with node interleaving " + "enabled.\n", __func__, (unsigned long) sys_addr, + node_id); + return NULL; + } + +found: + debugf2("%s(): sys_addr 0x%lx matches node %d\n", __func__, + (unsigned long) sys_addr, node_id); + return edac_mc_find(node_id); +} + +/* Return the base value defined by the DRAM Base register for the node + * represented by mci. This function returns the full 40-bit value despite + * the fact that the register only stores bits 39-24 of the value. See + * section 3.4.4.1. + */ +static inline u64 get_dram_base(struct mem_ctl_info *mci) +{ + struct k8_pvt *pvt; + + pvt = mci->pvt_info; + return ((u64) (pvt->dbr[pvt->node_id] & 0xffff0000)) << 8; +} + +/* Obtain info from the DRAM Hole Address Register (section 3.4.8) for the + * node represented by mci. Info is passed back in *hole_base, *hole_offset, + * and *hole_size. Function returns 0 if info is valid or 1 if info is + * invalid. Info may be invalid for either of the following reasons: + * + * - The revision of the node is not E or greater. In this case, the DRAM + * Hole Address Register does not exist. + * - The DramHoleValid bit is cleared in the DRAM Hole Address Register, + * indicating that its contents are not valid. + * + * The values passed back in *hole_base, *hole_offset, and *hole_size are + * complete 32-bit values despite the fact that the bitfields in the DHAR + * only represent bits 31-24 of the base and offset values. + */ +static int get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base, + u64 *hole_offset, u64 *hole_size) +{ + struct k8_pvt *pvt; + u64 base; + + pvt = mci->pvt_info; + + if (node_rev(pvt->node_id) < OPTERON_CPU_REV_E) { + debugf2("revision %d for node %d does not support DHAR\n", + node_rev(pvt->node_id), pvt->node_id); + return 1; + } + + if ((pvt->dhar & 0x01) == 0) { + debugf2("DramHoleValid bit cleared in DHAR for node %d\n", + pvt->node_id); + return 1; /* DramHoleValid bit is cleared */ + } + + /* +------------------+--------------------+--------------------+----- + * | memory | DRAM hole | relocated | + * | [0, (x - 1)] | [x, 0xffffffff] | addresses from | + * | | | DRAM hole | + * | | | [0x100000000, | + * | | | (0x100000000+ | + * | | | (0xffffffff-x))] | + * +------------------+--------------------+--------------------+----- + * + * Above is a diagram of physical memory showing the DRAM hole and the + * relocated addresses from the DRAM hole. As shown, the DRAM hole + * starts at address x (the base address) and extends through address + * 0xffffffff. The DRAM Hole Address Register (DHAR) relocates the + * addresses in the hole so that they start at 0x100000000. + */ + + base = pvt->dhar & 0xff000000; + *hole_base = base; + *hole_offset = (pvt->dhar & 0x0000ff00) << 16; + *hole_size = (0x1ull << 32) - base; + debugf2("DHAR info for node %d: base 0x%lx offset 0x%lx size 0x%lx\n", + pvt->node_id, (unsigned long) *hole_base, + (unsigned long) *hole_offset, (unsigned long) *hole_size); + return 0; +} + +/* Return the DramAddr that the SysAddr given by sys_addr maps to. It is + * assumed that sys_addr maps to the node given by mci. + */ +static u64 sys_addr_to_dram_addr(struct mem_ctl_info *mci, u64 sys_addr) +{ + u64 dram_base, hole_base, hole_offset, hole_size, dram_addr; + + /* The first part of section 3.4.4 (p. 70) shows how the DRAM Base + * (section 3.4.4.1) and DRAM Limit (section 3.4.4.2) registers are + * used to translate a SysAddr to a DramAddr. If the DRAM Hole + * Address Register (DHAR) is enabled, then it is also involved in + * translating a SysAddr to a DramAddr. Sections 3.4.8 and 3.5.8.2 + * describe the DHAR and how it is used for memory hoisting. These + * parts of the documentation are unclear. I interpret them as + * follows: + * + * When node n receives a SysAddr, it processes the SysAddr as + * follows: + * + * 1. It extracts the DRAMBase and DRAMLimit values from the + * DRAM Base and DRAM Limit registers for node n. If the + * SysAddr is not within the range specified by the base + * and limit values, then node n ignores the Sysaddr + * (since it does not map to node n). Otherwise continue + * to step 2 below. + * + * 2. If the DramHoleValid bit of the DHAR for node n is + * clear, the DHAR is disabled so skip to step 3 below. + * Otherwise see if the SysAddr is within the range of + * relocated addresses (starting at 0x100000000) from the + * DRAM hole. If not, skip to step 3 below. Else get the + * value of the DramHoleOffset field from the DHAR. To + * obtain the DramAddr, subtract the offset defined by + * this value from the SysAddr. + * + * 3. Obtain the base address for node n from the DRAMBase + * field of the DRAM Base register for node n. To obtain + * the DramAddr, subtract the base address from the + * SysAddr, as shown near the start of section 3.4.4 + * (p. 70). + */ + + dram_base = get_dram_base(mci); + + if (!get_dram_hole_info(mci, &hole_base, &hole_offset, &hole_size)) { + if ((sys_addr >= (1ull << 32)) && + (sys_addr < ((1ull << 32) + hole_size))) { + /* use DHAR to translate SysAddr to DramAddr */ + dram_addr = sys_addr - hole_offset; + debugf2("using DHAR to translate SysAddr 0x%lx to " + "DramAddr 0x%lx\n", + (unsigned long) sys_addr, + (unsigned long) dram_addr); + return dram_addr; + } + } + + /* Translate the SysAddr to a DramAddr as shown near the start of + * section 3.4.4 (p. 70). Although sys_addr is a 64-bit value, the k8 + * only deals with 40-bit values. Therefore we discard bits 63-40 of + * sys_addr below. If bit 39 of sys_addr is 1 then the bits we + * discard are all 1s. Otherwise the bits we discard are all 0s. See + * section 3.4.2 of AMD publication 24592: AMD x86-64 Architecture + * Programmer's Manual Volume 1 Application Programming. + */ + dram_addr = (sys_addr & 0xffffffffffull) - dram_base; + + debugf2("using DRAM Base register to translate SysAddr 0x%lx to " + "DramAddr 0x%lx\n", (unsigned long) sys_addr, + (unsigned long) dram_addr); + return dram_addr; +} + +/* Parameter intlv_en is the value of the IntlvEn field from a DRAM Base + * register (section 3.4.4.1). Return the number of bits from a SysAddr that + * are used for node interleaving. + */ +static int num_node_interleave_bits(unsigned intlv_en) +{ + static const int intlv_shift_table[] = { 0, 1, 0, 2, 0, 0, 0, 3 }; + int n; + + BUG_ON(intlv_en > 7); + n = intlv_shift_table[intlv_en]; + debugf2("using %d bits for node interleave\n", n); + return n; +} + +/* Translate the DramAddr given by dram_addr to an InputAddr and return the + * result. + */ +static u64 dram_addr_to_input_addr(struct mem_ctl_info *mci, u64 dram_addr) +{ + struct k8_pvt *pvt; + int intlv_shift; + u64 input_addr; + + pvt = mci->pvt_info; + + /* Near the start of section 3.4.4 (p. 70), the k8 documentation gives + * instructions for translating a DramAddr to an InputAddr. Here we + * are following these instructions. + */ + intlv_shift = num_node_interleave_bits((pvt->dbr[0] >> 8) & 0x07); + input_addr = ((dram_addr >> intlv_shift) & 0xffffff000ull) + + (dram_addr & 0xfff); + + debugf2("DramAddr 0x%lx translates to InputAddr 0x%lx\n", + (unsigned long) dram_addr, (unsigned long) input_addr); + return input_addr; +} + +/* Translate the SysAddr represented by sys_addr to an InputAddr and return + * the result. It is assumed that sys_addr maps to the node given by mci. + */ +static u64 sys_addr_to_input_addr(struct mem_ctl_info *mci, u64 sys_addr) +{ + u64 input_addr; + + input_addr = dram_addr_to_input_addr( + mci, sys_addr_to_dram_addr(mci, sys_addr)); + debugf2("%s(): SysAdddr 0x%lx translates to InputAddr 0x%lx\n", + __func__, (unsigned long) sys_addr, + (unsigned long) input_addr); + return input_addr; +} + +/* input_addr is an InputAddr associated with the node given by mci. Return + * the csrow that input_addr maps to, or -1 on failure (no csrow claims + * input_addr). + */ +static int input_addr_to_csrow(struct mem_ctl_info *mci, u64 input_addr) +{ + struct k8_pvt *pvt; + int i; + u32 dcsb, dcsm; + u64 base, mask; + + pvt = mci->pvt_info; + + /* Here we use the DRAM CS Base (section 3.5.4) and DRAM CS Mask + * (section 3.5.5) registers. For each CS base/mask register pair, + * test the condition shown near the start of section 3.5.4 (p. 84). + */ + + for (i = 0; i < K8_NR_CSROWS; i++) { + dcsb = pvt->dcsb[i]; + dcsm = pvt->dcsm[i]; + + if ((dcsb & 0x01) == 0) { + debugf2("input_addr_to_csrow: CSBE bit is cleared " + "for csrow %d (node %d)\n", i, + pvt->node_id); + continue; /* CSBE bit is cleared */ + } + + base = base_from_dcsb(dcsb); + mask = ~mask_from_dcsm(dcsm); + + if ((input_addr & mask) == (base & mask)) { + debugf2("InputAddr 0x%lx matches csrow %d " + "(node %d)\n", (unsigned long) input_addr, i, + pvt->node_id); + return i; /* success: csrow i matches */ + } + } + + debugf2("no matching csrow for InputAddr 0x%lx (node %d)\n", + (unsigned long) input_addr, pvt->node_id); + return -1; /* failed to find matching csrow */ +} + +/* input_addr is an InputAddr associated with the node represented by mci. + * Translate input_addr to a DramAddr and return the result. + */ +static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr) +{ + struct k8_pvt *pvt; + int node_id, intlv_shift; + u64 bits, dram_addr; + u32 intlv_sel; + + /* Near the start of section 3.4.4 (p. 70), the k8 documentation shows + * how to translate a DramAddr to an InputAddr. Here we reverse this + * procedure. When translating from a DramAddr to an InputAddr, the + * bits used for node interleaving are discarded. Here we recover + * these bits from the IntlvSel field of the DRAM Limit register + * (section 3.4.4.2) for the node that input_addr is associated with. + */ + + pvt = mci->pvt_info; + node_id = pvt->node_id; + BUG_ON((node_id < 0) || (node_id > 7)); + intlv_shift = num_node_interleave_bits((pvt->dbr[0] >> 8) & 0x07); + + if (intlv_shift == 0) { + debugf1("node interleaving disabled: InputAddr 0x%lx " + "translates to DramAddr of same value\n", + (unsigned long) input_addr); + return input_addr; + } + + bits = ((input_addr & 0xffffff000ull) << intlv_shift) + + (input_addr & 0xfff); + intlv_sel = pvt->dlr[node_id] & (((1 << intlv_shift) - 1) << 8); + dram_addr = bits + (intlv_sel << 4); + debugf1("InputAddr 0x%lx translates to DramAddr 0x%lx " + "(%d node interleave bits)\n", (unsigned long) input_addr, + (unsigned long) dram_addr, intlv_shift); + return dram_addr; +} + +/* dram_addr is a DramAddr that maps to the node represented by mci. Convert + * dram_addr to a SysAddr and return the result. + */ +static u64 dram_addr_to_sys_addr(struct mem_ctl_info *mci, u64 dram_addr) +{ + struct k8_pvt *pvt; + u64 hole_base, hole_offset, hole_size, base, limit, sys_addr; + + pvt = mci->pvt_info; + + if (!get_dram_hole_info(mci, &hole_base, &hole_offset, &hole_size)) { + if ((dram_addr >= hole_base) && + (dram_addr < (hole_base + hole_size))) { + /* use DHAR to translate DramAddr to SysAddr */ + sys_addr = dram_addr + hole_offset; + debugf1("using DHAR to translate DramAddr 0x%lx to " + "SysAddr 0x%lx\n", (unsigned long) dram_addr, + (unsigned long) sys_addr); + return sys_addr; + } + } + + get_base_and_limit(pvt, pvt->node_id, &base, &limit); + sys_addr = dram_addr + base; + + /* The sys_addr we have computed up to this point is a 40-bit value + * because the k8 deals with 40-bit values. However, the value we are + * supposed to return is a full 64-bit physical address. The AMD + * x86-64 architecture specifies that the most significant implemented + * address bit through bit 63 of a physical address must be either all + * 0s or all 1s. Therefore we sign-extend the 40-bit sys_addr to a + * 64-bit value below. See section 3.4.2 of AMD publication 24592: + * AMD x86-64 Architecture Programmer's Manual Volume 1 Application + * Programming. + */ + sys_addr |= ~((sys_addr & (1ull << 39)) - 1); + + debugf1("Using DRAM Base register for node %d to translate " + "DramAddr 0x%lx to SysAddr 0x%lx\n", pvt->node_id, + (unsigned long) dram_addr, (unsigned long) sys_addr); + return sys_addr; +} + +/* input_addr is an InputAddr associated with the node given by mci. + * Translate input_addr to a SysAddr and return the result. + */ +static inline u64 input_addr_to_sys_addr(struct mem_ctl_info *mci, + u64 input_addr) +{ + return dram_addr_to_sys_addr( + mci, input_addr_to_dram_addr(mci, input_addr)); +} + +/* Find the minimum and maximum InputAddr values that map to the given csrow. + * Pass back these values in *input_addr_min and *input_addr_max. + */ +static void find_csrow_limits(struct mem_ctl_info *mci, int csrow, + u64 *input_addr_min, u64 *input_addr_max) +{ + struct k8_pvt *pvt; + u64 base, mask; + + pvt = mci->pvt_info; + BUG_ON((csrow < 0) || (csrow >= K8_NR_CSROWS)); + base = base_from_dcsb(pvt->dcsb[csrow]); + mask = mask_from_dcsm(pvt->dcsm[csrow]); + *input_addr_min = base & ~mask; + + /* To find the max InputAddr for the csrow, start with the base + * address and set all bits that are "don't care" bits in the test at + * the start of section 3.5.4 (p. 84). The "don't care" bits are all + * set bits in the mask and all bits in the gaps between bit ranges + * [35-25] and [19-13]. The value 0x1f01fff represents bits [24-20] + * and [12-0], which are all bits in the above-mentioned gaps. + */ + *input_addr_max = base | mask | 0x1f01fff; +} + +/* Extract error address from MCA NB Address Low (section 3.6.4.5) and + * MCA NB Address High (section 3.6.4.6) register values and return the + * result. + */ +static inline u64 error_address_from_k8_error_info( + struct k8_error_info *info) +{ + return (((u64) (info->error_info.nbeah & 0xff)) << 32) + + (info->error_info.nbeal & ~0x03); +} + +static inline void error_address_to_page_and_offset(u64 error_address, + u32 *page, u32 *offset) +{ + *page = (u32) (error_address >> PAGE_SHIFT); + *offset = ((u32) error_address) & ~PAGE_MASK; +} + +/* Return 1 if registers contain valid error information. Else return 0. */ +static inline int k8_error_info_valid(struct k8_error_info_regs *regs) +{ + return ((regs->nbsh & K8_NBSH_VALID_BIT) != 0); +} + +/* return 0 if regs contains valid error info; else return 1 */ +static int k8_get_error_info_regs(struct mem_ctl_info *mci, + struct k8_error_info_regs *regs) +{ + struct k8_pvt *pvt; + + pvt = mci->pvt_info; + pci_read_config_dword(pvt->misc_ctl, K8_NBSH, ®s->nbsh); + + if (!k8_error_info_valid(regs)) + return 1; + + pci_read_config_dword(pvt->misc_ctl, K8_NBSL, ®s->nbsl); + pci_read_config_dword(pvt->misc_ctl, K8_NBEAH, ®s->nbeah); + pci_read_config_dword(pvt->misc_ctl, K8_NBEAL, ®s->nbeal); + return 0; +} + +static void k8_get_error_info(struct mem_ctl_info *mci, + struct k8_error_info *info) +{ + struct k8_pvt *pvt; + struct k8_error_info_regs regs; + + pvt = mci->pvt_info; + info->race_condition_detected = 0; + + if (k8_get_error_info_regs(mci, &info->error_info)) + return; + + /* + * Here's the problem with the K8's EDAC reporting: + * There are four registers which report pieces of error + * information. These four registers are shared between + * CEs and UEs. Furthermore, contrary to what is stated in + * the OBKG, the overflow bit is never used! Every error + * always updates the reporting registers. + * + * Can you see the race condition? All four error reporting + * registers must be read before a new error updates them! + * There is no way to read all four registers atomically. The + * best than can be done is to detect that a race has occured + * and then report the error without any kind of precision. + * + * What is still positive is that errors are + * still reported and thus problems can still be detected - + * just not localized because the syndrome and address are + * spread out across registers. + * + * Grrrrr!!!!! Here's hoping that AMD fixes this in some + * future K8 rev. UEs and CEs should have separate + * register sets with proper overflow bits that are used! + * At very least the problem can be fixed by honoring the + * ErrValid bit in nbsh and not updating registers - just + * set the overflow bit - unless the current error is CE + * and the new error is UE which would be the only situation + * for overwriting the current values. + */ + + regs = info->error_info; + + /* Use info from the second read - most current */ + if (unlikely(k8_get_error_info_regs(mci, &info->error_info))) + return; + + /* clear the error */ + pci_write_bits32(pvt->misc_ctl, K8_NBSH, 0, K8_NBSH_VALID_BIT); + + pci_read_config_dword(pvt->misc_ctl, K8_NBCFG, &info->nbcfg); + info->race_condition_detected = + ((regs.nbsh != info->error_info.nbsh) || + (regs.nbsl != info->error_info.nbsl) || + (regs.nbeah != info->error_info.nbeah) || + (regs.nbeal != info->error_info.nbeal)); +} + +static inline void decode_gart_tlb_error(struct mem_ctl_info *mci, + struct k8_error_info *info) +{ + u32 err_code; + u32 ec_tt; /* error code transaction type (2b) */ + u32 ec_ll; /* error code cache level (2b) */ + + err_code = info->error_info.nbsl & 0xffffUL; + ec_tt = (err_code >> 2) & 0x03UL; + ec_ll = (err_code >> 0) & 0x03UL; + k8_mc_printk(mci, KERN_ERR, + "GART TLB errorr: transaction type(%s), " + "cache level(%s)\n", tt_msgs[ec_tt], ll_msgs[ec_ll]); +} + +static inline void decode_cache_error(struct mem_ctl_info *mci, + struct k8_error_info *info) +{ + u32 err_code; + u32 ec_rrrr; /* error code memory transaction (4b) */ + u32 ec_tt; /* error code transaction type (2b) */ + u32 ec_ll; /* error code cache level (2b) */ + + err_code = info->error_info.nbsl & 0xffffUL; + ec_rrrr = (err_code >> 4) & 0x0fUL; + ec_tt = (err_code >> 2) & 0x03UL; + ec_ll = (err_code >> 0) & 0x03UL; + k8_mc_printk(mci, KERN_ERR, + "cache heirarchy error: memory transaction type(%s), " + "transaction type(%s), cache level(%s)\n", + memtt_msgs[ec_rrrr], tt_msgs[ec_tt], ll_msgs[ec_ll]); +} + +/* sys_addr is an error address (a SysAddr) extracted from the MCA NB Address + * Low (section 3.6.4.5) and MCA NB Address High (section 3.6.4.6) registers + * of a node that detected an ECC memory error. mci represents the node that + * the error address maps to (possibly different from the node that detected + * the error). Return the number of the csrow that sys_addr maps to, or -1 on + * error. + */ +static int sys_addr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr) +{ + int csrow; + + csrow = input_addr_to_csrow(mci, + sys_addr_to_input_addr(mci, sys_addr)); + + if (csrow == -1) + k8_mc_printk(mci, KERN_ERR, + "Failed to translate InputAddr to csrow for " + "address 0x%lx\n", (unsigned long) sys_addr); + + return csrow; +} + +static void k8_handle_ce(struct mem_ctl_info *mci, struct k8_error_info *info) +{ + struct k8_pvt *pvt; + unsigned syndrome; + u64 error_address; + u32 page, offset; + int channel, csrow; + struct mem_ctl_info *log_mci, *src_mci; + + log_mci = mci; + pvt = mci->pvt_info; + + if ((info->error_info.nbsh & BIT(26)) == 0) + goto no_info; /* error address not valid */ + + error_address = error_address_from_k8_error_info(info); + syndrome = ((info->error_info.nbsh >> 15) & 0xff); + + if (info->nbcfg & BIT(23)) { + /* chipkill ecc mode */ + syndrome += (info->error_info.nbsl >> 16) & 0xff00; + channel = chan_from_chipkill_syndrome(syndrome); + + if (channel < 0) { + /* If the syndrome couldn't be found then the race + * condition for error reporting registers likely + * occurred. There's alot more in doubt than just the + * channel. Might as well just log the error without + * any info. + */ + k8_mc_printk(mci, KERN_WARNING, + "unknown syndrome 0x%x - possible error " + "reporting race\n", syndrome); + goto no_info; + } + } else + /* non-chipkill ecc mode + * + * The k8 documentation is unclear about how to determine the + * channel number when using non-chipkill memory. This method + * was obtained from email communication with someone at AMD. + */ + channel = ((error_address & BIT(3)) != 0); + + /* Find out which node the error address belongs to. This may be + * different from the node that detected the error. + */ + if ((src_mci = find_mc_by_sys_addr(mci, error_address)) == NULL) { + k8_mc_printk(mci, KERN_ERR, + "failed to map error address 0x%lx to a node\n", + (unsigned long) error_address); + goto no_info; + } + + log_mci = src_mci; + + if ((csrow = sys_addr_to_csrow(log_mci, error_address)) < 0) + goto no_info; + + error_address_to_page_and_offset(error_address, &page, &offset); + edac_mc_handle_ce(log_mci, page, offset, syndrome, csrow, channel, + EDAC_MOD_STR); + return; + +no_info: + edac_mc_handle_ce_no_info(log_mci,EDAC_MOD_STR); +} + +static void k8_handle_ue(struct mem_ctl_info *mci, struct k8_error_info *info) +{ + int csrow; + u64 error_address; + u32 page, offset; + struct mem_ctl_info *log_mci, *src_mci; + + log_mci = mci; + + if ((info->error_info.nbsh & BIT(26)) == 0) + goto no_info; /* error address not valid */ + + error_address = error_address_from_k8_error_info(info); + + /* Find out which node the error address belongs to. This may be + * different from the node that detected the error. + */ + if ((src_mci = find_mc_by_sys_addr(mci, error_address)) == NULL) { + k8_mc_printk(mci, KERN_ERR, + "failed to map error address 0x%lx to a node\n", + (unsigned long) error_address); + goto no_info; + } + + log_mci = src_mci; + + if ((csrow = sys_addr_to_csrow(log_mci, error_address)) < 0) + goto no_info; + + error_address_to_page_and_offset(error_address, &page, &offset); + edac_mc_handle_ue(log_mci, page, offset, csrow, EDAC_MOD_STR); + return; + +no_info: + edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); +} + +static void decode_bus_error(struct mem_ctl_info *mci, + struct k8_error_info *info) +{ + u32 err_code, ext_ec; + u32 ec_pp; /* error code participating processor (2p) */ + u32 ec_to; /* error code timed out (1b) */ + u32 ec_rrrr; /* error code memory transaction (4b) */ + u32 ec_ii; /* error code memory or I/O (2b) */ + u32 ec_ll; /* error code cache level (2b) */ + + debugf0("MC%d: %s()\n", mci->mc_idx, __func__); + err_code = info->error_info.nbsl & 0xffffUL; + ec_pp = (err_code >> 9) & 0x03UL; + ec_to = (err_code >> 8) & 0x01UL; + ec_rrrr = (err_code >> 4) & 0x0fUL; + ec_ii = (err_code >> 2) & 0x03UL; + ec_ll = (err_code >> 0) & 0x03UL; + ext_ec = (info->error_info.nbsl >> 16) & 0xfUL; + + /* FIXME - these should report through EDAC channels */ + k8_mc_printk(mci, KERN_ERR, "general bus error: participating " + "processor(%s), time-out(%s) memory transaction " + "type(%s), mem or i/o(%s), cache level(%s)\n", + pp_msgs[ec_pp], to_msgs[ec_to], memtt_msgs[ec_rrrr], + ii_msgs[ec_ii], ll_msgs[ec_ll]); + + if (ec_pp & 0x02) + return; /* We aren't the node involved */ + + /* FIXME - other errors should have other error handling mechanisms */ + if (ext_ec && (ext_ec != 0x8)) { + k8_mc_printk(mci, KERN_ERR, + "no special error handling for this error\n"); + return; + } + + if (info->error_info.nbsh & BIT(14)) + k8_handle_ce(mci, info); + else if (info->error_info.nbsh & BIT(13)) + k8_handle_ue(mci, info); + + /* If main error is CE then overflow must be CE. If main error is UE + * then overflow is unknown. We'll call the overflow a CE - if + * panic_on_ue is set then we're already panic'ed and won't arrive + * here. If panic_on_ue is not set then apparently someone doesn't + * think that UE's are catastrophic. + */ + if (info->error_info.nbsh & BIT(30)) + edac_mc_handle_ce_no_info(mci, + EDAC_MOD_STR " Error Overflow set"); +} + +/* return 1 if error found or 0 if error not found */ +static int k8_process_error_info(struct mem_ctl_info *mci, + struct k8_error_info *info, int handle_errors) +{ + struct k8_pvt *pvt; + struct k8_error_info_regs *regs; + u32 err_code, ext_ec; + int gart_tlb_error; + + pvt = mci->pvt_info; + + /* check for an error */ + if (!k8_error_info_valid(&info->error_info)) + return 0; + + if (!handle_errors) + return 1; + + if (info->race_condition_detected) + k8_mc_printk(mci, KERN_WARNING, "race condition detected!\n"); + + gart_tlb_error = 0; + regs = &info->error_info; + err_code = info->error_info.nbsl & 0xffffUL; + ext_ec = (info->error_info.nbsl >> 16) & 0x0fUL; + debugf1("NorthBridge ERROR: mci(0x%p) node(%d) ErrAddr(0x%.8x-%.8x) " + "nbsh(0x%.8x) nbsl(0x%.8x)\n", mci, pvt->node_id, regs->nbeah, + regs->nbeal, regs->nbsh, regs->nbsl); + + if ((err_code & 0xfff0UL) == 0x0010UL) { + debugf1("GART TLB error\n"); + gart_tlb_error = 1; + decode_gart_tlb_error(mci, info); + } else if ((err_code & 0xff00UL) == 0x0100UL) { + debugf1("Cache error\n"); + decode_cache_error(mci, info); + } else if ((err_code & 0xf800UL) == 0x0800UL) { + debugf1("Bus error\n"); + decode_bus_error(mci, info); + } else + /* shouldn't reach here! */ + k8_mc_printk(mci, KERN_WARNING, + "%s(): unknown MCE error 0x%x\n", __func__, + err_code); + + k8_mc_printk(mci, KERN_ERR, "extended error code: %s\n", + ext_msgs[ext_ec]); + + if (((ext_ec >= 1 && ext_ec <= 4) || (ext_ec == 6)) && + ((info->error_info.nbsh >> 4) & 0x07UL)) + k8_mc_printk(mci, KERN_ERR, + "Error on hypertransport link: %s\n", + htlink_msgs[(info->error_info.nbsh >> 4) & 0x07UL]); + + /* GART errors are benign as per AMD, do not panic on them */ + if (!gart_tlb_error && (regs->nbsh & BIT(29))) { + k8_mc_printk(mci, KERN_CRIT, "uncorrected error\n"); + edac_mc_handle_ue_no_info(mci, "UE bit is set\n"); + } + + if (regs->nbsh & BIT(25)) + panic("MC%d: processor context corrupt", mci->mc_idx); + + return 1; +} + +static void k8_check(struct mem_ctl_info *mci) +{ + struct k8_error_info info; + + debugf3("%s()\n", __func__); + k8_get_error_info(mci, &info); + k8_process_error_info(mci, &info, 1); +} + +static int k8_get_devs(struct mem_ctl_info *mci, int dev_idx) +{ + const struct k8_dev_info *k8_dev = &k8_devs[dev_idx]; + struct k8_pvt *pvt; + struct pci_dev *pdev; + + pdev = to_pci_dev(mci->dev); + pvt = mci->pvt_info; + + /* The address mapping device provides a table that indicates which + * physical address ranges are owned by which node. Each node's + * memory controller has memory controller addresses that begin at + * 0x0. + */ + pvt->addr_map = pci_get_related_function(PCI_VENDOR_ID_AMD, + k8_dev->addr_map, pdev); + + if (pvt->addr_map == NULL) { + k8_printk(KERN_ERR, "error address map device not found: " + "vendor %x device 0x%x (broken BIOS?)\n", + PCI_VENDOR_ID_AMD, k8_dev->addr_map); + return 1; + } + + debugf1("Addr Map device PCI Bus ID:\t%s\n", + pci_name(pvt->addr_map)); + + pvt->misc_ctl = pci_get_related_function(PCI_VENDOR_ID_AMD, + k8_dev->misc_ctl, pdev); + + if (pvt->misc_ctl == NULL) { + pci_dev_put(pvt->addr_map); + pvt->addr_map = NULL; + k8_printk(KERN_ERR, "error miscellaneous device not found: " + "vendor %x device 0x%x (broken BIOS?)\n", + PCI_VENDOR_ID_AMD, k8_dev->misc_ctl); + return 1; + } + + debugf1("Misc device PCI Bus ID:\t\t%s\n", + pci_name(pvt->misc_ctl)); + + return 0; +} + +static void k8_get_mc_regs(struct mem_ctl_info *mci) +{ + struct k8_pvt *pvt; + struct pci_dev *pdev; + int i; + + pdev = to_pci_dev(mci->dev); + pvt = mci->pvt_info; + debugf1("k8 regs:\n"); + + for (i = 0; i < MAX_K8_NODES; i++) { + pci_read_config_dword(pvt->addr_map, K8_DBR + (i * 8), + &pvt->dbr[i]); + pci_read_config_dword(pvt->addr_map, K8_DLR + (i * 8), + &pvt->dlr[i]); + debugf1(" dbr[%d]: 0x%x\n", i, pvt->dbr[i]); + debugf1(" dlr[%d]: 0x%x\n", i, pvt->dlr[i]); + } + + pci_read_config_dword(pvt->misc_ctl, K8_NBCAP, &pvt->nbcap); + debugf1(" nbcap: %u\n", pvt->nbcap); + + for (i = 0; i < K8_NR_CSROWS; i++) { + pci_read_config_dword(pdev, K8_DCSB + (i * 4), &pvt->dcsb[i]); + pci_read_config_dword(pdev, K8_DCSM + (i * 4), &pvt->dcsm[i]); + debugf1(" dcsb[%d]: 0x%x\n", i, pvt->dcsb[i]); + debugf1(" dcsm[%d]: 0x%x\n", i, pvt->dcsm[i]); + } + + pci_read_config_dword(pvt->addr_map, K8_DHAR, &pvt->dhar); + pci_read_config_dword(pdev, K8_DBAM, &pvt->dbam); + debugf1(" dhar: 0x%x\n", pvt->dhar); + debugf1(" dbam: 0x%x\n", pvt->dbam); +} + +/* Return 1 if dual channel mode is active. Else return 0. */ +static inline int dual_channel_active(u32 dcl) +{ + return (dcl >> 16) & 0x1; +} + +static u32 csrow_nr_pages(int csrow_nr, struct k8_pvt *pvt) +{ + u32 cs; + + /* The math on this doesn't look right on the surface because x/2*4 + * can be simplified to x*2 but this expression makes use of the fact + * that it is integral math where 1/2=0 + */ + cs = (pvt->dbam >> ((csrow_nr / 2) * 4)) & 0xF; /* PG88 */ + + /* This line is tricky. It collapses the table used by revision D and + * later to one that matches revision CG and earlier + */ + cs -= (node_rev(pvt->node_id) >= OPTERON_CPU_REV_D) ? + (cs > 8 ? 4 : (cs > 5 ? 3 : (cs > 2 ? 1 : 0))) : 0; + + /* 25 is 32MiB minimum DIMM size */ + return 1 << (cs + 25 - PAGE_SHIFT + dual_channel_active(pvt->dcl)); +} + +static int k8_init_csrows(struct mem_ctl_info *mci) +{ + struct csrow_info *csrow; + struct k8_pvt *pvt; + int i, empty; + u64 input_addr_min, input_addr_max, sys_addr; + u32 nbcfg; + + pvt = mci->pvt_info; + pci_read_config_dword(pvt->misc_ctl, K8_NBCFG, &nbcfg); + empty = 1; + + for (i = 0; i < K8_NR_CSROWS; i++) { + csrow = &mci->csrows[i]; + + if ((pvt->dcsb[i] & 0x01) == 0) { + debugf1("csrow %d empty for node %d\n", i, + pvt->node_id); + continue; /* empty */ + } + + debugf1("revision for this node (%d) is %d\n", + pvt->node_id, node_rev(pvt->node_id)); + empty = 0; + csrow->nr_pages = csrow_nr_pages(i, pvt); + find_csrow_limits(mci, i, &input_addr_min, &input_addr_max); + sys_addr = input_addr_to_sys_addr(mci, input_addr_min); + csrow->first_page = (u32) (sys_addr >> PAGE_SHIFT); + sys_addr = input_addr_to_sys_addr(mci, input_addr_max); + csrow->last_page = (u32) (sys_addr >> PAGE_SHIFT); + csrow->page_mask = ~mask_from_dcsm(pvt->dcsm[i]); + csrow->grain = 8; /* 8 bytes of resolution */ + csrow->mtype = ((pvt->dcl >> 18) & 0x1) ? MEM_DDR : MEM_RDDR; + csrow->dtype = ((pvt->dcl >> (20 + (i / 2))) & 0x01) ? + DEV_X4 : DEV_UNKNOWN; + debugf1("for node %d csrow %d:\n nr_pages: %u " + "input_addr_min: 0x%lx input_addr_max: 0x%lx " + "sys_addr: 0x%lx first_page: 0x%lx last_page: 0x%lx " + "page_mask: 0x%lx\n", pvt->node_id, i, + (unsigned) csrow->nr_pages, + (unsigned long) input_addr_min, + (unsigned long) input_addr_max, + (unsigned long) sys_addr, + csrow->first_page, csrow->last_page, + csrow->page_mask); + + if (nbcfg & BIT(22)) + csrow->edac_mode = (nbcfg & BIT(23)) ? + EDAC_S4ECD4ED : EDAC_SECDED; + else + csrow->edac_mode = EDAC_NONE; + } + + return empty; +} + +static void k8_enable_error_reporting(struct mem_ctl_info *mci) +{ + struct k8_pvt *pvt; + u32 mc4ctl_l=0, mc4ctl_h=0, mcgctl_l=0, mcgctl_h=0; + + pvt = mci->pvt_info; + pci_write_bits32(pvt->misc_ctl, K8_NBCTL, 0x3UL, 0x3UL); + do_rdmsr(pvt->node_id, K8_MSR_MC4CTL, &mc4ctl_l, &mc4ctl_h); + mc4ctl_l |= BIT(0) | BIT(1); + do_wrmsr(pvt->node_id, K8_MSR_MC4CTL, mc4ctl_l, mc4ctl_h); + do_rdmsr(pvt->node_id, K8_MSR_MC4CTL, &mc4ctl_l, &mc4ctl_h); + do_rdmsr(pvt->node_id, K8_MSR_MCGCTL, &mcgctl_l, &mcgctl_h); + mcgctl_l |= BIT(4); + do_wrmsr(pvt->node_id, K8_MSR_MCGCTL, mcgctl_l, mcgctl_h); + do_rdmsr(pvt->node_id, K8_MSR_MCGCTL, &mcgctl_l, &mcgctl_h); +} + +static int k8_probe1(struct pci_dev *pdev, int dev_idx) +{ + struct mem_ctl_info *mci; + struct k8_pvt *pvt; + u32 dcl, dual_channel; + + debugf0("%s()\n", __func__); + build_node_revision_table(); + debugf1("pdev bus %u devfn %u\n", pdev->bus->number, pdev->devfn); + pci_read_config_dword(pdev, K8_DCL, &dcl); + dual_channel = dual_channel_active(dcl); + debugf1("dual_channel is %u (dcl is 0x%x)\n", dual_channel, dcl); + mci = edac_mc_alloc(sizeof(*pvt), K8_NR_CSROWS, dual_channel + 1); + + if (mci == NULL) + return -ENOMEM; + + debugf0("%s(): mci = %p\n", __func__, mci); + pvt = mci->pvt_info; + pvt->dcl = dcl; + mci->dev = &pdev->dev; + pvt->node_id = MCI_TO_NODE_ID(mci); + + if (k8_get_devs(mci, dev_idx)) + goto fail0; + + k8_get_mc_regs(mci); + mci->mtype_cap = MEM_FLAG_DDR | MEM_FLAG_RDDR; + mci->edac_ctl_cap = EDAC_FLAG_NONE; + debugf1("Initializing mci->edac_cap to EDAC_FLAG_NONE\n"); + mci->edac_cap = EDAC_FLAG_NONE; + + if ((pvt->nbcap >> 3) & 0x1) + mci->edac_ctl_cap |= EDAC_FLAG_SECDED; + + if ((pvt->nbcap >> 4) & 0x1) + mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED; + + if ((pvt->dcl >> 17) & 0x1) { + debugf1("setting EDAC_FLAG_SECDED in mci->edac_cap\n"); + mci->edac_cap |= EDAC_FLAG_SECDED; + + if (dual_channel) { + debugf1("setting EDAC_FLAG_S4ECD4ED in " + "mci->edac_cap\n"); + mci->edac_cap |= EDAC_FLAG_S4ECD4ED; + } + } + + mci->mod_name = EDAC_MOD_STR; + mci->mod_ver = EDAC_K8_VERSION; + mci->ctl_name = k8_devs[dev_idx].ctl_name; + mci->edac_check = k8_check; + mci->ctl_page_to_phys = NULL; + + if (k8_init_csrows(mci)) { + debugf1("Setting mci->edac_cap to EDAC_FLAG_NONE " + "because k8_init_csrows() returned nonzero " + "value\n"); + mci->edac_cap = EDAC_FLAG_NONE; /* no csrows found */ + } else + k8_enable_error_reporting(mci); + + if (edac_mc_add_mc(mci, pvt->node_id)) { + debugf1("%s(): failed edac_mc_add_mc()\n", __func__); + /* FIXME: perhaps some code should go here that disables error + * reporting if we just enabled it + */ + goto fail1; + } + + debugf1("%s(): success\n", __func__); + return 0; + +fail1: + pci_dev_put(pvt->addr_map); + pci_dev_put(pvt->misc_ctl); + +fail0: + edac_mc_free(mci); + return -ENODEV; +} + +/* returns count (>= 0), or negative on error */ +static int __devinit k8_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + debugf0("%s()\n", __func__); + + /* wake up and enable device */ + return pci_enable_device(pdev) ? + -EIO : k8_probe1(pdev, ent->driver_data); +} + +static void __devexit k8_remove_one(struct pci_dev *pdev) +{ + struct mem_ctl_info *mci; + struct k8_pvt *pvt; + + debugf0("%s()\n", __func__); + + if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL) + return; + + pvt = mci->pvt_info; + pci_dev_put(pvt->addr_map); + pci_dev_put(pvt->misc_ctl); + edac_mc_free(mci); +} + +static const struct pci_device_id k8_pci_tbl[] __devinitdata = { + {PCI_VEND_DEV(AMD, OPT_2_MEMCTL), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + OPTERON}, + {0,} /* 0 terminated list. */ +}; + +MODULE_DEVICE_TABLE(pci, k8_pci_tbl); + +static struct pci_driver k8_driver = { + .name = EDAC_MOD_STR, + .probe = k8_init_one, + .remove = __devexit_p(k8_remove_one), + .id_table = k8_pci_tbl, +}; + +int __init k8_init(void) +{ + return pci_module_init(&k8_driver); +} + +static void __exit k8_exit(void) +{ + pci_unregister_driver(&k8_driver); +} + +module_init(k8_init); +module_exit(k8_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh"); +MODULE_DESCRIPTION("MC support for AMD K8 memory controllers - " EDAC_K8_VERSION ); diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c new file mode 100644 index 000000000..35ad1b032 --- /dev/null +++ b/drivers/hwmon/abituguru.c @@ -0,0 +1,1455 @@ +/* + abituguru.c Copyright (c) 2005-2006 Hans de Goede <j.w.r.degoede@hhs.nl> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + This driver supports the sensor part of the custom Abit uGuru chip found + on Abit uGuru motherboards. Note: because of lack of specs the CPU / RAM / + etc voltage & frequency control is not supported! +*/ +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/jiffies.h> +#include <linux/mutex.h> +#include <linux/err.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <asm/io.h> + +/* Banks */ +#define ABIT_UGURU_ALARM_BANK 0x20 /* 1x 3 bytes */ +#define ABIT_UGURU_SENSOR_BANK1 0x21 /* 16x volt and temp */ +#define ABIT_UGURU_FAN_PWM 0x24 /* 3x 5 bytes */ +#define ABIT_UGURU_SENSOR_BANK2 0x26 /* fans */ +/* max nr of sensors in bank1, a bank1 sensor can be in, temp or nc */ +#define ABIT_UGURU_MAX_BANK1_SENSORS 16 +/* Warning if you increase one of the 2 MAX defines below to 10 or higher you + should adjust the belonging _NAMES_LENGTH macro for the 2 digit number! */ +/* max nr of sensors in bank2, currently mb's with max 6 fans are known */ +#define ABIT_UGURU_MAX_BANK2_SENSORS 6 +/* max nr of pwm outputs, currently mb's with max 5 pwm outputs are known */ +#define ABIT_UGURU_MAX_PWMS 5 +/* uGuru sensor bank 1 flags */ /* Alarm if: */ +#define ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE 0x01 /* temp over warn */ +#define ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE 0x02 /* volt over max */ +#define ABIT_UGURU_VOLT_LOW_ALARM_ENABLE 0x04 /* volt under min */ +#define ABIT_UGURU_TEMP_HIGH_ALARM_FLAG 0x10 /* temp is over warn */ +#define ABIT_UGURU_VOLT_HIGH_ALARM_FLAG 0x20 /* volt is over max */ +#define ABIT_UGURU_VOLT_LOW_ALARM_FLAG 0x40 /* volt is under min */ +/* uGuru sensor bank 2 flags */ /* Alarm if: */ +#define ABIT_UGURU_FAN_LOW_ALARM_ENABLE 0x01 /* fan under min */ +/* uGuru sensor bank common flags */ +#define ABIT_UGURU_BEEP_ENABLE 0x08 /* beep if alarm */ +#define ABIT_UGURU_SHUTDOWN_ENABLE 0x80 /* shutdown if alarm */ +/* uGuru fan PWM (speed control) flags */ +#define ABIT_UGURU_FAN_PWM_ENABLE 0x80 /* enable speed control */ +/* Values used for conversion */ +#define ABIT_UGURU_FAN_MAX 15300 /* RPM */ +/* Bank1 sensor types */ +#define ABIT_UGURU_IN_SENSOR 0 +#define ABIT_UGURU_TEMP_SENSOR 1 +#define ABIT_UGURU_NC 2 +/* In many cases we need to wait for the uGuru to reach a certain status, most + of the time it will reach this status within 30 - 90 ISA reads, and thus we + can best busy wait. This define gives the total amount of reads to try. */ +#define ABIT_UGURU_WAIT_TIMEOUT 125 +/* However sometimes older versions of the uGuru seem to be distracted and they + do not respond for a long time. To handle this we sleep before each of the + last ABIT_UGURU_WAIT_TIMEOUT_SLEEP tries. */ +#define ABIT_UGURU_WAIT_TIMEOUT_SLEEP 5 +/* Normally all expected status in abituguru_ready, are reported after the + first read, but sometimes not and we need to poll. */ +#define ABIT_UGURU_READY_TIMEOUT 5 +/* Maximum 3 retries on timedout reads/writes, delay 200 ms before retrying */ +#define ABIT_UGURU_MAX_RETRIES 3 +#define ABIT_UGURU_RETRY_DELAY (HZ/5) +/* Maximum 2 timeouts in abituguru_update_device, iow 3 in a row is an error */ +#define ABIT_UGURU_MAX_TIMEOUTS 2 +/* utility macros */ +#define ABIT_UGURU_NAME "abituguru" +#define ABIT_UGURU_DEBUG(level, format, arg...) \ + if (level <= verbose) \ + printk(KERN_DEBUG ABIT_UGURU_NAME ": " format , ## arg) +/* Macros to help calculate the sysfs_names array length */ +/* sum of strlen of: in??_input\0, in??_{min,max}\0, in??_{min,max}_alarm\0, + in??_{min,max}_alarm_enable\0, in??_beep\0, in??_shutdown\0 */ +#define ABITUGURU_IN_NAMES_LENGTH (11 + 2 * 9 + 2 * 15 + 2 * 22 + 10 + 14) +/* sum of strlen of: temp??_input\0, temp??_max\0, temp??_crit\0, + temp??_alarm\0, temp??_alarm_enable\0, temp??_beep\0, temp??_shutdown\0 */ +#define ABITUGURU_TEMP_NAMES_LENGTH (13 + 11 + 12 + 13 + 20 + 12 + 16) +/* sum of strlen of: fan?_input\0, fan?_min\0, fan?_alarm\0, + fan?_alarm_enable\0, fan?_beep\0, fan?_shutdown\0 */ +#define ABITUGURU_FAN_NAMES_LENGTH (11 + 9 + 11 + 18 + 10 + 14) +/* sum of strlen of: pwm?_enable\0, pwm?_auto_channels_temp\0, + pwm?_auto_point{1,2}_pwm\0, pwm?_auto_point{1,2}_temp\0 */ +#define ABITUGURU_PWM_NAMES_LENGTH (12 + 24 + 2 * 21 + 2 * 22) +/* IN_NAMES_LENGTH > TEMP_NAMES_LENGTH so assume all bank1 sensors are in */ +#define ABITUGURU_SYSFS_NAMES_LENGTH ( \ + ABIT_UGURU_MAX_BANK1_SENSORS * ABITUGURU_IN_NAMES_LENGTH + \ + ABIT_UGURU_MAX_BANK2_SENSORS * ABITUGURU_FAN_NAMES_LENGTH + \ + ABIT_UGURU_MAX_PWMS * ABITUGURU_PWM_NAMES_LENGTH) + +/* All the macros below are named identical to the oguru and oguru2 programs + reverse engineered by Olle Sandberg, hence the names might not be 100% + logical. I could come up with better names, but I prefer keeping the names + identical so that this driver can be compared with his work more easily. */ +/* Two i/o-ports are used by uGuru */ +#define ABIT_UGURU_BASE 0x00E0 +/* Used to tell uGuru what to read and to read the actual data */ +#define ABIT_UGURU_CMD 0x00 +/* Mostly used to check if uGuru is busy */ +#define ABIT_UGURU_DATA 0x04 +#define ABIT_UGURU_REGION_LENGTH 5 +/* uGuru status' */ +#define ABIT_UGURU_STATUS_WRITE 0x00 /* Ready to be written */ +#define ABIT_UGURU_STATUS_READ 0x01 /* Ready to be read */ +#define ABIT_UGURU_STATUS_INPUT 0x08 /* More input */ +#define ABIT_UGURU_STATUS_READY 0x09 /* Ready to be written */ + +/* Constants */ +/* in (Volt) sensors go up to 3494 mV, temp to 255000 millidegrees Celsius */ +static const int abituguru_bank1_max_value[2] = { 3494, 255000 }; +/* Min / Max allowed values for sensor2 (fan) alarm threshold, these values + correspond to 300-3000 RPM */ +static const u8 abituguru_bank2_min_threshold = 5; +static const u8 abituguru_bank2_max_threshold = 50; +/* Register 0 is a bitfield, 1 and 2 are pwm settings (255 = 100%), 3 and 4 + are temperature trip points. */ +static const int abituguru_pwm_settings_multiplier[5] = { 0, 1, 1, 1000, 1000 }; +/* Min / Max allowed values for pwm_settings. Note: pwm1 (CPU fan) is a + special case the minium allowed pwm% setting for this is 30% (77) on + some MB's this special case is handled in the code! */ +static const u8 abituguru_pwm_min[5] = { 0, 170, 170, 25, 25 }; +static const u8 abituguru_pwm_max[5] = { 0, 255, 255, 75, 75 }; + + +/* Insmod parameters */ +static int force; +module_param(force, bool, 0); +MODULE_PARM_DESC(force, "Set to one to force detection."); +static int bank1_types[ABIT_UGURU_MAX_BANK1_SENSORS] = { -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; +module_param_array(bank1_types, int, NULL, 0); +MODULE_PARM_DESC(bank1_types, "Bank1 sensortype autodetection override:\n" + " -1 autodetect\n" + " 0 volt sensor\n" + " 1 temp sensor\n" + " 2 not connected"); +static int fan_sensors; +module_param(fan_sensors, int, 0); +MODULE_PARM_DESC(fan_sensors, "Number of fan sensors on the uGuru " + "(0 = autodetect)"); +static int pwms; +module_param(pwms, int, 0); +MODULE_PARM_DESC(pwms, "Number of PWMs on the uGuru " + "(0 = autodetect)"); + +/* Default verbose is 2, since this driver is still in the testing phase */ +static int verbose = 2; +module_param(verbose, int, 0644); +MODULE_PARM_DESC(verbose, "How verbose should the driver be? (0-3):\n" + " 0 normal output\n" + " 1 + verbose error reporting\n" + " 2 + sensors type probing info\n" + " 3 + retryable error reporting"); + + +/* For the Abit uGuru, we need to keep some data in memory. + The structure is dynamically allocated, at the same time when a new + abituguru device is allocated. */ +struct abituguru_data { + struct class_device *class_dev; /* hwmon registered device */ + struct mutex update_lock; /* protect access to data and uGuru */ + unsigned long last_updated; /* In jiffies */ + unsigned short addr; /* uguru base address */ + char uguru_ready; /* is the uguru in ready state? */ + unsigned char update_timeouts; /* number of update timeouts since last + successful update */ + + /* The sysfs attr and their names are generated automatically, for bank1 + we cannot use a predefined array because we don't know beforehand + of a sensor is a volt or a temp sensor, for bank2 and the pwms its + easier todo things the same way. For in sensors we have 9 (temp 7) + sysfs entries per sensor, for bank2 and pwms 6. */ + struct sensor_device_attribute_2 sysfs_attr[ + ABIT_UGURU_MAX_BANK1_SENSORS * 9 + + ABIT_UGURU_MAX_BANK2_SENSORS * 6 + ABIT_UGURU_MAX_PWMS * 6]; + /* Buffer to store the dynamically generated sysfs names */ + char sysfs_names[ABITUGURU_SYSFS_NAMES_LENGTH]; + + /* Bank 1 data */ + /* number of and addresses of [0] in, [1] temp sensors */ + u8 bank1_sensors[2]; + u8 bank1_address[2][ABIT_UGURU_MAX_BANK1_SENSORS]; + u8 bank1_value[ABIT_UGURU_MAX_BANK1_SENSORS]; + /* This array holds 3 entries per sensor for the bank 1 sensor settings + (flags, min, max for voltage / flags, warn, shutdown for temp). */ + u8 bank1_settings[ABIT_UGURU_MAX_BANK1_SENSORS][3]; + /* Maximum value for each sensor used for scaling in mV/millidegrees + Celsius. */ + int bank1_max_value[ABIT_UGURU_MAX_BANK1_SENSORS]; + + /* Bank 2 data, ABIT_UGURU_MAX_BANK2_SENSORS entries for bank2 */ + u8 bank2_sensors; /* actual number of bank2 sensors found */ + u8 bank2_value[ABIT_UGURU_MAX_BANK2_SENSORS]; + u8 bank2_settings[ABIT_UGURU_MAX_BANK2_SENSORS][2]; /* flags, min */ + + /* Alarms 2 bytes for bank1, 1 byte for bank2 */ + u8 alarms[3]; + + /* Fan PWM (speed control) 5 bytes per PWM */ + u8 pwms; /* actual number of pwms found */ + u8 pwm_settings[ABIT_UGURU_MAX_PWMS][5]; +}; + +/* wait till the uguru is in the specified state */ +static int abituguru_wait(struct abituguru_data *data, u8 state) +{ + int timeout = ABIT_UGURU_WAIT_TIMEOUT; + + while (inb_p(data->addr + ABIT_UGURU_DATA) != state) { + timeout--; + if (timeout == 0) + return -EBUSY; + /* sleep a bit before our last few tries, see the comment on + this where ABIT_UGURU_WAIT_TIMEOUT_SLEEP is defined. */ + if (timeout <= ABIT_UGURU_WAIT_TIMEOUT_SLEEP) + msleep(0); + } + return 0; +} + +/* Put the uguru in ready for input state */ +static int abituguru_ready(struct abituguru_data *data) +{ + int timeout = ABIT_UGURU_READY_TIMEOUT; + + if (data->uguru_ready) + return 0; + + /* Reset? / Prepare for next read/write cycle */ + outb(0x00, data->addr + ABIT_UGURU_DATA); + + /* Wait till the uguru is ready */ + if (abituguru_wait(data, ABIT_UGURU_STATUS_READY)) { + ABIT_UGURU_DEBUG(1, + "timeout exceeded waiting for ready state\n"); + return -EIO; + } + + /* Cmd port MUST be read now and should contain 0xAC */ + while (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) { + timeout--; + if (timeout == 0) { + ABIT_UGURU_DEBUG(1, + "CMD reg does not hold 0xAC after ready command\n"); + return -EIO; + } + msleep(0); + } + + /* After this the ABIT_UGURU_DATA port should contain + ABIT_UGURU_STATUS_INPUT */ + timeout = ABIT_UGURU_READY_TIMEOUT; + while (inb_p(data->addr + ABIT_UGURU_DATA) != ABIT_UGURU_STATUS_INPUT) { + timeout--; + if (timeout == 0) { + ABIT_UGURU_DEBUG(1, + "state != more input after ready command\n"); + return -EIO; + } + msleep(0); + } + + data->uguru_ready = 1; + return 0; +} + +/* Send the bank and then sensor address to the uGuru for the next read/write + cycle. This function gets called as the first part of a read/write by + abituguru_read and abituguru_write. This function should never be + called by any other function. */ +static int abituguru_send_address(struct abituguru_data *data, + u8 bank_addr, u8 sensor_addr, int retries) +{ + /* assume the caller does error handling itself if it has not requested + any retries, and thus be quiet. */ + int report_errors = retries; + + for (;;) { + /* Make sure the uguru is ready and then send the bank address, + after this the uguru is no longer "ready". */ + if (abituguru_ready(data) != 0) + return -EIO; + outb(bank_addr, data->addr + ABIT_UGURU_DATA); + data->uguru_ready = 0; + + /* Wait till the uguru is ABIT_UGURU_STATUS_INPUT state again + and send the sensor addr */ + if (abituguru_wait(data, ABIT_UGURU_STATUS_INPUT)) { + if (retries) { + ABIT_UGURU_DEBUG(3, "timeout exceeded " + "waiting for more input state, %d " + "tries remaining\n", retries); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(ABIT_UGURU_RETRY_DELAY); + retries--; + continue; + } + if (report_errors) + ABIT_UGURU_DEBUG(1, "timeout exceeded " + "waiting for more input state " + "(bank: %d)\n", (int)bank_addr); + return -EBUSY; + } + outb(sensor_addr, data->addr + ABIT_UGURU_CMD); + return 0; + } +} + +/* Read count bytes from sensor sensor_addr in bank bank_addr and store the + result in buf, retry the send address part of the read retries times. */ +static int abituguru_read(struct abituguru_data *data, + u8 bank_addr, u8 sensor_addr, u8 *buf, int count, int retries) +{ + int i; + + /* Send the address */ + i = abituguru_send_address(data, bank_addr, sensor_addr, retries); + if (i) + return i; + + /* And read the data */ + for (i = 0; i < count; i++) { + if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) { + ABIT_UGURU_DEBUG(retries ? 1 : 3, + "timeout exceeded waiting for " + "read state (bank: %d, sensor: %d)\n", + (int)bank_addr, (int)sensor_addr); + break; + } + buf[i] = inb(data->addr + ABIT_UGURU_CMD); + } + + /* Last put the chip back in ready state */ + abituguru_ready(data); + + return i; +} + +/* Write count bytes from buf to sensor sensor_addr in bank bank_addr, the send + address part of the write is always retried ABIT_UGURU_MAX_RETRIES times. */ +static int abituguru_write(struct abituguru_data *data, + u8 bank_addr, u8 sensor_addr, u8 *buf, int count) +{ + /* We use the ready timeout as we have to wait for 0xAC just like the + ready function */ + int i, timeout = ABIT_UGURU_READY_TIMEOUT; + + /* Send the address */ + i = abituguru_send_address(data, bank_addr, sensor_addr, + ABIT_UGURU_MAX_RETRIES); + if (i) + return i; + + /* And write the data */ + for (i = 0; i < count; i++) { + if (abituguru_wait(data, ABIT_UGURU_STATUS_WRITE)) { + ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for " + "write state (bank: %d, sensor: %d)\n", + (int)bank_addr, (int)sensor_addr); + break; + } + outb(buf[i], data->addr + ABIT_UGURU_CMD); + } + + /* Now we need to wait till the chip is ready to be read again, + so that we can read 0xAC as confirmation that our write has + succeeded. */ + if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) { + ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for read state " + "after write (bank: %d, sensor: %d)\n", (int)bank_addr, + (int)sensor_addr); + return -EIO; + } + + /* Cmd port MUST be read now and should contain 0xAC */ + while (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) { + timeout--; + if (timeout == 0) { + ABIT_UGURU_DEBUG(1, "CMD reg does not hold 0xAC after " + "write (bank: %d, sensor: %d)\n", + (int)bank_addr, (int)sensor_addr); + return -EIO; + } + msleep(0); + } + + /* Last put the chip back in ready state */ + abituguru_ready(data); + + return i; +} + +/* Detect sensor type. Temp and Volt sensors are enabled with + different masks and will ignore enable masks not meant for them. + This enables us to test what kind of sensor we're dealing with. + By setting the alarm thresholds so that we will always get an + alarm for sensor type X and then enabling the sensor as sensor type + X, if we then get an alarm it is a sensor of type X. */ +static int __devinit +abituguru_detect_bank1_sensor_type(struct abituguru_data *data, + u8 sensor_addr) +{ + u8 val, buf[3]; + int i, ret = -ENODEV; /* error is the most common used retval :| */ + + /* If overriden by the user return the user selected type */ + if (bank1_types[sensor_addr] >= ABIT_UGURU_IN_SENSOR && + bank1_types[sensor_addr] <= ABIT_UGURU_NC) { + ABIT_UGURU_DEBUG(2, "assuming sensor type %d for bank1 sensor " + "%d because of \"bank1_types\" module param\n", + bank1_types[sensor_addr], (int)sensor_addr); + return bank1_types[sensor_addr]; + } + + /* First read the sensor and the current settings */ + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, sensor_addr, &val, + 1, ABIT_UGURU_MAX_RETRIES) != 1) + return -ENODEV; + + /* Test val is sane / usable for sensor type detection. */ + if ((val < 10u) || (val > 240u)) { + printk(KERN_WARNING ABIT_UGURU_NAME + ": bank1-sensor: %d reading (%d) too close to limits, " + "unable to determine sensor type, skipping sensor\n", + (int)sensor_addr, (int)val); + /* assume no sensor is there for sensors for which we can't + determine the sensor type because their reading is too close + to their limits, this usually means no sensor is there. */ + return ABIT_UGURU_NC; + } + + ABIT_UGURU_DEBUG(2, "testing bank1 sensor %d\n", (int)sensor_addr); + /* Volt sensor test, enable volt low alarm, set min value ridicously + high. If its a volt sensor this should always give us an alarm. */ + buf[0] = ABIT_UGURU_VOLT_LOW_ALARM_ENABLE; + buf[1] = 245; + buf[2] = 250; + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, + buf, 3) != 3) + goto abituguru_detect_bank1_sensor_type_exit; + /* Now we need 20 ms to give the uguru time to read the sensors + and raise a voltage alarm */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/50); + /* Check for alarm and check the alarm is a volt low alarm. */ + if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3, + ABIT_UGURU_MAX_RETRIES) != 3) + goto abituguru_detect_bank1_sensor_type_exit; + if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) { + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1, + sensor_addr, buf, 3, + ABIT_UGURU_MAX_RETRIES) != 3) + goto abituguru_detect_bank1_sensor_type_exit; + if (buf[0] & ABIT_UGURU_VOLT_LOW_ALARM_FLAG) { + ABIT_UGURU_DEBUG(2, " found volt sensor\n"); + ret = ABIT_UGURU_IN_SENSOR; + goto abituguru_detect_bank1_sensor_type_exit; + } else + ABIT_UGURU_DEBUG(2, " alarm raised during volt " + "sensor test, but volt low flag not set\n"); + } else + ABIT_UGURU_DEBUG(2, " alarm not raised during volt sensor " + "test\n"); + + /* Temp sensor test, enable sensor as a temp sensor, set beep value + ridicously low (but not too low, otherwise uguru ignores it). + If its a temp sensor this should always give us an alarm. */ + buf[0] = ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE; + buf[1] = 5; + buf[2] = 10; + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, + buf, 3) != 3) + goto abituguru_detect_bank1_sensor_type_exit; + /* Now we need 50 ms to give the uguru time to read the sensors + and raise a temp alarm */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(HZ/20); + /* Check for alarm and check the alarm is a temp high alarm. */ + if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3, + ABIT_UGURU_MAX_RETRIES) != 3) + goto abituguru_detect_bank1_sensor_type_exit; + if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) { + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1, + sensor_addr, buf, 3, + ABIT_UGURU_MAX_RETRIES) != 3) + goto abituguru_detect_bank1_sensor_type_exit; + if (buf[0] & ABIT_UGURU_TEMP_HIGH_ALARM_FLAG) { + ABIT_UGURU_DEBUG(2, " found temp sensor\n"); + ret = ABIT_UGURU_TEMP_SENSOR; + goto abituguru_detect_bank1_sensor_type_exit; + } else + ABIT_UGURU_DEBUG(2, " alarm raised during temp " + "sensor test, but temp high flag not set\n"); + } else + ABIT_UGURU_DEBUG(2, " alarm not raised during temp sensor " + "test\n"); + + ret = ABIT_UGURU_NC; +abituguru_detect_bank1_sensor_type_exit: + /* Restore original settings, failing here is really BAD, it has been + reported that some BIOS-es hang when entering the uGuru menu with + invalid settings present in the uGuru, so we try this 3 times. */ + for (i = 0; i < 3; i++) + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, + sensor_addr, data->bank1_settings[sensor_addr], + 3) == 3) + break; + if (i == 3) { + printk(KERN_ERR ABIT_UGURU_NAME + ": Fatal error could not restore original settings. " + "This should never happen please report this to the " + "abituguru maintainer (see MAINTAINERS)\n"); + return -ENODEV; + } + return ret; +} + +/* These functions try to find out how many sensors there are in bank2 and how + many pwms there are. The purpose of this is to make sure that we don't give + the user the possibility to change settings for non-existent sensors / pwm. + The uGuru will happily read / write whatever memory happens to be after the + memory storing the PWM settings when reading/writing to a PWM which is not + there. Notice even if we detect a PWM which doesn't exist we normally won't + write to it, unless the user tries to change the settings. + + Although the uGuru allows reading (settings) from non existing bank2 + sensors, my version of the uGuru does seem to stop writing to them, the + write function above aborts in this case with: + "CMD reg does not hold 0xAC after write" + + Notice these 2 tests are non destructive iow read-only tests, otherwise + they would defeat their purpose. Although for the bank2_sensors detection a + read/write test would be feasible because of the reaction above, I've + however opted to stay on the safe side. */ +static void __devinit +abituguru_detect_no_bank2_sensors(struct abituguru_data *data) +{ + int i; + + if (fan_sensors > 0 && fan_sensors <= ABIT_UGURU_MAX_BANK2_SENSORS) { + data->bank2_sensors = fan_sensors; + ABIT_UGURU_DEBUG(2, "assuming %d fan sensors because of " + "\"fan_sensors\" module param\n", + (int)data->bank2_sensors); + return; + } + + ABIT_UGURU_DEBUG(2, "detecting number of fan sensors\n"); + for (i = 0; i < ABIT_UGURU_MAX_BANK2_SENSORS; i++) { + /* 0x89 are the known used bits: + -0x80 enable shutdown + -0x08 enable beep + -0x01 enable alarm + All other bits should be 0, but on some motherboards + 0x40 (bit 6) is also high for some of the fans?? */ + if (data->bank2_settings[i][0] & ~0xC9) { + ABIT_UGURU_DEBUG(2, " bank2 sensor %d does not seem " + "to be a fan sensor: settings[0] = %02X\n", + i, (unsigned int)data->bank2_settings[i][0]); + break; + } + + /* check if the threshold is within the allowed range */ + if (data->bank2_settings[i][1] < + abituguru_bank2_min_threshold) { + ABIT_UGURU_DEBUG(2, " bank2 sensor %d does not seem " + "to be a fan sensor: the threshold (%d) is " + "below the minimum (%d)\n", i, + (int)data->bank2_settings[i][1], + (int)abituguru_bank2_min_threshold); + break; + } + if (data->bank2_settings[i][1] > + abituguru_bank2_max_threshold) { + ABIT_UGURU_DEBUG(2, " bank2 sensor %d does not seem " + "to be a fan sensor: the threshold (%d) is " + "above the maximum (%d)\n", i, + (int)data->bank2_settings[i][1], + (int)abituguru_bank2_max_threshold); + break; + } + } + + data->bank2_sensors = i; + ABIT_UGURU_DEBUG(2, " found: %d fan sensors\n", + (int)data->bank2_sensors); +} + +static void __devinit +abituguru_detect_no_pwms(struct abituguru_data *data) +{ + int i, j; + + if (pwms > 0 && pwms <= ABIT_UGURU_MAX_PWMS) { + data->pwms = pwms; + ABIT_UGURU_DEBUG(2, "assuming %d PWM outputs because of " + "\"pwms\" module param\n", (int)data->pwms); + return; + } + + ABIT_UGURU_DEBUG(2, "detecting number of PWM outputs\n"); + for (i = 0; i < ABIT_UGURU_MAX_PWMS; i++) { + /* 0x80 is the enable bit and the low + nibble is which temp sensor to use, + the other bits should be 0 */ + if (data->pwm_settings[i][0] & ~0x8F) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " + "to be a pwm channel: settings[0] = %02X\n", + i, (unsigned int)data->pwm_settings[i][0]); + break; + } + + /* the low nibble must correspond to one of the temp sensors + we've found */ + for (j = 0; j < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]; + j++) { + if (data->bank1_address[ABIT_UGURU_TEMP_SENSOR][j] == + (data->pwm_settings[i][0] & 0x0F)) + break; + } + if (j == data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " + "to be a pwm channel: %d is not a valid temp " + "sensor address\n", i, + data->pwm_settings[i][0] & 0x0F); + break; + } + + /* check if all other settings are within the allowed range */ + for (j = 1; j < 5; j++) { + u8 min; + /* special case pwm1 min pwm% */ + if ((i == 0) && ((j == 1) || (j == 2))) + min = 77; + else + min = abituguru_pwm_min[j]; + if (data->pwm_settings[i][j] < min) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does " + "not seem to be a pwm channel: " + "setting %d (%d) is below the minimum " + "value (%d)\n", i, j, + (int)data->pwm_settings[i][j], + (int)min); + goto abituguru_detect_no_pwms_exit; + } + if (data->pwm_settings[i][j] > abituguru_pwm_max[j]) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does " + "not seem to be a pwm channel: " + "setting %d (%d) is above the maximum " + "value (%d)\n", i, j, + (int)data->pwm_settings[i][j], + (int)abituguru_pwm_max[j]); + goto abituguru_detect_no_pwms_exit; + } + } + + /* check that min temp < max temp and min pwm < max pwm */ + if (data->pwm_settings[i][1] >= data->pwm_settings[i][2]) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " + "to be a pwm channel: min pwm (%d) >= " + "max pwm (%d)\n", i, + (int)data->pwm_settings[i][1], + (int)data->pwm_settings[i][2]); + break; + } + if (data->pwm_settings[i][3] >= data->pwm_settings[i][4]) { + ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " + "to be a pwm channel: min temp (%d) >= " + "max temp (%d)\n", i, + (int)data->pwm_settings[i][3], + (int)data->pwm_settings[i][4]); + break; + } + } + +abituguru_detect_no_pwms_exit: + data->pwms = i; + ABIT_UGURU_DEBUG(2, " found: %d PWM outputs\n", (int)data->pwms); +} + +/* Following are the sysfs callback functions. These functions expect: + sensor_device_attribute_2->index: sensor address/offset in the bank + sensor_device_attribute_2->nr: register offset, bitmask or NA. */ +static struct abituguru_data *abituguru_update_device(struct device *dev); + +static ssize_t show_bank1_value(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = abituguru_update_device(dev); + if (!data) + return -EIO; + return sprintf(buf, "%d\n", (data->bank1_value[attr->index] * + data->bank1_max_value[attr->index] + 128) / 255); +} + +static ssize_t show_bank1_setting(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", + (data->bank1_settings[attr->index][attr->nr] * + data->bank1_max_value[attr->index] + 128) / 255); +} + +static ssize_t show_bank2_value(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = abituguru_update_device(dev); + if (!data) + return -EIO; + return sprintf(buf, "%d\n", (data->bank2_value[attr->index] * + ABIT_UGURU_FAN_MAX + 128) / 255); +} + +static ssize_t show_bank2_setting(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", + (data->bank2_settings[attr->index][attr->nr] * + ABIT_UGURU_FAN_MAX + 128) / 255); +} + +static ssize_t store_bank1_setting(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + u8 val = (simple_strtoul(buf, NULL, 10) * 255 + + data->bank1_max_value[attr->index]/2) / + data->bank1_max_value[attr->index]; + ssize_t ret = count; + + mutex_lock(&data->update_lock); + if (data->bank1_settings[attr->index][attr->nr] != val) { + u8 orig_val = data->bank1_settings[attr->index][attr->nr]; + data->bank1_settings[attr->index][attr->nr] = val; + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, + attr->index, data->bank1_settings[attr->index], + 3) <= attr->nr) { + data->bank1_settings[attr->index][attr->nr] = orig_val; + ret = -EIO; + } + } + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t store_bank2_setting(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + u8 val = (simple_strtoul(buf, NULL, 10)*255 + ABIT_UGURU_FAN_MAX/2) / + ABIT_UGURU_FAN_MAX; + ssize_t ret = count; + + /* this check can be done before taking the lock */ + if ((val < abituguru_bank2_min_threshold) || + (val > abituguru_bank2_max_threshold)) + return -EINVAL; + + mutex_lock(&data->update_lock); + if (data->bank2_settings[attr->index][attr->nr] != val) { + u8 orig_val = data->bank2_settings[attr->index][attr->nr]; + data->bank2_settings[attr->index][attr->nr] = val; + if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK2 + 2, + attr->index, data->bank2_settings[attr->index], + 2) <= attr->nr) { + data->bank2_settings[attr->index][attr->nr] = orig_val; + ret = -EIO; + } + } + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t show_bank1_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = abituguru_update_device(dev); + if (!data) + return -EIO; + /* See if the alarm bit for this sensor is set, and if the + alarm matches the type of alarm we're looking for (for volt + it can be either low or high). The type is stored in a few + readonly bits in the settings part of the relevant sensor. + The bitmask of the type is passed to us in attr->nr. */ + if ((data->alarms[attr->index / 8] & (0x01 << (attr->index % 8))) && + (data->bank1_settings[attr->index][0] & attr->nr)) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t show_bank2_alarm(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = abituguru_update_device(dev); + if (!data) + return -EIO; + if (data->alarms[2] & (0x01 << attr->index)) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t show_bank1_mask(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + if (data->bank1_settings[attr->index][0] & attr->nr) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t show_bank2_mask(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + if (data->bank2_settings[attr->index][0] & attr->nr) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static ssize_t store_bank1_mask(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + int mask = simple_strtoul(buf, NULL, 10); + ssize_t ret = count; + u8 orig_val; + + mutex_lock(&data->update_lock); + orig_val = data->bank1_settings[attr->index][0]; + + if (mask) + data->bank1_settings[attr->index][0] |= attr->nr; + else + data->bank1_settings[attr->index][0] &= ~attr->nr; + + if ((data->bank1_settings[attr->index][0] != orig_val) && + (abituguru_write(data, + ABIT_UGURU_SENSOR_BANK1 + 2, attr->index, + data->bank1_settings[attr->index], 3) < 1)) { + data->bank1_settings[attr->index][0] = orig_val; + ret = -EIO; + } + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t store_bank2_mask(struct device *dev, + struct device_attribute *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + int mask = simple_strtoul(buf, NULL, 10); + ssize_t ret = count; + u8 orig_val; + + mutex_lock(&data->update_lock); + orig_val = data->bank2_settings[attr->index][0]; + + if (mask) + data->bank2_settings[attr->index][0] |= attr->nr; + else + data->bank2_settings[attr->index][0] &= ~attr->nr; + + if ((data->bank2_settings[attr->index][0] != orig_val) && + (abituguru_write(data, + ABIT_UGURU_SENSOR_BANK2 + 2, attr->index, + data->bank2_settings[attr->index], 2) < 1)) { + data->bank2_settings[attr->index][0] = orig_val; + ret = -EIO; + } + mutex_unlock(&data->update_lock); + return ret; +} + +/* Fan PWM (speed control) */ +static ssize_t show_pwm_setting(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + return sprintf(buf, "%d\n", data->pwm_settings[attr->index][attr->nr] * + abituguru_pwm_settings_multiplier[attr->nr]); +} + +static ssize_t store_pwm_setting(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + u8 min, val = (simple_strtoul(buf, NULL, 10) + + abituguru_pwm_settings_multiplier[attr->nr]/2) / + abituguru_pwm_settings_multiplier[attr->nr]; + ssize_t ret = count; + + /* special case pwm1 min pwm% */ + if ((attr->index == 0) && ((attr->nr == 1) || (attr->nr == 2))) + min = 77; + else + min = abituguru_pwm_min[attr->nr]; + + /* this check can be done before taking the lock */ + if ((val < min) || (val > abituguru_pwm_max[attr->nr])) + return -EINVAL; + + mutex_lock(&data->update_lock); + /* this check needs to be done after taking the lock */ + if ((attr->nr & 1) && + (val >= data->pwm_settings[attr->index][attr->nr + 1])) + ret = -EINVAL; + else if (!(attr->nr & 1) && + (val <= data->pwm_settings[attr->index][attr->nr - 1])) + ret = -EINVAL; + else if (data->pwm_settings[attr->index][attr->nr] != val) { + u8 orig_val = data->pwm_settings[attr->index][attr->nr]; + data->pwm_settings[attr->index][attr->nr] = val; + if (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1, + attr->index, data->pwm_settings[attr->index], + 5) <= attr->nr) { + data->pwm_settings[attr->index][attr->nr] = + orig_val; + ret = -EIO; + } + } + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t show_pwm_sensor(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + int i; + /* We need to walk to the temp sensor addresses to find what + the userspace id of the configured temp sensor is. */ + for (i = 0; i < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]; i++) + if (data->bank1_address[ABIT_UGURU_TEMP_SENSOR][i] == + (data->pwm_settings[attr->index][0] & 0x0F)) + return sprintf(buf, "%d\n", i+1); + + return -ENXIO; +} + +static ssize_t store_pwm_sensor(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + unsigned long val = simple_strtoul(buf, NULL, 10) - 1; + ssize_t ret = count; + + mutex_lock(&data->update_lock); + if (val < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]) { + u8 orig_val = data->pwm_settings[attr->index][0]; + u8 address = data->bank1_address[ABIT_UGURU_TEMP_SENSOR][val]; + data->pwm_settings[attr->index][0] &= 0xF0; + data->pwm_settings[attr->index][0] |= address; + if (data->pwm_settings[attr->index][0] != orig_val) { + if (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1, + attr->index, + data->pwm_settings[attr->index], + 5) < 1) { + data->pwm_settings[attr->index][0] = orig_val; + ret = -EIO; + } + } + } + else + ret = -EINVAL; + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t show_pwm_enable(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + int res = 0; + if (data->pwm_settings[attr->index][0] & ABIT_UGURU_FAN_PWM_ENABLE) + res = 2; + return sprintf(buf, "%d\n", res); +} + +static ssize_t store_pwm_enable(struct device *dev, struct device_attribute + *devattr, const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct abituguru_data *data = dev_get_drvdata(dev); + u8 orig_val, user_val = simple_strtoul(buf, NULL, 10); + ssize_t ret = count; + + mutex_lock(&data->update_lock); + orig_val = data->pwm_settings[attr->index][0]; + switch (user_val) { + case 0: + data->pwm_settings[attr->index][0] &= + ~ABIT_UGURU_FAN_PWM_ENABLE; + break; + case 2: + data->pwm_settings[attr->index][0] |= + ABIT_UGURU_FAN_PWM_ENABLE; + break; + default: + ret = -EINVAL; + } + if ((data->pwm_settings[attr->index][0] != orig_val) && + (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1, + attr->index, data->pwm_settings[attr->index], + 5) < 1)) { + data->pwm_settings[attr->index][0] = orig_val; + ret = -EIO; + } + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t show_name(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return sprintf(buf, "%s\n", ABIT_UGURU_NAME); +} + +/* Sysfs attr templates, the real entries are generated automatically. */ +static const +struct sensor_device_attribute_2 abituguru_sysfs_bank1_templ[2][9] = { + { + SENSOR_ATTR_2(in%d_input, 0444, show_bank1_value, NULL, 0, 0), + SENSOR_ATTR_2(in%d_min, 0644, show_bank1_setting, + store_bank1_setting, 1, 0), + SENSOR_ATTR_2(in%d_min_alarm, 0444, show_bank1_alarm, NULL, + ABIT_UGURU_VOLT_LOW_ALARM_FLAG, 0), + SENSOR_ATTR_2(in%d_max, 0644, show_bank1_setting, + store_bank1_setting, 2, 0), + SENSOR_ATTR_2(in%d_max_alarm, 0444, show_bank1_alarm, NULL, + ABIT_UGURU_VOLT_HIGH_ALARM_FLAG, 0), + SENSOR_ATTR_2(in%d_beep, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_BEEP_ENABLE, 0), + SENSOR_ATTR_2(in%d_shutdown, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0), + SENSOR_ATTR_2(in%d_min_alarm_enable, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_VOLT_LOW_ALARM_ENABLE, 0), + SENSOR_ATTR_2(in%d_max_alarm_enable, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE, 0), + }, { + SENSOR_ATTR_2(temp%d_input, 0444, show_bank1_value, NULL, 0, 0), + SENSOR_ATTR_2(temp%d_alarm, 0444, show_bank1_alarm, NULL, + ABIT_UGURU_TEMP_HIGH_ALARM_FLAG, 0), + SENSOR_ATTR_2(temp%d_max, 0644, show_bank1_setting, + store_bank1_setting, 1, 0), + SENSOR_ATTR_2(temp%d_crit, 0644, show_bank1_setting, + store_bank1_setting, 2, 0), + SENSOR_ATTR_2(temp%d_beep, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_BEEP_ENABLE, 0), + SENSOR_ATTR_2(temp%d_shutdown, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0), + SENSOR_ATTR_2(temp%d_alarm_enable, 0644, show_bank1_mask, + store_bank1_mask, ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE, 0), + } +}; + +static const struct sensor_device_attribute_2 abituguru_sysfs_fan_templ[6] = { + SENSOR_ATTR_2(fan%d_input, 0444, show_bank2_value, NULL, 0, 0), + SENSOR_ATTR_2(fan%d_alarm, 0444, show_bank2_alarm, NULL, 0, 0), + SENSOR_ATTR_2(fan%d_min, 0644, show_bank2_setting, + store_bank2_setting, 1, 0), + SENSOR_ATTR_2(fan%d_beep, 0644, show_bank2_mask, + store_bank2_mask, ABIT_UGURU_BEEP_ENABLE, 0), + SENSOR_ATTR_2(fan%d_shutdown, 0644, show_bank2_mask, + store_bank2_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0), + SENSOR_ATTR_2(fan%d_alarm_enable, 0644, show_bank2_mask, + store_bank2_mask, ABIT_UGURU_FAN_LOW_ALARM_ENABLE, 0), +}; + +static const struct sensor_device_attribute_2 abituguru_sysfs_pwm_templ[6] = { + SENSOR_ATTR_2(pwm%d_enable, 0644, show_pwm_enable, + store_pwm_enable, 0, 0), + SENSOR_ATTR_2(pwm%d_auto_channels_temp, 0644, show_pwm_sensor, + store_pwm_sensor, 0, 0), + SENSOR_ATTR_2(pwm%d_auto_point1_pwm, 0644, show_pwm_setting, + store_pwm_setting, 1, 0), + SENSOR_ATTR_2(pwm%d_auto_point2_pwm, 0644, show_pwm_setting, + store_pwm_setting, 2, 0), + SENSOR_ATTR_2(pwm%d_auto_point1_temp, 0644, show_pwm_setting, + store_pwm_setting, 3, 0), + SENSOR_ATTR_2(pwm%d_auto_point2_temp, 0644, show_pwm_setting, + store_pwm_setting, 4, 0), +}; + +static struct sensor_device_attribute_2 abituguru_sysfs_attr[] = { + SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0), +}; + +static int __devinit abituguru_probe(struct platform_device *pdev) +{ + struct abituguru_data *data; + int i, j, used, sysfs_names_free, sysfs_attr_i, res = -ENODEV; + char *sysfs_filename; + + /* El weirdo probe order, to keep the sysfs order identical to the + BIOS and window-appliction listing order. */ + const u8 probe_order[ABIT_UGURU_MAX_BANK1_SENSORS] = { + 0x00, 0x01, 0x03, 0x04, 0x0A, 0x08, 0x0E, 0x02, + 0x09, 0x06, 0x05, 0x0B, 0x0F, 0x0D, 0x07, 0x0C }; + + if (!(data = kzalloc(sizeof(struct abituguru_data), GFP_KERNEL))) + return -ENOMEM; + + data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; + mutex_init(&data->update_lock); + platform_set_drvdata(pdev, data); + + /* See if the uGuru is ready */ + if (inb_p(data->addr + ABIT_UGURU_DATA) == ABIT_UGURU_STATUS_INPUT) + data->uguru_ready = 1; + + /* Completely read the uGuru this has 2 purposes: + - testread / see if one really is there. + - make an in memory copy of all the uguru settings for future use. */ + if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, + data->alarms, 3, ABIT_UGURU_MAX_RETRIES) != 3) + goto abituguru_probe_error; + + for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) { + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, i, + &data->bank1_value[i], 1, + ABIT_UGURU_MAX_RETRIES) != 1) + goto abituguru_probe_error; + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1+1, i, + data->bank1_settings[i], 3, + ABIT_UGURU_MAX_RETRIES) != 3) + goto abituguru_probe_error; + } + /* Note: We don't know how many bank2 sensors / pwms there really are, + but in order to "detect" this we need to read the maximum amount + anyways. If we read sensors/pwms not there we'll just read crap + this can't hurt. We need the detection because we don't want + unwanted writes, which will hurt! */ + for (i = 0; i < ABIT_UGURU_MAX_BANK2_SENSORS; i++) { + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK2, i, + &data->bank2_value[i], 1, + ABIT_UGURU_MAX_RETRIES) != 1) + goto abituguru_probe_error; + if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK2+1, i, + data->bank2_settings[i], 2, + ABIT_UGURU_MAX_RETRIES) != 2) + goto abituguru_probe_error; + } + for (i = 0; i < ABIT_UGURU_MAX_PWMS; i++) { + if (abituguru_read(data, ABIT_UGURU_FAN_PWM, i, + data->pwm_settings[i], 5, + ABIT_UGURU_MAX_RETRIES) != 5) + goto abituguru_probe_error; + } + data->last_updated = jiffies; + + /* Detect sensor types and fill the sysfs attr for bank1 */ + sysfs_attr_i = 0; + sysfs_filename = data->sysfs_names; + sysfs_names_free = ABITUGURU_SYSFS_NAMES_LENGTH; + for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) { + res = abituguru_detect_bank1_sensor_type(data, probe_order[i]); + if (res < 0) + goto abituguru_probe_error; + if (res == ABIT_UGURU_NC) + continue; + + /* res 1 (temp) sensors have 7 sysfs entries, 0 (in) 9 */ + for (j = 0; j < (res ? 7 : 9); j++) { + used = snprintf(sysfs_filename, sysfs_names_free, + abituguru_sysfs_bank1_templ[res][j].dev_attr. + attr.name, data->bank1_sensors[res] + res) + + 1; + data->sysfs_attr[sysfs_attr_i] = + abituguru_sysfs_bank1_templ[res][j]; + data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name = + sysfs_filename; + data->sysfs_attr[sysfs_attr_i].index = probe_order[i]; + sysfs_filename += used; + sysfs_names_free -= used; + sysfs_attr_i++; + } + data->bank1_max_value[probe_order[i]] = + abituguru_bank1_max_value[res]; + data->bank1_address[res][data->bank1_sensors[res]] = + probe_order[i]; + data->bank1_sensors[res]++; + } + /* Detect number of sensors and fill the sysfs attr for bank2 (fans) */ + abituguru_detect_no_bank2_sensors(data); + for (i = 0; i < data->bank2_sensors; i++) { + for (j = 0; j < ARRAY_SIZE(abituguru_sysfs_fan_templ); j++) { + used = snprintf(sysfs_filename, sysfs_names_free, + abituguru_sysfs_fan_templ[j].dev_attr.attr.name, + i + 1) + 1; + data->sysfs_attr[sysfs_attr_i] = + abituguru_sysfs_fan_templ[j]; + data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name = + sysfs_filename; + data->sysfs_attr[sysfs_attr_i].index = i; + sysfs_filename += used; + sysfs_names_free -= used; + sysfs_attr_i++; + } + } + /* Detect number of sensors and fill the sysfs attr for pwms */ + abituguru_detect_no_pwms(data); + for (i = 0; i < data->pwms; i++) { + for (j = 0; j < ARRAY_SIZE(abituguru_sysfs_pwm_templ); j++) { + used = snprintf(sysfs_filename, sysfs_names_free, + abituguru_sysfs_pwm_templ[j].dev_attr.attr.name, + i + 1) + 1; + data->sysfs_attr[sysfs_attr_i] = + abituguru_sysfs_pwm_templ[j]; + data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name = + sysfs_filename; + data->sysfs_attr[sysfs_attr_i].index = i; + sysfs_filename += used; + sysfs_names_free -= used; + sysfs_attr_i++; + } + } + /* Fail safe check, this should never happen! */ + if (sysfs_names_free < 0) { + printk(KERN_ERR ABIT_UGURU_NAME ": Fatal error ran out of " + "space for sysfs attr names. This should never " + "happen please report to the abituguru maintainer " + "(see MAINTAINERS)\n"); + res = -ENAMETOOLONG; + goto abituguru_probe_error; + } + printk(KERN_INFO ABIT_UGURU_NAME ": found Abit uGuru\n"); + + /* Register sysfs hooks */ + data->class_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->class_dev)) { + res = PTR_ERR(data->class_dev); + goto abituguru_probe_error; + } + for (i = 0; i < sysfs_attr_i; i++) + device_create_file(&pdev->dev, &data->sysfs_attr[i].dev_attr); + for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) + device_create_file(&pdev->dev, + &abituguru_sysfs_attr[i].dev_attr); + + return 0; + +abituguru_probe_error: + kfree(data); + return res; +} + +static int __devexit abituguru_remove(struct platform_device *pdev) +{ + struct abituguru_data *data = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + hwmon_device_unregister(data->class_dev); + kfree(data); + + return 0; +} + +static struct abituguru_data *abituguru_update_device(struct device *dev) +{ + int i, err; + struct abituguru_data *data = dev_get_drvdata(dev); + /* fake a complete successful read if no update necessary. */ + char success = 1; + + mutex_lock(&data->update_lock); + if (time_after(jiffies, data->last_updated + HZ)) { + success = 0; + if ((err = abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, + data->alarms, 3, 0)) != 3) + goto LEAVE_UPDATE; + for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) { + if ((err = abituguru_read(data, + ABIT_UGURU_SENSOR_BANK1, i, + &data->bank1_value[i], 1, 0)) != 1) + goto LEAVE_UPDATE; + if ((err = abituguru_read(data, + ABIT_UGURU_SENSOR_BANK1 + 1, i, + data->bank1_settings[i], 3, 0)) != 3) + goto LEAVE_UPDATE; + } + for (i = 0; i < data->bank2_sensors; i++) + if ((err = abituguru_read(data, + ABIT_UGURU_SENSOR_BANK2, i, + &data->bank2_value[i], 1, 0)) != 1) + goto LEAVE_UPDATE; + /* success! */ + success = 1; + data->update_timeouts = 0; +LEAVE_UPDATE: + /* handle timeout condition */ + if (!success && (err == -EBUSY || err >= 0)) { + /* No overflow please */ + if (data->update_timeouts < 255u) + data->update_timeouts++; + if (data->update_timeouts <= ABIT_UGURU_MAX_TIMEOUTS) { + ABIT_UGURU_DEBUG(3, "timeout exceeded, will " + "try again next update\n"); + /* Just a timeout, fake a successful read */ + success = 1; + } else + ABIT_UGURU_DEBUG(1, "timeout exceeded %d " + "times waiting for more input state\n", + (int)data->update_timeouts); + } + /* On success set last_updated */ + if (success) + data->last_updated = jiffies; + } + mutex_unlock(&data->update_lock); + + if (success) + return data; + else + return NULL; +} + +static struct platform_driver abituguru_driver = { + .driver = { + .owner = THIS_MODULE, + .name = ABIT_UGURU_NAME, + }, + .probe = abituguru_probe, + .remove = __devexit_p(abituguru_remove), +}; + +static int __init abituguru_detect(void) +{ + /* See if there is an uguru there. After a reboot uGuru will hold 0x00 + at DATA and 0xAC, when this driver has already been loaded once + DATA will hold 0x08. For most uGuru's CMD will hold 0xAC in either + scenario but some will hold 0x00. + Some uGuru's initally hold 0x09 at DATA and will only hold 0x08 + after reading CMD first, so CMD must be read first! */ + u8 cmd_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_CMD); + u8 data_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_DATA); + if (((data_val == 0x00) || (data_val == 0x08)) && + ((cmd_val == 0x00) || (cmd_val == 0xAC))) + return ABIT_UGURU_BASE; + + ABIT_UGURU_DEBUG(2, "no Abit uGuru found, data = 0x%02X, cmd = " + "0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val); + + if (force) { + printk(KERN_INFO ABIT_UGURU_NAME ": Assuming Abit uGuru is " + "present because of \"force\" parameter\n"); + return ABIT_UGURU_BASE; + } + + /* No uGuru found */ + return -ENODEV; +} + +static struct platform_device *abituguru_pdev; + +static int __init abituguru_init(void) +{ + int address, err; + struct resource res = { .flags = IORESOURCE_IO }; + + address = abituguru_detect(); + if (address < 0) + return address; + + err = platform_driver_register(&abituguru_driver); + if (err) + goto exit; + + abituguru_pdev = platform_device_alloc(ABIT_UGURU_NAME, address); + if (!abituguru_pdev) { + printk(KERN_ERR ABIT_UGURU_NAME + ": Device allocation failed\n"); + err = -ENOMEM; + goto exit_driver_unregister; + } + + res.start = address; + res.end = address + ABIT_UGURU_REGION_LENGTH - 1; + res.name = ABIT_UGURU_NAME; + + err = platform_device_add_resources(abituguru_pdev, &res, 1); + if (err) { + printk(KERN_ERR ABIT_UGURU_NAME + ": Device resource addition failed (%d)\n", err); + goto exit_device_put; + } + + err = platform_device_add(abituguru_pdev); + if (err) { + printk(KERN_ERR ABIT_UGURU_NAME + ": Device addition failed (%d)\n", err); + goto exit_device_put; + } + + return 0; + +exit_device_put: + platform_device_put(abituguru_pdev); +exit_driver_unregister: + platform_driver_unregister(&abituguru_driver); +exit: + return err; +} + +static void __exit abituguru_exit(void) +{ + platform_device_unregister(abituguru_pdev); + platform_driver_unregister(&abituguru_driver); +} + +MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>"); +MODULE_DESCRIPTION("Abit uGuru Sensor device"); +MODULE_LICENSE("GPL"); + +module_init(abituguru_init); +module_exit(abituguru_exit); diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c new file mode 100644 index 000000000..6ba84731b --- /dev/null +++ b/drivers/hwmon/lm70.c @@ -0,0 +1,165 @@ +/* + * lm70.c + * + * The LM70 is a temperature sensor chip from National Semiconductor (NS). + * Copyright (C) 2006 Kaiwan N Billimoria <kaiwan@designergraphix.com> + * + * The LM70 communicates with a host processor via an SPI/Microwire Bus + * interface. The complete datasheet is available at National's website + * here: + * http://www.national.com/pf/LM/LM70.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/sysfs.h> +#include <linux/hwmon.h> +#include <linux/spi/spi.h> +#include <asm/semaphore.h> + +#define DRVNAME "lm70" + +struct lm70 { + struct class_device *cdev; + struct semaphore sem; +}; + +/* sysfs hook function */ +static ssize_t lm70_sense_temp(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct spi_device *spi = to_spi_device(dev); + int status, val; + u8 rxbuf[2]; + s16 raw=0; + struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); + + if (down_interruptible(&p_lm70->sem)) + return -ERESTARTSYS; + + /* + * spi_read() requires a DMA-safe buffer; so we use + * spi_write_then_read(), transmitting 0 bytes. + */ + status = spi_write_then_read(spi, NULL, 0, &rxbuf[0], 2); + if (status < 0) { + printk(KERN_WARNING + "spi_write_then_read failed with status %d\n", status); + goto out; + } + dev_dbg(dev, "rxbuf[1] : 0x%x rxbuf[0] : 0x%x\n", rxbuf[1], rxbuf[0]); + + raw = (rxbuf[1] << 8) + rxbuf[0]; + dev_dbg(dev, "raw=0x%x\n", raw); + + /* + * The "raw" temperature read into rxbuf[] is a 16-bit signed 2's + * complement value. Only the MSB 11 bits (1 sign + 10 temperature + * bits) are meaningful; the LSB 5 bits are to be discarded. + * See the datasheet. + * + * Further, each bit represents 0.25 degrees Celsius; so, multiply + * by 0.25. Also multiply by 1000 to represent in millidegrees + * Celsius. + * So it's equivalent to multiplying by 0.25 * 1000 = 250. + */ + val = ((int)raw/32) * 250; + status = sprintf(buf, "%+d\n", val); /* millidegrees Celsius */ +out: + up(&p_lm70->sem); + return status; +} + +static DEVICE_ATTR(temp1_input, S_IRUGO, lm70_sense_temp, NULL); + +/*----------------------------------------------------------------------*/ + +static int __devinit lm70_probe(struct spi_device *spi) +{ + struct lm70 *p_lm70; + int status; + + p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL); + if (!p_lm70) + return -ENOMEM; + + init_MUTEX(&p_lm70->sem); + + /* sysfs hook */ + p_lm70->cdev = hwmon_device_register(&spi->dev); + if (IS_ERR(p_lm70->cdev)) { + dev_dbg(&spi->dev, "hwmon_device_register failed.\n"); + status = PTR_ERR(p_lm70->cdev); + goto out_dev_reg_failed; + } + dev_set_drvdata(&spi->dev, p_lm70); + + if ((status = device_create_file(&spi->dev, &dev_attr_temp1_input))) { + dev_dbg(&spi->dev, "device_create_file failure.\n"); + goto out_dev_create_file_failed; + } + + return 0; + +out_dev_create_file_failed: + hwmon_device_unregister(p_lm70->cdev); +out_dev_reg_failed: + dev_set_drvdata(&spi->dev, NULL); + kfree(p_lm70); + return status; +} + +static int __exit lm70_remove(struct spi_device *spi) +{ + struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); + + device_remove_file(&spi->dev, &dev_attr_temp1_input); + hwmon_device_unregister(p_lm70->cdev); + dev_set_drvdata(&spi->dev, NULL); + kfree(p_lm70); + + return 0; +} + +static struct spi_driver lm70_driver = { + .driver = { + .name = "lm70", + .owner = THIS_MODULE, + }, + .probe = lm70_probe, + .remove = __devexit_p(lm70_remove), +}; + +static int __init init_lm70(void) +{ + return spi_register_driver(&lm70_driver); +} + +static void __exit cleanup_lm70(void) +{ + spi_unregister_driver(&lm70_driver); +} + +module_init(init_lm70); +module_exit(cleanup_lm70); + +MODULE_AUTHOR("Kaiwan N Billimoria"); +MODULE_DESCRIPTION("National Semiconductor LM70 Linux driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c new file mode 100644 index 000000000..bdc4570ac --- /dev/null +++ b/drivers/hwmon/smsc47m192.c @@ -0,0 +1,648 @@ +/* + smsc47m192.c - Support for hardware monitoring block of + SMSC LPC47M192 and LPC47M997 Super I/O chips + + Copyright (C) 2006 Hartmut Rick <linux@rick.claranet.de> + + Derived from lm78.c and other chip drivers. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/jiffies.h> +#include <linux/i2c.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/hwmon-vid.h> +#include <linux/err.h> + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD_1(smsc47m192); + +/* SMSC47M192 registers */ +#define SMSC47M192_REG_IN(nr) ((nr)<6 ? (0x20 + (nr)) : \ + (0x50 + (nr) - 6)) +#define SMSC47M192_REG_IN_MAX(nr) ((nr)<6 ? (0x2b + (nr) * 2) : \ + (0x54 + (((nr) - 6) * 2))) +#define SMSC47M192_REG_IN_MIN(nr) ((nr)<6 ? (0x2c + (nr) * 2) : \ + (0x55 + (((nr) - 6) * 2))) +static u8 SMSC47M192_REG_TEMP[3] = { 0x27, 0x26, 0x52 }; +static u8 SMSC47M192_REG_TEMP_MAX[3] = { 0x39, 0x37, 0x58 }; +static u8 SMSC47M192_REG_TEMP_MIN[3] = { 0x3A, 0x38, 0x59 }; +#define SMSC47M192_REG_TEMP_OFFSET(nr) ((nr)==2 ? 0x1e : 0x1f) +#define SMSC47M192_REG_ALARM1 0x41 +#define SMSC47M192_REG_ALARM2 0x42 +#define SMSC47M192_REG_VID 0x47 +#define SMSC47M192_REG_VID4 0x49 +#define SMSC47M192_REG_CONFIG 0x40 +#define SMSC47M192_REG_SFR 0x4f +#define SMSC47M192_REG_COMPANY_ID 0x3e +#define SMSC47M192_REG_VERSION 0x3f + +/* generalised scaling with integer rounding */ +static inline int SCALE(long val, int mul, int div) +{ + if (val < 0) + return (val * mul - div / 2) / div; + else + return (val * mul + div / 2) / div; +} + +/* Conversions */ + +/* smsc47m192 internally scales voltage measurements */ +static const u16 nom_mv[] = { 2500, 2250, 3300, 5000, 12000, 3300, 1500, 1800 }; + +static inline unsigned int IN_FROM_REG(u8 reg, int n) +{ + return SCALE(reg, nom_mv[n], 192); +} + +static inline u8 IN_TO_REG(unsigned long val, int n) +{ + return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255); +} + +/* TEMP: 0.001 degC units (-128C to +127C) + REG: 1C/bit, two's complement */ +static inline s8 TEMP_TO_REG(int val) +{ + return SENSORS_LIMIT(SCALE(val, 1, 1000), -128000, 127000); +} + +static inline int TEMP_FROM_REG(s8 val) +{ + return val * 1000; +} + +struct smsc47m192_data { + struct i2c_client client; + struct class_device *class_dev; + struct semaphore update_lock; + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + + u8 in[8]; /* Register value */ + u8 in_max[8]; /* Register value */ + u8 in_min[8]; /* Register value */ + s8 temp[3]; /* Register value */ + s8 temp_max[3]; /* Register value */ + s8 temp_min[3]; /* Register value */ + s8 temp_offset[3]; /* Register value */ + u16 alarms; /* Register encoding, combined */ + u8 vid; /* Register encoding, combined */ + u8 vrm; +}; + +static int smsc47m192_attach_adapter(struct i2c_adapter *adapter); +static int smsc47m192_detect(struct i2c_adapter *adapter, int address, + int kind); +static int smsc47m192_detach_client(struct i2c_client *client); +static struct smsc47m192_data *smsc47m192_update_device(struct device *dev); + +static struct i2c_driver smsc47m192_driver = { + .driver = { + .name = "smsc47m192", + }, + .attach_adapter = smsc47m192_attach_adapter, + .detach_client = smsc47m192_detach_client, +}; + +/* Voltages */ +static ssize_t show_in(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr)); +} + +static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr)); +} + +static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr)); +} + +static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + + down(&data->update_lock); + data->in_min[nr] = IN_TO_REG(val, nr); + i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MIN(nr), + data->in_min[nr]); + up(&data->update_lock); + return count; +} + +static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + + down(&data->update_lock); + data->in_max[nr] = IN_TO_REG(val, nr); + i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MAX(nr), + data->in_max[nr]); + up(&data->update_lock); + return count; +} + +#define show_in_offset(offset) \ +static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ + show_in, NULL, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ + show_in_min, set_in_min, offset); \ +static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ + show_in_max, set_in_max, offset); + +show_in_offset(0) +show_in_offset(1) +show_in_offset(2) +show_in_offset(3) +show_in_offset(4) +show_in_offset(5) +show_in_offset(6) +show_in_offset(7) + +/* Temperatures */ +static ssize_t show_temp(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])); +} + +static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr])); +} + +static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr])); +} + +static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + + down(&data->update_lock); + data->temp_min[nr] = TEMP_TO_REG(val); + i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MIN[nr], + data->temp_min[nr]); + up(&data->update_lock); + return count; +} + +static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + + down(&data->update_lock); + data->temp_max[nr] = TEMP_TO_REG(val); + i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MAX[nr], + data->temp_max[nr]); + up(&data->update_lock); + return count; +} + +static ssize_t show_temp_offset(struct device *dev, struct device_attribute + *attr, char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr])); +} + +static ssize_t set_temp_offset(struct device *dev, struct device_attribute + *attr, const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); + long val = simple_strtol(buf, NULL, 10); + + down(&data->update_lock); + data->temp_offset[nr] = TEMP_TO_REG(val); + if (nr>1) + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]); + else if (data->temp_offset[nr] != 0) { + /* offset[0] and offset[1] share the same register, + SFR bit 4 activates offset[0] */ + i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR, + (sfr & 0xef) | (nr==0 ? 0x10 : 0)); + data->temp_offset[1-nr] = 0; + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]); + } else if ((sfr & 0x10) == (nr==0 ? 0x10 : 0)) + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_TEMP_OFFSET(nr), 0); + up(&data->update_lock); + return count; +} + +#define show_temp_index(index) \ +static SENSOR_DEVICE_ATTR(temp##index##_input, S_IRUGO, \ + show_temp, NULL, index-1); \ +static SENSOR_DEVICE_ATTR(temp##index##_min, S_IRUGO | S_IWUSR, \ + show_temp_min, set_temp_min, index-1); \ +static SENSOR_DEVICE_ATTR(temp##index##_max, S_IRUGO | S_IWUSR, \ + show_temp_max, set_temp_max, index-1); \ +static SENSOR_DEVICE_ATTR(temp##index##_offset, S_IRUGO | S_IWUSR, \ + show_temp_offset, set_temp_offset, index-1); + +show_temp_index(1) +show_temp_index(2) +show_temp_index(3) + +/* VID */ +static ssize_t show_vid(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); +} +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); + +static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%d\n", data->vrm); +} + +static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + data->vrm = simple_strtoul(buf, NULL, 10); + return count; +} +static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); + +/* Alarms */ +static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct smsc47m192_data *data = smsc47m192_update_device(dev); + return sprintf(buf, "%u\n", (data->alarms & nr) ? 1 : 0); +} + +static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 0x0010); +static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0x0020); +static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 0x0040); +static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 0x4000); +static SENSOR_DEVICE_ATTR(temp3_input_fault, S_IRUGO, show_alarm, NULL, 0x8000); +static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0x0001); +static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 0x0002); +static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 0x0004); +static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 0x0008); +static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 0x0100); +static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 0x0200); +static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 0x0400); +static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 0x0800); + +/* This function is called when: + * smsc47m192_driver is inserted (when this module is loaded), for each + available adapter + * when a new adapter is inserted (and smsc47m192_driver is still present) */ +static int smsc47m192_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, smsc47m192_detect); +} + +static void smsc47m192_init_client(struct i2c_client *client) +{ + int i; + u8 config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); + u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); + + /* select cycle mode (pause 1 sec between updates) */ + i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR, + (sfr & 0xfd) | 0x02); + if (!(config & 0x01)) { + /* initialize alarm limits */ + for (i=0; i<8; i++) { + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_IN_MIN(i), 0); + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_IN_MAX(i), 0xff); + } + for (i=0; i<3; i++) { + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_TEMP_MIN[i], 0x80); + i2c_smbus_write_byte_data(client, + SMSC47M192_REG_TEMP_MAX[i], 0x7f); + } + + /* start monitoring */ + i2c_smbus_write_byte_data(client, SMSC47M192_REG_CONFIG, + (config & 0xf7) | 0x01); + } +} + +/* This function is called by i2c_probe */ +static int smsc47m192_detect(struct i2c_adapter *adapter, int address, + int kind) +{ + struct i2c_client *client; + struct smsc47m192_data *data; + int err = 0; + int version, config; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + goto exit; + + if (!(data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &data->client; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &smsc47m192_driver; + + if (kind == 0) + kind = smsc47m192; + + /* Detection criteria from sensors_detect script */ + if (kind < 0) { + if (i2c_smbus_read_byte_data(client, + SMSC47M192_REG_COMPANY_ID) == 0x55 + && ((version = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_VERSION)) & 0xf0) == 0x20 + && (i2c_smbus_read_byte_data(client, + SMSC47M192_REG_VID) & 0x70) == 0x00 + && (i2c_smbus_read_byte_data(client, + SMSC47M192_REG_VID4) & 0xfe) == 0x80) { + dev_info(&adapter->dev, + "found SMSC47M192 or SMSC47M997, " + "version 2, stepping A%d\n", version & 0x0f); + } else { + dev_dbg(&adapter->dev, + "SMSC47M192 detection failed at 0x%02x\n", + address); + goto exit_free; + } + } + + /* Fill in the remaining client fields and put into the global list */ + strlcpy(client->name, "smsc47m192", I2C_NAME_SIZE); + data->vrm = vid_which_vrm(); + init_MUTEX(&data->update_lock); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + + /* Initialize the SMSC47M192 chip */ + smsc47m192_init_client(client); + + /* Register sysfs hooks */ + data->class_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->class_dev)) { + err = PTR_ERR(data->class_dev); + goto exit_detach; + } + + device_create_file(&client->dev, &sensor_dev_attr_in0_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in0_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in0_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in0_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in1_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in1_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in1_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in1_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in2_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in2_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in2_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in2_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in3_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in3_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in3_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in3_alarm.dev_attr); + + /* Pin 110 is either in4 (+12V) or VID4 */ + config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); + if (!(config & 0x20)) { + device_create_file(&client->dev, + &sensor_dev_attr_in4_input.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_in4_min.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_in4_max.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_in4_alarm.dev_attr); + } + device_create_file(&client->dev, &sensor_dev_attr_in5_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in5_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in5_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in5_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in6_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in6_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in6_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in6_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in7_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in7_min.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in7_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_in7_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp1_min.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_temp1_offset.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp1_alarm.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp2_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp2_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp2_min.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_temp2_offset.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp2_alarm.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_temp2_input_fault.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp3_input.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp3_max.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp3_min.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_temp3_offset.dev_attr); + device_create_file(&client->dev, &sensor_dev_attr_temp3_alarm.dev_attr); + device_create_file(&client->dev, + &sensor_dev_attr_temp3_input_fault.dev_attr); + device_create_file(&client->dev, &dev_attr_cpu0_vid); + device_create_file(&client->dev, &dev_attr_vrm); + + return 0; + +exit_detach: + i2c_detach_client(client); +exit_free: + kfree(data); +exit: + return err; +} + +static int smsc47m192_detach_client(struct i2c_client *client) +{ + struct smsc47m192_data *data = i2c_get_clientdata(client); + int err; + + hwmon_device_unregister(data->class_dev); + + if ((err = i2c_detach_client(client))) + return err; + + kfree(data); + + return 0; +} + +static struct smsc47m192_data *smsc47m192_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct smsc47m192_data *data = i2c_get_clientdata(client); + int i, config; + + down(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); + + dev_dbg(&client->dev, "Starting smsc47m192 update\n"); + + for (i = 0; i <= 7; i++) { + data->in[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_IN(i)); + data->in_min[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_IN_MIN(i)); + data->in_max[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_IN_MAX(i)); + } + for (i = 0; i < 3; i++) { + data->temp[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_TEMP[i]); + data->temp_max[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_TEMP_MAX[i]); + data->temp_min[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_TEMP_MIN[i]); + } + for (i = 1; i < 3; i++) + data->temp_offset[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_TEMP_OFFSET(i)); + /* first offset is temp_offset[0] if SFR bit 4 is set, + temp_offset[1] otherwise */ + if (sfr & 0x10) { + data->temp_offset[0] = data->temp_offset[1]; + data->temp_offset[1] = 0; + } else + data->temp_offset[0] = 0; + + data->vid = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID) + & 0x0f; + config = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_CONFIG); + if (config & 0x20) + data->vid |= (i2c_smbus_read_byte_data(client, + SMSC47M192_REG_VID4) & 0x01) << 4; + data->alarms = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_ALARM1) | + (i2c_smbus_read_byte_data(client, + SMSC47M192_REG_ALARM2) << 8); + + data->last_updated = jiffies; + data->valid = 1; + } + + up(&data->update_lock); + + return data; +} + +static int __init smsc47m192_init(void) +{ + return i2c_add_driver(&smsc47m192_driver); +} + +static void __exit smsc47m192_exit(void) +{ + i2c_del_driver(&smsc47m192_driver); +} + +MODULE_AUTHOR("Hartmut Rick <linux@rick.claranet.de>"); +MODULE_DESCRIPTION("SMSC47M192 driver"); +MODULE_LICENSE("GPL"); + +module_init(smsc47m192_init); +module_exit(smsc47m192_exit); diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c new file mode 100644 index 000000000..87f7312cc --- /dev/null +++ b/drivers/hwmon/w83791d.c @@ -0,0 +1,1254 @@ +/* + w83791d.c - Part of lm_sensors, Linux kernel modules for hardware + monitoring + + Copyright (C) 2006 Charles Spirakis <bezaur@gmail.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + Supports following chips: + + Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + w83791d 10 5 3 3 0x71 0x5ca3 yes no + + The w83791d chip appears to be part way between the 83781d and the + 83792d. Thus, this file is derived from both the w83792d.c and + w83781d.c files, but its output is more along the lines of the + 83781d (which means there are no changes to the user-mode sensors + program which treats the 83791d as an 83781d). +*/ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/hwmon.h> +#include <linux/hwmon-vid.h> +#include <linux/hwmon-sysfs.h> +#include <linux/err.h> +#include <linux/mutex.h> + +#define NUMBER_OF_VIN 10 +#define NUMBER_OF_FANIN 5 +#define NUMBER_OF_TEMPIN 3 + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD_1(w83791d); +I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: " + "{bus, clientaddr, subclientaddr1, subclientaddr2}"); + +static int reset; +module_param(reset, bool, 0); +MODULE_PARM_DESC(reset, "Set to one to force a hardware chip reset"); + +static int init; +module_param(init, bool, 0); +MODULE_PARM_DESC(init, "Set to one to force extra software initialization"); + +/* The W83791D registers */ +static const u8 W83791D_REG_IN[NUMBER_OF_VIN] = { + 0x20, /* VCOREA in DataSheet */ + 0x21, /* VINR0 in DataSheet */ + 0x22, /* +3.3VIN in DataSheet */ + 0x23, /* VDD5V in DataSheet */ + 0x24, /* +12VIN in DataSheet */ + 0x25, /* -12VIN in DataSheet */ + 0x26, /* -5VIN in DataSheet */ + 0xB0, /* 5VSB in DataSheet */ + 0xB1, /* VBAT in DataSheet */ + 0xB2 /* VINR1 in DataSheet */ +}; + +static const u8 W83791D_REG_IN_MAX[NUMBER_OF_VIN] = { + 0x2B, /* VCOREA High Limit in DataSheet */ + 0x2D, /* VINR0 High Limit in DataSheet */ + 0x2F, /* +3.3VIN High Limit in DataSheet */ + 0x31, /* VDD5V High Limit in DataSheet */ + 0x33, /* +12VIN High Limit in DataSheet */ + 0x35, /* -12VIN High Limit in DataSheet */ + 0x37, /* -5VIN High Limit in DataSheet */ + 0xB4, /* 5VSB High Limit in DataSheet */ + 0xB6, /* VBAT High Limit in DataSheet */ + 0xB8 /* VINR1 High Limit in DataSheet */ +}; +static const u8 W83791D_REG_IN_MIN[NUMBER_OF_VIN] = { + 0x2C, /* VCOREA Low Limit in DataSheet */ + 0x2E, /* VINR0 Low Limit in DataSheet */ + 0x30, /* +3.3VIN Low Limit in DataSheet */ + 0x32, /* VDD5V Low Limit in DataSheet */ + 0x34, /* +12VIN Low Limit in DataSheet */ + 0x36, /* -12VIN Low Limit in DataSheet */ + 0x38, /* -5VIN Low Limit in DataSheet */ + 0xB5, /* 5VSB Low Limit in DataSheet */ + 0xB7, /* VBAT Low Limit in DataSheet */ + 0xB9 /* VINR1 Low Limit in DataSheet */ +}; +static const u8 W83791D_REG_FAN[NUMBER_OF_FANIN] = { + 0x28, /* FAN 1 Count in DataSheet */ + 0x29, /* FAN 2 Count in DataSheet */ + 0x2A, /* FAN 3 Count in DataSheet */ + 0xBA, /* FAN 4 Count in DataSheet */ + 0xBB, /* FAN 5 Count in DataSheet */ +}; +static const u8 W83791D_REG_FAN_MIN[NUMBER_OF_FANIN] = { + 0x3B, /* FAN 1 Count Low Limit in DataSheet */ + 0x3C, /* FAN 2 Count Low Limit in DataSheet */ + 0x3D, /* FAN 3 Count Low Limit in DataSheet */ + 0xBC, /* FAN 4 Count Low Limit in DataSheet */ + 0xBD, /* FAN 5 Count Low Limit in DataSheet */ +}; + +static const u8 W83791D_REG_FAN_CFG[2] = { + 0x84, /* FAN 1/2 configuration */ + 0x95, /* FAN 3 configuration */ +}; + +static const u8 W83791D_REG_FAN_DIV[3] = { + 0x47, /* contains FAN1 and FAN2 Divisor */ + 0x4b, /* contains FAN3 Divisor */ + 0x5C, /* contains FAN4 and FAN5 Divisor */ +}; + +#define W83791D_REG_BANK 0x4E +#define W83791D_REG_TEMP2_CONFIG 0xC2 +#define W83791D_REG_TEMP3_CONFIG 0xCA + +static const u8 W83791D_REG_TEMP1[3] = { + 0x27, /* TEMP 1 in DataSheet */ + 0x39, /* TEMP 1 Over in DataSheet */ + 0x3A, /* TEMP 1 Hyst in DataSheet */ +}; + +static const u8 W83791D_REG_TEMP_ADD[2][6] = { + {0xC0, /* TEMP 2 in DataSheet */ + 0xC1, /* TEMP 2(0.5 deg) in DataSheet */ + 0xC5, /* TEMP 2 Over High part in DataSheet */ + 0xC6, /* TEMP 2 Over Low part in DataSheet */ + 0xC3, /* TEMP 2 Thyst High part in DataSheet */ + 0xC4}, /* TEMP 2 Thyst Low part in DataSheet */ + {0xC8, /* TEMP 3 in DataSheet */ + 0xC9, /* TEMP 3(0.5 deg) in DataSheet */ + 0xCD, /* TEMP 3 Over High part in DataSheet */ + 0xCE, /* TEMP 3 Over Low part in DataSheet */ + 0xCB, /* TEMP 3 Thyst High part in DataSheet */ + 0xCC} /* TEMP 3 Thyst Low part in DataSheet */ +}; + +#define W83791D_REG_BEEP_CONFIG 0x4D + +static const u8 W83791D_REG_BEEP_CTRL[3] = { + 0x56, /* BEEP Control Register 1 */ + 0x57, /* BEEP Control Register 2 */ + 0xA3, /* BEEP Control Register 3 */ +}; + +#define W83791D_REG_CONFIG 0x40 +#define W83791D_REG_VID_FANDIV 0x47 +#define W83791D_REG_DID_VID4 0x49 +#define W83791D_REG_WCHIPID 0x58 +#define W83791D_REG_CHIPMAN 0x4F +#define W83791D_REG_PIN 0x4B +#define W83791D_REG_I2C_SUBADDR 0x4A + +#define W83791D_REG_ALARM1 0xA9 /* realtime status register1 */ +#define W83791D_REG_ALARM2 0xAA /* realtime status register2 */ +#define W83791D_REG_ALARM3 0xAB /* realtime status register3 */ + +#define W83791D_REG_VBAT 0x5D +#define W83791D_REG_I2C_ADDR 0x48 + +/* The SMBus locks itself. The Winbond W83791D has a bank select register + (index 0x4e), but the driver only accesses registers in bank 0. Since + we don't switch banks, we don't need any special code to handle + locking access between bank switches */ +static inline int w83791d_read(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static inline int w83791d_write(struct i2c_client *client, u8 reg, u8 value) +{ + return i2c_smbus_write_byte_data(client, reg, value); +} + +/* The analog voltage inputs have 16mV LSB. Since the sysfs output is + in mV as would be measured on the chip input pin, need to just + multiply/divide by 16 to translate from/to register values. */ +#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8) / 16), 0, 255)) +#define IN_FROM_REG(val) ((val) * 16) + +static u8 fan_to_reg(long rpm, int div) +{ + if (rpm == 0) + return 255; + rpm = SENSORS_LIMIT(rpm, 1, 1000000); + return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); +} + +#define FAN_FROM_REG(val,div) ((val) == 0 ? -1 : \ + ((val) == 255 ? 0 : \ + 1350000 / ((val) * (div)))) + +/* for temp1 which is 8-bit resolution, LSB = 1 degree Celsius */ +#define TEMP1_FROM_REG(val) ((val) * 1000) +#define TEMP1_TO_REG(val) ((val) <= -128000 ? -128 : \ + (val) >= 127000 ? 127 : \ + (val) < 0 ? ((val) - 500) / 1000 : \ + ((val) + 500) / 1000) + +/* for temp2 and temp3 which are 9-bit resolution, LSB = 0.5 degree Celsius + Assumes the top 8 bits are the integral amount and the bottom 8 bits + are the fractional amount. Since we only have 0.5 degree resolution, + the bottom 7 bits will always be zero */ +#define TEMP23_FROM_REG(val) ((val) / 128 * 500) +#define TEMP23_TO_REG(val) ((val) <= -128000 ? 0x8000 : \ + (val) >= 127500 ? 0x7F80 : \ + (val) < 0 ? ((val) - 250) / 500 * 128 : \ + ((val) + 250) / 500 * 128) + + +#define BEEP_MASK_TO_REG(val) ((val) & 0xffffff) +#define BEEP_MASK_FROM_REG(val) ((val) & 0xffffff) + +#define DIV_FROM_REG(val) (1 << (val)) + +static u8 div_to_reg(int nr, long val) +{ + int i; + int max; + + /* first three fan's divisor max out at 8, rest max out at 128 */ + max = (nr < 3) ? 8 : 128; + val = SENSORS_LIMIT(val, 1, max) >> 1; + for (i = 0; i < 7; i++) { + if (val == 0) + break; + val >>= 1; + } + return (u8) i; +} + +struct w83791d_data { + struct i2c_client client; + struct class_device *class_dev; + struct mutex update_lock; + + char valid; /* !=0 if following fields are valid */ + unsigned long last_updated; /* In jiffies */ + + /* array of 2 pointers to subclients */ + struct i2c_client *lm75[2]; + + /* volts */ + u8 in[NUMBER_OF_VIN]; /* Register value */ + u8 in_max[NUMBER_OF_VIN]; /* Register value */ + u8 in_min[NUMBER_OF_VIN]; /* Register value */ + + /* fans */ + u8 fan[NUMBER_OF_FANIN]; /* Register value */ + u8 fan_min[NUMBER_OF_FANIN]; /* Register value */ + u8 fan_div[NUMBER_OF_FANIN]; /* Register encoding, shifted right */ + + /* Temperature sensors */ + + s8 temp1[3]; /* current, over, thyst */ + s16 temp_add[2][3]; /* fixed point value. Top 8 bits are the + integral part, bottom 8 bits are the + fractional part. We only use the top + 9 bits as the resolution is only + to the 0.5 degree C... + two sensors with three values + (cur, over, hyst) */ + + /* Misc */ + u32 alarms; /* realtime status register encoding,combined */ + u8 beep_enable; /* Global beep enable */ + u32 beep_mask; /* Mask off specific beeps */ + u8 vid; /* Register encoding, combined */ + u8 vrm; /* hwmon-vid */ +}; + +static int w83791d_attach_adapter(struct i2c_adapter *adapter); +static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind); +static int w83791d_detach_client(struct i2c_client *client); + +static int w83791d_read(struct i2c_client *client, u8 register); +static int w83791d_write(struct i2c_client *client, u8 register, u8 value); +static struct w83791d_data *w83791d_update_device(struct device *dev); + +#ifdef DEBUG +static void w83791d_print_debug(struct w83791d_data *data, struct device *dev); +#endif + +static void w83791d_init_client(struct i2c_client *client); + +static struct i2c_driver w83791d_driver = { + .driver = { + .name = "w83791d", + }, + .attach_adapter = w83791d_attach_adapter, + .detach_client = w83791d_detach_client, +}; + +/* following are the sysfs callback functions */ +#define show_in_reg(reg) \ +static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ + char *buf) \ +{ \ + struct sensor_device_attribute *sensor_attr = \ + to_sensor_dev_attr(attr); \ + struct w83791d_data *data = w83791d_update_device(dev); \ + int nr = sensor_attr->index; \ + return sprintf(buf,"%d\n", IN_FROM_REG(data->reg[nr])); \ +} + +show_in_reg(in); +show_in_reg(in_min); +show_in_reg(in_max); + +#define store_in_reg(REG, reg) \ +static ssize_t store_in_##reg(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t count) \ +{ \ + struct sensor_device_attribute *sensor_attr = \ + to_sensor_dev_attr(attr); \ + struct i2c_client *client = to_i2c_client(dev); \ + struct w83791d_data *data = i2c_get_clientdata(client); \ + unsigned long val = simple_strtoul(buf, NULL, 10); \ + int nr = sensor_attr->index; \ + \ + mutex_lock(&data->update_lock); \ + data->in_##reg[nr] = IN_TO_REG(val); \ + w83791d_write(client, W83791D_REG_IN_##REG[nr], data->in_##reg[nr]); \ + mutex_unlock(&data->update_lock); \ + \ + return count; \ +} +store_in_reg(MIN, min); +store_in_reg(MAX, max); + +static struct sensor_device_attribute sda_in_input[] = { + SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), + SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), + SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), + SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), + SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), + SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), + SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), + SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), + SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), + SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9), +}; + +static struct sensor_device_attribute sda_in_min[] = { + SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), + SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), + SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2), + SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3), + SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4), + SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5), + SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6), + SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7), + SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8), + SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9), +}; + +static struct sensor_device_attribute sda_in_max[] = { + SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0), + SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1), + SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2), + SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3), + SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4), + SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5), + SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6), + SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7), + SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8), + SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9), +}; + +#define show_fan_reg(reg) \ +static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ + char *buf) \ +{ \ + struct sensor_device_attribute *sensor_attr = \ + to_sensor_dev_attr(attr); \ + struct w83791d_data *data = w83791d_update_device(dev); \ + int nr = sensor_attr->index; \ + return sprintf(buf,"%d\n", \ + FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \ +} + +show_fan_reg(fan); +show_fan_reg(fan_min); + +static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + int nr = sensor_attr->index; + + mutex_lock(&data->update_lock); + data->fan_min[nr] = fan_to_reg(val, DIV_FROM_REG(data->fan_div[nr])); + w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + int nr = sensor_attr->index; + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr])); +} + +/* Note: we save and restore the fan minimum here, because its value is + determined in part by the fan divisor. This follows the principle of + least suprise; the user doesn't expect the fan minimum to change just + because the divisor changed. */ +static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + int nr = sensor_attr->index; + unsigned long min; + u8 tmp_fan_div; + u8 fan_div_reg; + int indx = 0; + u8 keep_mask = 0; + u8 new_shift = 0; + + /* Save fan_min */ + min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); + + mutex_lock(&data->update_lock); + data->fan_div[nr] = div_to_reg(nr, simple_strtoul(buf, NULL, 10)); + + switch (nr) { + case 0: + indx = 0; + keep_mask = 0xcf; + new_shift = 4; + break; + case 1: + indx = 0; + keep_mask = 0x3f; + new_shift = 6; + break; + case 2: + indx = 1; + keep_mask = 0x3f; + new_shift = 6; + break; + case 3: + indx = 2; + keep_mask = 0xf8; + new_shift = 0; + break; + case 4: + indx = 2; + keep_mask = 0x8f; + new_shift = 4; + break; +#ifdef DEBUG + default: + dev_warn(dev, "store_fan_div: Unexpected nr seen: %d\n", nr); + count = -EINVAL; + goto err_exit; +#endif + } + + fan_div_reg = w83791d_read(client, W83791D_REG_FAN_DIV[indx]) + & keep_mask; + tmp_fan_div = (data->fan_div[nr] << new_shift) & ~keep_mask; + + w83791d_write(client, W83791D_REG_FAN_DIV[indx], + fan_div_reg | tmp_fan_div); + + /* Restore fan_min */ + data->fan_min[nr] = fan_to_reg(min, DIV_FROM_REG(data->fan_div[nr])); + w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]); + +#ifdef DEBUG +err_exit: +#endif + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sensor_device_attribute sda_fan_input[] = { + SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0), + SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1), + SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2), + SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3), + SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4), +}; + +static struct sensor_device_attribute sda_fan_min[] = { + SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, + show_fan_min, store_fan_min, 0), + SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, + show_fan_min, store_fan_min, 1), + SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, + show_fan_min, store_fan_min, 2), + SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, + show_fan_min, store_fan_min, 3), + SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, + show_fan_min, store_fan_min, 4), +}; + +static struct sensor_device_attribute sda_fan_div[] = { + SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO, + show_fan_div, store_fan_div, 0), + SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO, + show_fan_div, store_fan_div, 1), + SENSOR_ATTR(fan3_div, S_IWUSR | S_IRUGO, + show_fan_div, store_fan_div, 2), + SENSOR_ATTR(fan4_div, S_IWUSR | S_IRUGO, + show_fan_div, store_fan_div, 3), + SENSOR_ATTR(fan5_div, S_IWUSR | S_IRUGO, + show_fan_div, store_fan_div, 4), +}; + +/* read/write the temperature1, includes measured value and limits */ +static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp1[attr->index])); +} + +static ssize_t store_temp1(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + int nr = attr->index; + + mutex_lock(&data->update_lock); + data->temp1[nr] = TEMP1_TO_REG(val); + w83791d_write(client, W83791D_REG_TEMP1[nr], data->temp1[nr]); + mutex_unlock(&data->update_lock); + return count; +} + +/* read/write temperature2-3, includes measured value and limits */ +static ssize_t show_temp23(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct w83791d_data *data = w83791d_update_device(dev); + int nr = attr->nr; + int index = attr->index; + return sprintf(buf, "%d\n", TEMP23_FROM_REG(data->temp_add[nr][index])); +} + +static ssize_t store_temp23(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + int nr = attr->nr; + int index = attr->index; + + mutex_lock(&data->update_lock); + data->temp_add[nr][index] = TEMP23_TO_REG(val); + w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2], + data->temp_add[nr][index] >> 8); + w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2 + 1], + data->temp_add[nr][index] & 0x80); + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sensor_device_attribute_2 sda_temp_input[] = { + SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0), + SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0), + SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0), +}; + +static struct sensor_device_attribute_2 sda_temp_max[] = { + SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, + show_temp1, store_temp1, 0, 1), + SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, + show_temp23, store_temp23, 0, 1), + SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, + show_temp23, store_temp23, 1, 1), +}; + +static struct sensor_device_attribute_2 sda_temp_max_hyst[] = { + SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, + show_temp1, store_temp1, 0, 2), + SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, + show_temp23, store_temp23, 0, 2), + SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, + show_temp23, store_temp23, 1, 2), +}; + + +/* get reatime status of all sensors items: voltage, temp, fan */ +static ssize_t show_alarms_reg(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%u\n", data->alarms); +} + +static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); + +/* Beep control */ + +#define GLOBAL_BEEP_ENABLE_SHIFT 15 +#define GLOBAL_BEEP_ENABLE_MASK (1 << GLOBAL_BEEP_ENABLE_SHIFT) + +static ssize_t show_beep_enable(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%d\n", data->beep_enable); +} + +static ssize_t show_beep_mask(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%d\n", BEEP_MASK_FROM_REG(data->beep_mask)); +} + + +static ssize_t store_beep_mask(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + int i; + + mutex_lock(&data->update_lock); + + /* The beep_enable state overrides any enabling request from + the masks */ + data->beep_mask = BEEP_MASK_TO_REG(val) & ~GLOBAL_BEEP_ENABLE_MASK; + data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT); + + val = data->beep_mask; + + for (i = 0; i < 3; i++) { + w83791d_write(client, W83791D_REG_BEEP_CTRL[i], (val & 0xff)); + val >>= 8; + } + + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t store_beep_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + long val = simple_strtol(buf, NULL, 10); + + mutex_lock(&data->update_lock); + + data->beep_enable = val ? 1 : 0; + + /* Keep the full mask value in sync with the current enable */ + data->beep_mask &= ~GLOBAL_BEEP_ENABLE_MASK; + data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT); + + /* The global control is in the second beep control register + so only need to update that register */ + val = (data->beep_mask >> 8) & 0xff; + + w83791d_write(client, W83791D_REG_BEEP_CTRL[1], val); + + mutex_unlock(&data->update_lock); + + return count; +} + +static struct sensor_device_attribute sda_beep_ctrl[] = { + SENSOR_ATTR(beep_enable, S_IRUGO | S_IWUSR, + show_beep_enable, store_beep_enable, 0), + SENSOR_ATTR(beep_mask, S_IRUGO | S_IWUSR, + show_beep_mask, store_beep_mask, 1) +}; + +/* cpu voltage regulation information */ +static ssize_t show_vid_reg(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); +} + +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); + +static ssize_t show_vrm_reg(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct w83791d_data *data = w83791d_update_device(dev); + return sprintf(buf, "%d\n", data->vrm); +} + +static ssize_t store_vrm_reg(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + + /* No lock needed as vrm is internal to the driver + (not read from a chip register) and so is not + updated in w83791d_update_device() */ + data->vrm = val; + + return count; +} + +static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); + +/* This function is called when: + * w83791d_driver is inserted (when this module is loaded), for each + available adapter + * when a new adapter is inserted (and w83791d_driver is still present) */ +static int w83791d_attach_adapter(struct i2c_adapter *adapter) +{ + if (!(adapter->class & I2C_CLASS_HWMON)) + return 0; + return i2c_probe(adapter, &addr_data, w83791d_detect); +} + + +static int w83791d_create_subclient(struct i2c_adapter *adapter, + struct i2c_client *client, int addr, + struct i2c_client **sub_cli) +{ + int err; + struct i2c_client *sub_client; + + (*sub_cli) = sub_client = + kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!(sub_client)) { + return -ENOMEM; + } + sub_client->addr = 0x48 + addr; + i2c_set_clientdata(sub_client, NULL); + sub_client->adapter = adapter; + sub_client->driver = &w83791d_driver; + strlcpy(sub_client->name, "w83791d subclient", I2C_NAME_SIZE); + if ((err = i2c_attach_client(sub_client))) { + dev_err(&client->dev, "subclient registration " + "at address 0x%x failed\n", sub_client->addr); + kfree(sub_client); + return err; + } + return 0; +} + + +static int w83791d_detect_subclients(struct i2c_adapter *adapter, int address, + int kind, struct i2c_client *client) +{ + struct w83791d_data *data = i2c_get_clientdata(client); + int i, id, err; + u8 val; + + id = i2c_adapter_id(adapter); + if (force_subclients[0] == id && force_subclients[1] == address) { + for (i = 2; i <= 3; i++) { + if (force_subclients[i] < 0x48 || + force_subclients[i] > 0x4f) { + dev_err(&client->dev, + "invalid subclient " + "address %d; must be 0x48-0x4f\n", + force_subclients[i]); + err = -ENODEV; + goto error_sc_0; + } + } + w83791d_write(client, W83791D_REG_I2C_SUBADDR, + (force_subclients[2] & 0x07) | + ((force_subclients[3] & 0x07) << 4)); + } + + val = w83791d_read(client, W83791D_REG_I2C_SUBADDR); + if (!(val & 0x08)) { + err = w83791d_create_subclient(adapter, client, + val & 0x7, &data->lm75[0]); + if (err < 0) + goto error_sc_0; + } + if (!(val & 0x80)) { + if ((data->lm75[0] != NULL) && + ((val & 0x7) == ((val >> 4) & 0x7))) { + dev_err(&client->dev, + "duplicate addresses 0x%x, " + "use force_subclient\n", + data->lm75[0]->addr); + err = -ENODEV; + goto error_sc_1; + } + err = w83791d_create_subclient(adapter, client, + (val >> 4) & 0x7, &data->lm75[1]); + if (err < 0) + goto error_sc_1; + } + + return 0; + +/* Undo inits in case of errors */ + +error_sc_1: + if (data->lm75[0] != NULL) { + i2c_detach_client(data->lm75[0]); + kfree(data->lm75[0]); + } +error_sc_0: + return err; +} + + +static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct device *dev; + struct w83791d_data *data; + int i, val1, val2; + int err = 0; + const char *client_name = ""; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + goto error0; + } + + /* OK. For now, we presume we have a valid client. We now create the + client structure, even though we cannot fill it completely yet. + But it allows us to access w83791d_{read,write}_value. */ + if (!(data = kzalloc(sizeof(struct w83791d_data), GFP_KERNEL))) { + err = -ENOMEM; + goto error0; + } + + client = &data->client; + dev = &client->dev; + i2c_set_clientdata(client, data); + client->addr = address; + client->adapter = adapter; + client->driver = &w83791d_driver; + mutex_init(&data->update_lock); + + /* Now, we do the remaining detection. */ + + /* The w83791d may be stuck in some other bank than bank 0. This may + make reading other information impossible. Specify a force=... + parameter, and the Winbond will be reset to the right bank. */ + if (kind < 0) { + if (w83791d_read(client, W83791D_REG_CONFIG) & 0x80) { + dev_dbg(dev, "Detection failed at step 1\n"); + goto error1; + } + val1 = w83791d_read(client, W83791D_REG_BANK); + val2 = w83791d_read(client, W83791D_REG_CHIPMAN); + /* Check for Winbond ID if in bank 0 */ + if (!(val1 & 0x07)) { + /* yes it is Bank0 */ + if (((!(val1 & 0x80)) && (val2 != 0xa3)) || + ((val1 & 0x80) && (val2 != 0x5c))) { + dev_dbg(dev, "Detection failed at step 2\n"); + goto error1; + } + } + /* If Winbond chip, address of chip and W83791D_REG_I2C_ADDR + should match */ + if (w83791d_read(client, W83791D_REG_I2C_ADDR) != address) { + dev_dbg(dev, "Detection failed at step 3\n"); + goto error1; + } + } + + /* We either have a force parameter or we have reason to + believe it is a Winbond chip. Either way, we want bank 0 and + Vendor ID high byte */ + val1 = w83791d_read(client, W83791D_REG_BANK) & 0x78; + w83791d_write(client, W83791D_REG_BANK, val1 | 0x80); + + /* Verify it is a Winbond w83791d */ + if (kind <= 0) { + /* get vendor ID */ + val2 = w83791d_read(client, W83791D_REG_CHIPMAN); + if (val2 != 0x5c) { /* the vendor is NOT Winbond */ + dev_dbg(dev, "Detection failed at step 4\n"); + goto error1; + } + val1 = w83791d_read(client, W83791D_REG_WCHIPID); + if (val1 == 0x71) { + kind = w83791d; + } else { + if (kind == 0) + dev_warn(dev, + "w83791d: Ignoring 'force' parameter " + "for unknown chip at adapter %d, " + "address 0x%02x\n", + i2c_adapter_id(adapter), address); + goto error1; + } + } + + if (kind == w83791d) { + client_name = "w83791d"; + } else { + dev_err(dev, "w83791d: Internal error: unknown kind (%d)?!?", + kind); + goto error1; + } + +#ifdef DEBUG + val1 = w83791d_read(client, W83791D_REG_DID_VID4); + dev_dbg(dev, "Device ID version: %d.%d (0x%02x)\n", + (val1 >> 5) & 0x07, (val1 >> 1) & 0x0f, val1); +#endif + + /* Fill in the remaining client fields and put into the global list */ + strlcpy(client->name, client_name, I2C_NAME_SIZE); + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto error1; + + if ((err = w83791d_detect_subclients(adapter, address, kind, client))) + goto error2; + + /* Initialize the chip */ + w83791d_init_client(client); + + /* If the fan_div is changed, make sure there is a rational + fan_min in place */ + for (i = 0; i < NUMBER_OF_FANIN; i++) { + data->fan_min[i] = w83791d_read(client, W83791D_REG_FAN_MIN[i]); + } + + /* Register sysfs hooks */ + data->class_dev = hwmon_device_register(dev); + if (IS_ERR(data->class_dev)) { + err = PTR_ERR(data->class_dev); + goto error3; + } + + for (i = 0; i < NUMBER_OF_VIN; i++) { + device_create_file(dev, &sda_in_input[i].dev_attr); + device_create_file(dev, &sda_in_min[i].dev_attr); + device_create_file(dev, &sda_in_max[i].dev_attr); + } + + for (i = 0; i < NUMBER_OF_FANIN; i++) { + device_create_file(dev, &sda_fan_input[i].dev_attr); + device_create_file(dev, &sda_fan_div[i].dev_attr); + device_create_file(dev, &sda_fan_min[i].dev_attr); + } + + for (i = 0; i < NUMBER_OF_TEMPIN; i++) { + device_create_file(dev, &sda_temp_input[i].dev_attr); + device_create_file(dev, &sda_temp_max[i].dev_attr); + device_create_file(dev, &sda_temp_max_hyst[i].dev_attr); + } + + device_create_file(dev, &dev_attr_alarms); + + for (i = 0; i < ARRAY_SIZE(sda_beep_ctrl); i++) { + device_create_file(dev, &sda_beep_ctrl[i].dev_attr); + } + + device_create_file(dev, &dev_attr_cpu0_vid); + device_create_file(dev, &dev_attr_vrm); + + return 0; + +error3: + if (data->lm75[0] != NULL) { + i2c_detach_client(data->lm75[0]); + kfree(data->lm75[0]); + } + if (data->lm75[1] != NULL) { + i2c_detach_client(data->lm75[1]); + kfree(data->lm75[1]); + } +error2: + i2c_detach_client(client); +error1: + kfree(data); +error0: + return err; +} + +static int w83791d_detach_client(struct i2c_client *client) +{ + struct w83791d_data *data = i2c_get_clientdata(client); + int err; + + /* main client */ + if (data) + hwmon_device_unregister(data->class_dev); + + if ((err = i2c_detach_client(client))) + return err; + + /* main client */ + if (data) + kfree(data); + /* subclient */ + else + kfree(client); + + return 0; +} + +static void w83791d_init_client(struct i2c_client *client) +{ + struct w83791d_data *data = i2c_get_clientdata(client); + u8 tmp; + u8 old_beep; + + /* The difference between reset and init is that reset + does a hard reset of the chip via index 0x40, bit 7, + but init simply forces certain registers to have "sane" + values. The hope is that the BIOS has done the right + thing (which is why the default is reset=0, init=0), + but if not, reset is the hard hammer and init + is the soft mallet both of which are trying to whack + things into place... + NOTE: The data sheet makes a distinction between + "power on defaults" and "reset by MR". As far as I can tell, + the hard reset puts everything into a power-on state so I'm + not sure what "reset by MR" means or how it can happen. + */ + if (reset || init) { + /* keep some BIOS settings when we... */ + old_beep = w83791d_read(client, W83791D_REG_BEEP_CONFIG); + + if (reset) { + /* ... reset the chip and ... */ + w83791d_write(client, W83791D_REG_CONFIG, 0x80); + } + + /* ... disable power-on abnormal beep */ + w83791d_write(client, W83791D_REG_BEEP_CONFIG, old_beep | 0x80); + + /* disable the global beep (not done by hard reset) */ + tmp = w83791d_read(client, W83791D_REG_BEEP_CTRL[1]); + w83791d_write(client, W83791D_REG_BEEP_CTRL[1], tmp & 0xef); + + if (init) { + /* Make sure monitoring is turned on for add-ons */ + tmp = w83791d_read(client, W83791D_REG_TEMP2_CONFIG); + if (tmp & 1) { + w83791d_write(client, W83791D_REG_TEMP2_CONFIG, + tmp & 0xfe); + } + + tmp = w83791d_read(client, W83791D_REG_TEMP3_CONFIG); + if (tmp & 1) { + w83791d_write(client, W83791D_REG_TEMP3_CONFIG, + tmp & 0xfe); + } + + /* Start monitoring */ + tmp = w83791d_read(client, W83791D_REG_CONFIG) & 0xf7; + w83791d_write(client, W83791D_REG_CONFIG, tmp | 0x01); + } + } + + data->vrm = vid_which_vrm(); +} + +static struct w83791d_data *w83791d_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct w83791d_data *data = i2c_get_clientdata(client); + int i, j; + u8 reg_array_tmp[3]; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + (HZ * 3)) + || !data->valid) { + dev_dbg(dev, "Starting w83791d device update\n"); + + /* Update the voltages measured value and limits */ + for (i = 0; i < NUMBER_OF_VIN; i++) { + data->in[i] = w83791d_read(client, + W83791D_REG_IN[i]); + data->in_max[i] = w83791d_read(client, + W83791D_REG_IN_MAX[i]); + data->in_min[i] = w83791d_read(client, + W83791D_REG_IN_MIN[i]); + } + + /* Update the fan counts and limits */ + for (i = 0; i < NUMBER_OF_FANIN; i++) { + /* Update the Fan measured value and limits */ + data->fan[i] = w83791d_read(client, + W83791D_REG_FAN[i]); + data->fan_min[i] = w83791d_read(client, + W83791D_REG_FAN_MIN[i]); + } + + /* Update the fan divisor */ + for (i = 0; i < 3; i++) { + reg_array_tmp[i] = w83791d_read(client, + W83791D_REG_FAN_DIV[i]); + } + data->fan_div[0] = (reg_array_tmp[0] >> 4) & 0x03; + data->fan_div[1] = (reg_array_tmp[0] >> 6) & 0x03; + data->fan_div[2] = (reg_array_tmp[1] >> 6) & 0x03; + data->fan_div[3] = reg_array_tmp[2] & 0x07; + data->fan_div[4] = (reg_array_tmp[2] >> 4) & 0x07; + + /* Update the first temperature sensor */ + for (i = 0; i < 3; i++) { + data->temp1[i] = w83791d_read(client, + W83791D_REG_TEMP1[i]); + } + + /* Update the rest of the temperature sensors */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 3; j++) { + data->temp_add[i][j] = + (w83791d_read(client, + W83791D_REG_TEMP_ADD[i][j * 2]) << 8) | + w83791d_read(client, + W83791D_REG_TEMP_ADD[i][j * 2 + 1]); + } + } + + /* Update the realtime status */ + data->alarms = + w83791d_read(client, W83791D_REG_ALARM1) + + (w83791d_read(client, W83791D_REG_ALARM2) << 8) + + (w83791d_read(client, W83791D_REG_ALARM3) << 16); + + /* Update the beep configuration information */ + data->beep_mask = + w83791d_read(client, W83791D_REG_BEEP_CTRL[0]) + + (w83791d_read(client, W83791D_REG_BEEP_CTRL[1]) << 8) + + (w83791d_read(client, W83791D_REG_BEEP_CTRL[2]) << 16); + + data->beep_enable = + (data->beep_mask >> GLOBAL_BEEP_ENABLE_SHIFT) & 0x01; + + /* Update the cpu voltage information */ + i = w83791d_read(client, W83791D_REG_VID_FANDIV); + data->vid = i & 0x0f; + data->vid |= (w83791d_read(client, W83791D_REG_DID_VID4) & 0x01) + << 4; + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + +#ifdef DEBUG + w83791d_print_debug(data, dev); +#endif + + return data; +} + +#ifdef DEBUG +static void w83791d_print_debug(struct w83791d_data *data, struct device *dev) +{ + int i = 0, j = 0; + + dev_dbg(dev, "======Start of w83791d debug values======\n"); + dev_dbg(dev, "%d set of Voltages: ===>\n", NUMBER_OF_VIN); + for (i = 0; i < NUMBER_OF_VIN; i++) { + dev_dbg(dev, "vin[%d] is: 0x%02x\n", i, data->in[i]); + dev_dbg(dev, "vin[%d] min is: 0x%02x\n", i, data->in_min[i]); + dev_dbg(dev, "vin[%d] max is: 0x%02x\n", i, data->in_max[i]); + } + dev_dbg(dev, "%d set of Fan Counts/Divisors: ===>\n", NUMBER_OF_FANIN); + for (i = 0; i < NUMBER_OF_FANIN; i++) { + dev_dbg(dev, "fan[%d] is: 0x%02x\n", i, data->fan[i]); + dev_dbg(dev, "fan[%d] min is: 0x%02x\n", i, data->fan_min[i]); + dev_dbg(dev, "fan_div[%d] is: 0x%02x\n", i, data->fan_div[i]); + } + + /* temperature math is signed, but only print out the + bits that matter */ + dev_dbg(dev, "%d set of Temperatures: ===>\n", NUMBER_OF_TEMPIN); + for (i = 0; i < 3; i++) { + dev_dbg(dev, "temp1[%d] is: 0x%02x\n", i, (u8) data->temp1[i]); + } + for (i = 0; i < 2; i++) { + for (j = 0; j < 3; j++) { + dev_dbg(dev, "temp_add[%d][%d] is: 0x%04x\n", i, j, + (u16) data->temp_add[i][j]); + } + } + + dev_dbg(dev, "Misc Information: ===>\n"); + dev_dbg(dev, "alarm is: 0x%08x\n", data->alarms); + dev_dbg(dev, "beep_mask is: 0x%08x\n", data->beep_mask); + dev_dbg(dev, "beep_enable is: %d\n", data->beep_enable); + dev_dbg(dev, "vid is: 0x%02x\n", data->vid); + dev_dbg(dev, "vrm is: 0x%02x\n", data->vrm); + dev_dbg(dev, "=======End of w83791d debug values========\n"); + dev_dbg(dev, "\n"); +} +#endif + +static int __init sensors_w83791d_init(void) +{ + return i2c_add_driver(&w83791d_driver); +} + +static void __exit sensors_w83791d_exit(void) +{ + i2c_del_driver(&w83791d_driver); +} + +MODULE_AUTHOR("Charles Spirakis <bezaur@gmail.com>"); +MODULE_DESCRIPTION("W83791D driver"); +MODULE_LICENSE("GPL"); + +module_init(sensors_w83791d_init); +module_exit(sensors_w83791d_exit); diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c new file mode 100644 index 000000000..820a75232 --- /dev/null +++ b/drivers/i2c/busses/i2c-ocores.c @@ -0,0 +1,340 @@ +/* + * i2c-ocores.c: I2C bus driver for OpenCores I2C controller + * (http://www.opencores.org/projects.cgi/web/i2c/overview). + * + * Peter Korsgaard <jacmet@sunsite.dk> + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/platform_device.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/wait.h> +#include <linux/i2c-ocores.h> +#include <asm/io.h> + +struct ocores_i2c { + void __iomem *base; + int regstep; + wait_queue_head_t wait; + struct i2c_adapter adap; + struct i2c_msg *msg; + int pos; + int nmsgs; + int state; /* see STATE_ */ +}; + +/* registers */ +#define OCI2C_PRELOW 0 +#define OCI2C_PREHIGH 1 +#define OCI2C_CONTROL 2 +#define OCI2C_DATA 3 +#define OCI2C_CMD 4 /* write only */ +#define OCI2C_STATUS 4 /* read only, same address as OCI2C_CMD */ + +#define OCI2C_CTRL_IEN 0x40 +#define OCI2C_CTRL_EN 0x80 + +#define OCI2C_CMD_START 0x91 +#define OCI2C_CMD_STOP 0x41 +#define OCI2C_CMD_READ 0x21 +#define OCI2C_CMD_WRITE 0x11 +#define OCI2C_CMD_READ_ACK 0x21 +#define OCI2C_CMD_READ_NACK 0x29 +#define OCI2C_CMD_IACK 0x01 + +#define OCI2C_STAT_IF 0x01 +#define OCI2C_STAT_TIP 0x02 +#define OCI2C_STAT_ARBLOST 0x20 +#define OCI2C_STAT_BUSY 0x40 +#define OCI2C_STAT_NACK 0x80 + +#define STATE_DONE 0 +#define STATE_START 1 +#define STATE_WRITE 2 +#define STATE_READ 3 +#define STATE_ERROR 4 + +static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) +{ + iowrite8(value, i2c->base + reg * i2c->regstep); +} + +static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) +{ + return ioread8(i2c->base + reg * i2c->regstep); +} + +static void ocores_process(struct ocores_i2c *i2c) +{ + struct i2c_msg *msg = i2c->msg; + u8 stat = oc_getreg(i2c, OCI2C_STATUS); + + if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) { + /* stop has been sent */ + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); + wake_up(&i2c->wait); + return; + } + + /* error? */ + if (stat & OCI2C_STAT_ARBLOST) { + i2c->state = STATE_ERROR; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + return; + } + + if ((i2c->state == STATE_START) || (i2c->state == STATE_WRITE)) { + i2c->state = + (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE; + + if (stat & OCI2C_STAT_NACK) { + i2c->state = STATE_ERROR; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + return; + } + } else + msg->buf[i2c->pos++] = oc_getreg(i2c, OCI2C_DATA); + + /* end of msg? */ + if (i2c->pos == msg->len) { + i2c->nmsgs--; + i2c->msg++; + i2c->pos = 0; + msg = i2c->msg; + + if (i2c->nmsgs) { /* end? */ + /* send start? */ + if (!(msg->flags & I2C_M_NOSTART)) { + u8 addr = (msg->addr << 1); + + if (msg->flags & I2C_M_RD) + addr |= 1; + + i2c->state = STATE_START; + + oc_setreg(i2c, OCI2C_DATA, addr); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); + return; + } else + i2c->state = (msg->flags & I2C_M_RD) + ? STATE_READ : STATE_WRITE; + } else { + i2c->state = STATE_DONE; + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); + return; + } + } + + if (i2c->state == STATE_READ) { + oc_setreg(i2c, OCI2C_CMD, i2c->pos == (msg->len-1) ? + OCI2C_CMD_READ_NACK : OCI2C_CMD_READ_ACK); + } else { + oc_setreg(i2c, OCI2C_DATA, msg->buf[i2c->pos++]); + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_WRITE); + } +} + +static irqreturn_t ocores_isr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct ocores_i2c *i2c = dev_id; + + ocores_process(i2c); + + return IRQ_HANDLED; +} + +static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct ocores_i2c *i2c = i2c_get_adapdata(adap); + + i2c->msg = msgs; + i2c->pos = 0; + i2c->nmsgs = num; + i2c->state = STATE_START; + + oc_setreg(i2c, OCI2C_DATA, + (i2c->msg->addr << 1) | + ((i2c->msg->flags & I2C_M_RD) ? 1:0)); + + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); + + if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || + (i2c->state == STATE_DONE), HZ)) + return (i2c->state == STATE_DONE) ? num : -EIO; + else + return -ETIMEDOUT; +} + +static void ocores_init(struct ocores_i2c *i2c, + struct ocores_i2c_platform_data *pdata) +{ + int prescale; + u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL); + + /* make sure the device is disabled */ + oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); + + prescale = (pdata->clock_khz / (5*100)) - 1; + oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff); + oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8); + + /* Init the device */ + oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); + oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN | OCI2C_CTRL_EN); +} + + +static u32 ocores_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static struct i2c_algorithm ocores_algorithm = { + .master_xfer = ocores_xfer, + .functionality = ocores_func, +}; + +static struct i2c_adapter ocores_adapter = { + .owner = THIS_MODULE, + .name = "i2c-ocores", + .class = I2C_CLASS_HWMON, + .algo = &ocores_algorithm, +}; + + +static int __devinit ocores_i2c_probe(struct platform_device *pdev) +{ + struct ocores_i2c *i2c; + struct ocores_i2c_platform_data *pdata; + struct resource *res, *res2; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res2) + return -ENODEV; + + pdata = (struct ocores_i2c_platform_data*) pdev->dev.platform_data; + if (!pdata) + return -ENODEV; + + i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + + if (!request_mem_region(res->start, res->end - res->start + 1, + pdev->name)) { + dev_err(&pdev->dev, "Memory region busy\n"); + ret = -EBUSY; + goto request_mem_failed; + } + + i2c->base = ioremap(res->start, res->end - res->start + 1); + if (!i2c->base) { + dev_err(&pdev->dev, "Unable to map registers\n"); + ret = -EIO; + goto map_failed; + } + + i2c->regstep = pdata->regstep; + ocores_init(i2c, pdata); + + init_waitqueue_head(&i2c->wait); + ret = request_irq(res2->start, ocores_isr, 0, pdev->name, i2c); + if (ret) { + dev_err(&pdev->dev, "Cannot claim IRQ\n"); + goto request_irq_failed; + } + + /* hook up driver to tree */ + platform_set_drvdata(pdev, i2c); + i2c->adap = ocores_adapter; + i2c_set_adapdata(&i2c->adap, i2c); + i2c->adap.dev.parent = &pdev->dev; + + /* add i2c adapter to i2c tree */ + ret = i2c_add_adapter(&i2c->adap); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter\n"); + goto add_adapter_failed; + } + + return 0; + +add_adapter_failed: + free_irq(res2->start, i2c); +request_irq_failed: + iounmap(i2c->base); +map_failed: + release_mem_region(res->start, res->end - res->start + 1); +request_mem_failed: + kfree(i2c); + + return ret; +} + +static int __devexit ocores_i2c_remove(struct platform_device* pdev) +{ + struct ocores_i2c *i2c = platform_get_drvdata(pdev); + struct resource *res; + + /* disable i2c logic */ + oc_setreg(i2c, OCI2C_CONTROL, oc_getreg(i2c, OCI2C_CONTROL) + & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); + + /* remove adapter & data */ + i2c_del_adapter(&i2c->adap); + platform_set_drvdata(pdev, NULL); + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res) + free_irq(res->start, i2c); + + iounmap(i2c->base); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res) + release_mem_region(res->start, res->end - res->start + 1); + + kfree(i2c); + + return 0; +} + +static struct platform_driver ocores_i2c_driver = { + .probe = ocores_i2c_probe, + .remove = __devexit_p(ocores_i2c_remove), + .driver = { + .owner = THIS_MODULE, + .name = "ocores-i2c", + }, +}; + +static int __init ocores_i2c_init(void) +{ + return platform_driver_register(&ocores_i2c_driver); +} + +static void __exit ocores_i2c_exit(void) +{ + platform_driver_unregister(&ocores_i2c_driver); +} + +module_init(ocores_i2c_init); +module_exit(ocores_i2c_exit); + +MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>"); +MODULE_DESCRIPTION("OpenCores I2C bus driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c new file mode 100644 index 000000000..1205e8027 --- /dev/null +++ b/drivers/infiniband/core/addr.c @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2005 Voltaire Inc. All rights reserved. + * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved. + * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved. + * Copyright (c) 2005 Intel Corporation. All rights reserved. + * + * This Software is licensed under one of the following licenses: + * + * 1) under the terms of the "Common Public License 1.0" a copy of which is + * available from the Open Source Initiative, see + * http://www.opensource.org/licenses/cpl.php. + * + * 2) under the terms of the "The BSD License" a copy of which is + * available from the Open Source Initiative, see + * http://www.opensource.org/licenses/bsd-license.php. + * + * 3) under the terms of the "GNU General Public License (GPL) Version 2" a + * copy of which is available from the Open Source Initiative, see + * http://www.opensource.org/licenses/gpl-license.php. + * + * Licensee has the right to choose one of the above licenses. + * + * Redistributions of source code must retain the above copyright + * notice and one of the license notices. + * + * Redistributions in binary form must reproduce both the above copyright + * notice, one of the license notices in the documentation + * and/or other materials provided with the distribution. + */ + +#include <linux/mutex.h> +#include <linux/inetdevice.h> +#include <linux/workqueue.h> +#include <linux/if_arp.h> +#include <net/arp.h> +#include <net/neighbour.h> +#include <net/route.h> +#include <net/netevent.h> +#include <rdma/ib_addr.h> + +MODULE_AUTHOR("Sean Hefty"); +MODULE_DESCRIPTION("IB Address Translation"); +MODULE_LICENSE("Dual BSD/GPL"); + +struct addr_req { + struct list_head list; + struct sockaddr src_addr; + struct sockaddr dst_addr; + struct rdma_dev_addr *addr; + void *context; + void (*callback)(int status, struct sockaddr *src_addr, + struct rdma_dev_addr *addr, void *context); + unsigned long timeout; + int status; +}; + +static void process_req(void *data); + +static DEFINE_MUTEX(lock); +static LIST_HEAD(req_list); +static DECLARE_WORK(work, process_req, NULL); +static struct workqueue_struct *addr_wq; + +static int copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, + unsigned char *dst_dev_addr) +{ + switch (dev->type) { + case ARPHRD_INFINIBAND: + dev_addr->dev_type = IB_NODE_CA; + break; + default: + return -EADDRNOTAVAIL; + } + + memcpy(dev_addr->src_dev_addr, dev->dev_addr, MAX_ADDR_LEN); + memcpy(dev_addr->broadcast, dev->broadcast, MAX_ADDR_LEN); + if (dst_dev_addr) + memcpy(dev_addr->dst_dev_addr, dst_dev_addr, MAX_ADDR_LEN); + return 0; +} + +int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr) +{ + struct net_device *dev; + u32 ip = ((struct sockaddr_in *) addr)->sin_addr.s_addr; + int ret; + + dev = ip_dev_find(ip); + if (!dev) + return -EADDRNOTAVAIL; + + ret = copy_addr(dev_addr, dev, NULL); + dev_put(dev); + return ret; +} +EXPORT_SYMBOL(rdma_translate_ip); + +static void set_timeout(unsigned long time) +{ + unsigned long delay; + + cancel_delayed_work(&work); + + delay = time - jiffies; + if ((long)delay <= 0) + delay = 1; + + queue_delayed_work(addr_wq, &work, delay); +} + +static void queue_req(struct addr_req *req) +{ + struct addr_req *temp_req; + + mutex_lock(&lock); + list_for_each_entry_reverse(temp_req, &req_list, list) { + if (time_after(req->timeout, temp_req->timeout)) + break; + } + + list_add(&req->list, &temp_req->list); + + if (req_list.next == &req->list) + set_timeout(req->timeout); + mutex_unlock(&lock); +} + +static void addr_send_arp(struct sockaddr_in *dst_in) +{ + struct rtable *rt; + struct flowi fl; + u32 dst_ip = dst_in->sin_addr.s_addr; + + memset(&fl, 0, sizeof fl); + fl.nl_u.ip4_u.daddr = dst_ip; + if (ip_route_output_key(&rt, &fl)) + return; + + arp_send(ARPOP_REQUEST, ETH_P_ARP, rt->rt_gateway, rt->idev->dev, + rt->rt_src, NULL, rt->idev->dev->dev_addr, NULL); + ip_rt_put(rt); +} + +static int addr_resolve_remote(struct sockaddr_in *src_in, + struct sockaddr_in *dst_in, + struct rdma_dev_addr *addr) +{ + u32 src_ip = src_in->sin_addr.s_addr; + u32 dst_ip = dst_in->sin_addr.s_addr; + struct flowi fl; + struct rtable *rt; + struct neighbour *neigh; + int ret; + + memset(&fl, 0, sizeof fl); + fl.nl_u.ip4_u.daddr = dst_ip; + fl.nl_u.ip4_u.saddr = src_ip; + ret = ip_route_output_key(&rt, &fl); + if (ret) + goto out; + + /* If the device does ARP internally, return 'done' */ + if (rt->idev->dev->flags & IFF_NOARP) { + copy_addr(addr, rt->idev->dev, NULL); + goto put; + } + + neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->idev->dev); + if (!neigh) { + ret = -ENODATA; + goto put; + } + + if (!(neigh->nud_state & NUD_VALID)) { + ret = -ENODATA; + goto release; + } + + if (!src_ip) { + src_in->sin_family = dst_in->sin_family; + src_in->sin_addr.s_addr = rt->rt_src; + } + + ret = copy_addr(addr, neigh->dev, neigh->ha); +release: + neigh_release(neigh); +put: + ip_rt_put(rt); +out: + return ret; +} + +static void process_req(void *data) +{ + struct addr_req *req, *temp_req; + struct sockaddr_in *src_in, *dst_in; + struct list_head done_list; + + INIT_LIST_HEAD(&done_list); + + mutex_lock(&lock); + list_for_each_entry_safe(req, temp_req, &req_list, list) { + if (req->status) { + src_in = (struct sockaddr_in *) &req->src_addr; + dst_in = (struct sockaddr_in *) &req->dst_addr; + req->status = addr_resolve_remote(src_in, dst_in, + req->addr); + } + if (req->status && time_after(jiffies, req->timeout)) + req->status = -ETIMEDOUT; + else if (req->status == -ENODATA) + continue; + + list_del(&req->list); + list_add_tail(&req->list, &done_list); + } + + if (!list_empty(&req_list)) { + req = list_entry(req_list.next, struct addr_req, list); + set_timeout(req->timeout); + } + mutex_unlock(&lock); + + list_for_each_entry_safe(req, temp_req, &done_list, list) { + list_del(&req->list); + req->callback(req->status, &req->src_addr, req->addr, + req->context); + kfree(req); + } +} + +static int addr_resolve_local(struct sockaddr_in *src_in, + struct sockaddr_in *dst_in, + struct rdma_dev_addr *addr) +{ + struct net_device *dev; + u32 src_ip = src_in->sin_addr.s_addr; + u32 dst_ip = dst_in->sin_addr.s_addr; + int ret; + + dev = ip_dev_find(dst_ip); + if (!dev) + return -EADDRNOTAVAIL; + + if (ZERONET(src_ip)) { + src_in->sin_family = dst_in->sin_family; + src_in->sin_addr.s_addr = dst_ip; + ret = copy_addr(addr, dev, dev->dev_addr); + } else if (LOOPBACK(src_ip)) { + ret = rdma_translate_ip((struct sockaddr *)dst_in, addr); + if (!ret) + memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN); + } else { + ret = rdma_translate_ip((struct sockaddr *)src_in, addr); + if (!ret) + memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN); + } + + dev_put(dev); + return ret; +} + +int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr, + struct rdma_dev_addr *addr, int timeout_ms, + void (*callback)(int status, struct sockaddr *src_addr, + struct rdma_dev_addr *addr, void *context), + void *context) +{ + struct sockaddr_in *src_in, *dst_in; + struct addr_req *req; + int ret = 0; + + req = kmalloc(sizeof *req, GFP_KERNEL); + if (!req) + return -ENOMEM; + memset(req, 0, sizeof *req); + + if (src_addr) + memcpy(&req->src_addr, src_addr, ip_addr_size(src_addr)); + memcpy(&req->dst_addr, dst_addr, ip_addr_size(dst_addr)); + req->addr = addr; + req->callback = callback; + req->context = context; + + src_in = (struct sockaddr_in *) &req->src_addr; + dst_in = (struct sockaddr_in *) &req->dst_addr; + + req->status = addr_resolve_local(src_in, dst_in, addr); + if (req->status == -EADDRNOTAVAIL) + req->status = addr_resolve_remote(src_in, dst_in, addr); + + switch (req->status) { + case 0: + req->timeout = jiffies; + queue_req(req); + break; + case -ENODATA: + req->timeout = msecs_to_jiffies(timeout_ms) + jiffies; + queue_req(req); + addr_send_arp(dst_in); + break; + default: + ret = req->status; + kfree(req); + break; + } + return ret; +} +EXPORT_SYMBOL(rdma_resolve_ip); + +void rdma_addr_cancel(struct rdma_dev_addr *addr) +{ + struct addr_req *req, *temp_req; + + mutex_lock(&lock); + list_for_each_entry_safe(req, temp_req, &req_list, list) { + if (req->addr == addr) { + req->status = -ECANCELED; + req->timeout = jiffies; + list_del(&req->list); + list_add(&req->list, &req_list); + set_timeout(req->timeout); + break; + } + } + mutex_unlock(&lock); +} +EXPORT_SYMBOL(rdma_addr_cancel); + +static int netevent_callback(struct notifier_block *self, unsigned long event, + void *ctx) +{ + if (event == NETEVENT_NEIGH_UPDATE) { + struct neighbour *neigh = ctx; + + if (neigh->dev->type == ARPHRD_INFINIBAND && + (neigh->nud_state & NUD_VALID)) { + set_timeout(jiffies); + } + } + return 0; +} + +static struct notifier_block nb = { + .notifier_call = netevent_callback +}; + +static int addr_init(void) +{ + addr_wq = create_singlethread_workqueue("ib_addr_wq"); + if (!addr_wq) + return -ENOMEM; + + register_netevent_notifier(&nb); + return 0; +} + +static void addr_cleanup(void) +{ + unregister_netevent_notifier(&nb); + destroy_workqueue(addr_wq); +} + +module_init(addr_init); +module_exit(addr_cleanup); diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c new file mode 100644 index 000000000..5d625a811 --- /dev/null +++ b/drivers/infiniband/core/cma.c @@ -0,0 +1,1929 @@ +/* + * Copyright (c) 2005 Voltaire Inc. All rights reserved. + * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved. + * Copyright (c) 1999-2005, Mellanox Technologies, Inc. All rights reserved. + * Copyright (c) 2005-2006 Intel Corporation. All rights reserved. + * + * This Software is licensed under one of the following licenses: + * + * 1) under the terms of the "Common Public License 1.0" a copy of which is + * available from the Open Source Initiative, see + * http://www.opensource.org/licenses/cpl.php. + * + * 2) under the terms of the "The BSD License" a copy of which is + * available from the Open Source Initiative, see + * http://www.opensource.org/licenses/bsd-license.php. + * + * 3) under the terms of the "GNU General Public License (GPL) Version 2" a + * copy of which is available from the Open Source Initiative, see + * http://www.opensource.org/licenses/gpl-license.php. + * + * Licensee has the right to choose one of the above licenses. + * + * Redistributions of source code must retain the above copyright + * notice and one of the license notices. + * + * Redistributions in binary form must reproduce both the above copyright + * notice, one of the license notices in the documentation + * and/or other materials provided with the distribution. + * + */ + +#include <linux/completion.h> +#include <linux/in.h> +#include <linux/in6.h> +#include <linux/mutex.h> +#include <linux/random.h> +#include <linux/idr.h> + +#include <net/tcp.h> + +#include <rdma/rdma_cm.h> +#include <rdma/rdma_cm_ib.h> +#include <rdma/ib_cache.h> +#include <rdma/ib_cm.h> +#include <rdma/ib_sa.h> + +MODULE_AUTHOR("Sean Hefty"); +MODULE_DESCRIPTION("Generic RDMA CM Agent"); +MODULE_LICENSE("Dual BSD/GPL"); + +#define CMA_CM_RESPONSE_TIMEOUT 20 +#define CMA_MAX_CM_RETRIES 15 + +static void cma_add_one(struct ib_device *device); +static void cma_remove_one(struct ib_device *device); + +static struct ib_client cma_client = { + .name = "cma", + .add = cma_add_one, + .remove = cma_remove_one +}; + +static LIST_HEAD(dev_list); +static LIST_HEAD(listen_any_list); +static DEFINE_MUTEX(lock); +static struct workqueue_struct *cma_wq; +static DEFINE_IDR(sdp_ps); +static DEFINE_IDR(tcp_ps); + +struct cma_device { + struct list_head list; + struct ib_device *device; + __be64 node_guid; + struct completion comp; + atomic_t refcount; + struct list_head id_list; +}; + +enum cma_state { + CMA_IDLE, + CMA_ADDR_QUERY, + CMA_ADDR_RESOLVED, + CMA_ROUTE_QUERY, + CMA_ROUTE_RESOLVED, + CMA_CONNECT, + CMA_DISCONNECT, + CMA_ADDR_BOUND, + CMA_LISTEN, + CMA_DEVICE_REMOVAL, + CMA_DESTROYING +}; + +struct rdma_bind_list { + struct idr *ps; + struct hlist_head owners; + unsigned short port; +}; + +/* + * Device removal can occur at anytime, so we need extra handling to + * serialize notifying the user of device removal with other callbacks. + * We do this by disabling removal notification while a callback is in process, + * and reporting it after the callback completes. + */ +struct rdma_id_private { + struct rdma_cm_id id; + + struct rdma_bind_list *bind_list; + struct hlist_node node; + struct list_head list; + struct list_head listen_list; + struct cma_device *cma_dev; + + enum cma_state state; + spinlock_t lock; + struct completion comp; + atomic_t refcount; + wait_queue_head_t wait_remove; + atomic_t dev_remove; + + int backlog; + int timeout_ms; + struct ib_sa_query *query; + int query_id; + union { + struct ib_cm_id *ib; + } cm_id; + + u32 seq_num; + u32 qp_num; + enum ib_qp_type qp_type; + u8 srq; +}; + +struct cma_work { + struct work_struct work; + struct rdma_id_private *id; + enum cma_state old_state; + enum cma_state new_state; + struct rdma_cm_event event; +}; + +union cma_ip_addr { + struct in6_addr ip6; + struct { + __u32 pad[3]; + __u32 addr; + } ip4; +}; + +struct cma_hdr { + u8 cma_version; + u8 ip_version; /* IP version: 7:4 */ + __u16 port; + union cma_ip_addr src_addr; + union cma_ip_addr dst_addr; +}; + +struct sdp_hh { + u8 bsdh[16]; + u8 sdp_version; /* Major version: 7:4 */ + u8 ip_version; /* IP version: 7:4 */ + u8 sdp_specific1[10]; + __u16 port; + __u16 sdp_specific2; + union cma_ip_addr src_addr; + union cma_ip_addr dst_addr; +}; + +struct sdp_hah { + u8 bsdh[16]; + u8 sdp_version; +}; + +#define CMA_VERSION 0x00 +#define SDP_MAJ_VERSION 0x2 + +static int cma_comp(struct rdma_id_private *id_priv, enum cma_state comp) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&id_priv->lock, flags); + ret = (id_priv->state == comp); + spin_unlock_irqrestore(&id_priv->lock, flags); + return ret; +} + +static int cma_comp_exch(struct rdma_id_private *id_priv, + enum cma_state comp, enum cma_state exch) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&id_priv->lock, flags); + if ((ret = (id_priv->state == comp))) + id_priv->state = exch; + spin_unlock_irqrestore(&id_priv->lock, flags); + return ret; +} + +static enum cma_state cma_exch(struct rdma_id_private *id_priv, + enum cma_state exch) +{ + unsigned long flags; + enum cma_state old; + + spin_lock_irqsave(&id_priv->lock, flags); + old = id_priv->state; + id_priv->state = exch; + spin_unlock_irqrestore(&id_priv->lock, flags); + return old; +} + +static inline u8 cma_get_ip_ver(struct cma_hdr *hdr) +{ + return hdr->ip_version >> 4; +} + +static inline void cma_set_ip_ver(struct cma_hdr *hdr, u8 ip_ver) +{ + hdr->ip_version = (ip_ver << 4) | (hdr->ip_version & 0xF); +} + +static inline u8 sdp_get_majv(u8 sdp_version) +{ + return sdp_version >> 4; +} + +static inline u8 sdp_get_ip_ver(struct sdp_hh *hh) +{ + return hh->ip_version >> 4; +} + +static inline void sdp_set_ip_ver(struct sdp_hh *hh, u8 ip_ver) +{ + hh->ip_version = (ip_ver << 4) | (hh->ip_version & 0xF); +} + +static void cma_attach_to_dev(struct rdma_id_private *id_priv, + struct cma_device *cma_dev) +{ + atomic_inc(&cma_dev->refcount); + id_priv->cma_dev = cma_dev; + id_priv->id.device = cma_dev->device; + list_add_tail(&id_priv->list, &cma_dev->id_list); +} + +static inline void cma_deref_dev(struct cma_device *cma_dev) +{ + if (atomic_dec_and_test(&cma_dev->refcount)) + complete(&cma_dev->comp); +} + +static void cma_detach_from_dev(struct rdma_id_private *id_priv) +{ + list_del(&id_priv->list); + cma_deref_dev(id_priv->cma_dev); + id_priv->cma_dev = NULL; +} + +static int cma_acquire_ib_dev(struct rdma_id_private *id_priv) +{ + struct cma_device *cma_dev; + union ib_gid gid; + int ret = -ENODEV; + + ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid), + + mutex_lock(&lock); + list_for_each_entry(cma_dev, &dev_list, list) { + ret = ib_find_cached_gid(cma_dev->device, &gid, + &id_priv->id.port_num, NULL); + if (!ret) { + cma_attach_to_dev(id_priv, cma_dev); + break; + } + } + mutex_unlock(&lock); + return ret; +} + +static int cma_acquire_dev(struct rdma_id_private *id_priv) +{ + switch (id_priv->id.route.addr.dev_addr.dev_type) { + case IB_NODE_CA: + return cma_acquire_ib_dev(id_priv); + default: + return -ENODEV; + } +} + +static void cma_deref_id(struct rdma_id_private *id_priv) +{ + if (atomic_dec_and_test(&id_priv->refcount)) + complete(&id_priv->comp); +} + +static void cma_release_remove(struct rdma_id_private *id_priv) +{ + if (atomic_dec_and_test(&id_priv->dev_remove)) + wake_up(&id_priv->wait_remove); +} + +struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler, + void *context, enum rdma_port_space ps) +{ + struct rdma_id_private *id_priv; + + id_priv = kzalloc(sizeof *id_priv, GFP_KERNEL); + if (!id_priv) + return ERR_PTR(-ENOMEM); + + id_priv->state = CMA_IDLE; + id_priv->id.context = context; + id_priv->id.event_handler = event_handler; + id_priv->id.ps = ps; + spin_lock_init(&id_priv->lock); + init_completion(&id_priv->comp); + atomic_set(&id_priv->refcount, 1); + init_waitqueue_head(&id_priv->wait_remove); + atomic_set(&id_priv->dev_remove, 0); + INIT_LIST_HEAD(&id_priv->listen_list); + get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num); + + return &id_priv->id; +} +EXPORT_SYMBOL(rdma_create_id); + +static int cma_init_ib_qp(struct rdma_id_private *id_priv, struct ib_qp *qp) +{ + struct ib_qp_attr qp_attr; + struct rdma_dev_addr *dev_addr; + int ret; + + dev_addr = &id_priv->id.route.addr.dev_addr; + ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num, + ib_addr_get_pkey(dev_addr), + &qp_attr.pkey_index); + if (ret) + return ret; + + qp_attr.qp_state = IB_QPS_INIT; + qp_attr.qp_access_flags = IB_ACCESS_LOCAL_WRITE; + qp_attr.port_num = id_priv->id.port_num; + return ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_ACCESS_FLAGS | + IB_QP_PKEY_INDEX | IB_QP_PORT); +} + +int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd, + struct ib_qp_init_attr *qp_init_attr) +{ + struct rdma_id_private *id_priv; + struct ib_qp *qp; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (id->device != pd->device) + return -EINVAL; + + qp = ib_create_qp(pd, qp_init_attr); + if (IS_ERR(qp)) + return PTR_ERR(qp); + + switch (id->device->node_type) { + case IB_NODE_CA: + ret = cma_init_ib_qp(id_priv, qp); + break; + default: + ret = -ENOSYS; + break; + } + + if (ret) + goto err; + + id->qp = qp; + id_priv->qp_num = qp->qp_num; + id_priv->qp_type = qp->qp_type; + id_priv->srq = (qp->srq != NULL); + return 0; +err: + ib_destroy_qp(qp); + return ret; +} +EXPORT_SYMBOL(rdma_create_qp); + +void rdma_destroy_qp(struct rdma_cm_id *id) +{ + ib_destroy_qp(id->qp); +} +EXPORT_SYMBOL(rdma_destroy_qp); + +static int cma_modify_qp_rtr(struct rdma_cm_id *id) +{ + struct ib_qp_attr qp_attr; + int qp_attr_mask, ret; + + if (!id->qp) + return 0; + + /* Need to update QP attributes from default values. */ + qp_attr.qp_state = IB_QPS_INIT; + ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask); + if (ret) + return ret; + + ret = ib_modify_qp(id->qp, &qp_attr, qp_attr_mask); + if (ret) + return ret; + + qp_attr.qp_state = IB_QPS_RTR; + ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask); + if (ret) + return ret; + + return ib_modify_qp(id->qp, &qp_attr, qp_attr_mask); +} + +static int cma_modify_qp_rts(struct rdma_cm_id *id) +{ + struct ib_qp_attr qp_attr; + int qp_attr_mask, ret; + + if (!id->qp) + return 0; + + qp_attr.qp_state = IB_QPS_RTS; + ret = rdma_init_qp_attr(id, &qp_attr, &qp_attr_mask); + if (ret) + return ret; + + return ib_modify_qp(id->qp, &qp_attr, qp_attr_mask); +} + +static int cma_modify_qp_err(struct rdma_cm_id *id) +{ + struct ib_qp_attr qp_attr; + + if (!id->qp) + return 0; + + qp_attr.qp_state = IB_QPS_ERR; + return ib_modify_qp(id->qp, &qp_attr, IB_QP_STATE); +} + +int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr, + int *qp_attr_mask) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + switch (id_priv->id.device->node_type) { + case IB_NODE_CA: + ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, qp_attr, + qp_attr_mask); + if (qp_attr->qp_state == IB_QPS_RTR) + qp_attr->rq_psn = id_priv->seq_num; + break; + default: + ret = -ENOSYS; + break; + } + + return ret; +} +EXPORT_SYMBOL(rdma_init_qp_attr); + +static inline int cma_zero_addr(struct sockaddr *addr) +{ + struct in6_addr *ip6; + + if (addr->sa_family == AF_INET) + return ZERONET(((struct sockaddr_in *) addr)->sin_addr.s_addr); + else { + ip6 = &((struct sockaddr_in6 *) addr)->sin6_addr; + return (ip6->s6_addr32[0] | ip6->s6_addr32[1] | + ip6->s6_addr32[2] | ip6->s6_addr32[3]) == 0; + } +} + +static inline int cma_loopback_addr(struct sockaddr *addr) +{ + return LOOPBACK(((struct sockaddr_in *) addr)->sin_addr.s_addr); +} + +static inline int cma_any_addr(struct sockaddr *addr) +{ + return cma_zero_addr(addr) || cma_loopback_addr(addr); +} + +static inline int cma_any_port(struct sockaddr *addr) +{ + return !((struct sockaddr_in *) addr)->sin_port; +} + +static int cma_get_net_info(void *hdr, enum rdma_port_space ps, + u8 *ip_ver, __u16 *port, + union cma_ip_addr **src, union cma_ip_addr **dst) +{ + switch (ps) { + case RDMA_PS_SDP: + if (sdp_get_majv(((struct sdp_hh *) hdr)->sdp_version) != + SDP_MAJ_VERSION) + return -EINVAL; + + *ip_ver = sdp_get_ip_ver(hdr); + *port = ((struct sdp_hh *) hdr)->port; + *src = &((struct sdp_hh *) hdr)->src_addr; + *dst = &((struct sdp_hh *) hdr)->dst_addr; + break; + default: + if (((struct cma_hdr *) hdr)->cma_version != CMA_VERSION) + return -EINVAL; + + *ip_ver = cma_get_ip_ver(hdr); + *port = ((struct cma_hdr *) hdr)->port; + *src = &((struct cma_hdr *) hdr)->src_addr; + *dst = &((struct cma_hdr *) hdr)->dst_addr; + break; + } + + if (*ip_ver != 4 && *ip_ver != 6) + return -EINVAL; + return 0; +} + +static void cma_save_net_info(struct rdma_addr *addr, + struct rdma_addr *listen_addr, + u8 ip_ver, __u16 port, + union cma_ip_addr *src, union cma_ip_addr *dst) +{ + struct sockaddr_in *listen4, *ip4; + struct sockaddr_in6 *listen6, *ip6; + + switch (ip_ver) { + case 4: + listen4 = (struct sockaddr_in *) &listen_addr->src_addr; + ip4 = (struct sockaddr_in *) &addr->src_addr; + ip4->sin_family = listen4->sin_family; + ip4->sin_addr.s_addr = dst->ip4.addr; + ip4->sin_port = listen4->sin_port; + + ip4 = (struct sockaddr_in *) &addr->dst_addr; + ip4->sin_family = listen4->sin_family; + ip4->sin_addr.s_addr = src->ip4.addr; + ip4->sin_port = port; + break; + case 6: + listen6 = (struct sockaddr_in6 *) &listen_addr->src_addr; + ip6 = (struct sockaddr_in6 *) &addr->src_addr; + ip6->sin6_family = listen6->sin6_family; + ip6->sin6_addr = dst->ip6; + ip6->sin6_port = listen6->sin6_port; + + ip6 = (struct sockaddr_in6 *) &addr->dst_addr; + ip6->sin6_family = listen6->sin6_family; + ip6->sin6_addr = src->ip6; + ip6->sin6_port = port; + break; + default: + break; + } +} + +static inline int cma_user_data_offset(enum rdma_port_space ps) +{ + switch (ps) { + case RDMA_PS_SDP: + return 0; + default: + return sizeof(struct cma_hdr); + } +} + +static int cma_notify_user(struct rdma_id_private *id_priv, + enum rdma_cm_event_type type, int status, + void *data, u8 data_len) +{ + struct rdma_cm_event event; + + event.event = type; + event.status = status; + event.private_data = data; + event.private_data_len = data_len; + + return id_priv->id.event_handler(&id_priv->id, &event); +} + +static void cma_cancel_route(struct rdma_id_private *id_priv) +{ + switch (id_priv->id.device->node_type) { + case IB_NODE_CA: + if (id_priv->query) + ib_sa_cancel_query(id_priv->query_id, id_priv->query); + break; + default: + break; + } +} + +static inline int cma_internal_listen(struct rdma_id_private *id_priv) +{ + return (id_priv->state == CMA_LISTEN) && id_priv->cma_dev && + cma_any_addr(&id_priv->id.route.addr.src_addr); +} + +static void cma_destroy_listen(struct rdma_id_private *id_priv) +{ + cma_exch(id_priv, CMA_DESTROYING); + + if (id_priv->cma_dev) { + switch (id_priv->id.device->node_type) { + case IB_NODE_CA: + if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib)) + ib_destroy_cm_id(id_priv->cm_id.ib); + break; + default: + break; + } + cma_detach_from_dev(id_priv); + } + list_del(&id_priv->listen_list); + + cma_deref_id(id_priv); + wait_for_completion(&id_priv->comp); + + kfree(id_priv); +} + +static void cma_cancel_listens(struct rdma_id_private *id_priv) +{ + struct rdma_id_private *dev_id_priv; + + mutex_lock(&lock); + list_del(&id_priv->list); + + while (!list_empty(&id_priv->listen_list)) { + dev_id_priv = list_entry(id_priv->listen_list.next, + struct rdma_id_private, listen_list); + cma_destroy_listen(dev_id_priv); + } + mutex_unlock(&lock); +} + +static void cma_cancel_operation(struct rdma_id_private *id_priv, + enum cma_state state) +{ + switch (state) { + case CMA_ADDR_QUERY: + rdma_addr_cancel(&id_priv->id.route.addr.dev_addr); + break; + case CMA_ROUTE_QUERY: + cma_cancel_route(id_priv); + break; + case CMA_LISTEN: + if (cma_any_addr(&id_priv->id.route.addr.src_addr) && + !id_priv->cma_dev) + cma_cancel_listens(id_priv); + break; + default: + break; + } +} + +static void cma_release_port(struct rdma_id_private *id_priv) +{ + struct rdma_bind_list *bind_list = id_priv->bind_list; + + if (!bind_list) + return; + + mutex_lock(&lock); + hlist_del(&id_priv->node); + if (hlist_empty(&bind_list->owners)) { + idr_remove(bind_list->ps, bind_list->port); + kfree(bind_list); + } + mutex_unlock(&lock); +} + +void rdma_destroy_id(struct rdma_cm_id *id) +{ + struct rdma_id_private *id_priv; + enum cma_state state; + + id_priv = container_of(id, struct rdma_id_private, id); + state = cma_exch(id_priv, CMA_DESTROYING); + cma_cancel_operation(id_priv, state); + + if (id_priv->cma_dev) { + switch (id->device->node_type) { + case IB_NODE_CA: + if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib)) + ib_destroy_cm_id(id_priv->cm_id.ib); + break; + default: + break; + } + mutex_lock(&lock); + cma_detach_from_dev(id_priv); + mutex_unlock(&lock); + } + + cma_release_port(id_priv); + cma_deref_id(id_priv); + wait_for_completion(&id_priv->comp); + + kfree(id_priv->id.route.path_rec); + kfree(id_priv); +} +EXPORT_SYMBOL(rdma_destroy_id); + +static int cma_rep_recv(struct rdma_id_private *id_priv) +{ + int ret; + + ret = cma_modify_qp_rtr(&id_priv->id); + if (ret) + goto reject; + + ret = cma_modify_qp_rts(&id_priv->id); + if (ret) + goto reject; + + ret = ib_send_cm_rtu(id_priv->cm_id.ib, NULL, 0); + if (ret) + goto reject; + + return 0; +reject: + cma_modify_qp_err(&id_priv->id); + ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED, + NULL, 0, NULL, 0); + return ret; +} + +static int cma_verify_rep(struct rdma_id_private *id_priv, void *data) +{ + if (id_priv->id.ps == RDMA_PS_SDP && + sdp_get_majv(((struct sdp_hah *) data)->sdp_version) != + SDP_MAJ_VERSION) + return -EINVAL; + + return 0; +} + +static int cma_rtu_recv(struct rdma_id_private *id_priv) +{ + int ret; + + ret = cma_modify_qp_rts(&id_priv->id); + if (ret) + goto reject; + + return 0; +reject: + cma_modify_qp_err(&id_priv->id); + ib_send_cm_rej(id_priv->cm_id.ib, IB_CM_REJ_CONSUMER_DEFINED, + NULL, 0, NULL, 0); + return ret; +} + +static int cma_ib_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) +{ + struct rdma_id_private *id_priv = cm_id->context; + enum rdma_cm_event_type event; + u8 private_data_len = 0; + int ret = 0, status = 0; + + atomic_inc(&id_priv->dev_remove); + if (!cma_comp(id_priv, CMA_CONNECT)) + goto out; + + switch (ib_event->event) { + case IB_CM_REQ_ERROR: + case IB_CM_REP_ERROR: + event = RDMA_CM_EVENT_UNREACHABLE; + status = -ETIMEDOUT; + break; + case IB_CM_REP_RECEIVED: + status = cma_verify_rep(id_priv, ib_event->private_data); + if (status) + event = RDMA_CM_EVENT_CONNECT_ERROR; + else if (id_priv->id.qp && id_priv->id.ps != RDMA_PS_SDP) { + status = cma_rep_recv(id_priv); + event = status ? RDMA_CM_EVENT_CONNECT_ERROR : + RDMA_CM_EVENT_ESTABLISHED; + } else + event = RDMA_CM_EVENT_CONNECT_RESPONSE; + private_data_len = IB_CM_REP_PRIVATE_DATA_SIZE; + break; + case IB_CM_RTU_RECEIVED: + status = cma_rtu_recv(id_priv); + event = status ? RDMA_CM_EVENT_CONNECT_ERROR : + RDMA_CM_EVENT_ESTABLISHED; + break; + case IB_CM_DREQ_ERROR: + status = -ETIMEDOUT; /* fall through */ + case IB_CM_DREQ_RECEIVED: + case IB_CM_DREP_RECEIVED: + if (!cma_comp_exch(id_priv, CMA_CONNECT, CMA_DISCONNECT)) + goto out; + event = RDMA_CM_EVENT_DISCONNECTED; + break; + case IB_CM_TIMEWAIT_EXIT: + case IB_CM_MRA_RECEIVED: + /* ignore event */ + goto out; + case IB_CM_REJ_RECEIVED: + cma_modify_qp_err(&id_priv->id); + status = ib_event->param.rej_rcvd.reason; + event = RDMA_CM_EVENT_REJECTED; + private_data_len = IB_CM_REJ_PRIVATE_DATA_SIZE; + break; + default: + printk(KERN_ERR "RDMA CMA: unexpected IB CM event: %d", + ib_event->event); + goto out; + } + + ret = cma_notify_user(id_priv, event, status, ib_event->private_data, + private_data_len); + if (ret) { + /* Destroy the CM ID by returning a non-zero value. */ + id_priv->cm_id.ib = NULL; + cma_exch(id_priv, CMA_DESTROYING); + cma_release_remove(id_priv); + rdma_destroy_id(&id_priv->id); + return ret; + } +out: + cma_release_remove(id_priv); + return ret; +} + +static struct rdma_id_private *cma_new_id(struct rdma_cm_id *listen_id, + struct ib_cm_event *ib_event) +{ + struct rdma_id_private *id_priv; + struct rdma_cm_id *id; + struct rdma_route *rt; + union cma_ip_addr *src, *dst; + __u16 port; + u8 ip_ver; + + id = rdma_create_id(listen_id->event_handler, listen_id->context, + listen_id->ps); + if (IS_ERR(id)) + return NULL; + + rt = &id->route; + rt->num_paths = ib_event->param.req_rcvd.alternate_path ? 2 : 1; + rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths, GFP_KERNEL); + if (!rt->path_rec) + goto err; + + if (cma_get_net_info(ib_event->private_data, listen_id->ps, + &ip_ver, &port, &src, &dst)) + goto err; + + cma_save_net_info(&id->route.addr, &listen_id->route.addr, + ip_ver, port, src, dst); + rt->path_rec[0] = *ib_event->param.req_rcvd.primary_path; + if (rt->num_paths == 2) + rt->path_rec[1] = *ib_event->param.req_rcvd.alternate_path; + + ib_addr_set_sgid(&rt->addr.dev_addr, &rt->path_rec[0].sgid); + ib_addr_set_dgid(&rt->addr.dev_addr, &rt->path_rec[0].dgid); + ib_addr_set_pkey(&rt->addr.dev_addr, be16_to_cpu(rt->path_rec[0].pkey)); + rt->addr.dev_addr.dev_type = IB_NODE_CA; + + id_priv = container_of(id, struct rdma_id_private, id); + id_priv->state = CMA_CONNECT; + return id_priv; +err: + rdma_destroy_id(id); + return NULL; +} + +static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) +{ + struct rdma_id_private *listen_id, *conn_id; + int offset, ret; + + listen_id = cm_id->context; + atomic_inc(&listen_id->dev_remove); + if (!cma_comp(listen_id, CMA_LISTEN)) { + ret = -ECONNABORTED; + goto out; + } + + conn_id = cma_new_id(&listen_id->id, ib_event); + if (!conn_id) { + ret = -ENOMEM; + goto out; + } + + atomic_inc(&conn_id->dev_remove); + ret = cma_acquire_ib_dev(conn_id); + if (ret) { + ret = -ENODEV; + cma_release_remove(conn_id); + rdma_destroy_id(&conn_id->id); + goto out; + } + + conn_id->cm_id.ib = cm_id; + cm_id->context = conn_id; + cm_id->cm_handler = cma_ib_handler; + + offset = cma_user_data_offset(listen_id->id.ps); + ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0, + ib_event->private_data + offset, + IB_CM_REQ_PRIVATE_DATA_SIZE - offset); + if (ret) { + /* Destroy the CM ID by returning a non-zero value. */ + conn_id->cm_id.ib = NULL; + cma_exch(conn_id, CMA_DESTROYING); + cma_release_remove(conn_id); + rdma_destroy_id(&conn_id->id); + } +out: + cma_release_remove(listen_id); + return ret; +} + +static __be64 cma_get_service_id(enum rdma_port_space ps, struct sockaddr *addr) +{ + return cpu_to_be64(((u64)ps << 16) + + be16_to_cpu(((struct sockaddr_in *) addr)->sin_port)); +} + +static void cma_set_compare_data(enum rdma_port_space ps, struct sockaddr *addr, + struct ib_cm_compare_data *compare) +{ + struct cma_hdr *cma_data, *cma_mask; + struct sdp_hh *sdp_data, *sdp_mask; + __u32 ip4_addr; + struct in6_addr ip6_addr; + + memset(compare, 0, sizeof *compare); + cma_data = (void *) compare->data; + cma_mask = (void *) compare->mask; + sdp_data = (void *) compare->data; + sdp_mask = (void *) compare->mask; + + switch (addr->sa_family) { + case AF_INET: + ip4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; + if (ps == RDMA_PS_SDP) { + sdp_set_ip_ver(sdp_data, 4); + sdp_set_ip_ver(sdp_mask, 0xF); + sdp_data->dst_addr.ip4.addr = ip4_addr; + sdp_mask->dst_addr.ip4.addr = ~0; + } else { + cma_set_ip_ver(cma_data, 4); + cma_set_ip_ver(cma_mask, 0xF); + cma_data->dst_addr.ip4.addr = ip4_addr; + cma_mask->dst_addr.ip4.addr = ~0; + } + break; + case AF_INET6: + ip6_addr = ((struct sockaddr_in6 *) addr)->sin6_addr; + if (ps == RDMA_PS_SDP) { + sdp_set_ip_ver(sdp_data, 6); + sdp_set_ip_ver(sdp_mask, 0xF); + sdp_data->dst_addr.ip6 = ip6_addr; + memset(&sdp_mask->dst_addr.ip6, 0xFF, + sizeof sdp_mask->dst_addr.ip6); + } else { + cma_set_ip_ver(cma_data, 6); + cma_set_ip_ver(cma_mask, 0xF); + cma_data->dst_addr.ip6 = ip6_addr; + memset(&cma_mask->dst_addr.ip6, 0xFF, + sizeof cma_mask->dst_addr.ip6); + } + break; + default: + break; + } +} + +static int cma_ib_listen(struct rdma_id_private *id_priv) +{ + struct ib_cm_compare_data compare_data; + struct sockaddr *addr; + __be64 svc_id; + int ret; + + id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_req_handler, + id_priv); + if (IS_ERR(id_priv->cm_id.ib)) + return PTR_ERR(id_priv->cm_id.ib); + + addr = &id_priv->id.route.addr.src_addr; + svc_id = cma_get_service_id(id_priv->id.ps, addr); + if (cma_any_addr(addr)) + ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, NULL); + else { + cma_set_compare_data(id_priv->id.ps, addr, &compare_data); + ret = ib_cm_listen(id_priv->cm_id.ib, svc_id, 0, &compare_data); + } + + if (ret) { + ib_destroy_cm_id(id_priv->cm_id.ib); + id_priv->cm_id.ib = NULL; + } + + return ret; +} + +static int cma_listen_handler(struct rdma_cm_id *id, + struct rdma_cm_event *event) +{ + struct rdma_id_private *id_priv = id->context; + + id->context = id_priv->id.context; + id->event_handler = id_priv->id.event_handler; + return id_priv->id.event_handler(id, event); +} + +static void cma_listen_on_dev(struct rdma_id_private *id_priv, + struct cma_device *cma_dev) +{ + struct rdma_id_private *dev_id_priv; + struct rdma_cm_id *id; + int ret; + + id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps); + if (IS_ERR(id)) + return; + + dev_id_priv = container_of(id, struct rdma_id_private, id); + + dev_id_priv->state = CMA_ADDR_BOUND; + memcpy(&id->route.addr.src_addr, &id_priv->id.route.addr.src_addr, + ip_addr_size(&id_priv->id.route.addr.src_addr)); + + cma_attach_to_dev(dev_id_priv, cma_dev); + list_add_tail(&dev_id_priv->listen_list, &id_priv->listen_list); + + ret = rdma_listen(id, id_priv->backlog); + if (ret) + goto err; + + return; +err: + cma_destroy_listen(dev_id_priv); +} + +static void cma_listen_on_all(struct rdma_id_private *id_priv) +{ + struct cma_device *cma_dev; + + mutex_lock(&lock); + list_add_tail(&id_priv->list, &listen_any_list); + list_for_each_entry(cma_dev, &dev_list, list) + cma_listen_on_dev(id_priv, cma_dev); + mutex_unlock(&lock); +} + +static int cma_bind_any(struct rdma_cm_id *id, sa_family_t af) +{ + struct sockaddr_in addr_in; + + memset(&addr_in, 0, sizeof addr_in); + addr_in.sin_family = af; + return rdma_bind_addr(id, (struct sockaddr *) &addr_in); +} + +int rdma_listen(struct rdma_cm_id *id, int backlog) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (id_priv->state == CMA_IDLE) { + ret = cma_bind_any(id, AF_INET); + if (ret) + return ret; + } + + if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_LISTEN)) + return -EINVAL; + + id_priv->backlog = backlog; + if (id->device) { + switch (id->device->node_type) { + case IB_NODE_CA: + ret = cma_ib_listen(id_priv); + if (ret) + goto err; + break; + default: + ret = -ENOSYS; + goto err; + } + } else + cma_listen_on_all(id_priv); + + return 0; +err: + id_priv->backlog = 0; + cma_comp_exch(id_priv, CMA_LISTEN, CMA_ADDR_BOUND); + return ret; +} +EXPORT_SYMBOL(rdma_listen); + +static void cma_query_handler(int status, struct ib_sa_path_rec *path_rec, + void *context) +{ + struct cma_work *work = context; + struct rdma_route *route; + + route = &work->id->id.route; + + if (!status) { + route->num_paths = 1; + *route->path_rec = *path_rec; + } else { + work->old_state = CMA_ROUTE_QUERY; + work->new_state = CMA_ADDR_RESOLVED; + work->event.event = RDMA_CM_EVENT_ROUTE_ERROR; + } + + queue_work(cma_wq, &work->work); +} + +static int cma_query_ib_route(struct rdma_id_private *id_priv, int timeout_ms, + struct cma_work *work) +{ + struct rdma_dev_addr *addr = &id_priv->id.route.addr.dev_addr; + struct ib_sa_path_rec path_rec; + + memset(&path_rec, 0, sizeof path_rec); + ib_addr_get_sgid(addr, &path_rec.sgid); + ib_addr_get_dgid(addr, &path_rec.dgid); + path_rec.pkey = cpu_to_be16(ib_addr_get_pkey(addr)); + path_rec.numb_path = 1; + + id_priv->query_id = ib_sa_path_rec_get(id_priv->id.device, + id_priv->id.port_num, &path_rec, + IB_SA_PATH_REC_DGID | IB_SA_PATH_REC_SGID | + IB_SA_PATH_REC_PKEY | IB_SA_PATH_REC_NUMB_PATH, + timeout_ms, GFP_KERNEL, + cma_query_handler, work, &id_priv->query); + + return (id_priv->query_id < 0) ? id_priv->query_id : 0; +} + +static void cma_work_handler(void *data) +{ + struct cma_work *work = data; + struct rdma_id_private *id_priv = work->id; + int destroy = 0; + + atomic_inc(&id_priv->dev_remove); + if (!cma_comp_exch(id_priv, work->old_state, work->new_state)) + goto out; + + if (id_priv->id.event_handler(&id_priv->id, &work->event)) { + cma_exch(id_priv, CMA_DESTROYING); + destroy = 1; + } +out: + cma_release_remove(id_priv); + cma_deref_id(id_priv); + if (destroy) + rdma_destroy_id(&id_priv->id); + kfree(work); +} + +static int cma_resolve_ib_route(struct rdma_id_private *id_priv, int timeout_ms) +{ + struct rdma_route *route = &id_priv->id.route; + struct cma_work *work; + int ret; + + work = kzalloc(sizeof *work, GFP_KERNEL); + if (!work) + return -ENOMEM; + + work->id = id_priv; + INIT_WORK(&work->work, cma_work_handler, work); + work->old_state = CMA_ROUTE_QUERY; + work->new_state = CMA_ROUTE_RESOLVED; + work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED; + + route->path_rec = kmalloc(sizeof *route->path_rec, GFP_KERNEL); + if (!route->path_rec) { + ret = -ENOMEM; + goto err1; + } + + ret = cma_query_ib_route(id_priv, timeout_ms, work); + if (ret) + goto err2; + + return 0; +err2: + kfree(route->path_rec); + route->path_rec = NULL; +err1: + kfree(work); + return ret; +} + +int rdma_set_ib_paths(struct rdma_cm_id *id, + struct ib_sa_path_rec *path_rec, int num_paths) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ROUTE_RESOLVED)) + return -EINVAL; + + id->route.path_rec = kmalloc(sizeof *path_rec * num_paths, GFP_KERNEL); + if (!id->route.path_rec) { + ret = -ENOMEM; + goto err; + } + + memcpy(id->route.path_rec, path_rec, sizeof *path_rec * num_paths); + return 0; +err: + cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_ADDR_RESOLVED); + return ret; +} +EXPORT_SYMBOL(rdma_set_ib_paths); + +int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ROUTE_QUERY)) + return -EINVAL; + + atomic_inc(&id_priv->refcount); + switch (id->device->node_type) { + case IB_NODE_CA: + ret = cma_resolve_ib_route(id_priv, timeout_ms); + break; + default: + ret = -ENOSYS; + break; + } + if (ret) + goto err; + + return 0; +err: + cma_comp_exch(id_priv, CMA_ROUTE_QUERY, CMA_ADDR_RESOLVED); + cma_deref_id(id_priv); + return ret; +} +EXPORT_SYMBOL(rdma_resolve_route); + +static int cma_bind_loopback(struct rdma_id_private *id_priv) +{ + struct cma_device *cma_dev; + struct ib_port_attr port_attr; + union ib_gid gid; + u16 pkey; + int ret; + u8 p; + + mutex_lock(&lock); + list_for_each_entry(cma_dev, &dev_list, list) + for (p = 1; p <= cma_dev->device->phys_port_cnt; ++p) + if (!ib_query_port (cma_dev->device, p, &port_attr) && + port_attr.state == IB_PORT_ACTIVE) + goto port_found; + + if (!list_empty(&dev_list)) { + p = 1; + cma_dev = list_entry(dev_list.next, struct cma_device, list); + } else { + ret = -ENODEV; + goto out; + } + +port_found: + ret = ib_get_cached_gid(cma_dev->device, p, 0, &gid); + if (ret) + goto out; + + ret = ib_get_cached_pkey(cma_dev->device, p, 0, &pkey); + if (ret) + goto out; + + ib_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid); + ib_addr_set_pkey(&id_priv->id.route.addr.dev_addr, pkey); + id_priv->id.port_num = p; + cma_attach_to_dev(id_priv, cma_dev); +out: + mutex_unlock(&lock); + return ret; +} + +static void addr_handler(int status, struct sockaddr *src_addr, + struct rdma_dev_addr *dev_addr, void *context) +{ + struct rdma_id_private *id_priv = context; + enum rdma_cm_event_type event; + + atomic_inc(&id_priv->dev_remove); + if (!id_priv->cma_dev && !status) + status = cma_acquire_dev(id_priv); + + if (status) { + if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND)) + goto out; + event = RDMA_CM_EVENT_ADDR_ERROR; + } else { + if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED)) + goto out; + memcpy(&id_priv->id.route.addr.src_addr, src_addr, + ip_addr_size(src_addr)); + event = RDMA_CM_EVENT_ADDR_RESOLVED; + } + + if (cma_notify_user(id_priv, event, status, NULL, 0)) { + cma_exch(id_priv, CMA_DESTROYING); + cma_release_remove(id_priv); + cma_deref_id(id_priv); + rdma_destroy_id(&id_priv->id); + return; + } +out: + cma_release_remove(id_priv); + cma_deref_id(id_priv); +} + +static int cma_resolve_loopback(struct rdma_id_private *id_priv) +{ + struct cma_work *work; + struct sockaddr_in *src_in, *dst_in; + union ib_gid gid; + int ret; + + work = kzalloc(sizeof *work, GFP_KERNEL); + if (!work) + return -ENOMEM; + + if (!id_priv->cma_dev) { + ret = cma_bind_loopback(id_priv); + if (ret) + goto err; + } + + ib_addr_get_sgid(&id_priv->id.route.addr.dev_addr, &gid); + ib_addr_set_dgid(&id_priv->id.route.addr.dev_addr, &gid); + + if (cma_zero_addr(&id_priv->id.route.addr.src_addr)) { + src_in = (struct sockaddr_in *)&id_priv->id.route.addr.src_addr; + dst_in = (struct sockaddr_in *)&id_priv->id.route.addr.dst_addr; + src_in->sin_family = dst_in->sin_family; + src_in->sin_addr.s_addr = dst_in->sin_addr.s_addr; + } + + work->id = id_priv; + INIT_WORK(&work->work, cma_work_handler, work); + work->old_state = CMA_ADDR_QUERY; + work->new_state = CMA_ADDR_RESOLVED; + work->event.event = RDMA_CM_EVENT_ADDR_RESOLVED; + queue_work(cma_wq, &work->work); + return 0; +err: + kfree(work); + return ret; +} + +static int cma_bind_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, + struct sockaddr *dst_addr) +{ + if (src_addr && src_addr->sa_family) + return rdma_bind_addr(id, src_addr); + else + return cma_bind_any(id, dst_addr->sa_family); +} + +int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, + struct sockaddr *dst_addr, int timeout_ms) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (id_priv->state == CMA_IDLE) { + ret = cma_bind_addr(id, src_addr, dst_addr); + if (ret) + return ret; + } + + if (!cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_ADDR_QUERY)) + return -EINVAL; + + atomic_inc(&id_priv->refcount); + memcpy(&id->route.addr.dst_addr, dst_addr, ip_addr_size(dst_addr)); + if (cma_any_addr(dst_addr)) + ret = cma_resolve_loopback(id_priv); + else + ret = rdma_resolve_ip(&id->route.addr.src_addr, dst_addr, + &id->route.addr.dev_addr, + timeout_ms, addr_handler, id_priv); + if (ret) + goto err; + + return 0; +err: + cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_BOUND); + cma_deref_id(id_priv); + return ret; +} +EXPORT_SYMBOL(rdma_resolve_addr); + +static void cma_bind_port(struct rdma_bind_list *bind_list, + struct rdma_id_private *id_priv) +{ + struct sockaddr_in *sin; + + sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr; + sin->sin_port = htons(bind_list->port); + id_priv->bind_list = bind_list; + hlist_add_head(&id_priv->node, &bind_list->owners); +} + +static int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv, + unsigned short snum) +{ + struct rdma_bind_list *bind_list; + int port, start, ret; + + bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL); + if (!bind_list) + return -ENOMEM; + + start = snum ? snum : sysctl_local_port_range[0]; + + do { + ret = idr_get_new_above(ps, bind_list, start, &port); + } while ((ret == -EAGAIN) && idr_pre_get(ps, GFP_KERNEL)); + + if (ret) + goto err; + + if ((snum && port != snum) || + (!snum && port > sysctl_local_port_range[1])) { + idr_remove(ps, port); + ret = -EADDRNOTAVAIL; + goto err; + } + + bind_list->ps = ps; + bind_list->port = (unsigned short) port; + cma_bind_port(bind_list, id_priv); + return 0; +err: + kfree(bind_list); + return ret; +} + +static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv) +{ + struct rdma_id_private *cur_id; + struct sockaddr_in *sin, *cur_sin; + struct rdma_bind_list *bind_list; + struct hlist_node *node; + unsigned short snum; + + sin = (struct sockaddr_in *) &id_priv->id.route.addr.src_addr; + snum = ntohs(sin->sin_port); + if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) + return -EACCES; + + bind_list = idr_find(ps, snum); + if (!bind_list) + return cma_alloc_port(ps, id_priv, snum); + + /* + * We don't support binding to any address if anyone is bound to + * a specific address on the same port. + */ + if (cma_any_addr(&id_priv->id.route.addr.src_addr)) + return -EADDRNOTAVAIL; + + hlist_for_each_entry(cur_id, node, &bind_list->owners, node) { + if (cma_any_addr(&cur_id->id.route.addr.src_addr)) + return -EADDRNOTAVAIL; + + cur_sin = (struct sockaddr_in *) &cur_id->id.route.addr.src_addr; + if (sin->sin_addr.s_addr == cur_sin->sin_addr.s_addr) + return -EADDRINUSE; + } + + cma_bind_port(bind_list, id_priv); + return 0; +} + +static int cma_get_port(struct rdma_id_private *id_priv) +{ + struct idr *ps; + int ret; + + switch (id_priv->id.ps) { + case RDMA_PS_SDP: + ps = &sdp_ps; + break; + case RDMA_PS_TCP: + ps = &tcp_ps; + break; + default: + return -EPROTONOSUPPORT; + } + + mutex_lock(&lock); + if (cma_any_port(&id_priv->id.route.addr.src_addr)) + ret = cma_alloc_port(ps, id_priv, 0); + else + ret = cma_use_port(ps, id_priv); + mutex_unlock(&lock); + + return ret; +} + +int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) +{ + struct rdma_id_private *id_priv; + int ret; + + if (addr->sa_family != AF_INET) + return -EAFNOSUPPORT; + + id_priv = container_of(id, struct rdma_id_private, id); + if (!cma_comp_exch(id_priv, CMA_IDLE, CMA_ADDR_BOUND)) + return -EINVAL; + + if (!cma_any_addr(addr)) { + ret = rdma_translate_ip(addr, &id->route.addr.dev_addr); + if (!ret) + ret = cma_acquire_dev(id_priv); + if (ret) + goto err; + } + + memcpy(&id->route.addr.src_addr, addr, ip_addr_size(addr)); + ret = cma_get_port(id_priv); + if (ret) + goto err; + + return 0; +err: + cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_IDLE); + return ret; +} +EXPORT_SYMBOL(rdma_bind_addr); + +static int cma_format_hdr(void *hdr, enum rdma_port_space ps, + struct rdma_route *route) +{ + struct sockaddr_in *src4, *dst4; + struct cma_hdr *cma_hdr; + struct sdp_hh *sdp_hdr; + + src4 = (struct sockaddr_in *) &route->addr.src_addr; + dst4 = (struct sockaddr_in *) &route->addr.dst_addr; + + switch (ps) { + case RDMA_PS_SDP: + sdp_hdr = hdr; + if (sdp_get_majv(sdp_hdr->sdp_version) != SDP_MAJ_VERSION) + return -EINVAL; + sdp_set_ip_ver(sdp_hdr, 4); + sdp_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr; + sdp_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr; + sdp_hdr->port = src4->sin_port; + break; + default: + cma_hdr = hdr; + cma_hdr->cma_version = CMA_VERSION; + cma_set_ip_ver(cma_hdr, 4); + cma_hdr->src_addr.ip4.addr = src4->sin_addr.s_addr; + cma_hdr->dst_addr.ip4.addr = dst4->sin_addr.s_addr; + cma_hdr->port = src4->sin_port; + break; + } + return 0; +} + +static int cma_connect_ib(struct rdma_id_private *id_priv, + struct rdma_conn_param *conn_param) +{ + struct ib_cm_req_param req; + struct rdma_route *route; + void *private_data; + int offset, ret; + + memset(&req, 0, sizeof req); + offset = cma_user_data_offset(id_priv->id.ps); + req.private_data_len = offset + conn_param->private_data_len; + private_data = kzalloc(req.private_data_len, GFP_ATOMIC); + if (!private_data) + return -ENOMEM; + + if (conn_param->private_data && conn_param->private_data_len) + memcpy(private_data + offset, conn_param->private_data, + conn_param->private_data_len); + + id_priv->cm_id.ib = ib_create_cm_id(id_priv->id.device, cma_ib_handler, + id_priv); + if (IS_ERR(id_priv->cm_id.ib)) { + ret = PTR_ERR(id_priv->cm_id.ib); + goto out; + } + + route = &id_priv->id.route; + ret = cma_format_hdr(private_data, id_priv->id.ps, route); + if (ret) + goto out; + req.private_data = private_data; + + req.primary_path = &route->path_rec[0]; + if (route->num_paths == 2) + req.alternate_path = &route->path_rec[1]; + + req.service_id = cma_get_service_id(id_priv->id.ps, + &route->addr.dst_addr); + req.qp_num = id_priv->qp_num; + req.qp_type = id_priv->qp_type; + req.starting_psn = id_priv->seq_num; + req.responder_resources = conn_param->responder_resources; + req.initiator_depth = conn_param->initiator_depth; + req.flow_control = conn_param->flow_control; + req.retry_count = conn_param->retry_count; + req.rnr_retry_count = conn_param->rnr_retry_count; + req.remote_cm_response_timeout = CMA_CM_RESPONSE_TIMEOUT; + req.local_cm_response_timeout = CMA_CM_RESPONSE_TIMEOUT; + req.max_cm_retries = CMA_MAX_CM_RETRIES; + req.srq = id_priv->srq ? 1 : 0; + + ret = ib_send_cm_req(id_priv->cm_id.ib, &req); +out: + kfree(private_data); + return ret; +} + +int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (!cma_comp_exch(id_priv, CMA_ROUTE_RESOLVED, CMA_CONNECT)) + return -EINVAL; + + if (!id->qp) { + id_priv->qp_num = conn_param->qp_num; + id_priv->qp_type = conn_param->qp_type; + id_priv->srq = conn_param->srq; + } + + switch (id->device->node_type) { + case IB_NODE_CA: + ret = cma_connect_ib(id_priv, conn_param); + break; + default: + ret = -ENOSYS; + break; + } + if (ret) + goto err; + + return 0; +err: + cma_comp_exch(id_priv, CMA_CONNECT, CMA_ROUTE_RESOLVED); + return ret; +} +EXPORT_SYMBOL(rdma_connect); + +static int cma_accept_ib(struct rdma_id_private *id_priv, + struct rdma_conn_param *conn_param) +{ + struct ib_cm_rep_param rep; + int ret; + + ret = cma_modify_qp_rtr(&id_priv->id); + if (ret) + return ret; + + memset(&rep, 0, sizeof rep); + rep.qp_num = id_priv->qp_num; + rep.starting_psn = id_priv->seq_num; + rep.private_data = conn_param->private_data; + rep.private_data_len = conn_param->private_data_len; + rep.responder_resources = conn_param->responder_resources; + rep.initiator_depth = conn_param->initiator_depth; + rep.target_ack_delay = CMA_CM_RESPONSE_TIMEOUT; + rep.failover_accepted = 0; + rep.flow_control = conn_param->flow_control; + rep.rnr_retry_count = conn_param->rnr_retry_count; + rep.srq = id_priv->srq ? 1 : 0; + + return ib_send_cm_rep(id_priv->cm_id.ib, &rep); +} + +int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (!cma_comp(id_priv, CMA_CONNECT)) + return -EINVAL; + + if (!id->qp && conn_param) { + id_priv->qp_num = conn_param->qp_num; + id_priv->qp_type = conn_param->qp_type; + id_priv->srq = conn_param->srq; + } + + switch (id->device->node_type) { + case IB_NODE_CA: + if (conn_param) + ret = cma_accept_ib(id_priv, conn_param); + else + ret = cma_rep_recv(id_priv); + break; + default: + ret = -ENOSYS; + break; + } + + if (ret) + goto reject; + + return 0; +reject: + cma_modify_qp_err(id); + rdma_reject(id, NULL, 0); + return ret; +} +EXPORT_SYMBOL(rdma_accept); + +int rdma_reject(struct rdma_cm_id *id, const void *private_data, + u8 private_data_len) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (!cma_comp(id_priv, CMA_CONNECT)) + return -EINVAL; + + switch (id->device->node_type) { + case IB_NODE_CA: + ret = ib_send_cm_rej(id_priv->cm_id.ib, + IB_CM_REJ_CONSUMER_DEFINED, NULL, 0, + private_data, private_data_len); + break; + default: + ret = -ENOSYS; + break; + } + return ret; +} +EXPORT_SYMBOL(rdma_reject); + +int rdma_disconnect(struct rdma_cm_id *id) +{ + struct rdma_id_private *id_priv; + int ret; + + id_priv = container_of(id, struct rdma_id_private, id); + if (!cma_comp(id_priv, CMA_CONNECT) && + !cma_comp(id_priv, CMA_DISCONNECT)) + return -EINVAL; + + ret = cma_modify_qp_err(id); + if (ret) + goto out; + + switch (id->device->node_type) { + case IB_NODE_CA: + /* Initiate or respond to a disconnect. */ + if (ib_send_cm_dreq(id_priv->cm_id.ib, NULL, 0)) + ib_send_cm_drep(id_priv->cm_id.ib, NULL, 0); + break; + default: + break; + } +out: + return ret; +} +EXPORT_SYMBOL(rdma_disconnect); + +static void cma_add_one(struct ib_device *device) +{ + struct cma_device *cma_dev; + struct rdma_id_private *id_priv; + + cma_dev = kmalloc(sizeof *cma_dev, GFP_KERNEL); + if (!cma_dev) + return; + + cma_dev->device = device; + cma_dev->node_guid = device->node_guid; + if (!cma_dev->node_guid) + goto err; + + init_completion(&cma_dev->comp); + atomic_set(&cma_dev->refcount, 1); + INIT_LIST_HEAD(&cma_dev->id_list); + ib_set_client_data(device, &cma_client, cma_dev); + + mutex_lock(&lock); + list_add_tail(&cma_dev->list, &dev_list); + list_for_each_entry(id_priv, &listen_any_list, list) + cma_listen_on_dev(id_priv, cma_dev); + mutex_unlock(&lock); + return; +err: + kfree(cma_dev); +} + +static int cma_remove_id_dev(struct rdma_id_private *id_priv) +{ + enum cma_state state; + + /* Record that we want to remove the device */ + state = cma_exch(id_priv, CMA_DEVICE_REMOVAL); + if (state == CMA_DESTROYING) + return 0; + + cma_cancel_operation(id_priv, state); + wait_event(id_priv->wait_remove, !atomic_read(&id_priv->dev_remove)); + + /* Check for destruction from another callback. */ + if (!cma_comp(id_priv, CMA_DEVICE_REMOVAL)) + return 0; + + return cma_notify_user(id_priv, RDMA_CM_EVENT_DEVICE_REMOVAL, + 0, NULL, 0); +} + +static void cma_process_remove(struct cma_device *cma_dev) +{ + struct list_head remove_list; + struct rdma_id_private *id_priv; + int ret; + + INIT_LIST_HEAD(&remove_list); + + mutex_lock(&lock); + while (!list_empty(&cma_dev->id_list)) { + id_priv = list_entry(cma_dev->id_list.next, + struct rdma_id_private, list); + + if (cma_internal_listen(id_priv)) { + cma_destroy_listen(id_priv); + continue; + } + + list_del(&id_priv->list); + list_add_tail(&id_priv->list, &remove_list); + atomic_inc(&id_priv->refcount); + mutex_unlock(&lock); + + ret = cma_remove_id_dev(id_priv); + cma_deref_id(id_priv); + if (ret) + rdma_destroy_id(&id_priv->id); + + mutex_lock(&lock); + } + mutex_unlock(&lock); + + cma_deref_dev(cma_dev); + wait_for_completion(&cma_dev->comp); +} + +static void cma_remove_one(struct ib_device *device) +{ + struct cma_device *cma_dev; + + cma_dev = ib_get_client_data(device, &cma_client); + if (!cma_dev) + return; + + mutex_lock(&lock); + list_del(&cma_dev->list); + mutex_unlock(&lock); + + cma_process_remove(cma_dev); + kfree(cma_dev); +} + +static int cma_init(void) +{ + int ret; + + cma_wq = create_singlethread_workqueue("rdma_cm_wq"); + if (!cma_wq) + return -ENOMEM; + + ret = ib_register_client(&cma_client); + if (ret) + goto err; + return 0; + +err: + destroy_workqueue(cma_wq); + return ret; +} + +static void cma_cleanup(void) +{ + ib_unregister_client(&cma_client); + destroy_workqueue(cma_wq); + idr_destroy(&sdp_ps); + idr_destroy(&tcp_ps); +} + +module_init(cma_init); +module_exit(cma_cleanup); diff --git a/drivers/infiniband/core/uverbs_marshall.c b/drivers/infiniband/core/uverbs_marshall.c new file mode 100644 index 000000000..ce46b13ae --- /dev/null +++ b/drivers/infiniband/core/uverbs_marshall.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2005 Intel Corporation. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <rdma/ib_marshall.h> + +static void ib_copy_ah_attr_to_user(struct ib_uverbs_ah_attr *dst, + struct ib_ah_attr *src) +{ + memcpy(dst->grh.dgid, src->grh.dgid.raw, sizeof src->grh.dgid); + dst->grh.flow_label = src->grh.flow_label; + dst->grh.sgid_index = src->grh.sgid_index; + dst->grh.hop_limit = src->grh.hop_limit; + dst->grh.traffic_class = src->grh.traffic_class; + dst->dlid = src->dlid; + dst->sl = src->sl; + dst->src_path_bits = src->src_path_bits; + dst->static_rate = src->static_rate; + dst->is_global = src->ah_flags & IB_AH_GRH ? 1 : 0; + dst->port_num = src->port_num; +} + +void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst, + struct ib_qp_attr *src) +{ + dst->cur_qp_state = src->cur_qp_state; + dst->path_mtu = src->path_mtu; + dst->path_mig_state = src->path_mig_state; + dst->qkey = src->qkey; + dst->rq_psn = src->rq_psn; + dst->sq_psn = src->sq_psn; + dst->dest_qp_num = src->dest_qp_num; + dst->qp_access_flags = src->qp_access_flags; + + dst->max_send_wr = src->cap.max_send_wr; + dst->max_recv_wr = src->cap.max_recv_wr; + dst->max_send_sge = src->cap.max_send_sge; + dst->max_recv_sge = src->cap.max_recv_sge; + dst->max_inline_data = src->cap.max_inline_data; + + ib_copy_ah_attr_to_user(&dst->ah_attr, &src->ah_attr); + ib_copy_ah_attr_to_user(&dst->alt_ah_attr, &src->alt_ah_attr); + + dst->pkey_index = src->pkey_index; + dst->alt_pkey_index = src->alt_pkey_index; + dst->en_sqd_async_notify = src->en_sqd_async_notify; + dst->sq_draining = src->sq_draining; + dst->max_rd_atomic = src->max_rd_atomic; + dst->max_dest_rd_atomic = src->max_dest_rd_atomic; + dst->min_rnr_timer = src->min_rnr_timer; + dst->port_num = src->port_num; + dst->timeout = src->timeout; + dst->retry_cnt = src->retry_cnt; + dst->rnr_retry = src->rnr_retry; + dst->alt_port_num = src->alt_port_num; + dst->alt_timeout = src->alt_timeout; +} +EXPORT_SYMBOL(ib_copy_qp_attr_to_user); + +void ib_copy_path_rec_to_user(struct ib_user_path_rec *dst, + struct ib_sa_path_rec *src) +{ + memcpy(dst->dgid, src->dgid.raw, sizeof src->dgid); + memcpy(dst->sgid, src->sgid.raw, sizeof src->sgid); + + dst->dlid = src->dlid; + dst->slid = src->slid; + dst->raw_traffic = src->raw_traffic; + dst->flow_label = src->flow_label; + dst->hop_limit = src->hop_limit; + dst->traffic_class = src->traffic_class; + dst->reversible = src->reversible; + dst->numb_path = src->numb_path; + dst->pkey = src->pkey; + dst->sl = src->sl; + dst->mtu_selector = src->mtu_selector; + dst->mtu = src->mtu; + dst->rate_selector = src->rate_selector; + dst->rate = src->rate; + dst->packet_life_time = src->packet_life_time; + dst->preference = src->preference; + dst->packet_life_time_selector = src->packet_life_time_selector; +} +EXPORT_SYMBOL(ib_copy_path_rec_to_user); + +void ib_copy_path_rec_from_user(struct ib_sa_path_rec *dst, + struct ib_user_path_rec *src) +{ + memcpy(dst->dgid.raw, src->dgid, sizeof dst->dgid); + memcpy(dst->sgid.raw, src->sgid, sizeof dst->sgid); + + dst->dlid = src->dlid; + dst->slid = src->slid; + dst->raw_traffic = src->raw_traffic; + dst->flow_label = src->flow_label; + dst->hop_limit = src->hop_limit; + dst->traffic_class = src->traffic_class; + dst->reversible = src->reversible; + dst->numb_path = src->numb_path; + dst->pkey = src->pkey; + dst->sl = src->sl; + dst->mtu_selector = src->mtu_selector; + dst->mtu = src->mtu; + dst->rate_selector = src->rate_selector; + dst->rate = src->rate; + dst->packet_life_time = src->packet_life_time; + dst->preference = src->preference; + dst->packet_life_time_selector = src->packet_life_time_selector; +} +EXPORT_SYMBOL(ib_copy_path_rec_from_user); diff --git a/drivers/infiniband/ulp/iser/Kconfig b/drivers/infiniband/ulp/iser/Kconfig new file mode 100644 index 000000000..fead87d1e --- /dev/null +++ b/drivers/infiniband/ulp/iser/Kconfig @@ -0,0 +1,11 @@ +config INFINIBAND_ISER + tristate "ISCSI RDMA Protocol" + depends on INFINIBAND && SCSI + select SCSI_ISCSI_ATTRS + ---help--- + Support for the ISCSI RDMA Protocol over InfiniBand. This + allows you to access storage devices that speak ISER/ISCSI + over InfiniBand. + + The ISER protocol is defined by IETF. + See <http://www.ietf.org/>. diff --git a/drivers/infiniband/ulp/iser/Makefile b/drivers/infiniband/ulp/iser/Makefile new file mode 100644 index 000000000..fe6cd15f2 --- /dev/null +++ b/drivers/infiniband/ulp/iser/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_INFINIBAND_ISER) += ib_iser.o + +ib_iser-y := iser_verbs.o iser_initiator.o iser_memory.o \ + iscsi_iser.o diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c new file mode 100644 index 000000000..1437d7ee3 --- /dev/null +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -0,0 +1,667 @@ +/* + * iSCSI Initiator over iSER Data-Path + * + * Copyright (C) 2004 Dmitry Yusupov + * Copyright (C) 2004 Alex Aizman + * Copyright (C) 2005 Mike Christie + * Copyright (c) 2005, 2006 Voltaire, Inc. All rights reserved. + * maintained by openib-general@openib.org + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Credits: + * Christoph Hellwig + * FUJITA Tomonori + * Arne Redlich + * Zhenyu Wang + * Modified by: + * Erez Zilber + * + * + * $Id: iscsi_iser.c 6965 2006-05-07 11:36:20Z ogerlitz $ + */ + +#include <linux/types.h> +#include <linux/list.h> +#include <linux/hardirq.h> +#include <linux/kfifo.h> +#include <linux/blkdev.h> +#include <linux/init.h> +#include <linux/ioctl.h> +#include <linux/cdev.h> +#include <linux/in.h> +#include <linux/net.h> +#include <linux/scatterlist.h> +#include <linux/delay.h> + +#include <net/sock.h> + +#include <asm/uaccess.h> + +#include <scsi/scsi_cmnd.h> +#include <scsi/scsi_device.h> +#include <scsi/scsi_eh.h> +#include <scsi/scsi_tcq.h> +#include <scsi/scsi_host.h> +#include <scsi/scsi.h> +#include <scsi/scsi_transport_iscsi.h> + +#include "iscsi_iser.h" + +static unsigned int iscsi_max_lun = 512; +module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO); + +int iser_debug_level = 0; + +MODULE_DESCRIPTION("iSER (iSCSI Extensions for RDMA) Datamover " + "v" DRV_VER " (" DRV_DATE ")"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_AUTHOR("Alex Nezhinsky, Dan Bar Dov, Or Gerlitz"); + +module_param_named(debug_level, iser_debug_level, int, 0644); +MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0 (default:disabled)"); + +struct iser_global ig; + +void +iscsi_iser_recv(struct iscsi_conn *conn, + struct iscsi_hdr *hdr, char *rx_data, int rx_data_len) +{ + int rc = 0; + uint32_t ret_itt; + int datalen; + int ahslen; + + /* verify PDU length */ + datalen = ntoh24(hdr->dlength); + if (datalen != rx_data_len) { + printk(KERN_ERR "iscsi_iser: datalen %d (hdr) != %d (IB) \n", + datalen, rx_data_len); + rc = ISCSI_ERR_DATALEN; + goto error; + } + + /* read AHS */ + ahslen = hdr->hlength * 4; + + /* verify itt (itt encoding: age+cid+itt) */ + rc = iscsi_verify_itt(conn, hdr, &ret_itt); + + if (!rc) + rc = iscsi_complete_pdu(conn, hdr, rx_data, rx_data_len); + + if (rc && rc != ISCSI_ERR_NO_SCSI_CMD) + goto error; + + return; +error: + iscsi_conn_failure(conn, rc); +} + + +/** + * iscsi_iser_cmd_init - Initialize iSCSI SCSI_READ or SCSI_WRITE commands + * + **/ +static void +iscsi_iser_cmd_init(struct iscsi_cmd_task *ctask) +{ + struct iscsi_iser_conn *iser_conn = ctask->conn->dd_data; + struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data; + struct scsi_cmnd *sc = ctask->sc; + + iser_ctask->command_sent = 0; + iser_ctask->iser_conn = iser_conn; + + if (sc->sc_data_direction == DMA_TO_DEVICE) { + BUG_ON(ctask->total_length == 0); + /* bytes to be sent via RDMA operations */ + iser_ctask->rdma_data_count = ctask->total_length - + ctask->imm_count - + ctask->unsol_count; + + debug_scsi("cmd [itt %x total %d imm %d unsol_data %d " + "rdma_data %d]\n", + ctask->itt, ctask->total_length, ctask->imm_count, + ctask->unsol_count, iser_ctask->rdma_data_count); + } else + /* bytes to be sent via RDMA operations */ + iser_ctask->rdma_data_count = ctask->total_length; + + iser_ctask_rdma_init(iser_ctask); +} + +/** + * iscsi_mtask_xmit - xmit management(immediate) task + * @conn: iscsi connection + * @mtask: task management task + * + * Notes: + * The function can return -EAGAIN in which case caller must + * call it again later, or recover. '0' return code means successful + * xmit. + * + **/ +static int +iscsi_iser_mtask_xmit(struct iscsi_conn *conn, + struct iscsi_mgmt_task *mtask) +{ + int error = 0; + + debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id, mtask->itt); + + error = iser_send_control(conn, mtask); + + /* since iser xmits control with zero copy, mtasks can not be recycled + * right after sending them. + * The recycling scheme is based on whether a response is expected + * - if yes, the mtask is recycled at iscsi_complete_pdu + * - if no, the mtask is recycled at iser_snd_completion + */ + if (error && error != -EAGAIN) + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + + return error; +} + +static int +iscsi_iser_ctask_xmit_unsol_data(struct iscsi_conn *conn, + struct iscsi_cmd_task *ctask) +{ + struct iscsi_data hdr; + int error = 0; + struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data; + + /* Send data-out PDUs while there's still unsolicited data to send */ + while (ctask->unsol_count > 0) { + iscsi_prep_unsolicit_data_pdu(ctask, &hdr, + iser_ctask->rdma_data_count); + + debug_scsi("Sending data-out: itt 0x%x, data count %d\n", + hdr.itt, ctask->data_count); + + /* the buffer description has been passed with the command */ + /* Send the command */ + error = iser_send_data_out(conn, ctask, &hdr); + if (error) { + ctask->unsol_datasn--; + goto iscsi_iser_ctask_xmit_unsol_data_exit; + } + ctask->unsol_count -= ctask->data_count; + debug_scsi("Need to send %d more as data-out PDUs\n", + ctask->unsol_count); + } + +iscsi_iser_ctask_xmit_unsol_data_exit: + return error; +} + +static int +iscsi_iser_ctask_xmit(struct iscsi_conn *conn, + struct iscsi_cmd_task *ctask) +{ + struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data; + int error = 0; + + debug_scsi("ctask deq [cid %d itt 0x%x]\n", + conn->id, ctask->itt); + + /* + * serialize with TMF AbortTask + */ + if (ctask->mtask) + return error; + + /* Send the cmd PDU */ + if (!iser_ctask->command_sent) { + error = iser_send_command(conn, ctask); + if (error) + goto iscsi_iser_ctask_xmit_exit; + iser_ctask->command_sent = 1; + } + + /* Send unsolicited data-out PDU(s) if necessary */ + if (ctask->unsol_count) + error = iscsi_iser_ctask_xmit_unsol_data(conn, ctask); + + iscsi_iser_ctask_xmit_exit: + if (error && error != -EAGAIN) + iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); + return error; +} + +static void +iscsi_iser_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) +{ + struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data; + + if (iser_ctask->status == ISER_TASK_STATUS_STARTED) { + iser_ctask->status = ISER_TASK_STATUS_COMPLETED; + iser_ctask_rdma_finalize(iser_ctask); + } +} + +static struct iser_conn * +iscsi_iser_ib_conn_lookup(__u64 ep_handle) +{ + struct iser_conn *ib_conn; + struct iser_conn *uib_conn = (struct iser_conn *)(unsigned long)ep_handle; + + mutex_lock(&ig.connlist_mutex); + list_for_each_entry(ib_conn, &ig.connlist, conn_list) { + if (ib_conn == uib_conn) { + mutex_unlock(&ig.connlist_mutex); + return ib_conn; + } + } + mutex_unlock(&ig.connlist_mutex); + iser_err("no conn exists for eph %llx\n",(unsigned long long)ep_handle); + return NULL; +} + +static struct iscsi_cls_conn * +iscsi_iser_conn_create(struct iscsi_cls_session *cls_session, uint32_t conn_idx) +{ + struct iscsi_conn *conn; + struct iscsi_cls_conn *cls_conn; + struct iscsi_iser_conn *iser_conn; + + cls_conn = iscsi_conn_setup(cls_session, conn_idx); + if (!cls_conn) + return NULL; + conn = cls_conn->dd_data; + + /* + * due to issues with the login code re iser sematics + * this not set in iscsi_conn_setup - FIXME + */ + conn->max_recv_dlength = 128; + + iser_conn = kzalloc(sizeof(*iser_conn), GFP_KERNEL); + if (!iser_conn) + goto conn_alloc_fail; + + /* currently this is the only field which need to be initiated */ + rwlock_init(&iser_conn->lock); + + conn->dd_data = iser_conn; + iser_conn->iscsi_conn = conn; + + return cls_conn; + +conn_alloc_fail: + iscsi_conn_teardown(cls_conn); + return NULL; +} + +static void +iscsi_iser_conn_destroy(struct iscsi_cls_conn *cls_conn) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_iser_conn *iser_conn = conn->dd_data; + + iscsi_conn_teardown(cls_conn); + kfree(iser_conn); +} + +static int +iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session, + struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, + int is_leading) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_iser_conn *iser_conn; + struct iser_conn *ib_conn; + int error; + + error = iscsi_conn_bind(cls_session, cls_conn, is_leading); + if (error) + return error; + + /* the transport ep handle comes from user space so it must be + * verified against the global ib connections list */ + ib_conn = iscsi_iser_ib_conn_lookup(transport_eph); + if (!ib_conn) { + iser_err("can't bind eph %llx\n", + (unsigned long long)transport_eph); + return -EINVAL; + } + /* binds the iSER connection retrieved from the previously + * connected ep_handle to the iSCSI layer connection. exchanges + * connection pointers */ + iser_err("binding iscsi conn %p to iser_conn %p\n",conn,ib_conn); + iser_conn = conn->dd_data; + ib_conn->iser_conn = iser_conn; + iser_conn->ib_conn = ib_conn; + + conn->recv_lock = &iser_conn->lock; + + return 0; +} + +static int +iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + int err; + + err = iscsi_conn_start(cls_conn); + if (err) + return err; + + return iser_conn_set_full_featured_mode(conn); +} + +static struct iscsi_transport iscsi_iser_transport; + +static struct iscsi_cls_session * +iscsi_iser_session_create(struct iscsi_transport *iscsit, + struct scsi_transport_template *scsit, + uint32_t initial_cmdsn, uint32_t *hostno) +{ + struct iscsi_cls_session *cls_session; + struct iscsi_session *session; + int i; + uint32_t hn; + struct iscsi_cmd_task *ctask; + struct iscsi_mgmt_task *mtask; + struct iscsi_iser_cmd_task *iser_ctask; + struct iser_desc *desc; + + cls_session = iscsi_session_setup(iscsit, scsit, + sizeof(struct iscsi_iser_cmd_task), + sizeof(struct iser_desc), + initial_cmdsn, &hn); + if (!cls_session) + return NULL; + + *hostno = hn; + session = class_to_transport_session(cls_session); + + /* libiscsi setup itts, data and pool so just set desc fields */ + for (i = 0; i < session->cmds_max; i++) { + ctask = session->cmds[i]; + iser_ctask = ctask->dd_data; + ctask->hdr = (struct iscsi_cmd *)&iser_ctask->desc.iscsi_header; + } + + for (i = 0; i < session->mgmtpool_max; i++) { + mtask = session->mgmt_cmds[i]; + desc = mtask->dd_data; + mtask->hdr = &desc->iscsi_header; + desc->data = mtask->data; + } + + return cls_session; +} + +static int +iscsi_iser_set_param(struct iscsi_cls_conn *cls_conn, + enum iscsi_param param, char *buf, int buflen) +{ + int value; + + switch (param) { + case ISCSI_PARAM_MAX_RECV_DLENGTH: + /* TBD */ + break; + case ISCSI_PARAM_HDRDGST_EN: + sscanf(buf, "%d", &value); + if (value) { + printk(KERN_ERR "DataDigest wasn't negotiated to None"); + return -EPROTO; + } + break; + case ISCSI_PARAM_DATADGST_EN: + sscanf(buf, "%d", &value); + if (value) { + printk(KERN_ERR "DataDigest wasn't negotiated to None"); + return -EPROTO; + } + break; + case ISCSI_PARAM_IFMARKER_EN: + sscanf(buf, "%d", &value); + if (value) { + printk(KERN_ERR "IFMarker wasn't negotiated to No"); + return -EPROTO; + } + break; + case ISCSI_PARAM_OFMARKER_EN: + sscanf(buf, "%d", &value); + if (value) { + printk(KERN_ERR "OFMarker wasn't negotiated to No"); + return -EPROTO; + } + break; + default: + return iscsi_set_param(cls_conn, param, buf, buflen); + } + + return 0; +} + +static void +iscsi_iser_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) +{ + struct iscsi_conn *conn = cls_conn->dd_data; + + stats->txdata_octets = conn->txdata_octets; + stats->rxdata_octets = conn->rxdata_octets; + stats->scsicmd_pdus = conn->scsicmd_pdus_cnt; + stats->dataout_pdus = conn->dataout_pdus_cnt; + stats->scsirsp_pdus = conn->scsirsp_pdus_cnt; + stats->datain_pdus = conn->datain_pdus_cnt; /* always 0 */ + stats->r2t_pdus = conn->r2t_pdus_cnt; /* always 0 */ + stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt; + stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt; + stats->custom_length = 3; + strcpy(stats->custom[0].desc, "qp_tx_queue_full"); + stats->custom[0].value = 0; /* TB iser_conn->qp_tx_queue_full; */ + strcpy(stats->custom[1].desc, "fmr_map_not_avail"); + stats->custom[1].value = 0; /* TB iser_conn->fmr_map_not_avail */; + strcpy(stats->custom[2].desc, "eh_abort_cnt"); + stats->custom[2].value = conn->eh_abort_cnt; +} + +static int +iscsi_iser_ep_connect(struct sockaddr *dst_addr, int non_blocking, + __u64 *ep_handle) +{ + int err; + struct iser_conn *ib_conn; + + err = iser_conn_init(&ib_conn); + if (err) + goto out; + + err = iser_connect(ib_conn, NULL, (struct sockaddr_in *)dst_addr, non_blocking); + if (!err) + *ep_handle = (__u64)(unsigned long)ib_conn; + +out: + return err; +} + +static int +iscsi_iser_ep_poll(__u64 ep_handle, int timeout_ms) +{ + struct iser_conn *ib_conn = iscsi_iser_ib_conn_lookup(ep_handle); + int rc; + + if (!ib_conn) + return -EINVAL; + + rc = wait_event_interruptible_timeout(ib_conn->wait, + ib_conn->state == ISER_CONN_UP, + msecs_to_jiffies(timeout_ms)); + + /* if conn establishment failed, return error code to iscsi */ + if (!rc && + (ib_conn->state == ISER_CONN_TERMINATING || + ib_conn->state == ISER_CONN_DOWN)) + rc = -1; + + iser_err("ib conn %p rc = %d\n", ib_conn, rc); + + if (rc > 0) + return 1; /* success, this is the equivalent of POLLOUT */ + else if (!rc) + return 0; /* timeout */ + else + return rc; /* signal */ +} + +static void +iscsi_iser_ep_disconnect(__u64 ep_handle) +{ + struct iser_conn *ib_conn; + + ib_conn = iscsi_iser_ib_conn_lookup(ep_handle); + if (!ib_conn) + return; + + iser_err("ib conn %p state %d\n",ib_conn, ib_conn->state); + iser_conn_terminate(ib_conn); +} + +static struct scsi_host_template iscsi_iser_sht = { + .name = "iSCSI Initiator over iSER, v." DRV_VER, + .queuecommand = iscsi_queuecommand, + .can_queue = ISCSI_XMIT_CMDS_MAX - 1, + .sg_tablesize = ISCSI_ISER_SG_TABLESIZE, + .cmd_per_lun = ISCSI_MAX_CMD_PER_LUN, + .eh_abort_handler = iscsi_eh_abort, + .eh_host_reset_handler = iscsi_eh_host_reset, + .use_clustering = DISABLE_CLUSTERING, + .proc_name = "iscsi_iser", + .this_id = -1, +}; + +static struct iscsi_transport iscsi_iser_transport = { + .owner = THIS_MODULE, + .name = "iser", + .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T, + .param_mask = ISCSI_MAX_RECV_DLENGTH | + ISCSI_MAX_XMIT_DLENGTH | + ISCSI_HDRDGST_EN | + ISCSI_DATADGST_EN | + ISCSI_INITIAL_R2T_EN | + ISCSI_MAX_R2T | + ISCSI_IMM_DATA_EN | + ISCSI_FIRST_BURST | + ISCSI_MAX_BURST | + ISCSI_PDU_INORDER_EN | + ISCSI_DATASEQ_INORDER_EN | + ISCSI_EXP_STATSN | + ISCSI_PERSISTENT_PORT | + ISCSI_PERSISTENT_ADDRESS | + ISCSI_TARGET_NAME | + ISCSI_TPGT, + .host_template = &iscsi_iser_sht, + .conndata_size = sizeof(struct iscsi_conn), + .max_lun = ISCSI_ISER_MAX_LUN, + .max_cmd_len = ISCSI_ISER_MAX_CMD_LEN, + /* session management */ + .create_session = iscsi_iser_session_create, + .destroy_session = iscsi_session_teardown, + /* connection management */ + .create_conn = iscsi_iser_conn_create, + .bind_conn = iscsi_iser_conn_bind, + .destroy_conn = iscsi_iser_conn_destroy, + .set_param = iscsi_iser_set_param, + .get_conn_param = iscsi_conn_get_param, + .get_session_param = iscsi_session_get_param, + .start_conn = iscsi_iser_conn_start, + .stop_conn = iscsi_conn_stop, + /* IO */ + .send_pdu = iscsi_conn_send_pdu, + .get_stats = iscsi_iser_conn_get_stats, + .init_cmd_task = iscsi_iser_cmd_init, + .xmit_cmd_task = iscsi_iser_ctask_xmit, + .xmit_mgmt_task = iscsi_iser_mtask_xmit, + .cleanup_cmd_task = iscsi_iser_cleanup_ctask, + /* recovery */ + .session_recovery_timedout = iscsi_session_recovery_timedout, + + .ep_connect = iscsi_iser_ep_connect, + .ep_poll = iscsi_iser_ep_poll, + .ep_disconnect = iscsi_iser_ep_disconnect +}; + +static int __init iser_init(void) +{ + int err; + + iser_dbg("Starting iSER datamover...\n"); + + if (iscsi_max_lun < 1) { + printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun); + return -EINVAL; + } + + iscsi_iser_transport.max_lun = iscsi_max_lun; + + memset(&ig, 0, sizeof(struct iser_global)); + + ig.desc_cache = kmem_cache_create("iser_descriptors", + sizeof (struct iser_desc), + 0, SLAB_HWCACHE_ALIGN, + NULL, NULL); + if (ig.desc_cache == NULL) + return -ENOMEM; + + /* device init is called only after the first addr resolution */ + mutex_init(&ig.device_list_mutex); + INIT_LIST_HEAD(&ig.device_list); + mutex_init(&ig.connlist_mutex); + INIT_LIST_HEAD(&ig.connlist); + + if (!iscsi_register_transport(&iscsi_iser_transport)) { + iser_err("iscsi_register_transport failed\n"); + err = -EINVAL; + goto register_transport_failure; + } + + return 0; + +register_transport_failure: + kmem_cache_destroy(ig.desc_cache); + + return err; +} + +static void __exit iser_exit(void) +{ + iser_dbg("Removing iSER datamover...\n"); + iscsi_unregister_transport(&iscsi_iser_transport); + kmem_cache_destroy(ig.desc_cache); +} + +module_init(iser_init); +module_exit(iser_exit); diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h new file mode 100644 index 000000000..3350ba690 --- /dev/null +++ b/drivers/infiniband/ulp/iser/iscsi_iser.h @@ -0,0 +1,354 @@ +/* + * iSER transport for the Open iSCSI Initiator & iSER transport internals + * + * Copyright (C) 2004 Dmitry Yusupov + * Copyright (C) 2004 Alex Aizman + * Copyright (C) 2005 Mike Christie + * based on code maintained by open-iscsi@googlegroups.com + * + * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: iscsi_iser.h 7051 2006-05-10 12:29:11Z ogerlitz $ + */ +#ifndef __ISCSI_ISER_H__ +#define __ISCSI_ISER_H__ + +#include <linux/types.h> +#include <linux/net.h> +#include <scsi/libiscsi.h> +#include <scsi/scsi_transport_iscsi.h> + +#include <linux/wait.h> +#include <linux/sched.h> +#include <linux/list.h> +#include <linux/slab.h> +#include <linux/dma-mapping.h> +#include <linux/mutex.h> +#include <linux/mempool.h> +#include <linux/uio.h> + +#include <linux/socket.h> +#include <linux/in.h> +#include <linux/in6.h> + +#include <rdma/ib_verbs.h> +#include <rdma/ib_fmr_pool.h> +#include <rdma/rdma_cm.h> + +#define DRV_NAME "iser" +#define PFX DRV_NAME ": " +#define DRV_VER "0.1" +#define DRV_DATE "May 7th, 2006" + +#define iser_dbg(fmt, arg...) \ + do { \ + if (iser_debug_level > 0) \ + printk(KERN_DEBUG PFX "%s:" fmt,\ + __func__ , ## arg); \ + } while (0) + +#define iser_err(fmt, arg...) \ + do { \ + printk(KERN_ERR PFX "%s:" fmt, \ + __func__ , ## arg); \ + } while (0) + + /* support upto 512KB in one RDMA */ +#define ISCSI_ISER_SG_TABLESIZE (0x80000 >> PAGE_SHIFT) +#define ISCSI_ISER_MAX_LUN 256 +#define ISCSI_ISER_MAX_CMD_LEN 16 + +/* QP settings */ +/* Maximal bounds on received asynchronous PDUs */ +#define ISER_MAX_RX_MISC_PDUS 4 /* NOOP_IN(2) , ASYNC_EVENT(2) */ + +#define ISER_MAX_TX_MISC_PDUS 6 /* NOOP_OUT(2), TEXT(1), * + * SCSI_TMFUNC(2), LOGOUT(1) */ + +#define ISER_QP_MAX_RECV_DTOS (ISCSI_XMIT_CMDS_MAX + \ + ISER_MAX_RX_MISC_PDUS + \ + ISER_MAX_TX_MISC_PDUS) + +/* the max TX (send) WR supported by the iSER QP is defined by * + * max_send_wr = T * (1 + D) + C ; D is how many inflight dataouts we expect * + * to have at max for SCSI command. The tx posting & completion handling code * + * supports -EAGAIN scheme where tx is suspended till the QP has room for more * + * send WR. D=8 comes from 64K/8K */ + +#define ISER_INFLIGHT_DATAOUTS 8 + +#define ISER_QP_MAX_REQ_DTOS (ISCSI_XMIT_CMDS_MAX * \ + (1 + ISER_INFLIGHT_DATAOUTS) + \ + ISER_MAX_TX_MISC_PDUS + \ + ISER_MAX_RX_MISC_PDUS) + +#define ISER_VER 0x10 +#define ISER_WSV 0x08 +#define ISER_RSV 0x04 + +struct iser_hdr { + u8 flags; + u8 rsvd[3]; + __be32 write_stag; /* write rkey */ + __be64 write_va; + __be32 read_stag; /* read rkey */ + __be64 read_va; +} __attribute__((packed)); + + +/* Length of an object name string */ +#define ISER_OBJECT_NAME_SIZE 64 + +enum iser_ib_conn_state { + ISER_CONN_INIT, /* descriptor allocd, no conn */ + ISER_CONN_PENDING, /* in the process of being established */ + ISER_CONN_UP, /* up and running */ + ISER_CONN_TERMINATING, /* in the process of being terminated */ + ISER_CONN_DOWN, /* shut down */ + ISER_CONN_STATES_NUM +}; + +enum iser_task_status { + ISER_TASK_STATUS_INIT = 0, + ISER_TASK_STATUS_STARTED, + ISER_TASK_STATUS_COMPLETED +}; + +enum iser_data_dir { + ISER_DIR_IN = 0, /* to initiator */ + ISER_DIR_OUT, /* from initiator */ + ISER_DIRS_NUM +}; + +struct iser_data_buf { + void *buf; /* pointer to the sg list */ + unsigned int size; /* num entries of this sg */ + unsigned long data_len; /* total data len */ + unsigned int dma_nents; /* returned by dma_map_sg */ + char *copy_buf; /* allocated copy buf for SGs unaligned * + * for rdma which are copied */ + struct scatterlist sg_single; /* SG-ified clone of a non SG SC or * + * unaligned SG */ + }; + +/* fwd declarations */ +struct iser_device; +struct iscsi_iser_conn; +struct iscsi_iser_cmd_task; + +struct iser_mem_reg { + u32 lkey; + u32 rkey; + u64 va; + u64 len; + void *mem_h; +}; + +struct iser_regd_buf { + struct iser_mem_reg reg; /* memory registration info */ + void *virt_addr; + struct iser_device *device; /* device->device for dma_unmap */ + dma_addr_t dma_addr; /* if non zero, addr for dma_unmap */ + enum dma_data_direction direction; /* direction for dma_unmap */ + unsigned int data_size; + atomic_t ref_count; /* refcount, freed when dec to 0 */ +}; + +#define MAX_REGD_BUF_VECTOR_LEN 2 + +struct iser_dto { + struct iscsi_iser_cmd_task *ctask; + struct iscsi_iser_conn *conn; + int notify_enable; + + /* vector of registered buffers */ + unsigned int regd_vector_len; + struct iser_regd_buf *regd[MAX_REGD_BUF_VECTOR_LEN]; + + /* offset into the registered buffer may be specified */ + unsigned int offset[MAX_REGD_BUF_VECTOR_LEN]; + + /* a smaller size may be specified, if 0, then full size is used */ + unsigned int used_sz[MAX_REGD_BUF_VECTOR_LEN]; +}; + +enum iser_desc_type { + ISCSI_RX, + ISCSI_TX_CONTROL , + ISCSI_TX_SCSI_COMMAND, + ISCSI_TX_DATAOUT +}; + +struct iser_desc { + struct iser_hdr iser_header; + struct iscsi_hdr iscsi_header; + struct iser_regd_buf hdr_regd_buf; + void *data; /* used by RX & TX_CONTROL */ + struct iser_regd_buf data_regd_buf; /* used by RX & TX_CONTROL */ + enum iser_desc_type type; + struct iser_dto dto; +}; + +struct iser_device { + struct ib_device *ib_device; + struct ib_pd *pd; + struct ib_cq *cq; + struct ib_mr *mr; + struct tasklet_struct cq_tasklet; + struct list_head ig_list; /* entry in ig devices list */ + int refcount; +}; + +struct iser_conn { + struct iscsi_iser_conn *iser_conn; /* iser conn for upcalls */ + enum iser_ib_conn_state state; /* rdma connection state */ + spinlock_t lock; /* used for state changes */ + struct iser_device *device; /* device context */ + struct rdma_cm_id *cma_id; /* CMA ID */ + struct ib_qp *qp; /* QP */ + struct ib_fmr_pool *fmr_pool; /* pool of IB FMRs */ + int disc_evt_flag; /* disconn event delivered */ + wait_queue_head_t wait; /* waitq for conn/disconn */ + atomic_t post_recv_buf_count; /* posted rx count */ + atomic_t post_send_buf_count; /* posted tx count */ + struct work_struct comperror_work; /* conn term sleepable ctx*/ + char name[ISER_OBJECT_NAME_SIZE]; + struct iser_page_vec *page_vec; /* represents SG to fmr maps* + * maps serialized as tx is*/ + struct list_head conn_list; /* entry in ig conn list */ +}; + +struct iscsi_iser_conn { + struct iscsi_conn *iscsi_conn;/* ptr to iscsi conn */ + struct iser_conn *ib_conn; /* iSER IB conn */ + + rwlock_t lock; +}; + +struct iscsi_iser_cmd_task { + struct iser_desc desc; + struct iscsi_iser_conn *iser_conn; + int rdma_data_count;/* RDMA bytes */ + enum iser_task_status status; + int command_sent; /* set if command sent */ + int dir[ISER_DIRS_NUM]; /* set if dir use*/ + struct iser_regd_buf rdma_regd[ISER_DIRS_NUM];/* regd rdma buf */ + struct iser_data_buf data[ISER_DIRS_NUM]; /* orig. data des*/ + struct iser_data_buf data_copy[ISER_DIRS_NUM];/* contig. copy */ +}; + +struct iser_page_vec { + u64 *pages; + int length; + int offset; + int data_size; +}; + +struct iser_global { + struct mutex device_list_mutex;/* */ + struct list_head device_list; /* all iSER devices */ + struct mutex connlist_mutex; + struct list_head connlist; /* all iSER IB connections */ + + kmem_cache_t *desc_cache; +}; + +extern struct iser_global ig; +extern int iser_debug_level; + +/* allocate connection resources needed for rdma functionality */ +int iser_conn_set_full_featured_mode(struct iscsi_conn *conn); + +int iser_send_control(struct iscsi_conn *conn, + struct iscsi_mgmt_task *mtask); + +int iser_send_command(struct iscsi_conn *conn, + struct iscsi_cmd_task *ctask); + +int iser_send_data_out(struct iscsi_conn *conn, + struct iscsi_cmd_task *ctask, + struct iscsi_data *hdr); + +void iscsi_iser_recv(struct iscsi_conn *conn, + struct iscsi_hdr *hdr, + char *rx_data, + int rx_data_len); + +int iser_conn_init(struct iser_conn **ib_conn); + +void iser_conn_terminate(struct iser_conn *ib_conn); + +void iser_conn_release(struct iser_conn *ib_conn); + +void iser_rcv_completion(struct iser_desc *desc, + unsigned long dto_xfer_len); + +void iser_snd_completion(struct iser_desc *desc); + +void iser_ctask_rdma_init(struct iscsi_iser_cmd_task *ctask); + +void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *ctask); + +void iser_dto_buffs_release(struct iser_dto *dto); + +int iser_regd_buff_release(struct iser_regd_buf *regd_buf); + +void iser_reg_single(struct iser_device *device, + struct iser_regd_buf *regd_buf, + enum dma_data_direction direction); + +int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *ctask, + enum iser_data_dir cmd_dir); + +void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *ctask, + enum iser_data_dir cmd_dir); + +int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *ctask, + enum iser_data_dir cmd_dir); + +int iser_connect(struct iser_conn *ib_conn, + struct sockaddr_in *src_addr, + struct sockaddr_in *dst_addr, + int non_blocking); + +int iser_reg_page_vec(struct iser_conn *ib_conn, + struct iser_page_vec *page_vec, + struct iser_mem_reg *mem_reg); + +void iser_unreg_mem(struct iser_mem_reg *mem_reg); + +int iser_post_recv(struct iser_desc *rx_desc); +int iser_post_send(struct iser_desc *tx_desc); + +int iser_conn_state_comp(struct iser_conn *ib_conn, + enum iser_ib_conn_state comp); +#endif diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c new file mode 100644 index 000000000..ccf56f6f7 --- /dev/null +++ b/drivers/infiniband/ulp/iser/iser_initiator.c @@ -0,0 +1,738 @@ +/* + * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: iser_initiator.c 6964 2006-05-07 11:11:43Z ogerlitz $ + */ +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/mm.h> +#include <asm/io.h> +#include <asm/scatterlist.h> +#include <linux/scatterlist.h> +#include <linux/kfifo.h> +#include <scsi/scsi_cmnd.h> +#include <scsi/scsi_host.h> + +#include "iscsi_iser.h" + +/* Constant PDU lengths calculations */ +#define ISER_TOTAL_HEADERS_LEN (sizeof (struct iser_hdr) + \ + sizeof (struct iscsi_hdr)) + +/* iser_dto_add_regd_buff - increments the reference count for * + * the registered buffer & adds it to the DTO object */ +static void iser_dto_add_regd_buff(struct iser_dto *dto, + struct iser_regd_buf *regd_buf, + unsigned long use_offset, + unsigned long use_size) +{ + int add_idx; + + atomic_inc(®d_buf->ref_count); + + add_idx = dto->regd_vector_len; + dto->regd[add_idx] = regd_buf; + dto->used_sz[add_idx] = use_size; + dto->offset[add_idx] = use_offset; + + dto->regd_vector_len++; +} + +static int iser_dma_map_task_data(struct iscsi_iser_cmd_task *iser_ctask, + struct iser_data_buf *data, + enum iser_data_dir iser_dir, + enum dma_data_direction dma_dir) +{ + struct device *dma_device; + + iser_ctask->dir[iser_dir] = 1; + dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device; + + data->dma_nents = dma_map_sg(dma_device, data->buf, data->size, dma_dir); + if (data->dma_nents == 0) { + iser_err("dma_map_sg failed!!!\n"); + return -EINVAL; + } + return 0; +} + +static void iser_dma_unmap_task_data(struct iscsi_iser_cmd_task *iser_ctask) +{ + struct device *dma_device; + struct iser_data_buf *data; + + dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device; + + if (iser_ctask->dir[ISER_DIR_IN]) { + data = &iser_ctask->data[ISER_DIR_IN]; + dma_unmap_sg(dma_device, data->buf, data->size, DMA_FROM_DEVICE); + } + + if (iser_ctask->dir[ISER_DIR_OUT]) { + data = &iser_ctask->data[ISER_DIR_OUT]; + dma_unmap_sg(dma_device, data->buf, data->size, DMA_TO_DEVICE); + } +} + +/* Register user buffer memory and initialize passive rdma + * dto descriptor. Total data size is stored in + * iser_ctask->data[ISER_DIR_IN].data_len + */ +static int iser_prepare_read_cmd(struct iscsi_cmd_task *ctask, + unsigned int edtl) + +{ + struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data; + struct iser_regd_buf *regd_buf; + int err; + struct iser_hdr *hdr = &iser_ctask->desc.iser_header; + struct iser_data_buf *buf_in = &iser_ctask->data[ISER_DIR_IN]; + + err = iser_dma_map_task_data(iser_ctask, + buf_in, + ISER_DIR_IN, + DMA_FROM_DEVICE); + if (err) + return err; + + if (edtl > iser_ctask->data[ISER_DIR_IN].data_len) { + iser_err("Total data length: %ld, less than EDTL: " + "%d, in READ cmd BHS itt: %d, conn: 0x%p\n", + iser_ctask->data[ISER_DIR_IN].data_len, edtl, + ctask->itt, iser_ctask->iser_conn); + return -EINVAL; + } + + err = iser_reg_rdma_mem(iser_ctask,ISER_DIR_IN); + if (err) { + iser_err("Failed to set up Data-IN RDMA\n"); + return err; + } + regd_buf = &iser_ctask->rdma_regd[ISER_DIR_IN]; + + hdr->flags |= ISER_RSV; + hdr->read_stag = cpu_to_be32(regd_buf->reg.rkey); + hdr->read_va = cpu_to_be64(regd_buf->reg.va); + + iser_dbg("Cmd itt:%d READ tags RKEY:%#.4X VA:%#llX\n", + ctask->itt, regd_buf->reg.rkey, + (unsigned long long)regd_buf->reg.va); + + return 0; +} + +/* Register user buffer memory and initialize passive rdma + * dto descriptor. Total data size is stored in + * ctask->data[ISER_DIR_OUT].data_len + */ +static int +iser_prepare_write_cmd(struct iscsi_cmd_task *ctask, + unsigned int imm_sz, + unsigned int unsol_sz, + unsigned int edtl) +{ + struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data; + struct iser_regd_buf *regd_buf; + int err; + struct iser_dto *send_dto = &iser_ctask->desc.dto; + struct iser_hdr *hdr = &iser_ctask->desc.iser_header; + struct iser_data_buf *buf_out = &iser_ctask->data[ISER_DIR_OUT]; + + err = iser_dma_map_task_data(iser_ctask, + buf_out, + ISER_DIR_OUT, + DMA_TO_DEVICE); + if (err) + return err; + + if (edtl > iser_ctask->data[ISER_DIR_OUT].data_len) { + iser_err("Total data length: %ld, less than EDTL: %d, " + "in WRITE cmd BHS itt: %d, conn: 0x%p\n", + iser_ctask->data[ISER_DIR_OUT].data_len, + edtl, ctask->itt, ctask->conn); + return -EINVAL; + } + + err = iser_reg_rdma_mem(iser_ctask,ISER_DIR_OUT); + if (err != 0) { + iser_err("Failed to register write cmd RDMA mem\n"); + return err; + } + + regd_buf = &iser_ctask->rdma_regd[ISER_DIR_OUT]; + + if (unsol_sz < edtl) { + hdr->flags |= ISER_WSV; + hdr->write_stag = cpu_to_be32(regd_buf->reg.rkey); + hdr->write_va = cpu_to_be64(regd_buf->reg.va + unsol_sz); + + iser_dbg("Cmd itt:%d, WRITE tags, RKEY:%#.4X " + "VA:%#llX + unsol:%d\n", + ctask->itt, regd_buf->reg.rkey, + (unsigned long long)regd_buf->reg.va, unsol_sz); + } + + if (imm_sz > 0) { + iser_dbg("Cmd itt:%d, WRITE, adding imm.data sz: %d\n", + ctask->itt, imm_sz); + iser_dto_add_regd_buff(send_dto, + regd_buf, + 0, + imm_sz); + } + + return 0; +} + +/** + * iser_post_receive_control - allocates, initializes and posts receive DTO. + */ +static int iser_post_receive_control(struct iscsi_conn *conn) +{ + struct iscsi_iser_conn *iser_conn = conn->dd_data; + struct iser_desc *rx_desc; + struct iser_regd_buf *regd_hdr; + struct iser_regd_buf *regd_data; + struct iser_dto *recv_dto = NULL; + struct iser_device *device = iser_conn->ib_conn->device; + int rx_data_size, err = 0; + + rx_desc = kmem_cache_alloc(ig.desc_cache, GFP_NOIO); + if (rx_desc == NULL) { + iser_err("Failed to alloc desc for post recv\n"); + return -ENOMEM; + } + rx_desc->type = ISCSI_RX; + + /* for the login sequence we must support rx of upto 8K; login is done + * after conn create/bind (connect) and conn stop/bind (reconnect), + * what's common for both schemes is that the connection is not started + */ + if (conn->c_stage != ISCSI_CONN_STARTED) + rx_data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; + else /* FIXME till user space sets conn->max_recv_dlength correctly */ + rx_data_size = 128; + + rx_desc->data = kmalloc(rx_data_size, GFP_NOIO); + if (rx_desc->data == NULL) { + iser_err("Failed to alloc data buf for post recv\n"); + err = -ENOMEM; + goto post_rx_kmalloc_failure; + } + + recv_dto = &rx_desc->dto; + recv_dto->conn = iser_conn; + recv_dto->regd_vector_len = 0; + + regd_hdr = &rx_desc->hdr_regd_buf; + memset(regd_hdr, 0, sizeof(struct iser_regd_buf)); + regd_hdr->device = device; + regd_hdr->virt_addr = rx_desc; /* == &rx_desc->iser_header */ + regd_hdr->data_size = ISER_TOTAL_HEADERS_LEN; + + iser_reg_single(device, regd_hdr, DMA_FROM_DEVICE); + + iser_dto_add_regd_buff(recv_dto, regd_hdr, 0, 0); + + regd_data = &rx_desc->data_regd_buf; + memset(regd_data, 0, sizeof(struct iser_regd_buf)); + regd_data->device = device; + regd_data->virt_addr = rx_desc->data; + regd_data->data_size = rx_data_size; + + iser_reg_single(device, regd_data, DMA_FROM_DEVICE); + + iser_dto_add_regd_buff(recv_dto, regd_data, 0, 0); + + err = iser_post_recv(rx_desc); + if (!err) + return 0; + + /* iser_post_recv failed */ + iser_dto_buffs_release(recv_dto); + kfree(rx_desc->data); +post_rx_kmalloc_failure: + kmem_cache_free(ig.desc_cache, rx_desc); + return err; +} + +/* creates a new tx descriptor and adds header regd buffer */ +static void iser_create_send_desc(struct iscsi_iser_conn *iser_conn, + struct iser_desc *tx_desc) +{ + struct iser_regd_buf *regd_hdr = &tx_desc->hdr_regd_buf; + struct iser_dto *send_dto = &tx_desc->dto; + + memset(regd_hdr, 0, sizeof(struct iser_regd_buf)); + regd_hdr->device = iser_conn->ib_conn->device; + regd_hdr->virt_addr = tx_desc; /* == &tx_desc->iser_header */ + regd_hdr->data_size = ISER_TOTAL_HEADERS_LEN; + + send_dto->conn = iser_conn; + send_dto->notify_enable = 1; + send_dto->regd_vector_len = 0; + + memset(&tx_desc->iser_header, 0, sizeof(struct iser_hdr)); + tx_desc->iser_header.flags = ISER_VER; + + iser_dto_add_regd_buff(send_dto, regd_hdr, 0, 0); +} + +/** + * iser_conn_set_full_featured_mode - (iSER API) + */ +int iser_conn_set_full_featured_mode(struct iscsi_conn *conn) +{ + struct iscsi_iser_conn *iser_conn = conn->dd_data; + + int i; + /* no need to keep it in a var, we are after login so if this should + * be negotiated, by now the result should be available here */ + int initial_post_recv_bufs_num = ISER_MAX_RX_MISC_PDUS; + + iser_dbg("Initially post: %d\n", initial_post_recv_bufs_num); + + /* Check that there is no posted recv or send buffers left - */ + /* they must be consumed during the login phase */ + BUG_ON(atomic_read(&iser_conn->ib_conn->post_recv_buf_count) != 0); + BUG_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0); + + /* Initial post receive buffers */ + for (i = 0; i < initial_post_recv_bufs_num; i++) { + if (iser_post_receive_control(conn) != 0) { + iser_err("Failed to post recv bufs at:%d conn:0x%p\n", + i, conn); + return -ENOMEM; + } + } + iser_dbg("Posted %d post recv bufs, conn:0x%p\n", i, conn); + return 0; +} + +static int +iser_check_xmit(struct iscsi_conn *conn, void *task) +{ + int rc = 0; + struct iscsi_iser_conn *iser_conn = conn->dd_data; + + write_lock_bh(conn->recv_lock); + if (atomic_read(&iser_conn->ib_conn->post_send_buf_count) == + ISER_QP_MAX_REQ_DTOS) { + iser_dbg("%ld can't xmit task %p, suspending tx\n",jiffies,task); + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + rc = -EAGAIN; + } + write_unlock_bh(conn->recv_lock); + return rc; +} + + +/** + * iser_send_command - send command PDU + */ +int iser_send_command(struct iscsi_conn *conn, + struct iscsi_cmd_task *ctask) +{ + struct iscsi_iser_conn *iser_conn = conn->dd_data; + struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data; + struct iser_dto *send_dto = NULL; + unsigned long edtl; + int err = 0; + struct iser_data_buf *data_buf; + + struct iscsi_cmd *hdr = ctask->hdr; + struct scsi_cmnd *sc = ctask->sc; + + if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) { + iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn); + return -EPERM; + } + if (iser_check_xmit(conn, ctask)) + return -EAGAIN; + + edtl = ntohl(hdr->data_length); + + /* build the tx desc regd header and add it to the tx desc dto */ + iser_ctask->desc.type = ISCSI_TX_SCSI_COMMAND; + send_dto = &iser_ctask->desc.dto; + send_dto->ctask = iser_ctask; + iser_create_send_desc(iser_conn, &iser_ctask->desc); + + if (hdr->flags & ISCSI_FLAG_CMD_READ) + data_buf = &iser_ctask->data[ISER_DIR_IN]; + else + data_buf = &iser_ctask->data[ISER_DIR_OUT]; + + if (sc->use_sg) { /* using a scatter list */ + data_buf->buf = sc->request_buffer; + data_buf->size = sc->use_sg; + } else if (sc->request_bufflen) { + /* using a single buffer - convert it into one entry SG */ + sg_init_one(&data_buf->sg_single, + sc->request_buffer, sc->request_bufflen); + data_buf->buf = &data_buf->sg_single; + data_buf->size = 1; + } + + data_buf->data_len = sc->request_bufflen; + + if (hdr->flags & ISCSI_FLAG_CMD_READ) { + err = iser_prepare_read_cmd(ctask, edtl); + if (err) + goto send_command_error; + } + if (hdr->flags & ISCSI_FLAG_CMD_WRITE) { + err = iser_prepare_write_cmd(ctask, + ctask->imm_count, + ctask->imm_count + + ctask->unsol_count, + edtl); + if (err) + goto send_command_error; + } + + iser_reg_single(iser_conn->ib_conn->device, + send_dto->regd[0], DMA_TO_DEVICE); + + if (iser_post_receive_control(conn) != 0) { + iser_err("post_recv failed!\n"); + err = -ENOMEM; + goto send_command_error; + } + + iser_ctask->status = ISER_TASK_STATUS_STARTED; + + err = iser_post_send(&iser_ctask->desc); + if (!err) + return 0; + +send_command_error: + iser_dto_buffs_release(send_dto); + iser_err("conn %p failed ctask->itt %d err %d\n",conn, ctask->itt, err); + return err; +} + +/** + * iser_send_data_out - send data out PDU + */ +int iser_send_data_out(struct iscsi_conn *conn, + struct iscsi_cmd_task *ctask, + struct iscsi_data *hdr) +{ + struct iscsi_iser_conn *iser_conn = conn->dd_data; + struct iscsi_iser_cmd_task *iser_ctask = ctask->dd_data; + struct iser_desc *tx_desc = NULL; + struct iser_dto *send_dto = NULL; + unsigned long buf_offset; + unsigned long data_seg_len; + unsigned int itt; + int err = 0; + + if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) { + iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn); + return -EPERM; + } + + if (iser_check_xmit(conn, ctask)) + return -EAGAIN; + + itt = ntohl(hdr->itt); + data_seg_len = ntoh24(hdr->dlength); + buf_offset = ntohl(hdr->offset); + + iser_dbg("%s itt %d dseg_len %d offset %d\n", + __func__,(int)itt,(int)data_seg_len,(int)buf_offset); + + tx_desc = kmem_cache_alloc(ig.desc_cache, GFP_NOIO); + if (tx_desc == NULL) { + iser_err("Failed to alloc desc for post dataout\n"); + return -ENOMEM; + } + + tx_desc->type = ISCSI_TX_DATAOUT; + memcpy(&tx_desc->iscsi_header, hdr, sizeof(struct iscsi_hdr)); + + /* build the tx desc regd header and add it to the tx desc dto */ + send_dto = &tx_desc->dto; + send_dto->ctask = iser_ctask; + iser_create_send_desc(iser_conn, tx_desc); + + iser_reg_single(iser_conn->ib_conn->device, + send_dto->regd[0], DMA_TO_DEVICE); + + /* all data was registered for RDMA, we can use the lkey */ + iser_dto_add_regd_buff(send_dto, + &iser_ctask->rdma_regd[ISER_DIR_OUT], + buf_offset, + data_seg_len); + + if (buf_offset + data_seg_len > iser_ctask->data[ISER_DIR_OUT].data_len) { + iser_err("Offset:%ld & DSL:%ld in Data-Out " + "inconsistent with total len:%ld, itt:%d\n", + buf_offset, data_seg_len, + iser_ctask->data[ISER_DIR_OUT].data_len, itt); + err = -EINVAL; + goto send_data_out_error; + } + iser_dbg("data-out itt: %d, offset: %ld, sz: %ld\n", + itt, buf_offset, data_seg_len); + + + err = iser_post_send(tx_desc); + if (!err) + return 0; + +send_data_out_error: + iser_dto_buffs_release(send_dto); + kmem_cache_free(ig.desc_cache, tx_desc); + iser_err("conn %p failed err %d\n",conn, err); + return err; +} + +int iser_send_control(struct iscsi_conn *conn, + struct iscsi_mgmt_task *mtask) +{ + struct iscsi_iser_conn *iser_conn = conn->dd_data; + struct iser_desc *mdesc = mtask->dd_data; + struct iser_dto *send_dto = NULL; + unsigned int itt; + unsigned long data_seg_len; + int err = 0; + unsigned char opcode; + struct iser_regd_buf *regd_buf; + struct iser_device *device; + + if (!iser_conn_state_comp(iser_conn->ib_conn, ISER_CONN_UP)) { + iser_err("Failed to send, conn: 0x%p is not up\n", iser_conn->ib_conn); + return -EPERM; + } + + if (iser_check_xmit(conn,mtask)) + return -EAGAIN; + + /* build the tx desc regd header and add it to the tx desc dto */ + mdesc->type = ISCSI_TX_CONTROL; + send_dto = &mdesc->dto; + send_dto->ctask = NULL; + iser_create_send_desc(iser_conn, mdesc); + + device = iser_conn->ib_conn->device; + + iser_reg_single(device, send_dto->regd[0], DMA_TO_DEVICE); + + itt = ntohl(mtask->hdr->itt); + opcode = mtask->hdr->opcode & ISCSI_OPCODE_MASK; + data_seg_len = ntoh24(mtask->hdr->dlength); + + if (data_seg_len > 0) { + regd_buf = &mdesc->data_regd_buf; + memset(regd_buf, 0, sizeof(struct iser_regd_buf)); + regd_buf->device = device; + regd_buf->virt_addr = mtask->data; + regd_buf->data_size = mtask->data_count; + iser_reg_single(device, regd_buf, + DMA_TO_DEVICE); + iser_dto_add_regd_buff(send_dto, regd_buf, + 0, + data_seg_len); + } + + if (iser_post_receive_control(conn) != 0) { + iser_err("post_rcv_buff failed!\n"); + err = -ENOMEM; + goto send_control_error; + } + + err = iser_post_send(mdesc); + if (!err) + return 0; + +send_control_error: + iser_dto_buffs_release(send_dto); + iser_err("conn %p failed err %d\n",conn, err); + return err; +} + +/** + * iser_rcv_dto_completion - recv DTO completion + */ +void iser_rcv_completion(struct iser_desc *rx_desc, + unsigned long dto_xfer_len) +{ + struct iser_dto *dto = &rx_desc->dto; + struct iscsi_iser_conn *conn = dto->conn; + struct iscsi_session *session = conn->iscsi_conn->session; + struct iscsi_cmd_task *ctask; + struct iscsi_iser_cmd_task *iser_ctask; + struct iscsi_hdr *hdr; + char *rx_data = NULL; + int rx_data_len = 0; + unsigned int itt; + unsigned char opcode; + + hdr = &rx_desc->iscsi_header; + + iser_dbg("op 0x%x itt 0x%x\n", hdr->opcode,hdr->itt); + + if (dto_xfer_len > ISER_TOTAL_HEADERS_LEN) { /* we have data */ + rx_data_len = dto_xfer_len - ISER_TOTAL_HEADERS_LEN; + rx_data = dto->regd[1]->virt_addr; + rx_data += dto->offset[1]; + } + + opcode = hdr->opcode & ISCSI_OPCODE_MASK; + + if (opcode == ISCSI_OP_SCSI_CMD_RSP) { + itt = hdr->itt & ISCSI_ITT_MASK; /* mask out cid and age bits */ + if (!(itt < session->cmds_max)) + iser_err("itt can't be matched to task!!!" + "conn %p opcode %d cmds_max %d itt %d\n", + conn->iscsi_conn,opcode,session->cmds_max,itt); + /* use the mapping given with the cmds array indexed by itt */ + ctask = (struct iscsi_cmd_task *)session->cmds[itt]; + iser_ctask = ctask->dd_data; + iser_dbg("itt %d ctask %p\n",itt,ctask); + iser_ctask->status = ISER_TASK_STATUS_COMPLETED; + iser_ctask_rdma_finalize(iser_ctask); + } + + iser_dto_buffs_release(dto); + + iscsi_iser_recv(conn->iscsi_conn, hdr, rx_data, rx_data_len); + + kfree(rx_desc->data); + kmem_cache_free(ig.desc_cache, rx_desc); + + /* decrementing conn->post_recv_buf_count only --after-- freeing the * + * task eliminates the need to worry on tasks which are completed in * + * parallel to the execution of iser_conn_term. So the code that waits * + * for the posted rx bufs refcount to become zero handles everything */ + atomic_dec(&conn->ib_conn->post_recv_buf_count); +} + +void iser_snd_completion(struct iser_desc *tx_desc) +{ + struct iser_dto *dto = &tx_desc->dto; + struct iscsi_iser_conn *iser_conn = dto->conn; + struct iscsi_conn *conn = iser_conn->iscsi_conn; + struct iscsi_mgmt_task *mtask; + + iser_dbg("Initiator, Data sent dto=0x%p\n", dto); + + iser_dto_buffs_release(dto); + + if (tx_desc->type == ISCSI_TX_DATAOUT) + kmem_cache_free(ig.desc_cache, tx_desc); + + atomic_dec(&iser_conn->ib_conn->post_send_buf_count); + + write_lock(conn->recv_lock); + if (conn->suspend_tx) { + iser_dbg("%ld resuming tx\n",jiffies); + clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + scsi_queue_work(conn->session->host, &conn->xmitwork); + } + write_unlock(conn->recv_lock); + + if (tx_desc->type == ISCSI_TX_CONTROL) { + /* this arithmetic is legal by libiscsi dd_data allocation */ + mtask = (void *) ((long)(void *)tx_desc - + sizeof(struct iscsi_mgmt_task)); + if (mtask->hdr->itt == cpu_to_be32(ISCSI_RESERVED_TAG)) { + struct iscsi_session *session = conn->session; + + spin_lock(&conn->session->lock); + list_del(&mtask->running); + __kfifo_put(session->mgmtpool.queue, (void*)&mtask, + sizeof(void*)); + spin_unlock(&session->lock); + } + } +} + +void iser_ctask_rdma_init(struct iscsi_iser_cmd_task *iser_ctask) + +{ + iser_ctask->status = ISER_TASK_STATUS_INIT; + + iser_ctask->dir[ISER_DIR_IN] = 0; + iser_ctask->dir[ISER_DIR_OUT] = 0; + + iser_ctask->data[ISER_DIR_IN].data_len = 0; + iser_ctask->data[ISER_DIR_OUT].data_len = 0; + + memset(&iser_ctask->rdma_regd[ISER_DIR_IN], 0, + sizeof(struct iser_regd_buf)); + memset(&iser_ctask->rdma_regd[ISER_DIR_OUT], 0, + sizeof(struct iser_regd_buf)); +} + +void iser_ctask_rdma_finalize(struct iscsi_iser_cmd_task *iser_ctask) +{ + int deferred; + + /* if we were reading, copy back to unaligned sglist, + * anyway dma_unmap and free the copy + */ + if (iser_ctask->data_copy[ISER_DIR_IN].copy_buf != NULL) + iser_finalize_rdma_unaligned_sg(iser_ctask, ISER_DIR_IN); + if (iser_ctask->data_copy[ISER_DIR_OUT].copy_buf != NULL) + iser_finalize_rdma_unaligned_sg(iser_ctask, ISER_DIR_OUT); + + if (iser_ctask->dir[ISER_DIR_IN]) { + deferred = iser_regd_buff_release + (&iser_ctask->rdma_regd[ISER_DIR_IN]); + if (deferred) { + iser_err("References remain for BUF-IN rdma reg\n"); + BUG(); + } + } + + if (iser_ctask->dir[ISER_DIR_OUT]) { + deferred = iser_regd_buff_release + (&iser_ctask->rdma_regd[ISER_DIR_OUT]); + if (deferred) { + iser_err("References remain for BUF-OUT rdma reg\n"); + BUG(); + } + } + + iser_dma_unmap_task_data(iser_ctask); +} + +void iser_dto_buffs_release(struct iser_dto *dto) +{ + int i; + + for (i = 0; i < dto->regd_vector_len; i++) + iser_regd_buff_release(dto->regd[i]); +} + diff --git a/drivers/infiniband/ulp/iser/iser_memory.c b/drivers/infiniband/ulp/iser/iser_memory.c new file mode 100644 index 000000000..31950a522 --- /dev/null +++ b/drivers/infiniband/ulp/iser/iser_memory.c @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: iser_memory.c 6964 2006-05-07 11:11:43Z ogerlitz $ + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/mm.h> +#include <asm/io.h> +#include <asm/scatterlist.h> +#include <linux/scatterlist.h> + +#include "iscsi_iser.h" + +#define ISER_KMALLOC_THRESHOLD 0x20000 /* 128K - kmalloc limit */ +/** + * Decrements the reference count for the + * registered buffer & releases it + * + * returns 0 if released, 1 if deferred + */ +int iser_regd_buff_release(struct iser_regd_buf *regd_buf) +{ + struct device *dma_device; + + if ((atomic_read(®d_buf->ref_count) == 0) || + atomic_dec_and_test(®d_buf->ref_count)) { + /* if we used the dma mr, unreg is just NOP */ + if (regd_buf->reg.rkey != 0) + iser_unreg_mem(®d_buf->reg); + + if (regd_buf->dma_addr) { + dma_device = regd_buf->device->ib_device->dma_device; + dma_unmap_single(dma_device, + regd_buf->dma_addr, + regd_buf->data_size, + regd_buf->direction); + } + /* else this regd buf is associated with task which we */ + /* dma_unmap_single/sg later */ + return 0; + } else { + iser_dbg("Release deferred, regd.buff: 0x%p\n", regd_buf); + return 1; + } +} + +/** + * iser_reg_single - fills registered buffer descriptor with + * registration information + */ +void iser_reg_single(struct iser_device *device, + struct iser_regd_buf *regd_buf, + enum dma_data_direction direction) +{ + dma_addr_t dma_addr; + + dma_addr = dma_map_single(device->ib_device->dma_device, + regd_buf->virt_addr, + regd_buf->data_size, direction); + BUG_ON(dma_mapping_error(dma_addr)); + + regd_buf->reg.lkey = device->mr->lkey; + regd_buf->reg.rkey = 0; /* indicate there's no need to unreg */ + regd_buf->reg.len = regd_buf->data_size; + regd_buf->reg.va = dma_addr; + + regd_buf->dma_addr = dma_addr; + regd_buf->direction = direction; +} + +/** + * iser_start_rdma_unaligned_sg + */ +int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, + enum iser_data_dir cmd_dir) +{ + int dma_nents; + struct device *dma_device; + char *mem = NULL; + struct iser_data_buf *data = &iser_ctask->data[cmd_dir]; + unsigned long cmd_data_len = data->data_len; + + if (cmd_data_len > ISER_KMALLOC_THRESHOLD) + mem = (void *)__get_free_pages(GFP_NOIO, + long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); + else + mem = kmalloc(cmd_data_len, GFP_NOIO); + + if (mem == NULL) { + iser_err("Failed to allocate mem size %d %d for copying sglist\n", + data->size,(int)cmd_data_len); + return -ENOMEM; + } + + if (cmd_dir == ISER_DIR_OUT) { + /* copy the unaligned sg the buffer which is used for RDMA */ + struct scatterlist *sg = (struct scatterlist *)data->buf; + int i; + char *p, *from; + + for (p = mem, i = 0; i < data->size; i++) { + from = kmap_atomic(sg[i].page, KM_USER0); + memcpy(p, + from + sg[i].offset, + sg[i].length); + kunmap_atomic(from, KM_USER0); + p += sg[i].length; + } + } + + sg_init_one(&iser_ctask->data_copy[cmd_dir].sg_single, mem, cmd_data_len); + iser_ctask->data_copy[cmd_dir].buf = + &iser_ctask->data_copy[cmd_dir].sg_single; + iser_ctask->data_copy[cmd_dir].size = 1; + + iser_ctask->data_copy[cmd_dir].copy_buf = mem; + + dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device; + + if (cmd_dir == ISER_DIR_OUT) + dma_nents = dma_map_sg(dma_device, + &iser_ctask->data_copy[cmd_dir].sg_single, + 1, DMA_TO_DEVICE); + else + dma_nents = dma_map_sg(dma_device, + &iser_ctask->data_copy[cmd_dir].sg_single, + 1, DMA_FROM_DEVICE); + + BUG_ON(dma_nents == 0); + + iser_ctask->data_copy[cmd_dir].dma_nents = dma_nents; + return 0; +} + +/** + * iser_finalize_rdma_unaligned_sg + */ +void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, + enum iser_data_dir cmd_dir) +{ + struct device *dma_device; + struct iser_data_buf *mem_copy; + unsigned long cmd_data_len; + + dma_device = iser_ctask->iser_conn->ib_conn->device->ib_device->dma_device; + mem_copy = &iser_ctask->data_copy[cmd_dir]; + + if (cmd_dir == ISER_DIR_OUT) + dma_unmap_sg(dma_device, &mem_copy->sg_single, 1, + DMA_TO_DEVICE); + else + dma_unmap_sg(dma_device, &mem_copy->sg_single, 1, + DMA_FROM_DEVICE); + + if (cmd_dir == ISER_DIR_IN) { + char *mem; + struct scatterlist *sg; + unsigned char *p, *to; + unsigned int sg_size; + int i; + + /* copy back read RDMA to unaligned sg */ + mem = mem_copy->copy_buf; + + sg = (struct scatterlist *)iser_ctask->data[ISER_DIR_IN].buf; + sg_size = iser_ctask->data[ISER_DIR_IN].size; + + for (p = mem, i = 0; i < sg_size; i++){ + to = kmap_atomic(sg[i].page, KM_SOFTIRQ0); + memcpy(to + sg[i].offset, + p, + sg[i].length); + kunmap_atomic(to, KM_SOFTIRQ0); + p += sg[i].length; + } + } + + cmd_data_len = iser_ctask->data[cmd_dir].data_len; + + if (cmd_data_len > ISER_KMALLOC_THRESHOLD) + free_pages((unsigned long)mem_copy->copy_buf, + long_log2(roundup_pow_of_two(cmd_data_len)) - PAGE_SHIFT); + else + kfree(mem_copy->copy_buf); + + mem_copy->copy_buf = NULL; +} + +/** + * iser_sg_to_page_vec - Translates scatterlist entries to physical addresses + * and returns the length of resulting physical address array (may be less than + * the original due to possible compaction). + * + * we build a "page vec" under the assumption that the SG meets the RDMA + * alignment requirements. Other then the first and last SG elements, all + * the "internal" elements can be compacted into a list whose elements are + * dma addresses of physical pages. The code supports also the weird case + * where --few fragments of the same page-- are present in the SG as + * consecutive elements. Also, it handles one entry SG. + */ +static int iser_sg_to_page_vec(struct iser_data_buf *data, + struct iser_page_vec *page_vec) +{ + struct scatterlist *sg = (struct scatterlist *)data->buf; + dma_addr_t first_addr, last_addr, page; + int start_aligned, end_aligned; + unsigned int cur_page = 0; + unsigned long total_sz = 0; + int i; + + /* compute the offset of first element */ + page_vec->offset = (u64) sg[0].offset; + + for (i = 0; i < data->dma_nents; i++) { + total_sz += sg_dma_len(&sg[i]); + + first_addr = sg_dma_address(&sg[i]); + last_addr = first_addr + sg_dma_len(&sg[i]); + + start_aligned = !(first_addr & ~PAGE_MASK); + end_aligned = !(last_addr & ~PAGE_MASK); + + /* continue to collect page fragments till aligned or SG ends */ + while (!end_aligned && (i + 1 < data->dma_nents)) { + i++; + total_sz += sg_dma_len(&sg[i]); + last_addr = sg_dma_address(&sg[i]) + sg_dma_len(&sg[i]); + end_aligned = !(last_addr & ~PAGE_MASK); + } + + first_addr = first_addr & PAGE_MASK; + + for (page = first_addr; page < last_addr; page += PAGE_SIZE) + page_vec->pages[cur_page++] = page; + + } + page_vec->data_size = total_sz; + iser_dbg("page_vec->data_size:%d cur_page %d\n", page_vec->data_size,cur_page); + return cur_page; +} + +#define MASK_4K ((1UL << 12) - 1) /* 0xFFF */ +#define IS_4K_ALIGNED(addr) ((((unsigned long)addr) & MASK_4K) == 0) + +/** + * iser_data_buf_aligned_len - Tries to determine the maximal correctly aligned + * for RDMA sub-list of a scatter-gather list of memory buffers, and returns + * the number of entries which are aligned correctly. Supports the case where + * consecutive SG elements are actually fragments of the same physcial page. + */ +static unsigned int iser_data_buf_aligned_len(struct iser_data_buf *data) +{ + struct scatterlist *sg; + dma_addr_t end_addr, next_addr; + int i, cnt; + unsigned int ret_len = 0; + + sg = (struct scatterlist *)data->buf; + + for (cnt = 0, i = 0; i < data->dma_nents; i++, cnt++) { + /* iser_dbg("Checking sg iobuf [%d]: phys=0x%08lX " + "offset: %ld sz: %ld\n", i, + (unsigned long)page_to_phys(sg[i].page), + (unsigned long)sg[i].offset, + (unsigned long)sg[i].length); */ + end_addr = sg_dma_address(&sg[i]) + + sg_dma_len(&sg[i]); + /* iser_dbg("Checking sg iobuf end address " + "0x%08lX\n", end_addr); */ + if (i + 1 < data->dma_nents) { + next_addr = sg_dma_address(&sg[i+1]); + /* are i, i+1 fragments of the same page? */ + if (end_addr == next_addr) + continue; + else if (!IS_4K_ALIGNED(end_addr)) { + ret_len = cnt + 1; + break; + } + } + } + if (i == data->dma_nents) + ret_len = cnt; /* loop ended */ + iser_dbg("Found %d aligned entries out of %d in sg:0x%p\n", + ret_len, data->dma_nents, data); + return ret_len; +} + +static void iser_data_buf_dump(struct iser_data_buf *data) +{ + struct scatterlist *sg = (struct scatterlist *)data->buf; + int i; + + for (i = 0; i < data->size; i++) + iser_err("sg[%d] dma_addr:0x%lX page:0x%p " + "off:%d sz:%d dma_len:%d\n", + i, (unsigned long)sg_dma_address(&sg[i]), + sg[i].page, sg[i].offset, + sg[i].length,sg_dma_len(&sg[i])); +} + +static void iser_dump_page_vec(struct iser_page_vec *page_vec) +{ + int i; + + iser_err("page vec length %d data size %d\n", + page_vec->length, page_vec->data_size); + for (i = 0; i < page_vec->length; i++) + iser_err("%d %lx\n",i,(unsigned long)page_vec->pages[i]); +} + +static void iser_page_vec_build(struct iser_data_buf *data, + struct iser_page_vec *page_vec) +{ + int page_vec_len = 0; + + page_vec->length = 0; + page_vec->offset = 0; + + iser_dbg("Translating sg sz: %d\n", data->dma_nents); + page_vec_len = iser_sg_to_page_vec(data,page_vec); + iser_dbg("sg len %d page_vec_len %d\n", data->dma_nents,page_vec_len); + + page_vec->length = page_vec_len; + + if (page_vec_len * PAGE_SIZE < page_vec->data_size) { + iser_err("page_vec too short to hold this SG\n"); + iser_data_buf_dump(data); + iser_dump_page_vec(page_vec); + BUG(); + } +} + +/** + * iser_reg_rdma_mem - Registers memory intended for RDMA, + * obtaining rkey and va + * + * returns 0 on success, errno code on failure + */ +int iser_reg_rdma_mem(struct iscsi_iser_cmd_task *iser_ctask, + enum iser_data_dir cmd_dir) +{ + struct iser_conn *ib_conn = iser_ctask->iser_conn->ib_conn; + struct iser_data_buf *mem = &iser_ctask->data[cmd_dir]; + struct iser_regd_buf *regd_buf; + int aligned_len; + int err; + + regd_buf = &iser_ctask->rdma_regd[cmd_dir]; + + aligned_len = iser_data_buf_aligned_len(mem); + if (aligned_len != mem->size) { + iser_err("rdma alignment violation %d/%d aligned\n", + aligned_len, mem->size); + iser_data_buf_dump(mem); + /* allocate copy buf, if we are writing, copy the */ + /* unaligned scatterlist, dma map the copy */ + if (iser_start_rdma_unaligned_sg(iser_ctask, cmd_dir) != 0) + return -ENOMEM; + mem = &iser_ctask->data_copy[cmd_dir]; + } + + iser_page_vec_build(mem, ib_conn->page_vec); + err = iser_reg_page_vec(ib_conn, ib_conn->page_vec, ®d_buf->reg); + if (err) + return err; + + /* take a reference on this regd buf such that it will not be released * + * (eg in send dto completion) before we get the scsi response */ + atomic_inc(®d_buf->ref_count); + return 0; +} diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c new file mode 100644 index 000000000..72febf1f8 --- /dev/null +++ b/drivers/infiniband/ulp/iser/iser_verbs.c @@ -0,0 +1,827 @@ +/* + * Copyright (c) 2004, 2005, 2006 Voltaire, Inc. All rights reserved. + * Copyright (c) 2005, 2006 Cisco Systems. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: iser_verbs.c 7051 2006-05-10 12:29:11Z ogerlitz $ + */ +#include <asm/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/smp_lock.h> +#include <linux/delay.h> +#include <linux/version.h> + +#include "iscsi_iser.h" + +#define ISCSI_ISER_MAX_CONN 8 +#define ISER_MAX_CQ_LEN ((ISER_QP_MAX_RECV_DTOS + \ + ISER_QP_MAX_REQ_DTOS) * \ + ISCSI_ISER_MAX_CONN) + +static void iser_cq_tasklet_fn(unsigned long data); +static void iser_cq_callback(struct ib_cq *cq, void *cq_context); +static void iser_comp_error_worker(void *data); + +static void iser_cq_event_callback(struct ib_event *cause, void *context) +{ + iser_err("got cq event %d \n", cause->event); +} + +static void iser_qp_event_callback(struct ib_event *cause, void *context) +{ + iser_err("got qp event %d\n",cause->event); +} + +/** + * iser_create_device_ib_res - creates Protection Domain (PD), Completion + * Queue (CQ), DMA Memory Region (DMA MR) with the device associated with + * the adapator. + * + * returns 0 on success, -1 on failure + */ +static int iser_create_device_ib_res(struct iser_device *device) +{ + device->pd = ib_alloc_pd(device->ib_device); + if (IS_ERR(device->pd)) + goto pd_err; + + device->cq = ib_create_cq(device->ib_device, + iser_cq_callback, + iser_cq_event_callback, + (void *)device, + ISER_MAX_CQ_LEN); + if (IS_ERR(device->cq)) + goto cq_err; + + if (ib_req_notify_cq(device->cq, IB_CQ_NEXT_COMP)) + goto cq_arm_err; + + tasklet_init(&device->cq_tasklet, + iser_cq_tasklet_fn, + (unsigned long)device); + + device->mr = ib_get_dma_mr(device->pd, + IB_ACCESS_LOCAL_WRITE); + if (IS_ERR(device->mr)) + goto dma_mr_err; + + return 0; + +dma_mr_err: + tasklet_kill(&device->cq_tasklet); +cq_arm_err: + ib_destroy_cq(device->cq); +cq_err: + ib_dealloc_pd(device->pd); +pd_err: + iser_err("failed to allocate an IB resource\n"); + return -1; +} + +/** + * iser_free_device_ib_res - destory/dealloc/dereg the DMA MR, + * CQ and PD created with the device associated with the adapator. + */ +static void iser_free_device_ib_res(struct iser_device *device) +{ + BUG_ON(device->mr == NULL); + + tasklet_kill(&device->cq_tasklet); + + (void)ib_dereg_mr(device->mr); + (void)ib_destroy_cq(device->cq); + (void)ib_dealloc_pd(device->pd); + + device->mr = NULL; + device->cq = NULL; + device->pd = NULL; +} + +/** + * iser_create_ib_conn_res - Creates FMR pool and Queue-Pair (QP) + * + * returns 0 on success, -1 on failure + */ +static int iser_create_ib_conn_res(struct iser_conn *ib_conn) +{ + struct iser_device *device; + struct ib_qp_init_attr init_attr; + int ret; + struct ib_fmr_pool_param params; + + BUG_ON(ib_conn->device == NULL); + + device = ib_conn->device; + + ib_conn->page_vec = kmalloc(sizeof(struct iser_page_vec) + + (sizeof(u64) * (ISCSI_ISER_SG_TABLESIZE +1)), + GFP_KERNEL); + if (!ib_conn->page_vec) { + ret = -ENOMEM; + goto alloc_err; + } + ib_conn->page_vec->pages = (u64 *) (ib_conn->page_vec + 1); + + params.page_shift = PAGE_SHIFT; + /* when the first/last SG element are not start/end * + * page aligned, the map whould be of N+1 pages */ + params.max_pages_per_fmr = ISCSI_ISER_SG_TABLESIZE + 1; + /* make the pool size twice the max number of SCSI commands * + * the ML is expected to queue, watermark for unmap at 50% */ + params.pool_size = ISCSI_XMIT_CMDS_MAX * 2; + params.dirty_watermark = ISCSI_XMIT_CMDS_MAX; + params.cache = 0; + params.flush_function = NULL; + params.access = (IB_ACCESS_LOCAL_WRITE | + IB_ACCESS_REMOTE_WRITE | + IB_ACCESS_REMOTE_READ); + + ib_conn->fmr_pool = ib_create_fmr_pool(device->pd, ¶ms); + if (IS_ERR(ib_conn->fmr_pool)) { + ret = PTR_ERR(ib_conn->fmr_pool); + goto fmr_pool_err; + } + + memset(&init_attr, 0, sizeof init_attr); + + init_attr.event_handler = iser_qp_event_callback; + init_attr.qp_context = (void *)ib_conn; + init_attr.send_cq = device->cq; + init_attr.recv_cq = device->cq; + init_attr.cap.max_send_wr = ISER_QP_MAX_REQ_DTOS; + init_attr.cap.max_recv_wr = ISER_QP_MAX_RECV_DTOS; + init_attr.cap.max_send_sge = MAX_REGD_BUF_VECTOR_LEN; + init_attr.cap.max_recv_sge = 2; + init_attr.sq_sig_type = IB_SIGNAL_REQ_WR; + init_attr.qp_type = IB_QPT_RC; + + ret = rdma_create_qp(ib_conn->cma_id, device->pd, &init_attr); + if (ret) + goto qp_err; + + ib_conn->qp = ib_conn->cma_id->qp; + iser_err("setting conn %p cma_id %p: fmr_pool %p qp %p\n", + ib_conn, ib_conn->cma_id, + ib_conn->fmr_pool, ib_conn->cma_id->qp); + return ret; + +qp_err: + (void)ib_destroy_fmr_pool(ib_conn->fmr_pool); +fmr_pool_err: + kfree(ib_conn->page_vec); +alloc_err: + iser_err("unable to alloc mem or create resource, err %d\n", ret); + return ret; +} + +/** + * releases the FMR pool, QP and CMA ID objects, returns 0 on success, + * -1 on failure + */ +static int iser_free_ib_conn_res(struct iser_conn *ib_conn) +{ + BUG_ON(ib_conn == NULL); + + iser_err("freeing conn %p cma_id %p fmr pool %p qp %p\n", + ib_conn, ib_conn->cma_id, + ib_conn->fmr_pool, ib_conn->qp); + + /* qp is created only once both addr & route are resolved */ + if (ib_conn->fmr_pool != NULL) + ib_destroy_fmr_pool(ib_conn->fmr_pool); + + if (ib_conn->qp != NULL) + rdma_destroy_qp(ib_conn->cma_id); + + if (ib_conn->cma_id != NULL) + rdma_destroy_id(ib_conn->cma_id); + + ib_conn->fmr_pool = NULL; + ib_conn->qp = NULL; + ib_conn->cma_id = NULL; + kfree(ib_conn->page_vec); + + return 0; +} + +/** + * based on the resolved device node GUID see if there already allocated + * device for this device. If there's no such, create one. + */ +static +struct iser_device *iser_device_find_by_ib_device(struct rdma_cm_id *cma_id) +{ + struct list_head *p_list; + struct iser_device *device = NULL; + + mutex_lock(&ig.device_list_mutex); + + p_list = ig.device_list.next; + while (p_list != &ig.device_list) { + device = list_entry(p_list, struct iser_device, ig_list); + /* find if there's a match using the node GUID */ + if (device->ib_device->node_guid == cma_id->device->node_guid) + break; + } + + if (device == NULL) { + device = kzalloc(sizeof *device, GFP_KERNEL); + if (device == NULL) + goto out; + /* assign this device to the device */ + device->ib_device = cma_id->device; + /* init the device and link it into ig device list */ + if (iser_create_device_ib_res(device)) { + kfree(device); + device = NULL; + goto out; + } + list_add(&device->ig_list, &ig.device_list); + } +out: + BUG_ON(device == NULL); + device->refcount++; + mutex_unlock(&ig.device_list_mutex); + return device; +} + +/* if there's no demand for this device, release it */ +static void iser_device_try_release(struct iser_device *device) +{ + mutex_lock(&ig.device_list_mutex); + device->refcount--; + iser_err("device %p refcount %d\n",device,device->refcount); + if (!device->refcount) { + iser_free_device_ib_res(device); + list_del(&device->ig_list); + kfree(device); + } + mutex_unlock(&ig.device_list_mutex); +} + +int iser_conn_state_comp(struct iser_conn *ib_conn, + enum iser_ib_conn_state comp) +{ + int ret; + + spin_lock_bh(&ib_conn->lock); + ret = (ib_conn->state == comp); + spin_unlock_bh(&ib_conn->lock); + return ret; +} + +static int iser_conn_state_comp_exch(struct iser_conn *ib_conn, + enum iser_ib_conn_state comp, + enum iser_ib_conn_state exch) +{ + int ret; + + spin_lock_bh(&ib_conn->lock); + if ((ret = (ib_conn->state == comp))) + ib_conn->state = exch; + spin_unlock_bh(&ib_conn->lock); + return ret; +} + +/** + * triggers start of the disconnect procedures and wait for them to be done + */ +void iser_conn_terminate(struct iser_conn *ib_conn) +{ + int err = 0; + + /* change the ib conn state only if the conn is UP, however always call + * rdma_disconnect since this is the only way to cause the CMA to change + * the QP state to ERROR + */ + + iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP, ISER_CONN_TERMINATING); + err = rdma_disconnect(ib_conn->cma_id); + if (err) + iser_err("Failed to disconnect, conn: 0x%p err %d\n", + ib_conn,err); + + wait_event_interruptible(ib_conn->wait, + ib_conn->state == ISER_CONN_DOWN); + + iser_conn_release(ib_conn); +} + +static void iser_connect_error(struct rdma_cm_id *cma_id) +{ + struct iser_conn *ib_conn; + ib_conn = (struct iser_conn *)cma_id->context; + + ib_conn->state = ISER_CONN_DOWN; + wake_up_interruptible(&ib_conn->wait); +} + +static void iser_addr_handler(struct rdma_cm_id *cma_id) +{ + struct iser_device *device; + struct iser_conn *ib_conn; + int ret; + + device = iser_device_find_by_ib_device(cma_id); + ib_conn = (struct iser_conn *)cma_id->context; + ib_conn->device = device; + + ret = rdma_resolve_route(cma_id, 1000); + if (ret) { + iser_err("resolve route failed: %d\n", ret); + iser_connect_error(cma_id); + } + return; +} + +static void iser_route_handler(struct rdma_cm_id *cma_id) +{ + struct rdma_conn_param conn_param; + int ret; + + ret = iser_create_ib_conn_res((struct iser_conn *)cma_id->context); + if (ret) + goto failure; + + iser_dbg("path.mtu is %d setting it to %d\n", + cma_id->route.path_rec->mtu, IB_MTU_1024); + + /* we must set the MTU to 1024 as this is what the target is assuming */ + if (cma_id->route.path_rec->mtu > IB_MTU_1024) + cma_id->route.path_rec->mtu = IB_MTU_1024; + + memset(&conn_param, 0, sizeof conn_param); + conn_param.responder_resources = 4; + conn_param.initiator_depth = 1; + conn_param.retry_count = 7; + conn_param.rnr_retry_count = 6; + + ret = rdma_connect(cma_id, &conn_param); + if (ret) { + iser_err("failure connecting: %d\n", ret); + goto failure; + } + + return; +failure: + iser_connect_error(cma_id); +} + +static void iser_connected_handler(struct rdma_cm_id *cma_id) +{ + struct iser_conn *ib_conn; + + ib_conn = (struct iser_conn *)cma_id->context; + ib_conn->state = ISER_CONN_UP; + wake_up_interruptible(&ib_conn->wait); +} + +static void iser_disconnected_handler(struct rdma_cm_id *cma_id) +{ + struct iser_conn *ib_conn; + + ib_conn = (struct iser_conn *)cma_id->context; + ib_conn->disc_evt_flag = 1; + + /* getting here when the state is UP means that the conn is being * + * terminated asynchronously from the iSCSI layer's perspective. */ + if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP, + ISER_CONN_TERMINATING)) + iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn, + ISCSI_ERR_CONN_FAILED); + + /* Complete the termination process if no posts are pending */ + if ((atomic_read(&ib_conn->post_recv_buf_count) == 0) && + (atomic_read(&ib_conn->post_send_buf_count) == 0)) { + ib_conn->state = ISER_CONN_DOWN; + wake_up_interruptible(&ib_conn->wait); + } +} + +static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) +{ + int ret = 0; + + iser_err("event %d conn %p id %p\n",event->event,cma_id->context,cma_id); + + switch (event->event) { + case RDMA_CM_EVENT_ADDR_RESOLVED: + iser_addr_handler(cma_id); + break; + case RDMA_CM_EVENT_ROUTE_RESOLVED: + iser_route_handler(cma_id); + break; + case RDMA_CM_EVENT_ESTABLISHED: + iser_connected_handler(cma_id); + break; + case RDMA_CM_EVENT_ADDR_ERROR: + case RDMA_CM_EVENT_ROUTE_ERROR: + case RDMA_CM_EVENT_CONNECT_ERROR: + case RDMA_CM_EVENT_UNREACHABLE: + case RDMA_CM_EVENT_REJECTED: + iser_err("event: %d, error: %d\n", event->event, event->status); + iser_connect_error(cma_id); + break; + case RDMA_CM_EVENT_DISCONNECTED: + iser_disconnected_handler(cma_id); + break; + case RDMA_CM_EVENT_DEVICE_REMOVAL: + BUG(); + break; + case RDMA_CM_EVENT_CONNECT_RESPONSE: + BUG(); + break; + case RDMA_CM_EVENT_CONNECT_REQUEST: + default: + break; + } + return ret; +} + +int iser_conn_init(struct iser_conn **ibconn) +{ + struct iser_conn *ib_conn; + + ib_conn = kzalloc(sizeof *ib_conn, GFP_KERNEL); + if (!ib_conn) { + iser_err("can't alloc memory for struct iser_conn\n"); + return -ENOMEM; + } + ib_conn->state = ISER_CONN_INIT; + init_waitqueue_head(&ib_conn->wait); + atomic_set(&ib_conn->post_recv_buf_count, 0); + atomic_set(&ib_conn->post_send_buf_count, 0); + INIT_WORK(&ib_conn->comperror_work, iser_comp_error_worker, + ib_conn); + INIT_LIST_HEAD(&ib_conn->conn_list); + spin_lock_init(&ib_conn->lock); + + *ibconn = ib_conn; + return 0; +} + + /** + * starts the process of connecting to the target + * sleeps untill the connection is established or rejected + */ +int iser_connect(struct iser_conn *ib_conn, + struct sockaddr_in *src_addr, + struct sockaddr_in *dst_addr, + int non_blocking) +{ + struct sockaddr *src, *dst; + int err = 0; + + sprintf(ib_conn->name,"%d.%d.%d.%d:%d", + NIPQUAD(dst_addr->sin_addr.s_addr), dst_addr->sin_port); + + /* the device is known only --after-- address resolution */ + ib_conn->device = NULL; + + iser_err("connecting to: %d.%d.%d.%d, port 0x%x\n", + NIPQUAD(dst_addr->sin_addr), dst_addr->sin_port); + + ib_conn->state = ISER_CONN_PENDING; + + ib_conn->cma_id = rdma_create_id(iser_cma_handler, + (void *)ib_conn, + RDMA_PS_TCP); + if (IS_ERR(ib_conn->cma_id)) { + err = PTR_ERR(ib_conn->cma_id); + iser_err("rdma_create_id failed: %d\n", err); + goto id_failure; + } + + src = (struct sockaddr *)src_addr; + dst = (struct sockaddr *)dst_addr; + err = rdma_resolve_addr(ib_conn->cma_id, src, dst, 1000); + if (err) { + iser_err("rdma_resolve_addr failed: %d\n", err); + goto addr_failure; + } + + if (!non_blocking) { + wait_event_interruptible(ib_conn->wait, + (ib_conn->state != ISER_CONN_PENDING)); + + if (ib_conn->state != ISER_CONN_UP) { + err = -EIO; + goto connect_failure; + } + } + + mutex_lock(&ig.connlist_mutex); + list_add(&ib_conn->conn_list, &ig.connlist); + mutex_unlock(&ig.connlist_mutex); + return 0; + +id_failure: + ib_conn->cma_id = NULL; +addr_failure: + ib_conn->state = ISER_CONN_DOWN; +connect_failure: + iser_conn_release(ib_conn); + return err; +} + +/** + * Frees all conn objects and deallocs conn descriptor + */ +void iser_conn_release(struct iser_conn *ib_conn) +{ + struct iser_device *device = ib_conn->device; + + BUG_ON(ib_conn->state != ISER_CONN_DOWN); + + mutex_lock(&ig.connlist_mutex); + list_del(&ib_conn->conn_list); + mutex_unlock(&ig.connlist_mutex); + + iser_free_ib_conn_res(ib_conn); + ib_conn->device = NULL; + /* on EVENT_ADDR_ERROR there's no device yet for this conn */ + if (device != NULL) + iser_device_try_release(device); + kfree(ib_conn); +} + + +/** + * iser_reg_page_vec - Register physical memory + * + * returns: 0 on success, errno code on failure + */ +int iser_reg_page_vec(struct iser_conn *ib_conn, + struct iser_page_vec *page_vec, + struct iser_mem_reg *mem_reg) +{ + struct ib_pool_fmr *mem; + u64 io_addr; + u64 *page_list; + int status; + + page_list = page_vec->pages; + io_addr = page_list[0]; + + mem = ib_fmr_pool_map_phys(ib_conn->fmr_pool, + page_list, + page_vec->length, + io_addr); + + if (IS_ERR(mem)) { + status = (int)PTR_ERR(mem); + iser_err("ib_fmr_pool_map_phys failed: %d\n", status); + return status; + } + + mem_reg->lkey = mem->fmr->lkey; + mem_reg->rkey = mem->fmr->rkey; + mem_reg->len = page_vec->length * PAGE_SIZE; + mem_reg->va = io_addr; + mem_reg->mem_h = (void *)mem; + + mem_reg->va += page_vec->offset; + mem_reg->len = page_vec->data_size; + + iser_dbg("PHYSICAL Mem.register, [PHYS p_array: 0x%p, sz: %d, " + "entry[0]: (0x%08lx,%ld)] -> " + "[lkey: 0x%08X mem_h: 0x%p va: 0x%08lX sz: %ld]\n", + page_vec, page_vec->length, + (unsigned long)page_vec->pages[0], + (unsigned long)page_vec->data_size, + (unsigned int)mem_reg->lkey, mem_reg->mem_h, + (unsigned long)mem_reg->va, (unsigned long)mem_reg->len); + return 0; +} + +/** + * Unregister (previosuly registered) memory. + */ +void iser_unreg_mem(struct iser_mem_reg *reg) +{ + int ret; + + iser_dbg("PHYSICAL Mem.Unregister mem_h %p\n",reg->mem_h); + + ret = ib_fmr_pool_unmap((struct ib_pool_fmr *)reg->mem_h); + if (ret) + iser_err("ib_fmr_pool_unmap failed %d\n", ret); + + reg->mem_h = NULL; +} + +/** + * iser_dto_to_iov - builds IOV from a dto descriptor + */ +static void iser_dto_to_iov(struct iser_dto *dto, struct ib_sge *iov, int iov_len) +{ + int i; + struct ib_sge *sge; + struct iser_regd_buf *regd_buf; + + if (dto->regd_vector_len > iov_len) { + iser_err("iov size %d too small for posting dto of len %d\n", + iov_len, dto->regd_vector_len); + BUG(); + } + + for (i = 0; i < dto->regd_vector_len; i++) { + sge = &iov[i]; + regd_buf = dto->regd[i]; + + sge->addr = regd_buf->reg.va; + sge->length = regd_buf->reg.len; + sge->lkey = regd_buf->reg.lkey; + + if (dto->used_sz[i] > 0) /* Adjust size */ + sge->length = dto->used_sz[i]; + + /* offset and length should not exceed the regd buf length */ + if (sge->length + dto->offset[i] > regd_buf->reg.len) { + iser_err("Used len:%ld + offset:%d, exceed reg.buf.len:" + "%ld in dto:0x%p [%d], va:0x%08lX\n", + (unsigned long)sge->length, dto->offset[i], + (unsigned long)regd_buf->reg.len, dto, i, + (unsigned long)sge->addr); + BUG(); + } + + sge->addr += dto->offset[i]; /* Adjust offset */ + } +} + +/** + * iser_post_recv - Posts a receive buffer. + * + * returns 0 on success, -1 on failure + */ +int iser_post_recv(struct iser_desc *rx_desc) +{ + int ib_ret, ret_val = 0; + struct ib_recv_wr recv_wr, *recv_wr_failed; + struct ib_sge iov[2]; + struct iser_conn *ib_conn; + struct iser_dto *recv_dto = &rx_desc->dto; + + /* Retrieve conn */ + ib_conn = recv_dto->conn->ib_conn; + + iser_dto_to_iov(recv_dto, iov, 2); + + recv_wr.next = NULL; + recv_wr.sg_list = iov; + recv_wr.num_sge = recv_dto->regd_vector_len; + recv_wr.wr_id = (unsigned long)rx_desc; + + atomic_inc(&ib_conn->post_recv_buf_count); + ib_ret = ib_post_recv(ib_conn->qp, &recv_wr, &recv_wr_failed); + if (ib_ret) { + iser_err("ib_post_recv failed ret=%d\n", ib_ret); + atomic_dec(&ib_conn->post_recv_buf_count); + ret_val = -1; + } + + return ret_val; +} + +/** + * iser_start_send - Initiate a Send DTO operation + * + * returns 0 on success, -1 on failure + */ +int iser_post_send(struct iser_desc *tx_desc) +{ + int ib_ret, ret_val = 0; + struct ib_send_wr send_wr, *send_wr_failed; + struct ib_sge iov[MAX_REGD_BUF_VECTOR_LEN]; + struct iser_conn *ib_conn; + struct iser_dto *dto = &tx_desc->dto; + + ib_conn = dto->conn->ib_conn; + + iser_dto_to_iov(dto, iov, MAX_REGD_BUF_VECTOR_LEN); + + send_wr.next = NULL; + send_wr.wr_id = (unsigned long)tx_desc; + send_wr.sg_list = iov; + send_wr.num_sge = dto->regd_vector_len; + send_wr.opcode = IB_WR_SEND; + send_wr.send_flags = dto->notify_enable ? IB_SEND_SIGNALED : 0; + + atomic_inc(&ib_conn->post_send_buf_count); + + ib_ret = ib_post_send(ib_conn->qp, &send_wr, &send_wr_failed); + if (ib_ret) { + iser_err("Failed to start SEND DTO, dto: 0x%p, IOV len: %d\n", + dto, dto->regd_vector_len); + iser_err("ib_post_send failed, ret:%d\n", ib_ret); + atomic_dec(&ib_conn->post_send_buf_count); + ret_val = -1; + } + + return ret_val; +} + +static void iser_comp_error_worker(void *data) +{ + struct iser_conn *ib_conn = data; + + /* getting here when the state is UP means that the conn is being * + * terminated asynchronously from the iSCSI layer's perspective. */ + if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP, + ISER_CONN_TERMINATING)) + iscsi_conn_failure(ib_conn->iser_conn->iscsi_conn, + ISCSI_ERR_CONN_FAILED); + + /* complete the termination process if disconnect event was delivered * + * note there are no more non completed posts to the QP */ + if (ib_conn->disc_evt_flag) { + ib_conn->state = ISER_CONN_DOWN; + wake_up_interruptible(&ib_conn->wait); + } +} + +static void iser_handle_comp_error(struct iser_desc *desc) +{ + struct iser_dto *dto = &desc->dto; + struct iser_conn *ib_conn = dto->conn->ib_conn; + + iser_dto_buffs_release(dto); + + if (desc->type == ISCSI_RX) { + kfree(desc->data); + kmem_cache_free(ig.desc_cache, desc); + atomic_dec(&ib_conn->post_recv_buf_count); + } else { /* type is TX control/command/dataout */ + if (desc->type == ISCSI_TX_DATAOUT) + kmem_cache_free(ig.desc_cache, desc); + atomic_dec(&ib_conn->post_send_buf_count); + } + + if (atomic_read(&ib_conn->post_recv_buf_count) == 0 && + atomic_read(&ib_conn->post_send_buf_count) == 0) + schedule_work(&ib_conn->comperror_work); +} + +static void iser_cq_tasklet_fn(unsigned long data) +{ + struct iser_device *device = (struct iser_device *)data; + struct ib_cq *cq = device->cq; + struct ib_wc wc; + struct iser_desc *desc; + unsigned long xfer_len; + + while (ib_poll_cq(cq, 1, &wc) == 1) { + desc = (struct iser_desc *) (unsigned long) wc.wr_id; + BUG_ON(desc == NULL); + + if (wc.status == IB_WC_SUCCESS) { + if (desc->type == ISCSI_RX) { + xfer_len = (unsigned long)wc.byte_len; + iser_rcv_completion(desc, xfer_len); + } else /* type == ISCSI_TX_CONTROL/SCSI_CMD/DOUT */ + iser_snd_completion(desc); + } else { + iser_err("comp w. error op %d status %d\n",desc->type,wc.status); + iser_handle_comp_error(desc); + } + } + /* #warning "it is assumed here that arming CQ only once its empty" * + * " would not cause interrupts to be missed" */ + ib_req_notify_cq(cq, IB_CQ_NEXT_COMP); +} + +static void iser_cq_callback(struct ib_cq *cq, void *cq_context) +{ + struct iser_device *device = (struct iser_device *)cq_context; + + tasklet_schedule(&device->cq_tasklet); +} diff --git a/drivers/leds/leds-ams-delta.c b/drivers/leds/leds-ams-delta.c new file mode 100644 index 000000000..599878c8e --- /dev/null +++ b/drivers/leds/leds-ams-delta.c @@ -0,0 +1,161 @@ +/* + * LEDs driver for Amstrad Delta (E3) + * + * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/leds.h> +#include <asm/arch/board-ams-delta.h> + +/* + * Our context + */ +struct ams_delta_led { + struct led_classdev cdev; + u8 bitmask; +}; + +static void ams_delta_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct ams_delta_led *led_dev = + container_of(led_cdev, struct ams_delta_led, cdev); + + if (value) + ams_delta_latch1_write(led_dev->bitmask, led_dev->bitmask); + else + ams_delta_latch1_write(led_dev->bitmask, 0); +} + +static struct ams_delta_led ams_delta_leds[] = { + { + .cdev = { + .name = "ams-delta:camera", + .brightness_set = ams_delta_led_set, + }, + .bitmask = AMS_DELTA_LATCH1_LED_CAMERA, + }, + { + .cdev = { + .name = "ams-delta:advert", + .brightness_set = ams_delta_led_set, + }, + .bitmask = AMS_DELTA_LATCH1_LED_ADVERT, + }, + { + .cdev = { + .name = "ams-delta:email", + .brightness_set = ams_delta_led_set, + }, + .bitmask = AMS_DELTA_LATCH1_LED_EMAIL, + }, + { + .cdev = { + .name = "ams-delta:handsfree", + .brightness_set = ams_delta_led_set, + }, + .bitmask = AMS_DELTA_LATCH1_LED_HANDSFREE, + }, + { + .cdev = { + .name = "ams-delta:voicemail", + .brightness_set = ams_delta_led_set, + }, + .bitmask = AMS_DELTA_LATCH1_LED_VOICEMAIL, + }, + { + .cdev = { + .name = "ams-delta:voice", + .brightness_set = ams_delta_led_set, + }, + .bitmask = AMS_DELTA_LATCH1_LED_VOICE, + }, +}; + +#ifdef CONFIG_PM +static int ams_delta_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++) + led_classdev_suspend(&ams_delta_leds[i].cdev); + + return 0; +} + +static int ams_delta_led_resume(struct platform_device *dev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++) + led_classdev_resume(&ams_delta_leds[i].cdev); + + return 0; +} +#else +#define ams_delta_led_suspend NULL +#define ams_delta_led_resume NULL +#endif + +static int ams_delta_led_probe(struct platform_device *pdev) +{ + int i; + int ret; + + for (i = ret = 0; ret >= 0 && i < ARRAY_SIZE(ams_delta_leds); i++) { + ret = led_classdev_register(&pdev->dev, + &ams_delta_leds[i].cdev); + } + + if (ret < 0 && i > 1) { + for (i = i - 2; i >= 0; i--) + led_classdev_unregister(&ams_delta_leds[i].cdev); + } + + return ret; +} + +static int ams_delta_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = ARRAY_SIZE(ams_delta_leds) - 1; i >= 0; i--) + led_classdev_unregister(&ams_delta_leds[i].cdev); + + return 0; +} + +static struct platform_driver ams_delta_led_driver = { + .probe = ams_delta_led_probe, + .remove = ams_delta_led_remove, + .suspend = ams_delta_led_suspend, + .resume = ams_delta_led_resume, + .driver = { + .name = "ams-delta-led", + }, +}; + +static int __init ams_delta_led_init(void) +{ + return platform_driver_register(&ams_delta_led_driver); +} + +static void __exit ams_delta_led_exit(void) +{ + return platform_driver_unregister(&ams_delta_led_driver); +} + +module_init(ams_delta_led_init); +module_exit(ams_delta_led_exit); + +MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>"); +MODULE_DESCRIPTION("Amstrad Delta LED driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/leds/leds-net48xx.c b/drivers/leds/leds-net48xx.c new file mode 100644 index 000000000..713c4a8aa --- /dev/null +++ b/drivers/leds/leds-net48xx.c @@ -0,0 +1,116 @@ +/* + * LEDs driver for Soekris net48xx + * + * Copyright (C) 2006 Chris Boot <bootc@bootc.net> + * + * Based on leds-ams-delta.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/leds.h> +#include <linux/err.h> +#include <asm/io.h> +#include <linux/scx200_gpio.h> + +#define DRVNAME "net48xx-led" +#define NET48XX_ERROR_LED_GPIO 20 + +static struct platform_device *pdev; + +static void net48xx_error_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + if (value) + scx200_gpio_set_high(NET48XX_ERROR_LED_GPIO); + else + scx200_gpio_set_low(NET48XX_ERROR_LED_GPIO); +} + +static struct led_classdev net48xx_error_led = { + .name = "net48xx:error", + .brightness_set = net48xx_error_led_set, +}; + +#ifdef CONFIG_PM +static int net48xx_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + led_classdev_suspend(&net48xx_error_led); + return 0; +} + +static int net48xx_led_resume(struct platform_device *dev) +{ + led_classdev_resume(&net48xx_error_led); + return 0; +} +#else +#define net48xx_led_suspend NULL +#define net48xx_led_resume NULL +#endif + +static int net48xx_led_probe(struct platform_device *pdev) +{ + return led_classdev_register(&pdev->dev, &net48xx_error_led); +} + +static int net48xx_led_remove(struct platform_device *pdev) +{ + led_classdev_unregister(&net48xx_error_led); + return 0; +} + +static struct platform_driver net48xx_led_driver = { + .probe = net48xx_led_probe, + .remove = net48xx_led_remove, + .suspend = net48xx_led_suspend, + .resume = net48xx_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init net48xx_led_init(void) +{ + int ret; + + if (!scx200_gpio_present()) { + ret = -ENODEV; + goto out; + } + + ret = platform_driver_register(&net48xx_led_driver); + if (ret < 0) + goto out; + + pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(pdev)) { + ret = PTR_ERR(pdev); + platform_driver_unregister(&net48xx_led_driver); + goto out; + } + +out: + return ret; +} + +static void __exit net48xx_led_exit(void) +{ + platform_device_unregister(pdev); + platform_driver_unregister(&net48xx_led_driver); +} + +module_init(net48xx_led_init); +module_exit(net48xx_led_exit); + +MODULE_AUTHOR("Chris Boot <bootc@bootc.net>"); +MODULE_DESCRIPTION("Soekris net48xx LED driver"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/leds/ledtrig-heartbeat.c b/drivers/leds/ledtrig-heartbeat.c new file mode 100644 index 000000000..4bf8cec8b --- /dev/null +++ b/drivers/leds/ledtrig-heartbeat.c @@ -0,0 +1,118 @@ +/* + * LED Heartbeat Trigger + * + * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> + * + * Based on Richard Purdie's ledtrig-timer.c and some arch's + * CONFIG_HEARTBEAT code. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/timer.h> +#include <linux/sched.h> +#include <linux/leds.h> +#include "leds.h" + +struct heartbeat_trig_data { + unsigned int phase; + unsigned int period; + struct timer_list timer; +}; + +static void led_heartbeat_function(unsigned long data) +{ + struct led_classdev *led_cdev = (struct led_classdev *) data; + struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; + unsigned long brightness = LED_OFF; + unsigned long delay = 0; + + /* acts like an actual heart beat -- ie thump-thump-pause... */ + switch (heartbeat_data->phase) { + case 0: + /* + * The hyperbolic function below modifies the + * heartbeat period length in dependency of the + * current (1min) load. It goes through the points + * f(0)=1260, f(1)=860, f(5)=510, f(inf)->300. + */ + heartbeat_data->period = 300 + + (6720 << FSHIFT) / (5 * avenrun[0] + (7 << FSHIFT)); + heartbeat_data->period = + msecs_to_jiffies(heartbeat_data->period); + delay = msecs_to_jiffies(70); + heartbeat_data->phase++; + brightness = LED_FULL; + break; + case 1: + delay = heartbeat_data->period / 4 - msecs_to_jiffies(70); + heartbeat_data->phase++; + break; + case 2: + delay = msecs_to_jiffies(70); + heartbeat_data->phase++; + brightness = LED_FULL; + break; + default: + delay = heartbeat_data->period - heartbeat_data->period / 4 - + msecs_to_jiffies(70); + heartbeat_data->phase = 0; + break; + } + + led_set_brightness(led_cdev, brightness); + mod_timer(&heartbeat_data->timer, jiffies + delay); +} + +static void heartbeat_trig_activate(struct led_classdev *led_cdev) +{ + struct heartbeat_trig_data *heartbeat_data; + + heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL); + if (!heartbeat_data) + return; + + led_cdev->trigger_data = heartbeat_data; + setup_timer(&heartbeat_data->timer, + led_heartbeat_function, (unsigned long) led_cdev); + heartbeat_data->phase = 0; + led_heartbeat_function(heartbeat_data->timer.data); +} + +static void heartbeat_trig_deactivate(struct led_classdev *led_cdev) +{ + struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data; + + if (heartbeat_data) { + del_timer_sync(&heartbeat_data->timer); + kfree(heartbeat_data); + } +} + +static struct led_trigger heartbeat_led_trigger = { + .name = "heartbeat", + .activate = heartbeat_trig_activate, + .deactivate = heartbeat_trig_deactivate, +}; + +static int __init heartbeat_trig_init(void) +{ + return led_trigger_register(&heartbeat_led_trigger); +} + +static void __exit heartbeat_trig_exit(void) +{ + led_trigger_unregister(&heartbeat_led_trigger); +} + +module_init(heartbeat_trig_init); +module_exit(heartbeat_trig_exit); + +MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); +MODULE_DESCRIPTION("Heartbeat LED trigger"); +MODULE_LICENSE("GPL"); diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c new file mode 100644 index 000000000..6c29fe727 --- /dev/null +++ b/drivers/macintosh/via-pmu-backlight.c @@ -0,0 +1,187 @@ +/* + * Backlight code for via-pmu + * + * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi. + * Copyright (C) 2001-2002 Benjamin Herrenschmidt + * Copyright (C) 2006 Michael Hanselmann <linux-kernel@hansmi.ch> + * + */ + +#include <asm/ptrace.h> +#include <linux/adb.h> +#include <linux/pmu.h> +#include <asm/backlight.h> +#include <asm/prom.h> + +#define MAX_PMU_LEVEL 0xFF + +static struct backlight_properties pmu_backlight_data; +static DEFINE_SPINLOCK(pmu_backlight_lock); +static int sleeping; +static u8 bl_curve[FB_BACKLIGHT_LEVELS]; + +static void pmu_backlight_init_curve(u8 off, u8 min, u8 max) +{ + unsigned int i, flat, count, range = (max - min); + + bl_curve[0] = off; + + for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat) + bl_curve[flat] = min; + + count = FB_BACKLIGHT_LEVELS * 15 / 16; + for (i = 0; i < count; ++i) + bl_curve[flat + i] = min + (range * (i + 1) / count); +} + +static int pmu_backlight_curve_lookup(int value) +{ + int level = (FB_BACKLIGHT_LEVELS - 1); + int i, max = 0; + + /* Look for biggest value */ + for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) + max = max((int)bl_curve[i], max); + + /* Look for nearest value */ + for (i = 0; i < FB_BACKLIGHT_LEVELS; i++) { + int diff = abs(bl_curve[i] - value); + if (diff < max) { + max = diff; + level = i; + } + } + return level; +} + +static int pmu_backlight_get_level_brightness(int level) +{ + int pmulevel; + + /* Get and convert the value */ + pmulevel = bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL; + if (pmulevel < 0) + pmulevel = 0; + else if (pmulevel > MAX_PMU_LEVEL) + pmulevel = MAX_PMU_LEVEL; + + return pmulevel; +} + +static int pmu_backlight_update_status(struct backlight_device *bd) +{ + struct adb_request req; + unsigned long flags; + int level = bd->props->brightness; + + spin_lock_irqsave(&pmu_backlight_lock, flags); + + /* Don't update brightness when sleeping */ + if (sleeping) + goto out; + + if (bd->props->power != FB_BLANK_UNBLANK || + bd->props->fb_blank != FB_BLANK_UNBLANK) + level = 0; + + if (level > 0) { + int pmulevel = pmu_backlight_get_level_brightness(level); + + pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel); + pmu_wait_complete(&req); + + pmu_request(&req, NULL, 2, PMU_POWER_CTRL, + PMU_POW_BACKLIGHT | PMU_POW_ON); + pmu_wait_complete(&req); + } else { + pmu_request(&req, NULL, 2, PMU_POWER_CTRL, + PMU_POW_BACKLIGHT | PMU_POW_OFF); + pmu_wait_complete(&req); + } + +out: + spin_unlock_irqrestore(&pmu_backlight_lock, flags); + + return 0; +} + +static int pmu_backlight_get_brightness(struct backlight_device *bd) +{ + return bd->props->brightness; +} + +static struct backlight_properties pmu_backlight_data = { + .owner = THIS_MODULE, + .get_brightness = pmu_backlight_get_brightness, + .update_status = pmu_backlight_update_status, + .max_brightness = (FB_BACKLIGHT_LEVELS - 1), +}; + +#ifdef CONFIG_PM +void pmu_backlight_set_sleep(int sleep) +{ + unsigned long flags; + + spin_lock_irqsave(&pmu_backlight_lock, flags); + sleeping = sleep; + spin_unlock_irqrestore(&pmu_backlight_lock, flags); +} +#endif /* CONFIG_PM */ + +void __init pmu_backlight_init() +{ + struct backlight_device *bd; + char name[10]; + int level, autosave; + + /* Special case for the old PowerBook since I can't test on it */ + autosave = + machine_is_compatible("AAPL,3400/2400") || + machine_is_compatible("AAPL,3500"); + + if (!autosave && + !pmac_has_backlight_type("pmu") && + !machine_is_compatible("AAPL,PowerBook1998") && + !machine_is_compatible("PowerBook1,1")) + return; + + snprintf(name, sizeof(name), "pmubl"); + + bd = backlight_device_register(name, NULL, &pmu_backlight_data); + if (IS_ERR(bd)) { + printk("pmubl: Backlight registration failed\n"); + goto error; + } + pmu_backlight_init_curve(0x7F, 0x46, 0x0E); + + level = pmu_backlight_data.max_brightness; + + if (autosave) { + /* read autosaved value if available */ + struct adb_request req; + pmu_request(&req, NULL, 2, 0xd9, 0); + pmu_wait_complete(&req); + + level = pmu_backlight_curve_lookup( + (req.reply[0] >> 4) * + pmu_backlight_data.max_brightness / 15); + } + + down(&bd->sem); + bd->props->brightness = level; + bd->props->power = FB_BLANK_UNBLANK; + bd->props->update_status(bd); + up(&bd->sem); + + mutex_lock(&pmac_backlight_mutex); + if (!pmac_backlight) + pmac_backlight = bd; + mutex_unlock(&pmac_backlight_mutex); + + printk("pmubl: Backlight initialized (%s)\n", name); + + return; + +error: + return; +} diff --git a/drivers/macintosh/via-pmu-event.c b/drivers/macintosh/via-pmu-event.c new file mode 100644 index 000000000..25cd56542 --- /dev/null +++ b/drivers/macintosh/via-pmu-event.c @@ -0,0 +1,80 @@ +/* + * via-pmu event device for reporting some events that come through the PMU + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include <linux/input.h> +#include <linux/adb.h> +#include <linux/pmu.h> +#include "via-pmu-event.h" + +static struct input_dev *pmu_input_dev; + +static int __init via_pmu_event_init(void) +{ + int err; + + /* do other models report button/lid status? */ + if (pmu_get_model() != PMU_KEYLARGO_BASED) + return -ENODEV; + + pmu_input_dev = input_allocate_device(); + if (!pmu_input_dev) + return -ENOMEM; + + pmu_input_dev->name = "PMU"; + pmu_input_dev->id.bustype = BUS_HOST; + pmu_input_dev->id.vendor = 0x0001; + pmu_input_dev->id.product = 0x0001; + pmu_input_dev->id.version = 0x0100; + + set_bit(EV_KEY, pmu_input_dev->evbit); + set_bit(EV_SW, pmu_input_dev->evbit); + set_bit(KEY_POWER, pmu_input_dev->keybit); + set_bit(SW_LID, pmu_input_dev->swbit); + + err = input_register_device(pmu_input_dev); + if (err) + input_free_device(pmu_input_dev); + return err; +} + +void via_pmu_event(int key, int down) +{ + + if (unlikely(!pmu_input_dev)) + return; + + switch (key) { + case PMU_EVT_POWER: + input_report_key(pmu_input_dev, KEY_POWER, down); + break; + case PMU_EVT_LID: + input_report_switch(pmu_input_dev, SW_LID, down); + break; + default: + /* no such key handled */ + return; + } + + input_sync(pmu_input_dev); +} + +late_initcall(via_pmu_event_init); diff --git a/drivers/macintosh/via-pmu-event.h b/drivers/macintosh/via-pmu-event.h new file mode 100644 index 000000000..72c54de40 --- /dev/null +++ b/drivers/macintosh/via-pmu-event.h @@ -0,0 +1,8 @@ +#ifndef __VIA_PMU_EVENT_H +#define __VIA_PMU_EVENT_H + +#define PMU_EVT_POWER 0 +#define PMU_EVT_LID 1 +extern void via_pmu_event(int key, int down); + +#endif /* __VIA_PMU_EVENT_H */ diff --git a/drivers/macintosh/via-pmu-led.c b/drivers/macintosh/via-pmu-led.c new file mode 100644 index 000000000..5189d5454 --- /dev/null +++ b/drivers/macintosh/via-pmu-led.c @@ -0,0 +1,144 @@ +/* + * via-pmu LED class device + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/leds.h> +#include <linux/adb.h> +#include <linux/pmu.h> +#include <asm/prom.h> + +static spinlock_t pmu_blink_lock; +static struct adb_request pmu_blink_req; +/* -1: no change, 0: request off, 1: request on */ +static int requested_change; +static int sleeping; + +static void pmu_req_done(struct adb_request * req) +{ + unsigned long flags; + + spin_lock_irqsave(&pmu_blink_lock, flags); + /* if someone requested a change in the meantime + * (we only see the last one which is fine) + * then apply it now */ + if (requested_change != -1 && !sleeping) + pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change); + /* reset requested change */ + requested_change = -1; + spin_unlock_irqrestore(&pmu_blink_lock, flags); +} + +static void pmu_led_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + unsigned long flags; + + spin_lock_irqsave(&pmu_blink_lock, flags); + switch (brightness) { + case LED_OFF: + requested_change = 0; + break; + case LED_FULL: + requested_change = 1; + break; + default: + goto out; + break; + } + /* if request isn't done, then don't do anything */ + if (pmu_blink_req.complete && !sleeping) + pmu_request(&pmu_blink_req, NULL, 4, 0xee, 4, 0, requested_change); + out: + spin_unlock_irqrestore(&pmu_blink_lock, flags); +} + +static struct led_classdev pmu_led = { + .name = "pmu-front-led", +#ifdef CONFIG_ADB_PMU_LED_IDE + .default_trigger = "ide-disk", +#endif + .brightness_set = pmu_led_set, +}; + +#ifdef CONFIG_PM +static int pmu_led_sleep_call(struct pmu_sleep_notifier *self, int when) +{ + unsigned long flags; + + spin_lock_irqsave(&pmu_blink_lock, flags); + + switch (when) { + case PBOOK_SLEEP_REQUEST: + sleeping = 1; + break; + case PBOOK_WAKE: + sleeping = 0; + break; + default: + /* do nothing */ + break; + } + spin_unlock_irqrestore(&pmu_blink_lock, flags); + + return PBOOK_SLEEP_OK; +} + +static struct pmu_sleep_notifier via_pmu_led_sleep_notif = { + .notifier_call = pmu_led_sleep_call, +}; +#endif + +static int __init via_pmu_led_init(void) +{ + struct device_node *dt; + const char *model; + + /* only do this on keylargo based models */ + if (pmu_get_model() != PMU_KEYLARGO_BASED) + return -ENODEV; + + dt = of_find_node_by_path("/"); + if (dt == NULL) + return -ENODEV; + model = (const char *)get_property(dt, "model", NULL); + if (model == NULL) + return -ENODEV; + if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 && + strncmp(model, "iBook", strlen("iBook")) != 0) { + of_node_put(dt); + /* ignore */ + return -ENODEV; + } + of_node_put(dt); + + spin_lock_init(&pmu_blink_lock); + /* no outstanding req */ + pmu_blink_req.complete = 1; + pmu_blink_req.done = pmu_req_done; +#ifdef CONFIG_PM + pmu_register_sleep_notifier(&via_pmu_led_sleep_notif); +#endif + return led_classdev_register(NULL, &pmu_led); +} + +late_initcall(via_pmu_led_init); diff --git a/drivers/media/dvb/dvb-core/dvb_math.c b/drivers/media/dvb/dvb-core/dvb_math.c new file mode 100644 index 000000000..beb7c93aa --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_math.c @@ -0,0 +1,145 @@ +/* + * dvb-math provides some complex fixed-point math + * operations shared between the dvb related stuff + * + * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com) + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/bitops.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <asm/bug.h> +#include "dvb_math.h" + +static const unsigned short logtable[256] = { + 0x0000, 0x0171, 0x02e0, 0x044e, 0x05ba, 0x0725, 0x088e, 0x09f7, + 0x0b5d, 0x0cc3, 0x0e27, 0x0f8a, 0x10eb, 0x124b, 0x13aa, 0x1508, + 0x1664, 0x17bf, 0x1919, 0x1a71, 0x1bc8, 0x1d1e, 0x1e73, 0x1fc6, + 0x2119, 0x226a, 0x23ba, 0x2508, 0x2656, 0x27a2, 0x28ed, 0x2a37, + 0x2b80, 0x2cc8, 0x2e0f, 0x2f54, 0x3098, 0x31dc, 0x331e, 0x345f, + 0x359f, 0x36de, 0x381b, 0x3958, 0x3a94, 0x3bce, 0x3d08, 0x3e41, + 0x3f78, 0x40af, 0x41e4, 0x4319, 0x444c, 0x457f, 0x46b0, 0x47e1, + 0x4910, 0x4a3f, 0x4b6c, 0x4c99, 0x4dc5, 0x4eef, 0x5019, 0x5142, + 0x526a, 0x5391, 0x54b7, 0x55dc, 0x5700, 0x5824, 0x5946, 0x5a68, + 0x5b89, 0x5ca8, 0x5dc7, 0x5ee5, 0x6003, 0x611f, 0x623a, 0x6355, + 0x646f, 0x6588, 0x66a0, 0x67b7, 0x68ce, 0x69e4, 0x6af8, 0x6c0c, + 0x6d20, 0x6e32, 0x6f44, 0x7055, 0x7165, 0x7274, 0x7383, 0x7490, + 0x759d, 0x76aa, 0x77b5, 0x78c0, 0x79ca, 0x7ad3, 0x7bdb, 0x7ce3, + 0x7dea, 0x7ef0, 0x7ff6, 0x80fb, 0x81ff, 0x8302, 0x8405, 0x8507, + 0x8608, 0x8709, 0x8809, 0x8908, 0x8a06, 0x8b04, 0x8c01, 0x8cfe, + 0x8dfa, 0x8ef5, 0x8fef, 0x90e9, 0x91e2, 0x92db, 0x93d2, 0x94ca, + 0x95c0, 0x96b6, 0x97ab, 0x98a0, 0x9994, 0x9a87, 0x9b7a, 0x9c6c, + 0x9d5e, 0x9e4f, 0x9f3f, 0xa02e, 0xa11e, 0xa20c, 0xa2fa, 0xa3e7, + 0xa4d4, 0xa5c0, 0xa6ab, 0xa796, 0xa881, 0xa96a, 0xaa53, 0xab3c, + 0xac24, 0xad0c, 0xadf2, 0xaed9, 0xafbe, 0xb0a4, 0xb188, 0xb26c, + 0xb350, 0xb433, 0xb515, 0xb5f7, 0xb6d9, 0xb7ba, 0xb89a, 0xb97a, + 0xba59, 0xbb38, 0xbc16, 0xbcf4, 0xbdd1, 0xbead, 0xbf8a, 0xc065, + 0xc140, 0xc21b, 0xc2f5, 0xc3cf, 0xc4a8, 0xc580, 0xc658, 0xc730, + 0xc807, 0xc8de, 0xc9b4, 0xca8a, 0xcb5f, 0xcc34, 0xcd08, 0xcddc, + 0xceaf, 0xcf82, 0xd054, 0xd126, 0xd1f7, 0xd2c8, 0xd399, 0xd469, + 0xd538, 0xd607, 0xd6d6, 0xd7a4, 0xd872, 0xd93f, 0xda0c, 0xdad9, + 0xdba5, 0xdc70, 0xdd3b, 0xde06, 0xded0, 0xdf9a, 0xe063, 0xe12c, + 0xe1f5, 0xe2bd, 0xe385, 0xe44c, 0xe513, 0xe5d9, 0xe69f, 0xe765, + 0xe82a, 0xe8ef, 0xe9b3, 0xea77, 0xeb3b, 0xebfe, 0xecc1, 0xed83, + 0xee45, 0xef06, 0xefc8, 0xf088, 0xf149, 0xf209, 0xf2c8, 0xf387, + 0xf446, 0xf505, 0xf5c3, 0xf680, 0xf73e, 0xf7fb, 0xf8b7, 0xf973, + 0xfa2f, 0xfaea, 0xfba5, 0xfc60, 0xfd1a, 0xfdd4, 0xfe8e, 0xff47 +}; + +unsigned int intlog2(u32 value) +{ + /** + * returns: log2(value) * 2^24 + * wrong result if value = 0 (log2(0) is undefined) + */ + unsigned int msb; + unsigned int logentry; + unsigned int significand; + unsigned int interpolation; + + if (unlikely(value == 0)) { + WARN_ON(1); + return 0; + } + + /* first detect the msb (count begins at 0) */ + msb = fls(value) - 1; + + /** + * now we use a logtable after the following method: + * + * log2(2^x * y) * 2^24 = x * 2^24 + log2(y) * 2^24 + * where x = msb and therefore 1 <= y < 2 + * first y is determined by shifting the value left + * so that msb is bit 31 + * 0x00231f56 -> 0x8C7D5800 + * the result is y * 2^31 -> "significand" + * then the highest 9 bits are used for a table lookup + * the highest bit is discarded because it's always set + * the highest nine bits in our example are 100011000 + * so we would use the entry 0x18 + */ + significand = value << (31 - msb); + logentry = (significand >> 23) & 0xff; + + /** + * last step we do is interpolation because of the + * limitations of the log table the error is that part of + * the significand which isn't used for lookup then we + * compute the ratio between the error and the next table entry + * and interpolate it between the log table entry used and the + * next one the biggest error possible is 0x7fffff + * (in our example it's 0x7D5800) + * needed value for next table entry is 0x800000 + * so the interpolation is + * (error / 0x800000) * (logtable_next - logtable_current) + * in the implementation the division is moved to the end for + * better accuracy there is also an overflow correction if + * logtable_next is 256 + */ + interpolation = ((significand & 0x7fffff) * + ((logtable[(logentry + 1) & 0xff] - + logtable[logentry]) & 0xffff)) >> 15; + + /* now we return the result */ + return ((msb << 24) + (logtable[logentry] << 8) + interpolation); +} +EXPORT_SYMBOL(intlog2); + +unsigned int intlog10(u32 value) +{ + /** + * returns: log10(value) * 2^24 + * wrong result if value = 0 (log10(0) is undefined) + */ + u64 log; + + if (unlikely(value == 0)) { + WARN_ON(1); + return 0; + } + + log = intlog2(value); + + /** + * we use the following method: + * log10(x) = log2(x) * log10(2) + */ + + return (log * 646456993) >> 31; +} +EXPORT_SYMBOL(intlog10); diff --git a/drivers/media/dvb/dvb-core/dvb_math.h b/drivers/media/dvb/dvb-core/dvb_math.h new file mode 100644 index 000000000..aecc867e9 --- /dev/null +++ b/drivers/media/dvb/dvb-core/dvb_math.h @@ -0,0 +1,58 @@ +/* + * dvb-math provides some complex fixed-point math + * operations shared between the dvb related stuff + * + * Copyright (C) 2006 Christoph Pfister (christophpfister@gmail.com) + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __DVB_MATH_H +#define __DVB_MATH_H + +#include <linux/types.h> + +/** + * computes log2 of a value; the result is shifted left by 24 bits + * + * to use rational values you can use the following method: + * intlog2(value) = intlog2(value * 2^x) - x * 2^24 + * + * example: intlog2(8) will give 3 << 24 = 3 * 2^24 + * example: intlog2(9) will give 3 << 24 + ... = 3.16... * 2^24 + * example: intlog2(1.5) = intlog2(3) - 2^24 = 0.584... * 2^24 + * + * @param value The value (must be != 0) + * @return log2(value) * 2^24 + */ +extern unsigned int intlog2(u32 value); + +/** + * computes log10 of a value; the result is shifted left by 24 bits + * + * to use rational values you can use the following method: + * intlog10(value) = intlog10(value * 10^x) - x * 2^24 + * + * example: intlog10(1000) will give 3 << 24 = 3 * 2^24 + * due to the implementation intlog10(1000) might be not exactly 3 * 2^24 + * + * look at intlog2 for similar examples + * + * @param value The value (must be != 0) + * @return log10(value) * 2^24 + */ +extern unsigned int intlog10(u32 value); + +#endif diff --git a/drivers/media/dvb/dvb-usb/gp8psk-fe.c b/drivers/media/dvb/dvb-usb/gp8psk-fe.c new file mode 100644 index 000000000..6ccbdc9cd --- /dev/null +++ b/drivers/media/dvb/dvb-usb/gp8psk-fe.c @@ -0,0 +1,272 @@ +/* DVB USB compliant Linux driver for the + * - GENPIX 8pks/qpsk USB2.0 DVB-S module + * + * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com) + * + * Thanks to GENPIX for the sample code used to implement this module. + * + * This module is based off the vp7045 and vp702x modules + * + * 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, version 2. + * + * see Documentation/dvb/README.dvb-usb for more information + */ +#include "gp8psk.h" + +struct gp8psk_fe_state { + struct dvb_frontend fe; + + struct dvb_usb_device *d; + + u16 snr; + + unsigned long next_snr_check; +}; + +static int gp8psk_fe_read_status(struct dvb_frontend* fe, fe_status_t *status) +{ + struct gp8psk_fe_state *st = fe->demodulator_priv; + u8 lock; + + if (gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0, 0, &lock,1)) + return -EINVAL; + + if (lock) + *status = FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER; + else + *status = 0; + + return 0; +} + +/* not supported by this Frontend */ +static int gp8psk_fe_read_ber(struct dvb_frontend* fe, u32 *ber) +{ + (void) fe; + *ber = 0; + return 0; +} + +/* not supported by this Frontend */ +static int gp8psk_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc) +{ + (void) fe; + *unc = 0; + return 0; +} + +static int gp8psk_fe_read_snr(struct dvb_frontend* fe, u16 *snr) +{ + struct gp8psk_fe_state *st = fe->demodulator_priv; + u8 buf[2]; + + if (time_after(jiffies,st->next_snr_check)) { + gp8psk_usb_in_op(st->d,GET_SIGNAL_STRENGTH,0,0,buf,2); + *snr = (int)(buf[1]) << 8 | buf[0]; + /* snr is reported in dBu*256 */ + /* snr / 38.4 ~= 100% strength */ + /* snr * 17 returns 100% strength as 65535 */ + if (*snr <= 3855) + *snr = (*snr<<4) + *snr; // snr * 17 + else + *snr = 65535; + st->next_snr_check = jiffies + (10*HZ)/1000; + } else { + *snr = st->snr; + } + return 0; +} + +static int gp8psk_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength) +{ + return gp8psk_fe_read_snr(fe, strength); +} + +static int gp8psk_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune) +{ + tune->min_delay_ms = 800; + return 0; +} + +static int gp8psk_fe_set_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *fep) +{ + struct gp8psk_fe_state *state = fe->demodulator_priv; + u8 cmd[10]; + u32 freq = fep->frequency * 1000; + + cmd[4] = freq & 0xff; + cmd[5] = (freq >> 8) & 0xff; + cmd[6] = (freq >> 16) & 0xff; + cmd[7] = (freq >> 24) & 0xff; + + switch(fe->ops.info.type) { + case FE_QPSK: + cmd[0] = fep->u.qpsk.symbol_rate & 0xff; + cmd[1] = (fep->u.qpsk.symbol_rate >> 8) & 0xff; + cmd[2] = (fep->u.qpsk.symbol_rate >> 16) & 0xff; + cmd[3] = (fep->u.qpsk.symbol_rate >> 24) & 0xff; + cmd[8] = ADV_MOD_DVB_QPSK; + cmd[9] = 0x03; /*ADV_MOD_FEC_XXX*/ + break; + default: + // other modes are unsuported right now + cmd[0] = 0; + cmd[1] = 0; + cmd[2] = 0; + cmd[3] = 0; + cmd[8] = 0; + cmd[9] = 0; + break; + } + + gp8psk_usb_out_op(state->d,TUNE_8PSK,0,0,cmd,10); + + state->next_snr_check = jiffies; + + return 0; +} + +static int gp8psk_fe_get_frontend(struct dvb_frontend* fe, + struct dvb_frontend_parameters *fep) +{ + return 0; +} + + +static int gp8psk_fe_send_diseqc_msg (struct dvb_frontend* fe, + struct dvb_diseqc_master_cmd *m) +{ + struct gp8psk_fe_state *st = fe->demodulator_priv; + + deb_fe("%s\n",__FUNCTION__); + + if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0, + m->msg, m->msg_len)) { + return -EINVAL; + } + return 0; +} + +static int gp8psk_fe_send_diseqc_burst (struct dvb_frontend* fe, + fe_sec_mini_cmd_t burst) +{ + struct gp8psk_fe_state *st = fe->demodulator_priv; + u8 cmd; + + deb_fe("%s\n",__FUNCTION__); + + /* These commands are certainly wrong */ + cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01; + + if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, cmd, 0, + &cmd, 0)) { + return -EINVAL; + } + return 0; +} + +static int gp8psk_fe_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone) +{ + struct gp8psk_fe_state* state = fe->demodulator_priv; + + if (gp8psk_usb_out_op(state->d,SET_22KHZ_TONE, + (tone == SEC_TONE_ON), 0, NULL, 0)) { + return -EINVAL; + } + return 0; +} + +static int gp8psk_fe_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage) +{ + struct gp8psk_fe_state* state = fe->demodulator_priv; + + if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, + voltage == SEC_VOLTAGE_18, 0, NULL, 0)) { + return -EINVAL; + } + return 0; +} + +static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd) +{ + struct gp8psk_fe_state* state = fe->demodulator_priv; + u8 cmd = sw_cmd & 0x7f; + + if (gp8psk_usb_out_op(state->d,SET_DN_SWITCH, cmd, 0, + NULL, 0)) { + return -EINVAL; + } + if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, !!(sw_cmd & 0x80), + 0, NULL, 0)) { + return -EINVAL; + } + + return 0; +} + +static void gp8psk_fe_release(struct dvb_frontend* fe) +{ + struct gp8psk_fe_state *state = fe->demodulator_priv; + kfree(state); +} + +static struct dvb_frontend_ops gp8psk_fe_ops; + +struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d) +{ + struct gp8psk_fe_state *s = kzalloc(sizeof(struct gp8psk_fe_state), GFP_KERNEL); + if (s == NULL) + goto error; + + s->d = d; + memcpy(&s->fe.ops, &gp8psk_fe_ops, sizeof(struct dvb_frontend_ops)); + s->fe.demodulator_priv = s; + + goto success; +error: + return NULL; +success: + return &s->fe; +} + + +static struct dvb_frontend_ops gp8psk_fe_ops = { + .info = { + .name = "Genpix 8psk-USB DVB-S", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 100, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .symbol_rate_tolerance = 500, /* ppm */ + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK + }, + + .release = gp8psk_fe_release, + + .init = NULL, + .sleep = NULL, + + .set_frontend = gp8psk_fe_set_frontend, + .get_frontend = gp8psk_fe_get_frontend, + .get_tune_settings = gp8psk_fe_get_tune_settings, + + .read_status = gp8psk_fe_read_status, + .read_ber = gp8psk_fe_read_ber, + .read_signal_strength = gp8psk_fe_read_signal_strength, + .read_snr = gp8psk_fe_read_snr, + .read_ucblocks = gp8psk_fe_read_unc_blocks, + + .diseqc_send_master_cmd = gp8psk_fe_send_diseqc_msg, + .diseqc_send_burst = gp8psk_fe_send_diseqc_burst, + .set_tone = gp8psk_fe_set_tone, + .set_voltage = gp8psk_fe_set_voltage, + .dishnetwork_send_legacy_command = gp8psk_fe_send_legacy_dish_cmd, +}; diff --git a/drivers/media/dvb/dvb-usb/gp8psk.c b/drivers/media/dvb/dvb-usb/gp8psk.c new file mode 100644 index 000000000..9a98f3fda --- /dev/null +++ b/drivers/media/dvb/dvb-usb/gp8psk.c @@ -0,0 +1,256 @@ +/* DVB USB compliant Linux driver for the + * - GENPIX 8pks/qpsk USB2.0 DVB-S module + * + * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com) + * + * Thanks to GENPIX for the sample code used to implement this module. + * + * This module is based off the vp7045 and vp702x modules + * + * 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, version 2. + * + * see Documentation/dvb/README.dvb-usb for more information + */ +#include "gp8psk.h" + +/* debug */ +static char bcm4500_firmware[] = "dvb-usb-gp8psk-02.fw"; +int dvb_usb_gp8psk_debug; +module_param_named(debug,dvb_usb_gp8psk_debug, int, 0644); +MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS); + +int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) +{ + int ret = 0,try = 0; + + if ((ret = mutex_lock_interruptible(&d->usb_mutex))) + return ret; + + while (ret >= 0 && ret != blen && try < 3) { + ret = usb_control_msg(d->udev, + usb_rcvctrlpipe(d->udev,0), + req, + USB_TYPE_VENDOR | USB_DIR_IN, + value,index,b,blen, + 2000); + deb_info("reading number %d (ret: %d)\n",try,ret); + try++; + } + + if (ret < 0 || ret != blen) { + warn("usb in operation failed."); + ret = -EIO; + } else + ret = 0; + + deb_xfer("in: req. %x, val: %x, ind: %x, buffer: ",req,value,index); + debug_dump(b,blen,deb_xfer); + + mutex_unlock(&d->usb_mutex); + + return ret; +} + +int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, + u16 index, u8 *b, int blen) +{ + int ret; + + deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index); + debug_dump(b,blen,deb_xfer); + + if ((ret = mutex_lock_interruptible(&d->usb_mutex))) + return ret; + + if (usb_control_msg(d->udev, + usb_sndctrlpipe(d->udev,0), + req, + USB_TYPE_VENDOR | USB_DIR_OUT, + value,index,b,blen, + 2000) != blen) { + warn("usb out operation failed."); + ret = -EIO; + } else + ret = 0; + mutex_unlock(&d->usb_mutex); + + return ret; +} + +static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d) +{ + int ret; + const struct firmware *fw = NULL; + u8 *ptr, *buf; + if ((ret = request_firmware(&fw, bcm4500_firmware, + &d->udev->dev)) != 0) { + err("did not find the bcm4500 firmware file. (%s) " + "Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)", + bcm4500_firmware,ret); + return ret; + } + + ret = -EINVAL; + + if (gp8psk_usb_out_op(d, LOAD_BCM4500,1,0,NULL, 0)) + goto out_rel_fw; + + info("downloaidng bcm4500 firmware from file '%s'",bcm4500_firmware); + + ptr = fw->data; + buf = kmalloc(512, GFP_KERNEL | GFP_DMA); + + while (ptr[0] != 0xff) { + u16 buflen = ptr[0] + 4; + if (ptr + buflen >= fw->data + fw->size) { + err("failed to load bcm4500 firmware."); + goto out_free; + } + memcpy(buf, ptr, buflen); + if (dvb_usb_generic_write(d, buf, buflen)) { + err("failed to load bcm4500 firmware."); + goto out_free; + } + ptr += buflen; + } + + ret = 0; + +out_free: + kfree(buf); +out_rel_fw: + release_firmware(fw); + + return ret; +} + +static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + u8 status, buf; + if (onoff) { + gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1); + if (! (status & 0x01)) /* started */ + if (gp8psk_usb_in_op(d, BOOT_8PSK, 1, 0, &buf, 1)) + return -EINVAL; + + if (! (status & 0x02)) /* BCM4500 firmware loaded */ + if(gp8psk_load_bcm4500fw(d)) + return EINVAL; + + if (! (status & 0x04)) /* LNB Power */ + if (gp8psk_usb_in_op(d, START_INTERSIL, 1, 0, + &buf, 1)) + return EINVAL; + + /* Set DVB mode */ + if(gp8psk_usb_out_op(d, SET_DVB_MODE, 1, 0, NULL, 0)) + return -EINVAL; + gp8psk_usb_in_op(d, GET_8PSK_CONFIG,0,0,&status,1); + } else { + /* Turn off LNB power */ + if (gp8psk_usb_in_op(d, START_INTERSIL, 0, 0, &buf, 1)) + return EINVAL; + /* Turn off 8psk power */ + if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1)) + return -EINVAL; + + } + return 0; +} + + +static int gp8psk_streaming_ctrl(struct dvb_usb_device *d, int onoff) +{ + return gp8psk_usb_out_op(d, ARM_TRANSFER, onoff, 0 , NULL, 0); +} + +static int gp8psk_frontend_attach(struct dvb_usb_device *d) +{ + d->fe = gp8psk_fe_attach(d); + + return 0; +} + +static struct dvb_usb_properties gp8psk_properties; + +static int gp8psk_usb_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + return dvb_usb_device_init(intf,&gp8psk_properties,THIS_MODULE,NULL); +} + +static struct usb_device_id gp8psk_usb_table [] = { + { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_COLD) }, + { USB_DEVICE(USB_VID_GENPIX, USB_PID_GENPIX_8PSK_WARM) }, + { 0 }, +}; +MODULE_DEVICE_TABLE(usb, gp8psk_usb_table); + +static struct dvb_usb_properties gp8psk_properties = { + .caps = 0, + + .usb_ctrl = CYPRESS_FX2, + .firmware = "dvb-usb-gp8psk-01.fw", + + .streaming_ctrl = gp8psk_streaming_ctrl, + .power_ctrl = gp8psk_power_ctrl, + .frontend_attach = gp8psk_frontend_attach, + + .generic_bulk_ctrl_endpoint = 0x01, + /* parameter for the MPEG2-data transfer */ + .urb = { + .type = DVB_USB_BULK, + .count = 7, + .endpoint = 0x82, + .u = { + .bulk = { + .buffersize = 8192, + } + } + }, + + .num_device_descs = 1, + .devices = { + { .name = "Genpix 8PSK-USB DVB-S USB2.0 receiver", + .cold_ids = { &gp8psk_usb_table[0], NULL }, + .warm_ids = { &gp8psk_usb_table[1], NULL }, + }, + { 0 }, + } +}; + +/* usb specific object needed to register this driver with the usb subsystem */ +static struct usb_driver gp8psk_usb_driver = { + .name = "dvb_usb_gp8psk", + .probe = gp8psk_usb_probe, + .disconnect = dvb_usb_device_exit, + .id_table = gp8psk_usb_table, +}; + +/* module stuff */ +static int __init gp8psk_usb_module_init(void) +{ + int result; + if ((result = usb_register(&gp8psk_usb_driver))) { + err("usb_register failed. (%d)",result); + return result; + } + + return 0; +} + +static void __exit gp8psk_usb_module_exit(void) +{ + /* deregister this driver from the USB subsystem */ + usb_deregister(&gp8psk_usb_driver); +} + +module_init(gp8psk_usb_module_init); +module_exit(gp8psk_usb_module_exit); + +MODULE_AUTHOR("Alan Nisota <alannisota@gamil.com>"); +MODULE_DESCRIPTION("Driver for Genpix 8psk-USB DVB-S USB2.0"); +MODULE_VERSION("1.0"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/dvb-usb/gp8psk.h b/drivers/media/dvb/dvb-usb/gp8psk.h new file mode 100644 index 000000000..3eba70610 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/gp8psk.h @@ -0,0 +1,79 @@ +/* DVB USB compliant Linux driver for the + * - GENPIX 8pks/qpsk USB2.0 DVB-S module + * + * Copyright (C) 2006 Alan Nisota (alannisota@gmail.com) + * + * Thanks to GENPIX for the sample code used to implement this module. + * + * This module is based off the vp7045 and vp702x modules + * + * 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, version 2. + * + * see Documentation/dvb/README.dvb-usb for more information + */ +#ifndef _DVB_USB_GP8PSK_H_ +#define _DVB_USB_GP8PSK_H_ + +#define DVB_USB_LOG_PREFIX "gp8psk" +#include "dvb-usb.h" + +extern int dvb_usb_gp8psk_debug; +#define deb_info(args...) dprintk(dvb_usb_gp8psk_debug,0x01,args) +#define deb_xfer(args...) dprintk(dvb_usb_gp8psk_debug,0x02,args) +#define deb_rc(args...) dprintk(dvb_usb_gp8psk_debug,0x04,args) +#define deb_fe(args...) dprintk(dvb_usb_gp8psk_debug,0x08,args) +/* gp8psk commands */ + +/* Twinhan Vendor requests */ +#define TH_COMMAND_IN 0xC0 +#define TH_COMMAND_OUT 0xC1 + +/* command bytes */ +#define GET_8PSK_CONFIG 0x80 +#define SET_8PSK_CONFIG 0x81 +#define ARM_TRANSFER 0x85 +#define TUNE_8PSK 0x86 +#define GET_SIGNAL_STRENGTH 0x87 +#define LOAD_BCM4500 0x88 +#define BOOT_8PSK 0x89 +#define START_INTERSIL 0x8A +#define SET_LNB_VOLTAGE 0x8B +#define SET_22KHZ_TONE 0x8C +#define SEND_DISEQC_COMMAND 0x8D +#define SET_DVB_MODE 0x8E +#define SET_DN_SWITCH 0x8F +#define GET_SIGNAL_LOCK 0x90 + +/* Satellite modulation modes */ +#define ADV_MOD_DVB_QPSK 0 /* DVB-S QPSK */ +#define ADV_MOD_TURBO_QPSK 1 /* Turbo QPSK */ +#define ADV_MOD_TURBO_8PSK 2 /* Turbo 8PSK (also used for Trellis 8PSK) */ +#define ADV_MOD_TURBO_16QAM 3 /* Turbo 16QAM (also used for Trellis 8PSK) */ + +#define ADV_MOD_DCII_C_QPSK 4 /* Digicipher II Combo */ +#define ADV_MOD_DCII_I_QPSK 5 /* Digicipher II I-stream */ +#define ADV_MOD_DCII_Q_QPSK 6 /* Digicipher II Q-stream */ +#define ADV_MOD_DCII_C_OQPSK 7 /* Digicipher II offset QPSK */ +#define ADV_MOD_DSS_QPSK 8 /* DSS (DIRECTV) QPSK */ +#define ADV_MOD_DVB_BPSK 9 /* DVB-S BPSK */ + +#define GET_USB_SPEED 0x07 + #define USB_SPEED_LOW 0 + #define USB_SPEED_FULL 1 + #define USB_SPEED_HIGH 2 + +#define RESET_FX2 0x13 + +#define FW_VERSION_READ 0x0B +#define VENDOR_STRING_READ 0x0C +#define PRODUCT_STRING_READ 0x0D +#define FW_BCD_VERSION_READ 0x14 + +extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d); +extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); +extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, + u16 index, u8 *b, int blen); + +#endif diff --git a/drivers/media/dvb/frontends/isl6421.c b/drivers/media/dvb/frontends/isl6421.c new file mode 100644 index 000000000..58c34db31 --- /dev/null +++ b/drivers/media/dvb/frontends/isl6421.c @@ -0,0 +1,149 @@ +/* + * isl6421.h - driver for lnb supply and control ic ISL6421 + * + * Copyright (C) 2006 Andrew de Quincey + * Copyright (C) 2006 Oliver Endriss + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org + */ +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/string.h> +#include <linux/slab.h> + +#include "dvb_frontend.h" +#include "isl6421.h" + +struct isl6421 { + u8 config; + u8 override_or; + u8 override_and; + struct i2c_adapter *i2c; + u8 i2c_addr; + void (*release_chain)(struct dvb_frontend* fe); +}; + +static int isl6421_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv; + struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0, + .buf = &isl6421->config, + .len = sizeof(isl6421->config) }; + + isl6421->config &= ~(ISL6421_VSEL1 | ISL6421_EN1); + + switch(voltage) { + case SEC_VOLTAGE_OFF: + break; + case SEC_VOLTAGE_13: + isl6421->config |= ISL6421_EN1; + break; + case SEC_VOLTAGE_18: + isl6421->config |= (ISL6421_EN1 | ISL6421_VSEL1); + break; + default: + return -EINVAL; + }; + + isl6421->config |= isl6421->override_or; + isl6421->config &= isl6421->override_and; + + return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) +{ + struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv; + struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0, + .buf = &isl6421->config, + .len = sizeof(isl6421->config) }; + + if (arg) + isl6421->config |= ISL6421_LLC1; + else + isl6421->config &= ~ISL6421_LLC1; + + isl6421->config |= isl6421->override_or; + isl6421->config &= isl6421->override_and; + + return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static void isl6421_release(struct dvb_frontend *fe) +{ + struct isl6421 *isl6421 = (struct isl6421 *) fe->misc_priv; + + /* power off */ + isl6421_set_voltage(fe, SEC_VOLTAGE_OFF); + + /* free data & call next release routine */ + fe->ops.release = isl6421->release_chain; + kfree(fe->misc_priv); + fe->misc_priv = NULL; + if (fe->ops.release) + fe->ops.release(fe); +} + +int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr, + u8 override_set, u8 override_clear) +{ + struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL); + if (!isl6421) + return -ENOMEM; + + /* default configuration */ + isl6421->config = ISL6421_ISEL1; + isl6421->i2c = i2c; + isl6421->i2c_addr = i2c_addr; + fe->misc_priv = isl6421; + + /* bits which should be forced to '1' */ + isl6421->override_or = override_set; + + /* bits which should be forced to '0' */ + isl6421->override_and = ~override_clear; + + /* detect if it is present or not */ + if (isl6421_set_voltage(fe, SEC_VOLTAGE_OFF)) { + kfree(isl6421); + fe->misc_priv = NULL; + return -EIO; + } + + /* install release callback */ + isl6421->release_chain = fe->ops.release; + fe->ops.release = isl6421_release; + + /* override frontend ops */ + fe->ops.set_voltage = isl6421_set_voltage; + fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage; + + return 0; +} +EXPORT_SYMBOL(isl6421_attach); + +MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6421"); +MODULE_AUTHOR("Andrew de Quincey & Oliver Endriss"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/isl6421.h b/drivers/media/dvb/frontends/isl6421.h new file mode 100644 index 000000000..675f80a19 --- /dev/null +++ b/drivers/media/dvb/frontends/isl6421.h @@ -0,0 +1,46 @@ +/* + * isl6421.h - driver for lnb supply and control ic ISL6421 + * + * Copyright (C) 2006 Andrew de Quincey + * Copyright (C) 2006 Oliver Endriss + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org + */ + +#ifndef _ISL6421_H +#define _ISL6421_H + +#include <linux/dvb/frontend.h> + +/* system register bits */ +#define ISL6421_OLF1 0x01 +#define ISL6421_EN1 0x02 +#define ISL6421_VSEL1 0x04 +#define ISL6421_LLC1 0x08 +#define ISL6421_ENT1 0x10 +#define ISL6421_ISEL1 0x20 +#define ISL6421_DCL 0x40 + +/* override_set and override_clear control which system register bits (above) to always set & clear */ +extern int isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr, + u8 override_set, u8 override_clear); + +#endif diff --git a/drivers/media/dvb/frontends/lg_h06xf.h b/drivers/media/dvb/frontends/lg_h06xf.h new file mode 100644 index 000000000..754d51d11 --- /dev/null +++ b/drivers/media/dvb/frontends/lg_h06xf.h @@ -0,0 +1,64 @@ +/* + * lg_h06xf.h - ATSC Tuner support for LG TDVS-H06xF + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _LG_H06XF_H_ +#define _LG_H06XF_H_ +#include "dvb-pll.h" + +static int lg_h06xf_pll_set(struct dvb_frontend* fe, struct i2c_adapter* i2c_adap, + struct dvb_frontend_parameters* params) +{ + u8 buf[4]; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, + .buf = buf, .len = sizeof(buf) }; + int err; + + dvb_pll_configure(&dvb_pll_lg_tdvs_h06xf, buf, params->frequency, 0); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "lg_h06xf: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + /* Set the Auxiliary Byte. */ + buf[0] = buf[2]; + buf[0] &= ~0x20; + buf[0] |= 0x18; + buf[1] = 0x50; + msg.len = 2; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if ((err = i2c_transfer(i2c_adap, &msg, 1)) != 1) { + printk(KERN_WARNING "lg_h06xf: %s error " + "(addr %02x <- %02x, err = %i)\n", + __FUNCTION__, buf[0], buf[1], err); + if (err < 0) + return err; + else + return -EREMOTEIO; + } + + return 0; +} +#endif diff --git a/drivers/media/dvb/frontends/lnbp21.c b/drivers/media/dvb/frontends/lnbp21.c new file mode 100644 index 000000000..e933edc8d --- /dev/null +++ b/drivers/media/dvb/frontends/lnbp21.c @@ -0,0 +1,145 @@ +/* + * lnbp21.h - driver for lnb supply and control ic lnbp21 + * + * Copyright (C) 2006 Oliver Endriss + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org + */ +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/string.h> +#include <linux/slab.h> + +#include "dvb_frontend.h" +#include "lnbp21.h" + +struct lnbp21 { + u8 config; + u8 override_or; + u8 override_and; + struct i2c_adapter *i2c; + void (*release_chain)(struct dvb_frontend* fe); +}; + +static int lnbp21_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) +{ + struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; + struct i2c_msg msg = { .addr = 0x08, .flags = 0, + .buf = &lnbp21->config, + .len = sizeof(lnbp21->config) }; + + lnbp21->config &= ~(LNBP21_VSEL | LNBP21_EN); + + switch(voltage) { + case SEC_VOLTAGE_OFF: + break; + case SEC_VOLTAGE_13: + lnbp21->config |= LNBP21_EN; + break; + case SEC_VOLTAGE_18: + lnbp21->config |= (LNBP21_EN | LNBP21_VSEL); + break; + default: + return -EINVAL; + }; + + lnbp21->config |= lnbp21->override_or; + lnbp21->config &= lnbp21->override_and; + + return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static int lnbp21_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg) +{ + struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; + struct i2c_msg msg = { .addr = 0x08, .flags = 0, + .buf = &lnbp21->config, + .len = sizeof(lnbp21->config) }; + + if (arg) + lnbp21->config |= LNBP21_LLC; + else + lnbp21->config &= ~LNBP21_LLC; + + lnbp21->config |= lnbp21->override_or; + lnbp21->config &= lnbp21->override_and; + + return (i2c_transfer(lnbp21->i2c, &msg, 1) == 1) ? 0 : -EIO; +} + +static void lnbp21_release(struct dvb_frontend *fe) +{ + struct lnbp21 *lnbp21 = (struct lnbp21 *) fe->misc_priv; + + /* LNBP power off */ + lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF); + + /* free data & call next release routine */ + fe->ops.release = lnbp21->release_chain; + kfree(fe->misc_priv); + fe->misc_priv = NULL; + if (fe->ops.release) + fe->ops.release(fe); +} + +int lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear) +{ + struct lnbp21 *lnbp21 = kmalloc(sizeof(struct lnbp21), GFP_KERNEL); + if (!lnbp21) + return -ENOMEM; + + /* default configuration */ + lnbp21->config = LNBP21_ISEL; + lnbp21->i2c = i2c; + fe->misc_priv = lnbp21; + + /* bits which should be forced to '1' */ + lnbp21->override_or = override_set; + + /* bits which should be forced to '0' */ + lnbp21->override_and = ~override_clear; + + /* detect if it is present or not */ + if (lnbp21_set_voltage(fe, SEC_VOLTAGE_OFF)) { + kfree(lnbp21); + fe->misc_priv = NULL; + return -EIO; + } + + /* install release callback */ + lnbp21->release_chain = fe->ops.release; + fe->ops.release = lnbp21_release; + + /* override frontend ops */ + fe->ops.set_voltage = lnbp21_set_voltage; + fe->ops.enable_high_lnb_voltage = lnbp21_enable_high_lnb_voltage; + + return 0; +} +EXPORT_SYMBOL(lnbp21_attach); + +MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp21"); +MODULE_AUTHOR("Oliver Endriss"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c new file mode 100644 index 000000000..f7e33f9ee --- /dev/null +++ b/drivers/media/radio/dsbr100.c @@ -0,0 +1,430 @@ +/* A driver for the D-Link DSB-R100 USB radio. The R100 plugs + into both the USB and an analog audio input, so this thing + only deals with initialisation and frequency setting, the + audio data has to be handled by a sound driver. + + Major issue: I can't find out where the device reports the signal + strength, and indeed the windows software appearantly just looks + at the stereo indicator as well. So, scanning will only find + stereo stations. Sad, but I can't help it. + + Also, the windows program sends oodles of messages over to the + device, and I couldn't figure out their meaning. My suspicion + is that they don't have any:-) + + You might find some interesting stuff about this module at + http://unimut.fsk.uni-heidelberg.de/unimut/demi/dsbr + + Copyright (c) 2000 Markus Demleitner <msdemlei@cl.uni-heidelberg.de> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + History: + + Version 0.40: + Markus: Updates for 2.6.x kernels, code layout changes, name sanitizing + + Version 0.30: + Markus: Updates for 2.5.x kernel and more ISO compliant source + + Version 0.25: + PSL and Markus: Cleanup, radio now doesn't stop on device close + + Version 0.24: + Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally + right. Some minor cleanup, improved standalone compilation + + Version 0.23: + Markus: Sign extension bug fixed by declaring transfer_buffer unsigned + + Version 0.22: + Markus: Some (brown bag) cleanup in what VIDIOCSTUNER returns, + thanks to Mike Cox for pointing the problem out. + + Version 0.21: + Markus: Minor cleanup, warnings if something goes wrong, lame attempt + to adhere to Documentation/CodingStyle + + Version 0.2: + Brad Hards <bradh@dynamite.com.au>: Fixes to make it work as non-module + Markus: Copyright clarification + + Version 0.01: Markus: initial release + +*/ + + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/input.h> +#include <linux/videodev.h> +#include <media/v4l2-common.h> +#include <linux/usb.h> +#include <linux/smp_lock.h> + +/* + * Version Information + */ +#define DRIVER_VERSION "v0.40" +#define DRIVER_AUTHOR "Markus Demleitner <msdemlei@tucana.harvard.edu>" +#define DRIVER_DESC "D-Link DSB-R100 USB FM radio driver" + +#define DSB100_VENDOR 0x04b4 +#define DSB100_PRODUCT 0x1002 + +/* Commands the device appears to understand */ +#define DSB100_TUNE 1 +#define DSB100_ONOFF 2 + +#define TB_LEN 16 + +/* Frequency limits in MHz -- these are European values. For Japanese +devices, that would be 76 and 91. */ +#define FREQ_MIN 87.5 +#define FREQ_MAX 108.0 +#define FREQ_MUL 16000 + + +static int usb_dsbr100_probe(struct usb_interface *intf, + const struct usb_device_id *id); +static void usb_dsbr100_disconnect(struct usb_interface *intf); +static int usb_dsbr100_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); +static int usb_dsbr100_open(struct inode *inode, struct file *file); +static int usb_dsbr100_close(struct inode *inode, struct file *file); + +static int radio_nr = -1; +module_param(radio_nr, int, 0); + +/* Data for one (physical) device */ +typedef struct { + struct usb_device *usbdev; + struct video_device *videodev; + unsigned char transfer_buffer[TB_LEN]; + int curfreq; + int stereo; + int users; + int removed; +} dsbr100_device; + + +/* File system interface */ +static struct file_operations usb_dsbr100_fops = { + .owner = THIS_MODULE, + .open = usb_dsbr100_open, + .release = usb_dsbr100_close, + .ioctl = usb_dsbr100_ioctl, + .compat_ioctl = v4l_compat_ioctl32, + .llseek = no_llseek, +}; + +/* V4L interface */ +static struct video_device dsbr100_videodev_template= +{ + .owner = THIS_MODULE, + .name = "D-Link DSB-R 100", + .type = VID_TYPE_TUNER, + .hardware = VID_HARDWARE_AZTECH, + .fops = &usb_dsbr100_fops, + .release = video_device_release, +}; + +static struct usb_device_id usb_dsbr100_device_table [] = { + { USB_DEVICE(DSB100_VENDOR, DSB100_PRODUCT) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, usb_dsbr100_device_table); + +/* USB subsystem interface */ +static struct usb_driver usb_dsbr100_driver = { + .name = "dsbr100", + .probe = usb_dsbr100_probe, + .disconnect = usb_dsbr100_disconnect, + .id_table = usb_dsbr100_device_table, +}; + +/* Low-level device interface begins here */ + +/* switch on radio */ +static int dsbr100_start(dsbr100_device *radio) +{ + if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x00, 0xC7, radio->transfer_buffer, 8, 300)<0 || + usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + DSB100_ONOFF, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x01, 0x00, radio->transfer_buffer, 8, 300)<0) + return -1; + return (radio->transfer_buffer)[0]; +} + + +/* switch off radio */ +static int dsbr100_stop(dsbr100_device *radio) +{ + if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x16, 0x1C, radio->transfer_buffer, 8, 300)<0 || + usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + DSB100_ONOFF, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x00, 0x00, radio->transfer_buffer, 8, 300)<0) + return -1; + return (radio->transfer_buffer)[0]; +} + +/* set a frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */ +static int dsbr100_setfreq(dsbr100_device *radio, int freq) +{ + freq = (freq/16*80)/1000+856; + if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + DSB100_TUNE, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + (freq>>8)&0x00ff, freq&0xff, + radio->transfer_buffer, 8, 300)<0 || + usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 || + usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x00, 0x24, radio->transfer_buffer, 8, 300)<0) { + radio->stereo = -1; + return -1; + } + radio->stereo = ! ((radio->transfer_buffer)[0]&0x01); + return (radio->transfer_buffer)[0]; +} + +/* return the device status. This is, in effect, just whether it +sees a stereo signal or not. Pity. */ +static void dsbr100_getstat(dsbr100_device *radio) +{ + if (usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), + USB_REQ_GET_STATUS, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x00 , 0x24, radio->transfer_buffer, 8, 300)<0) + radio->stereo = -1; + else + radio->stereo = ! (radio->transfer_buffer[0]&0x01); +} + + +/* USB subsystem interface begins here */ + +/* check if the device is present and register with v4l and +usb if it is */ +static int usb_dsbr100_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + dsbr100_device *radio; + + if (!(radio = kmalloc(sizeof(dsbr100_device), GFP_KERNEL))) + return -ENOMEM; + if (!(radio->videodev = video_device_alloc())) { + kfree(radio); + return -ENOMEM; + } + memcpy(radio->videodev, &dsbr100_videodev_template, + sizeof(dsbr100_videodev_template)); + radio->removed = 0; + radio->users = 0; + radio->usbdev = interface_to_usbdev(intf); + radio->curfreq = FREQ_MIN*FREQ_MUL; + video_set_drvdata(radio->videodev, radio); + if (video_register_device(radio->videodev, VFL_TYPE_RADIO, + radio_nr)) { + warn("Could not register video device"); + video_device_release(radio->videodev); + kfree(radio); + return -EIO; + } + usb_set_intfdata(intf, radio); + return 0; +} + +/* handle unplugging of the device, release data structures +if nothing keeps us from doing it. If something is still +keeping us busy, the release callback of v4l will take care +of releasing it. stv680.c does not relase its private +data, so I don't do this here either. Checking out the +code I'd expect I better did that, but if there's a memory +leak here it's tiny (~50 bytes per disconnect) */ +static void usb_dsbr100_disconnect(struct usb_interface *intf) +{ + dsbr100_device *radio = usb_get_intfdata(intf); + + usb_set_intfdata (intf, NULL); + if (radio) { + video_unregister_device(radio->videodev); + radio->videodev = NULL; + if (radio->users) { + kfree(radio); + } else { + radio->removed = 1; + } + } +} + + +/* Video for Linux interface */ + +static int usb_dsbr100_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + dsbr100_device *radio=video_get_drvdata(video_devdata(file)); + + if (!radio) + return -EIO; + + switch(cmd) { + case VIDIOCGCAP: { + struct video_capability *v = arg; + + memset(v, 0, sizeof(*v)); + v->type = VID_TYPE_TUNER; + v->channels = 1; + v->audios = 1; + strcpy(v->name, "D-Link R-100 USB FM Radio"); + return 0; + } + case VIDIOCGTUNER: { + struct video_tuner *v = arg; + + dsbr100_getstat(radio); + if(v->tuner) /* Only 1 tuner */ + return -EINVAL; + v->rangelow = FREQ_MIN*FREQ_MUL; + v->rangehigh = FREQ_MAX*FREQ_MUL; + v->flags = VIDEO_TUNER_LOW; + v->mode = VIDEO_MODE_AUTO; + v->signal = radio->stereo*0x7000; + /* Don't know how to get signal strength */ + v->flags |= VIDEO_TUNER_STEREO_ON*radio->stereo; + strcpy(v->name, "DSB R-100"); + return 0; + } + case VIDIOCSTUNER: { + struct video_tuner *v = arg; + + if(v->tuner!=0) + return -EINVAL; + /* Only 1 tuner so no setting needed ! */ + return 0; + } + case VIDIOCGFREQ: { + int *freq = arg; + + if (radio->curfreq==-1) + return -EINVAL; + *freq = radio->curfreq; + return 0; + } + case VIDIOCSFREQ: { + int *freq = arg; + + radio->curfreq = *freq; + if (dsbr100_setfreq(radio, radio->curfreq)==-1) + warn("Set frequency failed"); + return 0; + } + case VIDIOCGAUDIO: { + struct video_audio *v = arg; + + memset(v, 0, sizeof(*v)); + v->flags |= VIDEO_AUDIO_MUTABLE; + v->mode = VIDEO_SOUND_STEREO; + v->volume = 1; + v->step = 1; + strcpy(v->name, "Radio"); + return 0; + } + case VIDIOCSAUDIO: { + struct video_audio *v = arg; + + if (v->audio) + return -EINVAL; + if (v->flags&VIDEO_AUDIO_MUTE) { + if (dsbr100_stop(radio)==-1) + warn("Radio did not respond properly"); + } + else + if (dsbr100_start(radio)==-1) + warn("Radio did not respond properly"); + return 0; + } + default: + return -ENOIOCTLCMD; + } +} + +static int usb_dsbr100_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + return video_usercopy(inode, file, cmd, arg, usb_dsbr100_do_ioctl); +} + +static int usb_dsbr100_open(struct inode *inode, struct file *file) +{ + dsbr100_device *radio=video_get_drvdata(video_devdata(file)); + + radio->users = 1; + if (dsbr100_start(radio)<0) { + warn("Radio did not start up properly"); + radio->users = 0; + return -EIO; + } + dsbr100_setfreq(radio, radio->curfreq); + return 0; +} + +static int usb_dsbr100_close(struct inode *inode, struct file *file) +{ + dsbr100_device *radio=video_get_drvdata(video_devdata(file)); + + if (!radio) + return -ENODEV; + radio->users = 0; + if (radio->removed) { + kfree(radio); + } + return 0; +} + +static int __init dsbr100_init(void) +{ + int retval = usb_register(&usb_dsbr100_driver); + info(DRIVER_VERSION ":" DRIVER_DESC); + return retval; +} + +static void __exit dsbr100_exit(void) +{ + usb_deregister(&usb_dsbr100_driver); +} + +module_init (dsbr100_init); +module_exit (dsbr100_exit); + +MODULE_AUTHOR( DRIVER_AUTHOR ); +MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/video/bt866.c b/drivers/media/video/bt866.c new file mode 100644 index 000000000..05e42bbcf --- /dev/null +++ b/drivers/media/video/bt866.c @@ -0,0 +1,377 @@ +/* + bt866 - BT866 Digital Video Encoder (Rockwell Part) + + Copyright (C) 1999 Mike Bernson <mike@mlb.org> + Copyright (C) 1998 Dave Perks <dperks@ibm.net> + + Modifications for LML33/DC10plus unified driver + Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx> + + This code was modify/ported from the saa7111 driver written + by Dave Perks. + + This code was adapted for the bt866 by Christer Weinigel and ported + to 2.6 by Martin Samuelsson. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/fs.h> +#include <linux/kernel.h> +#include <linux/major.h> +#include <linux/slab.h> +#include <linux/mm.h> +#include <linux/pci.h> +#include <linux/signal.h> +#include <asm/io.h> +#include <asm/pgtable.h> +#include <asm/page.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/i2c.h> + +#include <linux/videodev.h> +#include <asm/uaccess.h> + +#include <linux/video_encoder.h> + +MODULE_LICENSE("GPL"); + +#define BT866_DEVNAME "bt866" +#define I2C_BT866 0x88 + +MODULE_LICENSE("GPL"); + +#define DEBUG(x) /* Debug driver */ + +/* ----------------------------------------------------------------------- */ + +struct bt866 { + struct i2c_client *i2c; + int addr; + unsigned char reg[128]; + + int norm; + int enable; + int bright; + int contrast; + int hue; + int sat; +}; + +static int bt866_write(struct bt866 *dev, + unsigned char subaddr, unsigned char data); + +static int bt866_do_command(struct bt866 *encoder, + unsigned int cmd, void *arg) +{ + switch (cmd) { + case ENCODER_GET_CAPABILITIES: + { + struct video_encoder_capability *cap = arg; + + DEBUG(printk + (KERN_INFO "%s: get capabilities\n", + encoder->i2c->name)); + + cap->flags + = VIDEO_ENCODER_PAL + | VIDEO_ENCODER_NTSC + | VIDEO_ENCODER_CCIR; + cap->inputs = 2; + cap->outputs = 1; + } + break; + + case ENCODER_SET_NORM: + { + int *iarg = arg; + + DEBUG(printk(KERN_INFO "%s: set norm %d\n", + encoder->i2c->name, *iarg)); + + switch (*iarg) { + + case VIDEO_MODE_NTSC: + break; + + case VIDEO_MODE_PAL: + break; + + default: + return -EINVAL; + + } + encoder->norm = *iarg; + } + break; + + case ENCODER_SET_INPUT: + { + int *iarg = arg; + static const __u8 init[] = { + 0xc8, 0xcc, /* CRSCALE */ + 0xca, 0x91, /* CBSCALE */ + 0xcc, 0x24, /* YC16 | OSDNUM */ + 0xda, 0x00, /* */ + 0xdc, 0x24, /* SETMODE | PAL */ + 0xde, 0x02, /* EACTIVE */ + + /* overlay colors */ + 0x70, 0xEB, 0x90, 0x80, 0xB0, 0x80, /* white */ + 0x72, 0xA2, 0x92, 0x8E, 0xB2, 0x2C, /* yellow */ + 0x74, 0x83, 0x94, 0x2C, 0xB4, 0x9C, /* cyan */ + 0x76, 0x70, 0x96, 0x3A, 0xB6, 0x48, /* green */ + 0x78, 0x54, 0x98, 0xC6, 0xB8, 0xB8, /* magenta */ + 0x7A, 0x41, 0x9A, 0xD4, 0xBA, 0x64, /* red */ + 0x7C, 0x23, 0x9C, 0x72, 0xBC, 0xD4, /* blue */ + 0x7E, 0x10, 0x9E, 0x80, 0xBE, 0x80, /* black */ + + 0x60, 0xEB, 0x80, 0x80, 0xc0, 0x80, /* white */ + 0x62, 0xA2, 0x82, 0x8E, 0xc2, 0x2C, /* yellow */ + 0x64, 0x83, 0x84, 0x2C, 0xc4, 0x9C, /* cyan */ + 0x66, 0x70, 0x86, 0x3A, 0xc6, 0x48, /* green */ + 0x68, 0x54, 0x88, 0xC6, 0xc8, 0xB8, /* magenta */ + 0x6A, 0x41, 0x8A, 0xD4, 0xcA, 0x64, /* red */ + 0x6C, 0x23, 0x8C, 0x72, 0xcC, 0xD4, /* blue */ + 0x6E, 0x10, 0x8E, 0x80, 0xcE, 0x80, /* black */ + }; + int i; + u8 val; + + for (i = 0; i < ARRAY_SIZE(init) / 2; i += 2) + bt866_write(encoder, init[i], init[i+1]); + + val = encoder->reg[0xdc]; + + if (*iarg == 0) + val |= 0x40; /* CBSWAP */ + else + val &= ~0x40; /* !CBSWAP */ + + bt866_write(encoder, 0xdc, val); + + val = encoder->reg[0xcc]; + if (*iarg == 2) + val |= 0x01; /* OSDBAR */ + else + val &= ~0x01; /* !OSDBAR */ + bt866_write(encoder, 0xcc, val); + + DEBUG(printk(KERN_INFO "%s: set input %d\n", + encoder->i2c->name, *iarg)); + + switch (*iarg) { + case 0: + break; + case 1: + break; + default: + return -EINVAL; + + } + } + break; + + case ENCODER_SET_OUTPUT: + { + int *iarg = arg; + + DEBUG(printk(KERN_INFO "%s: set output %d\n", + encoder->i2c->name, *iarg)); + + /* not much choice of outputs */ + if (*iarg != 0) + return -EINVAL; + } + break; + + case ENCODER_ENABLE_OUTPUT: + { + int *iarg = arg; + encoder->enable = !!*iarg; + + DEBUG(printk + (KERN_INFO "%s: enable output %d\n", + encoder->i2c->name, encoder->enable)); + } + break; + + case 4711: + { + int *iarg = arg; + __u8 val; + + printk("bt866: square = %d\n", *iarg); + + val = encoder->reg[0xdc]; + if (*iarg) + val |= 1; /* SQUARE */ + else + val &= ~1; /* !SQUARE */ + bt866_write(encoder, 0xdc, val); + break; + } + + default: + return -EINVAL; + } + + return 0; +} + +static int bt866_write(struct bt866 *encoder, + unsigned char subaddr, unsigned char data) +{ + unsigned char buffer[2]; + int err; + + buffer[0] = subaddr; + buffer[1] = data; + + encoder->reg[subaddr] = data; + + DEBUG(printk + ("%s: write 0x%02X = 0x%02X\n", + encoder->i2c->name, subaddr, data)); + + for (err = 0; err < 3;) { + if (i2c_master_send(encoder->i2c, buffer, 2) == 2) + break; + err++; + printk(KERN_WARNING "%s: I/O error #%d " + "(write 0x%02x/0x%02x)\n", + encoder->i2c->name, err, encoder->addr, subaddr); + schedule_timeout_interruptible(HZ/10); + } + if (err == 3) { + printk(KERN_WARNING "%s: giving up\n", + encoder->i2c->name); + return -1; + } + + return 0; +} + +static int bt866_attach(struct i2c_adapter *adapter); +static int bt866_detach(struct i2c_client *client); +static int bt866_command(struct i2c_client *client, + unsigned int cmd, void *arg); + + +/* Addresses to scan */ +static unsigned short normal_i2c[] = {I2C_BT866>>1, I2C_CLIENT_END}; +static unsigned short probe[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; +static unsigned short ignore[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; + +static struct i2c_client_address_data addr_data = { + normal_i2c, + probe, + ignore, +}; + +static struct i2c_driver i2c_driver_bt866 = { + .driver.name = BT866_DEVNAME, + .id = I2C_DRIVERID_BT866, + .attach_adapter = bt866_attach, + .detach_client = bt866_detach, + .command = bt866_command +}; + + +static struct i2c_client bt866_client_tmpl = +{ + .name = "(nil)", + .addr = 0, + .adapter = NULL, + .driver = &i2c_driver_bt866, + .usage_count = 0 +}; + +static int bt866_found_proc(struct i2c_adapter *adapter, + int addr, int kind) +{ + struct bt866 *encoder; + struct i2c_client *client; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (client == NULL) + return -ENOMEM; + memcpy(client, &bt866_client_tmpl, sizeof(*client)); + + encoder = kzalloc(sizeof(*encoder), GFP_KERNEL); + if (encoder == NULL) { + kfree(client); + return -ENOMEM; + } + + i2c_set_clientdata(client, encoder); + client->adapter = adapter; + client->addr = addr; + sprintf(client->name, "%s-%02x", BT866_DEVNAME, adapter->id); + + encoder->i2c = client; + encoder->addr = addr; + //encoder->encoder_type = ENCODER_TYPE_UNKNOWN; + + /* initialize */ + + i2c_attach_client(client); + + return 0; +} + +static int bt866_attach(struct i2c_adapter *adapter) +{ + if (adapter->id == I2C_HW_B_ZR36067) + return i2c_probe(adapter, &addr_data, bt866_found_proc); + return 0; +} + +static int bt866_detach(struct i2c_client *client) +{ + struct bt866 *encoder = i2c_get_clientdata(client); + + i2c_detach_client(client); + kfree(encoder); + kfree(client); + + return 0; +} + +static int bt866_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + struct bt866 *encoder = i2c_get_clientdata(client); + return bt866_do_command(encoder, cmd, arg); +} + +static int __devinit bt866_init(void) +{ + i2c_add_driver(&i2c_driver_bt866); + return 0; +} + +static void __devexit bt866_exit(void) +{ + i2c_del_driver(&i2c_driver_bt866); +} + +module_init(bt866_init); +module_exit(bt866_exit); diff --git a/drivers/media/video/cx2341x.c b/drivers/media/video/cx2341x.c new file mode 100644 index 000000000..65f00fc08 --- /dev/null +++ b/drivers/media/video/cx2341x.c @@ -0,0 +1,932 @@ +/* + * cx2341x - generic code for cx23415/6 based devices + * + * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/types.h> +#include <linux/videodev2.h> +#include <linux/i2c.h> + +#include <media/tuner.h> +#include <media/cx2341x.h> +#include <media/v4l2-common.h> + +MODULE_DESCRIPTION("cx23415/6 driver"); +MODULE_AUTHOR("Hans Verkuil"); +MODULE_LICENSE("GPL"); + +static int debug = 0; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Debug level (0-1)"); + +const u32 cx2341x_mpeg_ctrls[] = { + V4L2_CID_MPEG_CLASS, + V4L2_CID_MPEG_STREAM_TYPE, + V4L2_CID_MPEG_STREAM_VBI_FMT, + V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, + V4L2_CID_MPEG_AUDIO_ENCODING, + V4L2_CID_MPEG_AUDIO_L2_BITRATE, + V4L2_CID_MPEG_AUDIO_MODE, + V4L2_CID_MPEG_AUDIO_MODE_EXTENSION, + V4L2_CID_MPEG_AUDIO_EMPHASIS, + V4L2_CID_MPEG_AUDIO_CRC, + V4L2_CID_MPEG_VIDEO_ENCODING, + V4L2_CID_MPEG_VIDEO_ASPECT, + V4L2_CID_MPEG_VIDEO_B_FRAMES, + V4L2_CID_MPEG_VIDEO_GOP_SIZE, + V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, + V4L2_CID_MPEG_VIDEO_PULLDOWN, + V4L2_CID_MPEG_VIDEO_BITRATE_MODE, + V4L2_CID_MPEG_VIDEO_BITRATE, + V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, + V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, + V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE, + V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER, + V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE, + V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE, + V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE, + V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER, + V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE, + V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM, + V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP, + V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM, + V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP, + 0 +}; + + +/* Map the control ID to the correct field in the cx2341x_mpeg_params + struct. Return -EINVAL if the ID is unknown, else return 0. */ +static int cx2341x_get_ctrl(struct cx2341x_mpeg_params *params, + struct v4l2_ext_control *ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + ctrl->value = params->audio_sampling_freq; + break; + case V4L2_CID_MPEG_AUDIO_ENCODING: + ctrl->value = params->audio_encoding; + break; + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: + ctrl->value = params->audio_l2_bitrate; + break; + case V4L2_CID_MPEG_AUDIO_MODE: + ctrl->value = params->audio_mode; + break; + case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: + ctrl->value = params->audio_mode_extension; + break; + case V4L2_CID_MPEG_AUDIO_EMPHASIS: + ctrl->value = params->audio_emphasis; + break; + case V4L2_CID_MPEG_AUDIO_CRC: + ctrl->value = params->audio_crc; + break; + case V4L2_CID_MPEG_VIDEO_ENCODING: + ctrl->value = params->video_encoding; + break; + case V4L2_CID_MPEG_VIDEO_ASPECT: + ctrl->value = params->video_aspect; + break; + case V4L2_CID_MPEG_VIDEO_B_FRAMES: + ctrl->value = params->video_b_frames; + break; + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + ctrl->value = params->video_gop_size; + break; + case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: + ctrl->value = params->video_gop_closure; + break; + case V4L2_CID_MPEG_VIDEO_PULLDOWN: + ctrl->value = params->video_pulldown; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + ctrl->value = params->video_bitrate_mode; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: + ctrl->value = params->video_bitrate; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + ctrl->value = params->video_bitrate_peak; + break; + case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: + ctrl->value = params->video_temporal_decimation; + break; + case V4L2_CID_MPEG_STREAM_TYPE: + ctrl->value = params->stream_type; + break; + case V4L2_CID_MPEG_STREAM_VBI_FMT: + ctrl->value = params->stream_vbi_fmt; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: + ctrl->value = params->video_spatial_filter_mode; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: + ctrl->value = params->video_spatial_filter; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: + ctrl->value = params->video_luma_spatial_filter_type; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: + ctrl->value = params->video_chroma_spatial_filter_type; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: + ctrl->value = params->video_temporal_filter_mode; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: + ctrl->value = params->video_temporal_filter; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: + ctrl->value = params->video_median_filter_type; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: + ctrl->value = params->video_luma_median_filter_top; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: + ctrl->value = params->video_luma_median_filter_bottom; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: + ctrl->value = params->video_chroma_median_filter_top; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: + ctrl->value = params->video_chroma_median_filter_bottom; + break; + default: + return -EINVAL; + } + return 0; +} + +/* Map the control ID to the correct field in the cx2341x_mpeg_params + struct. Return -EINVAL if the ID is unknown, else return 0. */ +static int cx2341x_set_ctrl(struct cx2341x_mpeg_params *params, + struct v4l2_ext_control *ctrl) +{ + switch (ctrl->id) { + case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: + params->audio_sampling_freq = ctrl->value; + break; + case V4L2_CID_MPEG_AUDIO_ENCODING: + params->audio_encoding = ctrl->value; + break; + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: + params->audio_l2_bitrate = ctrl->value; + break; + case V4L2_CID_MPEG_AUDIO_MODE: + params->audio_mode = ctrl->value; + break; + case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: + params->audio_mode_extension = ctrl->value; + break; + case V4L2_CID_MPEG_AUDIO_EMPHASIS: + params->audio_emphasis = ctrl->value; + break; + case V4L2_CID_MPEG_AUDIO_CRC: + params->audio_crc = ctrl->value; + break; + case V4L2_CID_MPEG_VIDEO_ASPECT: + params->video_aspect = ctrl->value; + break; + case V4L2_CID_MPEG_VIDEO_B_FRAMES: { + int b = ctrl->value + 1; + int gop = params->video_gop_size; + params->video_b_frames = ctrl->value; + params->video_gop_size = b * ((gop + b - 1) / b); + /* Max GOP size = 34 */ + while (params->video_gop_size > 34) + params->video_gop_size -= b; + break; + } + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: { + int b = params->video_b_frames + 1; + int gop = ctrl->value; + params->video_gop_size = b * ((gop + b - 1) / b); + /* Max GOP size = 34 */ + while (params->video_gop_size > 34) + params->video_gop_size -= b; + ctrl->value = params->video_gop_size; + break; + } + case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: + params->video_gop_closure = ctrl->value; + break; + case V4L2_CID_MPEG_VIDEO_PULLDOWN: + params->video_pulldown = ctrl->value; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + /* MPEG-1 only allows CBR */ + if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1 && + ctrl->value != V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) + return -EINVAL; + params->video_bitrate_mode = ctrl->value; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE: + params->video_bitrate = ctrl->value; + break; + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + params->video_bitrate_peak = ctrl->value; + break; + case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: + params->video_temporal_decimation = ctrl->value; + break; + case V4L2_CID_MPEG_STREAM_TYPE: + params->stream_type = ctrl->value; + params->video_encoding = + (params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_SS || + params->stream_type == V4L2_MPEG_STREAM_TYPE_MPEG1_VCD) ? + V4L2_MPEG_VIDEO_ENCODING_MPEG_1 : V4L2_MPEG_VIDEO_ENCODING_MPEG_2; + if (params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) { + /* MPEG-1 implies CBR */ + params->video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR; + } + break; + case V4L2_CID_MPEG_STREAM_VBI_FMT: + params->stream_vbi_fmt = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: + params->video_spatial_filter_mode = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: + params->video_spatial_filter = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: + params->video_luma_spatial_filter_type = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: + params->video_chroma_spatial_filter_type = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: + params->video_temporal_filter_mode = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: + params->video_temporal_filter = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: + params->video_median_filter_type = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: + params->video_luma_median_filter_top = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: + params->video_luma_median_filter_bottom = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: + params->video_chroma_median_filter_top = ctrl->value; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: + params->video_chroma_median_filter_bottom = ctrl->value; + break; + default: + return -EINVAL; + } + return 0; +} + +static int cx2341x_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def) +{ + const char *name; + + qctrl->flags = 0; + switch (qctrl->id) { + /* MPEG controls */ + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: + name = "Spatial Filter Mode"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: + name = "Spatial Filter"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: + name = "Spatial Luma Filter Type"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: + name = "Spatial Chroma Filter Type"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: + name = "Temporal Filter Mode"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: + name = "Temporal Filter"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: + name = "Median Filter Type"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: + name = "Median Luma Filter Maximum"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: + name = "Median Luma Filter Minimum"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: + name = "Median Chroma Filter Maximum"; + break; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: + name = "Median Chroma Filter Minimum"; + break; + + default: + return v4l2_ctrl_query_fill(qctrl, min, max, step, def); + } + switch (qctrl->id) { + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: + case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: + qctrl->type = V4L2_CTRL_TYPE_MENU; + min = 0; + step = 1; + break; + default: + qctrl->type = V4L2_CTRL_TYPE_INTEGER; + break; + } + switch (qctrl->id) { + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: + case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: + qctrl->flags |= V4L2_CTRL_FLAG_UPDATE; + break; + } + qctrl->minimum = min; + qctrl->maximum = max; + qctrl->step = step; + qctrl->default_value = def; + qctrl->reserved[0] = qctrl->reserved[1] = 0; + snprintf(qctrl->name, sizeof(qctrl->name), name); + return 0; +} + +int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, struct v4l2_queryctrl *qctrl) +{ + int err; + + switch (qctrl->id) { + case V4L2_CID_MPEG_AUDIO_ENCODING: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_ENCODING_LAYER_2, + V4L2_MPEG_AUDIO_ENCODING_LAYER_2, 1, + V4L2_MPEG_AUDIO_ENCODING_LAYER_2); + + case V4L2_CID_MPEG_AUDIO_L2_BITRATE: + return v4l2_ctrl_query_fill(qctrl, + V4L2_MPEG_AUDIO_L2_BITRATE_192K, + V4L2_MPEG_AUDIO_L2_BITRATE_384K, 1, + V4L2_MPEG_AUDIO_L2_BITRATE_224K); + + case V4L2_CID_MPEG_AUDIO_L1_BITRATE: + case V4L2_CID_MPEG_AUDIO_L3_BITRATE: + return -EINVAL; + + case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: + err = v4l2_ctrl_query_fill_std(qctrl); + if (err == 0 && params->audio_mode != V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return err; + + case V4L2_CID_MPEG_VIDEO_ENCODING: + /* this setting is read-only for the cx2341x since the + V4L2_CID_MPEG_STREAM_TYPE really determines the + MPEG-1/2 setting */ + err = v4l2_ctrl_query_fill_std(qctrl); + if (err == 0) + qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; + return err; + + case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: + err = v4l2_ctrl_query_fill_std(qctrl); + if (err == 0 && params->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return err; + + case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: + err = v4l2_ctrl_query_fill_std(qctrl); + if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CBR) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return err; + + case V4L2_CID_MPEG_STREAM_VBI_FMT: + if (params->capabilities & CX2341X_CAP_HAS_SLICED_VBI) + return v4l2_ctrl_query_fill_std(qctrl); + return cx2341x_ctrl_query_fill(qctrl, + V4L2_MPEG_STREAM_VBI_FMT_NONE, + V4L2_MPEG_STREAM_VBI_FMT_NONE, 1, + V4L2_MPEG_STREAM_VBI_FMT_NONE); + + /* CX23415/6 specific */ + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: + return cx2341x_ctrl_query_fill(qctrl, + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL, + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO, 1, + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL); + + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER: + cx2341x_ctrl_query_fill(qctrl, 0, 15, 1, 0); + qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; + if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; + + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: + cx2341x_ctrl_query_fill(qctrl, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE, 1, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF); + if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; + + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: + cx2341x_ctrl_query_fill(qctrl, + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF, + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, 1, + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF); + if (params->video_spatial_filter_mode == V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; + + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: + return cx2341x_ctrl_query_fill(qctrl, + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL, + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO, 1, + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL); + + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER: + cx2341x_ctrl_query_fill(qctrl, 0, 31, 1, 0); + qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; + if (params->video_temporal_filter_mode == V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; + + case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: + return cx2341x_ctrl_query_fill(qctrl, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG, 1, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF); + + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP: + cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255); + qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; + if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; + + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM: + cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0); + qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; + if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; + + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP: + cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 255); + qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; + if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; + + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM: + cx2341x_ctrl_query_fill(qctrl, 0, 255, 1, 0); + qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; + if (params->video_median_filter_type == V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF) + qctrl->flags |= V4L2_CTRL_FLAG_INACTIVE; + return 0; + + default: + return v4l2_ctrl_query_fill_std(qctrl); + + } +} + +const char **cx2341x_ctrl_get_menu(u32 id) +{ + static const char *mpeg_stream_type[] = { + "MPEG-2 Program Stream", + "", + "MPEG-1 System Stream", + "MPEG-2 DVD-compatible Stream", + "MPEG-1 VCD-compatible Stream", + "MPEG-2 SVCD-compatible Stream", + NULL + }; + + static const char *cx2341x_video_spatial_filter_mode_menu[] = { + "Manual", + "Auto", + NULL + }; + + static const char *cx2341x_video_luma_spatial_filter_type_menu[] = { + "Off", + "1D Horizontal", + "1D Vertical", + "2D H/V Separable", + "2D Symmetric non-separable", + NULL + }; + + static const char *cx2341x_video_chroma_spatial_filter_type_menu[] = { + "Off", + "1D Horizontal", + NULL + }; + + static const char *cx2341x_video_temporal_filter_mode_menu[] = { + "Manual", + "Auto", + NULL + }; + + static const char *cx2341x_video_median_filter_type_menu[] = { + "Off", + "Horizontal", + "Vertical", + "Horizontal/Vertical", + "Diagonal", + NULL + }; + + switch (id) { + case V4L2_CID_MPEG_STREAM_TYPE: + return mpeg_stream_type; + case V4L2_CID_MPEG_AUDIO_L1_BITRATE: + case V4L2_CID_MPEG_AUDIO_L3_BITRATE: + return NULL; + case V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE: + return cx2341x_video_spatial_filter_mode_menu; + case V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE: + return cx2341x_video_luma_spatial_filter_type_menu; + case V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE: + return cx2341x_video_chroma_spatial_filter_type_menu; + case V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE: + return cx2341x_video_temporal_filter_mode_menu; + case V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE: + return cx2341x_video_median_filter_type_menu; + default: + return v4l2_ctrl_get_menu(id); + } +} + +static void cx2341x_calc_audio_properties(struct cx2341x_mpeg_params *params) +{ + params->audio_properties = (params->audio_sampling_freq << 0) | + ((3 - params->audio_encoding) << 2) | + ((1 + params->audio_l2_bitrate) << 4) | + (params->audio_mode << 8) | + (params->audio_mode_extension << 10) | + (((params->audio_emphasis == V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17) ? + 3 : + params->audio_emphasis) << 12) | + (params->audio_crc << 14); +} + +int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, + struct v4l2_ext_controls *ctrls, unsigned int cmd) +{ + int err = 0; + int i; + + if (cmd == VIDIOC_G_EXT_CTRLS) { + for (i = 0; i < ctrls->count; i++) { + struct v4l2_ext_control *ctrl = ctrls->controls + i; + + err = cx2341x_get_ctrl(params, ctrl); + if (err) { + ctrls->error_idx = i; + break; + } + } + return err; + } + for (i = 0; i < ctrls->count; i++) { + struct v4l2_ext_control *ctrl = ctrls->controls + i; + struct v4l2_queryctrl qctrl; + const char **menu_items = NULL; + + qctrl.id = ctrl->id; + err = cx2341x_ctrl_query(params, &qctrl); + if (err) + break; + if (qctrl.type == V4L2_CTRL_TYPE_MENU) + menu_items = cx2341x_ctrl_get_menu(qctrl.id); + err = v4l2_ctrl_check(ctrl, &qctrl, menu_items); + if (err) + break; + err = cx2341x_set_ctrl(params, ctrl); + if (err) + break; + } + if (err == 0 && params->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR && + params->video_bitrate_peak < params->video_bitrate) { + err = -ERANGE; + ctrls->error_idx = ctrls->count; + } + if (err) { + ctrls->error_idx = i; + } + else { + cx2341x_calc_audio_properties(params); + } + return err; +} + +void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p) +{ + static struct cx2341x_mpeg_params default_params = { + /* misc */ + .capabilities = 0, + .port = CX2341X_PORT_MEMORY, + .width = 720, + .height = 480, + .is_50hz = 0, + + /* stream */ + .stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS, + .stream_vbi_fmt = V4L2_MPEG_STREAM_VBI_FMT_NONE, + + /* audio */ + .audio_sampling_freq = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000, + .audio_encoding = V4L2_MPEG_AUDIO_ENCODING_LAYER_2, + .audio_l2_bitrate = V4L2_MPEG_AUDIO_L2_BITRATE_224K, + .audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO, + .audio_mode_extension = V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4, + .audio_emphasis = V4L2_MPEG_AUDIO_EMPHASIS_NONE, + .audio_crc = V4L2_MPEG_AUDIO_CRC_NONE, + + /* video */ + .video_encoding = V4L2_MPEG_VIDEO_ENCODING_MPEG_2, + .video_aspect = V4L2_MPEG_VIDEO_ASPECT_4x3, + .video_b_frames = 2, + .video_gop_size = 12, + .video_gop_closure = 1, + .video_pulldown = 0, + .video_bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR, + .video_bitrate = 6000000, + .video_bitrate_peak = 8000000, + .video_temporal_decimation = 0, + + /* encoding filters */ + .video_spatial_filter_mode = V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL, + .video_spatial_filter = 0, + .video_luma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR, + .video_chroma_spatial_filter_type = V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR, + .video_temporal_filter_mode = V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL, + .video_temporal_filter = 0, + .video_median_filter_type = V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF, + .video_luma_median_filter_top = 255, + .video_luma_median_filter_bottom = 0, + .video_chroma_median_filter_top = 255, + .video_chroma_median_filter_bottom = 0, + }; + + *p = default_params; + cx2341x_calc_audio_properties(p); +} + +static int cx2341x_api(void *priv, cx2341x_mbox_func func, int cmd, int args, ...) +{ + u32 data[CX2341X_MBOX_MAX_DATA]; + va_list vargs; + int i; + + va_start(vargs, args); + + for (i = 0; i < args; i++) { + data[i] = va_arg(vargs, int); + } + va_end(vargs); + return func(priv, cmd, args, 0, data); +} + +int cx2341x_update(void *priv, cx2341x_mbox_func func, + const struct cx2341x_mpeg_params *old, const struct cx2341x_mpeg_params *new) +{ + static int mpeg_stream_type[] = { + 0, /* MPEG-2 PS */ + 1, /* MPEG-2 TS */ + 2, /* MPEG-1 SS */ + 14, /* DVD */ + 11, /* VCD */ + 12, /* SVCD */ + }; + + int err = 0; + + cx2341x_api(priv, func, CX2341X_ENC_SET_OUTPUT_PORT, 2, new->port, 0); + + if (old == NULL || old->is_50hz != new->is_50hz) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_RATE, 1, new->is_50hz); + if (err) return err; + } + + if (old == NULL || old->width != new->width || old->height != new->height || + old->video_encoding != new->video_encoding) { + u16 w = new->width; + u16 h = new->height; + + if (new->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) { + w /= 2; + h /= 2; + } + err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_SIZE, 2, h, w); + if (err) return err; + } + + if (old == NULL || old->stream_type != new->stream_type) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_STREAM_TYPE, 1, mpeg_stream_type[new->stream_type]); + if (err) return err; + } + if (old == NULL || old->video_aspect != new->video_aspect) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_ASPECT_RATIO, 1, 1 + new->video_aspect); + if (err) return err; + } + if (old == NULL || old->video_b_frames != new->video_b_frames || + old->video_gop_size != new->video_gop_size) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_PROPERTIES, 2, + new->video_gop_size, new->video_b_frames + 1); + if (err) return err; + } + if (old == NULL || old->video_gop_closure != new->video_gop_closure) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_GOP_CLOSURE, 1, new->video_gop_closure); + if (err) return err; + } + if (old == NULL || old->video_pulldown != new->video_pulldown) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_3_2_PULLDOWN, 1, new->video_pulldown); + if (err) return err; + } + if (old == NULL || old->audio_properties != new->audio_properties) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_AUDIO_PROPERTIES, 1, new->audio_properties); + if (err) return err; + } + if (old == NULL || old->video_bitrate_mode != new->video_bitrate_mode || + old->video_bitrate != new->video_bitrate || + old->video_bitrate_peak != new->video_bitrate_peak) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_BIT_RATE, 5, + new->video_bitrate_mode, new->video_bitrate, + new->video_bitrate_peak / 400, 0, 0); + if (err) return err; + } + if (old == NULL || old->video_spatial_filter_mode != new->video_spatial_filter_mode || + old->video_temporal_filter_mode != new->video_temporal_filter_mode || + old->video_median_filter_type != new->video_median_filter_type) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_MODE, 2, + new->video_spatial_filter_mode | (new->video_temporal_filter_mode << 1), + new->video_median_filter_type); + if (err) return err; + } + if (old == NULL || + old->video_luma_median_filter_bottom != new->video_luma_median_filter_bottom || + old->video_luma_median_filter_top != new->video_luma_median_filter_top || + old->video_chroma_median_filter_bottom != new->video_chroma_median_filter_bottom || + old->video_chroma_median_filter_top != new->video_chroma_median_filter_top) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_CORING_LEVELS, 4, + new->video_luma_median_filter_bottom, + new->video_luma_median_filter_top, + new->video_chroma_median_filter_bottom, + new->video_chroma_median_filter_top); + if (err) return err; + } + if (old == NULL || + old->video_luma_spatial_filter_type != new->video_luma_spatial_filter_type || + old->video_chroma_spatial_filter_type != new->video_chroma_spatial_filter_type) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_SPATIAL_FILTER_TYPE, 2, + new->video_luma_spatial_filter_type, new->video_chroma_spatial_filter_type); + if (err) return err; + } + if (old == NULL || + old->video_spatial_filter != new->video_spatial_filter || + old->video_temporal_filter != new->video_temporal_filter) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_DNR_FILTER_PROPS, 2, + new->video_spatial_filter, new->video_temporal_filter); + if (err) return err; + } + if (old == NULL || old->video_temporal_decimation != new->video_temporal_decimation) { + err = cx2341x_api(priv, func, CX2341X_ENC_SET_FRAME_DROP_RATE, 1, + new->video_temporal_decimation); + if (err) return err; + } + return 0; +} + +static const char *cx2341x_menu_item(struct cx2341x_mpeg_params *p, u32 id) +{ + const char **menu = cx2341x_ctrl_get_menu(id); + struct v4l2_ext_control ctrl; + + if (menu == NULL) + goto invalid; + ctrl.id = id; + if (cx2341x_get_ctrl(p, &ctrl)) + goto invalid; + while (ctrl.value-- && *menu) menu++; + if (*menu == NULL) + goto invalid; + return *menu; + +invalid: + return "<invalid>"; +} + +void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix) +{ + int is_mpeg1 = p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1; + + /* Stream */ + printk(KERN_INFO "%s: Stream: %s\n", + prefix, + cx2341x_menu_item(p, V4L2_CID_MPEG_STREAM_TYPE)); + + /* Video */ + printk(KERN_INFO "%s: Video: %dx%d, %d fps\n", + prefix, + p->width / (is_mpeg1 ? 2 : 1), p->height / (is_mpeg1 ? 2 : 1), + p->is_50hz ? 25 : 30); + printk(KERN_INFO "%s: Video: %s, %s, %s, %d", + prefix, + cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ENCODING), + cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_ASPECT), + cx2341x_menu_item(p, V4L2_CID_MPEG_VIDEO_BITRATE_MODE), + p->video_bitrate); + if (p->video_bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) { + printk(", Peak %d", p->video_bitrate_peak); + } + printk("\n"); + printk(KERN_INFO "%s: Video: GOP Size %d, %d B-Frames, %sGOP Closure, %s3:2 Pulldown\n", + prefix, + p->video_gop_size, p->video_b_frames, + p->video_gop_closure ? "" : "No ", + p->video_pulldown ? "" : "No "); + if (p->video_temporal_decimation) { + printk(KERN_INFO "%s: Video: Temporal Decimation %d\n", + prefix, p->video_temporal_decimation); + } + + /* Audio */ + printk(KERN_INFO "%s: Audio: %s, %s, %s, %s", + prefix, + cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ), + cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_ENCODING), + cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_L2_BITRATE), + cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE)); + if (p->audio_mode == V4L2_MPEG_AUDIO_MODE_JOINT_STEREO) { + printk(", %s", + cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_MODE_EXTENSION)); + } + printk(", %s, %s\n", + cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_EMPHASIS), + cx2341x_menu_item(p, V4L2_CID_MPEG_AUDIO_CRC)); + + /* Encoding filters */ + printk(KERN_INFO "%s: Spatial Filter: %s, Luma %s, Chroma %s, %d\n", + prefix, + cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE), + cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE), + cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE), + p->video_spatial_filter); + printk(KERN_INFO "%s: Temporal Filter: %s, %d\n", + prefix, + cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE), + p->video_temporal_filter); + printk(KERN_INFO "%s: Median Filter: %s, Luma [%d, %d], Chroma [%d, %d]\n", + prefix, + cx2341x_menu_item(p, V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE), + p->video_luma_median_filter_bottom, + p->video_luma_median_filter_top, + p->video_chroma_median_filter_bottom, + p->video_chroma_median_filter_top); +} + +EXPORT_SYMBOL(cx2341x_fill_defaults); +EXPORT_SYMBOL(cx2341x_ctrl_query); +EXPORT_SYMBOL(cx2341x_ctrl_get_menu); +EXPORT_SYMBOL(cx2341x_ext_ctrls); +EXPORT_SYMBOL(cx2341x_update); +EXPORT_SYMBOL(cx2341x_log_status); +EXPORT_SYMBOL(cx2341x_mpeg_ctrls); + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ + diff --git a/drivers/media/video/ks0127.c b/drivers/media/video/ks0127.c new file mode 100644 index 000000000..3bf7ac4f5 --- /dev/null +++ b/drivers/media/video/ks0127.c @@ -0,0 +1,846 @@ +/* + * Video Capture Driver (Video for Linux 1/2) + * for the Matrox Marvel G200,G400 and Rainbow Runner-G series + * + * This module is an interface to the KS0127 video decoder chip. + * + * Copyright (C) 1999 Ryan Drake <stiletto@mediaone.net> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + ***************************************************************************** + * + * Modified and extended by + * Mike Bernson <mike@mlb.org> + * Gerard v.d. Horst + * Leon van Stuivenberg <l.vanstuivenberg@chello.nl> + * Gernot Ziegler <gz@lysator.liu.se> + * + * Version History: + * V1.0 Ryan Drake Initial version by Ryan Drake + * V1.1 Gerard v.d. Horst Added some debugoutput, reset the video-standard + */ + +#ifndef __KERNEL__ +#define __KERNEL__ +#endif + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/proc_fs.h> +#include "ks0127.h" + +#include <linux/i2c.h> +#include <linux/video_decoder.h> + +#define dprintk if (debug) printk + +/* i2c identification */ +#define I2C_KS0127_ADDON 0xD8 +#define I2C_KS0127_ONBOARD 0xDA + +#define KS_TYPE_UNKNOWN 0 +#define KS_TYPE_0122S 1 +#define KS_TYPE_0127 2 +#define KS_TYPE_0127B 3 + +/* ks0127 control registers */ +#define KS_STAT 0x00 +#define KS_CMDA 0x01 +#define KS_CMDB 0x02 +#define KS_CMDC 0x03 +#define KS_CMDD 0x04 +#define KS_HAVB 0x05 +#define KS_HAVE 0x06 +#define KS_HS1B 0x07 +#define KS_HS1E 0x08 +#define KS_HS2B 0x09 +#define KS_HS2E 0x0a +#define KS_AGC 0x0b +#define KS_HXTRA 0x0c +#define KS_CDEM 0x0d +#define KS_PORTAB 0x0e +#define KS_LUMA 0x0f +#define KS_CON 0x10 +#define KS_BRT 0x11 +#define KS_CHROMA 0x12 +#define KS_CHROMB 0x13 +#define KS_DEMOD 0x14 +#define KS_SAT 0x15 +#define KS_HUE 0x16 +#define KS_VERTIA 0x17 +#define KS_VERTIB 0x18 +#define KS_VERTIC 0x19 +#define KS_HSCLL 0x1a +#define KS_HSCLH 0x1b +#define KS_VSCLL 0x1c +#define KS_VSCLH 0x1d +#define KS_OFMTA 0x1e +#define KS_OFMTB 0x1f +#define KS_VBICTL 0x20 +#define KS_CCDAT2 0x21 +#define KS_CCDAT1 0x22 +#define KS_VBIL30 0x23 +#define KS_VBIL74 0x24 +#define KS_VBIL118 0x25 +#define KS_VBIL1512 0x26 +#define KS_TTFRAM 0x27 +#define KS_TESTA 0x28 +#define KS_UVOFFH 0x29 +#define KS_UVOFFL 0x2a +#define KS_UGAIN 0x2b +#define KS_VGAIN 0x2c +#define KS_VAVB 0x2d +#define KS_VAVE 0x2e +#define KS_CTRACK 0x2f +#define KS_POLCTL 0x30 +#define KS_REFCOD 0x31 +#define KS_INVALY 0x32 +#define KS_INVALU 0x33 +#define KS_INVALV 0x34 +#define KS_UNUSEY 0x35 +#define KS_UNUSEU 0x36 +#define KS_UNUSEV 0x37 +#define KS_USRSAV 0x38 +#define KS_USREAV 0x39 +#define KS_SHS1A 0x3a +#define KS_SHS1B 0x3b +#define KS_SHS1C 0x3c +#define KS_CMDE 0x3d +#define KS_VSDEL 0x3e +#define KS_CMDF 0x3f +#define KS_GAMMA0 0x40 +#define KS_GAMMA1 0x41 +#define KS_GAMMA2 0x42 +#define KS_GAMMA3 0x43 +#define KS_GAMMA4 0x44 +#define KS_GAMMA5 0x45 +#define KS_GAMMA6 0x46 +#define KS_GAMMA7 0x47 +#define KS_GAMMA8 0x48 +#define KS_GAMMA9 0x49 +#define KS_GAMMA10 0x4a +#define KS_GAMMA11 0x4b +#define KS_GAMMA12 0x4c +#define KS_GAMMA13 0x4d +#define KS_GAMMA14 0x4e +#define KS_GAMMA15 0x4f +#define KS_GAMMA16 0x50 +#define KS_GAMMA17 0x51 +#define KS_GAMMA18 0x52 +#define KS_GAMMA19 0x53 +#define KS_GAMMA20 0x54 +#define KS_GAMMA21 0x55 +#define KS_GAMMA22 0x56 +#define KS_GAMMA23 0x57 +#define KS_GAMMA24 0x58 +#define KS_GAMMA25 0x59 +#define KS_GAMMA26 0x5a +#define KS_GAMMA27 0x5b +#define KS_GAMMA28 0x5c +#define KS_GAMMA29 0x5d +#define KS_GAMMA30 0x5e +#define KS_GAMMA31 0x5f +#define KS_GAMMAD0 0x60 +#define KS_GAMMAD1 0x61 +#define KS_GAMMAD2 0x62 +#define KS_GAMMAD3 0x63 +#define KS_GAMMAD4 0x64 +#define KS_GAMMAD5 0x65 +#define KS_GAMMAD6 0x66 +#define KS_GAMMAD7 0x67 +#define KS_GAMMAD8 0x68 +#define KS_GAMMAD9 0x69 +#define KS_GAMMAD10 0x6a +#define KS_GAMMAD11 0x6b +#define KS_GAMMAD12 0x6c +#define KS_GAMMAD13 0x6d +#define KS_GAMMAD14 0x6e +#define KS_GAMMAD15 0x6f +#define KS_GAMMAD16 0x70 +#define KS_GAMMAD17 0x71 +#define KS_GAMMAD18 0x72 +#define KS_GAMMAD19 0x73 +#define KS_GAMMAD20 0x74 +#define KS_GAMMAD21 0x75 +#define KS_GAMMAD22 0x76 +#define KS_GAMMAD23 0x77 +#define KS_GAMMAD24 0x78 +#define KS_GAMMAD25 0x79 +#define KS_GAMMAD26 0x7a +#define KS_GAMMAD27 0x7b +#define KS_GAMMAD28 0x7c +#define KS_GAMMAD29 0x7d +#define KS_GAMMAD30 0x7e +#define KS_GAMMAD31 0x7f + + +/**************************************************************************** +* mga_dev : represents one ks0127 chip. +****************************************************************************/ + +struct adjust { + int contrast; + int bright; + int hue; + int ugain; + int vgain; +}; + +struct ks0127 { + struct i2c_client *client; + unsigned char addr; + int format_width; + int format_height; + int cap_width; + int cap_height; + int norm; + int ks_type; + u8 regs[256]; +}; + + +static int debug; /* insmod parameter */ + +module_param(debug, int, 0); +MODULE_PARM_DESC(debug, "Debug output"); +MODULE_LICENSE("GPL"); + +static u8 reg_defaults[64]; + + + +static void init_reg_defaults(void) +{ + u8 *table = reg_defaults; + + table[KS_CMDA] = 0x2c; /* VSE=0, CCIR 601, autodetect standard */ + table[KS_CMDB] = 0x12; /* VALIGN=0, AGC control and input */ + table[KS_CMDC] = 0x00; /* Test options */ + /* clock & input select, write 1 to PORTA */ + table[KS_CMDD] = 0x01; + table[KS_HAVB] = 0x00; /* HAV Start Control */ + table[KS_HAVE] = 0x00; /* HAV End Control */ + table[KS_HS1B] = 0x10; /* HS1 Start Control */ + table[KS_HS1E] = 0x00; /* HS1 End Control */ + table[KS_HS2B] = 0x00; /* HS2 Start Control */ + table[KS_HS2E] = 0x00; /* HS2 End Control */ + table[KS_AGC] = 0x53; /* Manual setting for AGC */ + table[KS_HXTRA] = 0x00; /* Extra Bits for HAV and HS1/2 */ + table[KS_CDEM] = 0x00; /* Chroma Demodulation Control */ + table[KS_PORTAB] = 0x0f; /* port B is input, port A output GPPORT */ + table[KS_LUMA] = 0x01; /* Luma control */ + table[KS_CON] = 0x00; /* Contrast Control */ + table[KS_BRT] = 0x00; /* Brightness Control */ + table[KS_CHROMA] = 0x2a; /* Chroma control A */ + table[KS_CHROMB] = 0x90; /* Chroma control B */ + table[KS_DEMOD] = 0x00; /* Chroma Demodulation Control & Status */ + table[KS_SAT] = 0x00; /* Color Saturation Control*/ + table[KS_HUE] = 0x00; /* Hue Control */ + table[KS_VERTIA] = 0x00; /* Vertical Processing Control A */ + /* Vertical Processing Control B, luma 1 line delayed */ + table[KS_VERTIB] = 0x12; + table[KS_VERTIC] = 0x0b; /* Vertical Processing Control C */ + table[KS_HSCLL] = 0x00; /* Horizontal Scaling Ratio Low */ + table[KS_HSCLH] = 0x00; /* Horizontal Scaling Ratio High */ + table[KS_VSCLL] = 0x00; /* Vertical Scaling Ratio Low */ + table[KS_VSCLH] = 0x00; /* Vertical Scaling Ratio High */ + /* 16 bit YCbCr 4:2:2 output; I can't make the bt866 like 8 bit /Sam */ + table[KS_OFMTA] = 0x30; + table[KS_OFMTB] = 0x00; /* Output Control B */ + /* VBI Decoder Control; 4bit fmt: avoid Y overflow */ + table[KS_VBICTL] = 0x5d; + table[KS_CCDAT2] = 0x00; /* Read Only register */ + table[KS_CCDAT1] = 0x00; /* Read Only register */ + table[KS_VBIL30] = 0xa8; /* VBI data decoding options */ + table[KS_VBIL74] = 0xaa; /* VBI data decoding options */ + table[KS_VBIL118] = 0x2a; /* VBI data decoding options */ + table[KS_VBIL1512] = 0x00; /* VBI data decoding options */ + table[KS_TTFRAM] = 0x00; /* Teletext frame alignment pattern */ + table[KS_TESTA] = 0x00; /* test register, shouldn't be written */ + table[KS_UVOFFH] = 0x00; /* UV Offset Adjustment High */ + table[KS_UVOFFL] = 0x00; /* UV Offset Adjustment Low */ + table[KS_UGAIN] = 0x00; /* U Component Gain Adjustment */ + table[KS_VGAIN] = 0x00; /* V Component Gain Adjustment */ + table[KS_VAVB] = 0x07; /* VAV Begin */ + table[KS_VAVE] = 0x00; /* VAV End */ + table[KS_CTRACK] = 0x00; /* Chroma Tracking Control */ + table[KS_POLCTL] = 0x41; /* Timing Signal Polarity Control */ + table[KS_REFCOD] = 0x80; /* Reference Code Insertion Control */ + table[KS_INVALY] = 0x10; /* Invalid Y Code */ + table[KS_INVALU] = 0x80; /* Invalid U Code */ + table[KS_INVALV] = 0x80; /* Invalid V Code */ + table[KS_UNUSEY] = 0x10; /* Unused Y Code */ + table[KS_UNUSEU] = 0x80; /* Unused U Code */ + table[KS_UNUSEV] = 0x80; /* Unused V Code */ + table[KS_USRSAV] = 0x00; /* reserved */ + table[KS_USREAV] = 0x00; /* reserved */ + table[KS_SHS1A] = 0x00; /* User Defined SHS1 A */ + /* User Defined SHS1 B, ALT656=1 on 0127B */ + table[KS_SHS1B] = 0x80; + table[KS_SHS1C] = 0x00; /* User Defined SHS1 C */ + table[KS_CMDE] = 0x00; /* Command Register E */ + table[KS_VSDEL] = 0x00; /* VS Delay Control */ + /* Command Register F, update -immediately- */ + /* (there might come no vsync)*/ + table[KS_CMDF] = 0x02; +} + + +/* We need to manually read because of a bug in the KS0127 chip. + * + * An explanation from kayork@mail.utexas.edu: + * + * During I2C reads, the KS0127 only samples for a stop condition + * during the place where the acknoledge bit should be. Any standard + * I2C implementation (correctly) throws in another clock transition + * at the 9th bit, and the KS0127 will not recognize the stop condition + * and will continue to clock out data. + * + * So we have to do the read ourself. Big deal. + workaround in i2c-algo-bit + */ + + +static u8 ks0127_read(struct ks0127 *ks, u8 reg) +{ + struct i2c_client *c = ks->client; + char val = 0; + struct i2c_msg msgs[] = { + {c->addr, 0, sizeof(reg), ®}, + {c->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val}}; + int ret; + + ret = i2c_transfer(c->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) + dprintk("ks0127_write error\n"); + + return val; +} + + +static void ks0127_write(struct ks0127 *ks, u8 reg, u8 val) +{ + char msg[] = {reg, val}; + + if (i2c_master_send(ks->client, msg, sizeof(msg)) != sizeof(msg)) + dprintk("ks0127_write error\n"); + + ks->regs[reg] = val; +} + + +/* generic bit-twiddling */ +static void ks0127_and_or(struct ks0127 *ks, u8 reg, u8 and_v, u8 or_v) +{ + u8 val = ks->regs[reg]; + val = (val & and_v) | or_v; + ks0127_write(ks, reg, val); +} + + + +/**************************************************************************** +* ks0127 private api +****************************************************************************/ +static void ks0127_reset(struct ks0127* ks) +{ + int i; + u8 *table = reg_defaults; + + ks->ks_type = KS_TYPE_UNKNOWN; + + dprintk("ks0127: reset\n"); + msleep(1); + + /* initialize all registers to known values */ + /* (except STAT, 0x21, 0x22, TEST and 0x38,0x39) */ + + for(i = 1; i < 33; i++) + ks0127_write(ks, i, table[i]); + + for(i = 35; i < 40; i++) + ks0127_write(ks, i, table[i]); + + for(i = 41; i < 56; i++) + ks0127_write(ks, i, table[i]); + + for(i = 58; i < 64; i++) + ks0127_write(ks, i, table[i]); + + + if ((ks0127_read(ks, KS_STAT) & 0x80) == 0) { + ks->ks_type = KS_TYPE_0122S; + dprintk("ks0127: ks0122s Found\n"); + return; + } + + switch(ks0127_read(ks, KS_CMDE) & 0x0f) { + + case 0: + ks->ks_type = KS_TYPE_0127; + dprintk("ks0127: ks0127 found\n"); + break; + + case 9: + ks->ks_type = KS_TYPE_0127B; + dprintk("ks0127: ks0127B Revision A found\n"); + break; + + default: + dprintk("ks0127: unknown revision\n"); + break; + } +} + +static int ks0127_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + struct ks0127 *ks = i2c_get_clientdata(client); + + int *iarg = (int*)arg; + + int status; + + if (!ks) + return -ENODEV; + + switch (cmd) { + + case DECODER_INIT: + dprintk("ks0127: command DECODER_INIT\n"); + ks0127_reset(ks); + break; + + case DECODER_SET_INPUT: + switch(*iarg) { + case KS_INPUT_COMPOSITE_1: + case KS_INPUT_COMPOSITE_2: + case KS_INPUT_COMPOSITE_3: + case KS_INPUT_COMPOSITE_4: + case KS_INPUT_COMPOSITE_5: + case KS_INPUT_COMPOSITE_6: + dprintk("ks0127: command DECODER_SET_INPUT %d: " + "Composite\n", *iarg); + /* autodetect 50/60 Hz */ + ks0127_and_or(ks, KS_CMDA, 0xfc, 0x00); + /* VSE=0 */ + ks0127_and_or(ks, KS_CMDA, ~0x40, 0x00); + /* set input line */ + ks0127_and_or(ks, KS_CMDB, 0xb0, *iarg); + /* non-freerunning mode */ + ks0127_and_or(ks, KS_CMDC, 0x70, 0x0a); + /* analog input */ + ks0127_and_or(ks, KS_CMDD, 0x03, 0x00); + /* enable chroma demodulation */ + ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00); + /* chroma trap, HYBWR=1 */ + ks0127_and_or(ks, KS_LUMA, 0x00, + (reg_defaults[KS_LUMA])|0x0c); + /* scaler fullbw, luma comb off */ + ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81); + /* manual chroma comb .25 .5 .25 */ + ks0127_and_or(ks, KS_VERTIC, 0x0f, 0x90); + + /* chroma path delay */ + ks0127_and_or(ks, KS_CHROMB, 0x0f, 0x90); + + ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]); + ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]); + ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]); + ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]); + break; + + case KS_INPUT_SVIDEO_1: + case KS_INPUT_SVIDEO_2: + case KS_INPUT_SVIDEO_3: + dprintk("ks0127: command DECODER_SET_INPUT %d: " + "S-Video\n", *iarg); + /* autodetect 50/60 Hz */ + ks0127_and_or(ks, KS_CMDA, 0xfc, 0x00); + /* VSE=0 */ + ks0127_and_or(ks, KS_CMDA, ~0x40, 0x00); + /* set input line */ + ks0127_and_or(ks, KS_CMDB, 0xb0, *iarg); + /* non-freerunning mode */ + ks0127_and_or(ks, KS_CMDC, 0x70, 0x0a); + /* analog input */ + ks0127_and_or(ks, KS_CMDD, 0x03, 0x00); + /* enable chroma demodulation */ + ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x00); + ks0127_and_or(ks, KS_LUMA, 0x00, + reg_defaults[KS_LUMA]); + /* disable luma comb */ + ks0127_and_or(ks, KS_VERTIA, 0x08, + (reg_defaults[KS_VERTIA]&0xf0)|0x01); + ks0127_and_or(ks, KS_VERTIC, 0x0f, + reg_defaults[KS_VERTIC]&0xf0); + + ks0127_and_or(ks, KS_CHROMB, 0x0f, + reg_defaults[KS_CHROMB]&0xf0); + + ks0127_write(ks, KS_UGAIN, reg_defaults[KS_UGAIN]); + ks0127_write(ks, KS_VGAIN, reg_defaults[KS_VGAIN]); + ks0127_write(ks, KS_UVOFFH, reg_defaults[KS_UVOFFH]); + ks0127_write(ks, KS_UVOFFL, reg_defaults[KS_UVOFFL]); + break; + + case KS_INPUT_YUV656: + dprintk("ks0127: command DECODER_SET_INPUT 15: " + "YUV656\n"); + if (ks->norm == VIDEO_MODE_NTSC || + ks->norm == KS_STD_PAL_M) + /* force 60 Hz */ + ks0127_and_or(ks, KS_CMDA, 0xfc, 0x03); + else + /* force 50 Hz */ + ks0127_and_or(ks, KS_CMDA, 0xfc, 0x02); + + ks0127_and_or(ks, KS_CMDA, 0xff, 0x40); /* VSE=1 */ + /* set input line and VALIGN */ + ks0127_and_or(ks, KS_CMDB, 0xb0, (*iarg | 0x40)); + /* freerunning mode, */ + /* TSTGEN = 1 TSTGFR=11 TSTGPH=0 TSTGPK=0 VMEM=1*/ + ks0127_and_or(ks, KS_CMDC, 0x70, 0x87); + /* digital input, SYNDIR = 0 INPSL=01 CLKDIR=0 EAV=0 */ + ks0127_and_or(ks, KS_CMDD, 0x03, 0x08); + /* disable chroma demodulation */ + ks0127_and_or(ks, KS_CTRACK, 0xcf, 0x30); + /* HYPK =01 CTRAP = 0 HYBWR=0 PED=1 RGBH=1 UNIT=1 */ + ks0127_and_or(ks, KS_LUMA, 0x00, 0x71); + ks0127_and_or(ks, KS_VERTIC, 0x0f, + reg_defaults[KS_VERTIC]&0xf0); + + /* scaler fullbw, luma comb off */ + ks0127_and_or(ks, KS_VERTIA, 0x08, 0x81); + + ks0127_and_or(ks, KS_CHROMB, 0x0f, + reg_defaults[KS_CHROMB]&0xf0); + + ks0127_and_or(ks, KS_CON, 0x00, 0x00); + ks0127_and_or(ks, KS_BRT, 0x00, 32); /* spec: 34 */ + /* spec: 229 (e5) */ + ks0127_and_or(ks, KS_SAT, 0x00, 0xe8); + ks0127_and_or(ks, KS_HUE, 0x00, 0); + + ks0127_and_or(ks, KS_UGAIN, 0x00, 238); + ks0127_and_or(ks, KS_VGAIN, 0x00, 0x00); + + /*UOFF:0x30, VOFF:0x30, TSTCGN=1 */ + ks0127_and_or(ks, KS_UVOFFH, 0x00, 0x4f); + ks0127_and_or(ks, KS_UVOFFL, 0x00, 0x00); + break; + + default: + dprintk("ks0127: command DECODER_SET_INPUT: " + "Unknown input %d\n", *iarg); + break; + } + + /* hack: CDMLPF sometimes spontaneously switches on; */ + /* force back off */ + ks0127_write(ks, KS_DEMOD, reg_defaults[KS_DEMOD]); + break; + + case DECODER_SET_OUTPUT: + switch(*iarg) { + case KS_OUTPUT_YUV656E: + dprintk("ks0127: command DECODER_SET_OUTPUT: " + "OUTPUT_YUV656E (Missing)\n"); + return -EINVAL; + break; + + case KS_OUTPUT_EXV: + dprintk("ks0127: command DECODER_SET_OUTPUT: " + "OUTPUT_EXV\n"); + ks0127_and_or(ks, KS_OFMTA, 0xf0, 0x09); + break; + } + break; + + case DECODER_SET_NORM: //sam This block mixes old and new norm names... + /* Set to automatic SECAM/Fsc mode */ + ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00); + + ks->norm = *iarg; + switch(*iarg) + { + /* this is untested !! */ + /* It just detects PAL_N/NTSC_M (no special frequencies) */ + /* And you have to set the standard a second time afterwards */ + case VIDEO_MODE_AUTO: + dprintk("ks0127: command DECODER_SET_NORM: AUTO\n"); + + /* The chip determines the format */ + /* based on the current field rate */ + ks0127_and_or(ks, KS_CMDA, 0xfc, 0x00); + ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20); + /* This is wrong for PAL ! As I said, */ + /* you need to set the standard once again !! */ + ks->format_height = 240; + ks->format_width = 704; + break; + + case VIDEO_MODE_NTSC: + dprintk("ks0127: command DECODER_SET_NORM: NTSC_M\n"); + ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20); + ks->format_height = 240; + ks->format_width = 704; + break; + + case KS_STD_NTSC_N: + dprintk("ks0127: command KS0127_SET_STANDARD: " + "NTSC_N (fixme)\n"); + ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40); + ks->format_height = 240; + ks->format_width = 704; + break; + + case VIDEO_MODE_PAL: + dprintk("ks0127: command DECODER_SET_NORM: PAL_N\n"); + ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x20); + ks->format_height = 290; + ks->format_width = 704; + break; + + case KS_STD_PAL_M: + dprintk("ks0127: command KS0127_SET_STANDARD: " + "PAL_M (fixme)\n"); + ks0127_and_or(ks, KS_CHROMA, 0x9f, 0x40); + ks->format_height = 290; + ks->format_width = 704; + break; + + case VIDEO_MODE_SECAM: + dprintk("ks0127: command KS0127_SET_STANDARD: " + "SECAM\n"); + ks->format_height = 290; + ks->format_width = 704; + + /* set to secam autodetection */ + ks0127_and_or(ks, KS_CHROMA, 0xdf, 0x20); + ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x00); + schedule_timeout_interruptible(HZ/10+1); + + /* did it autodetect? */ + if (ks0127_read(ks, KS_DEMOD) & 0x40) + break; + + /* force to secam mode */ + ks0127_and_or(ks, KS_DEMOD, 0xf0, 0x0f); + break; + + default: + dprintk("ks0127: command DECODER_SET_NORM: " + "Unknown norm %d\n", *iarg); + break; + } + break; + + case DECODER_SET_PICTURE: + dprintk("ks0127: command DECODER_SET_PICTURE " + "not yet supported (fixme)\n"); + return -EINVAL; + + //sam todo: KS0127_SET_BRIGHTNESS: Merge into DECODER_SET_PICTURE + //sam todo: KS0127_SET_CONTRAST: Merge into DECODER_SET_PICTURE + //sam todo: KS0127_SET_HUE: Merge into DECODER_SET_PICTURE? + //sam todo: KS0127_SET_SATURATION: Merge into DECODER_SET_PICTURE + //sam todo: KS0127_SET_AGC_MODE: + //sam todo: KS0127_SET_AGC: + //sam todo: KS0127_SET_CHROMA_MODE: + //sam todo: KS0127_SET_PIXCLK_MODE: + //sam todo: KS0127_SET_GAMMA_MODE: + //sam todo: KS0127_SET_UGAIN: + //sam todo: KS0127_SET_VGAIN: + //sam todo: KS0127_SET_INVALY: + //sam todo: KS0127_SET_INVALU: + //sam todo: KS0127_SET_INVALV: + //sam todo: KS0127_SET_UNUSEY: + //sam todo: KS0127_SET_UNUSEU: + //sam todo: KS0127_SET_UNUSEV: + //sam todo: KS0127_SET_VSALIGN_MODE: + + case DECODER_ENABLE_OUTPUT: + { + + int *iarg = arg; + int enable = (*iarg != 0); + if (enable) { + dprintk("ks0127: command " + "DECODER_ENABLE_OUTPUT on " + "(%d)\n", enable); + /* All output pins on */ + ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x30); + /* Obey the OEN pin */ + ks0127_and_or(ks, KS_CDEM, 0x7f, 0x00); + } else { + dprintk("ks0127: command " + "DECODER_ENABLE_OUTPUT off " + "(%d)\n", enable); + /* Video output pins off */ + ks0127_and_or(ks, KS_OFMTA, 0xcf, 0x00); + /* Ignore the OEN pin */ + ks0127_and_or(ks, KS_CDEM, 0x7f, 0x80); + } + } + break; + + //sam todo: KS0127_SET_OUTPUT_MODE: + //sam todo: KS0127_SET_WIDTH: + //sam todo: KS0127_SET_HEIGHT: + //sam todo: KS0127_SET_HSCALE: + + case DECODER_GET_STATUS: + dprintk("ks0127: command DECODER_GET_STATUS\n"); + *iarg = 0; + status = ks0127_read(ks, KS_STAT); + if (!(status & 0x20)) /* NOVID not set */ + *iarg = (*iarg & DECODER_STATUS_GOOD); + if ((status & 0x01)) /* CLOCK set */ + *iarg = (*iarg & DECODER_STATUS_COLOR); + if ((status & 0x08)) /* PALDET set */ + *iarg = (*iarg & DECODER_STATUS_PAL); + else + *iarg = (*iarg & DECODER_STATUS_NTSC); + break; + + //Catch any unknown command + default: + dprintk("ks0127: command unknown: %04X\n", cmd); + return -EINVAL; + } + return 0; +} + + + + +static int ks0127_probe(struct i2c_adapter *adapter); +static int ks0127_detach(struct i2c_client *client); +static int ks0127_command(struct i2c_client *client, + unsigned int cmd, void *arg); + + + +/* Addresses to scan */ +static unsigned short normal_i2c[] = {I2C_KS0127_ADDON>>1, + I2C_KS0127_ONBOARD>>1, I2C_CLIENT_END}; +static unsigned short probe[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; +static unsigned short ignore[2] = {I2C_CLIENT_END, I2C_CLIENT_END}; +static struct i2c_client_address_data addr_data = { + normal_i2c, + probe, + ignore, +}; + +static struct i2c_driver i2c_driver_ks0127 = { + .driver.name = "ks0127", + .id = I2C_DRIVERID_KS0127, + .attach_adapter = ks0127_probe, + .detach_client = ks0127_detach, + .command = ks0127_command +}; + +static struct i2c_client ks0127_client_tmpl = +{ + .name = "(ks0127 unset)", + .addr = 0, + .adapter = NULL, + .driver = &i2c_driver_ks0127, + .usage_count = 0 +}; + +static int ks0127_found_proc(struct i2c_adapter *adapter, int addr, int kind) +{ + struct ks0127 *ks; + struct i2c_client *client; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (client == NULL) + return -ENOMEM; + memcpy(client, &ks0127_client_tmpl, sizeof(*client)); + + ks = kzalloc(sizeof(*ks), GFP_KERNEL); + if (ks == NULL) { + kfree(client); + return -ENOMEM; + } + + i2c_set_clientdata(client, ks); + client->adapter = adapter; + client->addr = addr; + sprintf(client->name, "ks0127-%02x", adapter->id); + + ks->client = client; + ks->addr = addr; + ks->ks_type = KS_TYPE_UNKNOWN; + + /* power up */ + ks0127_write(ks, KS_CMDA, 0x2c); + mdelay(10); + + /* reset the device */ + ks0127_reset(ks); + printk(KERN_INFO "ks0127: attach: %s video decoder\n", + ks->addr==(I2C_KS0127_ADDON>>1) ? "addon" : "on-board"); + + i2c_attach_client(client); + return 0; +} + + +static int ks0127_probe(struct i2c_adapter *adapter) +{ + if (adapter->id == I2C_HW_B_ZR36067) + return i2c_probe(adapter, &addr_data, ks0127_found_proc); + return 0; +} + +static int ks0127_detach(struct i2c_client *client) +{ + struct ks0127 *ks = i2c_get_clientdata(client); + + ks0127_write(ks, KS_OFMTA, 0x20); /*tristate*/ + ks0127_write(ks, KS_CMDA, 0x2c | 0x80); /* power down */ + + i2c_detach_client(client); + kfree(ks); + kfree(client); + + dprintk("ks0127: detach\n"); + return 0; +} + + +static int __devinit ks0127_init_module(void) +{ + init_reg_defaults(); + i2c_add_driver(&i2c_driver_ks0127); + return 0; +} + +static void __devexit ks0127_cleanup_module(void) +{ + i2c_del_driver(&i2c_driver_ks0127); +} + + +module_init(ks0127_init_module); +module_exit(ks0127_cleanup_module); diff --git a/drivers/media/video/ks0127.h b/drivers/media/video/ks0127.h new file mode 100644 index 000000000..1ec578833 --- /dev/null +++ b/drivers/media/video/ks0127.h @@ -0,0 +1,53 @@ +/* + * Video Capture Driver ( Video for Linux 1/2 ) + * for the Matrox Marvel G200,G400 and Rainbow Runner-G series + * + * This module is an interface to the KS0127 video decoder chip. + * + * Copyright (C) 1999 Ryan Drake <stiletto@mediaone.net> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef KS0127_H +#define KS0127_H + +#include <linux/videodev.h> + +/* input channels */ +#define KS_INPUT_COMPOSITE_1 0 +#define KS_INPUT_COMPOSITE_2 1 +#define KS_INPUT_COMPOSITE_3 2 +#define KS_INPUT_COMPOSITE_4 4 +#define KS_INPUT_COMPOSITE_5 5 +#define KS_INPUT_COMPOSITE_6 6 + +#define KS_INPUT_SVIDEO_1 8 +#define KS_INPUT_SVIDEO_2 9 +#define KS_INPUT_SVIDEO_3 10 + +#define KS_INPUT_YUV656 15 +#define KS_INPUT_COUNT 10 + +/* output channels */ +#define KS_OUTPUT_YUV656E 0 +#define KS_OUTPUT_EXV 1 + +/* video standards */ +#define KS_STD_NTSC_N 112 /* 50 Hz NTSC */ +#define KS_STD_PAL_M 113 /* 60 Hz PAL */ + +#endif /* KS0127_H */ + diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig new file mode 100644 index 000000000..e43a97927 --- /dev/null +++ b/drivers/media/video/pvrusb2/Kconfig @@ -0,0 +1,57 @@ +config VIDEO_PVRUSB2 + tristate "Hauppauge WinTV-PVR USB2 support" + depends on VIDEO_V4L2 && USB && I2C && EXPERIMENTAL + select FW_LOADER + select VIDEO_TUNER + select VIDEO_TVEEPROM + select VIDEO_CX2341X + select VIDEO_SAA711X + select VIDEO_MSP3400 + ---help--- + This is a video4linux driver for Conexant 23416 based + usb2 personal video recorder devices. + + To compile this driver as a module, choose M here: the + module will be called pvrusb2 + +config VIDEO_PVRUSB2_24XXX + bool "Hauppauge WinTV-PVR USB2 support for 24xxx model series" + depends on VIDEO_PVRUSB2 && EXPERIMENTAL + select VIDEO_CX25840 + select VIDEO_WM8775 + ---help--- + This option enables inclusion of additional logic to operate + newer WinTV-PVR USB2 devices whose model number is of the + form "24xxx" (leading prefix of "24" followed by 3 digits). + To see if you may need this option, examine the white + sticker on the underside of your device. Enabling this + option will not harm support for older devices. + + If you are in doubt, say Y. + +config VIDEO_PVRUSB2_SYSFS + bool "pvrusb2 sysfs support (EXPERIMENTAL)" + default y + depends on VIDEO_PVRUSB2 && SYSFS && EXPERIMENTAL + ---help--- + This option enables the operation of a sysfs based + interface for query and control of the pvrusb2 driver. + + This is not generally needed for v4l applications, + although certain applications are optimized to take + advantage of this feature. + + If you are in doubt, say Y. + + Note: This feature is experimental and subject to change. + +config VIDEO_PVRUSB2_DEBUGIFC + bool "pvrusb2 debug interface" + depends on VIDEO_PVRUSB2_SYSFS + ---help--- + This option enables the inclusion of a debug interface + in the pvrusb2 driver, hosted through sysfs. + + You do not need to select this option unless you plan + on debugging the driver or performing a manual firmware + extraction. diff --git a/drivers/media/video/pvrusb2/Makefile b/drivers/media/video/pvrusb2/Makefile new file mode 100644 index 000000000..02e414210 --- /dev/null +++ b/drivers/media/video/pvrusb2/Makefile @@ -0,0 +1,18 @@ +obj-pvrusb2-sysfs-$(CONFIG_VIDEO_PVRUSB2_SYSFS) := pvrusb2-sysfs.o +obj-pvrusb2-debugifc-$(CONFIG_VIDEO_PVRUSB2_DEBUGIFC) := pvrusb2-debugifc.o + +obj-pvrusb2-24xxx-$(CONFIG_VIDEO_PVRUSB2_24XXX) := \ + pvrusb2-cx2584x-v4l.o \ + pvrusb2-wm8775.o + +pvrusb2-objs := pvrusb2-i2c-core.o pvrusb2-i2c-cmd-v4l2.o \ + pvrusb2-audio.o pvrusb2-i2c-chips-v4l2.o \ + pvrusb2-encoder.o pvrusb2-video-v4l.o \ + pvrusb2-eeprom.o pvrusb2-tuner.o \ + pvrusb2-main.o pvrusb2-hdw.o pvrusb2-v4l2.o \ + pvrusb2-ctrl.o pvrusb2-std.o \ + pvrusb2-context.o pvrusb2-io.o pvrusb2-ioread.o \ + $(obj-pvrusb2-24xxx-y) \ + $(obj-pvrusb2-sysfs-y) $(obj-pvrusb2-debugifc-y) + +obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.c b/drivers/media/video/pvrusb2/pvrusb2-audio.c new file mode 100644 index 000000000..9846c464e --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-audio.c @@ -0,0 +1,204 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "pvrusb2-audio.h" +#include "pvrusb2-hdw-internal.h" +#include "pvrusb2-debug.h" +#include <linux/videodev2.h> +#include <media/msp3400.h> +#include <media/v4l2-common.h> + +struct pvr2_msp3400_handler { + struct pvr2_hdw *hdw; + struct pvr2_i2c_client *client; + struct pvr2_i2c_handler i2c_handler; + struct pvr2_audio_stat astat; + unsigned long stale_mask; +}; + + +/* This function selects the correct audio input source */ +static void set_stereo(struct pvr2_msp3400_handler *ctxt) +{ + struct pvr2_hdw *hdw = ctxt->hdw; + struct v4l2_routing route; + + pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo"); + + if (hdw->input_val == PVR2_CVAL_INPUT_TV) { + struct v4l2_tuner vt; + memset(&vt,0,sizeof(vt)); + vt.audmode = hdw->audiomode_val; + pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_TUNER,&vt); + } + + route.input = MSP_INPUT_DEFAULT; + route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); + switch (hdw->input_val) { + case PVR2_CVAL_INPUT_TV: + break; + case PVR2_CVAL_INPUT_RADIO: + /* Assume that msp34xx also handle FM decoding, in which case + we're still using the tuner. */ + /* HV: actually it is more likely to be the SCART2 input if + the ivtv experience is any indication. */ + route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1, + MSP_DSP_IN_SCART, MSP_DSP_IN_SCART); + break; + case PVR2_CVAL_INPUT_SVIDEO: + case PVR2_CVAL_INPUT_COMPOSITE: + /* SCART 1 input */ + route.input = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, + MSP_DSP_IN_SCART, MSP_DSP_IN_SCART); + break; + } + pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route); +} + + +static int check_stereo(struct pvr2_msp3400_handler *ctxt) +{ + struct pvr2_hdw *hdw = ctxt->hdw; + return (hdw->input_dirty || + hdw->audiomode_dirty); +} + + +struct pvr2_msp3400_ops { + void (*update)(struct pvr2_msp3400_handler *); + int (*check)(struct pvr2_msp3400_handler *); +}; + + +static const struct pvr2_msp3400_ops msp3400_ops[] = { + { .update = set_stereo, .check = check_stereo}, +}; + + +static int msp3400_check(struct pvr2_msp3400_handler *ctxt) +{ + unsigned long msk; + unsigned int idx; + + for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]); + idx++) { + msk = 1 << idx; + if (ctxt->stale_mask & msk) continue; + if (msp3400_ops[idx].check(ctxt)) { + ctxt->stale_mask |= msk; + } + } + return ctxt->stale_mask != 0; +} + + +static void msp3400_update(struct pvr2_msp3400_handler *ctxt) +{ + unsigned long msk; + unsigned int idx; + + for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]); + idx++) { + msk = 1 << idx; + if (!(ctxt->stale_mask & msk)) continue; + ctxt->stale_mask &= ~msk; + msp3400_ops[idx].update(ctxt); + } +} + + +/* This reads back the current signal type */ +static int get_audio_status(struct pvr2_msp3400_handler *ctxt) +{ + struct v4l2_tuner vt; + int stat; + + memset(&vt,0,sizeof(vt)); + stat = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt); + if (stat < 0) return stat; + + ctxt->hdw->flag_stereo = (vt.audmode & V4L2_TUNER_MODE_STEREO) != 0; + ctxt->hdw->flag_bilingual = + (vt.audmode & V4L2_TUNER_MODE_LANG2) != 0; + return 0; +} + + +static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt) +{ + ctxt->client->handler = NULL; + ctxt->hdw->audio_stat = NULL; + kfree(ctxt); +} + + +static unsigned int pvr2_msp3400_describe(struct pvr2_msp3400_handler *ctxt, + char *buf,unsigned int cnt) +{ + return scnprintf(buf,cnt,"handler: pvrusb2-audio v4l2"); +} + + +const static struct pvr2_i2c_handler_functions msp3400_funcs = { + .detach = (void (*)(void *))pvr2_msp3400_detach, + .check = (int (*)(void *))msp3400_check, + .update = (void (*)(void *))msp3400_update, + .describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_msp3400_describe, +}; + + +int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) +{ + struct pvr2_msp3400_handler *ctxt; + if (hdw->audio_stat) return 0; + if (cp->handler) return 0; + + ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL); + if (!ctxt) return 0; + memset(ctxt,0,sizeof(*ctxt)); + + ctxt->i2c_handler.func_data = ctxt; + ctxt->i2c_handler.func_table = &msp3400_funcs; + ctxt->client = cp; + ctxt->hdw = hdw; + ctxt->astat.ctxt = ctxt; + ctxt->astat.status = (int (*)(void *))get_audio_status; + ctxt->astat.detach = (void (*)(void *))pvr2_msp3400_detach; + ctxt->stale_mask = (1 << (sizeof(msp3400_ops)/ + sizeof(msp3400_ops[0]))) - 1; + cp->handler = &ctxt->i2c_handler; + hdw->audio_stat = &ctxt->astat; + pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up", + cp->client->addr); + return !0; +} + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-audio.h b/drivers/media/video/pvrusb2/pvrusb2-audio.h new file mode 100644 index 000000000..536339b68 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-audio.h @@ -0,0 +1,40 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __PVRUSB2_AUDIO_H +#define __PVRUSB2_AUDIO_H + +#include "pvrusb2-i2c-core.h" + +int pvr2_i2c_msp3400_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); + +#endif /* __PVRUSB2_AUDIO_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.c b/drivers/media/video/pvrusb2/pvrusb2-context.c new file mode 100644 index 000000000..f129f316d --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-context.c @@ -0,0 +1,230 @@ +/* + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "pvrusb2-context.h" +#include "pvrusb2-io.h" +#include "pvrusb2-ioread.h" +#include "pvrusb2-hdw.h" +#include "pvrusb2-debug.h" +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <asm/semaphore.h> + + +static void pvr2_context_destroy(struct pvr2_context *mp) +{ + if (mp->hdw) pvr2_hdw_destroy(mp->hdw); + pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr_main id=%p",mp); + flush_workqueue(mp->workqueue); + destroy_workqueue(mp->workqueue); + kfree(mp); +} + + +static void pvr2_context_trigger_poll(struct pvr2_context *mp) +{ + queue_work(mp->workqueue,&mp->workpoll); +} + + +static void pvr2_context_poll(struct pvr2_context *mp) +{ + pvr2_context_enter(mp); do { + pvr2_hdw_poll(mp->hdw); + } while (0); pvr2_context_exit(mp); +} + + +static void pvr2_context_setup(struct pvr2_context *mp) +{ + pvr2_context_enter(mp); do { + if (!pvr2_hdw_dev_ok(mp->hdw)) break; + pvr2_hdw_setup(mp->hdw); + pvr2_hdw_setup_poll_trigger( + mp->hdw, + (void (*)(void *))pvr2_context_trigger_poll, + mp); + if (!pvr2_hdw_dev_ok(mp->hdw)) break; + if (!pvr2_hdw_init_ok(mp->hdw)) break; + mp->video_stream.stream = pvr2_hdw_get_video_stream(mp->hdw); + if (mp->setup_func) { + mp->setup_func(mp); + } + } while (0); pvr2_context_exit(mp); +} + + +struct pvr2_context *pvr2_context_create( + struct usb_interface *intf, + const struct usb_device_id *devid, + void (*setup_func)(struct pvr2_context *)) +{ + struct pvr2_context *mp = NULL; + mp = kmalloc(sizeof(*mp),GFP_KERNEL); + if (!mp) goto done; + memset(mp,0,sizeof(*mp)); + pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_main id=%p",mp); + mp->setup_func = setup_func; + mutex_init(&mp->mutex); + mp->hdw = pvr2_hdw_create(intf,devid); + if (!mp->hdw) { + pvr2_context_destroy(mp); + mp = NULL; + goto done; + } + + mp->workqueue = create_singlethread_workqueue("pvrusb2"); + INIT_WORK(&mp->workinit,(void (*)(void*))pvr2_context_setup,mp); + INIT_WORK(&mp->workpoll,(void (*)(void*))pvr2_context_poll,mp); + queue_work(mp->workqueue,&mp->workinit); + done: + return mp; +} + + +void pvr2_context_enter(struct pvr2_context *mp) +{ + mutex_lock(&mp->mutex); + pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_enter(id=%p)",mp); +} + + +void pvr2_context_exit(struct pvr2_context *mp) +{ + int destroy_flag = 0; + if (!(mp->mc_first || !mp->disconnect_flag)) { + destroy_flag = !0; + } + pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_exit(id=%p) outside",mp); + mutex_unlock(&mp->mutex); + if (destroy_flag) pvr2_context_destroy(mp); +} + + +static void pvr2_context_run_checks(struct pvr2_context *mp) +{ + struct pvr2_channel *ch1,*ch2; + for (ch1 = mp->mc_first; ch1; ch1 = ch2) { + ch2 = ch1->mc_next; + if (ch1->check_func) { + ch1->check_func(ch1); + } + } +} + + +void pvr2_context_disconnect(struct pvr2_context *mp) +{ + pvr2_context_enter(mp); do { + pvr2_hdw_disconnect(mp->hdw); + mp->disconnect_flag = !0; + pvr2_context_run_checks(mp); + } while (0); pvr2_context_exit(mp); +} + + +void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp) +{ + cp->hdw = mp->hdw; + cp->mc_head = mp; + cp->mc_next = NULL; + cp->mc_prev = mp->mc_last; + if (mp->mc_last) { + mp->mc_last->mc_next = cp; + } else { + mp->mc_first = cp; + } + mp->mc_last = cp; +} + + +static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp) +{ + if (!cp->stream) return; + pvr2_stream_kill(cp->stream->stream); + cp->stream->user = NULL; + cp->stream = NULL; +} + + +void pvr2_channel_done(struct pvr2_channel *cp) +{ + struct pvr2_context *mp = cp->mc_head; + pvr2_channel_disclaim_stream(cp); + if (cp->mc_next) { + cp->mc_next->mc_prev = cp->mc_prev; + } else { + mp->mc_last = cp->mc_prev; + } + if (cp->mc_prev) { + cp->mc_prev->mc_next = cp->mc_next; + } else { + mp->mc_first = cp->mc_next; + } + cp->hdw = NULL; +} + + +int pvr2_channel_claim_stream(struct pvr2_channel *cp, + struct pvr2_context_stream *sp) +{ + int code = 0; + pvr2_context_enter(cp->mc_head); do { + if (sp == cp->stream) break; + if (sp->user) { + code = -EBUSY; + break; + } + pvr2_channel_disclaim_stream(cp); + if (!sp) break; + sp->user = cp; + cp->stream = sp; + } while (0); pvr2_context_exit(cp->mc_head); + return code; +} + + +// This is the marker for the real beginning of a legitimate mpeg2 stream. +static char stream_sync_key[] = { + 0x00, 0x00, 0x01, 0xba, +}; + +struct pvr2_ioread *pvr2_channel_create_mpeg_stream( + struct pvr2_context_stream *sp) +{ + struct pvr2_ioread *cp; + cp = pvr2_ioread_create(); + if (!cp) return NULL; + pvr2_ioread_setup(cp,sp->stream); + pvr2_ioread_set_sync_key(cp,stream_sync_key,sizeof(stream_sync_key)); + return cp; +} + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-context.h b/drivers/media/video/pvrusb2/pvrusb2-context.h new file mode 100644 index 000000000..6327fa1f7 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-context.h @@ -0,0 +1,92 @@ +/* + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __PVRUSB2_BASE_H +#define __PVRUSB2_BASE_H + +#include <linux/mutex.h> +#include <linux/usb.h> +#include <linux/workqueue.h> + +struct pvr2_hdw; /* hardware interface - defined elsewhere */ +struct pvr2_stream; /* stream interface - defined elsewhere */ + +struct pvr2_context; /* All central state */ +struct pvr2_channel; /* One I/O pathway to a user */ +struct pvr2_context_stream; /* Wrapper for a stream */ +struct pvr2_crit_reg; /* Critical region pointer */ +struct pvr2_ioread; /* Low level stream structure */ + +struct pvr2_context_stream { + struct pvr2_channel *user; + struct pvr2_stream *stream; +}; + +struct pvr2_context { + struct pvr2_channel *mc_first; + struct pvr2_channel *mc_last; + struct pvr2_hdw *hdw; + struct pvr2_context_stream video_stream; + struct mutex mutex; + int disconnect_flag; + + /* Called after pvr2_context initialization is complete */ + void (*setup_func)(struct pvr2_context *); + + /* Work queue overhead for out-of-line processing */ + struct workqueue_struct *workqueue; + struct work_struct workinit; + struct work_struct workpoll; +}; + +struct pvr2_channel { + struct pvr2_context *mc_head; + struct pvr2_channel *mc_next; + struct pvr2_channel *mc_prev; + struct pvr2_context_stream *stream; + struct pvr2_hdw *hdw; + void (*check_func)(struct pvr2_channel *); +}; + +void pvr2_context_enter(struct pvr2_context *); +void pvr2_context_exit(struct pvr2_context *); + +struct pvr2_context *pvr2_context_create(struct usb_interface *intf, + const struct usb_device_id *devid, + void (*setup_func)(struct pvr2_context *)); +void pvr2_context_disconnect(struct pvr2_context *); + +void pvr2_channel_init(struct pvr2_channel *,struct pvr2_context *); +void pvr2_channel_done(struct pvr2_channel *); +int pvr2_channel_claim_stream(struct pvr2_channel *, + struct pvr2_context_stream *); +struct pvr2_ioread *pvr2_channel_create_mpeg_stream( + struct pvr2_context_stream *); + + +#endif /* __PVRUSB2_CONTEXT_H */ +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.c b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c new file mode 100644 index 000000000..c77de859c --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.c @@ -0,0 +1,602 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "pvrusb2-ctrl.h" +#include "pvrusb2-hdw-internal.h" +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mutex.h> + + +/* Set the given control. */ +int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val) +{ + return pvr2_ctrl_set_mask_value(cptr,~0,val); +} + + +/* Set/clear specific bits of the given control. */ +int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val) +{ + int ret = 0; + if (!cptr) return -EINVAL; + LOCK_TAKE(cptr->hdw->big_lock); do { + if (cptr->info->set_value != 0) { + if (cptr->info->type == pvr2_ctl_bitmask) { + mask &= cptr->info->def.type_bitmask.valid_bits; + } else if (cptr->info->type == pvr2_ctl_int) { + int lim; + lim = cptr->info->def.type_int.min_value; + if (cptr->info->get_min_value) { + cptr->info->get_min_value(cptr,&lim); + } + if (val < lim) break; + lim = cptr->info->def.type_int.max_value; + if (cptr->info->get_max_value) { + cptr->info->get_max_value(cptr,&lim); + } + if (val > lim) break; + } else if (cptr->info->type == pvr2_ctl_enum) { + if (val >= cptr->info->def.type_enum.count) { + break; + } + } else if (cptr->info->type != pvr2_ctl_bool) { + break; + } + ret = cptr->info->set_value(cptr,mask,val); + } else { + ret = -EPERM; + } + } while(0); LOCK_GIVE(cptr->hdw->big_lock); + return ret; +} + + +/* Get the current value of the given control. */ +int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr) +{ + int ret = 0; + if (!cptr) return -EINVAL; + LOCK_TAKE(cptr->hdw->big_lock); do { + ret = cptr->info->get_value(cptr,valptr); + } while(0); LOCK_GIVE(cptr->hdw->big_lock); + return ret; +} + + +/* Retrieve control's type */ +enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *cptr) +{ + if (!cptr) return pvr2_ctl_int; + return cptr->info->type; +} + + +/* Retrieve control's maximum value (int type) */ +int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr) +{ + int ret = 0; + if (!cptr) return 0; + LOCK_TAKE(cptr->hdw->big_lock); do { + if (cptr->info->get_max_value) { + cptr->info->get_max_value(cptr,&ret); + } else if (cptr->info->type == pvr2_ctl_int) { + ret = cptr->info->def.type_int.max_value; + } + } while(0); LOCK_GIVE(cptr->hdw->big_lock); + return ret; +} + + +/* Retrieve control's minimum value (int type) */ +int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr) +{ + int ret = 0; + if (!cptr) return 0; + LOCK_TAKE(cptr->hdw->big_lock); do { + if (cptr->info->get_min_value) { + cptr->info->get_min_value(cptr,&ret); + } else if (cptr->info->type == pvr2_ctl_int) { + ret = cptr->info->def.type_int.min_value; + } + } while(0); LOCK_GIVE(cptr->hdw->big_lock); + return ret; +} + + +/* Retrieve control's default value (any type) */ +int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr) +{ + int ret = 0; + if (!cptr) return 0; + LOCK_TAKE(cptr->hdw->big_lock); do { + if (cptr->info->type == pvr2_ctl_int) { + ret = cptr->info->default_value; + } + } while(0); LOCK_GIVE(cptr->hdw->big_lock); + return ret; +} + + +/* Retrieve control's enumeration count (enum only) */ +int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr) +{ + int ret = 0; + if (!cptr) return 0; + LOCK_TAKE(cptr->hdw->big_lock); do { + if (cptr->info->type == pvr2_ctl_enum) { + ret = cptr->info->def.type_enum.count; + } + } while(0); LOCK_GIVE(cptr->hdw->big_lock); + return ret; +} + + +/* Retrieve control's valid mask bits (bit mask only) */ +int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr) +{ + int ret = 0; + if (!cptr) return 0; + LOCK_TAKE(cptr->hdw->big_lock); do { + if (cptr->info->type == pvr2_ctl_bitmask) { + ret = cptr->info->def.type_bitmask.valid_bits; + } + } while(0); LOCK_GIVE(cptr->hdw->big_lock); + return ret; +} + + +/* Retrieve the control's name */ +const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr) +{ + if (!cptr) return NULL; + return cptr->info->name; +} + + +/* Retrieve the control's desc */ +const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr) +{ + if (!cptr) return NULL; + return cptr->info->desc; +} + + +/* Retrieve a control enumeration or bit mask value */ +int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val, + char *bptr,unsigned int bmax, + unsigned int *blen) +{ + int ret = -EINVAL; + if (!cptr) return 0; + *blen = 0; + LOCK_TAKE(cptr->hdw->big_lock); do { + if (cptr->info->type == pvr2_ctl_enum) { + const char **names; + names = cptr->info->def.type_enum.value_names; + if ((val >= 0) && + (val < cptr->info->def.type_enum.count)) { + if (names[val]) { + *blen = scnprintf( + bptr,bmax,"%s", + names[val]); + } else { + *blen = 0; + } + ret = 0; + } + } else if (cptr->info->type == pvr2_ctl_bitmask) { + const char **names; + unsigned int idx; + int msk; + names = cptr->info->def.type_bitmask.bit_names; + val &= cptr->info->def.type_bitmask.valid_bits; + for (idx = 0, msk = 1; val; idx++, msk <<= 1) { + if (val & msk) { + *blen = scnprintf(bptr,bmax,"%s", + names[idx]); + ret = 0; + break; + } + } + } + } while(0); LOCK_GIVE(cptr->hdw->big_lock); + return ret; +} + + +/* Return V4L ID for this control or zero if none */ +int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr) +{ + if (!cptr) return 0; + return cptr->info->v4l_id; +} + + +unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr) +{ + unsigned int flags = 0; + + if (cptr->info->get_v4lflags) { + flags = cptr->info->get_v4lflags(cptr); + } + + if (cptr->info->set_value) { + flags &= ~V4L2_CTRL_FLAG_READ_ONLY; + } else { + flags |= V4L2_CTRL_FLAG_READ_ONLY; + } + + return flags; +} + + +/* Return true if control is writable */ +int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr) +{ + if (!cptr) return 0; + return cptr->info->set_value != 0; +} + + +/* Return true if control has custom symbolic representation */ +int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr) +{ + if (!cptr) return 0; + if (!cptr->info->val_to_sym) return 0; + if (!cptr->info->sym_to_val) return 0; + return !0; +} + + +/* Convert a given mask/val to a custom symbolic value */ +int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr, + int mask,int val, + char *buf,unsigned int maxlen, + unsigned int *len) +{ + if (!cptr) return -EINVAL; + if (!cptr->info->val_to_sym) return -EINVAL; + return cptr->info->val_to_sym(cptr,mask,val,buf,maxlen,len); +} + + +/* Convert a symbolic value to a mask/value pair */ +int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *cptr, + const char *buf,unsigned int len, + int *maskptr,int *valptr) +{ + if (!cptr) return -EINVAL; + if (!cptr->info->sym_to_val) return -EINVAL; + return cptr->info->sym_to_val(cptr,buf,len,maskptr,valptr); +} + + +static unsigned int gen_bitmask_string(int msk,int val,int msk_only, + const char **names, + char *ptr,unsigned int len) +{ + unsigned int idx; + long sm,um; + int spcFl; + unsigned int uc,cnt; + const char *idStr; + + spcFl = 0; + uc = 0; + um = 0; + for (idx = 0, sm = 1; msk; idx++, sm <<= 1) { + if (sm & msk) { + msk &= ~sm; + idStr = names[idx]; + if (idStr) { + cnt = scnprintf(ptr,len,"%s%s%s", + (spcFl ? " " : ""), + (msk_only ? "" : + ((val & sm) ? "+" : "-")), + idStr); + ptr += cnt; len -= cnt; uc += cnt; + spcFl = !0; + } else { + um |= sm; + } + } + } + if (um) { + if (msk_only) { + cnt = scnprintf(ptr,len,"%s0x%lx", + (spcFl ? " " : ""), + um); + ptr += cnt; len -= cnt; uc += cnt; + spcFl = !0; + } else if (um & val) { + cnt = scnprintf(ptr,len,"%s+0x%lx", + (spcFl ? " " : ""), + um & val); + ptr += cnt; len -= cnt; uc += cnt; + spcFl = !0; + } else if (um & ~val) { + cnt = scnprintf(ptr,len,"%s+0x%lx", + (spcFl ? " " : ""), + um & ~val); + ptr += cnt; len -= cnt; uc += cnt; + spcFl = !0; + } + } + return uc; +} + + +static const char *boolNames[] = { + "false", + "true", + "no", + "yes", +}; + + +static int parse_token(const char *ptr,unsigned int len, + int *valptr, + const char **names,unsigned int namecnt) +{ + char buf[33]; + unsigned int slen; + unsigned int idx; + int negfl; + char *p2; + *valptr = 0; + if (!names) namecnt = 0; + for (idx = 0; idx < namecnt; idx++) { + if (!names[idx]) continue; + slen = strlen(names[idx]); + if (slen != len) continue; + if (memcmp(names[idx],ptr,slen)) continue; + *valptr = idx; + return 0; + } + negfl = 0; + if ((*ptr == '-') || (*ptr == '+')) { + negfl = (*ptr == '-'); + ptr++; len--; + } + if (len >= sizeof(buf)) return -EINVAL; + memcpy(buf,ptr,len); + buf[len] = 0; + *valptr = simple_strtol(buf,&p2,0); + if (negfl) *valptr = -(*valptr); + if (*p2) return -EINVAL; + return 1; +} + + +static int parse_mtoken(const char *ptr,unsigned int len, + int *valptr, + const char **names,int valid_bits) +{ + char buf[33]; + unsigned int slen; + unsigned int idx; + char *p2; + int msk; + *valptr = 0; + for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) { + if (!msk & valid_bits) continue; + valid_bits &= ~msk; + if (!names[idx]) continue; + slen = strlen(names[idx]); + if (slen != len) continue; + if (memcmp(names[idx],ptr,slen)) continue; + *valptr = msk; + return 0; + } + if (len >= sizeof(buf)) return -EINVAL; + memcpy(buf,ptr,len); + buf[len] = 0; + *valptr = simple_strtol(buf,&p2,0); + if (*p2) return -EINVAL; + return 0; +} + + +static int parse_tlist(const char *ptr,unsigned int len, + int *maskptr,int *valptr, + const char **names,int valid_bits) +{ + unsigned int cnt; + int mask,val,kv,mode,ret; + mask = 0; + val = 0; + ret = 0; + while (len) { + cnt = 0; + while ((cnt < len) && + ((ptr[cnt] <= 32) || + (ptr[cnt] >= 127))) cnt++; + ptr += cnt; + len -= cnt; + mode = 0; + if ((*ptr == '-') || (*ptr == '+')) { + mode = (*ptr == '-') ? -1 : 1; + ptr++; + len--; + } + cnt = 0; + while (cnt < len) { + if (ptr[cnt] <= 32) break; + if (ptr[cnt] >= 127) break; + cnt++; + } + if (!cnt) break; + if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) { + ret = -EINVAL; + break; + } + ptr += cnt; + len -= cnt; + switch (mode) { + case 0: + mask = valid_bits; + val |= kv; + break; + case -1: + mask |= kv; + val &= ~kv; + break; + case 1: + mask |= kv; + val |= kv; + break; + default: + break; + } + } + *maskptr = mask; + *valptr = val; + return ret; +} + + +/* Convert a symbolic value to a mask/value pair */ +int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr, + const char *ptr,unsigned int len, + int *maskptr,int *valptr) +{ + int ret = -EINVAL; + unsigned int cnt; + + *maskptr = 0; + *valptr = 0; + + cnt = 0; + while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++; + len -= cnt; ptr += cnt; + cnt = 0; + while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) || + (ptr[len-(cnt+1)] >= 127))) cnt++; + len -= cnt; + + if (!len) return -EINVAL; + + LOCK_TAKE(cptr->hdw->big_lock); do { + if (cptr->info->type == pvr2_ctl_int) { + ret = parse_token(ptr,len,valptr,NULL,0); + if ((ret >= 0) && + ((*valptr < cptr->info->def.type_int.min_value) || + (*valptr > cptr->info->def.type_int.max_value))) { + ret = -ERANGE; + } + if (maskptr) *maskptr = ~0; + } else if (cptr->info->type == pvr2_ctl_bool) { + ret = parse_token( + ptr,len,valptr,boolNames, + sizeof(boolNames)/sizeof(boolNames[0])); + if (ret == 1) { + *valptr = *valptr ? !0 : 0; + } else if (ret == 0) { + *valptr = (*valptr & 1) ? !0 : 0; + } + if (maskptr) *maskptr = 1; + } else if (cptr->info->type == pvr2_ctl_enum) { + ret = parse_token( + ptr,len,valptr, + cptr->info->def.type_enum.value_names, + cptr->info->def.type_enum.count); + if ((ret >= 0) && + ((*valptr < 0) || + (*valptr >= cptr->info->def.type_enum.count))) { + ret = -ERANGE; + } + if (maskptr) *maskptr = ~0; + } else if (cptr->info->type == pvr2_ctl_bitmask) { + ret = parse_tlist( + ptr,len,maskptr,valptr, + cptr->info->def.type_bitmask.bit_names, + cptr->info->def.type_bitmask.valid_bits); + } + } while(0); LOCK_GIVE(cptr->hdw->big_lock); + return ret; +} + + +/* Convert a given mask/val to a symbolic value */ +int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr, + int mask,int val, + char *buf,unsigned int maxlen, + unsigned int *len) +{ + int ret = -EINVAL; + + *len = 0; + if (cptr->info->type == pvr2_ctl_int) { + *len = scnprintf(buf,maxlen,"%d",val); + ret = 0; + } else if (cptr->info->type == pvr2_ctl_bool) { + *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false"); + ret = 0; + } else if (cptr->info->type == pvr2_ctl_enum) { + const char **names; + names = cptr->info->def.type_enum.value_names; + if ((val >= 0) && + (val < cptr->info->def.type_enum.count)) { + if (names[val]) { + *len = scnprintf( + buf,maxlen,"%s", + names[val]); + } else { + *len = 0; + } + ret = 0; + } + } else if (cptr->info->type == pvr2_ctl_bitmask) { + *len = gen_bitmask_string( + val & mask & cptr->info->def.type_bitmask.valid_bits, + ~0,!0, + cptr->info->def.type_bitmask.bit_names, + buf,maxlen); + } + return ret; +} + + +/* Convert a given mask/val to a symbolic value */ +int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr, + int mask,int val, + char *buf,unsigned int maxlen, + unsigned int *len) +{ + int ret; + LOCK_TAKE(cptr->hdw->big_lock); do { + ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val, + buf,maxlen,len); + } while(0); LOCK_GIVE(cptr->hdw->big_lock); + return ret; +} + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-ctrl.h b/drivers/media/video/pvrusb2/pvrusb2-ctrl.h new file mode 100644 index 000000000..c1680053c --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-ctrl.h @@ -0,0 +1,123 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __PVRUSB2_CTRL_H +#define __PVRUSB2_CTRL_H + +struct pvr2_ctrl; + +enum pvr2_ctl_type { + pvr2_ctl_int = 0, + pvr2_ctl_enum = 1, + pvr2_ctl_bitmask = 2, + pvr2_ctl_bool = 3, +}; + + +/* Set the given control. */ +int pvr2_ctrl_set_value(struct pvr2_ctrl *,int val); + +/* Set/clear specific bits of the given control. */ +int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *,int mask,int val); + +/* Get the current value of the given control. */ +int pvr2_ctrl_get_value(struct pvr2_ctrl *,int *valptr); + +/* Retrieve control's type */ +enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *); + +/* Retrieve control's maximum value (int type) */ +int pvr2_ctrl_get_max(struct pvr2_ctrl *); + +/* Retrieve control's minimum value (int type) */ +int pvr2_ctrl_get_min(struct pvr2_ctrl *); + +/* Retrieve control's default value (any type) */ +int pvr2_ctrl_get_def(struct pvr2_ctrl *); + +/* Retrieve control's enumeration count (enum only) */ +int pvr2_ctrl_get_cnt(struct pvr2_ctrl *); + +/* Retrieve control's valid mask bits (bit mask only) */ +int pvr2_ctrl_get_mask(struct pvr2_ctrl *); + +/* Retrieve the control's name */ +const char *pvr2_ctrl_get_name(struct pvr2_ctrl *); + +/* Retrieve the control's desc */ +const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *); + +/* Retrieve a control enumeration or bit mask value */ +int pvr2_ctrl_get_valname(struct pvr2_ctrl *,int,char *,unsigned int, + unsigned int *); + +/* Return true if control is writable */ +int pvr2_ctrl_is_writable(struct pvr2_ctrl *); + +/* Return V4L flags value for control (or zero if there is no v4l control + actually under this control) */ +unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *); + +/* Return V4L ID for this control or zero if none */ +int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *); + +/* Return true if control has custom symbolic representation */ +int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *); + +/* Convert a given mask/val to a custom symbolic value */ +int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *, + int mask,int val, + char *buf,unsigned int maxlen, + unsigned int *len); + +/* Convert a symbolic value to a mask/value pair */ +int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *, + const char *buf,unsigned int len, + int *maskptr,int *valptr); + +/* Convert a given mask/val to a symbolic value */ +int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *, + int mask,int val, + char *buf,unsigned int maxlen, + unsigned int *len); + +/* Convert a symbolic value to a mask/value pair */ +int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *, + const char *buf,unsigned int len, + int *maskptr,int *valptr); + +/* Convert a given mask/val to a symbolic value - must already be + inside of critical region. */ +int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *, + int mask,int val, + char *buf,unsigned int maxlen, + unsigned int *len); + +#endif /* __PVRUSB2_CTRL_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c new file mode 100644 index 000000000..c80c26be6 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -0,0 +1,279 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + + This source file is specifically designed to interface with the + cx2584x, in kernels 2.6.16 or newer. + +*/ + +#include "pvrusb2-cx2584x-v4l.h" +#include "pvrusb2-video-v4l.h" +#include "pvrusb2-i2c-cmd-v4l2.h" + + +#include "pvrusb2-hdw-internal.h" +#include "pvrusb2-debug.h" +#include <media/cx25840.h> +#include <linux/videodev2.h> +#include <media/v4l2-common.h> +#include <linux/errno.h> +#include <linux/slab.h> + +struct pvr2_v4l_cx2584x { + struct pvr2_i2c_handler handler; + struct pvr2_decoder_ctrl ctrl; + struct pvr2_i2c_client *client; + struct pvr2_hdw *hdw; + unsigned long stale_mask; +}; + + +static void set_input(struct pvr2_v4l_cx2584x *ctxt) +{ + struct pvr2_hdw *hdw = ctxt->hdw; + struct v4l2_routing route; + enum cx25840_video_input vid_input; + enum cx25840_audio_input aud_input; + + memset(&route,0,sizeof(route)); + + switch(hdw->input_val) { + case PVR2_CVAL_INPUT_TV: + vid_input = CX25840_COMPOSITE7; + aud_input = CX25840_AUDIO8; + break; + case PVR2_CVAL_INPUT_COMPOSITE: + vid_input = CX25840_COMPOSITE3; + aud_input = CX25840_AUDIO_SERIAL; + break; + case PVR2_CVAL_INPUT_SVIDEO: + vid_input = CX25840_SVIDEO1; + aud_input = CX25840_AUDIO_SERIAL; + break; + case PVR2_CVAL_INPUT_RADIO: + default: + // Just set it to be composite input for now... + vid_input = CX25840_COMPOSITE3; + aud_input = CX25840_AUDIO_SERIAL; + break; + } + + pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_input vid=0x%x aud=0x%x", + vid_input,aud_input); + route.input = (u32)vid_input; + pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route); + route.input = (u32)aud_input; + pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route); +} + + +static int check_input(struct pvr2_v4l_cx2584x *ctxt) +{ + struct pvr2_hdw *hdw = ctxt->hdw; + return hdw->input_dirty != 0; +} + + +static void set_audio(struct pvr2_v4l_cx2584x *ctxt) +{ + u32 val; + struct pvr2_hdw *hdw = ctxt->hdw; + + pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx2584x set_audio %d", + hdw->srate_val); + switch (hdw->srate_val) { + default: + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: + val = 48000; + break; + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: + val = 44100; + break; + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: + val = 32000; + break; + } + pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val); +} + + +static int check_audio(struct pvr2_v4l_cx2584x *ctxt) +{ + struct pvr2_hdw *hdw = ctxt->hdw; + return hdw->srate_dirty != 0; +} + + +struct pvr2_v4l_cx2584x_ops { + void (*update)(struct pvr2_v4l_cx2584x *); + int (*check)(struct pvr2_v4l_cx2584x *); +}; + + +static const struct pvr2_v4l_cx2584x_ops decoder_ops[] = { + { .update = set_input, .check = check_input}, + { .update = set_audio, .check = check_audio}, +}; + + +static void decoder_detach(struct pvr2_v4l_cx2584x *ctxt) +{ + ctxt->client->handler = NULL; + ctxt->hdw->decoder_ctrl = NULL; + kfree(ctxt); +} + + +static int decoder_check(struct pvr2_v4l_cx2584x *ctxt) +{ + unsigned long msk; + unsigned int idx; + + for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]); + idx++) { + msk = 1 << idx; + if (ctxt->stale_mask & msk) continue; + if (decoder_ops[idx].check(ctxt)) { + ctxt->stale_mask |= msk; + } + } + return ctxt->stale_mask != 0; +} + + +static void decoder_update(struct pvr2_v4l_cx2584x *ctxt) +{ + unsigned long msk; + unsigned int idx; + + for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]); + idx++) { + msk = 1 << idx; + if (!(ctxt->stale_mask & msk)) continue; + ctxt->stale_mask &= ~msk; + decoder_ops[idx].update(ctxt); + } +} + + +static void decoder_enable(struct pvr2_v4l_cx2584x *ctxt,int fl) +{ + pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_enable(%d)",fl); + pvr2_v4l2_cmd_stream(ctxt->client,fl); +} + + +static int decoder_detect(struct pvr2_i2c_client *cp) +{ + int ret; + /* Attempt to query the decoder - let's see if it will answer */ + struct v4l2_queryctrl qc; + + memset(&qc,0,sizeof(qc)); + + qc.id = V4L2_CID_BRIGHTNESS; + + ret = pvr2_i2c_client_cmd(cp,VIDIOC_QUERYCTRL,&qc); + return ret == 0; /* Return true if it answered */ +} + + +static int decoder_is_tuned(struct pvr2_v4l_cx2584x *ctxt) +{ + struct v4l2_tuner vt; + int ret; + + memset(&vt,0,sizeof(vt)); + ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt); + if (ret < 0) return -EINVAL; + return vt.signal ? 1 : 0; +} + + +static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt, + char *buf,unsigned int cnt) +{ + return scnprintf(buf,cnt,"handler: pvrusb2-cx2584x-v4l"); +} + + +static void decoder_reset(struct pvr2_v4l_cx2584x *ctxt) +{ + int ret; + ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_RESET,NULL); + pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_reset (ret=%d)",ret); +} + + +const static struct pvr2_i2c_handler_functions hfuncs = { + .detach = (void (*)(void *))decoder_detach, + .check = (int (*)(void *))decoder_check, + .update = (void (*)(void *))decoder_update, + .describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe, +}; + + +int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *hdw, + struct pvr2_i2c_client *cp) +{ + struct pvr2_v4l_cx2584x *ctxt; + + if (hdw->decoder_ctrl) return 0; + if (cp->handler) return 0; + if (!decoder_detect(cp)) return 0; + + ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL); + if (!ctxt) return 0; + memset(ctxt,0,sizeof(*ctxt)); + + ctxt->handler.func_data = ctxt; + ctxt->handler.func_table = &hfuncs; + ctxt->ctrl.ctxt = ctxt; + ctxt->ctrl.detach = (void (*)(void *))decoder_detach; + ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; + ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned; + ctxt->ctrl.force_reset = (void (*)(void*))decoder_reset; + ctxt->client = cp; + ctxt->hdw = hdw; + ctxt->stale_mask = (1 << (sizeof(decoder_ops)/ + sizeof(decoder_ops[0]))) - 1; + hdw->decoder_ctrl = &ctxt->ctrl; + cp->handler = &ctxt->handler; + pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x cx2584x V4L2 handler set up", + cp->client->addr); + return !0; +} + + + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h new file mode 100644 index 000000000..54b2844e7 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h @@ -0,0 +1,53 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __PVRUSB2_CX2584X_V4L_H +#define __PVRUSB2_CX2584X_V4L_H + +/* + + This module connects the pvrusb2 driver to the I2C chip level + driver which handles combined device audio & video processing. + This interface is used internally by the driver; higher level code + should only interact through the interface provided by + pvrusb2-hdw.h. + +*/ + + + +#include "pvrusb2-i2c-core.h" + +int pvr2_i2c_cx2584x_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); + + +#endif /* __PVRUSB2_CX2584X_V4L_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-debug.h b/drivers/media/video/pvrusb2/pvrusb2-debug.h new file mode 100644 index 000000000..d95a8588e --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-debug.h @@ -0,0 +1,67 @@ +/* + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __PVRUSB2_DEBUG_H +#define __PVRUSB2_DEBUG_H + +extern int pvrusb2_debug; + +#define pvr2_trace(msk, fmt, arg...) do {if(msk & pvrusb2_debug) printk(KERN_INFO "pvrusb2: " fmt "\n", ##arg); } while (0) + +/* These are listed in *rough* order of decreasing usefulness and + increasing noise level. */ +#define PVR2_TRACE_INFO (1 << 0) // Normal messages +#define PVR2_TRACE_ERROR_LEGS (1 << 1) // error messages +#define PVR2_TRACE_TOLERANCE (1 << 2) // track tolerance-affected errors +#define PVR2_TRACE_TRAP (1 << 3) // Trap & report misbehavior from app +#define PVR2_TRACE_INIT (1 << 4) // misc initialization steps +#define PVR2_TRACE_START_STOP (1 << 5) // Streaming start / stop +#define PVR2_TRACE_CTL (1 << 6) // commit of control changes +#define PVR2_TRACE_DEBUG (1 << 7) // Temporary debug code +#define PVR2_TRACE_EEPROM (1 << 8) // eeprom parsing / report +#define PVR2_TRACE_STRUCT (1 << 9) // internal struct creation +#define PVR2_TRACE_OPEN_CLOSE (1 << 10) // application open / close +#define PVR2_TRACE_CREG (1 << 11) // Main critical region entry / exit +#define PVR2_TRACE_SYSFS (1 << 12) // Sysfs driven I/O +#define PVR2_TRACE_FIRMWARE (1 << 13) // firmware upload actions +#define PVR2_TRACE_CHIPS (1 << 14) // chip broadcast operation +#define PVR2_TRACE_I2C (1 << 15) // I2C related stuff +#define PVR2_TRACE_I2C_CMD (1 << 16) // Software commands to I2C modules +#define PVR2_TRACE_I2C_CORE (1 << 17) // I2C core debugging +#define PVR2_TRACE_I2C_TRAF (1 << 18) // I2C traffic through the adapter +#define PVR2_TRACE_V4LIOCTL (1 << 19) // v4l ioctl details +#define PVR2_TRACE_ENCODER (1 << 20) // mpeg2 encoder operation +#define PVR2_TRACE_BUF_POOL (1 << 21) // Track buffer pool management +#define PVR2_TRACE_BUF_FLOW (1 << 22) // Track buffer flow in system +#define PVR2_TRACE_DATA_FLOW (1 << 23) // Track data flow +#define PVR2_TRACE_DEBUGIFC (1 << 24) // Debug interface actions +#define PVR2_TRACE_GPIO (1 << 25) // GPIO state bit changes + + +#endif /* __PVRUSB2_HDW_INTERNAL_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.c b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c new file mode 100644 index 000000000..f985f00d8 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.c @@ -0,0 +1,478 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/string.h> +#include <linux/slab.h> +#include "pvrusb2-debugifc.h" +#include "pvrusb2-hdw.h" +#include "pvrusb2-debug.h" +#include "pvrusb2-i2c-core.h" + +struct debugifc_mask_item { + const char *name; + unsigned long msk; +}; + +static struct debugifc_mask_item mask_items[] = { + {"ENC_FIRMWARE",(1<<PVR2_SUBSYS_B_ENC_FIRMWARE)}, + {"ENC_CFG",(1<<PVR2_SUBSYS_B_ENC_CFG)}, + {"DIG_RUN",(1<<PVR2_SUBSYS_B_DIGITIZER_RUN)}, + {"USB_RUN",(1<<PVR2_SUBSYS_B_USBSTREAM_RUN)}, + {"ENC_RUN",(1<<PVR2_SUBSYS_B_ENC_RUN)}, +}; + + +static unsigned int debugifc_count_whitespace(const char *buf, + unsigned int count) +{ + unsigned int scnt; + char ch; + + for (scnt = 0; scnt < count; scnt++) { + ch = buf[scnt]; + if (ch == ' ') continue; + if (ch == '\t') continue; + if (ch == '\n') continue; + break; + } + return scnt; +} + + +static unsigned int debugifc_count_nonwhitespace(const char *buf, + unsigned int count) +{ + unsigned int scnt; + char ch; + + for (scnt = 0; scnt < count; scnt++) { + ch = buf[scnt]; + if (ch == ' ') break; + if (ch == '\t') break; + if (ch == '\n') break; + } + return scnt; +} + + +static unsigned int debugifc_isolate_word(const char *buf,unsigned int count, + const char **wstrPtr, + unsigned int *wlenPtr) +{ + const char *wptr; + unsigned int consume_cnt = 0; + unsigned int wlen; + unsigned int scnt; + + wptr = NULL; + wlen = 0; + scnt = debugifc_count_whitespace(buf,count); + consume_cnt += scnt; count -= scnt; buf += scnt; + if (!count) goto done; + + scnt = debugifc_count_nonwhitespace(buf,count); + if (!scnt) goto done; + wptr = buf; + wlen = scnt; + consume_cnt += scnt; count -= scnt; buf += scnt; + + done: + *wstrPtr = wptr; + *wlenPtr = wlen; + return consume_cnt; +} + + +static int debugifc_parse_unsigned_number(const char *buf,unsigned int count, + u32 *num_ptr) +{ + u32 result = 0; + u32 val; + int ch; + int radix = 10; + if ((count >= 2) && (buf[0] == '0') && + ((buf[1] == 'x') || (buf[1] == 'X'))) { + radix = 16; + count -= 2; + buf += 2; + } else if ((count >= 1) && (buf[0] == '0')) { + radix = 8; + } + + while (count--) { + ch = *buf++; + if ((ch >= '0') && (ch <= '9')) { + val = ch - '0'; + } else if ((ch >= 'a') && (ch <= 'f')) { + val = ch - 'a' + 10; + } else if ((ch >= 'A') && (ch <= 'F')) { + val = ch - 'A' + 10; + } else { + return -EINVAL; + } + if (val >= radix) return -EINVAL; + result *= radix; + result += val; + } + *num_ptr = result; + return 0; +} + + +static int debugifc_match_keyword(const char *buf,unsigned int count, + const char *keyword) +{ + unsigned int kl; + if (!keyword) return 0; + kl = strlen(keyword); + if (kl != count) return 0; + return !memcmp(buf,keyword,kl); +} + + +static unsigned long debugifc_find_mask(const char *buf,unsigned int count) +{ + struct debugifc_mask_item *mip; + unsigned int idx; + for (idx = 0; idx < sizeof(mask_items)/sizeof(mask_items[0]); idx++) { + mip = mask_items + idx; + if (debugifc_match_keyword(buf,count,mip->name)) { + return mip->msk; + } + } + return 0; +} + + +static int debugifc_print_mask(char *buf,unsigned int sz, + unsigned long msk,unsigned long val) +{ + struct debugifc_mask_item *mip; + unsigned int idx; + int bcnt = 0; + int ccnt; + for (idx = 0; idx < sizeof(mask_items)/sizeof(mask_items[0]); idx++) { + mip = mask_items + idx; + if (!(mip->msk & msk)) continue; + ccnt = scnprintf(buf,sz,"%s%c%s", + (bcnt ? " " : ""), + ((mip->msk & val) ? '+' : '-'), + mip->name); + sz -= ccnt; + buf += ccnt; + bcnt += ccnt; + } + return bcnt; +} + +static unsigned int debugifc_parse_subsys_mask(const char *buf, + unsigned int count, + unsigned long *mskPtr, + unsigned long *valPtr) +{ + const char *wptr; + unsigned int consume_cnt = 0; + unsigned int scnt; + unsigned int wlen; + int mode; + unsigned long m1,msk,val; + + msk = 0; + val = 0; + + while (count) { + scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); + if (!scnt) break; + consume_cnt += scnt; count -= scnt; buf += scnt; + if (!wptr) break; + + mode = 0; + if (wlen) switch (wptr[0]) { + case '+': + wptr++; + wlen--; + break; + case '-': + mode = 1; + wptr++; + wlen--; + break; + } + if (!wlen) continue; + m1 = debugifc_find_mask(wptr,wlen); + if (!m1) break; + msk |= m1; + if (!mode) val |= m1; + } + *mskPtr = msk; + *valPtr = val; + return consume_cnt; +} + + +int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt) +{ + int bcnt = 0; + int ccnt; + struct pvr2_hdw_debug_info dbg; + + pvr2_hdw_get_debug_info(hdw,&dbg); + + ccnt = scnprintf(buf,acnt,"big lock %s; ctl lock %s", + (dbg.big_lock_held ? "held" : "free"), + (dbg.ctl_lock_held ? "held" : "free")); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + if (dbg.ctl_lock_held) { + ccnt = scnprintf(buf,acnt,"; cmd_state=%d cmd_code=%d" + " cmd_wlen=%d cmd_rlen=%d" + " wpend=%d rpend=%d tmout=%d rstatus=%d" + " wstatus=%d", + dbg.cmd_debug_state,dbg.cmd_code, + dbg.cmd_debug_write_len, + dbg.cmd_debug_read_len, + dbg.cmd_debug_write_pend, + dbg.cmd_debug_read_pend, + dbg.cmd_debug_timeout, + dbg.cmd_debug_rstatus, + dbg.cmd_debug_wstatus); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + } + ccnt = scnprintf(buf,acnt,"\n"); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + ccnt = scnprintf( + buf,acnt,"driver flags: %s %s %s\n", + (dbg.flag_init_ok ? "initialized" : "uninitialized"), + (dbg.flag_ok ? "ok" : "fail"), + (dbg.flag_disconnected ? "disconnected" : "connected")); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + ccnt = scnprintf(buf,acnt,"Subsystems enabled / configured: "); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + ccnt = debugifc_print_mask(buf,acnt,dbg.subsys_flags,dbg.subsys_flags); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + ccnt = scnprintf(buf,acnt,"\n"); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + ccnt = scnprintf(buf,acnt,"Subsystems disabled / unconfigured: "); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + ccnt = debugifc_print_mask(buf,acnt,~dbg.subsys_flags,dbg.subsys_flags); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + ccnt = scnprintf(buf,acnt,"\n"); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + + ccnt = scnprintf(buf,acnt,"Attached I2C modules:\n"); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + ccnt = pvr2_i2c_report(hdw,buf,acnt); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + + return bcnt; +} + + +int pvr2_debugifc_print_status(struct pvr2_hdw *hdw, + char *buf,unsigned int acnt) +{ + int bcnt = 0; + int ccnt; + unsigned long msk; + int ret; + u32 gpio_dir,gpio_in,gpio_out; + + ret = pvr2_hdw_is_hsm(hdw); + ccnt = scnprintf(buf,acnt,"USB link speed: %s\n", + (ret < 0 ? "FAIL" : (ret ? "high" : "full"))); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + + gpio_dir = 0; gpio_in = 0; gpio_out = 0; + pvr2_hdw_gpio_get_dir(hdw,&gpio_dir); + pvr2_hdw_gpio_get_out(hdw,&gpio_out); + pvr2_hdw_gpio_get_in(hdw,&gpio_in); + ccnt = scnprintf(buf,acnt,"GPIO state: dir=0x%x in=0x%x out=0x%x\n", + gpio_dir,gpio_in,gpio_out); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + + ccnt = scnprintf(buf,acnt,"Streaming is %s\n", + pvr2_hdw_get_streaming(hdw) ? "on" : "off"); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + + msk = pvr2_hdw_subsys_get(hdw); + ccnt = scnprintf(buf,acnt,"Subsystems enabled / configured: "); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + ccnt = debugifc_print_mask(buf,acnt,msk,msk); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + ccnt = scnprintf(buf,acnt,"\n"); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + ccnt = scnprintf(buf,acnt,"Subsystems disabled / unconfigured: "); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + ccnt = debugifc_print_mask(buf,acnt,~msk,msk); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + ccnt = scnprintf(buf,acnt,"\n"); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + + msk = pvr2_hdw_subsys_stream_get(hdw); + ccnt = scnprintf(buf,acnt,"Subsystems stopped on stream shutdown: "); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + ccnt = debugifc_print_mask(buf,acnt,msk,msk); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + ccnt = scnprintf(buf,acnt,"\n"); + bcnt += ccnt; acnt -= ccnt; buf += ccnt; + + return bcnt; +} + + +static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf, + unsigned int count) +{ + const char *wptr; + unsigned int wlen; + unsigned int scnt; + + scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); + if (!scnt) return 0; + count -= scnt; buf += scnt; + if (!wptr) return 0; + + pvr2_trace(PVR2_TRACE_DEBUGIFC,"debugifc cmd: \"%.*s\"",wlen,wptr); + if (debugifc_match_keyword(wptr,wlen,"reset")) { + scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); + if (!scnt) return -EINVAL; + count -= scnt; buf += scnt; + if (!wptr) return -EINVAL; + if (debugifc_match_keyword(wptr,wlen,"cpu")) { + pvr2_hdw_cpureset_assert(hdw,!0); + pvr2_hdw_cpureset_assert(hdw,0); + return 0; + } else if (debugifc_match_keyword(wptr,wlen,"bus")) { + pvr2_hdw_device_reset(hdw); + } else if (debugifc_match_keyword(wptr,wlen,"soft")) { + return pvr2_hdw_cmd_powerup(hdw); + } else if (debugifc_match_keyword(wptr,wlen,"deep")) { + return pvr2_hdw_cmd_deep_reset(hdw); + } else if (debugifc_match_keyword(wptr,wlen,"firmware")) { + return pvr2_upload_firmware2(hdw); + } else if (debugifc_match_keyword(wptr,wlen,"decoder")) { + return pvr2_hdw_cmd_decoder_reset(hdw); + } + return -EINVAL; + } else if (debugifc_match_keyword(wptr,wlen,"subsys_flags")) { + unsigned long msk = 0; + unsigned long val = 0; + if (debugifc_parse_subsys_mask(buf,count,&msk,&val) != count) { + pvr2_trace(PVR2_TRACE_DEBUGIFC, + "debugifc parse error on subsys mask"); + return -EINVAL; + } + pvr2_hdw_subsys_bit_chg(hdw,msk,val); + return 0; + } else if (debugifc_match_keyword(wptr,wlen,"stream_flags")) { + unsigned long msk = 0; + unsigned long val = 0; + if (debugifc_parse_subsys_mask(buf,count,&msk,&val) != count) { + pvr2_trace(PVR2_TRACE_DEBUGIFC, + "debugifc parse error on stream mask"); + return -EINVAL; + } + pvr2_hdw_subsys_stream_bit_chg(hdw,msk,val); + return 0; + } else if (debugifc_match_keyword(wptr,wlen,"cpufw")) { + scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); + if (!scnt) return -EINVAL; + count -= scnt; buf += scnt; + if (!wptr) return -EINVAL; + if (debugifc_match_keyword(wptr,wlen,"fetch")) { + pvr2_hdw_cpufw_set_enabled(hdw,!0); + return 0; + } else if (debugifc_match_keyword(wptr,wlen,"done")) { + pvr2_hdw_cpufw_set_enabled(hdw,0); + return 0; + } else { + return -EINVAL; + } + } else if (debugifc_match_keyword(wptr,wlen,"gpio")) { + int dir_fl = 0; + int ret; + u32 msk,val; + scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); + if (!scnt) return -EINVAL; + count -= scnt; buf += scnt; + if (!wptr) return -EINVAL; + if (debugifc_match_keyword(wptr,wlen,"dir")) { + dir_fl = !0; + } else if (!debugifc_match_keyword(wptr,wlen,"out")) { + return -EINVAL; + } + scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); + if (!scnt) return -EINVAL; + count -= scnt; buf += scnt; + if (!wptr) return -EINVAL; + ret = debugifc_parse_unsigned_number(wptr,wlen,&msk); + if (ret) return ret; + scnt = debugifc_isolate_word(buf,count,&wptr,&wlen); + if (wptr) { + ret = debugifc_parse_unsigned_number(wptr,wlen,&val); + if (ret) return ret; + } else { + val = msk; + msk = 0xffffffff; + } + if (dir_fl) { + ret = pvr2_hdw_gpio_chg_dir(hdw,msk,val); + } else { + ret = pvr2_hdw_gpio_chg_out(hdw,msk,val); + } + return ret; + } + pvr2_trace(PVR2_TRACE_DEBUGIFC, + "debugifc failed to recognize cmd: \"%.*s\"",wlen,wptr); + return -EINVAL; +} + + +int pvr2_debugifc_docmd(struct pvr2_hdw *hdw,const char *buf, + unsigned int count) +{ + unsigned int bcnt = 0; + int ret; + + while (count) { + for (bcnt = 0; bcnt < count; bcnt++) { + if (buf[bcnt] == '\n') break; + } + + ret = pvr2_debugifc_do1cmd(hdw,buf,bcnt); + if (ret < 0) return ret; + if (bcnt < count) bcnt++; + buf += bcnt; + count -= bcnt; + } + + return 0; +} + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-debugifc.h b/drivers/media/video/pvrusb2/pvrusb2-debugifc.h new file mode 100644 index 000000000..990b02d35 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-debugifc.h @@ -0,0 +1,53 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __PVRUSB2_DEBUGIFC_H +#define __PVRUSB2_DEBUGIFC_H + +struct pvr2_hdw; + +/* Non-intrusively print some useful debugging info from inside the + driver. This should work even if the driver appears to be + wedged. */ +int pvr2_debugifc_print_info(struct pvr2_hdw *, + char *buf_ptr,unsigned int buf_size); + +/* Print general status of driver. This will also trigger a probe of + the USB link. Unlike print_info(), this one synchronizes with the + driver so the information should be self-consistent (but it will + hang if the driver is wedged). */ +int pvr2_debugifc_print_status(struct pvr2_hdw *, + char *buf_ptr,unsigned int buf_size); + +/* Parse a string command into a driver action. */ +int pvr2_debugifc_docmd(struct pvr2_hdw *, + const char *buf_ptr,unsigned int buf_size); + +#endif /* __PVRUSB2_DEBUGIFC_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-eeprom.c b/drivers/media/video/pvrusb2/pvrusb2-eeprom.c new file mode 100644 index 000000000..6cff8e75f --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-eeprom.c @@ -0,0 +1,164 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "pvrusb2-eeprom.h" +#include "pvrusb2-hdw-internal.h" +#include "pvrusb2-debug.h" + +#define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__) + + + +/* + + Read and analyze data in the eeprom. Use tveeprom to figure out + the packet structure, since this is another Hauppauge device and + internally it has a family resemblence to ivtv-type devices + +*/ + +#include <media/tveeprom.h> + +/* We seem to only be interested in the last 128 bytes of the EEPROM */ +#define EEPROM_SIZE 128 + +/* Grab EEPROM contents, needed for direct method. */ +static u8 *pvr2_eeprom_fetch(struct pvr2_hdw *hdw) +{ + struct i2c_msg msg[2]; + u8 *eeprom; + u8 iadd[2]; + u8 addr; + u16 eepromSize; + unsigned int offs; + int ret; + int mode16 = 0; + unsigned pcnt,tcnt; + eeprom = kmalloc(EEPROM_SIZE,GFP_KERNEL); + if (!eeprom) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Failed to allocate memory" + " required to read eeprom"); + return NULL; + } + + trace_eeprom("Value for eeprom addr from controller was 0x%x", + hdw->eeprom_addr); + addr = hdw->eeprom_addr; + /* Seems that if the high bit is set, then the *real* eeprom + address is shifted right now bit position (noticed this in + newer PVR USB2 hardware) */ + if (addr & 0x80) addr >>= 1; + + /* FX2 documentation states that a 16bit-addressed eeprom is + expected if the I2C address is an odd number (yeah, this is + strange but it's what they do) */ + mode16 = (addr & 1); + eepromSize = (mode16 ? 4096 : 256); + trace_eeprom("Examining %d byte eeprom at location 0x%x" + " using %d bit addressing",eepromSize,addr, + mode16 ? 16 : 8); + + msg[0].addr = addr; + msg[0].flags = 0; + msg[0].len = mode16 ? 2 : 1; + msg[0].buf = iadd; + msg[1].addr = addr; + msg[1].flags = I2C_M_RD; + + /* We have to do the actual eeprom data fetch ourselves, because + (1) we're only fetching part of the eeprom, and (2) if we were + getting the whole thing our I2C driver can't grab it in one + pass - which is what tveeprom is otherwise going to attempt */ + memset(eeprom,0,EEPROM_SIZE); + for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) { + pcnt = 16; + if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt; + offs = tcnt + (eepromSize - EEPROM_SIZE); + if (mode16) { + iadd[0] = offs >> 8; + iadd[1] = offs; + } else { + iadd[0] = offs; + } + msg[1].len = pcnt; + msg[1].buf = eeprom+tcnt; + if ((ret = i2c_transfer( + &hdw->i2c_adap, + msg,sizeof(msg)/sizeof(msg[0]))) != 2) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "eeprom fetch set offs err=%d",ret); + kfree(eeprom); + return NULL; + } + } + return eeprom; +} + + +/* Directly call eeprom analysis function within tveeprom. */ +int pvr2_eeprom_analyze(struct pvr2_hdw *hdw) +{ + u8 *eeprom; + struct tveeprom tvdata; + + memset(&tvdata,0,sizeof(tvdata)); + + eeprom = pvr2_eeprom_fetch(hdw); + if (!eeprom) return -EINVAL; + + { + struct i2c_client fake_client; + /* Newer version expects a useless client interface */ + fake_client.addr = hdw->eeprom_addr; + fake_client.adapter = &hdw->i2c_adap; + tveeprom_hauppauge_analog(&fake_client,&tvdata,eeprom); + } + + trace_eeprom("eeprom assumed v4l tveeprom module"); + trace_eeprom("eeprom direct call results:"); + trace_eeprom("has_radio=%d",tvdata.has_radio); + trace_eeprom("tuner_type=%d",tvdata.tuner_type); + trace_eeprom("tuner_formats=0x%x",tvdata.tuner_formats); + trace_eeprom("audio_processor=%d",tvdata.audio_processor); + trace_eeprom("model=%d",tvdata.model); + trace_eeprom("revision=%d",tvdata.revision); + trace_eeprom("serial_number=%d",tvdata.serial_number); + trace_eeprom("rev_str=%s",tvdata.rev_str); + hdw->tuner_type = tvdata.tuner_type; + hdw->serial_number = tvdata.serial_number; + hdw->std_mask_eeprom = tvdata.tuner_formats; + + kfree(eeprom); + + return 0; +} + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-eeprom.h b/drivers/media/video/pvrusb2/pvrusb2-eeprom.h new file mode 100644 index 000000000..84242975d --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-eeprom.h @@ -0,0 +1,40 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __PVRUSB2_EEPROM_H +#define __PVRUSB2_EEPROM_H + +struct pvr2_hdw; + +int pvr2_eeprom_analyze(struct pvr2_hdw *); + +#endif /* __PVRUSB2_EEPROM_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c new file mode 100644 index 000000000..18a707350 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c @@ -0,0 +1,418 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/device.h> // for linux/firmware.h +#include <linux/firmware.h> +#include "pvrusb2-util.h" +#include "pvrusb2-encoder.h" +#include "pvrusb2-hdw-internal.h" +#include "pvrusb2-debug.h" + + + +/* Firmware mailbox flags - definitions found from ivtv */ +#define IVTV_MBOX_FIRMWARE_DONE 0x00000004 +#define IVTV_MBOX_DRIVER_DONE 0x00000002 +#define IVTV_MBOX_DRIVER_BUSY 0x00000001 + + +static int pvr2_encoder_write_words(struct pvr2_hdw *hdw, + const u32 *data, unsigned int dlen) +{ + unsigned int idx; + int ret; + unsigned int offs = 0; + unsigned int chunkCnt; + + /* + + Format: First byte must be 0x01. Remaining 32 bit words are + spread out into chunks of 7 bytes each, little-endian ordered, + offset at zero within each 2 blank bytes following and a + single byte that is 0x44 plus the offset of the word. Repeat + request for additional words, with offset adjusted + accordingly. + + */ + while (dlen) { + chunkCnt = 8; + if (chunkCnt > dlen) chunkCnt = dlen; + memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer)); + hdw->cmd_buffer[0] = 0x01; + for (idx = 0; idx < chunkCnt; idx++) { + hdw->cmd_buffer[1+(idx*7)+6] = 0x44 + idx + offs; + PVR2_DECOMPOSE_LE(hdw->cmd_buffer, 1+(idx*7), + data[idx]); + } + ret = pvr2_send_request(hdw, + hdw->cmd_buffer,1+(chunkCnt*7), + NULL,0); + if (ret) return ret; + data += chunkCnt; + dlen -= chunkCnt; + offs += chunkCnt; + } + + return 0; +} + + +static int pvr2_encoder_read_words(struct pvr2_hdw *hdw,int statusFl, + u32 *data, unsigned int dlen) +{ + unsigned int idx; + int ret; + unsigned int offs = 0; + unsigned int chunkCnt; + + /* + + Format: First byte must be 0x02 (status check) or 0x28 (read + back block of 32 bit words). Next 6 bytes must be zero, + followed by a single byte of 0x44+offset for portion to be + read. Returned data is packed set of 32 bits words that were + read. + + */ + + while (dlen) { + chunkCnt = 16; + if (chunkCnt > dlen) chunkCnt = dlen; + memset(hdw->cmd_buffer,0,sizeof(hdw->cmd_buffer)); + hdw->cmd_buffer[0] = statusFl ? 0x02 : 0x28; + hdw->cmd_buffer[7] = 0x44 + offs; + ret = pvr2_send_request(hdw, + hdw->cmd_buffer,8, + hdw->cmd_buffer,chunkCnt * 4); + if (ret) return ret; + + for (idx = 0; idx < chunkCnt; idx++) { + data[idx] = PVR2_COMPOSE_LE(hdw->cmd_buffer,idx*4); + } + data += chunkCnt; + dlen -= chunkCnt; + offs += chunkCnt; + } + + return 0; +} + + +/* This prototype is set up to be compatible with the + cx2341x_mbox_func prototype in cx2341x.h, which should be in + kernels 2.6.18 or later. We do this so that we can enable + cx2341x.ko to write to our encoder (by handing it a pointer to this + function). For earlier kernels this doesn't really matter. */ +static int pvr2_encoder_cmd(void *ctxt, + int cmd, + int arg_cnt_send, + int arg_cnt_recv, + u32 *argp) +{ + unsigned int poll_count; + int ret = 0; + unsigned int idx; + /* These sizes look to be limited by the FX2 firmware implementation */ + u32 wrData[16]; + u32 rdData[16]; + struct pvr2_hdw *hdw = (struct pvr2_hdw *)ctxt; + + + /* + + The encoder seems to speak entirely using blocks 32 bit words. + In ivtv driver terms, this is a mailbox which we populate with + data and watch what the hardware does with it. The first word + is a set of flags used to control the transaction, the second + word is the command to execute, the third byte is zero (ivtv + driver suggests that this is some kind of return value), and + the fourth byte is a specified timeout (windows driver always + uses 0x00060000 except for one case when it is zero). All + successive words are the argument words for the command. + + First, write out the entire set of words, with the first word + being zero. + + Next, write out just the first word again, but set it to + IVTV_MBOX_DRIVER_DONE | IVTV_DRIVER_BUSY this time (which + probably means "go"). + + Next, read back 16 words as status. Check the first word, + which should have IVTV_MBOX_FIRMWARE_DONE set. If however + that bit is not set, then the command isn't done so repeat the + read. + + Next, read back 32 words and compare with the original + arugments. Hopefully they will match. + + Finally, write out just the first word again, but set it to + 0x0 this time (which probably means "idle"). + + */ + + if (arg_cnt_send > (sizeof(wrData)/sizeof(wrData[0]))-4) { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "Failed to write cx23416 command" + " - too many input arguments" + " (was given %u limit %u)", + arg_cnt_send, + (unsigned int)(sizeof(wrData)/sizeof(wrData[0])) - 4); + return -EINVAL; + } + + if (arg_cnt_recv > (sizeof(rdData)/sizeof(rdData[0]))-4) { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "Failed to write cx23416 command" + " - too many return arguments" + " (was given %u limit %u)", + arg_cnt_recv, + (unsigned int)(sizeof(rdData)/sizeof(rdData[0])) - 4); + return -EINVAL; + } + + + LOCK_TAKE(hdw->ctl_lock); do { + + wrData[0] = 0; + wrData[1] = cmd; + wrData[2] = 0; + wrData[3] = 0x00060000; + for (idx = 0; idx < arg_cnt_send; idx++) { + wrData[idx+4] = argp[idx]; + } + for (; idx < (sizeof(wrData)/sizeof(wrData[0]))-4; idx++) { + wrData[idx+4] = 0; + } + + ret = pvr2_encoder_write_words(hdw,wrData,idx); + if (ret) break; + wrData[0] = IVTV_MBOX_DRIVER_DONE|IVTV_MBOX_DRIVER_BUSY; + ret = pvr2_encoder_write_words(hdw,wrData,1); + if (ret) break; + poll_count = 0; + while (1) { + if (poll_count < 10000000) poll_count++; + ret = pvr2_encoder_read_words(hdw,!0,rdData,1); + if (ret) break; + if (rdData[0] & IVTV_MBOX_FIRMWARE_DONE) { + break; + } + if (poll_count == 100) { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "***WARNING*** device's encoder" + " appears to be stuck" + " (status=0%08x)",rdData[0]); + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "Encoder command: 0x%02x",cmd); + for (idx = 4; idx < arg_cnt_send; idx++) { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "Encoder arg%d: 0x%08x", + idx-3,wrData[idx]); + } + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "Giving up waiting." + " It is likely that" + " this is a bad idea..."); + ret = -EBUSY; + break; + } + } + if (ret) break; + wrData[0] = 0x7; + ret = pvr2_encoder_read_words( + hdw,0,rdData, + sizeof(rdData)/sizeof(rdData[0])); + if (ret) break; + for (idx = 0; idx < arg_cnt_recv; idx++) { + argp[idx] = rdData[idx+4]; + } + + wrData[0] = 0x0; + ret = pvr2_encoder_write_words(hdw,wrData,1); + if (ret) break; + + } while(0); LOCK_GIVE(hdw->ctl_lock); + + return ret; +} + + +static int pvr2_encoder_vcmd(struct pvr2_hdw *hdw, int cmd, + int args, ...) +{ + va_list vl; + unsigned int idx; + u32 data[12]; + + if (args > sizeof(data)/sizeof(data[0])) { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "Failed to write cx23416 command" + " - too many arguments" + " (was given %u limit %u)", + args,(unsigned int)(sizeof(data)/sizeof(data[0]))); + return -EINVAL; + } + + va_start(vl, args); + for (idx = 0; idx < args; idx++) { + data[idx] = va_arg(vl, u32); + } + va_end(vl); + + return pvr2_encoder_cmd(hdw,cmd,args,0,data); +} + +int pvr2_encoder_configure(struct pvr2_hdw *hdw) +{ + int ret; + pvr2_trace(PVR2_TRACE_ENCODER,"pvr2_encoder_configure" + " (cx2341x module)"); + hdw->enc_ctl_state.port = CX2341X_PORT_STREAMING; + hdw->enc_ctl_state.width = hdw->res_hor_val; + hdw->enc_ctl_state.height = hdw->res_ver_val; + hdw->enc_ctl_state.is_50hz = ((hdw->std_mask_cur & + (V4L2_STD_NTSC|V4L2_STD_PAL_M)) ? + 0 : 1); + + ret = 0; + + if (!ret) ret = pvr2_encoder_vcmd( + hdw,CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, + 0xf0, 0xf0); + + /* setup firmware to notify us about some events (don't know why...) */ + if (!ret) ret = pvr2_encoder_vcmd( + hdw,CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, + 0, 0, 0x10000000, 0xffffffff); + + if (!ret) ret = pvr2_encoder_vcmd( + hdw,CX2341X_ENC_SET_VBI_LINE, 5, + 0xffffffff,0,0,0,0); + + if (ret) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Failed to configure cx32416"); + return ret; + } + + ret = cx2341x_update(hdw,pvr2_encoder_cmd, + (hdw->enc_cur_valid ? &hdw->enc_cur_state : NULL), + &hdw->enc_ctl_state); + if (ret) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Error from cx2341x module code=%d",ret); + return ret; + } + + ret = 0; + + if (!ret) ret = pvr2_encoder_vcmd( + hdw, CX2341X_ENC_INITIALIZE_INPUT, 0); + + if (ret) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Failed to initialize cx32416 video input"); + return ret; + } + + hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG); + memcpy(&hdw->enc_cur_state,&hdw->enc_ctl_state, + sizeof(struct cx2341x_mpeg_params)); + hdw->enc_cur_valid = !0; + return 0; +} + + +int pvr2_encoder_start(struct pvr2_hdw *hdw) +{ + int status; + + /* unmask some interrupts */ + pvr2_write_register(hdw, 0x0048, 0xbfffffff); + + /* change some GPIO data */ + pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000481); + pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000); + + if (hdw->config == pvr2_config_vbi) { + status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, + 0x01,0x14); + } else if (hdw->config == pvr2_config_mpeg) { + status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, + 0,0x13); + } else { + status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_START_CAPTURE,2, + 0,0x13); + } + if (!status) { + hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_RUN); + } + return status; +} + +int pvr2_encoder_stop(struct pvr2_hdw *hdw) +{ + int status; + + /* mask all interrupts */ + pvr2_write_register(hdw, 0x0048, 0xffffffff); + + if (hdw->config == pvr2_config_vbi) { + status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, + 0x01,0x01,0x14); + } else if (hdw->config == pvr2_config_mpeg) { + status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, + 0x01,0,0x13); + } else { + status = pvr2_encoder_vcmd(hdw,CX2341X_ENC_STOP_CAPTURE,3, + 0x01,0,0x13); + } + + /* change some GPIO data */ + /* Note: Bit d7 of dir appears to control the LED. So we shut it + off here. */ + pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000401); + pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000000); + + if (!status) { + hdw->subsys_enabled_mask &= ~(1<<PVR2_SUBSYS_B_ENC_RUN); + } + return status; +} + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.h b/drivers/media/video/pvrusb2/pvrusb2-encoder.h new file mode 100644 index 000000000..01b5a0b89 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.h @@ -0,0 +1,42 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __PVRUSB2_ENCODER_H +#define __PVRUSB2_ENCODER_H + +struct pvr2_hdw; + +int pvr2_encoder_configure(struct pvr2_hdw *); +int pvr2_encoder_start(struct pvr2_hdw *); +int pvr2_encoder_stop(struct pvr2_hdw *); + +#endif /* __PVRUSB2_ENCODER_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h new file mode 100644 index 000000000..7dd6c3d83 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h @@ -0,0 +1,368 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __PVRUSB2_HDW_INTERNAL_H +#define __PVRUSB2_HDW_INTERNAL_H + +/* + + This header sets up all the internal structures and definitions needed to + track and coordinate the driver's interaction with the hardware. ONLY + source files which actually implement part of that whole circus should be + including this header. Higher levels, like the external layers to the + various public APIs (V4L, sysfs, etc) should NOT ever include this + private, internal header. This means that pvrusb2-hdw, pvrusb2-encoder, + etc will include this, but pvrusb2-v4l should not. + +*/ + +#include <linux/videodev2.h> +#include <linux/i2c.h> +#include <linux/mutex.h> +#include "pvrusb2-hdw.h" +#include "pvrusb2-io.h" +#include <media/cx2341x.h> + +/* Legal values for the SRATE state variable */ +#define PVR2_CVAL_SRATE_48 0 +#define PVR2_CVAL_SRATE_44_1 1 + +/* Legal values for the AUDIOBITRATE state variable */ +#define PVR2_CVAL_AUDIOBITRATE_384 0 +#define PVR2_CVAL_AUDIOBITRATE_320 1 +#define PVR2_CVAL_AUDIOBITRATE_256 2 +#define PVR2_CVAL_AUDIOBITRATE_224 3 +#define PVR2_CVAL_AUDIOBITRATE_192 4 +#define PVR2_CVAL_AUDIOBITRATE_160 5 +#define PVR2_CVAL_AUDIOBITRATE_128 6 +#define PVR2_CVAL_AUDIOBITRATE_112 7 +#define PVR2_CVAL_AUDIOBITRATE_96 8 +#define PVR2_CVAL_AUDIOBITRATE_80 9 +#define PVR2_CVAL_AUDIOBITRATE_64 10 +#define PVR2_CVAL_AUDIOBITRATE_56 11 +#define PVR2_CVAL_AUDIOBITRATE_48 12 +#define PVR2_CVAL_AUDIOBITRATE_32 13 +#define PVR2_CVAL_AUDIOBITRATE_VBR 14 + +/* Legal values for the AUDIOEMPHASIS state variable */ +#define PVR2_CVAL_AUDIOEMPHASIS_NONE 0 +#define PVR2_CVAL_AUDIOEMPHASIS_50_15 1 +#define PVR2_CVAL_AUDIOEMPHASIS_CCITT 2 + +/* Legal values for PVR2_CID_HSM */ +#define PVR2_CVAL_HSM_FAIL 0 +#define PVR2_CVAL_HSM_FULL 1 +#define PVR2_CVAL_HSM_HIGH 2 + +#define PVR2_VID_ENDPOINT 0x84 +#define PVR2_UNK_ENDPOINT 0x86 /* maybe raw yuv ? */ +#define PVR2_VBI_ENDPOINT 0x88 + +#define PVR2_CTL_BUFFSIZE 64 + +#define FREQTABLE_SIZE 500 + +#define LOCK_TAKE(x) do { mutex_lock(&x##_mutex); x##_held = !0; } while (0) +#define LOCK_GIVE(x) do { x##_held = 0; mutex_unlock(&x##_mutex); } while (0) + +struct pvr2_decoder; + +typedef int (*pvr2_ctlf_is_dirty)(struct pvr2_ctrl *); +typedef void (*pvr2_ctlf_clear_dirty)(struct pvr2_ctrl *); +typedef int (*pvr2_ctlf_get_value)(struct pvr2_ctrl *,int *); +typedef int (*pvr2_ctlf_set_value)(struct pvr2_ctrl *,int msk,int val); +typedef int (*pvr2_ctlf_val_to_sym)(struct pvr2_ctrl *,int msk,int val, + char *,unsigned int,unsigned int *); +typedef int (*pvr2_ctlf_sym_to_val)(struct pvr2_ctrl *, + const char *,unsigned int, + int *mskp,int *valp); +typedef unsigned int (*pvr2_ctlf_get_v4lflags)(struct pvr2_ctrl *); + +/* This structure describes a specific control. A table of these is set up + in pvrusb2-hdw.c. */ +struct pvr2_ctl_info { + /* Control's name suitable for use as an identifier */ + const char *name; + + /* Short description of control */ + const char *desc; + + /* Control's implementation */ + pvr2_ctlf_get_value get_value; /* Get its value */ + pvr2_ctlf_get_value get_min_value; /* Get minimum allowed value */ + pvr2_ctlf_get_value get_max_value; /* Get maximum allowed value */ + pvr2_ctlf_set_value set_value; /* Set its value */ + pvr2_ctlf_val_to_sym val_to_sym; /* Custom convert value->symbol */ + pvr2_ctlf_sym_to_val sym_to_val; /* Custom convert symbol->value */ + pvr2_ctlf_is_dirty is_dirty; /* Return true if dirty */ + pvr2_ctlf_clear_dirty clear_dirty; /* Clear dirty state */ + pvr2_ctlf_get_v4lflags get_v4lflags;/* Retrieve v4l flags */ + + /* Control's type (int, enum, bitmask) */ + enum pvr2_ctl_type type; + + /* Associated V4L control ID, if any */ + int v4l_id; + + /* Associated driver internal ID, if any */ + int internal_id; + + /* Don't implicitly initialize this control's value */ + int skip_init; + + /* Starting value for this control */ + int default_value; + + /* Type-specific control information */ + union { + struct { /* Integer control */ + long min_value; /* lower limit */ + long max_value; /* upper limit */ + } type_int; + struct { /* enumerated control */ + unsigned int count; /* enum value count */ + const char **value_names; /* symbol names */ + } type_enum; + struct { /* bitmask control */ + unsigned int valid_bits; /* bits in use */ + const char **bit_names; /* symbol name/bit */ + } type_bitmask; + } def; +}; + + +/* Same as pvr2_ctl_info, but includes storage for the control description */ +#define PVR2_CTLD_INFO_DESC_SIZE 32 +struct pvr2_ctld_info { + struct pvr2_ctl_info info; + char desc[PVR2_CTLD_INFO_DESC_SIZE]; +}; + +struct pvr2_ctrl { + const struct pvr2_ctl_info *info; + struct pvr2_hdw *hdw; +}; + + +struct pvr2_audio_stat { + void *ctxt; + void (*detach)(void *); + int (*status)(void *); +}; + +struct pvr2_decoder_ctrl { + void *ctxt; + void (*detach)(void *); + void (*enable)(void *,int); + int (*tuned)(void *); + void (*force_reset)(void *); +}; + +#define PVR2_I2C_PEND_DETECT 0x01 /* Need to detect a client type */ +#define PVR2_I2C_PEND_CLIENT 0x02 /* Client needs a specific update */ +#define PVR2_I2C_PEND_REFRESH 0x04 /* Client has specific pending bits */ +#define PVR2_I2C_PEND_STALE 0x08 /* Broadcast pending bits */ + +#define PVR2_I2C_PEND_ALL (PVR2_I2C_PEND_DETECT |\ + PVR2_I2C_PEND_CLIENT |\ + PVR2_I2C_PEND_REFRESH |\ + PVR2_I2C_PEND_STALE) + +/* Disposition of firmware1 loading situation */ +#define FW1_STATE_UNKNOWN 0 +#define FW1_STATE_MISSING 1 +#define FW1_STATE_FAILED 2 +#define FW1_STATE_RELOAD 3 +#define FW1_STATE_OK 4 + +/* Known major hardware variants, keyed from device ID */ +#define PVR2_HDW_TYPE_29XXX 0 +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX +#define PVR2_HDW_TYPE_24XXX 1 +#endif + +typedef int (*pvr2_i2c_func)(struct pvr2_hdw *,u8,u8 *,u16,u8 *, u16); +#define PVR2_I2C_FUNC_CNT 128 + +/* This structure contains all state data directly needed to + manipulate the hardware (as opposed to complying with a kernel + interface) */ +struct pvr2_hdw { + /* Underlying USB device handle */ + struct usb_device *usb_dev; + struct usb_interface *usb_intf; + + /* Device type, one of PVR2_HDW_TYPE_xxxxx */ + unsigned int hdw_type; + + /* Video spigot */ + struct pvr2_stream *vid_stream; + + /* Mutex for all hardware state control */ + struct mutex big_lock_mutex; + int big_lock_held; /* For debugging */ + + void (*poll_trigger_func)(void *); + void *poll_trigger_data; + + char name[32]; + + /* I2C stuff */ + struct i2c_adapter i2c_adap; + struct i2c_algorithm i2c_algo; + pvr2_i2c_func i2c_func[PVR2_I2C_FUNC_CNT]; + int i2c_cx25840_hack_state; + int i2c_linked; + unsigned int i2c_pend_types; /* Which types of update are needed */ + unsigned long i2c_pend_mask; /* Change bits we need to scan */ + unsigned long i2c_stale_mask; /* Pending broadcast change bits */ + unsigned long i2c_active_mask; /* All change bits currently in use */ + struct list_head i2c_clients; + struct mutex i2c_list_lock; + + /* Frequency table */ + unsigned int freqTable[FREQTABLE_SIZE]; + unsigned int freqProgSlot; + unsigned int freqSlot; + + /* Stuff for handling low level control interaction with device */ + struct mutex ctl_lock_mutex; + int ctl_lock_held; /* For debugging */ + struct urb *ctl_write_urb; + struct urb *ctl_read_urb; + unsigned char *ctl_write_buffer; + unsigned char *ctl_read_buffer; + volatile int ctl_write_pend_flag; + volatile int ctl_read_pend_flag; + volatile int ctl_timeout_flag; + struct completion ctl_done; + unsigned char cmd_buffer[PVR2_CTL_BUFFSIZE]; + int cmd_debug_state; // Low level command debugging info + unsigned char cmd_debug_code; // + unsigned int cmd_debug_write_len; // + unsigned int cmd_debug_read_len; // + + int flag_ok; // device in known good state + int flag_disconnected; // flag_ok == 0 due to disconnect + int flag_init_ok; // true if structure is fully initialized + int flag_streaming_enabled; // true if streaming should be on + int fw1_state; // current situation with fw1 + + int flag_decoder_is_tuned; + + struct pvr2_decoder_ctrl *decoder_ctrl; + + // CPU firmware info (used to help find / save firmware data) + char *fw_buffer; + unsigned int fw_size; + + // Which subsystem pieces have been enabled / configured + unsigned long subsys_enabled_mask; + + // Which subsystems are manipulated to enable streaming + unsigned long subsys_stream_mask; + + // True if there is a request to trigger logging of state in each + // module. + int log_requested; + + /* Tuner / frequency control stuff */ + unsigned int tuner_type; + int tuner_updated; + unsigned int freqVal; + int freqDirty; + + /* Video standard handling */ + v4l2_std_id std_mask_eeprom; // Hardware supported selections + v4l2_std_id std_mask_avail; // Which standards we may select from + v4l2_std_id std_mask_cur; // Currently selected standard(s) + unsigned int std_enum_cnt; // # of enumerated standards + int std_enum_cur; // selected standard enumeration value + int std_dirty; // True if std_mask_cur has changed + struct pvr2_ctl_info std_info_enum; + struct pvr2_ctl_info std_info_avail; + struct pvr2_ctl_info std_info_cur; + struct v4l2_standard *std_defs; + const char **std_enum_names; + + // Generated string names, one per actual V4L2 standard + const char *std_mask_ptrs[32]; + char std_mask_names[32][10]; + + int unit_number; /* ID for driver instance */ + unsigned long serial_number; /* ID for hardware itself */ + + /* Minor number used by v4l logic (yes, this is a hack, as there should + be no v4l junk here). Probably a better way to do this. */ + int v4l_minor_number; + + /* Location of eeprom or a negative number if none */ + int eeprom_addr; + + enum pvr2_config config; + + /* Information about what audio signal we're hearing */ + int flag_stereo; + int flag_bilingual; + struct pvr2_audio_stat *audio_stat; + + /* Control state needed for cx2341x module */ + struct cx2341x_mpeg_params enc_cur_state; + struct cx2341x_mpeg_params enc_ctl_state; + /* True if an encoder attribute has changed */ + int enc_stale; + /* True if enc_cur_state is valid */ + int enc_cur_valid; + + /* Control state */ +#define VCREATE_DATA(lab) int lab##_val; int lab##_dirty + VCREATE_DATA(brightness); + VCREATE_DATA(contrast); + VCREATE_DATA(saturation); + VCREATE_DATA(hue); + VCREATE_DATA(volume); + VCREATE_DATA(balance); + VCREATE_DATA(bass); + VCREATE_DATA(treble); + VCREATE_DATA(mute); + VCREATE_DATA(input); + VCREATE_DATA(audiomode); + VCREATE_DATA(res_hor); + VCREATE_DATA(res_ver); + VCREATE_DATA(srate); +#undef VCREATE_DATA + + struct pvr2_ctld_info *mpeg_ctrl_info; + + struct pvr2_ctrl *controls; + unsigned int control_cnt; +}; + +#endif /* __PVRUSB2_HDW_INTERNAL_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c new file mode 100644 index 000000000..a36a69d9e --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -0,0 +1,3128 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/firmware.h> +#include <linux/videodev2.h> +#include <asm/semaphore.h> +#include "pvrusb2.h" +#include "pvrusb2-std.h" +#include "pvrusb2-util.h" +#include "pvrusb2-hdw.h" +#include "pvrusb2-i2c-core.h" +#include "pvrusb2-tuner.h" +#include "pvrusb2-eeprom.h" +#include "pvrusb2-hdw-internal.h" +#include "pvrusb2-encoder.h" +#include "pvrusb2-debug.h" + +struct usb_device_id pvr2_device_table[] = { + [PVR2_HDW_TYPE_29XXX] = { USB_DEVICE(0x2040, 0x2900) }, +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX + [PVR2_HDW_TYPE_24XXX] = { USB_DEVICE(0x2040, 0x2400) }, +#endif + { } +}; + +MODULE_DEVICE_TABLE(usb, pvr2_device_table); + +static const char *pvr2_device_names[] = { + [PVR2_HDW_TYPE_29XXX] = "WinTV PVR USB2 Model Category 29xxxx", +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX + [PVR2_HDW_TYPE_24XXX] = "WinTV PVR USB2 Model Category 24xxxx", +#endif +}; + +struct pvr2_string_table { + const char **lst; + unsigned int cnt; +}; + +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX +// Names of other client modules to request for 24xxx model hardware +static const char *pvr2_client_24xxx[] = { + "cx25840", + "tuner", + "wm8775", +}; +#endif + +// Names of other client modules to request for 29xxx model hardware +static const char *pvr2_client_29xxx[] = { + "msp3400", + "saa7115", + "tuner", +}; + +static struct pvr2_string_table pvr2_client_lists[] = { + [PVR2_HDW_TYPE_29XXX] = { + pvr2_client_29xxx, + sizeof(pvr2_client_29xxx)/sizeof(pvr2_client_29xxx[0]), + }, +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX + [PVR2_HDW_TYPE_24XXX] = { + pvr2_client_24xxx, + sizeof(pvr2_client_24xxx)/sizeof(pvr2_client_24xxx[0]), + }, +#endif +}; + +static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL}; +static DECLARE_MUTEX(pvr2_unit_sem); + +static int ctlchg = 0; +static int initusbreset = 1; +static int procreload = 0; +static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 }; +static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 }; +static int video_std[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 }; +static int init_pause_msec = 0; + +module_param(ctlchg, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value"); +module_param(init_pause_msec, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(init_pause_msec, "hardware initialization settling delay"); +module_param(initusbreset, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(initusbreset, "Do USB reset device on probe"); +module_param(procreload, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(procreload, + "Attempt init failure recovery with firmware reload"); +module_param_array(tuner, int, NULL, 0444); +MODULE_PARM_DESC(tuner,"specify installed tuner type"); +module_param_array(video_std, int, NULL, 0444); +MODULE_PARM_DESC(video_std,"specify initial video standard"); +module_param_array(tolerance, int, NULL, 0444); +MODULE_PARM_DESC(tolerance,"specify stream error tolerance"); + +#define PVR2_CTL_WRITE_ENDPOINT 0x01 +#define PVR2_CTL_READ_ENDPOINT 0x81 + +#define PVR2_GPIO_IN 0x9008 +#define PVR2_GPIO_OUT 0x900c +#define PVR2_GPIO_DIR 0x9020 + +#define trace_firmware(...) pvr2_trace(PVR2_TRACE_FIRMWARE,__VA_ARGS__) + +#define PVR2_FIRMWARE_ENDPOINT 0x02 + +/* size of a firmware chunk */ +#define FIRMWARE_CHUNK_SIZE 0x2000 + +/* Define the list of additional controls we'll dynamically construct based + on query of the cx2341x module. */ +struct pvr2_mpeg_ids { + const char *strid; + int id; +}; +static const struct pvr2_mpeg_ids mpeg_ids[] = { + { + .strid = "audio_layer", + .id = V4L2_CID_MPEG_AUDIO_ENCODING, + },{ + .strid = "audio_bitrate", + .id = V4L2_CID_MPEG_AUDIO_L2_BITRATE, + },{ + /* Already using audio_mode elsewhere :-( */ + .strid = "mpeg_audio_mode", + .id = V4L2_CID_MPEG_AUDIO_MODE, + },{ + .strid = "mpeg_audio_mode_extension", + .id = V4L2_CID_MPEG_AUDIO_MODE_EXTENSION, + },{ + .strid = "audio_emphasis", + .id = V4L2_CID_MPEG_AUDIO_EMPHASIS, + },{ + .strid = "audio_crc", + .id = V4L2_CID_MPEG_AUDIO_CRC, + },{ + .strid = "video_aspect", + .id = V4L2_CID_MPEG_VIDEO_ASPECT, + },{ + .strid = "video_b_frames", + .id = V4L2_CID_MPEG_VIDEO_B_FRAMES, + },{ + .strid = "video_gop_size", + .id = V4L2_CID_MPEG_VIDEO_GOP_SIZE, + },{ + .strid = "video_gop_closure", + .id = V4L2_CID_MPEG_VIDEO_GOP_CLOSURE, + },{ + .strid = "video_pulldown", + .id = V4L2_CID_MPEG_VIDEO_PULLDOWN, + },{ + .strid = "video_bitrate_mode", + .id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE, + },{ + .strid = "video_bitrate", + .id = V4L2_CID_MPEG_VIDEO_BITRATE, + },{ + .strid = "video_bitrate_peak", + .id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK, + },{ + .strid = "video_temporal_decimation", + .id = V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION, + },{ + .strid = "stream_type", + .id = V4L2_CID_MPEG_STREAM_TYPE, + },{ + .strid = "video_spatial_filter_mode", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE, + },{ + .strid = "video_spatial_filter", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER, + },{ + .strid = "video_luma_spatial_filter_type", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE, + },{ + .strid = "video_chroma_spatial_filter_type", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE, + },{ + .strid = "video_temporal_filter_mode", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE, + },{ + .strid = "video_temporal_filter", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER, + },{ + .strid = "video_median_filter_type", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE, + },{ + .strid = "video_luma_median_filter_top", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP, + },{ + .strid = "video_luma_median_filter_bottom", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM, + },{ + .strid = "video_chroma_median_filter_top", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP, + },{ + .strid = "video_chroma_median_filter_bottom", + .id = V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM, + } +}; +#define MPEGDEF_COUNT (sizeof(mpeg_ids)/sizeof(mpeg_ids[0])) + +static const char *control_values_srate[] = { + [PVR2_CVAL_SRATE_48] = "48KHz", + [PVR2_CVAL_SRATE_44_1] = "44.1KHz", +}; + + + + +static const char *control_values_input[] = { + [PVR2_CVAL_INPUT_TV] = "television", /*xawtv needs this name*/ + [PVR2_CVAL_INPUT_RADIO] = "radio", + [PVR2_CVAL_INPUT_SVIDEO] = "s-video", + [PVR2_CVAL_INPUT_COMPOSITE] = "composite", +}; + + +static const char *control_values_audiomode[] = { + [V4L2_TUNER_MODE_MONO] = "Mono", + [V4L2_TUNER_MODE_STEREO] = "Stereo", + [V4L2_TUNER_MODE_LANG1] = "Lang1", + [V4L2_TUNER_MODE_LANG2] = "Lang2", + [V4L2_TUNER_MODE_LANG1_LANG2] = "Lang1+Lang2", +}; + + +static const char *control_values_hsm[] = { + [PVR2_CVAL_HSM_FAIL] = "Fail", + [PVR2_CVAL_HSM_HIGH] = "High", + [PVR2_CVAL_HSM_FULL] = "Full", +}; + + +static const char *control_values_subsystem[] = { + [PVR2_SUBSYS_B_ENC_FIRMWARE] = "enc_firmware", + [PVR2_SUBSYS_B_ENC_CFG] = "enc_config", + [PVR2_SUBSYS_B_DIGITIZER_RUN] = "digitizer_run", + [PVR2_SUBSYS_B_USBSTREAM_RUN] = "usbstream_run", + [PVR2_SUBSYS_B_ENC_RUN] = "enc_run", +}; + +static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl); +static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw); +static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw); +static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw); +static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw); +static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw); +static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw); +static void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw, + unsigned long msk, + unsigned long val); +static void pvr2_hdw_subsys_stream_bit_chg_no_lock(struct pvr2_hdw *hdw, + unsigned long msk, + unsigned long val); +static int pvr2_send_request_ex(struct pvr2_hdw *hdw, + unsigned int timeout,int probe_fl, + void *write_data,unsigned int write_len, + void *read_data,unsigned int read_len); +static int pvr2_write_u16(struct pvr2_hdw *hdw, u16 data, int res); +static int pvr2_write_u8(struct pvr2_hdw *hdw, u8 data, int res); + +static int ctrl_channelfreq_get(struct pvr2_ctrl *cptr,int *vp) +{ + struct pvr2_hdw *hdw = cptr->hdw; + if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) { + *vp = hdw->freqTable[hdw->freqProgSlot-1]; + } else { + *vp = 0; + } + return 0; +} + +static int ctrl_channelfreq_set(struct pvr2_ctrl *cptr,int m,int v) +{ + struct pvr2_hdw *hdw = cptr->hdw; + if ((hdw->freqProgSlot > 0) && (hdw->freqProgSlot <= FREQTABLE_SIZE)) { + hdw->freqTable[hdw->freqProgSlot-1] = v; + } + return 0; +} + +static int ctrl_channelprog_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->freqProgSlot; + return 0; +} + +static int ctrl_channelprog_set(struct pvr2_ctrl *cptr,int m,int v) +{ + struct pvr2_hdw *hdw = cptr->hdw; + if ((v >= 0) && (v <= FREQTABLE_SIZE)) { + hdw->freqProgSlot = v; + } + return 0; +} + +static int ctrl_channel_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->freqSlot; + return 0; +} + +static int ctrl_channel_set(struct pvr2_ctrl *cptr,int m,int v) +{ + unsigned freq = 0; + struct pvr2_hdw *hdw = cptr->hdw; + hdw->freqSlot = v; + if ((hdw->freqSlot > 0) && (hdw->freqSlot <= FREQTABLE_SIZE)) { + freq = hdw->freqTable[hdw->freqSlot-1]; + } + if (freq && (freq != hdw->freqVal)) { + hdw->freqVal = freq; + hdw->freqDirty = !0; + } + return 0; +} + +static int ctrl_freq_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->freqVal; + return 0; +} + +static int ctrl_freq_is_dirty(struct pvr2_ctrl *cptr) +{ + return cptr->hdw->freqDirty != 0; +} + +static void ctrl_freq_clear_dirty(struct pvr2_ctrl *cptr) +{ + cptr->hdw->freqDirty = 0; +} + +static int ctrl_freq_set(struct pvr2_ctrl *cptr,int m,int v) +{ + struct pvr2_hdw *hdw = cptr->hdw; + hdw->freqVal = v; + hdw->freqDirty = !0; + hdw->freqSlot = 0; + return 0; +} + +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX +static int ctrl_hres_max_get(struct pvr2_ctrl *cptr,int *vp) +{ + /* If we're dealing with a 24xxx device, force the horizontal + maximum to be 720 no matter what, since we can't get the device + to work properly with any other value. Otherwise just return + the normal value. */ + *vp = cptr->info->def.type_int.max_value; + if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720; + return 0; +} + +static int ctrl_hres_min_get(struct pvr2_ctrl *cptr,int *vp) +{ + /* If we're dealing with a 24xxx device, force the horizontal + minimum to be 720 no matter what, since we can't get the device + to work properly with any other value. Otherwise just return + the normal value. */ + *vp = cptr->info->def.type_int.min_value; + if (cptr->hdw->hdw_type == PVR2_HDW_TYPE_24XXX) *vp = 720; + return 0; +} +#endif + +static int ctrl_cx2341x_is_dirty(struct pvr2_ctrl *cptr) +{ + return cptr->hdw->enc_stale != 0; +} + +static void ctrl_cx2341x_clear_dirty(struct pvr2_ctrl *cptr) +{ + cptr->hdw->enc_stale = 0; +} + +static int ctrl_cx2341x_get(struct pvr2_ctrl *cptr,int *vp) +{ + int ret; + struct v4l2_ext_controls cs; + struct v4l2_ext_control c1; + memset(&cs,0,sizeof(cs)); + memset(&c1,0,sizeof(c1)); + cs.controls = &c1; + cs.count = 1; + c1.id = cptr->info->v4l_id; + ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state,&cs, + VIDIOC_G_EXT_CTRLS); + if (ret) return ret; + *vp = c1.value; + return 0; +} + +static int ctrl_cx2341x_set(struct pvr2_ctrl *cptr,int m,int v) +{ + int ret; + struct v4l2_ext_controls cs; + struct v4l2_ext_control c1; + memset(&cs,0,sizeof(cs)); + memset(&c1,0,sizeof(c1)); + cs.controls = &c1; + cs.count = 1; + c1.id = cptr->info->v4l_id; + c1.value = v; + ret = cx2341x_ext_ctrls(&cptr->hdw->enc_ctl_state,&cs, + VIDIOC_S_EXT_CTRLS); + if (ret) return ret; + cptr->hdw->enc_stale = !0; + return 0; +} + +static unsigned int ctrl_cx2341x_getv4lflags(struct pvr2_ctrl *cptr) +{ + struct v4l2_queryctrl qctrl; + struct pvr2_ctl_info *info; + qctrl.id = cptr->info->v4l_id; + cx2341x_ctrl_query(&cptr->hdw->enc_ctl_state,&qctrl); + /* Strip out the const so we can adjust a function pointer. It's + OK to do this here because we know this is a dynamically created + control, so the underlying storage for the info pointer is (a) + private to us, and (b) not in read-only storage. Either we do + this or we significantly complicate the underlying control + implementation. */ + info = (struct pvr2_ctl_info *)(cptr->info); + if (qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY) { + if (info->set_value) { + info->set_value = NULL; + } + } else { + if (!(info->set_value)) { + info->set_value = ctrl_cx2341x_set; + } + } + return qctrl.flags; +} + +static int ctrl_streamingenabled_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->flag_streaming_enabled; + return 0; +} + +static int ctrl_hsm_get(struct pvr2_ctrl *cptr,int *vp) +{ + int result = pvr2_hdw_is_hsm(cptr->hdw); + *vp = PVR2_CVAL_HSM_FULL; + if (result < 0) *vp = PVR2_CVAL_HSM_FAIL; + if (result) *vp = PVR2_CVAL_HSM_HIGH; + return 0; +} + +static int ctrl_stdavail_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->std_mask_avail; + return 0; +} + +static int ctrl_stdavail_set(struct pvr2_ctrl *cptr,int m,int v) +{ + struct pvr2_hdw *hdw = cptr->hdw; + v4l2_std_id ns; + ns = hdw->std_mask_avail; + ns = (ns & ~m) | (v & m); + if (ns == hdw->std_mask_avail) return 0; + hdw->std_mask_avail = ns; + pvr2_hdw_internal_set_std_avail(hdw); + pvr2_hdw_internal_find_stdenum(hdw); + return 0; +} + +static int ctrl_std_val_to_sym(struct pvr2_ctrl *cptr,int msk,int val, + char *bufPtr,unsigned int bufSize, + unsigned int *len) +{ + *len = pvr2_std_id_to_str(bufPtr,bufSize,msk & val); + return 0; +} + +static int ctrl_std_sym_to_val(struct pvr2_ctrl *cptr, + const char *bufPtr,unsigned int bufSize, + int *mskp,int *valp) +{ + int ret; + v4l2_std_id id; + ret = pvr2_std_str_to_id(&id,bufPtr,bufSize); + if (ret < 0) return ret; + if (mskp) *mskp = id; + if (valp) *valp = id; + return 0; +} + +static int ctrl_stdcur_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->std_mask_cur; + return 0; +} + +static int ctrl_stdcur_set(struct pvr2_ctrl *cptr,int m,int v) +{ + struct pvr2_hdw *hdw = cptr->hdw; + v4l2_std_id ns; + ns = hdw->std_mask_cur; + ns = (ns & ~m) | (v & m); + if (ns == hdw->std_mask_cur) return 0; + hdw->std_mask_cur = ns; + hdw->std_dirty = !0; + pvr2_hdw_internal_find_stdenum(hdw); + return 0; +} + +static int ctrl_stdcur_is_dirty(struct pvr2_ctrl *cptr) +{ + return cptr->hdw->std_dirty != 0; +} + +static void ctrl_stdcur_clear_dirty(struct pvr2_ctrl *cptr) +{ + cptr->hdw->std_dirty = 0; +} + +static int ctrl_signal_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = ((pvr2_hdw_get_signal_status_internal(cptr->hdw) & + PVR2_SIGNAL_OK) ? 1 : 0); + return 0; +} + +static int ctrl_subsys_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->subsys_enabled_mask; + return 0; +} + +static int ctrl_subsys_set(struct pvr2_ctrl *cptr,int m,int v) +{ + pvr2_hdw_subsys_bit_chg_no_lock(cptr->hdw,m,v); + return 0; +} + +static int ctrl_subsys_stream_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->subsys_stream_mask; + return 0; +} + +static int ctrl_subsys_stream_set(struct pvr2_ctrl *cptr,int m,int v) +{ + pvr2_hdw_subsys_stream_bit_chg_no_lock(cptr->hdw,m,v); + return 0; +} + +static int ctrl_stdenumcur_set(struct pvr2_ctrl *cptr,int m,int v) +{ + struct pvr2_hdw *hdw = cptr->hdw; + if (v < 0) return -EINVAL; + if (v > hdw->std_enum_cnt) return -EINVAL; + hdw->std_enum_cur = v; + if (!v) return 0; + v--; + if (hdw->std_mask_cur == hdw->std_defs[v].id) return 0; + hdw->std_mask_cur = hdw->std_defs[v].id; + hdw->std_dirty = !0; + return 0; +} + + +static int ctrl_stdenumcur_get(struct pvr2_ctrl *cptr,int *vp) +{ + *vp = cptr->hdw->std_enum_cur; + return 0; +} + + +static int ctrl_stdenumcur_is_dirty(struct pvr2_ctrl *cptr) +{ + return cptr->hdw->std_dirty != 0; +} + + +static void ctrl_stdenumcur_clear_dirty(struct pvr2_ctrl *cptr) +{ + cptr->hdw->std_dirty = 0; +} + + +#define DEFINT(vmin,vmax) \ + .type = pvr2_ctl_int, \ + .def.type_int.min_value = vmin, \ + .def.type_int.max_value = vmax + +#define DEFENUM(tab) \ + .type = pvr2_ctl_enum, \ + .def.type_enum.count = (sizeof(tab)/sizeof((tab)[0])), \ + .def.type_enum.value_names = tab + +#define DEFBOOL \ + .type = pvr2_ctl_bool + +#define DEFMASK(msk,tab) \ + .type = pvr2_ctl_bitmask, \ + .def.type_bitmask.valid_bits = msk, \ + .def.type_bitmask.bit_names = tab + +#define DEFREF(vname) \ + .set_value = ctrl_set_##vname, \ + .get_value = ctrl_get_##vname, \ + .is_dirty = ctrl_isdirty_##vname, \ + .clear_dirty = ctrl_cleardirty_##vname + + +#define VCREATE_FUNCS(vname) \ +static int ctrl_get_##vname(struct pvr2_ctrl *cptr,int *vp) \ +{*vp = cptr->hdw->vname##_val; return 0;} \ +static int ctrl_set_##vname(struct pvr2_ctrl *cptr,int m,int v) \ +{cptr->hdw->vname##_val = v; cptr->hdw->vname##_dirty = !0; return 0;} \ +static int ctrl_isdirty_##vname(struct pvr2_ctrl *cptr) \ +{return cptr->hdw->vname##_dirty != 0;} \ +static void ctrl_cleardirty_##vname(struct pvr2_ctrl *cptr) \ +{cptr->hdw->vname##_dirty = 0;} + +VCREATE_FUNCS(brightness) +VCREATE_FUNCS(contrast) +VCREATE_FUNCS(saturation) +VCREATE_FUNCS(hue) +VCREATE_FUNCS(volume) +VCREATE_FUNCS(balance) +VCREATE_FUNCS(bass) +VCREATE_FUNCS(treble) +VCREATE_FUNCS(mute) +VCREATE_FUNCS(input) +VCREATE_FUNCS(audiomode) +VCREATE_FUNCS(res_hor) +VCREATE_FUNCS(res_ver) +VCREATE_FUNCS(srate) + +#define MIN_FREQ 55250000L +#define MAX_FREQ 850000000L + +/* Table definition of all controls which can be manipulated */ +static const struct pvr2_ctl_info control_defs[] = { + { + .v4l_id = V4L2_CID_BRIGHTNESS, + .desc = "Brightness", + .name = "brightness", + .default_value = 128, + DEFREF(brightness), + DEFINT(0,255), + },{ + .v4l_id = V4L2_CID_CONTRAST, + .desc = "Contrast", + .name = "contrast", + .default_value = 68, + DEFREF(contrast), + DEFINT(0,127), + },{ + .v4l_id = V4L2_CID_SATURATION, + .desc = "Saturation", + .name = "saturation", + .default_value = 64, + DEFREF(saturation), + DEFINT(0,127), + },{ + .v4l_id = V4L2_CID_HUE, + .desc = "Hue", + .name = "hue", + .default_value = 0, + DEFREF(hue), + DEFINT(-128,127), + },{ + .v4l_id = V4L2_CID_AUDIO_VOLUME, + .desc = "Volume", + .name = "volume", + .default_value = 65535, + DEFREF(volume), + DEFINT(0,65535), + },{ + .v4l_id = V4L2_CID_AUDIO_BALANCE, + .desc = "Balance", + .name = "balance", + .default_value = 0, + DEFREF(balance), + DEFINT(-32768,32767), + },{ + .v4l_id = V4L2_CID_AUDIO_BASS, + .desc = "Bass", + .name = "bass", + .default_value = 0, + DEFREF(bass), + DEFINT(-32768,32767), + },{ + .v4l_id = V4L2_CID_AUDIO_TREBLE, + .desc = "Treble", + .name = "treble", + .default_value = 0, + DEFREF(treble), + DEFINT(-32768,32767), + },{ + .v4l_id = V4L2_CID_AUDIO_MUTE, + .desc = "Mute", + .name = "mute", + .default_value = 0, + DEFREF(mute), + DEFBOOL, + },{ + .desc = "Video Source", + .name = "input", + .internal_id = PVR2_CID_INPUT, + .default_value = PVR2_CVAL_INPUT_TV, + DEFREF(input), + DEFENUM(control_values_input), + },{ + .desc = "Audio Mode", + .name = "audio_mode", + .internal_id = PVR2_CID_AUDIOMODE, + .default_value = V4L2_TUNER_MODE_STEREO, + DEFREF(audiomode), + DEFENUM(control_values_audiomode), + },{ + .desc = "Horizontal capture resolution", + .name = "resolution_hor", + .internal_id = PVR2_CID_HRES, + .default_value = 720, + DEFREF(res_hor), + DEFINT(320,720), +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX + /* Hook in check for clamp on horizontal resolution in + order to avoid unsolved problem involving cx25840. */ + .get_max_value = ctrl_hres_max_get, + .get_min_value = ctrl_hres_min_get, +#endif + },{ + .desc = "Vertical capture resolution", + .name = "resolution_ver", + .internal_id = PVR2_CID_VRES, + .default_value = 480, + DEFREF(res_ver), + DEFINT(200,625), + },{ + .v4l_id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ, + .desc = "Sample rate", + .name = "srate", + .default_value = PVR2_CVAL_SRATE_48, + DEFREF(srate), + DEFENUM(control_values_srate), + },{ + .desc = "Tuner Frequency (Hz)", + .name = "frequency", + .internal_id = PVR2_CID_FREQUENCY, + .default_value = 175250000L, + .set_value = ctrl_freq_set, + .get_value = ctrl_freq_get, + .is_dirty = ctrl_freq_is_dirty, + .clear_dirty = ctrl_freq_clear_dirty, + DEFINT(MIN_FREQ,MAX_FREQ), + },{ + .desc = "Channel", + .name = "channel", + .set_value = ctrl_channel_set, + .get_value = ctrl_channel_get, + DEFINT(0,FREQTABLE_SIZE), + },{ + .desc = "Channel Program Frequency", + .name = "freq_table_value", + .set_value = ctrl_channelfreq_set, + .get_value = ctrl_channelfreq_get, + DEFINT(MIN_FREQ,MAX_FREQ), + },{ + .desc = "Channel Program ID", + .name = "freq_table_channel", + .set_value = ctrl_channelprog_set, + .get_value = ctrl_channelprog_get, + DEFINT(0,FREQTABLE_SIZE), + },{ + .desc = "Streaming Enabled", + .name = "streaming_enabled", + .get_value = ctrl_streamingenabled_get, + DEFBOOL, + },{ + .desc = "USB Speed", + .name = "usb_speed", + .get_value = ctrl_hsm_get, + DEFENUM(control_values_hsm), + },{ + .desc = "Signal Present", + .name = "signal_present", + .get_value = ctrl_signal_get, + DEFBOOL, + },{ + .desc = "Video Standards Available Mask", + .name = "video_standard_mask_available", + .internal_id = PVR2_CID_STDAVAIL, + .skip_init = !0, + .get_value = ctrl_stdavail_get, + .set_value = ctrl_stdavail_set, + .val_to_sym = ctrl_std_val_to_sym, + .sym_to_val = ctrl_std_sym_to_val, + .type = pvr2_ctl_bitmask, + },{ + .desc = "Video Standards In Use Mask", + .name = "video_standard_mask_active", + .internal_id = PVR2_CID_STDCUR, + .skip_init = !0, + .get_value = ctrl_stdcur_get, + .set_value = ctrl_stdcur_set, + .is_dirty = ctrl_stdcur_is_dirty, + .clear_dirty = ctrl_stdcur_clear_dirty, + .val_to_sym = ctrl_std_val_to_sym, + .sym_to_val = ctrl_std_sym_to_val, + .type = pvr2_ctl_bitmask, + },{ + .desc = "Subsystem enabled mask", + .name = "debug_subsys_mask", + .skip_init = !0, + .get_value = ctrl_subsys_get, + .set_value = ctrl_subsys_set, + DEFMASK(PVR2_SUBSYS_ALL,control_values_subsystem), + },{ + .desc = "Subsystem stream mask", + .name = "debug_subsys_stream_mask", + .skip_init = !0, + .get_value = ctrl_subsys_stream_get, + .set_value = ctrl_subsys_stream_set, + DEFMASK(PVR2_SUBSYS_ALL,control_values_subsystem), + },{ + .desc = "Video Standard Name", + .name = "video_standard", + .internal_id = PVR2_CID_STDENUM, + .skip_init = !0, + .get_value = ctrl_stdenumcur_get, + .set_value = ctrl_stdenumcur_set, + .is_dirty = ctrl_stdenumcur_is_dirty, + .clear_dirty = ctrl_stdenumcur_clear_dirty, + .type = pvr2_ctl_enum, + } +}; + +#define CTRLDEF_COUNT (sizeof(control_defs)/sizeof(control_defs[0])) + + +const char *pvr2_config_get_name(enum pvr2_config cfg) +{ + switch (cfg) { + case pvr2_config_empty: return "empty"; + case pvr2_config_mpeg: return "mpeg"; + case pvr2_config_vbi: return "vbi"; + case pvr2_config_radio: return "radio"; + } + return "<unknown>"; +} + + +struct usb_device *pvr2_hdw_get_dev(struct pvr2_hdw *hdw) +{ + return hdw->usb_dev; +} + + +unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *hdw) +{ + return hdw->serial_number; +} + +int pvr2_hdw_get_unit_number(struct pvr2_hdw *hdw) +{ + return hdw->unit_number; +} + + +/* Attempt to locate one of the given set of files. Messages are logged + appropriate to what has been found. The return value will be 0 or + greater on success (it will be the index of the file name found) and + fw_entry will be filled in. Otherwise a negative error is returned on + failure. If the return value is -ENOENT then no viable firmware file + could be located. */ +static int pvr2_locate_firmware(struct pvr2_hdw *hdw, + const struct firmware **fw_entry, + const char *fwtypename, + unsigned int fwcount, + const char *fwnames[]) +{ + unsigned int idx; + int ret = -EINVAL; + for (idx = 0; idx < fwcount; idx++) { + ret = request_firmware(fw_entry, + fwnames[idx], + &hdw->usb_dev->dev); + if (!ret) { + trace_firmware("Located %s firmware: %s;" + " uploading...", + fwtypename, + fwnames[idx]); + return idx; + } + if (ret == -ENOENT) continue; + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "request_firmware fatal error with code=%d",ret); + return ret; + } + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "***WARNING***" + " Device %s firmware" + " seems to be missing.", + fwtypename); + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Did you install the pvrusb2 firmware files" + " in their proper location?"); + if (fwcount == 1) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "request_firmware unable to locate %s file %s", + fwtypename,fwnames[0]); + } else { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "request_firmware unable to locate" + " one of the following %s files:", + fwtypename); + for (idx = 0; idx < fwcount; idx++) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "request_firmware: Failed to find %s", + fwnames[idx]); + } + } + return ret; +} + + +/* + * pvr2_upload_firmware1(). + * + * Send the 8051 firmware to the device. After the upload, arrange for + * device to re-enumerate. + * + * NOTE : the pointer to the firmware data given by request_firmware() + * is not suitable for an usb transaction. + * + */ +static int pvr2_upload_firmware1(struct pvr2_hdw *hdw) +{ + const struct firmware *fw_entry = NULL; + void *fw_ptr; + unsigned int pipe; + int ret; + u16 address; + static const char *fw_files_29xxx[] = { + "v4l-pvrusb2-29xxx-01.fw", + }; +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX + static const char *fw_files_24xxx[] = { + "v4l-pvrusb2-24xxx-01.fw", + }; +#endif + static const struct pvr2_string_table fw_file_defs[] = { + [PVR2_HDW_TYPE_29XXX] = { + fw_files_29xxx, + sizeof(fw_files_29xxx)/sizeof(fw_files_29xxx[0]), + }, +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX + [PVR2_HDW_TYPE_24XXX] = { + fw_files_24xxx, + sizeof(fw_files_24xxx)/sizeof(fw_files_24xxx[0]), + }, +#endif + }; + hdw->fw1_state = FW1_STATE_FAILED; // default result + + trace_firmware("pvr2_upload_firmware1"); + + ret = pvr2_locate_firmware(hdw,&fw_entry,"fx2 controller", + fw_file_defs[hdw->hdw_type].cnt, + fw_file_defs[hdw->hdw_type].lst); + if (ret < 0) { + if (ret == -ENOENT) hdw->fw1_state = FW1_STATE_MISSING; + return ret; + } + + usb_settoggle(hdw->usb_dev, 0 & 0xf, !(0 & USB_DIR_IN), 0); + usb_clear_halt(hdw->usb_dev, usb_sndbulkpipe(hdw->usb_dev, 0 & 0x7f)); + + pipe = usb_sndctrlpipe(hdw->usb_dev, 0); + + if (fw_entry->size != 0x2000){ + pvr2_trace(PVR2_TRACE_ERROR_LEGS,"wrong fx2 firmware size"); + release_firmware(fw_entry); + return -ENOMEM; + } + + fw_ptr = kmalloc(0x800, GFP_KERNEL); + if (fw_ptr == NULL){ + release_firmware(fw_entry); + return -ENOMEM; + } + + /* We have to hold the CPU during firmware upload. */ + pvr2_hdw_cpureset_assert(hdw,1); + + /* upload the firmware to address 0000-1fff in 2048 (=0x800) bytes + chunk. */ + + ret = 0; + for(address = 0; address < fw_entry->size; address += 0x800) { + memcpy(fw_ptr, fw_entry->data + address, 0x800); + ret += usb_control_msg(hdw->usb_dev, pipe, 0xa0, 0x40, address, + 0, fw_ptr, 0x800, HZ); + } + + trace_firmware("Upload done, releasing device's CPU"); + + /* Now release the CPU. It will disconnect and reconnect later. */ + pvr2_hdw_cpureset_assert(hdw,0); + + kfree(fw_ptr); + release_firmware(fw_entry); + + trace_firmware("Upload done (%d bytes sent)",ret); + + /* We should have written 8192 bytes */ + if (ret == 8192) { + hdw->fw1_state = FW1_STATE_RELOAD; + return 0; + } + + return -EIO; +} + + +/* + * pvr2_upload_firmware2() + * + * This uploads encoder firmware on endpoint 2. + * + */ + +int pvr2_upload_firmware2(struct pvr2_hdw *hdw) +{ + const struct firmware *fw_entry = NULL; + void *fw_ptr; + unsigned int pipe, fw_len, fw_done; + int actual_length; + int ret = 0; + int fwidx; + static const char *fw_files[] = { + CX2341X_FIRM_ENC_FILENAME, + }; + + trace_firmware("pvr2_upload_firmware2"); + + ret = pvr2_locate_firmware(hdw,&fw_entry,"encoder", + sizeof(fw_files)/sizeof(fw_files[0]), + fw_files); + if (ret < 0) return ret; + fwidx = ret; + ret = 0; + /* Since we're about to completely reinitialize the encoder, + invalidate our cached copy of its configuration state. Next + time we configure the encoder, then we'll fully configure it. */ + hdw->enc_cur_valid = 0; + + /* First prepare firmware loading */ + ret |= pvr2_write_register(hdw, 0x0048, 0xffffffff); /*interrupt mask*/ + ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000088); /*gpio dir*/ + ret |= pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000008); /*gpio output state*/ + ret |= pvr2_hdw_cmd_deep_reset(hdw); + ret |= pvr2_write_register(hdw, 0xa064, 0x00000000); /*APU command*/ + ret |= pvr2_hdw_gpio_chg_dir(hdw,0xffffffff,0x00000408); /*gpio dir*/ + ret |= pvr2_hdw_gpio_chg_out(hdw,0xffffffff,0x00000008); /*gpio output state*/ + ret |= pvr2_write_register(hdw, 0x9058, 0xffffffed); /*VPU ctrl*/ + ret |= pvr2_write_register(hdw, 0x9054, 0xfffffffd); /*reset hw blocks*/ + ret |= pvr2_write_register(hdw, 0x07f8, 0x80000800); /*encoder SDRAM refresh*/ + ret |= pvr2_write_register(hdw, 0x07fc, 0x0000001a); /*encoder SDRAM pre-charge*/ + ret |= pvr2_write_register(hdw, 0x0700, 0x00000000); /*I2C clock*/ + ret |= pvr2_write_register(hdw, 0xaa00, 0x00000000); /*unknown*/ + ret |= pvr2_write_register(hdw, 0xaa04, 0x00057810); /*unknown*/ + ret |= pvr2_write_register(hdw, 0xaa10, 0x00148500); /*unknown*/ + ret |= pvr2_write_register(hdw, 0xaa18, 0x00840000); /*unknown*/ + ret |= pvr2_write_u8(hdw, 0x52, 0); + ret |= pvr2_write_u16(hdw, 0x0600, 0); + + if (ret) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "firmware2 upload prep failed, ret=%d",ret); + release_firmware(fw_entry); + return ret; + } + + /* Now send firmware */ + + fw_len = fw_entry->size; + + if (fw_len % FIRMWARE_CHUNK_SIZE) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "size of %s firmware" + " must be a multiple of 8192B", + fw_files[fwidx]); + release_firmware(fw_entry); + return -1; + } + + fw_ptr = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL); + if (fw_ptr == NULL){ + release_firmware(fw_entry); + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "failed to allocate memory for firmware2 upload"); + return -ENOMEM; + } + + pipe = usb_sndbulkpipe(hdw->usb_dev, PVR2_FIRMWARE_ENDPOINT); + + for (fw_done = 0 ; (fw_done < fw_len) && !ret ; + fw_done += FIRMWARE_CHUNK_SIZE ) { + int i; + memcpy(fw_ptr, fw_entry->data + fw_done, FIRMWARE_CHUNK_SIZE); + /* Usbsnoop log shows that we must swap bytes... */ + for (i = 0; i < FIRMWARE_CHUNK_SIZE/4 ; i++) + ((u32 *)fw_ptr)[i] = ___swab32(((u32 *)fw_ptr)[i]); + + ret |= usb_bulk_msg(hdw->usb_dev, pipe, fw_ptr, + FIRMWARE_CHUNK_SIZE, + &actual_length, HZ); + ret |= (actual_length != FIRMWARE_CHUNK_SIZE); + } + + trace_firmware("upload of %s : %i / %i ", + fw_files[fwidx],fw_done,fw_len); + + kfree(fw_ptr); + release_firmware(fw_entry); + + if (ret) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "firmware2 upload transfer failure"); + return ret; + } + + /* Finish upload */ + + ret |= pvr2_write_register(hdw, 0x9054, 0xffffffff); /*reset hw blocks*/ + ret |= pvr2_write_register(hdw, 0x9058, 0xffffffe8); /*VPU ctrl*/ + ret |= pvr2_write_u16(hdw, 0x0600, 0); + + if (ret) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "firmware2 upload post-proc failure"); + } else { + hdw->subsys_enabled_mask |= (1<<PVR2_SUBSYS_B_ENC_FIRMWARE); + } + return ret; +} + + +#define FIRMWARE_RECOVERY_BITS \ + ((1<<PVR2_SUBSYS_B_ENC_CFG) | \ + (1<<PVR2_SUBSYS_B_ENC_RUN) | \ + (1<<PVR2_SUBSYS_B_ENC_FIRMWARE) | \ + (1<<PVR2_SUBSYS_B_USBSTREAM_RUN)) + +/* + + This single function is key to pretty much everything. The pvrusb2 + device can logically be viewed as a series of subsystems which can be + stopped / started or unconfigured / configured. To get things streaming, + one must configure everything and start everything, but there may be + various reasons over time to deconfigure something or stop something. + This function handles all of this activity. Everything EVERYWHERE that + must affect a subsystem eventually comes here to do the work. + + The current state of all subsystems is represented by a single bit mask, + known as subsys_enabled_mask. The bit positions are defined by the + PVR2_SUBSYS_xxxx macros, with one subsystem per bit position. At any + time the set of configured or active subsystems can be queried just by + looking at that mask. To change bits in that mask, this function here + must be called. The "msk" argument indicates which bit positions to + change, and the "val" argument defines the new values for the positions + defined by "msk". + + There is a priority ordering of starting / stopping things, and for + multiple requested changes, this function implements that ordering. + (Thus we will act on a request to load encoder firmware before we + configure the encoder.) In addition to priority ordering, there is a + recovery strategy implemented here. If a particular step fails and we + detect that failure, this function will clear the affected subsystem bits + and restart. Thus we have a means for recovering from a dead encoder: + Clear all bits that correspond to subsystems that we need to restart / + reconfigure and start over. + +*/ +static void pvr2_hdw_subsys_bit_chg_no_lock(struct pvr2_hdw *hdw, + unsigned long msk, + unsigned long val) +{ + unsigned long nmsk; + unsigned long vmsk; + int ret; + unsigned int tryCount = 0; + + if (!hdw->flag_ok) return; + + msk &= PVR2_SUBSYS_ALL; + nmsk = (hdw->subsys_enabled_mask & ~msk) | (val & msk); + nmsk &= PVR2_SUBSYS_ALL; + + for (;;) { + tryCount++; + if (!((nmsk ^ hdw->subsys_enabled_mask) & + PVR2_SUBSYS_ALL)) break; + if (tryCount > 4) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Too many retries when configuring device;" + " giving up"); + pvr2_hdw_render_useless(hdw); + break; + } + if (tryCount > 1) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Retrying device reconfiguration"); + } + pvr2_trace(PVR2_TRACE_INIT, + "subsys mask changing 0x%lx:0x%lx" + " from 0x%lx to 0x%lx", + msk,val,hdw->subsys_enabled_mask,nmsk); + + vmsk = (nmsk ^ hdw->subsys_enabled_mask) & + hdw->subsys_enabled_mask; + if (vmsk) { + if (vmsk & (1<<PVR2_SUBSYS_B_ENC_RUN)) { + pvr2_trace(PVR2_TRACE_CTL, + "/*---TRACE_CTL----*/" + " pvr2_encoder_stop"); + ret = pvr2_encoder_stop(hdw); + if (ret) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Error recovery initiated"); + hdw->subsys_enabled_mask &= + ~FIRMWARE_RECOVERY_BITS; + continue; + } + } + if (vmsk & (1<<PVR2_SUBSYS_B_USBSTREAM_RUN)) { + pvr2_trace(PVR2_TRACE_CTL, + "/*---TRACE_CTL----*/" + " pvr2_hdw_cmd_usbstream(0)"); + pvr2_hdw_cmd_usbstream(hdw,0); + } + if (vmsk & (1<<PVR2_SUBSYS_B_DIGITIZER_RUN)) { + pvr2_trace(PVR2_TRACE_CTL, + "/*---TRACE_CTL----*/" + " decoder disable"); + if (hdw->decoder_ctrl) { + hdw->decoder_ctrl->enable( + hdw->decoder_ctrl->ctxt,0); + } else { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "WARNING:" + " No decoder present"); + } + hdw->subsys_enabled_mask &= + ~(1<<PVR2_SUBSYS_B_DIGITIZER_RUN); + } + if (vmsk & PVR2_SUBSYS_CFG_ALL) { + hdw->subsys_enabled_mask &= + ~(vmsk & PVR2_SUBSYS_CFG_ALL); + } + } + vmsk = (nmsk ^ hdw->subsys_enabled_mask) & nmsk; + if (vmsk) { + if (vmsk & (1<<PVR2_SUBSYS_B_ENC_FIRMWARE)) { + pvr2_trace(PVR2_TRACE_CTL, + "/*---TRACE_CTL----*/" + " pvr2_upload_firmware2"); + ret = pvr2_upload_firmware2(hdw); + if (ret) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Failure uploading encoder" + " firmware"); + pvr2_hdw_render_useless(hdw); + break; + } + } + if (vmsk & (1<<PVR2_SUBSYS_B_ENC_CFG)) { + pvr2_trace(PVR2_TRACE_CTL, + "/*---TRACE_CTL----*/" + " pvr2_encoder_configure"); + ret = pvr2_encoder_configure(hdw); + if (ret) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Error recovery initiated"); + hdw->subsys_enabled_mask &= + ~FIRMWARE_RECOVERY_BITS; + continue; + } + } + if (vmsk & (1<<PVR2_SUBSYS_B_DIGITIZER_RUN)) { + pvr2_trace(PVR2_TRACE_CTL, + "/*---TRACE_CTL----*/" + " decoder enable"); + if (hdw->decoder_ctrl) { + hdw->decoder_ctrl->enable( + hdw->decoder_ctrl->ctxt,!0); + } else { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "WARNING:" + " No decoder present"); + } + hdw->subsys_enabled_mask |= + (1<<PVR2_SUBSYS_B_DIGITIZER_RUN); + } + if (vmsk & (1<<PVR2_SUBSYS_B_USBSTREAM_RUN)) { + pvr2_trace(PVR2_TRACE_CTL, + "/*---TRACE_CTL----*/" + " pvr2_hdw_cmd_usbstream(1)"); + pvr2_hdw_cmd_usbstream(hdw,!0); + } + if (vmsk & (1<<PVR2_SUBSYS_B_ENC_RUN)) { + pvr2_trace(PVR2_TRACE_CTL, + "/*---TRACE_CTL----*/" + " pvr2_encoder_start"); + ret = pvr2_encoder_start(hdw); + if (ret) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Error recovery initiated"); + hdw->subsys_enabled_mask &= + ~FIRMWARE_RECOVERY_BITS; + continue; + } + } + } + } +} + + +void pvr2_hdw_subsys_bit_chg(struct pvr2_hdw *hdw, + unsigned long msk,unsigned long val) +{ + LOCK_TAKE(hdw->big_lock); do { + pvr2_hdw_subsys_bit_chg_no_lock(hdw,msk,val); + } while (0); LOCK_GIVE(hdw->big_lock); +} + + +unsigned long pvr2_hdw_subsys_get(struct pvr2_hdw *hdw) +{ + return hdw->subsys_enabled_mask; +} + + +unsigned long pvr2_hdw_subsys_stream_get(struct pvr2_hdw *hdw) +{ + return hdw->subsys_stream_mask; +} + + +static void pvr2_hdw_subsys_stream_bit_chg_no_lock(struct pvr2_hdw *hdw, + unsigned long msk, + unsigned long val) +{ + unsigned long val2; + msk &= PVR2_SUBSYS_ALL; + val2 = ((hdw->subsys_stream_mask & ~msk) | (val & msk)); + pvr2_trace(PVR2_TRACE_INIT, + "stream mask changing 0x%lx:0x%lx from 0x%lx to 0x%lx", + msk,val,hdw->subsys_stream_mask,val2); + hdw->subsys_stream_mask = val2; +} + + +void pvr2_hdw_subsys_stream_bit_chg(struct pvr2_hdw *hdw, + unsigned long msk, + unsigned long val) +{ + LOCK_TAKE(hdw->big_lock); do { + pvr2_hdw_subsys_stream_bit_chg_no_lock(hdw,msk,val); + } while (0); LOCK_GIVE(hdw->big_lock); +} + + +static int pvr2_hdw_set_streaming_no_lock(struct pvr2_hdw *hdw,int enableFl) +{ + if ((!enableFl) == !(hdw->flag_streaming_enabled)) return 0; + if (enableFl) { + pvr2_trace(PVR2_TRACE_START_STOP, + "/*--TRACE_STREAM--*/ enable"); + pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,~0); + } else { + pvr2_trace(PVR2_TRACE_START_STOP, + "/*--TRACE_STREAM--*/ disable"); + pvr2_hdw_subsys_bit_chg_no_lock(hdw,hdw->subsys_stream_mask,0); + } + if (!hdw->flag_ok) return -EIO; + hdw->flag_streaming_enabled = enableFl != 0; + return 0; +} + + +int pvr2_hdw_get_streaming(struct pvr2_hdw *hdw) +{ + return hdw->flag_streaming_enabled != 0; +} + + +int pvr2_hdw_set_streaming(struct pvr2_hdw *hdw,int enable_flag) +{ + int ret; + LOCK_TAKE(hdw->big_lock); do { + ret = pvr2_hdw_set_streaming_no_lock(hdw,enable_flag); + } while (0); LOCK_GIVE(hdw->big_lock); + return ret; +} + + +static int pvr2_hdw_set_stream_type_no_lock(struct pvr2_hdw *hdw, + enum pvr2_config config) +{ + unsigned long sm = hdw->subsys_enabled_mask; + if (!hdw->flag_ok) return -EIO; + pvr2_hdw_subsys_bit_chg_no_lock(hdw,hdw->subsys_stream_mask,0); + hdw->config = config; + pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,sm); + return 0; +} + + +int pvr2_hdw_set_stream_type(struct pvr2_hdw *hdw,enum pvr2_config config) +{ + int ret; + if (!hdw->flag_ok) return -EIO; + LOCK_TAKE(hdw->big_lock); + ret = pvr2_hdw_set_stream_type_no_lock(hdw,config); + LOCK_GIVE(hdw->big_lock); + return ret; +} + + +static int get_default_tuner_type(struct pvr2_hdw *hdw) +{ + int unit_number = hdw->unit_number; + int tp = -1; + if ((unit_number >= 0) && (unit_number < PVR_NUM)) { + tp = tuner[unit_number]; + } + if (tp < 0) return -EINVAL; + hdw->tuner_type = tp; + return 0; +} + + +static v4l2_std_id get_default_standard(struct pvr2_hdw *hdw) +{ + int unit_number = hdw->unit_number; + int tp = 0; + if ((unit_number >= 0) && (unit_number < PVR_NUM)) { + tp = video_std[unit_number]; + } + return tp; +} + + +static unsigned int get_default_error_tolerance(struct pvr2_hdw *hdw) +{ + int unit_number = hdw->unit_number; + int tp = 0; + if ((unit_number >= 0) && (unit_number < PVR_NUM)) { + tp = tolerance[unit_number]; + } + return tp; +} + + +static int pvr2_hdw_check_firmware(struct pvr2_hdw *hdw) +{ + /* Try a harmless request to fetch the eeprom's address over + endpoint 1. See what happens. Only the full FX2 image can + respond to this. If this probe fails then likely the FX2 + firmware needs be loaded. */ + int result; + LOCK_TAKE(hdw->ctl_lock); do { + hdw->cmd_buffer[0] = 0xeb; + result = pvr2_send_request_ex(hdw,HZ*1,!0, + hdw->cmd_buffer,1, + hdw->cmd_buffer,1); + if (result < 0) break; + } while(0); LOCK_GIVE(hdw->ctl_lock); + if (result) { + pvr2_trace(PVR2_TRACE_INIT, + "Probe of device endpoint 1 result status %d", + result); + } else { + pvr2_trace(PVR2_TRACE_INIT, + "Probe of device endpoint 1 succeeded"); + } + return result == 0; +} + +static void pvr2_hdw_setup_std(struct pvr2_hdw *hdw) +{ + char buf[40]; + unsigned int bcnt; + v4l2_std_id std1,std2; + + std1 = get_default_standard(hdw); + + bcnt = pvr2_std_id_to_str(buf,sizeof(buf),hdw->std_mask_eeprom); + pvr2_trace(PVR2_TRACE_INIT, + "Supported video standard(s) reported by eeprom: %.*s", + bcnt,buf); + + hdw->std_mask_avail = hdw->std_mask_eeprom; + + std2 = std1 & ~hdw->std_mask_avail; + if (std2) { + bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std2); + pvr2_trace(PVR2_TRACE_INIT, + "Expanding supported video standards" + " to include: %.*s", + bcnt,buf); + hdw->std_mask_avail |= std2; + } + + pvr2_hdw_internal_set_std_avail(hdw); + + if (std1) { + bcnt = pvr2_std_id_to_str(buf,sizeof(buf),std1); + pvr2_trace(PVR2_TRACE_INIT, + "Initial video standard forced to %.*s", + bcnt,buf); + hdw->std_mask_cur = std1; + hdw->std_dirty = !0; + pvr2_hdw_internal_find_stdenum(hdw); + return; + } + + if (hdw->std_enum_cnt > 1) { + // Autoselect the first listed standard + hdw->std_enum_cur = 1; + hdw->std_mask_cur = hdw->std_defs[hdw->std_enum_cur-1].id; + hdw->std_dirty = !0; + pvr2_trace(PVR2_TRACE_INIT, + "Initial video standard auto-selected to %s", + hdw->std_defs[hdw->std_enum_cur-1].name); + return; + } + + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Unable to select a viable initial video standard"); +} + + +static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) +{ + int ret; + unsigned int idx; + struct pvr2_ctrl *cptr; + int reloadFl = 0; + if (!reloadFl) { + reloadFl = (hdw->usb_intf->cur_altsetting->desc.bNumEndpoints + == 0); + if (reloadFl) { + pvr2_trace(PVR2_TRACE_INIT, + "USB endpoint config looks strange" + "; possibly firmware needs to be loaded"); + } + } + if (!reloadFl) { + reloadFl = !pvr2_hdw_check_firmware(hdw); + if (reloadFl) { + pvr2_trace(PVR2_TRACE_INIT, + "Check for FX2 firmware failed" + "; possibly firmware needs to be loaded"); + } + } + if (reloadFl) { + if (pvr2_upload_firmware1(hdw) != 0) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Failure uploading firmware1"); + } + return; + } + hdw->fw1_state = FW1_STATE_OK; + + if (initusbreset) { + pvr2_hdw_device_reset(hdw); + } + if (!pvr2_hdw_dev_ok(hdw)) return; + + for (idx = 0; idx < pvr2_client_lists[hdw->hdw_type].cnt; idx++) { + request_module(pvr2_client_lists[hdw->hdw_type].lst[idx]); + } + + pvr2_hdw_cmd_powerup(hdw); + if (!pvr2_hdw_dev_ok(hdw)) return; + + if (pvr2_upload_firmware2(hdw)){ + pvr2_trace(PVR2_TRACE_ERROR_LEGS,"device unstable!!"); + pvr2_hdw_render_useless(hdw); + return; + } + + // This step MUST happen after the earlier powerup step. + pvr2_i2c_core_init(hdw); + if (!pvr2_hdw_dev_ok(hdw)) return; + + for (idx = 0; idx < CTRLDEF_COUNT; idx++) { + cptr = hdw->controls + idx; + if (cptr->info->skip_init) continue; + if (!cptr->info->set_value) continue; + cptr->info->set_value(cptr,~0,cptr->info->default_value); + } + + // Do not use pvr2_reset_ctl_endpoints() here. It is not + // thread-safe against the normal pvr2_send_request() mechanism. + // (We should make it thread safe). + + ret = pvr2_hdw_get_eeprom_addr(hdw); + if (!pvr2_hdw_dev_ok(hdw)) return; + if (ret < 0) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Unable to determine location of eeprom, skipping"); + } else { + hdw->eeprom_addr = ret; + pvr2_eeprom_analyze(hdw); + if (!pvr2_hdw_dev_ok(hdw)) return; + } + + pvr2_hdw_setup_std(hdw); + + if (!get_default_tuner_type(hdw)) { + pvr2_trace(PVR2_TRACE_INIT, + "pvr2_hdw_setup: Tuner type overridden to %d", + hdw->tuner_type); + } + + hdw->tuner_updated = !0; + pvr2_i2c_core_check_stale(hdw); + hdw->tuner_updated = 0; + + if (!pvr2_hdw_dev_ok(hdw)) return; + + pvr2_hdw_commit_ctl_internal(hdw); + if (!pvr2_hdw_dev_ok(hdw)) return; + + hdw->vid_stream = pvr2_stream_create(); + if (!pvr2_hdw_dev_ok(hdw)) return; + pvr2_trace(PVR2_TRACE_INIT, + "pvr2_hdw_setup: video stream is %p",hdw->vid_stream); + if (hdw->vid_stream) { + idx = get_default_error_tolerance(hdw); + if (idx) { + pvr2_trace(PVR2_TRACE_INIT, + "pvr2_hdw_setup: video stream %p" + " setting tolerance %u", + hdw->vid_stream,idx); + } + pvr2_stream_setup(hdw->vid_stream,hdw->usb_dev, + PVR2_VID_ENDPOINT,idx); + } + + if (!pvr2_hdw_dev_ok(hdw)) return; + + /* Make sure everything is up to date */ + pvr2_i2c_core_sync(hdw); + + if (!pvr2_hdw_dev_ok(hdw)) return; + + hdw->flag_init_ok = !0; +} + + +int pvr2_hdw_setup(struct pvr2_hdw *hdw) +{ + pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) begin",hdw); + LOCK_TAKE(hdw->big_lock); do { + pvr2_hdw_setup_low(hdw); + pvr2_trace(PVR2_TRACE_INIT, + "pvr2_hdw_setup(hdw=%p) done, ok=%d init_ok=%d", + hdw,hdw->flag_ok,hdw->flag_init_ok); + if (pvr2_hdw_dev_ok(hdw)) { + if (pvr2_hdw_init_ok(hdw)) { + pvr2_trace( + PVR2_TRACE_INFO, + "Device initialization" + " completed successfully."); + break; + } + if (hdw->fw1_state == FW1_STATE_RELOAD) { + pvr2_trace( + PVR2_TRACE_INFO, + "Device microcontroller firmware" + " (re)loaded; it should now reset" + " and reconnect."); + break; + } + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "Device initialization was not successful."); + if (hdw->fw1_state == FW1_STATE_MISSING) { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "Giving up since device" + " microcontroller firmware" + " appears to be missing."); + break; + } + } + if (procreload) { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "Attempting pvrusb2 recovery by reloading" + " primary firmware."); + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "If this works, device should disconnect" + " and reconnect in a sane state."); + hdw->fw1_state = FW1_STATE_UNKNOWN; + pvr2_upload_firmware1(hdw); + } else { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "***WARNING*** pvrusb2 device hardware" + " appears to be jammed" + " and I can't clear it."); + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "You might need to power cycle" + " the pvrusb2 device" + " in order to recover."); + } + } while (0); LOCK_GIVE(hdw->big_lock); + pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_setup(hdw=%p) end",hdw); + return hdw->flag_init_ok; +} + + +/* Create and return a structure for interacting with the underlying + hardware */ +struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, + const struct usb_device_id *devid) +{ + unsigned int idx,cnt1,cnt2; + struct pvr2_hdw *hdw; + unsigned int hdw_type; + int valid_std_mask; + struct pvr2_ctrl *cptr; + __u8 ifnum; + struct v4l2_queryctrl qctrl; + struct pvr2_ctl_info *ciptr; + + hdw_type = devid - pvr2_device_table; + if (hdw_type >= + sizeof(pvr2_device_names)/sizeof(pvr2_device_names[0])) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Bogus device type of %u reported",hdw_type); + return NULL; + } + + hdw = kmalloc(sizeof(*hdw),GFP_KERNEL); + pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_create: hdw=%p, type \"%s\"", + hdw,pvr2_device_names[hdw_type]); + if (!hdw) goto fail; + memset(hdw,0,sizeof(*hdw)); + cx2341x_fill_defaults(&hdw->enc_ctl_state); + + hdw->control_cnt = CTRLDEF_COUNT; + hdw->control_cnt += MPEGDEF_COUNT; + hdw->controls = kmalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt, + GFP_KERNEL); + if (!hdw->controls) goto fail; + memset(hdw->controls,0,sizeof(struct pvr2_ctrl) * hdw->control_cnt); + hdw->hdw_type = hdw_type; + for (idx = 0; idx < hdw->control_cnt; idx++) { + cptr = hdw->controls + idx; + cptr->hdw = hdw; + } + for (idx = 0; idx < 32; idx++) { + hdw->std_mask_ptrs[idx] = hdw->std_mask_names[idx]; + } + for (idx = 0; idx < CTRLDEF_COUNT; idx++) { + cptr = hdw->controls + idx; + cptr->info = control_defs+idx; + } + /* Define and configure additional controls from cx2341x module. */ + hdw->mpeg_ctrl_info = kmalloc( + sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL); + if (!hdw->mpeg_ctrl_info) goto fail; + memset(hdw->mpeg_ctrl_info,0, + sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT); + for (idx = 0; idx < MPEGDEF_COUNT; idx++) { + cptr = hdw->controls + idx + CTRLDEF_COUNT; + ciptr = &(hdw->mpeg_ctrl_info[idx].info); + ciptr->desc = hdw->mpeg_ctrl_info[idx].desc; + ciptr->name = mpeg_ids[idx].strid; + ciptr->v4l_id = mpeg_ids[idx].id; + ciptr->skip_init = !0; + ciptr->get_value = ctrl_cx2341x_get; + ciptr->get_v4lflags = ctrl_cx2341x_getv4lflags; + ciptr->is_dirty = ctrl_cx2341x_is_dirty; + if (!idx) ciptr->clear_dirty = ctrl_cx2341x_clear_dirty; + qctrl.id = ciptr->v4l_id; + cx2341x_ctrl_query(&hdw->enc_ctl_state,&qctrl); + if (!(qctrl.flags & V4L2_CTRL_FLAG_READ_ONLY)) { + ciptr->set_value = ctrl_cx2341x_set; + } + strncpy(hdw->mpeg_ctrl_info[idx].desc,qctrl.name, + PVR2_CTLD_INFO_DESC_SIZE); + hdw->mpeg_ctrl_info[idx].desc[PVR2_CTLD_INFO_DESC_SIZE-1] = 0; + ciptr->default_value = qctrl.default_value; + switch (qctrl.type) { + default: + case V4L2_CTRL_TYPE_INTEGER: + ciptr->type = pvr2_ctl_int; + ciptr->def.type_int.min_value = qctrl.minimum; + ciptr->def.type_int.max_value = qctrl.maximum; + break; + case V4L2_CTRL_TYPE_BOOLEAN: + ciptr->type = pvr2_ctl_bool; + break; + case V4L2_CTRL_TYPE_MENU: + ciptr->type = pvr2_ctl_enum; + ciptr->def.type_enum.value_names = + cx2341x_ctrl_get_menu(ciptr->v4l_id); + for (cnt1 = 0; + ciptr->def.type_enum.value_names[cnt1] != NULL; + cnt1++) { } + ciptr->def.type_enum.count = cnt1; + break; + } + cptr->info = ciptr; + } + + // Initialize video standard enum dynamic control + cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDENUM); + if (cptr) { + memcpy(&hdw->std_info_enum,cptr->info, + sizeof(hdw->std_info_enum)); + cptr->info = &hdw->std_info_enum; + + } + // Initialize control data regarding video standard masks + valid_std_mask = pvr2_std_get_usable(); + for (idx = 0; idx < 32; idx++) { + if (!(valid_std_mask & (1 << idx))) continue; + cnt1 = pvr2_std_id_to_str( + hdw->std_mask_names[idx], + sizeof(hdw->std_mask_names[idx])-1, + 1 << idx); + hdw->std_mask_names[idx][cnt1] = 0; + } + cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDAVAIL); + if (cptr) { + memcpy(&hdw->std_info_avail,cptr->info, + sizeof(hdw->std_info_avail)); + cptr->info = &hdw->std_info_avail; + hdw->std_info_avail.def.type_bitmask.bit_names = + hdw->std_mask_ptrs; + hdw->std_info_avail.def.type_bitmask.valid_bits = + valid_std_mask; + } + cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR); + if (cptr) { + memcpy(&hdw->std_info_cur,cptr->info, + sizeof(hdw->std_info_cur)); + cptr->info = &hdw->std_info_cur; + hdw->std_info_cur.def.type_bitmask.bit_names = + hdw->std_mask_ptrs; + hdw->std_info_avail.def.type_bitmask.valid_bits = + valid_std_mask; + } + + hdw->eeprom_addr = -1; + hdw->unit_number = -1; + hdw->v4l_minor_number = -1; + hdw->ctl_write_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL); + if (!hdw->ctl_write_buffer) goto fail; + hdw->ctl_read_buffer = kmalloc(PVR2_CTL_BUFFSIZE,GFP_KERNEL); + if (!hdw->ctl_read_buffer) goto fail; + hdw->ctl_write_urb = usb_alloc_urb(0,GFP_KERNEL); + if (!hdw->ctl_write_urb) goto fail; + hdw->ctl_read_urb = usb_alloc_urb(0,GFP_KERNEL); + if (!hdw->ctl_read_urb) goto fail; + + down(&pvr2_unit_sem); do { + for (idx = 0; idx < PVR_NUM; idx++) { + if (unit_pointers[idx]) continue; + hdw->unit_number = idx; + unit_pointers[idx] = hdw; + break; + } + } while (0); up(&pvr2_unit_sem); + + cnt1 = 0; + cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"pvrusb2"); + cnt1 += cnt2; + if (hdw->unit_number >= 0) { + cnt2 = scnprintf(hdw->name+cnt1,sizeof(hdw->name)-cnt1,"_%c", + ('a' + hdw->unit_number)); + cnt1 += cnt2; + } + if (cnt1 >= sizeof(hdw->name)) cnt1 = sizeof(hdw->name)-1; + hdw->name[cnt1] = 0; + + pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s", + hdw->unit_number,hdw->name); + + hdw->tuner_type = -1; + hdw->flag_ok = !0; + /* Initialize the mask of subsystems that we will shut down when we + stop streaming. */ + hdw->subsys_stream_mask = PVR2_SUBSYS_RUN_ALL; + hdw->subsys_stream_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG); + + pvr2_trace(PVR2_TRACE_INIT,"subsys_stream_mask: 0x%lx", + hdw->subsys_stream_mask); + + hdw->usb_intf = intf; + hdw->usb_dev = interface_to_usbdev(intf); + + ifnum = hdw->usb_intf->cur_altsetting->desc.bInterfaceNumber; + usb_set_interface(hdw->usb_dev,ifnum,0); + + mutex_init(&hdw->ctl_lock_mutex); + mutex_init(&hdw->big_lock_mutex); + + return hdw; + fail: + if (hdw) { + if (hdw->ctl_read_urb) usb_free_urb(hdw->ctl_read_urb); + if (hdw->ctl_write_urb) usb_free_urb(hdw->ctl_write_urb); + if (hdw->ctl_read_buffer) kfree(hdw->ctl_read_buffer); + if (hdw->ctl_write_buffer) kfree(hdw->ctl_write_buffer); + if (hdw->controls) kfree(hdw->controls); + if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info); + kfree(hdw); + } + return NULL; +} + + +/* Remove _all_ associations between this driver and the underlying USB + layer. */ +static void pvr2_hdw_remove_usb_stuff(struct pvr2_hdw *hdw) +{ + if (hdw->flag_disconnected) return; + pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_remove_usb_stuff: hdw=%p",hdw); + if (hdw->ctl_read_urb) { + usb_kill_urb(hdw->ctl_read_urb); + usb_free_urb(hdw->ctl_read_urb); + hdw->ctl_read_urb = NULL; + } + if (hdw->ctl_write_urb) { + usb_kill_urb(hdw->ctl_write_urb); + usb_free_urb(hdw->ctl_write_urb); + hdw->ctl_write_urb = NULL; + } + if (hdw->ctl_read_buffer) { + kfree(hdw->ctl_read_buffer); + hdw->ctl_read_buffer = NULL; + } + if (hdw->ctl_write_buffer) { + kfree(hdw->ctl_write_buffer); + hdw->ctl_write_buffer = NULL; + } + pvr2_hdw_render_useless_unlocked(hdw); + hdw->flag_disconnected = !0; + hdw->usb_dev = NULL; + hdw->usb_intf = NULL; +} + + +/* Destroy hardware interaction structure */ +void pvr2_hdw_destroy(struct pvr2_hdw *hdw) +{ + pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_destroy: hdw=%p",hdw); + if (hdw->fw_buffer) { + kfree(hdw->fw_buffer); + hdw->fw_buffer = NULL; + } + if (hdw->vid_stream) { + pvr2_stream_destroy(hdw->vid_stream); + hdw->vid_stream = NULL; + } + if (hdw->audio_stat) { + hdw->audio_stat->detach(hdw->audio_stat->ctxt); + } + if (hdw->decoder_ctrl) { + hdw->decoder_ctrl->detach(hdw->decoder_ctrl->ctxt); + } + pvr2_i2c_core_done(hdw); + pvr2_hdw_remove_usb_stuff(hdw); + down(&pvr2_unit_sem); do { + if ((hdw->unit_number >= 0) && + (hdw->unit_number < PVR_NUM) && + (unit_pointers[hdw->unit_number] == hdw)) { + unit_pointers[hdw->unit_number] = NULL; + } + } while (0); up(&pvr2_unit_sem); + if (hdw->controls) kfree(hdw->controls); + if (hdw->mpeg_ctrl_info) kfree(hdw->mpeg_ctrl_info); + if (hdw->std_defs) kfree(hdw->std_defs); + if (hdw->std_enum_names) kfree(hdw->std_enum_names); + kfree(hdw); +} + + +int pvr2_hdw_init_ok(struct pvr2_hdw *hdw) +{ + return hdw->flag_init_ok; +} + + +int pvr2_hdw_dev_ok(struct pvr2_hdw *hdw) +{ + return (hdw && hdw->flag_ok); +} + + +/* Called when hardware has been unplugged */ +void pvr2_hdw_disconnect(struct pvr2_hdw *hdw) +{ + pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_disconnect(hdw=%p)",hdw); + LOCK_TAKE(hdw->big_lock); + LOCK_TAKE(hdw->ctl_lock); + pvr2_hdw_remove_usb_stuff(hdw); + LOCK_GIVE(hdw->ctl_lock); + LOCK_GIVE(hdw->big_lock); +} + + +// Attempt to autoselect an appropriate value for std_enum_cur given +// whatever is currently in std_mask_cur +static void pvr2_hdw_internal_find_stdenum(struct pvr2_hdw *hdw) +{ + unsigned int idx; + for (idx = 1; idx < hdw->std_enum_cnt; idx++) { + if (hdw->std_defs[idx-1].id == hdw->std_mask_cur) { + hdw->std_enum_cur = idx; + return; + } + } + hdw->std_enum_cur = 0; +} + + +// Calculate correct set of enumerated standards based on currently known +// set of available standards bits. +static void pvr2_hdw_internal_set_std_avail(struct pvr2_hdw *hdw) +{ + struct v4l2_standard *newstd; + unsigned int std_cnt; + unsigned int idx; + + newstd = pvr2_std_create_enum(&std_cnt,hdw->std_mask_avail); + + if (hdw->std_defs) { + kfree(hdw->std_defs); + hdw->std_defs = NULL; + } + hdw->std_enum_cnt = 0; + if (hdw->std_enum_names) { + kfree(hdw->std_enum_names); + hdw->std_enum_names = NULL; + } + + if (!std_cnt) { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "WARNING: Failed to identify any viable standards"); + } + hdw->std_enum_names = kmalloc(sizeof(char *)*(std_cnt+1),GFP_KERNEL); + hdw->std_enum_names[0] = "none"; + for (idx = 0; idx < std_cnt; idx++) { + hdw->std_enum_names[idx+1] = + newstd[idx].name; + } + // Set up the dynamic control for this standard + hdw->std_info_enum.def.type_enum.value_names = hdw->std_enum_names; + hdw->std_info_enum.def.type_enum.count = std_cnt+1; + hdw->std_defs = newstd; + hdw->std_enum_cnt = std_cnt+1; + hdw->std_enum_cur = 0; + hdw->std_info_cur.def.type_bitmask.valid_bits = hdw->std_mask_avail; +} + + +int pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw, + struct v4l2_standard *std, + unsigned int idx) +{ + int ret = -EINVAL; + if (!idx) return ret; + LOCK_TAKE(hdw->big_lock); do { + if (idx >= hdw->std_enum_cnt) break; + idx--; + memcpy(std,hdw->std_defs+idx,sizeof(*std)); + ret = 0; + } while (0); LOCK_GIVE(hdw->big_lock); + return ret; +} + + +/* Get the number of defined controls */ +unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *hdw) +{ + return hdw->control_cnt; +} + + +/* Retrieve a control handle given its index (0..count-1) */ +struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *hdw, + unsigned int idx) +{ + if (idx >= hdw->control_cnt) return NULL; + return hdw->controls + idx; +} + + +/* Retrieve a control handle given its index (0..count-1) */ +struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *hdw, + unsigned int ctl_id) +{ + struct pvr2_ctrl *cptr; + unsigned int idx; + int i; + + /* This could be made a lot more efficient, but for now... */ + for (idx = 0; idx < hdw->control_cnt; idx++) { + cptr = hdw->controls + idx; + i = cptr->info->internal_id; + if (i && (i == ctl_id)) return cptr; + } + return NULL; +} + + +/* Given a V4L ID, retrieve the control structure associated with it. */ +struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *hdw,unsigned int ctl_id) +{ + struct pvr2_ctrl *cptr; + unsigned int idx; + int i; + + /* This could be made a lot more efficient, but for now... */ + for (idx = 0; idx < hdw->control_cnt; idx++) { + cptr = hdw->controls + idx; + i = cptr->info->v4l_id; + if (i && (i == ctl_id)) return cptr; + } + return NULL; +} + + +/* Given a V4L ID for its immediate predecessor, retrieve the control + structure associated with it. */ +struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *hdw, + unsigned int ctl_id) +{ + struct pvr2_ctrl *cptr,*cp2; + unsigned int idx; + int i; + + /* This could be made a lot more efficient, but for now... */ + cp2 = NULL; + for (idx = 0; idx < hdw->control_cnt; idx++) { + cptr = hdw->controls + idx; + i = cptr->info->v4l_id; + if (!i) continue; + if (i <= ctl_id) continue; + if (cp2 && (cp2->info->v4l_id < i)) continue; + cp2 = cptr; + } + return cp2; + return NULL; +} + + +static const char *get_ctrl_typename(enum pvr2_ctl_type tp) +{ + switch (tp) { + case pvr2_ctl_int: return "integer"; + case pvr2_ctl_enum: return "enum"; + case pvr2_ctl_bool: return "boolean"; + case pvr2_ctl_bitmask: return "bitmask"; + } + return ""; +} + + +/* Commit all control changes made up to this point. Subsystems can be + indirectly affected by these changes. For a given set of things being + committed, we'll clear the affected subsystem bits and then once we're + done committing everything we'll make a request to restore the subsystem + state(s) back to their previous value before this function was called. + Thus we can automatically reconfigure affected pieces of the driver as + controls are changed. */ +static int pvr2_hdw_commit_ctl_internal(struct pvr2_hdw *hdw) +{ + unsigned long saved_subsys_mask = hdw->subsys_enabled_mask; + unsigned long stale_subsys_mask = 0; + unsigned int idx; + struct pvr2_ctrl *cptr; + int value; + int commit_flag = 0; + char buf[100]; + unsigned int bcnt,ccnt; + + for (idx = 0; idx < hdw->control_cnt; idx++) { + cptr = hdw->controls + idx; + if (cptr->info->is_dirty == 0) continue; + if (!cptr->info->is_dirty(cptr)) continue; + if (!commit_flag) { + commit_flag = !0; + } + + bcnt = scnprintf(buf,sizeof(buf),"\"%s\" <-- ", + cptr->info->name); + value = 0; + cptr->info->get_value(cptr,&value); + pvr2_ctrl_value_to_sym_internal(cptr,~0,value, + buf+bcnt, + sizeof(buf)-bcnt,&ccnt); + bcnt += ccnt; + bcnt += scnprintf(buf+bcnt,sizeof(buf)-bcnt," <%s>", + get_ctrl_typename(cptr->info->type)); + pvr2_trace(PVR2_TRACE_CTL, + "/*--TRACE_COMMIT--*/ %.*s", + bcnt,buf); + } + + if (!commit_flag) { + /* Nothing has changed */ + return 0; + } + + /* When video standard changes, reset the hres and vres values - + but if the user has pending changes there, then let the changes + take priority. */ + if (hdw->std_dirty) { + /* Rewrite the vertical resolution to be appropriate to the + video standard that has been selected. */ + int nvres; + if (hdw->std_mask_cur & V4L2_STD_525_60) { + nvres = 480; + } else { + nvres = 576; + } + if (nvres != hdw->res_ver_val) { + hdw->res_ver_val = nvres; + hdw->res_ver_dirty = !0; + } + } + + if (hdw->std_dirty || + 0) { + /* If any of this changes, then the encoder needs to be + reconfigured, and we need to reset the stream. */ + stale_subsys_mask |= (1<<PVR2_SUBSYS_B_ENC_CFG); + stale_subsys_mask |= hdw->subsys_stream_mask; + } + + if (hdw->srate_dirty) { + /* Write new sample rate into control structure since + * the master copy is stale. We must track srate + * separate from the mpeg control structure because + * other logic also uses this value. */ + struct v4l2_ext_controls cs; + struct v4l2_ext_control c1; + memset(&cs,0,sizeof(cs)); + memset(&c1,0,sizeof(c1)); + cs.controls = &c1; + cs.count = 1; + c1.id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ; + c1.value = hdw->srate_val; + cx2341x_ext_ctrls(&hdw->enc_ctl_state,&cs,VIDIOC_S_EXT_CTRLS); + } + + /* Scan i2c core at this point - before we clear all the dirty + bits. Various parts of the i2c core will notice dirty bits as + appropriate and arrange to broadcast or directly send updates to + the client drivers in order to keep everything in sync */ + pvr2_i2c_core_check_stale(hdw); + + for (idx = 0; idx < hdw->control_cnt; idx++) { + cptr = hdw->controls + idx; + if (!cptr->info->clear_dirty) continue; + cptr->info->clear_dirty(cptr); + } + + /* Now execute i2c core update */ + pvr2_i2c_core_sync(hdw); + + pvr2_hdw_subsys_bit_chg_no_lock(hdw,stale_subsys_mask,0); + pvr2_hdw_subsys_bit_chg_no_lock(hdw,~0,saved_subsys_mask); + + return 0; +} + + +int pvr2_hdw_commit_ctl(struct pvr2_hdw *hdw) +{ + LOCK_TAKE(hdw->big_lock); do { + pvr2_hdw_commit_ctl_internal(hdw); + } while (0); LOCK_GIVE(hdw->big_lock); + return 0; +} + + +void pvr2_hdw_poll(struct pvr2_hdw *hdw) +{ + LOCK_TAKE(hdw->big_lock); do { + pvr2_i2c_core_sync(hdw); + } while (0); LOCK_GIVE(hdw->big_lock); +} + + +void pvr2_hdw_setup_poll_trigger(struct pvr2_hdw *hdw, + void (*func)(void *), + void *data) +{ + LOCK_TAKE(hdw->big_lock); do { + hdw->poll_trigger_func = func; + hdw->poll_trigger_data = data; + } while (0); LOCK_GIVE(hdw->big_lock); +} + + +void pvr2_hdw_poll_trigger_unlocked(struct pvr2_hdw *hdw) +{ + if (hdw->poll_trigger_func) { + hdw->poll_trigger_func(hdw->poll_trigger_data); + } +} + +/* Return name for this driver instance */ +const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *hdw) +{ + return hdw->name; +} + + +/* Return bit mask indicating signal status */ +static unsigned int pvr2_hdw_get_signal_status_internal(struct pvr2_hdw *hdw) +{ + unsigned int msk = 0; + switch (hdw->input_val) { + case PVR2_CVAL_INPUT_TV: + case PVR2_CVAL_INPUT_RADIO: + if (hdw->decoder_ctrl && + hdw->decoder_ctrl->tuned(hdw->decoder_ctrl->ctxt)) { + msk |= PVR2_SIGNAL_OK; + if (hdw->audio_stat && + hdw->audio_stat->status(hdw->audio_stat->ctxt)) { + if (hdw->flag_stereo) { + msk |= PVR2_SIGNAL_STEREO; + } + if (hdw->flag_bilingual) { + msk |= PVR2_SIGNAL_SAP; + } + } + } + break; + default: + msk |= PVR2_SIGNAL_OK | PVR2_SIGNAL_STEREO; + } + return msk; +} + + +int pvr2_hdw_is_hsm(struct pvr2_hdw *hdw) +{ + int result; + LOCK_TAKE(hdw->ctl_lock); do { + hdw->cmd_buffer[0] = 0x0b; + result = pvr2_send_request(hdw, + hdw->cmd_buffer,1, + hdw->cmd_buffer,1); + if (result < 0) break; + result = (hdw->cmd_buffer[0] != 0); + } while(0); LOCK_GIVE(hdw->ctl_lock); + return result; +} + + +/* Return bit mask indicating signal status */ +unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *hdw) +{ + unsigned int msk = 0; + LOCK_TAKE(hdw->big_lock); do { + msk = pvr2_hdw_get_signal_status_internal(hdw); + } while (0); LOCK_GIVE(hdw->big_lock); + return msk; +} + + +/* Get handle to video output stream */ +struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *hp) +{ + return hp->vid_stream; +} + + +void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw) +{ + int nr = pvr2_hdw_get_unit_number(hdw); + LOCK_TAKE(hdw->big_lock); do { + hdw->log_requested = !0; + printk(KERN_INFO "pvrusb2: ================= START STATUS CARD #%d =================\n", nr); + pvr2_i2c_core_check_stale(hdw); + hdw->log_requested = 0; + pvr2_i2c_core_sync(hdw); + pvr2_trace(PVR2_TRACE_INFO,"cx2341x config:"); + cx2341x_log_status(&hdw->enc_ctl_state, "pvrusb2"); + printk(KERN_INFO "pvrusb2: ================== END STATUS CARD #%d ==================\n", nr); + } while (0); LOCK_GIVE(hdw->big_lock); +} + +void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, int enable_flag) +{ + int ret; + u16 address; + unsigned int pipe; + LOCK_TAKE(hdw->big_lock); do { + if ((hdw->fw_buffer == 0) == !enable_flag) break; + + if (!enable_flag) { + pvr2_trace(PVR2_TRACE_FIRMWARE, + "Cleaning up after CPU firmware fetch"); + kfree(hdw->fw_buffer); + hdw->fw_buffer = NULL; + hdw->fw_size = 0; + /* Now release the CPU. It will disconnect and + reconnect later. */ + pvr2_hdw_cpureset_assert(hdw,0); + break; + } + + pvr2_trace(PVR2_TRACE_FIRMWARE, + "Preparing to suck out CPU firmware"); + hdw->fw_size = 0x2000; + hdw->fw_buffer = kmalloc(hdw->fw_size,GFP_KERNEL); + if (!hdw->fw_buffer) { + hdw->fw_size = 0; + break; + } + + memset(hdw->fw_buffer,0,hdw->fw_size); + + /* We have to hold the CPU during firmware upload. */ + pvr2_hdw_cpureset_assert(hdw,1); + + /* download the firmware from address 0000-1fff in 2048 + (=0x800) bytes chunk. */ + + pvr2_trace(PVR2_TRACE_FIRMWARE,"Grabbing CPU firmware"); + pipe = usb_rcvctrlpipe(hdw->usb_dev, 0); + for(address = 0; address < hdw->fw_size; address += 0x800) { + ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0xc0, + address,0, + hdw->fw_buffer+address,0x800,HZ); + if (ret < 0) break; + } + + pvr2_trace(PVR2_TRACE_FIRMWARE,"Done grabbing CPU firmware"); + + } while (0); LOCK_GIVE(hdw->big_lock); +} + + +/* Return true if we're in a mode for retrieval CPU firmware */ +int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *hdw) +{ + return hdw->fw_buffer != 0; +} + + +int pvr2_hdw_cpufw_get(struct pvr2_hdw *hdw,unsigned int offs, + char *buf,unsigned int cnt) +{ + int ret = -EINVAL; + LOCK_TAKE(hdw->big_lock); do { + if (!buf) break; + if (!cnt) break; + + if (!hdw->fw_buffer) { + ret = -EIO; + break; + } + + if (offs >= hdw->fw_size) { + pvr2_trace(PVR2_TRACE_FIRMWARE, + "Read firmware data offs=%d EOF", + offs); + ret = 0; + break; + } + + if (offs + cnt > hdw->fw_size) cnt = hdw->fw_size - offs; + + memcpy(buf,hdw->fw_buffer+offs,cnt); + + pvr2_trace(PVR2_TRACE_FIRMWARE, + "Read firmware data offs=%d cnt=%d", + offs,cnt); + ret = cnt; + } while (0); LOCK_GIVE(hdw->big_lock); + + return ret; +} + + +int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *hdw) +{ + return hdw->v4l_minor_number; +} + + +/* Store the v4l minor device number */ +void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *hdw,int v) +{ + hdw->v4l_minor_number = v; +} + + +static void pvr2_ctl_write_complete(struct urb *urb, struct pt_regs *regs) +{ + struct pvr2_hdw *hdw = urb->context; + hdw->ctl_write_pend_flag = 0; + if (hdw->ctl_read_pend_flag) return; + complete(&hdw->ctl_done); +} + + +static void pvr2_ctl_read_complete(struct urb *urb, struct pt_regs *regs) +{ + struct pvr2_hdw *hdw = urb->context; + hdw->ctl_read_pend_flag = 0; + if (hdw->ctl_write_pend_flag) return; + complete(&hdw->ctl_done); +} + + +static void pvr2_ctl_timeout(unsigned long data) +{ + struct pvr2_hdw *hdw = (struct pvr2_hdw *)data; + if (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) { + hdw->ctl_timeout_flag = !0; + if (hdw->ctl_write_pend_flag && hdw->ctl_write_urb) { + usb_unlink_urb(hdw->ctl_write_urb); + } + if (hdw->ctl_read_pend_flag && hdw->ctl_read_urb) { + usb_unlink_urb(hdw->ctl_read_urb); + } + } +} + + +/* Issue a command and get a response from the device. This extended + version includes a probe flag (which if set means that device errors + should not be logged or treated as fatal) and a timeout in jiffies. + This can be used to non-lethally probe the health of endpoint 1. */ +static int pvr2_send_request_ex(struct pvr2_hdw *hdw, + unsigned int timeout,int probe_fl, + void *write_data,unsigned int write_len, + void *read_data,unsigned int read_len) +{ + unsigned int idx; + int status = 0; + struct timer_list timer; + if (!hdw->ctl_lock_held) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Attempted to execute control transfer" + " without lock!!"); + return -EDEADLK; + } + if ((!hdw->flag_ok) && !probe_fl) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Attempted to execute control transfer" + " when device not ok"); + return -EIO; + } + if (!(hdw->ctl_read_urb && hdw->ctl_write_urb)) { + if (!probe_fl) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Attempted to execute control transfer" + " when USB is disconnected"); + } + return -ENOTTY; + } + + /* Ensure that we have sane parameters */ + if (!write_data) write_len = 0; + if (!read_data) read_len = 0; + if (write_len > PVR2_CTL_BUFFSIZE) { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "Attempted to execute %d byte" + " control-write transfer (limit=%d)", + write_len,PVR2_CTL_BUFFSIZE); + return -EINVAL; + } + if (read_len > PVR2_CTL_BUFFSIZE) { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "Attempted to execute %d byte" + " control-read transfer (limit=%d)", + write_len,PVR2_CTL_BUFFSIZE); + return -EINVAL; + } + if ((!write_len) && (!read_len)) { + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "Attempted to execute null control transfer?"); + return -EINVAL; + } + + + hdw->cmd_debug_state = 1; + if (write_len) { + hdw->cmd_debug_code = ((unsigned char *)write_data)[0]; + } else { + hdw->cmd_debug_code = 0; + } + hdw->cmd_debug_write_len = write_len; + hdw->cmd_debug_read_len = read_len; + + /* Initialize common stuff */ + init_completion(&hdw->ctl_done); + hdw->ctl_timeout_flag = 0; + hdw->ctl_write_pend_flag = 0; + hdw->ctl_read_pend_flag = 0; + init_timer(&timer); + timer.expires = jiffies + timeout; + timer.data = (unsigned long)hdw; + timer.function = pvr2_ctl_timeout; + + if (write_len) { + hdw->cmd_debug_state = 2; + /* Transfer write data to internal buffer */ + for (idx = 0; idx < write_len; idx++) { + hdw->ctl_write_buffer[idx] = + ((unsigned char *)write_data)[idx]; + } + /* Initiate a write request */ + usb_fill_bulk_urb(hdw->ctl_write_urb, + hdw->usb_dev, + usb_sndbulkpipe(hdw->usb_dev, + PVR2_CTL_WRITE_ENDPOINT), + hdw->ctl_write_buffer, + write_len, + pvr2_ctl_write_complete, + hdw); + hdw->ctl_write_urb->actual_length = 0; + hdw->ctl_write_pend_flag = !0; + status = usb_submit_urb(hdw->ctl_write_urb,GFP_KERNEL); + if (status < 0) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Failed to submit write-control" + " URB status=%d",status); + hdw->ctl_write_pend_flag = 0; + goto done; + } + } + + if (read_len) { + hdw->cmd_debug_state = 3; + memset(hdw->ctl_read_buffer,0x43,read_len); + /* Initiate a read request */ + usb_fill_bulk_urb(hdw->ctl_read_urb, + hdw->usb_dev, + usb_rcvbulkpipe(hdw->usb_dev, + PVR2_CTL_READ_ENDPOINT), + hdw->ctl_read_buffer, + read_len, + pvr2_ctl_read_complete, + hdw); + hdw->ctl_read_urb->actual_length = 0; + hdw->ctl_read_pend_flag = !0; + status = usb_submit_urb(hdw->ctl_read_urb,GFP_KERNEL); + if (status < 0) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Failed to submit read-control" + " URB status=%d",status); + hdw->ctl_read_pend_flag = 0; + goto done; + } + } + + /* Start timer */ + add_timer(&timer); + + /* Now wait for all I/O to complete */ + hdw->cmd_debug_state = 4; + while (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) { + wait_for_completion(&hdw->ctl_done); + } + hdw->cmd_debug_state = 5; + + /* Stop timer */ + del_timer_sync(&timer); + + hdw->cmd_debug_state = 6; + status = 0; + + if (hdw->ctl_timeout_flag) { + status = -ETIMEDOUT; + if (!probe_fl) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Timed out control-write"); + } + goto done; + } + + if (write_len) { + /* Validate results of write request */ + if ((hdw->ctl_write_urb->status != 0) && + (hdw->ctl_write_urb->status != -ENOENT) && + (hdw->ctl_write_urb->status != -ESHUTDOWN) && + (hdw->ctl_write_urb->status != -ECONNRESET)) { + /* USB subsystem is reporting some kind of failure + on the write */ + status = hdw->ctl_write_urb->status; + if (!probe_fl) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "control-write URB failure," + " status=%d", + status); + } + goto done; + } + if (hdw->ctl_write_urb->actual_length < write_len) { + /* Failed to write enough data */ + status = -EIO; + if (!probe_fl) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "control-write URB short," + " expected=%d got=%d", + write_len, + hdw->ctl_write_urb->actual_length); + } + goto done; + } + } + if (read_len) { + /* Validate results of read request */ + if ((hdw->ctl_read_urb->status != 0) && + (hdw->ctl_read_urb->status != -ENOENT) && + (hdw->ctl_read_urb->status != -ESHUTDOWN) && + (hdw->ctl_read_urb->status != -ECONNRESET)) { + /* USB subsystem is reporting some kind of failure + on the read */ + status = hdw->ctl_read_urb->status; + if (!probe_fl) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "control-read URB failure," + " status=%d", + status); + } + goto done; + } + if (hdw->ctl_read_urb->actual_length < read_len) { + /* Failed to read enough data */ + status = -EIO; + if (!probe_fl) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "control-read URB short," + " expected=%d got=%d", + read_len, + hdw->ctl_read_urb->actual_length); + } + goto done; + } + /* Transfer retrieved data out from internal buffer */ + for (idx = 0; idx < read_len; idx++) { + ((unsigned char *)read_data)[idx] = + hdw->ctl_read_buffer[idx]; + } + } + + done: + + hdw->cmd_debug_state = 0; + if ((status < 0) && (!probe_fl)) { + pvr2_hdw_render_useless_unlocked(hdw); + } + return status; +} + + +int pvr2_send_request(struct pvr2_hdw *hdw, + void *write_data,unsigned int write_len, + void *read_data,unsigned int read_len) +{ + return pvr2_send_request_ex(hdw,HZ*4,0, + write_data,write_len, + read_data,read_len); +} + +int pvr2_write_register(struct pvr2_hdw *hdw, u16 reg, u32 data) +{ + int ret; + + LOCK_TAKE(hdw->ctl_lock); + + hdw->cmd_buffer[0] = 0x04; /* write register prefix */ + PVR2_DECOMPOSE_LE(hdw->cmd_buffer,1,data); + hdw->cmd_buffer[5] = 0; + hdw->cmd_buffer[6] = (reg >> 8) & 0xff; + hdw->cmd_buffer[7] = reg & 0xff; + + + ret = pvr2_send_request(hdw, hdw->cmd_buffer, 8, hdw->cmd_buffer, 0); + + LOCK_GIVE(hdw->ctl_lock); + + return ret; +} + + +static int pvr2_read_register(struct pvr2_hdw *hdw, u16 reg, u32 *data) +{ + int ret = 0; + + LOCK_TAKE(hdw->ctl_lock); + + hdw->cmd_buffer[0] = 0x05; /* read register prefix */ + hdw->cmd_buffer[1] = 0; + hdw->cmd_buffer[2] = 0; + hdw->cmd_buffer[3] = 0; + hdw->cmd_buffer[4] = 0; + hdw->cmd_buffer[5] = 0; + hdw->cmd_buffer[6] = (reg >> 8) & 0xff; + hdw->cmd_buffer[7] = reg & 0xff; + + ret |= pvr2_send_request(hdw, hdw->cmd_buffer, 8, hdw->cmd_buffer, 4); + *data = PVR2_COMPOSE_LE(hdw->cmd_buffer,0); + + LOCK_GIVE(hdw->ctl_lock); + + return ret; +} + + +static int pvr2_write_u16(struct pvr2_hdw *hdw, u16 data, int res) +{ + int ret; + + LOCK_TAKE(hdw->ctl_lock); + + hdw->cmd_buffer[0] = (data >> 8) & 0xff; + hdw->cmd_buffer[1] = data & 0xff; + + ret = pvr2_send_request(hdw, hdw->cmd_buffer, 2, hdw->cmd_buffer, res); + + LOCK_GIVE(hdw->ctl_lock); + + return ret; +} + + +static int pvr2_write_u8(struct pvr2_hdw *hdw, u8 data, int res) +{ + int ret; + + LOCK_TAKE(hdw->ctl_lock); + + hdw->cmd_buffer[0] = data; + + ret = pvr2_send_request(hdw, hdw->cmd_buffer, 1, hdw->cmd_buffer, res); + + LOCK_GIVE(hdw->ctl_lock); + + return ret; +} + + +static void pvr2_hdw_render_useless_unlocked(struct pvr2_hdw *hdw) +{ + if (!hdw->flag_ok) return; + pvr2_trace(PVR2_TRACE_INIT,"render_useless"); + hdw->flag_ok = 0; + if (hdw->vid_stream) { + pvr2_stream_setup(hdw->vid_stream,NULL,0,0); + } + hdw->flag_streaming_enabled = 0; + hdw->subsys_enabled_mask = 0; +} + + +void pvr2_hdw_render_useless(struct pvr2_hdw *hdw) +{ + LOCK_TAKE(hdw->ctl_lock); + pvr2_hdw_render_useless_unlocked(hdw); + LOCK_GIVE(hdw->ctl_lock); +} + + +void pvr2_hdw_device_reset(struct pvr2_hdw *hdw) +{ + int ret; + pvr2_trace(PVR2_TRACE_INIT,"Performing a device reset..."); + ret = usb_lock_device_for_reset(hdw->usb_dev,NULL); + if (ret == 1) { + ret = usb_reset_device(hdw->usb_dev); + usb_unlock_device(hdw->usb_dev); + } else { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Failed to lock USB device ret=%d",ret); + } + if (init_pause_msec) { + pvr2_trace(PVR2_TRACE_INFO, + "Waiting %u msec for hardware to settle", + init_pause_msec); + msleep(init_pause_msec); + } + +} + + +void pvr2_hdw_cpureset_assert(struct pvr2_hdw *hdw,int val) +{ + char da[1]; + unsigned int pipe; + int ret; + + if (!hdw->usb_dev) return; + + pvr2_trace(PVR2_TRACE_INIT,"cpureset_assert(%d)",val); + + da[0] = val ? 0x01 : 0x00; + + /* Write the CPUCS register on the 8051. The lsb of the register + is the reset bit; a 1 asserts reset while a 0 clears it. */ + pipe = usb_sndctrlpipe(hdw->usb_dev, 0); + ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0x40,0xe600,0,da,1,HZ); + if (ret < 0) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "cpureset_assert(%d) error=%d",val,ret); + pvr2_hdw_render_useless(hdw); + } +} + + +int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *hdw) +{ + int status; + LOCK_TAKE(hdw->ctl_lock); do { + pvr2_trace(PVR2_TRACE_INIT,"Requesting uproc hard reset"); + hdw->flag_ok = !0; + hdw->cmd_buffer[0] = 0xdd; + status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0); + } while (0); LOCK_GIVE(hdw->ctl_lock); + return status; +} + + +int pvr2_hdw_cmd_powerup(struct pvr2_hdw *hdw) +{ + int status; + LOCK_TAKE(hdw->ctl_lock); do { + pvr2_trace(PVR2_TRACE_INIT,"Requesting powerup"); + hdw->cmd_buffer[0] = 0xde; + status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0); + } while (0); LOCK_GIVE(hdw->ctl_lock); + return status; +} + + +int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *hdw) +{ + if (!hdw->decoder_ctrl) { + pvr2_trace(PVR2_TRACE_INIT, + "Unable to reset decoder: nothing attached"); + return -ENOTTY; + } + + if (!hdw->decoder_ctrl->force_reset) { + pvr2_trace(PVR2_TRACE_INIT, + "Unable to reset decoder: not implemented"); + return -ENOTTY; + } + + pvr2_trace(PVR2_TRACE_INIT, + "Requesting decoder reset"); + hdw->decoder_ctrl->force_reset(hdw->decoder_ctrl->ctxt); + return 0; +} + + +/* Stop / start video stream transport */ +static int pvr2_hdw_cmd_usbstream(struct pvr2_hdw *hdw,int runFl) +{ + int status; + LOCK_TAKE(hdw->ctl_lock); do { + hdw->cmd_buffer[0] = (runFl ? 0x36 : 0x37); + status = pvr2_send_request(hdw,hdw->cmd_buffer,1,NULL,0); + } while (0); LOCK_GIVE(hdw->ctl_lock); + if (!status) { + hdw->subsys_enabled_mask = + ((hdw->subsys_enabled_mask & + ~(1<<PVR2_SUBSYS_B_USBSTREAM_RUN)) | + (runFl ? (1<<PVR2_SUBSYS_B_USBSTREAM_RUN) : 0)); + } + return status; +} + + +void pvr2_hdw_get_debug_info(const struct pvr2_hdw *hdw, + struct pvr2_hdw_debug_info *ptr) +{ + ptr->big_lock_held = hdw->big_lock_held; + ptr->ctl_lock_held = hdw->ctl_lock_held; + ptr->flag_ok = hdw->flag_ok; + ptr->flag_disconnected = hdw->flag_disconnected; + ptr->flag_init_ok = hdw->flag_init_ok; + ptr->flag_streaming_enabled = hdw->flag_streaming_enabled; + ptr->subsys_flags = hdw->subsys_enabled_mask; + ptr->cmd_debug_state = hdw->cmd_debug_state; + ptr->cmd_code = hdw->cmd_debug_code; + ptr->cmd_debug_write_len = hdw->cmd_debug_write_len; + ptr->cmd_debug_read_len = hdw->cmd_debug_read_len; + ptr->cmd_debug_timeout = hdw->ctl_timeout_flag; + ptr->cmd_debug_write_pend = hdw->ctl_write_pend_flag; + ptr->cmd_debug_read_pend = hdw->ctl_read_pend_flag; + ptr->cmd_debug_rstatus = hdw->ctl_read_urb->status; + ptr->cmd_debug_wstatus = hdw->ctl_read_urb->status; +} + + +int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *dp) +{ + return pvr2_read_register(hdw,PVR2_GPIO_DIR,dp); +} + + +int pvr2_hdw_gpio_get_out(struct pvr2_hdw *hdw,u32 *dp) +{ + return pvr2_read_register(hdw,PVR2_GPIO_OUT,dp); +} + + +int pvr2_hdw_gpio_get_in(struct pvr2_hdw *hdw,u32 *dp) +{ + return pvr2_read_register(hdw,PVR2_GPIO_IN,dp); +} + + +int pvr2_hdw_gpio_chg_dir(struct pvr2_hdw *hdw,u32 msk,u32 val) +{ + u32 cval,nval; + int ret; + if (~msk) { + ret = pvr2_read_register(hdw,PVR2_GPIO_DIR,&cval); + if (ret) return ret; + nval = (cval & ~msk) | (val & msk); + pvr2_trace(PVR2_TRACE_GPIO, + "GPIO direction changing 0x%x:0x%x" + " from 0x%x to 0x%x", + msk,val,cval,nval); + } else { + nval = val; + pvr2_trace(PVR2_TRACE_GPIO, + "GPIO direction changing to 0x%x",nval); + } + return pvr2_write_register(hdw,PVR2_GPIO_DIR,nval); +} + + +int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val) +{ + u32 cval,nval; + int ret; + if (~msk) { + ret = pvr2_read_register(hdw,PVR2_GPIO_OUT,&cval); + if (ret) return ret; + nval = (cval & ~msk) | (val & msk); + pvr2_trace(PVR2_TRACE_GPIO, + "GPIO output changing 0x%x:0x%x from 0x%x to 0x%x", + msk,val,cval,nval); + } else { + nval = val; + pvr2_trace(PVR2_TRACE_GPIO, + "GPIO output changing to 0x%x",nval); + } + return pvr2_write_register(hdw,PVR2_GPIO_OUT,nval); +} + + +/* Find I2C address of eeprom */ +static int pvr2_hdw_get_eeprom_addr(struct pvr2_hdw *hdw) +{ + int result; + LOCK_TAKE(hdw->ctl_lock); do { + hdw->cmd_buffer[0] = 0xeb; + result = pvr2_send_request(hdw, + hdw->cmd_buffer,1, + hdw->cmd_buffer,1); + if (result < 0) break; + result = hdw->cmd_buffer[0]; + } while(0); LOCK_GIVE(hdw->ctl_lock); + return result; +} + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.h b/drivers/media/video/pvrusb2/pvrusb2-hdw.h new file mode 100644 index 000000000..fd931b5da --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.h @@ -0,0 +1,303 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __PVRUSB2_HDW_H +#define __PVRUSB2_HDW_H + +#include <linux/usb.h> +#include <linux/videodev2.h> +#include "pvrusb2-io.h" +#include "pvrusb2-ctrl.h" + + +/* Private internal control ids, look these up with + pvr2_hdw_get_ctrl_by_id() - these are NOT visible in V4L */ +#define PVR2_CID_STDENUM 1 +#define PVR2_CID_STDCUR 2 +#define PVR2_CID_STDAVAIL 3 +#define PVR2_CID_INPUT 4 +#define PVR2_CID_AUDIOMODE 5 +#define PVR2_CID_FREQUENCY 6 +#define PVR2_CID_HRES 7 +#define PVR2_CID_VRES 8 + +/* Legal values for the INPUT state variable */ +#define PVR2_CVAL_INPUT_TV 0 +#define PVR2_CVAL_INPUT_SVIDEO 1 +#define PVR2_CVAL_INPUT_COMPOSITE 2 +#define PVR2_CVAL_INPUT_RADIO 3 + +/* Values that pvr2_hdw_get_signal_status() returns */ +#define PVR2_SIGNAL_OK 0x0001 +#define PVR2_SIGNAL_STEREO 0x0002 +#define PVR2_SIGNAL_SAP 0x0004 + + +/* Subsystem definitions - these are various pieces that can be + independently stopped / started. Usually you don't want to mess with + this directly (let the driver handle things itself), but it is useful + for debugging. */ +#define PVR2_SUBSYS_B_ENC_FIRMWARE 0 +#define PVR2_SUBSYS_B_ENC_CFG 1 +#define PVR2_SUBSYS_B_DIGITIZER_RUN 2 +#define PVR2_SUBSYS_B_USBSTREAM_RUN 3 +#define PVR2_SUBSYS_B_ENC_RUN 4 + +#define PVR2_SUBSYS_CFG_ALL ( \ + (1 << PVR2_SUBSYS_B_ENC_FIRMWARE) | \ + (1 << PVR2_SUBSYS_B_ENC_CFG) ) +#define PVR2_SUBSYS_RUN_ALL ( \ + (1 << PVR2_SUBSYS_B_DIGITIZER_RUN) | \ + (1 << PVR2_SUBSYS_B_USBSTREAM_RUN) | \ + (1 << PVR2_SUBSYS_B_ENC_RUN) ) +#define PVR2_SUBSYS_ALL ( \ + PVR2_SUBSYS_CFG_ALL | \ + PVR2_SUBSYS_RUN_ALL ) + +enum pvr2_config { + pvr2_config_empty, + pvr2_config_mpeg, + pvr2_config_vbi, + pvr2_config_radio, +}; + +const char *pvr2_config_get_name(enum pvr2_config); + +struct pvr2_hdw; + +/* Create and return a structure for interacting with the underlying + hardware */ +struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, + const struct usb_device_id *devid); + +/* Poll for background activity (if any) */ +void pvr2_hdw_poll(struct pvr2_hdw *); + +/* Trigger a poll to take place later at a convenient time */ +void pvr2_hdw_poll_trigger_unlocked(struct pvr2_hdw *); + +/* Register a callback used to trigger a future poll */ +void pvr2_hdw_setup_poll_trigger(struct pvr2_hdw *, + void (*func)(void *), + void *data); + +/* Destroy hardware interaction structure */ +void pvr2_hdw_destroy(struct pvr2_hdw *); + +/* Set up the structure and attempt to put the device into a usable state. + This can be a time-consuming operation, which is why it is not done + internally as part of the create() step. Return value is exactly the + same as pvr2_hdw_init_ok(). */ +int pvr2_hdw_setup(struct pvr2_hdw *); + +/* Initialization succeeded */ +int pvr2_hdw_init_ok(struct pvr2_hdw *); + +/* Return true if in the ready (normal) state */ +int pvr2_hdw_dev_ok(struct pvr2_hdw *); + +/* Return small integer number [1..N] for logical instance number of this + device. This is useful for indexing array-valued module parameters. */ +int pvr2_hdw_get_unit_number(struct pvr2_hdw *); + +/* Get pointer to underlying USB device */ +struct usb_device *pvr2_hdw_get_dev(struct pvr2_hdw *); + +/* Retrieve serial number of device */ +unsigned long pvr2_hdw_get_sn(struct pvr2_hdw *); + +/* Called when hardware has been unplugged */ +void pvr2_hdw_disconnect(struct pvr2_hdw *); + +/* Get the number of defined controls */ +unsigned int pvr2_hdw_get_ctrl_count(struct pvr2_hdw *); + +/* Retrieve a control handle given its index (0..count-1) */ +struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_index(struct pvr2_hdw *,unsigned int); + +/* Retrieve a control handle given its internal ID (if any) */ +struct pvr2_ctrl *pvr2_hdw_get_ctrl_by_id(struct pvr2_hdw *,unsigned int); + +/* Retrieve a control handle given its V4L ID (if any) */ +struct pvr2_ctrl *pvr2_hdw_get_ctrl_v4l(struct pvr2_hdw *,unsigned int ctl_id); + +/* Retrieve a control handle given its immediate predecessor V4L ID (if any) */ +struct pvr2_ctrl *pvr2_hdw_get_ctrl_nextv4l(struct pvr2_hdw *, + unsigned int ctl_id); + +/* Commit all control changes made up to this point */ +int pvr2_hdw_commit_ctl(struct pvr2_hdw *); + +/* Return name for this driver instance */ +const char *pvr2_hdw_get_driver_name(struct pvr2_hdw *); + +/* Return PVR2_SIGNAL_XXXX bit mask indicating signal status */ +unsigned int pvr2_hdw_get_signal_status(struct pvr2_hdw *); + +/* Query device and see if it thinks it is on a high-speed USB link */ +int pvr2_hdw_is_hsm(struct pvr2_hdw *); + +/* Turn streaming on/off */ +int pvr2_hdw_set_streaming(struct pvr2_hdw *,int); + +/* Find out if streaming is on */ +int pvr2_hdw_get_streaming(struct pvr2_hdw *); + +/* Configure the type of stream to generate */ +int pvr2_hdw_set_stream_type(struct pvr2_hdw *, enum pvr2_config); + +/* Get handle to video output stream */ +struct pvr2_stream *pvr2_hdw_get_video_stream(struct pvr2_hdw *); + +/* Emit a video standard struct */ +int pvr2_hdw_get_stdenum_value(struct pvr2_hdw *hdw,struct v4l2_standard *std, + unsigned int idx); + +/* Enable / disable various pieces of hardware. Items to change are + identified by bit positions within msk, and new state for each item is + identified by corresponding bit positions within val. */ +void pvr2_hdw_subsys_bit_chg(struct pvr2_hdw *hdw, + unsigned long msk,unsigned long val); + +/* Retrieve mask indicating which pieces of hardware are currently enabled + / configured. */ +unsigned long pvr2_hdw_subsys_get(struct pvr2_hdw *); + +/* Adjust mask of what get shut down when streaming is stopped. This is a + debugging aid. */ +void pvr2_hdw_subsys_stream_bit_chg(struct pvr2_hdw *hdw, + unsigned long msk,unsigned long val); + +/* Retrieve mask indicating which pieces of hardware are disabled when + streaming is turned off. */ +unsigned long pvr2_hdw_subsys_stream_get(struct pvr2_hdw *); + + +/* Enable / disable retrieval of CPU firmware. This must be enabled before + pvr2_hdw_cpufw_get() will function. Note that doing this may prevent + the device from running (and leaving this mode may imply a device + reset). */ +void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *, int enable_flag); + +/* Return true if we're in a mode for retrieval CPU firmware */ +int pvr2_hdw_cpufw_get_enabled(struct pvr2_hdw *); + +/* Retrieve a piece of the CPU's firmware at the given offset. Return + value is the number of bytes retrieved or zero if we're past the end or + an error otherwise (e.g. if firmware retrieval is not enabled). */ +int pvr2_hdw_cpufw_get(struct pvr2_hdw *,unsigned int offs, + char *buf,unsigned int cnt); + +/* Retrieve previously stored v4l minor device number */ +int pvr2_hdw_v4l_get_minor_number(struct pvr2_hdw *); + +/* Store the v4l minor device number */ +void pvr2_hdw_v4l_store_minor_number(struct pvr2_hdw *,int); + + +/* The following entry points are all lower level things you normally don't + want to worry about. */ + +/* Issue a command and get a response from the device. LOTS of higher + level stuff is built on this. */ +int pvr2_send_request(struct pvr2_hdw *, + void *write_ptr,unsigned int write_len, + void *read_ptr,unsigned int read_len); + +/* Slightly higher level device communication functions. */ +int pvr2_write_register(struct pvr2_hdw *, u16, u32); + +/* Call if for any reason we can't talk to the hardware anymore - this will + cause the driver to stop flailing on the device. */ +void pvr2_hdw_render_useless(struct pvr2_hdw *); + +/* Set / clear 8051's reset bit */ +void pvr2_hdw_cpureset_assert(struct pvr2_hdw *,int); + +/* Execute a USB-commanded device reset */ +void pvr2_hdw_device_reset(struct pvr2_hdw *); + +/* Execute hard reset command (after this point it's likely that the + encoder will have to be reconfigured). This also clears the "useless" + state. */ +int pvr2_hdw_cmd_deep_reset(struct pvr2_hdw *); + +/* Execute simple reset command */ +int pvr2_hdw_cmd_powerup(struct pvr2_hdw *); + +/* Order decoder to reset */ +int pvr2_hdw_cmd_decoder_reset(struct pvr2_hdw *); + +/* Direct manipulation of GPIO bits */ +int pvr2_hdw_gpio_get_dir(struct pvr2_hdw *hdw,u32 *); +int pvr2_hdw_gpio_get_out(struct pvr2_hdw *hdw,u32 *); +int pvr2_hdw_gpio_get_in(struct pvr2_hdw *hdw,u32 *); +int pvr2_hdw_gpio_chg_dir(struct pvr2_hdw *hdw,u32 msk,u32 val); +int pvr2_hdw_gpio_chg_out(struct pvr2_hdw *hdw,u32 msk,u32 val); + +/* This data structure is specifically for the next function... */ +struct pvr2_hdw_debug_info { + int big_lock_held; + int ctl_lock_held; + int flag_ok; + int flag_disconnected; + int flag_init_ok; + int flag_streaming_enabled; + unsigned long subsys_flags; + int cmd_debug_state; + int cmd_debug_write_len; + int cmd_debug_read_len; + int cmd_debug_write_pend; + int cmd_debug_read_pend; + int cmd_debug_timeout; + int cmd_debug_rstatus; + int cmd_debug_wstatus; + unsigned char cmd_code; +}; + +/* Non-intrusively retrieve internal state info - this is useful for + diagnosing lockups. Note that this operation is completed without any + kind of locking and so it is not atomic and may yield inconsistent + results. This is *purely* a debugging aid. */ +void pvr2_hdw_get_debug_info(const struct pvr2_hdw *hdw, + struct pvr2_hdw_debug_info *); + +/* Cause modules to log their state once */ +void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw); + +/* Cause encoder firmware to be uploaded into the device. This is normally + done autonomously, but the interface is exported here because it is also + a debugging aid. */ +int pvr2_upload_firmware2(struct pvr2_hdw *hdw); + +/* List of device types that we can match */ +extern struct usb_device_id pvr2_device_table[]; + +#endif /* __PVRUSB2_HDW_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c new file mode 100644 index 000000000..fbe6039ae --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-chips-v4l2.c @@ -0,0 +1,109 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "pvrusb2-i2c-core.h" +#include "pvrusb2-hdw-internal.h" +#include "pvrusb2-debug.h" +#include "pvrusb2-i2c-cmd-v4l2.h" +#include "pvrusb2-audio.h" +#include "pvrusb2-tuner.h" +#include "pvrusb2-video-v4l.h" +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX +#include "pvrusb2-cx2584x-v4l.h" +#include "pvrusb2-wm8775.h" +#endif + +#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) + +#define OP_STANDARD 0 +#define OP_BCSH 1 +#define OP_VOLUME 2 +#define OP_FREQ 3 +#define OP_AUDIORATE 4 +#define OP_SIZE 5 +#define OP_LOG 6 + +static const struct pvr2_i2c_op * const ops[] = { + [OP_STANDARD] = &pvr2_i2c_op_v4l2_standard, + [OP_BCSH] = &pvr2_i2c_op_v4l2_bcsh, + [OP_VOLUME] = &pvr2_i2c_op_v4l2_volume, + [OP_FREQ] = &pvr2_i2c_op_v4l2_frequency, + [OP_SIZE] = &pvr2_i2c_op_v4l2_size, + [OP_LOG] = &pvr2_i2c_op_v4l2_log, +}; + +void pvr2_i2c_probe(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) +{ + int id; + id = cp->client->driver->id; + cp->ctl_mask = ((1 << OP_STANDARD) | + (1 << OP_BCSH) | + (1 << OP_VOLUME) | + (1 << OP_FREQ) | + (1 << OP_SIZE) | + (1 << OP_LOG)); + + if (id == I2C_DRIVERID_MSP3400) { + if (pvr2_i2c_msp3400_setup(hdw,cp)) { + return; + } + } + if (id == I2C_DRIVERID_TUNER) { + if (pvr2_i2c_tuner_setup(hdw,cp)) { + return; + } + } +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX + if (id == I2C_DRIVERID_CX25840) { + if (pvr2_i2c_cx2584x_v4l_setup(hdw,cp)) { + return; + } + } + if (id == I2C_DRIVERID_WM8775) { + if (pvr2_i2c_wm8775_setup(hdw,cp)) { + return; + } + } +#endif + if (id == I2C_DRIVERID_SAA711X) { + if (pvr2_i2c_decoder_v4l_setup(hdw,cp)) { + return; + } + } +} + + +const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx) +{ + if (idx >= sizeof(ops)/sizeof(ops[0])) return 0; + return ops[idx]; +} + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c new file mode 100644 index 000000000..8a9933dec --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.c @@ -0,0 +1,232 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "pvrusb2-i2c-cmd-v4l2.h" +#include "pvrusb2-hdw-internal.h" +#include "pvrusb2-debug.h" +#include <linux/videodev2.h> + + +static void set_standard(struct pvr2_hdw *hdw) +{ + v4l2_std_id vs; + vs = hdw->std_mask_cur; + pvr2_trace(PVR2_TRACE_CHIPS, + "i2c v4l2 set_standard(0x%llx)",(__u64)vs); + + pvr2_i2c_core_cmd(hdw,VIDIOC_S_STD,&vs); +} + + +static int check_standard(struct pvr2_hdw *hdw) +{ + return hdw->std_dirty != 0; +} + + +const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard = { + .check = check_standard, + .update = set_standard, + .name = "v4l2_standard", +}; + + +static void set_bcsh(struct pvr2_hdw *hdw) +{ + struct v4l2_control ctrl; + pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_bcsh" + " b=%d c=%d s=%d h=%d", + hdw->brightness_val,hdw->contrast_val, + hdw->saturation_val,hdw->hue_val); + memset(&ctrl,0,sizeof(ctrl)); + ctrl.id = V4L2_CID_BRIGHTNESS; + ctrl.value = hdw->brightness_val; + pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); + ctrl.id = V4L2_CID_CONTRAST; + ctrl.value = hdw->contrast_val; + pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); + ctrl.id = V4L2_CID_SATURATION; + ctrl.value = hdw->saturation_val; + pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); + ctrl.id = V4L2_CID_HUE; + ctrl.value = hdw->hue_val; + pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); +} + + +static int check_bcsh(struct pvr2_hdw *hdw) +{ + return (hdw->brightness_dirty || + hdw->contrast_dirty || + hdw->saturation_dirty || + hdw->hue_dirty); +} + + +const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh = { + .check = check_bcsh, + .update = set_bcsh, + .name = "v4l2_bcsh", +}; + + +static void set_volume(struct pvr2_hdw *hdw) +{ + struct v4l2_control ctrl; + pvr2_trace(PVR2_TRACE_CHIPS, + "i2c v4l2 set_volume" + "(vol=%d bal=%d bas=%d treb=%d mute=%d)", + hdw->volume_val, + hdw->balance_val, + hdw->bass_val, + hdw->treble_val, + hdw->mute_val); + memset(&ctrl,0,sizeof(ctrl)); + ctrl.id = V4L2_CID_AUDIO_MUTE; + ctrl.value = hdw->mute_val ? 1 : 0; + pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); + ctrl.id = V4L2_CID_AUDIO_VOLUME; + ctrl.value = hdw->volume_val; + pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); + ctrl.id = V4L2_CID_AUDIO_BALANCE; + ctrl.value = hdw->balance_val; + pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); + ctrl.id = V4L2_CID_AUDIO_BASS; + ctrl.value = hdw->bass_val; + pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); + ctrl.id = V4L2_CID_AUDIO_TREBLE; + ctrl.value = hdw->treble_val; + pvr2_i2c_core_cmd(hdw,VIDIOC_S_CTRL,&ctrl); +} + + +static int check_volume(struct pvr2_hdw *hdw) +{ + return (hdw->volume_dirty || + hdw->balance_dirty || + hdw->bass_dirty || + hdw->treble_dirty || + hdw->mute_dirty); +} + + +const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume = { + .check = check_volume, + .update = set_volume, + .name = "v4l2_volume", +}; + + +static void set_frequency(struct pvr2_hdw *hdw) +{ + unsigned long fv; + struct v4l2_frequency freq; + fv = hdw->freqVal; + pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_freq(%lu)",fv); + memset(&freq,0,sizeof(freq)); + freq.frequency = fv / 62500; + freq.tuner = 0; + freq.type = V4L2_TUNER_ANALOG_TV; + pvr2_i2c_core_cmd(hdw,VIDIOC_S_FREQUENCY,&freq); +} + + +static int check_frequency(struct pvr2_hdw *hdw) +{ + return hdw->freqDirty != 0; +} + + +const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency = { + .check = check_frequency, + .update = set_frequency, + .name = "v4l2_freq", +}; + + +static void set_size(struct pvr2_hdw *hdw) +{ + struct v4l2_format fmt; + + memset(&fmt,0,sizeof(fmt)); + + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + fmt.fmt.pix.width = hdw->res_hor_val; + fmt.fmt.pix.height = hdw->res_ver_val; + + pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_size(%dx%d)", + fmt.fmt.pix.width,fmt.fmt.pix.height); + + pvr2_i2c_core_cmd(hdw,VIDIOC_S_FMT,&fmt); +} + + +static int check_size(struct pvr2_hdw *hdw) +{ + return (hdw->res_hor_dirty || hdw->res_ver_dirty); +} + + +const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size = { + .check = check_size, + .update = set_size, + .name = "v4l2_size", +}; + + +static void do_log(struct pvr2_hdw *hdw) +{ + pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 do_log()"); + pvr2_i2c_core_cmd(hdw,VIDIOC_LOG_STATUS,NULL); + +} + + +static int check_log(struct pvr2_hdw *hdw) +{ + return hdw->log_requested != 0; +} + + +const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log = { + .check = check_log, + .update = do_log, + .name = "v4l2_log", +}; + + +void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *cp,int fl) +{ + pvr2_i2c_client_cmd(cp, + (fl ? VIDIOC_STREAMON : VIDIOC_STREAMOFF),NULL); +} + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h new file mode 100644 index 000000000..ecabddba1 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-cmd-v4l2.h @@ -0,0 +1,47 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __PVRUSB2_CMD_V4L2_H +#define __PVRUSB2_CMD_V4L2_H + +#include "pvrusb2-i2c-core.h" + +extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_standard; +extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_bcsh; +extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_volume; +extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_frequency; +extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_size; +extern const struct pvr2_i2c_op pvr2_i2c_op_v4l2_log; + +void pvr2_v4l2_cmd_stream(struct pvr2_i2c_client *,int); + +#endif /* __PVRUSB2_CMD_V4L2_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c new file mode 100644 index 000000000..7fca47982 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c @@ -0,0 +1,941 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "pvrusb2-i2c-core.h" +#include "pvrusb2-hdw-internal.h" +#include "pvrusb2-debug.h" + +#define trace_i2c(...) pvr2_trace(PVR2_TRACE_I2C,__VA_ARGS__) + +/* + + This module attempts to implement a compliant I2C adapter for the pvrusb2 + device. By doing this we can then make use of existing functionality in + V4L (e.g. tuner.c) rather than rolling our own. + +*/ + +static unsigned int i2c_scan = 0; +module_param(i2c_scan, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(i2c_scan,"scan i2c bus at insmod time"); + +static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, + unsigned int detail, + char *buf,unsigned int maxlen); + +static int pvr2_i2c_write(struct pvr2_hdw *hdw, /* Context */ + u8 i2c_addr, /* I2C address we're talking to */ + u8 *data, /* Data to write */ + u16 length) /* Size of data to write */ +{ + /* Return value - default 0 means success */ + int ret; + + + if (!data) length = 0; + if (length > (sizeof(hdw->cmd_buffer) - 3)) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Killing an I2C write to %u that is too large" + " (desired=%u limit=%u)", + i2c_addr, + length,(unsigned int)(sizeof(hdw->cmd_buffer) - 3)); + return -ENOTSUPP; + } + + LOCK_TAKE(hdw->ctl_lock); + + /* Clear the command buffer (likely to be paranoia) */ + memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer)); + + /* Set up command buffer for an I2C write */ + hdw->cmd_buffer[0] = 0x08; /* write prefix */ + hdw->cmd_buffer[1] = i2c_addr; /* i2c addr of chip */ + hdw->cmd_buffer[2] = length; /* length of what follows */ + if (length) memcpy(hdw->cmd_buffer + 3, data, length); + + /* Do the operation */ + ret = pvr2_send_request(hdw, + hdw->cmd_buffer, + length + 3, + hdw->cmd_buffer, + 1); + if (!ret) { + if (hdw->cmd_buffer[0] != 8) { + ret = -EIO; + if (hdw->cmd_buffer[0] != 7) { + trace_i2c("unexpected status" + " from i2_write[%d]: %d", + i2c_addr,hdw->cmd_buffer[0]); + } + } + } + + LOCK_GIVE(hdw->ctl_lock); + + return ret; +} + +static int pvr2_i2c_read(struct pvr2_hdw *hdw, /* Context */ + u8 i2c_addr, /* I2C address we're talking to */ + u8 *data, /* Data to write */ + u16 dlen, /* Size of data to write */ + u8 *res, /* Where to put data we read */ + u16 rlen) /* Amount of data to read */ +{ + /* Return value - default 0 means success */ + int ret; + + + if (!data) dlen = 0; + if (dlen > (sizeof(hdw->cmd_buffer) - 4)) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Killing an I2C read to %u that has wlen too large" + " (desired=%u limit=%u)", + i2c_addr, + dlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 4)); + return -ENOTSUPP; + } + if (res && (rlen > (sizeof(hdw->cmd_buffer) - 1))) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Killing an I2C read to %u that has rlen too large" + " (desired=%u limit=%u)", + i2c_addr, + rlen,(unsigned int)(sizeof(hdw->cmd_buffer) - 1)); + return -ENOTSUPP; + } + + LOCK_TAKE(hdw->ctl_lock); + + /* Clear the command buffer (likely to be paranoia) */ + memset(hdw->cmd_buffer, 0, sizeof(hdw->cmd_buffer)); + + /* Set up command buffer for an I2C write followed by a read */ + hdw->cmd_buffer[0] = 0x09; /* read prefix */ + hdw->cmd_buffer[1] = dlen; /* arg length */ + hdw->cmd_buffer[2] = rlen; /* answer length. Device will send one + more byte (status). */ + hdw->cmd_buffer[3] = i2c_addr; /* i2c addr of chip */ + if (dlen) memcpy(hdw->cmd_buffer + 4, data, dlen); + + /* Do the operation */ + ret = pvr2_send_request(hdw, + hdw->cmd_buffer, + 4 + dlen, + hdw->cmd_buffer, + rlen + 1); + if (!ret) { + if (hdw->cmd_buffer[0] != 8) { + ret = -EIO; + if (hdw->cmd_buffer[0] != 7) { + trace_i2c("unexpected status" + " from i2_read[%d]: %d", + i2c_addr,hdw->cmd_buffer[0]); + } + } + } + + /* Copy back the result */ + if (res && rlen) { + if (ret) { + /* Error, just blank out the return buffer */ + memset(res, 0, rlen); + } else { + memcpy(res, hdw->cmd_buffer + 1, rlen); + } + } + + LOCK_GIVE(hdw->ctl_lock); + + return ret; +} + +/* This is the common low level entry point for doing I2C operations to the + hardware. */ +static int pvr2_i2c_basic_op(struct pvr2_hdw *hdw, + u8 i2c_addr, + u8 *wdata, + u16 wlen, + u8 *rdata, + u16 rlen) +{ + if (!rdata) rlen = 0; + if (!wdata) wlen = 0; + if (rlen || !wlen) { + return pvr2_i2c_read(hdw,i2c_addr,wdata,wlen,rdata,rlen); + } else { + return pvr2_i2c_write(hdw,i2c_addr,wdata,wlen); + } +} + +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX + +/* This is a special entry point that is entered if an I2C operation is + attempted to a wm8775 chip on model 24xxx hardware. Autodetect of this + part doesn't work, but we know it is really there. So let's look for + the autodetect attempt and just return success if we see that. */ +static int i2c_hack_wm8775(struct pvr2_hdw *hdw, + u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen) +{ + if (!(rlen || wlen)) { + // This is a probe attempt. Just let it succeed. + return 0; + } + return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen); +} + +/* This is a special entry point that is entered if an I2C operation is + attempted to a cx25840 chip on model 24xxx hardware. This chip can + sometimes wedge itself. Worse still, when this happens msp3400 can + falsely detect this part and then the system gets hosed up after msp3400 + gets confused and dies. What we want to do here is try to keep msp3400 + away and also try to notice if the chip is wedged and send a warning to + the system log. */ +static int i2c_hack_cx25840(struct pvr2_hdw *hdw, + u8 i2c_addr,u8 *wdata,u16 wlen,u8 *rdata,u16 rlen) +{ + int ret; + unsigned int subaddr; + u8 wbuf[2]; + int state = hdw->i2c_cx25840_hack_state; + + if (!(rlen || wlen)) { + // Probe attempt - always just succeed and don't bother the + // hardware (this helps to make the state machine further + // down somewhat easier). + return 0; + } + + if (state == 3) { + return pvr2_i2c_basic_op(hdw,i2c_addr,wdata,wlen,rdata,rlen); + } + + /* We're looking for the exact pattern where the revision register + is being read. The cx25840 module will always look at the + revision register first. Any other pattern of access therefore + has to be a probe attempt from somebody else so we'll reject it. + Normally we could just let each client just probe the part + anyway, but when the cx25840 is wedged, msp3400 will get a false + positive and that just screws things up... */ + + if (wlen == 0) { + switch (state) { + case 1: subaddr = 0x0100; break; + case 2: subaddr = 0x0101; break; + default: goto fail; + } + } else if (wlen == 2) { + subaddr = (wdata[0] << 8) | wdata[1]; + switch (subaddr) { + case 0x0100: state = 1; break; + case 0x0101: state = 2; break; + default: goto fail; + } + } else { + goto fail; + } + if (!rlen) goto success; + state = 0; + if (rlen != 1) goto fail; + + /* If we get to here then we have a legitimate read for one of the + two revision bytes, so pass it through. */ + wbuf[0] = subaddr >> 8; + wbuf[1] = subaddr; + ret = pvr2_i2c_basic_op(hdw,i2c_addr,wbuf,2,rdata,rlen); + + if ((ret != 0) || (*rdata == 0x04) || (*rdata == 0x0a)) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "WARNING: Detected a wedged cx25840 chip;" + " the device will not work."); + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "WARNING: Try power cycling the pvrusb2 device."); + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "WARNING: Disabling further access to the device" + " to prevent other foul-ups."); + // This blocks all further communication with the part. + hdw->i2c_func[0x44] = NULL; + pvr2_hdw_render_useless(hdw); + goto fail; + } + + /* Success! */ + pvr2_trace(PVR2_TRACE_CHIPS,"cx25840 appears to be OK."); + state = 3; + + success: + hdw->i2c_cx25840_hack_state = state; + return 0; + + fail: + hdw->i2c_cx25840_hack_state = state; + return -EIO; +} + +#endif /* CONFIG_VIDEO_PVRUSB2_24XXX */ + +/* This is a very, very limited I2C adapter implementation. We can only + support what we actually know will work on the device... */ +static int pvr2_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg msgs[], + int num) +{ + int ret = -ENOTSUPP; + pvr2_i2c_func funcp = NULL; + struct pvr2_hdw *hdw = (struct pvr2_hdw *)(i2c_adap->algo_data); + + if (!num) { + ret = -EINVAL; + goto done; + } + if ((msgs[0].flags & I2C_M_NOSTART)) { + trace_i2c("i2c refusing I2C_M_NOSTART"); + goto done; + } + if (msgs[0].addr < PVR2_I2C_FUNC_CNT) { + funcp = hdw->i2c_func[msgs[0].addr]; + } + if (!funcp) { + ret = -EIO; + goto done; + } + + if (num == 1) { + if (msgs[0].flags & I2C_M_RD) { + /* Simple read */ + u16 tcnt,bcnt,offs; + if (!msgs[0].len) { + /* Length == 0 read. This is a probe. */ + if (funcp(hdw,msgs[0].addr,NULL,0,NULL,0)) { + ret = -EIO; + goto done; + } + ret = 1; + goto done; + } + /* If the read is short enough we'll do the whole + thing atomically. Otherwise we have no choice + but to break apart the reads. */ + tcnt = msgs[0].len; + offs = 0; + while (tcnt) { + bcnt = tcnt; + if (bcnt > sizeof(hdw->cmd_buffer)-1) { + bcnt = sizeof(hdw->cmd_buffer)-1; + } + if (funcp(hdw,msgs[0].addr,NULL,0, + msgs[0].buf+offs,bcnt)) { + ret = -EIO; + goto done; + } + offs += bcnt; + tcnt -= bcnt; + } + ret = 1; + goto done; + } else { + /* Simple write */ + ret = 1; + if (funcp(hdw,msgs[0].addr, + msgs[0].buf,msgs[0].len,NULL,0)) { + ret = -EIO; + } + goto done; + } + } else if (num == 2) { + if (msgs[0].addr != msgs[1].addr) { + trace_i2c("i2c refusing 2 phase transfer with" + " conflicting target addresses"); + ret = -ENOTSUPP; + goto done; + } + if ((!((msgs[0].flags & I2C_M_RD))) && + (msgs[1].flags & I2C_M_RD)) { + u16 tcnt,bcnt,wcnt,offs; + /* Write followed by atomic read. If the read + portion is short enough we'll do the whole thing + atomically. Otherwise we have no choice but to + break apart the reads. */ + tcnt = msgs[1].len; + wcnt = msgs[0].len; + offs = 0; + while (tcnt || wcnt) { + bcnt = tcnt; + if (bcnt > sizeof(hdw->cmd_buffer)-1) { + bcnt = sizeof(hdw->cmd_buffer)-1; + } + if (funcp(hdw,msgs[0].addr, + msgs[0].buf,wcnt, + msgs[1].buf+offs,bcnt)) { + ret = -EIO; + goto done; + } + offs += bcnt; + tcnt -= bcnt; + wcnt = 0; + } + ret = 2; + goto done; + } else { + trace_i2c("i2c refusing complex transfer" + " read0=%d read1=%d", + (msgs[0].flags & I2C_M_RD), + (msgs[1].flags & I2C_M_RD)); + } + } else { + trace_i2c("i2c refusing %d phase transfer",num); + } + + done: + if (pvrusb2_debug & PVR2_TRACE_I2C_TRAF) { + unsigned int idx,offs,cnt; + for (idx = 0; idx < num; idx++) { + cnt = msgs[idx].len; + printk(KERN_INFO + "pvrusb2 i2c xfer %u/%u:" + " addr=0x%x len=%d %s%s", + idx+1,num, + msgs[idx].addr, + cnt, + (msgs[idx].flags & I2C_M_RD ? + "read" : "write"), + (msgs[idx].flags & I2C_M_NOSTART ? + " nostart" : "")); + if ((ret > 0) || !(msgs[idx].flags & I2C_M_RD)) { + if (cnt > 8) cnt = 8; + printk(" ["); + for (offs = 0; offs < (cnt>8?8:cnt); offs++) { + if (offs) printk(" "); + printk("%02x",msgs[idx].buf[offs]); + } + if (offs < cnt) printk(" ..."); + printk("]"); + } + if (idx+1 == num) { + printk(" result=%d",ret); + } + printk("\n"); + } + if (!num) { + printk(KERN_INFO + "pvrusb2 i2c xfer null transfer result=%d\n", + ret); + } + } + return ret; +} + +static int pvr2_i2c_control(struct i2c_adapter *adapter, + unsigned int cmd, unsigned long arg) +{ + return 0; +} + +static u32 pvr2_i2c_functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE_DATA; +} + +static int pvr2_i2c_core_singleton(struct i2c_client *cp, + unsigned int cmd,void *arg) +{ + int stat; + if (!cp) return -EINVAL; + if (!(cp->driver)) return -EINVAL; + if (!(cp->driver->command)) return -EINVAL; + if (!try_module_get(cp->driver->driver.owner)) return -EAGAIN; + stat = cp->driver->command(cp,cmd,arg); + module_put(cp->driver->driver.owner); + return stat; +} + +int pvr2_i2c_client_cmd(struct pvr2_i2c_client *cp,unsigned int cmd,void *arg) +{ + int stat; + if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) { + char buf[100]; + unsigned int cnt; + cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG, + buf,sizeof(buf)); + pvr2_trace(PVR2_TRACE_I2C_CMD, + "i2c COMMAND (code=%u 0x%x) to %.*s", + cmd,cmd,cnt,buf); + } + stat = pvr2_i2c_core_singleton(cp->client,cmd,arg); + if (pvrusb2_debug & PVR2_TRACE_I2C_CMD) { + char buf[100]; + unsigned int cnt; + cnt = pvr2_i2c_client_describe(cp,PVR2_I2C_DETAIL_DEBUG, + buf,sizeof(buf)); + pvr2_trace(PVR2_TRACE_I2C_CMD, + "i2c COMMAND to %.*s (ret=%d)",cnt,buf,stat); + } + return stat; +} + +int pvr2_i2c_core_cmd(struct pvr2_hdw *hdw,unsigned int cmd,void *arg) +{ + struct list_head *item,*nc; + struct pvr2_i2c_client *cp; + int stat = -EINVAL; + + if (!hdw) return stat; + + mutex_lock(&hdw->i2c_list_lock); + list_for_each_safe(item,nc,&hdw->i2c_clients) { + cp = list_entry(item,struct pvr2_i2c_client,list); + if (!cp->recv_enable) continue; + mutex_unlock(&hdw->i2c_list_lock); + stat = pvr2_i2c_client_cmd(cp,cmd,arg); + mutex_lock(&hdw->i2c_list_lock); + } + mutex_unlock(&hdw->i2c_list_lock); + return stat; +} + + +static int handler_check(struct pvr2_i2c_client *cp) +{ + struct pvr2_i2c_handler *hp = cp->handler; + if (!hp) return 0; + if (!hp->func_table->check) return 0; + return hp->func_table->check(hp->func_data) != 0; +} + +#define BUFSIZE 500 + +void pvr2_i2c_core_sync(struct pvr2_hdw *hdw) +{ + unsigned long msk; + unsigned int idx; + struct list_head *item,*nc; + struct pvr2_i2c_client *cp; + + if (!hdw->i2c_linked) return; + if (!(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL)) { + return; + } + mutex_lock(&hdw->i2c_list_lock); do { + pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync BEGIN"); + if (hdw->i2c_pend_types & PVR2_I2C_PEND_DETECT) { + /* One or more I2C clients have attached since we + last synced. So scan the list and identify the + new clients. */ + char *buf; + unsigned int cnt; + unsigned long amask = 0; + buf = kmalloc(BUFSIZE,GFP_KERNEL); + pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_DETECT"); + hdw->i2c_pend_types &= ~PVR2_I2C_PEND_DETECT; + list_for_each(item,&hdw->i2c_clients) { + cp = list_entry(item,struct pvr2_i2c_client, + list); + if (!cp->detected_flag) { + cp->ctl_mask = 0; + pvr2_i2c_probe(hdw,cp); + cp->detected_flag = !0; + msk = cp->ctl_mask; + cnt = 0; + if (buf) { + cnt = pvr2_i2c_client_describe( + cp, + PVR2_I2C_DETAIL_ALL, + buf,BUFSIZE); + } + trace_i2c("Probed: %.*s",cnt,buf); + if (handler_check(cp)) { + hdw->i2c_pend_types |= + PVR2_I2C_PEND_CLIENT; + } + cp->pend_mask = msk; + hdw->i2c_pend_mask |= msk; + hdw->i2c_pend_types |= + PVR2_I2C_PEND_REFRESH; + } + amask |= cp->ctl_mask; + } + hdw->i2c_active_mask = amask; + if (buf) kfree(buf); + } + if (hdw->i2c_pend_types & PVR2_I2C_PEND_STALE) { + /* Need to do one or more global updates. Arrange + for this to happen. */ + unsigned long m2; + pvr2_trace(PVR2_TRACE_I2C_CORE, + "i2c: PEND_STALE (0x%lx)", + hdw->i2c_stale_mask); + hdw->i2c_pend_types &= ~PVR2_I2C_PEND_STALE; + list_for_each(item,&hdw->i2c_clients) { + cp = list_entry(item,struct pvr2_i2c_client, + list); + m2 = hdw->i2c_stale_mask; + m2 &= cp->ctl_mask; + m2 &= ~cp->pend_mask; + if (m2) { + pvr2_trace(PVR2_TRACE_I2C_CORE, + "i2c: cp=%p setting 0x%lx", + cp,m2); + cp->pend_mask |= m2; + } + } + hdw->i2c_pend_mask |= hdw->i2c_stale_mask; + hdw->i2c_stale_mask = 0; + hdw->i2c_pend_types |= PVR2_I2C_PEND_REFRESH; + } + if (hdw->i2c_pend_types & PVR2_I2C_PEND_CLIENT) { + /* One or more client handlers are asking for an + update. Run through the list of known clients + and update each one. */ + pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_CLIENT"); + hdw->i2c_pend_types &= ~PVR2_I2C_PEND_CLIENT; + list_for_each_safe(item,nc,&hdw->i2c_clients) { + cp = list_entry(item,struct pvr2_i2c_client, + list); + if (!cp->handler) continue; + if (!cp->handler->func_table->update) continue; + pvr2_trace(PVR2_TRACE_I2C_CORE, + "i2c: cp=%p update",cp); + mutex_unlock(&hdw->i2c_list_lock); + cp->handler->func_table->update( + cp->handler->func_data); + mutex_lock(&hdw->i2c_list_lock); + /* If client's update function set some + additional pending bits, account for that + here. */ + if (cp->pend_mask & ~hdw->i2c_pend_mask) { + hdw->i2c_pend_mask |= cp->pend_mask; + hdw->i2c_pend_types |= + PVR2_I2C_PEND_REFRESH; + } + } + } + if (hdw->i2c_pend_types & PVR2_I2C_PEND_REFRESH) { + const struct pvr2_i2c_op *opf; + unsigned long pm; + /* Some actual updates are pending. Walk through + each update type and perform it. */ + pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: PEND_REFRESH" + " (0x%lx)",hdw->i2c_pend_mask); + hdw->i2c_pend_types &= ~PVR2_I2C_PEND_REFRESH; + pm = hdw->i2c_pend_mask; + hdw->i2c_pend_mask = 0; + for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { + if (!(pm & msk)) continue; + pm &= ~msk; + list_for_each(item,&hdw->i2c_clients) { + cp = list_entry(item, + struct pvr2_i2c_client, + list); + if (cp->pend_mask & msk) { + cp->pend_mask &= ~msk; + cp->recv_enable = !0; + } else { + cp->recv_enable = 0; + } + } + opf = pvr2_i2c_get_op(idx); + if (!opf) continue; + mutex_unlock(&hdw->i2c_list_lock); + opf->update(hdw); + mutex_lock(&hdw->i2c_list_lock); + } + } + pvr2_trace(PVR2_TRACE_I2C_CORE,"i2c: core_sync END"); + } while (0); mutex_unlock(&hdw->i2c_list_lock); +} + +int pvr2_i2c_core_check_stale(struct pvr2_hdw *hdw) +{ + unsigned long msk,sm,pm; + unsigned int idx; + const struct pvr2_i2c_op *opf; + struct list_head *item; + struct pvr2_i2c_client *cp; + unsigned int pt = 0; + + pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale BEGIN"); + + pm = hdw->i2c_active_mask; + sm = 0; + for (idx = 0, msk = 1; pm; idx++, msk <<= 1) { + if (!(msk & pm)) continue; + pm &= ~msk; + opf = pvr2_i2c_get_op(idx); + if (!opf) continue; + if (opf->check(hdw)) { + sm |= msk; + } + } + if (sm) pt |= PVR2_I2C_PEND_STALE; + + list_for_each(item,&hdw->i2c_clients) { + cp = list_entry(item,struct pvr2_i2c_client,list); + if (!handler_check(cp)) continue; + pt |= PVR2_I2C_PEND_CLIENT; + } + + if (pt) { + mutex_lock(&hdw->i2c_list_lock); do { + hdw->i2c_pend_types |= pt; + hdw->i2c_stale_mask |= sm; + hdw->i2c_pend_mask |= hdw->i2c_stale_mask; + } while (0); mutex_unlock(&hdw->i2c_list_lock); + } + + pvr2_trace(PVR2_TRACE_I2C_CORE, + "i2c: types=0x%x stale=0x%lx pend=0x%lx", + hdw->i2c_pend_types, + hdw->i2c_stale_mask, + hdw->i2c_pend_mask); + pvr2_trace(PVR2_TRACE_I2C_CORE,"pvr2_i2c_core_check_stale END"); + + return (hdw->i2c_pend_types & PVR2_I2C_PEND_ALL) != 0; +} + +static unsigned int pvr2_i2c_client_describe(struct pvr2_i2c_client *cp, + unsigned int detail, + char *buf,unsigned int maxlen) +{ + unsigned int ccnt,bcnt; + int spcfl = 0; + const struct pvr2_i2c_op *opf; + + ccnt = 0; + if (detail & PVR2_I2C_DETAIL_DEBUG) { + bcnt = scnprintf(buf,maxlen, + "ctxt=%p ctl_mask=0x%lx", + cp,cp->ctl_mask); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + spcfl = !0; + } + bcnt = scnprintf(buf,maxlen, + "%s%s @ 0x%x", + (spcfl ? " " : ""), + cp->client->name, + cp->client->addr); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + if ((detail & PVR2_I2C_DETAIL_HANDLER) && + cp->handler && cp->handler->func_table->describe) { + bcnt = scnprintf(buf,maxlen," ("); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + bcnt = cp->handler->func_table->describe( + cp->handler->func_data,buf,maxlen); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + bcnt = scnprintf(buf,maxlen,")"); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + } + if ((detail & PVR2_I2C_DETAIL_CTLMASK) && cp->ctl_mask) { + unsigned int idx; + unsigned long msk,sm; + int spcfl; + bcnt = scnprintf(buf,maxlen," ["); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + sm = 0; + spcfl = 0; + for (idx = 0, msk = 1; msk; idx++, msk <<= 1) { + if (!(cp->ctl_mask & msk)) continue; + opf = pvr2_i2c_get_op(idx); + if (opf) { + bcnt = scnprintf(buf,maxlen,"%s%s", + spcfl ? " " : "", + opf->name); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + spcfl = !0; + } else { + sm |= msk; + } + } + if (sm) { + bcnt = scnprintf(buf,maxlen,"%s%lx", + idx != 0 ? " " : "",sm); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + } + bcnt = scnprintf(buf,maxlen,"]"); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + } + return ccnt; +} + +unsigned int pvr2_i2c_report(struct pvr2_hdw *hdw, + char *buf,unsigned int maxlen) +{ + unsigned int ccnt,bcnt; + struct list_head *item; + struct pvr2_i2c_client *cp; + ccnt = 0; + mutex_lock(&hdw->i2c_list_lock); do { + list_for_each(item,&hdw->i2c_clients) { + cp = list_entry(item,struct pvr2_i2c_client,list); + bcnt = pvr2_i2c_client_describe( + cp, + (PVR2_I2C_DETAIL_HANDLER| + PVR2_I2C_DETAIL_CTLMASK), + buf,maxlen); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + bcnt = scnprintf(buf,maxlen,"\n"); + ccnt += bcnt; buf += bcnt; maxlen -= bcnt; + } + } while (0); mutex_unlock(&hdw->i2c_list_lock); + return ccnt; +} + +static int pvr2_i2c_attach_inform(struct i2c_client *client) +{ + struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); + struct pvr2_i2c_client *cp; + int fl = !(hdw->i2c_pend_types & PVR2_I2C_PEND_ALL); + cp = kmalloc(sizeof(*cp),GFP_KERNEL); + trace_i2c("i2c_attach [client=%s @ 0x%x ctxt=%p]", + client->name, + client->addr,cp); + if (!cp) return -ENOMEM; + memset(cp,0,sizeof(*cp)); + INIT_LIST_HEAD(&cp->list); + cp->client = client; + mutex_lock(&hdw->i2c_list_lock); do { + list_add_tail(&cp->list,&hdw->i2c_clients); + hdw->i2c_pend_types |= PVR2_I2C_PEND_DETECT; + } while (0); mutex_unlock(&hdw->i2c_list_lock); + if (fl) pvr2_hdw_poll_trigger_unlocked(hdw); + return 0; +} + +static int pvr2_i2c_detach_inform(struct i2c_client *client) +{ + struct pvr2_hdw *hdw = (struct pvr2_hdw *)(client->adapter->algo_data); + struct pvr2_i2c_client *cp; + struct list_head *item,*nc; + unsigned long amask = 0; + int foundfl = 0; + mutex_lock(&hdw->i2c_list_lock); do { + list_for_each_safe(item,nc,&hdw->i2c_clients) { + cp = list_entry(item,struct pvr2_i2c_client,list); + if (cp->client == client) { + trace_i2c("pvr2_i2c_detach" + " [client=%s @ 0x%x ctxt=%p]", + client->name, + client->addr,cp); + if (cp->handler && + cp->handler->func_table->detach) { + cp->handler->func_table->detach( + cp->handler->func_data); + } + list_del(&cp->list); + kfree(cp); + foundfl = !0; + continue; + } + amask |= cp->ctl_mask; + } + hdw->i2c_active_mask = amask; + } while (0); mutex_unlock(&hdw->i2c_list_lock); + if (!foundfl) { + trace_i2c("pvr2_i2c_detach [client=%s @ 0x%x ctxt=<unknown>]", + client->name, + client->addr); + } + return 0; +} + +static struct i2c_algorithm pvr2_i2c_algo_template = { + .master_xfer = pvr2_i2c_xfer, + .algo_control = pvr2_i2c_control, + .functionality = pvr2_i2c_functionality, +}; + +static struct i2c_adapter pvr2_i2c_adap_template = { + .owner = THIS_MODULE, + .class = I2C_CLASS_TV_ANALOG, + .id = I2C_HW_B_BT848, + .client_register = pvr2_i2c_attach_inform, + .client_unregister = pvr2_i2c_detach_inform, +}; + +static void do_i2c_scan(struct pvr2_hdw *hdw) +{ + struct i2c_msg msg[1]; + int i,rc; + msg[0].addr = 0; + msg[0].flags = I2C_M_RD; + msg[0].len = 0; + msg[0].buf = NULL; + printk("%s: i2c scan beginning\n",hdw->name); + for (i = 0; i < 128; i++) { + msg[0].addr = i; + rc = i2c_transfer(&hdw->i2c_adap,msg, + sizeof(msg)/sizeof(msg[0])); + if (rc != 1) continue; + printk("%s: i2c scan: found device @ 0x%x\n",hdw->name,i); + } + printk("%s: i2c scan done.\n",hdw->name); +} + +void pvr2_i2c_core_init(struct pvr2_hdw *hdw) +{ + unsigned int idx; + + // The default action for all possible I2C addresses is just to do + // the transfer normally. + for (idx = 0; idx < PVR2_I2C_FUNC_CNT; idx++) { + hdw->i2c_func[idx] = pvr2_i2c_basic_op; + } + +#ifdef CONFIG_VIDEO_PVRUSB2_24XXX + // If however we're dealing with new hardware, insert some hacks in + // the I2C transfer stack to let things work better. + if (hdw->hdw_type == PVR2_HDW_TYPE_24XXX) { + hdw->i2c_func[0x1b] = i2c_hack_wm8775; + hdw->i2c_func[0x44] = i2c_hack_cx25840; + } +#endif + + // Configure the adapter and set up everything else related to it. + memcpy(&hdw->i2c_adap,&pvr2_i2c_adap_template,sizeof(hdw->i2c_adap)); + memcpy(&hdw->i2c_algo,&pvr2_i2c_algo_template,sizeof(hdw->i2c_algo)); + strlcpy(hdw->i2c_adap.name,hdw->name,sizeof(hdw->i2c_adap.name)); + hdw->i2c_adap.algo = &hdw->i2c_algo; + hdw->i2c_adap.algo_data = hdw; + hdw->i2c_pend_mask = 0; + hdw->i2c_stale_mask = 0; + hdw->i2c_active_mask = 0; + INIT_LIST_HEAD(&hdw->i2c_clients); + mutex_init(&hdw->i2c_list_lock); + hdw->i2c_linked = !0; + i2c_add_adapter(&hdw->i2c_adap); + if (i2c_scan) do_i2c_scan(hdw); +} + +void pvr2_i2c_core_done(struct pvr2_hdw *hdw) +{ + if (hdw->i2c_linked) { + i2c_del_adapter(&hdw->i2c_adap); + hdw->i2c_linked = 0; + } +} + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h new file mode 100644 index 000000000..6d7e25247 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-i2c-core.h @@ -0,0 +1,93 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __PVRUSB2_I2C_CORE_H +#define __PVRUSB2_I2C_CORE_H + +#include <linux/list.h> +#include <linux/i2c.h> + +struct pvr2_hdw; +struct pvr2_i2c_client; +struct pvr2_i2c_handler; +struct pvr2_i2c_handler_functions; +struct pvr2_i2c_op; +struct pvr2_i2c_op_functions; + +struct pvr2_i2c_client { + struct i2c_client *client; + struct pvr2_i2c_handler *handler; + struct list_head list; + int detected_flag; + int recv_enable; + unsigned long pend_mask; + unsigned long ctl_mask; +}; + +struct pvr2_i2c_handler { + void *func_data; + const struct pvr2_i2c_handler_functions *func_table; +}; + +struct pvr2_i2c_handler_functions { + void (*detach)(void *); + int (*check)(void *); + void (*update)(void *); + unsigned int (*describe)(void *,char *,unsigned int); +}; + +struct pvr2_i2c_op { + int (*check)(struct pvr2_hdw *); + void (*update)(struct pvr2_hdw *); + const char *name; +}; + +void pvr2_i2c_core_init(struct pvr2_hdw *); +void pvr2_i2c_core_done(struct pvr2_hdw *); + +int pvr2_i2c_client_cmd(struct pvr2_i2c_client *,unsigned int cmd,void *arg); +int pvr2_i2c_core_cmd(struct pvr2_hdw *,unsigned int cmd,void *arg); + +int pvr2_i2c_core_check_stale(struct pvr2_hdw *); +void pvr2_i2c_core_sync(struct pvr2_hdw *); +unsigned int pvr2_i2c_report(struct pvr2_hdw *,char *buf,unsigned int maxlen); +#define PVR2_I2C_DETAIL_DEBUG 0x0001 +#define PVR2_I2C_DETAIL_HANDLER 0x0002 +#define PVR2_I2C_DETAIL_CTLMASK 0x0004 +#define PVR2_I2C_DETAIL_ALL (\ + PVR2_I2C_DETAIL_DEBUG |\ + PVR2_I2C_DETAIL_HANDLER |\ + PVR2_I2C_DETAIL_CTLMASK) + +void pvr2_i2c_probe(struct pvr2_hdw *,struct pvr2_i2c_client *); +const struct pvr2_i2c_op *pvr2_i2c_get_op(unsigned int idx); + +#endif /* __PVRUSB2_I2C_CORE_H */ + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c new file mode 100644 index 000000000..1e3937625 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-io.c @@ -0,0 +1,667 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "pvrusb2-io.h" +#include "pvrusb2-debug.h" +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/mutex.h> + +static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state); + +#define BUFFER_SIG 0x47653271 + +// #define SANITY_CHECK_BUFFERS + + +#ifdef SANITY_CHECK_BUFFERS +#define BUFFER_CHECK(bp) do { \ + if ((bp)->signature != BUFFER_SIG) { \ + pvr2_trace(PVR2_TRACE_ERROR_LEGS, \ + "Buffer %p is bad at %s:%d", \ + (bp),__FILE__,__LINE__); \ + pvr2_buffer_describe(bp,"BadSig"); \ + BUG(); \ + } \ +} while (0) +#else +#define BUFFER_CHECK(bp) do {} while(0) +#endif + +struct pvr2_stream { + /* Buffers queued for reading */ + struct list_head queued_list; + unsigned int q_count; + unsigned int q_bcount; + /* Buffers with retrieved data */ + struct list_head ready_list; + unsigned int r_count; + unsigned int r_bcount; + /* Buffers available for use */ + struct list_head idle_list; + unsigned int i_count; + unsigned int i_bcount; + /* Pointers to all buffers */ + struct pvr2_buffer **buffers; + /* Array size of buffers */ + unsigned int buffer_slot_count; + /* Total buffers actually in circulation */ + unsigned int buffer_total_count; + /* Designed number of buffers to be in circulation */ + unsigned int buffer_target_count; + /* Executed when ready list become non-empty */ + pvr2_stream_callback callback_func; + void *callback_data; + /* Context for transfer endpoint */ + struct usb_device *dev; + int endpoint; + /* Overhead for mutex enforcement */ + spinlock_t list_lock; + struct mutex mutex; + /* Tracking state for tolerating errors */ + unsigned int fail_count; + unsigned int fail_tolerance; +}; + +struct pvr2_buffer { + int id; + int signature; + enum pvr2_buffer_state state; + void *ptr; /* Pointer to storage area */ + unsigned int max_count; /* Size of storage area */ + unsigned int used_count; /* Amount of valid data in storage area */ + int status; /* Transfer result status */ + struct pvr2_stream *stream; + struct list_head list_overhead; + struct urb *purb; +}; + +static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state st) +{ + switch (st) { + case pvr2_buffer_state_none: return "none"; + case pvr2_buffer_state_idle: return "idle"; + case pvr2_buffer_state_queued: return "queued"; + case pvr2_buffer_state_ready: return "ready"; + } + return "unknown"; +} + +#ifdef SANITY_CHECK_BUFFERS +static void pvr2_buffer_describe(struct pvr2_buffer *bp,const char *msg) +{ + pvr2_trace(PVR2_TRACE_INFO, + "buffer%s%s %p state=%s id=%d status=%d" + " stream=%p purb=%p sig=0x%x", + (msg ? " " : ""), + (msg ? msg : ""), + bp, + (bp ? pvr2_buffer_state_decode(bp->state) : "(invalid)"), + (bp ? bp->id : 0), + (bp ? bp->status : 0), + (bp ? bp->stream : NULL), + (bp ? bp->purb : NULL), + (bp ? bp->signature : 0)); +} +#endif /* SANITY_CHECK_BUFFERS */ + +static void pvr2_buffer_remove(struct pvr2_buffer *bp) +{ + unsigned int *cnt; + unsigned int *bcnt; + unsigned int ccnt; + struct pvr2_stream *sp = bp->stream; + switch (bp->state) { + case pvr2_buffer_state_idle: + cnt = &sp->i_count; + bcnt = &sp->i_bcount; + ccnt = bp->max_count; + break; + case pvr2_buffer_state_queued: + cnt = &sp->q_count; + bcnt = &sp->q_bcount; + ccnt = bp->max_count; + break; + case pvr2_buffer_state_ready: + cnt = &sp->r_count; + bcnt = &sp->r_bcount; + ccnt = bp->used_count; + break; + default: + return; + } + list_del_init(&bp->list_overhead); + (*cnt)--; + (*bcnt) -= ccnt; + pvr2_trace(PVR2_TRACE_BUF_FLOW, + "/*---TRACE_FLOW---*/" + " bufferPool %8s dec cap=%07d cnt=%02d", + pvr2_buffer_state_decode(bp->state),*bcnt,*cnt); + bp->state = pvr2_buffer_state_none; +} + +static void pvr2_buffer_set_none(struct pvr2_buffer *bp) +{ + unsigned long irq_flags; + struct pvr2_stream *sp; + BUFFER_CHECK(bp); + sp = bp->stream; + pvr2_trace(PVR2_TRACE_BUF_FLOW, + "/*---TRACE_FLOW---*/ bufferState %p %6s --> %6s", + bp, + pvr2_buffer_state_decode(bp->state), + pvr2_buffer_state_decode(pvr2_buffer_state_none)); + spin_lock_irqsave(&sp->list_lock,irq_flags); + pvr2_buffer_remove(bp); + spin_unlock_irqrestore(&sp->list_lock,irq_flags); +} + +static int pvr2_buffer_set_ready(struct pvr2_buffer *bp) +{ + int fl; + unsigned long irq_flags; + struct pvr2_stream *sp; + BUFFER_CHECK(bp); + sp = bp->stream; + pvr2_trace(PVR2_TRACE_BUF_FLOW, + "/*---TRACE_FLOW---*/ bufferState %p %6s --> %6s", + bp, + pvr2_buffer_state_decode(bp->state), + pvr2_buffer_state_decode(pvr2_buffer_state_ready)); + spin_lock_irqsave(&sp->list_lock,irq_flags); + fl = (sp->r_count == 0); + pvr2_buffer_remove(bp); + list_add_tail(&bp->list_overhead,&sp->ready_list); + bp->state = pvr2_buffer_state_ready; + (sp->r_count)++; + sp->r_bcount += bp->used_count; + pvr2_trace(PVR2_TRACE_BUF_FLOW, + "/*---TRACE_FLOW---*/" + " bufferPool %8s inc cap=%07d cnt=%02d", + pvr2_buffer_state_decode(bp->state), + sp->r_bcount,sp->r_count); + spin_unlock_irqrestore(&sp->list_lock,irq_flags); + return fl; +} + +static void pvr2_buffer_set_idle(struct pvr2_buffer *bp) +{ + unsigned long irq_flags; + struct pvr2_stream *sp; + BUFFER_CHECK(bp); + sp = bp->stream; + pvr2_trace(PVR2_TRACE_BUF_FLOW, + "/*---TRACE_FLOW---*/ bufferState %p %6s --> %6s", + bp, + pvr2_buffer_state_decode(bp->state), + pvr2_buffer_state_decode(pvr2_buffer_state_idle)); + spin_lock_irqsave(&sp->list_lock,irq_flags); + pvr2_buffer_remove(bp); + list_add_tail(&bp->list_overhead,&sp->idle_list); + bp->state = pvr2_buffer_state_idle; + (sp->i_count)++; + sp->i_bcount += bp->max_count; + pvr2_trace(PVR2_TRACE_BUF_FLOW, + "/*---TRACE_FLOW---*/" + " bufferPool %8s inc cap=%07d cnt=%02d", + pvr2_buffer_state_decode(bp->state), + sp->i_bcount,sp->i_count); + spin_unlock_irqrestore(&sp->list_lock,irq_flags); +} + +static void pvr2_buffer_set_queued(struct pvr2_buffer *bp) +{ + unsigned long irq_flags; + struct pvr2_stream *sp; + BUFFER_CHECK(bp); + sp = bp->stream; + pvr2_trace(PVR2_TRACE_BUF_FLOW, + "/*---TRACE_FLOW---*/ bufferState %p %6s --> %6s", + bp, + pvr2_buffer_state_decode(bp->state), + pvr2_buffer_state_decode(pvr2_buffer_state_queued)); + spin_lock_irqsave(&sp->list_lock,irq_flags); + pvr2_buffer_remove(bp); + list_add_tail(&bp->list_overhead,&sp->queued_list); + bp->state = pvr2_buffer_state_queued; + (sp->q_count)++; + sp->q_bcount += bp->max_count; + pvr2_trace(PVR2_TRACE_BUF_FLOW, + "/*---TRACE_FLOW---*/" + " bufferPool %8s inc cap=%07d cnt=%02d", + pvr2_buffer_state_decode(bp->state), + sp->q_bcount,sp->q_count); + spin_unlock_irqrestore(&sp->list_lock,irq_flags); +} + +static void pvr2_buffer_wipe(struct pvr2_buffer *bp) +{ + if (bp->state == pvr2_buffer_state_queued) { + usb_kill_urb(bp->purb); + } +} + +static int pvr2_buffer_init(struct pvr2_buffer *bp, + struct pvr2_stream *sp, + unsigned int id) +{ + memset(bp,0,sizeof(*bp)); + bp->signature = BUFFER_SIG; + bp->id = id; + pvr2_trace(PVR2_TRACE_BUF_POOL, + "/*---TRACE_FLOW---*/ bufferInit %p stream=%p",bp,sp); + bp->stream = sp; + bp->state = pvr2_buffer_state_none; + INIT_LIST_HEAD(&bp->list_overhead); + bp->purb = usb_alloc_urb(0,GFP_KERNEL); + if (! bp->purb) return -ENOMEM; +#ifdef SANITY_CHECK_BUFFERS + pvr2_buffer_describe(bp,"create"); +#endif + return 0; +} + +static void pvr2_buffer_done(struct pvr2_buffer *bp) +{ +#ifdef SANITY_CHECK_BUFFERS + pvr2_buffer_describe(bp,"delete"); +#endif + pvr2_buffer_wipe(bp); + pvr2_buffer_set_none(bp); + bp->signature = 0; + bp->stream = NULL; + if (bp->purb) usb_free_urb(bp->purb); + pvr2_trace(PVR2_TRACE_BUF_POOL,"/*---TRACE_FLOW---*/" + " bufferDone %p",bp); +} + +static int pvr2_stream_buffer_count(struct pvr2_stream *sp,unsigned int cnt) +{ + int ret; + unsigned int scnt; + + /* Allocate buffers pointer array in multiples of 32 entries */ + if (cnt == sp->buffer_total_count) return 0; + + pvr2_trace(PVR2_TRACE_BUF_POOL, + "/*---TRACE_FLOW---*/ poolResize " + " stream=%p cur=%d adj=%+d", + sp, + sp->buffer_total_count, + cnt-sp->buffer_total_count); + + scnt = cnt & ~0x1f; + if (cnt > scnt) scnt += 0x20; + + if (cnt > sp->buffer_total_count) { + if (scnt > sp->buffer_slot_count) { + struct pvr2_buffer **nb; + nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL); + if (!nb) return -ENOMEM; + if (sp->buffer_slot_count) { + memcpy(nb,sp->buffers, + sp->buffer_slot_count * sizeof(*nb)); + kfree(sp->buffers); + } + sp->buffers = nb; + sp->buffer_slot_count = scnt; + } + while (sp->buffer_total_count < cnt) { + struct pvr2_buffer *bp; + bp = kmalloc(sizeof(*bp),GFP_KERNEL); + if (!bp) return -ENOMEM; + ret = pvr2_buffer_init(bp,sp,sp->buffer_total_count); + if (ret) { + kfree(bp); + return -ENOMEM; + } + sp->buffers[sp->buffer_total_count] = bp; + (sp->buffer_total_count)++; + pvr2_buffer_set_idle(bp); + } + } else { + while (sp->buffer_total_count > cnt) { + struct pvr2_buffer *bp; + bp = sp->buffers[sp->buffer_total_count - 1]; + /* Paranoia */ + sp->buffers[sp->buffer_total_count - 1] = NULL; + (sp->buffer_total_count)--; + pvr2_buffer_done(bp); + kfree(bp); + } + if (scnt < sp->buffer_slot_count) { + struct pvr2_buffer **nb = NULL; + if (scnt) { + nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL); + if (!nb) return -ENOMEM; + memcpy(nb,sp->buffers,scnt * sizeof(*nb)); + } + kfree(sp->buffers); + sp->buffers = nb; + sp->buffer_slot_count = scnt; + } + } + return 0; +} + +static int pvr2_stream_achieve_buffer_count(struct pvr2_stream *sp) +{ + struct pvr2_buffer *bp; + unsigned int cnt; + + if (sp->buffer_total_count == sp->buffer_target_count) return 0; + + pvr2_trace(PVR2_TRACE_BUF_POOL, + "/*---TRACE_FLOW---*/" + " poolCheck stream=%p cur=%d tgt=%d", + sp,sp->buffer_total_count,sp->buffer_target_count); + + if (sp->buffer_total_count < sp->buffer_target_count) { + return pvr2_stream_buffer_count(sp,sp->buffer_target_count); + } + + cnt = 0; + while ((sp->buffer_total_count - cnt) > sp->buffer_target_count) { + bp = sp->buffers[sp->buffer_total_count - (cnt + 1)]; + if (bp->state != pvr2_buffer_state_idle) break; + cnt++; + } + if (cnt) { + pvr2_stream_buffer_count(sp,sp->buffer_total_count - cnt); + } + + return 0; +} + +static void pvr2_stream_internal_flush(struct pvr2_stream *sp) +{ + struct list_head *lp; + struct pvr2_buffer *bp1; + while ((lp = sp->queued_list.next) != &sp->queued_list) { + bp1 = list_entry(lp,struct pvr2_buffer,list_overhead); + pvr2_buffer_wipe(bp1); + /* At this point, we should be guaranteed that no + completion callback may happen on this buffer. But it's + possible that it might have completed after we noticed + it but before we wiped it. So double check its status + here first. */ + if (bp1->state != pvr2_buffer_state_queued) continue; + pvr2_buffer_set_idle(bp1); + } + if (sp->buffer_total_count != sp->buffer_target_count) { + pvr2_stream_achieve_buffer_count(sp); + } +} + +static void pvr2_stream_init(struct pvr2_stream *sp) +{ + spin_lock_init(&sp->list_lock); + mutex_init(&sp->mutex); + INIT_LIST_HEAD(&sp->queued_list); + INIT_LIST_HEAD(&sp->ready_list); + INIT_LIST_HEAD(&sp->idle_list); +} + +static void pvr2_stream_done(struct pvr2_stream *sp) +{ + mutex_lock(&sp->mutex); do { + pvr2_stream_internal_flush(sp); + pvr2_stream_buffer_count(sp,0); + } while (0); mutex_unlock(&sp->mutex); +} + +static void buffer_complete(struct urb *urb, struct pt_regs *regs) +{ + struct pvr2_buffer *bp = urb->context; + struct pvr2_stream *sp; + unsigned long irq_flags; + BUFFER_CHECK(bp); + sp = bp->stream; + bp->used_count = 0; + bp->status = 0; + pvr2_trace(PVR2_TRACE_BUF_FLOW, + "/*---TRACE_FLOW---*/ bufferComplete %p stat=%d cnt=%d", + bp,urb->status,urb->actual_length); + spin_lock_irqsave(&sp->list_lock,irq_flags); + if ((!(urb->status)) || + (urb->status == -ENOENT) || + (urb->status == -ECONNRESET) || + (urb->status == -ESHUTDOWN)) { + bp->used_count = urb->actual_length; + if (sp->fail_count) { + pvr2_trace(PVR2_TRACE_TOLERANCE, + "stream %p transfer ok" + " - fail count reset",sp); + sp->fail_count = 0; + } + } else if (sp->fail_count < sp->fail_tolerance) { + // We can tolerate this error, because we're below the + // threshold... + (sp->fail_count)++; + pvr2_trace(PVR2_TRACE_TOLERANCE, + "stream %p ignoring error %d" + " - fail count increased to %u", + sp,urb->status,sp->fail_count); + } else { + bp->status = urb->status; + } + spin_unlock_irqrestore(&sp->list_lock,irq_flags); + pvr2_buffer_set_ready(bp); + if (sp && sp->callback_func) { + sp->callback_func(sp->callback_data); + } +} + +struct pvr2_stream *pvr2_stream_create(void) +{ + struct pvr2_stream *sp; + sp = kmalloc(sizeof(*sp),GFP_KERNEL); + if (!sp) return sp; + memset(sp,0,sizeof(*sp)); + pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_create: sp=%p",sp); + pvr2_stream_init(sp); + return sp; +} + +void pvr2_stream_destroy(struct pvr2_stream *sp) +{ + if (!sp) return; + pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_destroy: sp=%p",sp); + pvr2_stream_done(sp); + kfree(sp); +} + +void pvr2_stream_setup(struct pvr2_stream *sp, + struct usb_device *dev, + int endpoint, + unsigned int tolerance) +{ + mutex_lock(&sp->mutex); do { + pvr2_stream_internal_flush(sp); + sp->dev = dev; + sp->endpoint = endpoint; + sp->fail_tolerance = tolerance; + } while(0); mutex_unlock(&sp->mutex); +} + +void pvr2_stream_set_callback(struct pvr2_stream *sp, + pvr2_stream_callback func, + void *data) +{ + unsigned long irq_flags; + mutex_lock(&sp->mutex); do { + spin_lock_irqsave(&sp->list_lock,irq_flags); + sp->callback_data = data; + sp->callback_func = func; + spin_unlock_irqrestore(&sp->list_lock,irq_flags); + } while(0); mutex_unlock(&sp->mutex); +} + +/* Query / set the nominal buffer count */ +int pvr2_stream_get_buffer_count(struct pvr2_stream *sp) +{ + return sp->buffer_target_count; +} + +int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt) +{ + int ret; + if (sp->buffer_target_count == cnt) return 0; + mutex_lock(&sp->mutex); do { + sp->buffer_target_count = cnt; + ret = pvr2_stream_achieve_buffer_count(sp); + } while(0); mutex_unlock(&sp->mutex); + return ret; +} + +struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *sp) +{ + struct list_head *lp = sp->idle_list.next; + if (lp == &sp->idle_list) return NULL; + return list_entry(lp,struct pvr2_buffer,list_overhead); +} + +struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *sp) +{ + struct list_head *lp = sp->ready_list.next; + if (lp == &sp->ready_list) return NULL; + return list_entry(lp,struct pvr2_buffer,list_overhead); +} + +struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id) +{ + if (id < 0) return NULL; + if (id >= sp->buffer_total_count) return NULL; + return sp->buffers[id]; +} + +int pvr2_stream_get_ready_count(struct pvr2_stream *sp) +{ + return sp->r_count; +} + +void pvr2_stream_kill(struct pvr2_stream *sp) +{ + struct pvr2_buffer *bp; + mutex_lock(&sp->mutex); do { + pvr2_stream_internal_flush(sp); + while ((bp = pvr2_stream_get_ready_buffer(sp)) != 0) { + pvr2_buffer_set_idle(bp); + } + if (sp->buffer_total_count != sp->buffer_target_count) { + pvr2_stream_achieve_buffer_count(sp); + } + } while(0); mutex_unlock(&sp->mutex); +} + +int pvr2_buffer_queue(struct pvr2_buffer *bp) +{ +#undef SEED_BUFFER +#ifdef SEED_BUFFER + unsigned int idx; + unsigned int val; +#endif + int ret = 0; + struct pvr2_stream *sp; + if (!bp) return -EINVAL; + sp = bp->stream; + mutex_lock(&sp->mutex); do { + pvr2_buffer_wipe(bp); + if (!sp->dev) { + ret = -EIO; + break; + } + pvr2_buffer_set_queued(bp); +#ifdef SEED_BUFFER + for (idx = 0; idx < (bp->max_count) / 4; idx++) { + val = bp->id << 24; + val |= idx; + ((unsigned int *)(bp->ptr))[idx] = val; + } +#endif + bp->status = -EINPROGRESS; + usb_fill_bulk_urb(bp->purb, // struct urb *urb + sp->dev, // struct usb_device *dev + // endpoint (below) + usb_rcvbulkpipe(sp->dev,sp->endpoint), + bp->ptr, // void *transfer_buffer + bp->max_count, // int buffer_length + buffer_complete, + bp); + usb_submit_urb(bp->purb,GFP_KERNEL); + } while(0); mutex_unlock(&sp->mutex); + return ret; +} + +int pvr2_buffer_set_buffer(struct pvr2_buffer *bp,void *ptr,unsigned int cnt) +{ + int ret = 0; + unsigned long irq_flags; + struct pvr2_stream *sp; + if (!bp) return -EINVAL; + sp = bp->stream; + mutex_lock(&sp->mutex); do { + spin_lock_irqsave(&sp->list_lock,irq_flags); + if (bp->state != pvr2_buffer_state_idle) { + ret = -EPERM; + } else { + bp->ptr = ptr; + bp->stream->i_bcount -= bp->max_count; + bp->max_count = cnt; + bp->stream->i_bcount += bp->max_count; + pvr2_trace(PVR2_TRACE_BUF_FLOW, + "/*---TRACE_FLOW---*/ bufferPool " + " %8s cap cap=%07d cnt=%02d", + pvr2_buffer_state_decode( + pvr2_buffer_state_idle), + bp->stream->i_bcount,bp->stream->i_count); + } + spin_unlock_irqrestore(&sp->list_lock,irq_flags); + } while(0); mutex_unlock(&sp->mutex); + return ret; +} + +unsigned int pvr2_buffer_get_count(struct pvr2_buffer *bp) +{ + return bp->used_count; +} + +int pvr2_buffer_get_status(struct pvr2_buffer *bp) +{ + return bp->status; +} + +int pvr2_buffer_get_id(struct pvr2_buffer *bp) +{ + return bp->id; +} + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.h b/drivers/media/video/pvrusb2/pvrusb2-io.h new file mode 100644 index 000000000..93279cc2a --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-io.h @@ -0,0 +1,91 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __PVRUSB2_IO_H +#define __PVRUSB2_IO_H + +#include <linux/usb.h> +#include <linux/list.h> + +typedef void (*pvr2_stream_callback)(void *); + +enum pvr2_buffer_state { + pvr2_buffer_state_none = 0, // Not on any list + pvr2_buffer_state_idle = 1, // Buffer is ready to be used again + pvr2_buffer_state_queued = 2, // Buffer has been queued for filling + pvr2_buffer_state_ready = 3, // Buffer has data available +}; + +struct pvr2_stream; +struct pvr2_buffer; + +/* Initialize / tear down stream structure */ +struct pvr2_stream *pvr2_stream_create(void); +void pvr2_stream_destroy(struct pvr2_stream *); +void pvr2_stream_setup(struct pvr2_stream *, + struct usb_device *dev,int endpoint, + unsigned int tolerance); +void pvr2_stream_set_callback(struct pvr2_stream *, + pvr2_stream_callback func, + void *data); + +/* Query / set the nominal buffer count */ +int pvr2_stream_get_buffer_count(struct pvr2_stream *); +int pvr2_stream_set_buffer_count(struct pvr2_stream *,unsigned int); + +/* Get a pointer to a buffer that is either idle, ready, or is specified + named. */ +struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *); +struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *); +struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id); + +/* Find out how many buffers are idle or ready */ +int pvr2_stream_get_ready_count(struct pvr2_stream *); + + +/* Kill all pending buffers and throw away any ready buffers as well */ +void pvr2_stream_kill(struct pvr2_stream *); + +/* Set up the actual storage for a buffer */ +int pvr2_buffer_set_buffer(struct pvr2_buffer *,void *ptr,unsigned int cnt); + +/* Find out size of data in the given ready buffer */ +unsigned int pvr2_buffer_get_count(struct pvr2_buffer *); + +/* Retrieve completion code for given ready buffer */ +int pvr2_buffer_get_status(struct pvr2_buffer *); + +/* Retrieve ID of given buffer */ +int pvr2_buffer_get_id(struct pvr2_buffer *); + +/* Start reading into given buffer (kill it if needed) */ +int pvr2_buffer_queue(struct pvr2_buffer *); + +#endif /* __PVRUSB2_IO_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.c b/drivers/media/video/pvrusb2/pvrusb2-ioread.c new file mode 100644 index 000000000..b71f9a961 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-ioread.c @@ -0,0 +1,510 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "pvrusb2-ioread.h" +#include "pvrusb2-debug.h" +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/mutex.h> +#include <asm/uaccess.h> + +#define BUFFER_COUNT 32 +#define BUFFER_SIZE PAGE_ALIGN(0x4000) + +struct pvr2_ioread { + struct pvr2_stream *stream; + char *buffer_storage[BUFFER_COUNT]; + char *sync_key_ptr; + unsigned int sync_key_len; + unsigned int sync_buf_offs; + unsigned int sync_state; + unsigned int sync_trashed_count; + int enabled; // Streaming is on + int spigot_open; // OK to pass data to client + int stream_running; // Passing data to client now + + /* State relevant to current buffer being read */ + struct pvr2_buffer *c_buf; + char *c_data_ptr; + unsigned int c_data_len; + unsigned int c_data_offs; + struct mutex mutex; +}; + +static int pvr2_ioread_init(struct pvr2_ioread *cp) +{ + unsigned int idx; + + cp->stream = NULL; + mutex_init(&cp->mutex); + + for (idx = 0; idx < BUFFER_COUNT; idx++) { + cp->buffer_storage[idx] = kmalloc(BUFFER_SIZE,GFP_KERNEL); + if (!(cp->buffer_storage[idx])) break; + } + + if (idx < BUFFER_COUNT) { + // An allocation appears to have failed + for (idx = 0; idx < BUFFER_COUNT; idx++) { + if (!(cp->buffer_storage[idx])) continue; + kfree(cp->buffer_storage[idx]); + } + return -ENOMEM; + } + return 0; +} + +static void pvr2_ioread_done(struct pvr2_ioread *cp) +{ + unsigned int idx; + + pvr2_ioread_setup(cp,NULL); + for (idx = 0; idx < BUFFER_COUNT; idx++) { + if (!(cp->buffer_storage[idx])) continue; + kfree(cp->buffer_storage[idx]); + } +} + +struct pvr2_ioread *pvr2_ioread_create(void) +{ + struct pvr2_ioread *cp; + cp = kmalloc(sizeof(*cp),GFP_KERNEL); + if (!cp) return NULL; + pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_create id=%p",cp); + memset(cp,0,sizeof(*cp)); + if (pvr2_ioread_init(cp) < 0) { + kfree(cp); + return NULL; + } + return cp; +} + +void pvr2_ioread_destroy(struct pvr2_ioread *cp) +{ + if (!cp) return; + pvr2_ioread_done(cp); + pvr2_trace(PVR2_TRACE_STRUCT,"pvr2_ioread_destroy id=%p",cp); + if (cp->sync_key_ptr) { + kfree(cp->sync_key_ptr); + cp->sync_key_ptr = NULL; + } + kfree(cp); +} + +void pvr2_ioread_set_sync_key(struct pvr2_ioread *cp, + const char *sync_key_ptr, + unsigned int sync_key_len) +{ + if (!cp) return; + + if (!sync_key_ptr) sync_key_len = 0; + if ((sync_key_len == cp->sync_key_len) && + ((!sync_key_len) || + (!memcmp(sync_key_ptr,cp->sync_key_ptr,sync_key_len)))) return; + + if (sync_key_len != cp->sync_key_len) { + if (cp->sync_key_ptr) { + kfree(cp->sync_key_ptr); + cp->sync_key_ptr = NULL; + } + cp->sync_key_len = 0; + if (sync_key_len) { + cp->sync_key_ptr = kmalloc(sync_key_len,GFP_KERNEL); + if (cp->sync_key_ptr) { + cp->sync_key_len = sync_key_len; + } + } + } + if (!cp->sync_key_len) return; + memcpy(cp->sync_key_ptr,sync_key_ptr,cp->sync_key_len); +} + +static void pvr2_ioread_stop(struct pvr2_ioread *cp) +{ + if (!(cp->enabled)) return; + pvr2_trace(PVR2_TRACE_START_STOP, + "/*---TRACE_READ---*/ pvr2_ioread_stop id=%p",cp); + pvr2_stream_kill(cp->stream); + cp->c_buf = NULL; + cp->c_data_ptr = NULL; + cp->c_data_len = 0; + cp->c_data_offs = 0; + cp->enabled = 0; + cp->stream_running = 0; + cp->spigot_open = 0; + if (cp->sync_state) { + pvr2_trace(PVR2_TRACE_DATA_FLOW, + "/*---TRACE_READ---*/ sync_state <== 0"); + cp->sync_state = 0; + } +} + +static int pvr2_ioread_start(struct pvr2_ioread *cp) +{ + int stat; + struct pvr2_buffer *bp; + if (cp->enabled) return 0; + if (!(cp->stream)) return 0; + pvr2_trace(PVR2_TRACE_START_STOP, + "/*---TRACE_READ---*/ pvr2_ioread_start id=%p",cp); + while ((bp = pvr2_stream_get_idle_buffer(cp->stream)) != 0) { + stat = pvr2_buffer_queue(bp); + if (stat < 0) { + pvr2_trace(PVR2_TRACE_DATA_FLOW, + "/*---TRACE_READ---*/" + " pvr2_ioread_start id=%p" + " error=%d", + cp,stat); + pvr2_ioread_stop(cp); + return stat; + } + } + cp->enabled = !0; + cp->c_buf = NULL; + cp->c_data_ptr = NULL; + cp->c_data_len = 0; + cp->c_data_offs = 0; + cp->stream_running = 0; + if (cp->sync_key_len) { + pvr2_trace(PVR2_TRACE_DATA_FLOW, + "/*---TRACE_READ---*/ sync_state <== 1"); + cp->sync_state = 1; + cp->sync_trashed_count = 0; + cp->sync_buf_offs = 0; + } + cp->spigot_open = 0; + return 0; +} + +struct pvr2_stream *pvr2_ioread_get_stream(struct pvr2_ioread *cp) +{ + return cp->stream; +} + +int pvr2_ioread_setup(struct pvr2_ioread *cp,struct pvr2_stream *sp) +{ + int ret; + unsigned int idx; + struct pvr2_buffer *bp; + + mutex_lock(&cp->mutex); do { + if (cp->stream) { + pvr2_trace(PVR2_TRACE_START_STOP, + "/*---TRACE_READ---*/" + " pvr2_ioread_setup (tear-down) id=%p",cp); + pvr2_ioread_stop(cp); + pvr2_stream_kill(cp->stream); + if (pvr2_stream_get_buffer_count(cp->stream)) { + pvr2_stream_set_buffer_count(cp->stream,0); + } + cp->stream = NULL; + } + if (sp) { + pvr2_trace(PVR2_TRACE_START_STOP, + "/*---TRACE_READ---*/" + " pvr2_ioread_setup (setup) id=%p",cp); + pvr2_stream_kill(sp); + ret = pvr2_stream_set_buffer_count(sp,BUFFER_COUNT); + if (ret < 0) return ret; + for (idx = 0; idx < BUFFER_COUNT; idx++) { + bp = pvr2_stream_get_buffer(sp,idx); + pvr2_buffer_set_buffer(bp, + cp->buffer_storage[idx], + BUFFER_SIZE); + } + cp->stream = sp; + } + } while (0); mutex_unlock(&cp->mutex); + + return 0; +} + +int pvr2_ioread_set_enabled(struct pvr2_ioread *cp,int fl) +{ + int ret = 0; + if ((!fl) == (!(cp->enabled))) return ret; + + mutex_lock(&cp->mutex); do { + if (fl) { + ret = pvr2_ioread_start(cp); + } else { + pvr2_ioread_stop(cp); + } + } while (0); mutex_unlock(&cp->mutex); + return ret; +} + +static int pvr2_ioread_get_buffer(struct pvr2_ioread *cp) +{ + int stat; + + while (cp->c_data_len <= cp->c_data_offs) { + if (cp->c_buf) { + // Flush out current buffer first. + stat = pvr2_buffer_queue(cp->c_buf); + if (stat < 0) { + // Streaming error... + pvr2_trace(PVR2_TRACE_DATA_FLOW, + "/*---TRACE_READ---*/" + " pvr2_ioread_read id=%p" + " queue_error=%d", + cp,stat); + pvr2_ioread_stop(cp); + return 0; + } + cp->c_buf = NULL; + cp->c_data_ptr = NULL; + cp->c_data_len = 0; + cp->c_data_offs = 0; + } + // Now get a freshly filled buffer. + cp->c_buf = pvr2_stream_get_ready_buffer(cp->stream); + if (!cp->c_buf) break; // Nothing ready; done. + cp->c_data_len = pvr2_buffer_get_count(cp->c_buf); + if (!cp->c_data_len) { + // Nothing transferred. Was there an error? + stat = pvr2_buffer_get_status(cp->c_buf); + if (stat < 0) { + // Streaming error... + pvr2_trace(PVR2_TRACE_DATA_FLOW, + "/*---TRACE_READ---*/" + " pvr2_ioread_read id=%p" + " buffer_error=%d", + cp,stat); + pvr2_ioread_stop(cp); + // Give up. + return 0; + } + // Start over... + continue; + } + cp->c_data_offs = 0; + cp->c_data_ptr = cp->buffer_storage[ + pvr2_buffer_get_id(cp->c_buf)]; + } + return !0; +} + +static void pvr2_ioread_filter(struct pvr2_ioread *cp) +{ + unsigned int idx; + if (!cp->enabled) return; + if (cp->sync_state != 1) return; + + // Search the stream for our synchronization key. This is made + // complicated by the fact that in order to be honest with + // ourselves here we must search across buffer boundaries... + mutex_lock(&cp->mutex); while (1) { + // Ensure we have a buffer + if (!pvr2_ioread_get_buffer(cp)) break; + if (!cp->c_data_len) break; + + // Now walk the buffer contents until we match the key or + // run out of buffer data. + for (idx = cp->c_data_offs; idx < cp->c_data_len; idx++) { + if (cp->sync_buf_offs >= cp->sync_key_len) break; + if (cp->c_data_ptr[idx] == + cp->sync_key_ptr[cp->sync_buf_offs]) { + // Found the next key byte + (cp->sync_buf_offs)++; + } else { + // Whoops, mismatched. Start key over... + cp->sync_buf_offs = 0; + } + } + + // Consume what we've walked through + cp->c_data_offs += idx; + cp->sync_trashed_count += idx; + + // If we've found the key, then update state and get out. + if (cp->sync_buf_offs >= cp->sync_key_len) { + cp->sync_trashed_count -= cp->sync_key_len; + pvr2_trace(PVR2_TRACE_DATA_FLOW, + "/*---TRACE_READ---*/" + " sync_state <== 2 (skipped %u bytes)", + cp->sync_trashed_count); + cp->sync_state = 2; + cp->sync_buf_offs = 0; + break; + } + + if (cp->c_data_offs < cp->c_data_len) { + // Sanity check - should NEVER get here + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "ERROR: pvr2_ioread filter sync problem" + " len=%u offs=%u", + cp->c_data_len,cp->c_data_offs); + // Get out so we don't get stuck in an infinite + // loop. + break; + } + + continue; // (for clarity) + } mutex_unlock(&cp->mutex); +} + +int pvr2_ioread_avail(struct pvr2_ioread *cp) +{ + int ret; + if (!(cp->enabled)) { + // Stream is not enabled; so this is an I/O error + return -EIO; + } + + if (cp->sync_state == 1) { + pvr2_ioread_filter(cp); + if (cp->sync_state == 1) return -EAGAIN; + } + + ret = 0; + if (cp->stream_running) { + if (!pvr2_stream_get_ready_count(cp->stream)) { + // No data available at all right now. + ret = -EAGAIN; + } + } else { + if (pvr2_stream_get_ready_count(cp->stream) < BUFFER_COUNT/2) { + // Haven't buffered up enough yet; try again later + ret = -EAGAIN; + } + } + + if ((!(cp->spigot_open)) != (!(ret == 0))) { + cp->spigot_open = (ret == 0); + pvr2_trace(PVR2_TRACE_DATA_FLOW, + "/*---TRACE_READ---*/ data is %s", + cp->spigot_open ? "available" : "pending"); + } + + return ret; +} + +int pvr2_ioread_read(struct pvr2_ioread *cp,void __user *buf,unsigned int cnt) +{ + unsigned int copied_cnt; + unsigned int bcnt; + const char *src; + int stat; + int ret = 0; + unsigned int req_cnt = cnt; + + if (!cnt) { + pvr2_trace(PVR2_TRACE_TRAP, + "/*---TRACE_READ---*/ pvr2_ioread_read id=%p" + " ZERO Request? Returning zero.",cp); + return 0; + } + + stat = pvr2_ioread_avail(cp); + if (stat < 0) return stat; + + cp->stream_running = !0; + + mutex_lock(&cp->mutex); do { + + // Suck data out of the buffers and copy to the user + copied_cnt = 0; + if (!buf) cnt = 0; + while (1) { + if (!pvr2_ioread_get_buffer(cp)) { + ret = -EIO; + break; + } + + if (!cnt) break; + + if (cp->sync_state == 2) { + // We're repeating the sync key data into + // the stream. + src = cp->sync_key_ptr + cp->sync_buf_offs; + bcnt = cp->sync_key_len - cp->sync_buf_offs; + } else { + // Normal buffer copy + src = cp->c_data_ptr + cp->c_data_offs; + bcnt = cp->c_data_len - cp->c_data_offs; + } + + if (!bcnt) break; + + // Don't run past user's buffer + if (bcnt > cnt) bcnt = cnt; + + if (copy_to_user(buf,src,bcnt)) { + // User supplied a bad pointer? + // Give up - this *will* cause data + // to be lost. + ret = -EFAULT; + break; + } + cnt -= bcnt; + buf += bcnt; + copied_cnt += bcnt; + + if (cp->sync_state == 2) { + // Update offset inside sync key that we're + // repeating back out. + cp->sync_buf_offs += bcnt; + if (cp->sync_buf_offs >= cp->sync_key_len) { + // Consumed entire key; switch mode + // to normal. + pvr2_trace(PVR2_TRACE_DATA_FLOW, + "/*---TRACE_READ---*/" + " sync_state <== 0"); + cp->sync_state = 0; + } + } else { + // Update buffer offset. + cp->c_data_offs += bcnt; + } + } + + } while (0); mutex_unlock(&cp->mutex); + + if (!ret) { + if (copied_cnt) { + // If anything was copied, return that count + ret = copied_cnt; + } else { + // Nothing copied; suggest to caller that another + // attempt should be tried again later + ret = -EAGAIN; + } + } + + pvr2_trace(PVR2_TRACE_DATA_FLOW, + "/*---TRACE_READ---*/ pvr2_ioread_read" + " id=%p request=%d result=%d", + cp,req_cnt,ret); + return ret; +} + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-ioread.h b/drivers/media/video/pvrusb2/pvrusb2-ioread.h new file mode 100644 index 000000000..1d362f833 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-ioread.h @@ -0,0 +1,49 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __PVRUSB2_IOREAD_H +#define __PVRUSB2_IOREAD_H + +#include "pvrusb2-io.h" + +struct pvr2_ioread; + +struct pvr2_ioread *pvr2_ioread_create(void); +void pvr2_ioread_destroy(struct pvr2_ioread *); +int pvr2_ioread_setup(struct pvr2_ioread *,struct pvr2_stream *); +struct pvr2_stream *pvr2_ioread_get_stream(struct pvr2_ioread *); +void pvr2_ioread_set_sync_key(struct pvr2_ioread *, + const char *sync_key_ptr, + unsigned int sync_key_len); +int pvr2_ioread_set_enabled(struct pvr2_ioread *,int fl); +int pvr2_ioread_read(struct pvr2_ioread *,void __user *buf,unsigned int cnt); +int pvr2_ioread_avail(struct pvr2_ioread *); + +#endif /* __PVRUSB2_IOREAD_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-main.c b/drivers/media/video/pvrusb2/pvrusb2-main.c new file mode 100644 index 000000000..e976c484c --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-main.c @@ -0,0 +1,171 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/smp_lock.h> +#include <linux/usb.h> +#include <linux/videodev2.h> + +#include "pvrusb2-hdw.h" +#include "pvrusb2-context.h" +#include "pvrusb2-debug.h" +#include "pvrusb2-v4l2.h" +#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS +#include "pvrusb2-sysfs.h" +#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ + +#define DRIVER_AUTHOR "Mike Isely <isely@pobox.com>" +#define DRIVER_DESC "Hauppauge WinTV-PVR-USB2 MPEG2 Encoder/Tuner" +#define DRIVER_VERSION "V4L in-tree version" + +#define DEFAULT_DEBUG_MASK (PVR2_TRACE_ERROR_LEGS| \ + PVR2_TRACE_INFO| \ + PVR2_TRACE_TOLERANCE| \ + PVR2_TRACE_TRAP| \ + 0) + +int pvrusb2_debug = DEFAULT_DEBUG_MASK; + +module_param_named(debug,pvrusb2_debug,int,S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(debug, "Debug trace mask"); + +#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS +static struct pvr2_sysfs_class *class_ptr = NULL; +#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ + +static void pvr_setup_attach(struct pvr2_context *pvr) +{ + /* Create association with v4l layer */ + pvr2_v4l2_create(pvr); +#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS + pvr2_sysfs_create(pvr,class_ptr); +#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ +} + +static int pvr_probe(struct usb_interface *intf, + const struct usb_device_id *devid) +{ + struct pvr2_context *pvr; + + /* Create underlying hardware interface */ + pvr = pvr2_context_create(intf,devid,pvr_setup_attach); + if (!pvr) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "Failed to create hdw handler"); + return -ENOMEM; + } + + pvr2_trace(PVR2_TRACE_INIT,"pvr_probe(pvr=%p)",pvr); + + usb_set_intfdata(intf, pvr); + + return 0; +} + +/* + * pvr_disconnect() + * + */ +static void pvr_disconnect(struct usb_interface *intf) +{ + struct pvr2_context *pvr = usb_get_intfdata(intf); + + pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) BEGIN",pvr); + + usb_set_intfdata (intf, NULL); + pvr2_context_disconnect(pvr); + + pvr2_trace(PVR2_TRACE_INIT,"pvr_disconnect(pvr=%p) DONE",pvr); + +} + +static struct usb_driver pvr_driver = { + .name = "pvrusb2", + .id_table = pvr2_device_table, + .probe = pvr_probe, + .disconnect = pvr_disconnect +}; + +/* + * pvr_init() / pvr_exit() + * + * This code is run to initialize/exit the driver. + * + */ +static int __init pvr_init(void) +{ + int ret; + + pvr2_trace(PVR2_TRACE_INIT,"pvr_init"); + +#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS + class_ptr = pvr2_sysfs_class_create(); +#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ + + ret = usb_register(&pvr_driver); + + if (ret == 0) + info(DRIVER_DESC " : " DRIVER_VERSION); + if (pvrusb2_debug) info("Debug mask is %d (0x%x)", + pvrusb2_debug,pvrusb2_debug); + + return ret; +} + +static void __exit pvr_exit(void) +{ + + pvr2_trace(PVR2_TRACE_INIT,"pvr_exit"); + +#ifdef CONFIG_VIDEO_PVRUSB2_SYSFS + pvr2_sysfs_class_destroy(class_ptr); +#endif /* CONFIG_VIDEO_PVRUSB2_SYSFS */ + + usb_deregister(&pvr_driver); +} + +module_init(pvr_init); +module_exit(pvr_exit); + +/* Mike Isely <mcisely@pobox.com> 11-Mar-2006: See pvrusb2-hdw.c for + MODULE_DEVICE_TABLE(). We have to declare that attribute there + because that's where the device table actually is now and it seems + that certain gcc configurations get angry if MODULE_DEVICE_TABLE() + is used on what ends up being an external symbol. */ +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.c b/drivers/media/video/pvrusb2/pvrusb2-std.c new file mode 100644 index 000000000..f95c598ff --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-std.c @@ -0,0 +1,408 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "pvrusb2-std.h" +#include "pvrusb2-debug.h" +#include <asm/string.h> +#include <linux/slab.h> + +struct std_name { + const char *name; + v4l2_std_id id; +}; + + +#define CSTD_PAL \ + (V4L2_STD_PAL_B| \ + V4L2_STD_PAL_B1| \ + V4L2_STD_PAL_G| \ + V4L2_STD_PAL_H| \ + V4L2_STD_PAL_I| \ + V4L2_STD_PAL_D| \ + V4L2_STD_PAL_D1| \ + V4L2_STD_PAL_K| \ + V4L2_STD_PAL_M| \ + V4L2_STD_PAL_N| \ + V4L2_STD_PAL_Nc| \ + V4L2_STD_PAL_60) + +#define CSTD_NTSC \ + (V4L2_STD_NTSC_M| \ + V4L2_STD_NTSC_M_JP| \ + V4L2_STD_NTSC_M_KR| \ + V4L2_STD_NTSC_443) + +#define CSTD_SECAM \ + (V4L2_STD_SECAM_B| \ + V4L2_STD_SECAM_D| \ + V4L2_STD_SECAM_G| \ + V4L2_STD_SECAM_H| \ + V4L2_STD_SECAM_K| \ + V4L2_STD_SECAM_K1| \ + V4L2_STD_SECAM_L| \ + V4L2_STD_SECAM_LC) + +#define TSTD_B (V4L2_STD_PAL_B|V4L2_STD_SECAM_B) +#define TSTD_B1 (V4L2_STD_PAL_B1) +#define TSTD_D (V4L2_STD_PAL_D|V4L2_STD_SECAM_D) +#define TSTD_D1 (V4L2_STD_PAL_D1) +#define TSTD_G (V4L2_STD_PAL_G|V4L2_STD_SECAM_G) +#define TSTD_H (V4L2_STD_PAL_H|V4L2_STD_SECAM_H) +#define TSTD_I (V4L2_STD_PAL_I) +#define TSTD_K (V4L2_STD_PAL_K|V4L2_STD_SECAM_K) +#define TSTD_K1 (V4L2_STD_SECAM_K1) +#define TSTD_L (V4L2_STD_SECAM_L) +#define TSTD_M (V4L2_STD_PAL_M|V4L2_STD_NTSC_M) +#define TSTD_N (V4L2_STD_PAL_N) +#define TSTD_Nc (V4L2_STD_PAL_Nc) +#define TSTD_60 (V4L2_STD_PAL_60) + +#define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_SECAM) + +/* Mapping of standard bits to color system */ +const static struct std_name std_groups[] = { + {"PAL",CSTD_PAL}, + {"NTSC",CSTD_NTSC}, + {"SECAM",CSTD_SECAM}, +}; + +/* Mapping of standard bits to modulation system */ +const static struct std_name std_items[] = { + {"B",TSTD_B}, + {"B1",TSTD_B1}, + {"D",TSTD_D}, + {"D1",TSTD_D1}, + {"G",TSTD_G}, + {"H",TSTD_H}, + {"I",TSTD_I}, + {"K",TSTD_K}, + {"K1",TSTD_K1}, + {"L",TSTD_L}, + {"LC",V4L2_STD_SECAM_LC}, + {"M",TSTD_M}, + {"Mj",V4L2_STD_NTSC_M_JP}, + {"443",V4L2_STD_NTSC_443}, + {"Mk",V4L2_STD_NTSC_M_KR}, + {"N",TSTD_N}, + {"Nc",TSTD_Nc}, + {"60",TSTD_60}, +}; + + +// Search an array of std_name structures and return a pointer to the +// element with the matching name. +static const struct std_name *find_std_name(const struct std_name *arrPtr, + unsigned int arrSize, + const char *bufPtr, + unsigned int bufSize) +{ + unsigned int idx; + const struct std_name *p; + for (idx = 0; idx < arrSize; idx++) { + p = arrPtr + idx; + if (strlen(p->name) != bufSize) continue; + if (!memcmp(bufPtr,p->name,bufSize)) return p; + } + return NULL; +} + + +int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr, + unsigned int bufSize) +{ + v4l2_std_id id = 0; + v4l2_std_id cmsk = 0; + v4l2_std_id t; + int mMode = 0; + unsigned int cnt; + char ch; + const struct std_name *sp; + + while (bufSize) { + if (!mMode) { + cnt = 0; + while ((cnt < bufSize) && (bufPtr[cnt] != '-')) cnt++; + if (cnt >= bufSize) return 0; // No more characters + sp = find_std_name( + std_groups, + sizeof(std_groups)/sizeof(std_groups[0]), + bufPtr,cnt); + if (!sp) return 0; // Illegal color system name + cnt++; + bufPtr += cnt; + bufSize -= cnt; + mMode = !0; + cmsk = sp->id; + continue; + } + cnt = 0; + while (cnt < bufSize) { + ch = bufPtr[cnt]; + if (ch == ';') { + mMode = 0; + break; + } + if (ch == '/') break; + cnt++; + } + sp = find_std_name(std_items, + sizeof(std_items)/sizeof(std_items[0]), + bufPtr,cnt); + if (!sp) return 0; // Illegal modulation system ID + t = sp->id & cmsk; + if (!t) return 0; // Specific color + modulation system illegal + id |= t; + if (cnt < bufSize) cnt++; + bufPtr += cnt; + bufSize -= cnt; + } + + if (idPtr) *idPtr = id; + return !0; +} + + +unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize, + v4l2_std_id id) +{ + unsigned int idx1,idx2; + const struct std_name *ip,*gp; + int gfl,cfl; + unsigned int c1,c2; + cfl = 0; + c1 = 0; + for (idx1 = 0; + idx1 < sizeof(std_groups)/sizeof(std_groups[0]); + idx1++) { + gp = std_groups + idx1; + gfl = 0; + for (idx2 = 0; + idx2 < sizeof(std_items)/sizeof(std_items[0]); + idx2++) { + ip = std_items + idx2; + if (!(gp->id & ip->id & id)) continue; + if (!gfl) { + if (cfl) { + c2 = scnprintf(bufPtr,bufSize,";"); + c1 += c2; + bufSize -= c2; + bufPtr += c2; + } + cfl = !0; + c2 = scnprintf(bufPtr,bufSize, + "%s-",gp->name); + gfl = !0; + } else { + c2 = scnprintf(bufPtr,bufSize,"/"); + } + c1 += c2; + bufSize -= c2; + bufPtr += c2; + c2 = scnprintf(bufPtr,bufSize, + ip->name); + c1 += c2; + bufSize -= c2; + bufPtr += c2; + } + } + return c1; +} + + +// Template data for possible enumerated video standards. Here we group +// standards which share common frame rates and resolution. +static struct v4l2_standard generic_standards[] = { + { + .id = (TSTD_B|TSTD_B1| + TSTD_D|TSTD_D1| + TSTD_G| + TSTD_H| + TSTD_I| + TSTD_K|TSTD_K1| + TSTD_L| + V4L2_STD_SECAM_LC | + TSTD_N|TSTD_Nc), + .frameperiod = + { + .numerator = 1, + .denominator= 25 + }, + .framelines = 625, + .reserved = {0,0,0,0} + }, { + .id = (TSTD_M| + V4L2_STD_NTSC_M_JP| + V4L2_STD_NTSC_M_KR), + .frameperiod = + { + .numerator = 1001, + .denominator= 30000 + }, + .framelines = 525, + .reserved = {0,0,0,0} + }, { // This is a total wild guess + .id = (TSTD_60), + .frameperiod = + { + .numerator = 1001, + .denominator= 30000 + }, + .framelines = 525, + .reserved = {0,0,0,0} + }, { // This is total wild guess + .id = V4L2_STD_NTSC_443, + .frameperiod = + { + .numerator = 1001, + .denominator= 30000 + }, + .framelines = 525, + .reserved = {0,0,0,0} + } +}; + +#define generic_standards_cnt (sizeof(generic_standards)/sizeof(generic_standards[0])) + +static struct v4l2_standard *match_std(v4l2_std_id id) +{ + unsigned int idx; + for (idx = 0; idx < generic_standards_cnt; idx++) { + if (generic_standards[idx].id & id) { + return generic_standards + idx; + } + } + return NULL; +} + +static int pvr2_std_fill(struct v4l2_standard *std,v4l2_std_id id) +{ + struct v4l2_standard *template; + int idx; + unsigned int bcnt; + template = match_std(id); + if (!template) return 0; + idx = std->index; + memcpy(std,template,sizeof(*template)); + std->index = idx; + std->id = id; + bcnt = pvr2_std_id_to_str(std->name,sizeof(std->name)-1,id); + std->name[bcnt] = 0; + pvr2_trace(PVR2_TRACE_INIT,"Set up standard idx=%u name=%s", + std->index,std->name); + return !0; +} + +/* These are special cases of combined standards that we should enumerate + separately if the component pieces are present. */ +static v4l2_std_id std_mixes[] = { + V4L2_STD_PAL_B | V4L2_STD_PAL_G, + V4L2_STD_PAL_D | V4L2_STD_PAL_K, + V4L2_STD_SECAM_B | V4L2_STD_SECAM_G, + V4L2_STD_SECAM_D | V4L2_STD_SECAM_K, +}; + +struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr, + v4l2_std_id id) +{ + unsigned int std_cnt = 0; + unsigned int idx,bcnt,idx2; + v4l2_std_id idmsk,cmsk,fmsk; + struct v4l2_standard *stddefs; + + if (pvrusb2_debug & PVR2_TRACE_INIT) { + char buf[50]; + bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id); + pvr2_trace( + PVR2_TRACE_INIT,"Mapping standards mask=0x%x (%.*s)", + (int)id,bcnt,buf); + } + + *countptr = 0; + std_cnt = 0; + fmsk = 0; + for (idmsk = 1, cmsk = id; cmsk; idmsk <<= 1) { + if (!(idmsk & cmsk)) continue; + cmsk &= ~idmsk; + if (match_std(idmsk)) { + std_cnt++; + continue; + } + fmsk |= idmsk; + } + + for (idx2 = 0; idx2 < sizeof(std_mixes)/sizeof(std_mixes[0]); idx2++) { + if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++; + } + + if (fmsk) { + char buf[50]; + bcnt = pvr2_std_id_to_str(buf,sizeof(buf),fmsk); + pvr2_trace( + PVR2_TRACE_ERROR_LEGS, + "WARNING:" + " Failed to classify the following standard(s): %.*s", + bcnt,buf); + } + + pvr2_trace(PVR2_TRACE_INIT,"Setting up %u unique standard(s)", + std_cnt); + if (!std_cnt) return NULL; // paranoia + + stddefs = kmalloc(sizeof(struct v4l2_standard) * std_cnt, + GFP_KERNEL); + memset(stddefs,0,sizeof(struct v4l2_standard) * std_cnt); + for (idx = 0; idx < std_cnt; idx++) stddefs[idx].index = idx; + + idx = 0; + + /* Enumerate potential special cases */ + for (idx2 = 0; ((idx2 < sizeof(std_mixes)/sizeof(std_mixes[0])) && + (idx < std_cnt)); idx2++) { + if (!(id & std_mixes[idx2])) continue; + if (pvr2_std_fill(stddefs+idx,std_mixes[idx2])) idx++; + } + /* Now enumerate individual pieces */ + for (idmsk = 1, cmsk = id; cmsk && (idx < std_cnt); idmsk <<= 1) { + if (!(idmsk & cmsk)) continue; + cmsk &= ~idmsk; + if (!pvr2_std_fill(stddefs+idx,idmsk)) continue; + idx++; + } + + *countptr = std_cnt; + return stddefs; +} + +v4l2_std_id pvr2_std_get_usable(void) +{ + return CSTD_ALL; +} + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-std.h b/drivers/media/video/pvrusb2/pvrusb2-std.h new file mode 100644 index 000000000..07c399375 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-std.h @@ -0,0 +1,60 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __PVRUSB2_STD_H +#define __PVRUSB2_STD_H + +#include <linux/videodev2.h> + +// Convert string describing one or more video standards into a mask of V4L +// standard bits. Return true if conversion succeeds otherwise return +// false. String is expected to be of the form: C1-x/y;C2-a/b where C1 and +// C2 are color system names (e.g. "PAL", "NTSC") and x, y, a, and b are +// modulation schemes (e.g. "M", "B", "G", etc). +int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr, + unsigned int bufSize); + +// Convert any arbitrary set of video standard bits into an unambiguous +// readable string. Return value is the number of bytes consumed in the +// buffer. The formatted string is of a form that can be parsed by our +// sibling std_std_to_id() function. +unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize, + v4l2_std_id id); + +// Create an array of suitable v4l2_standard structures given a bit mask of +// video standards to support. The array is allocated from the heap, and +// the number of elements is returned in the first argument. +struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr, + v4l2_std_id id); + +// Return mask of which video standard bits are valid +v4l2_std_id pvr2_std_get_usable(void); + +#endif /* __PVRUSB2_STD_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.c b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c new file mode 100644 index 000000000..38e9222dc --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.c @@ -0,0 +1,925 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/string.h> +#include <linux/slab.h> +#include <asm/semaphore.h> +#include "pvrusb2-sysfs.h" +#include "pvrusb2-hdw.h" +#include "pvrusb2-debug.h" +#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC +#include "pvrusb2-debugifc.h" +#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ + +#define pvr2_sysfs_trace(...) pvr2_trace(PVR2_TRACE_SYSFS,__VA_ARGS__) + +struct pvr2_sysfs { + struct pvr2_channel channel; + struct class_device *class_dev; +#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC + struct pvr2_sysfs_debugifc *debugifc; +#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ + struct pvr2_sysfs_ctl_item *item_first; + struct pvr2_sysfs_ctl_item *item_last; + struct sysfs_ops kops; + struct kobj_type ktype; + struct class_device_attribute attr_v4l_minor_number; + struct class_device_attribute attr_unit_number; + int v4l_minor_number_created_ok; + int unit_number_created_ok; +}; + +#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC +struct pvr2_sysfs_debugifc { + struct class_device_attribute attr_debugcmd; + struct class_device_attribute attr_debuginfo; + int debugcmd_created_ok; + int debuginfo_created_ok; +}; +#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ + +struct pvr2_sysfs_ctl_item { + struct class_device_attribute attr_name; + struct class_device_attribute attr_type; + struct class_device_attribute attr_min; + struct class_device_attribute attr_max; + struct class_device_attribute attr_enum; + struct class_device_attribute attr_bits; + struct class_device_attribute attr_val; + struct class_device_attribute attr_custom; + struct pvr2_ctrl *cptr; + struct pvr2_sysfs *chptr; + struct pvr2_sysfs_ctl_item *item_next; + struct attribute *attr_gen[7]; + struct attribute_group grp; + int created_ok; + char name[80]; +}; + +struct pvr2_sysfs_class { + struct class class; +}; + +static ssize_t show_name(int id,struct class_device *class_dev,char *buf) +{ + struct pvr2_ctrl *cptr; + struct pvr2_sysfs *sfp; + const char *name; + + sfp = (struct pvr2_sysfs *)class_dev->class_data; + if (!sfp) return -EINVAL; + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (!cptr) return -EINVAL; + + name = pvr2_ctrl_get_desc(cptr); + pvr2_sysfs_trace("pvr2_sysfs(%p) show_name(cid=%d) is %s",sfp,id,name); + + if (!name) return -EINVAL; + + return scnprintf(buf,PAGE_SIZE,"%s\n",name); +} + +static ssize_t show_type(int id,struct class_device *class_dev,char *buf) +{ + struct pvr2_ctrl *cptr; + struct pvr2_sysfs *sfp; + const char *name; + enum pvr2_ctl_type tp; + + sfp = (struct pvr2_sysfs *)class_dev->class_data; + if (!sfp) return -EINVAL; + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (!cptr) return -EINVAL; + + tp = pvr2_ctrl_get_type(cptr); + switch (tp) { + case pvr2_ctl_int: name = "integer"; break; + case pvr2_ctl_enum: name = "enum"; break; + case pvr2_ctl_bitmask: name = "bitmask"; break; + case pvr2_ctl_bool: name = "boolean"; break; + default: name = "?"; break; + } + pvr2_sysfs_trace("pvr2_sysfs(%p) show_type(cid=%d) is %s",sfp,id,name); + + if (!name) return -EINVAL; + + return scnprintf(buf,PAGE_SIZE,"%s\n",name); +} + +static ssize_t show_min(int id,struct class_device *class_dev,char *buf) +{ + struct pvr2_ctrl *cptr; + struct pvr2_sysfs *sfp; + long val; + + sfp = (struct pvr2_sysfs *)class_dev->class_data; + if (!sfp) return -EINVAL; + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (!cptr) return -EINVAL; + val = pvr2_ctrl_get_min(cptr); + + pvr2_sysfs_trace("pvr2_sysfs(%p) show_min(cid=%d) is %ld",sfp,id,val); + + return scnprintf(buf,PAGE_SIZE,"%ld\n",val); +} + +static ssize_t show_max(int id,struct class_device *class_dev,char *buf) +{ + struct pvr2_ctrl *cptr; + struct pvr2_sysfs *sfp; + long val; + + sfp = (struct pvr2_sysfs *)class_dev->class_data; + if (!sfp) return -EINVAL; + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (!cptr) return -EINVAL; + val = pvr2_ctrl_get_max(cptr); + + pvr2_sysfs_trace("pvr2_sysfs(%p) show_max(cid=%d) is %ld",sfp,id,val); + + return scnprintf(buf,PAGE_SIZE,"%ld\n",val); +} + +static ssize_t show_val_norm(int id,struct class_device *class_dev,char *buf) +{ + struct pvr2_ctrl *cptr; + struct pvr2_sysfs *sfp; + int val,ret; + unsigned int cnt = 0; + + sfp = (struct pvr2_sysfs *)class_dev->class_data; + if (!sfp) return -EINVAL; + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (!cptr) return -EINVAL; + + ret = pvr2_ctrl_get_value(cptr,&val); + if (ret < 0) return ret; + + ret = pvr2_ctrl_value_to_sym(cptr,~0,val, + buf,PAGE_SIZE-1,&cnt); + + pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_norm(cid=%d) is %.*s (%d)", + sfp,id,cnt,buf,val); + buf[cnt] = '\n'; + return cnt+1; +} + +static ssize_t show_val_custom(int id,struct class_device *class_dev,char *buf) +{ + struct pvr2_ctrl *cptr; + struct pvr2_sysfs *sfp; + int val,ret; + unsigned int cnt = 0; + + sfp = (struct pvr2_sysfs *)class_dev->class_data; + if (!sfp) return -EINVAL; + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (!cptr) return -EINVAL; + + ret = pvr2_ctrl_get_value(cptr,&val); + if (ret < 0) return ret; + + ret = pvr2_ctrl_custom_value_to_sym(cptr,~0,val, + buf,PAGE_SIZE-1,&cnt); + + pvr2_sysfs_trace("pvr2_sysfs(%p) show_val_custom(cid=%d) is %.*s (%d)", + sfp,id,cnt,buf,val); + buf[cnt] = '\n'; + return cnt+1; +} + +static ssize_t show_enum(int id,struct class_device *class_dev,char *buf) +{ + struct pvr2_ctrl *cptr; + struct pvr2_sysfs *sfp; + long val; + unsigned int bcnt,ccnt,ecnt; + + sfp = (struct pvr2_sysfs *)class_dev->class_data; + if (!sfp) return -EINVAL; + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (!cptr) return -EINVAL; + ecnt = pvr2_ctrl_get_cnt(cptr); + bcnt = 0; + for (val = 0; val < ecnt; val++) { + pvr2_ctrl_get_valname(cptr,val,buf+bcnt,PAGE_SIZE-bcnt,&ccnt); + if (!ccnt) continue; + bcnt += ccnt; + if (bcnt >= PAGE_SIZE) break; + buf[bcnt] = '\n'; + bcnt++; + } + pvr2_sysfs_trace("pvr2_sysfs(%p) show_enum(cid=%d)",sfp,id); + return bcnt; +} + +static ssize_t show_bits(int id,struct class_device *class_dev,char *buf) +{ + struct pvr2_ctrl *cptr; + struct pvr2_sysfs *sfp; + int valid_bits,msk; + unsigned int bcnt,ccnt; + + sfp = (struct pvr2_sysfs *)class_dev->class_data; + if (!sfp) return -EINVAL; + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (!cptr) return -EINVAL; + valid_bits = pvr2_ctrl_get_mask(cptr); + bcnt = 0; + for (msk = 1; valid_bits; msk <<= 1) { + if (!(msk & valid_bits)) continue; + valid_bits &= ~msk; + pvr2_ctrl_get_valname(cptr,msk,buf+bcnt,PAGE_SIZE-bcnt,&ccnt); + bcnt += ccnt; + if (bcnt >= PAGE_SIZE) break; + buf[bcnt] = '\n'; + bcnt++; + } + pvr2_sysfs_trace("pvr2_sysfs(%p) show_bits(cid=%d)",sfp,id); + return bcnt; +} + +static int store_val_any(int id,int customfl,struct pvr2_sysfs *sfp, + const char *buf,unsigned int count) +{ + struct pvr2_ctrl *cptr; + int ret; + int mask,val; + + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,id); + if (customfl) { + ret = pvr2_ctrl_custom_sym_to_value(cptr,buf,count,&mask,&val); + } else { + ret = pvr2_ctrl_sym_to_value(cptr,buf,count,&mask,&val); + } + if (ret < 0) return ret; + ret = pvr2_ctrl_set_mask_value(cptr,mask,val); + pvr2_hdw_commit_ctl(sfp->channel.hdw); + return ret; +} + +static ssize_t store_val_norm(int id,struct class_device *class_dev, + const char *buf,size_t count) +{ + struct pvr2_sysfs *sfp; + int ret; + sfp = (struct pvr2_sysfs *)class_dev->class_data; + ret = store_val_any(id,0,sfp,buf,count); + if (!ret) ret = count; + return ret; +} + +static ssize_t store_val_custom(int id,struct class_device *class_dev, + const char *buf,size_t count) +{ + struct pvr2_sysfs *sfp; + int ret; + sfp = (struct pvr2_sysfs *)class_dev->class_data; + ret = store_val_any(id,1,sfp,buf,count); + if (!ret) ret = count; + return ret; +} + +/* + Mike Isely <isely@pobox.com> 30-April-2005 + + This next batch of horrible preprocessor hackery is needed because the + kernel's class_device_attribute mechanism fails to pass the actual + attribute through to the show / store functions, which means we have no + way to package up any attribute-specific parameters, like for example the + control id. So we work around this brain-damage by encoding the control + id into the show / store functions themselves and pick the function based + on the control id we're setting up. These macros try to ease the pain. + Yuck. +*/ + +#define CREATE_SHOW_INSTANCE(sf_name,ctl_id) \ +static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,char *buf) \ +{ return sf_name(ctl_id,class_dev,buf); } + +#define CREATE_STORE_INSTANCE(sf_name,ctl_id) \ +static ssize_t sf_name##_##ctl_id(struct class_device *class_dev,const char *buf,size_t count) \ +{ return sf_name(ctl_id,class_dev,buf,count); } + +#define CREATE_BATCH(ctl_id) \ +CREATE_SHOW_INSTANCE(show_name,ctl_id) \ +CREATE_SHOW_INSTANCE(show_type,ctl_id) \ +CREATE_SHOW_INSTANCE(show_min,ctl_id) \ +CREATE_SHOW_INSTANCE(show_max,ctl_id) \ +CREATE_SHOW_INSTANCE(show_val_norm,ctl_id) \ +CREATE_SHOW_INSTANCE(show_val_custom,ctl_id) \ +CREATE_SHOW_INSTANCE(show_enum,ctl_id) \ +CREATE_SHOW_INSTANCE(show_bits,ctl_id) \ +CREATE_STORE_INSTANCE(store_val_norm,ctl_id) \ +CREATE_STORE_INSTANCE(store_val_custom,ctl_id) \ + +CREATE_BATCH(0) +CREATE_BATCH(1) +CREATE_BATCH(2) +CREATE_BATCH(3) +CREATE_BATCH(4) +CREATE_BATCH(5) +CREATE_BATCH(6) +CREATE_BATCH(7) +CREATE_BATCH(8) +CREATE_BATCH(9) +CREATE_BATCH(10) +CREATE_BATCH(11) +CREATE_BATCH(12) +CREATE_BATCH(13) +CREATE_BATCH(14) +CREATE_BATCH(15) +CREATE_BATCH(16) +CREATE_BATCH(17) +CREATE_BATCH(18) +CREATE_BATCH(19) +CREATE_BATCH(20) +CREATE_BATCH(21) +CREATE_BATCH(22) +CREATE_BATCH(23) +CREATE_BATCH(24) +CREATE_BATCH(25) +CREATE_BATCH(26) +CREATE_BATCH(27) +CREATE_BATCH(28) +CREATE_BATCH(29) +CREATE_BATCH(30) +CREATE_BATCH(31) +CREATE_BATCH(32) +CREATE_BATCH(33) +CREATE_BATCH(34) +CREATE_BATCH(35) +CREATE_BATCH(36) +CREATE_BATCH(37) +CREATE_BATCH(38) +CREATE_BATCH(39) +CREATE_BATCH(40) +CREATE_BATCH(41) +CREATE_BATCH(42) +CREATE_BATCH(43) +CREATE_BATCH(44) +CREATE_BATCH(45) +CREATE_BATCH(46) +CREATE_BATCH(47) +CREATE_BATCH(48) +CREATE_BATCH(49) +CREATE_BATCH(50) +CREATE_BATCH(51) +CREATE_BATCH(52) +CREATE_BATCH(53) +CREATE_BATCH(54) +CREATE_BATCH(55) +CREATE_BATCH(56) +CREATE_BATCH(57) +CREATE_BATCH(58) +CREATE_BATCH(59) + +struct pvr2_sysfs_func_set { + ssize_t (*show_name)(struct class_device *,char *); + ssize_t (*show_type)(struct class_device *,char *); + ssize_t (*show_min)(struct class_device *,char *); + ssize_t (*show_max)(struct class_device *,char *); + ssize_t (*show_enum)(struct class_device *,char *); + ssize_t (*show_bits)(struct class_device *,char *); + ssize_t (*show_val_norm)(struct class_device *,char *); + ssize_t (*store_val_norm)(struct class_device *, + const char *,size_t); + ssize_t (*show_val_custom)(struct class_device *,char *); + ssize_t (*store_val_custom)(struct class_device *, + const char *,size_t); +}; + +#define INIT_BATCH(ctl_id) \ +[ctl_id] = { \ + .show_name = show_name_##ctl_id, \ + .show_type = show_type_##ctl_id, \ + .show_min = show_min_##ctl_id, \ + .show_max = show_max_##ctl_id, \ + .show_enum = show_enum_##ctl_id, \ + .show_bits = show_bits_##ctl_id, \ + .show_val_norm = show_val_norm_##ctl_id, \ + .store_val_norm = store_val_norm_##ctl_id, \ + .show_val_custom = show_val_custom_##ctl_id, \ + .store_val_custom = store_val_custom_##ctl_id, \ +} \ + +static struct pvr2_sysfs_func_set funcs[] = { + INIT_BATCH(0), + INIT_BATCH(1), + INIT_BATCH(2), + INIT_BATCH(3), + INIT_BATCH(4), + INIT_BATCH(5), + INIT_BATCH(6), + INIT_BATCH(7), + INIT_BATCH(8), + INIT_BATCH(9), + INIT_BATCH(10), + INIT_BATCH(11), + INIT_BATCH(12), + INIT_BATCH(13), + INIT_BATCH(14), + INIT_BATCH(15), + INIT_BATCH(16), + INIT_BATCH(17), + INIT_BATCH(18), + INIT_BATCH(19), + INIT_BATCH(20), + INIT_BATCH(21), + INIT_BATCH(22), + INIT_BATCH(23), + INIT_BATCH(24), + INIT_BATCH(25), + INIT_BATCH(26), + INIT_BATCH(27), + INIT_BATCH(28), + INIT_BATCH(29), + INIT_BATCH(30), + INIT_BATCH(31), + INIT_BATCH(32), + INIT_BATCH(33), + INIT_BATCH(34), + INIT_BATCH(35), + INIT_BATCH(36), + INIT_BATCH(37), + INIT_BATCH(38), + INIT_BATCH(39), + INIT_BATCH(40), + INIT_BATCH(41), + INIT_BATCH(42), + INIT_BATCH(43), + INIT_BATCH(44), + INIT_BATCH(45), + INIT_BATCH(46), + INIT_BATCH(47), + INIT_BATCH(48), + INIT_BATCH(49), + INIT_BATCH(50), + INIT_BATCH(51), + INIT_BATCH(52), + INIT_BATCH(53), + INIT_BATCH(54), + INIT_BATCH(55), + INIT_BATCH(56), + INIT_BATCH(57), + INIT_BATCH(58), + INIT_BATCH(59), +}; + + +static void pvr2_sysfs_add_control(struct pvr2_sysfs *sfp,int ctl_id) +{ + struct pvr2_sysfs_ctl_item *cip; + struct pvr2_sysfs_func_set *fp; + struct pvr2_ctrl *cptr; + unsigned int cnt,acnt; + int ret; + + if ((ctl_id < 0) || (ctl_id >= (sizeof(funcs)/sizeof(funcs[0])))) { + return; + } + + fp = funcs + ctl_id; + cptr = pvr2_hdw_get_ctrl_by_index(sfp->channel.hdw,ctl_id); + if (!cptr) return; + + cip = kmalloc(sizeof(*cip),GFP_KERNEL); + if (!cip) return; + memset(cip,0,sizeof(*cip)); + pvr2_sysfs_trace("Creating pvr2_sysfs_ctl_item id=%p",cip); + + cip->cptr = cptr; + + cip->chptr = sfp; + cip->item_next = NULL; + if (sfp->item_last) { + sfp->item_last->item_next = cip; + } else { + sfp->item_first = cip; + } + sfp->item_last = cip; + + cip->attr_name.attr.owner = THIS_MODULE; + cip->attr_name.attr.name = "name"; + cip->attr_name.attr.mode = S_IRUGO; + cip->attr_name.show = fp->show_name; + + cip->attr_type.attr.owner = THIS_MODULE; + cip->attr_type.attr.name = "type"; + cip->attr_type.attr.mode = S_IRUGO; + cip->attr_type.show = fp->show_type; + + cip->attr_min.attr.owner = THIS_MODULE; + cip->attr_min.attr.name = "min_val"; + cip->attr_min.attr.mode = S_IRUGO; + cip->attr_min.show = fp->show_min; + + cip->attr_max.attr.owner = THIS_MODULE; + cip->attr_max.attr.name = "max_val"; + cip->attr_max.attr.mode = S_IRUGO; + cip->attr_max.show = fp->show_max; + + cip->attr_val.attr.owner = THIS_MODULE; + cip->attr_val.attr.name = "cur_val"; + cip->attr_val.attr.mode = S_IRUGO; + + cip->attr_custom.attr.owner = THIS_MODULE; + cip->attr_custom.attr.name = "custom_val"; + cip->attr_custom.attr.mode = S_IRUGO; + + cip->attr_enum.attr.owner = THIS_MODULE; + cip->attr_enum.attr.name = "enum_val"; + cip->attr_enum.attr.mode = S_IRUGO; + cip->attr_enum.show = fp->show_enum; + + cip->attr_bits.attr.owner = THIS_MODULE; + cip->attr_bits.attr.name = "bit_val"; + cip->attr_bits.attr.mode = S_IRUGO; + cip->attr_bits.show = fp->show_bits; + + if (pvr2_ctrl_is_writable(cptr)) { + cip->attr_val.attr.mode |= S_IWUSR|S_IWGRP; + cip->attr_custom.attr.mode |= S_IWUSR|S_IWGRP; + } + + acnt = 0; + cip->attr_gen[acnt++] = &cip->attr_name.attr; + cip->attr_gen[acnt++] = &cip->attr_type.attr; + cip->attr_gen[acnt++] = &cip->attr_val.attr; + cip->attr_val.show = fp->show_val_norm; + cip->attr_val.store = fp->store_val_norm; + if (pvr2_ctrl_has_custom_symbols(cptr)) { + cip->attr_gen[acnt++] = &cip->attr_custom.attr; + cip->attr_custom.show = fp->show_val_custom; + cip->attr_custom.store = fp->store_val_custom; + } + switch (pvr2_ctrl_get_type(cptr)) { + case pvr2_ctl_enum: + // Control is an enumeration + cip->attr_gen[acnt++] = &cip->attr_enum.attr; + break; + case pvr2_ctl_int: + // Control is an integer + cip->attr_gen[acnt++] = &cip->attr_min.attr; + cip->attr_gen[acnt++] = &cip->attr_max.attr; + break; + case pvr2_ctl_bitmask: + // Control is an bitmask + cip->attr_gen[acnt++] = &cip->attr_bits.attr; + break; + default: break; + } + + cnt = scnprintf(cip->name,sizeof(cip->name)-1,"ctl_%s", + pvr2_ctrl_get_name(cptr)); + cip->name[cnt] = 0; + cip->grp.name = cip->name; + cip->grp.attrs = cip->attr_gen; + + ret = sysfs_create_group(&sfp->class_dev->kobj,&cip->grp); + if (ret) { + printk(KERN_WARNING "%s: sysfs_create_group error: %d\n", + __FUNCTION__, ret); + return; + } + cip->created_ok = !0; +} + +#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC +static ssize_t debuginfo_show(struct class_device *,char *); +static ssize_t debugcmd_show(struct class_device *,char *); +static ssize_t debugcmd_store(struct class_device *,const char *,size_t count); + +static void pvr2_sysfs_add_debugifc(struct pvr2_sysfs *sfp) +{ + struct pvr2_sysfs_debugifc *dip; + int ret; + + dip = kmalloc(sizeof(*dip),GFP_KERNEL); + if (!dip) return; + memset(dip,0,sizeof(*dip)); + dip->attr_debugcmd.attr.owner = THIS_MODULE; + dip->attr_debugcmd.attr.name = "debugcmd"; + dip->attr_debugcmd.attr.mode = S_IRUGO|S_IWUSR|S_IWGRP; + dip->attr_debugcmd.show = debugcmd_show; + dip->attr_debugcmd.store = debugcmd_store; + dip->attr_debuginfo.attr.owner = THIS_MODULE; + dip->attr_debuginfo.attr.name = "debuginfo"; + dip->attr_debuginfo.attr.mode = S_IRUGO; + dip->attr_debuginfo.show = debuginfo_show; + sfp->debugifc = dip; + ret = class_device_create_file(sfp->class_dev,&dip->attr_debugcmd); + if (ret < 0) { + printk(KERN_WARNING "%s: class_device_create_file error: %d\n", + __FUNCTION__, ret); + } else { + dip->debugcmd_created_ok = !0; + } + ret = class_device_create_file(sfp->class_dev,&dip->attr_debuginfo); + if (ret < 0) { + printk(KERN_WARNING "%s: class_device_create_file error: %d\n", + __FUNCTION__, ret); + } else { + dip->debuginfo_created_ok = !0; + } +} + + +static void pvr2_sysfs_tear_down_debugifc(struct pvr2_sysfs *sfp) +{ + if (!sfp->debugifc) return; + if (sfp->debugifc->debuginfo_created_ok) { + class_device_remove_file(sfp->class_dev, + &sfp->debugifc->attr_debuginfo); + } + if (sfp->debugifc->debugcmd_created_ok) { + class_device_remove_file(sfp->class_dev, + &sfp->debugifc->attr_debugcmd); + } + kfree(sfp->debugifc); + sfp->debugifc = NULL; +} +#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ + + +static void pvr2_sysfs_add_controls(struct pvr2_sysfs *sfp) +{ + unsigned int idx,cnt; + cnt = pvr2_hdw_get_ctrl_count(sfp->channel.hdw); + for (idx = 0; idx < cnt; idx++) { + pvr2_sysfs_add_control(sfp,idx); + } +} + + +static void pvr2_sysfs_tear_down_controls(struct pvr2_sysfs *sfp) +{ + struct pvr2_sysfs_ctl_item *cip1,*cip2; + for (cip1 = sfp->item_first; cip1; cip1 = cip2) { + cip2 = cip1->item_next; + if (cip1->created_ok) { + sysfs_remove_group(&sfp->class_dev->kobj,&cip1->grp); + } + pvr2_sysfs_trace("Destroying pvr2_sysfs_ctl_item id=%p",cip1); + kfree(cip1); + } +} + + +static void pvr2_sysfs_class_release(struct class *class) +{ + struct pvr2_sysfs_class *clp; + clp = container_of(class,struct pvr2_sysfs_class,class); + pvr2_sysfs_trace("Destroying pvr2_sysfs_class id=%p",clp); + kfree(clp); +} + + +static void pvr2_sysfs_release(struct class_device *class_dev) +{ + pvr2_sysfs_trace("Releasing class_dev id=%p",class_dev); + kfree(class_dev); +} + + +static void class_dev_destroy(struct pvr2_sysfs *sfp) +{ + if (!sfp->class_dev) return; +#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC + pvr2_sysfs_tear_down_debugifc(sfp); +#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ + pvr2_sysfs_tear_down_controls(sfp); + if (sfp->v4l_minor_number_created_ok) { + class_device_remove_file(sfp->class_dev, + &sfp->attr_v4l_minor_number); + } + if (sfp->unit_number_created_ok) { + class_device_remove_file(sfp->class_dev, + &sfp->attr_unit_number); + } + pvr2_sysfs_trace("Destroying class_dev id=%p",sfp->class_dev); + sfp->class_dev->class_data = NULL; + class_device_unregister(sfp->class_dev); + sfp->class_dev = NULL; +} + + +static ssize_t v4l_minor_number_show(struct class_device *class_dev,char *buf) +{ + struct pvr2_sysfs *sfp; + sfp = (struct pvr2_sysfs *)class_dev->class_data; + if (!sfp) return -EINVAL; + return scnprintf(buf,PAGE_SIZE,"%d\n", + pvr2_hdw_v4l_get_minor_number(sfp->channel.hdw)); +} + + +static ssize_t unit_number_show(struct class_device *class_dev,char *buf) +{ + struct pvr2_sysfs *sfp; + sfp = (struct pvr2_sysfs *)class_dev->class_data; + if (!sfp) return -EINVAL; + return scnprintf(buf,PAGE_SIZE,"%d\n", + pvr2_hdw_get_unit_number(sfp->channel.hdw)); +} + + +static void class_dev_create(struct pvr2_sysfs *sfp, + struct pvr2_sysfs_class *class_ptr) +{ + struct usb_device *usb_dev; + struct class_device *class_dev; + int ret; + + usb_dev = pvr2_hdw_get_dev(sfp->channel.hdw); + if (!usb_dev) return; + class_dev = kmalloc(sizeof(*class_dev),GFP_KERNEL); + if (!class_dev) return; + memset(class_dev,0,sizeof(*class_dev)); + + pvr2_sysfs_trace("Creating class_dev id=%p",class_dev); + + class_dev->class = &class_ptr->class; + if (pvr2_hdw_get_sn(sfp->channel.hdw)) { + snprintf(class_dev->class_id,BUS_ID_SIZE,"sn-%lu", + pvr2_hdw_get_sn(sfp->channel.hdw)); + } else if (pvr2_hdw_get_unit_number(sfp->channel.hdw) >= 0) { + snprintf(class_dev->class_id,BUS_ID_SIZE,"unit-%c", + pvr2_hdw_get_unit_number(sfp->channel.hdw) + 'a'); + } else { + kfree(class_dev); + return; + } + + class_dev->dev = &usb_dev->dev; + + sfp->class_dev = class_dev; + class_dev->class_data = sfp; + ret = class_device_register(class_dev); + if (ret) { + printk(KERN_ERR "%s: class_device_register failed\n", + __FUNCTION__); + kfree(class_dev); + return; + } + + sfp->attr_v4l_minor_number.attr.owner = THIS_MODULE; + sfp->attr_v4l_minor_number.attr.name = "v4l_minor_number"; + sfp->attr_v4l_minor_number.attr.mode = S_IRUGO; + sfp->attr_v4l_minor_number.show = v4l_minor_number_show; + sfp->attr_v4l_minor_number.store = NULL; + ret = class_device_create_file(sfp->class_dev, + &sfp->attr_v4l_minor_number); + if (ret < 0) { + printk(KERN_WARNING "%s: class_device_create_file error: %d\n", + __FUNCTION__, ret); + } else { + sfp->v4l_minor_number_created_ok = !0; + } + + sfp->attr_unit_number.attr.owner = THIS_MODULE; + sfp->attr_unit_number.attr.name = "unit_number"; + sfp->attr_unit_number.attr.mode = S_IRUGO; + sfp->attr_unit_number.show = unit_number_show; + sfp->attr_unit_number.store = NULL; + ret = class_device_create_file(sfp->class_dev,&sfp->attr_unit_number); + if (ret < 0) { + printk(KERN_WARNING "%s: class_device_create_file error: %d\n", + __FUNCTION__, ret); + } else { + sfp->unit_number_created_ok = !0; + } + + pvr2_sysfs_add_controls(sfp); +#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC + pvr2_sysfs_add_debugifc(sfp); +#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ +} + + +static void pvr2_sysfs_internal_check(struct pvr2_channel *chp) +{ + struct pvr2_sysfs *sfp; + sfp = container_of(chp,struct pvr2_sysfs,channel); + if (!sfp->channel.mc_head->disconnect_flag) return; + pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_sysfs id=%p",sfp); + class_dev_destroy(sfp); + pvr2_channel_done(&sfp->channel); + kfree(sfp); +} + + +struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *mp, + struct pvr2_sysfs_class *class_ptr) +{ + struct pvr2_sysfs *sfp; + sfp = kmalloc(sizeof(*sfp),GFP_KERNEL); + if (!sfp) return sfp; + memset(sfp,0,sizeof(*sfp)); + pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_sysfs id=%p",sfp); + pvr2_channel_init(&sfp->channel,mp); + sfp->channel.check_func = pvr2_sysfs_internal_check; + + class_dev_create(sfp,class_ptr); + return sfp; +} + + +static int pvr2_sysfs_hotplug(struct class_device *cd,char **envp, + int numenvp,char *buf,int size) +{ + /* Even though we don't do anything here, we still need this function + because sysfs will still try to call it. */ + return 0; +} + +struct pvr2_sysfs_class *pvr2_sysfs_class_create(void) +{ + struct pvr2_sysfs_class *clp; + clp = kmalloc(sizeof(*clp),GFP_KERNEL); + if (!clp) return clp; + memset(clp,0,sizeof(*clp)); + pvr2_sysfs_trace("Creating pvr2_sysfs_class id=%p",clp); + clp->class.name = "pvrusb2"; + clp->class.class_release = pvr2_sysfs_class_release; + clp->class.release = pvr2_sysfs_release; + clp->class.uevent = pvr2_sysfs_hotplug; + if (class_register(&clp->class)) { + pvr2_sysfs_trace( + "Registration failed for pvr2_sysfs_class id=%p",clp); + kfree(clp); + clp = NULL; + } + return clp; +} + + +void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *clp) +{ + class_unregister(&clp->class); +} + + +#ifdef CONFIG_VIDEO_PVRUSB2_DEBUGIFC +static ssize_t debuginfo_show(struct class_device *class_dev,char *buf) +{ + struct pvr2_sysfs *sfp; + sfp = (struct pvr2_sysfs *)class_dev->class_data; + if (!sfp) return -EINVAL; + pvr2_hdw_trigger_module_log(sfp->channel.hdw); + return pvr2_debugifc_print_info(sfp->channel.hdw,buf,PAGE_SIZE); +} + + +static ssize_t debugcmd_show(struct class_device *class_dev,char *buf) +{ + struct pvr2_sysfs *sfp; + sfp = (struct pvr2_sysfs *)class_dev->class_data; + if (!sfp) return -EINVAL; + return pvr2_debugifc_print_status(sfp->channel.hdw,buf,PAGE_SIZE); +} + + +static ssize_t debugcmd_store(struct class_device *class_dev, + const char *buf,size_t count) +{ + struct pvr2_sysfs *sfp; + int ret; + + sfp = (struct pvr2_sysfs *)class_dev->class_data; + if (!sfp) return -EINVAL; + + ret = pvr2_debugifc_docmd(sfp->channel.hdw,buf,count); + if (ret < 0) return ret; + return count; +} +#endif /* CONFIG_VIDEO_PVRUSB2_DEBUGIFC */ + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-sysfs.h b/drivers/media/video/pvrusb2/pvrusb2-sysfs.h new file mode 100644 index 000000000..ff9373b47 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-sysfs.h @@ -0,0 +1,47 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __PVRUSB2_SYSFS_H +#define __PVRUSB2_SYSFS_H + +#include <linux/list.h> +#include <linux/sysfs.h> +#include "pvrusb2-context.h" + +struct pvr2_sysfs; +struct pvr2_sysfs_class; + +struct pvr2_sysfs_class *pvr2_sysfs_class_create(void); +void pvr2_sysfs_class_destroy(struct pvr2_sysfs_class *); + +struct pvr2_sysfs *pvr2_sysfs_create(struct pvr2_context *, + struct pvr2_sysfs_class *); + +#endif /* __PVRUSB2_SYSFS_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.c b/drivers/media/video/pvrusb2/pvrusb2-tuner.c new file mode 100644 index 000000000..af9f246f8 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-tuner.c @@ -0,0 +1,122 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "pvrusb2.h" +#include "pvrusb2-util.h" +#include "pvrusb2-tuner.h" +#include "pvrusb2-hdw-internal.h" +#include "pvrusb2-debug.h" +#include <linux/videodev2.h> +#include <media/tuner.h> +#include <media/v4l2-common.h> + +struct pvr2_tuner_handler { + struct pvr2_hdw *hdw; + struct pvr2_i2c_client *client; + struct pvr2_i2c_handler i2c_handler; + int type_update_fl; +}; + + +static void set_type(struct pvr2_tuner_handler *ctxt) +{ + struct pvr2_hdw *hdw = ctxt->hdw; + struct tuner_setup setup; + pvr2_trace(PVR2_TRACE_CHIPS,"i2c tuner set_type(%d)",hdw->tuner_type); + if (((int)(hdw->tuner_type)) < 0) return; + + setup.addr = ADDR_UNSET; + setup.type = hdw->tuner_type; + setup.mode_mask = T_RADIO | T_ANALOG_TV; + /* We may really want mode_mask to be T_ANALOG_TV for now */ + pvr2_i2c_client_cmd(ctxt->client,TUNER_SET_TYPE_ADDR,&setup); + ctxt->type_update_fl = 0; +} + + +static int tuner_check(struct pvr2_tuner_handler *ctxt) +{ + struct pvr2_hdw *hdw = ctxt->hdw; + if (hdw->tuner_updated) ctxt->type_update_fl = !0; + return ctxt->type_update_fl != 0; +} + + +static void tuner_update(struct pvr2_tuner_handler *ctxt) +{ + if (ctxt->type_update_fl) set_type(ctxt); +} + + +static void pvr2_tuner_detach(struct pvr2_tuner_handler *ctxt) +{ + ctxt->client->handler = NULL; + kfree(ctxt); +} + + +static unsigned int pvr2_tuner_describe(struct pvr2_tuner_handler *ctxt,char *buf,unsigned int cnt) +{ + return scnprintf(buf,cnt,"handler: pvrusb2-tuner"); +} + + +const static struct pvr2_i2c_handler_functions tuner_funcs = { + .detach = (void (*)(void *))pvr2_tuner_detach, + .check = (int (*)(void *))tuner_check, + .update = (void (*)(void *))tuner_update, + .describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_tuner_describe, +}; + + +int pvr2_i2c_tuner_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) +{ + struct pvr2_tuner_handler *ctxt; + if (cp->handler) return 0; + + ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL); + if (!ctxt) return 0; + memset(ctxt,0,sizeof(*ctxt)); + + ctxt->i2c_handler.func_data = ctxt; + ctxt->i2c_handler.func_table = &tuner_funcs; + ctxt->type_update_fl = !0; + ctxt->client = cp; + ctxt->hdw = hdw; + cp->handler = &ctxt->i2c_handler; + pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x tuner handler set up", + cp->client->addr); + return !0; +} + + + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-tuner.h b/drivers/media/video/pvrusb2/pvrusb2-tuner.h new file mode 100644 index 000000000..556f12aa9 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-tuner.h @@ -0,0 +1,38 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __PVRUSB2_TUNER_H +#define __PVRUSB2_TUNER_H + +#include "pvrusb2-i2c-core.h" + +int pvr2_i2c_tuner_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); + +#endif /* __PVRUSB2_TUNER_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-util.h b/drivers/media/video/pvrusb2/pvrusb2-util.h new file mode 100644 index 000000000..e53aee416 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-util.h @@ -0,0 +1,63 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __PVRUSB2_UTIL_H +#define __PVRUSB2_UTIL_H + +#define PVR2_DECOMPOSE_LE(t,i,d) \ + do { \ + (t)[i] = (d) & 0xff;\ + (t)[i+1] = ((d) >> 8) & 0xff;\ + (t)[i+2] = ((d) >> 16) & 0xff;\ + (t)[i+3] = ((d) >> 24) & 0xff;\ + } while(0) + +#define PVR2_DECOMPOSE_BE(t,i,d) \ + do { \ + (t)[i+3] = (d) & 0xff;\ + (t)[i+2] = ((d) >> 8) & 0xff;\ + (t)[i+1] = ((d) >> 16) & 0xff;\ + (t)[i] = ((d) >> 24) & 0xff;\ + } while(0) + +#define PVR2_COMPOSE_LE(t,i) \ + ((((u32)((t)[i+3])) << 24) | \ + (((u32)((t)[i+2])) << 16) | \ + (((u32)((t)[i+1])) << 8) | \ + ((u32)((t)[i]))) + +#define PVR2_COMPOSE_BE(t,i) \ + ((((u32)((t)[i])) << 24) | \ + (((u32)((t)[i+1])) << 16) | \ + (((u32)((t)[i+2])) << 8) | \ + ((u32)((t)[i+3]))) + + +#endif /* __PVRUSB2_UTIL_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c new file mode 100644 index 000000000..72f444cf3 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -0,0 +1,1087 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/kernel.h> +#include <linux/version.h> +#include <linux/videodev.h> +#include "pvrusb2-context.h" +#include "pvrusb2-hdw.h" +#include "pvrusb2.h" +#include "pvrusb2-debug.h" +#include "pvrusb2-v4l2.h" +#include "pvrusb2-ioread.h" +#include <linux/videodev2.h> +#include <media/v4l2-common.h> + +/* Mike Isely <isely@pobox.com> 23-Sep-2006 - This function is prototyped + * only for V4L1 but is implemented regardless of the V4L1 compatibility + * option state. V4L2 has no replacement for this and we need it. For now + * copy the prototype here so we can avoid the compiler warning. */ +extern struct video_device* video_devdata(struct file*); + +struct pvr2_v4l2_dev; +struct pvr2_v4l2_fh; +struct pvr2_v4l2; + + +struct pvr2_v4l2_dev { + struct pvr2_v4l2 *v4lp; + struct video_device *vdev; + struct pvr2_context_stream *stream; + enum pvr2_config config; +}; + +struct pvr2_v4l2_fh { + struct pvr2_channel channel; + struct pvr2_v4l2_dev *dev_info; + enum v4l2_priority prio; + struct pvr2_ioread *rhp; + struct file *file; + struct pvr2_v4l2 *vhead; + struct pvr2_v4l2_fh *vnext; + struct pvr2_v4l2_fh *vprev; + wait_queue_head_t wait_data; + int fw_mode_flag; +}; + +struct pvr2_v4l2 { + struct pvr2_channel channel; + struct pvr2_v4l2_fh *vfirst; + struct pvr2_v4l2_fh *vlast; + + struct v4l2_prio_state prio; + + /* streams */ + struct pvr2_v4l2_dev video_dev; +}; + +static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1}; +module_param_array(video_nr, int, NULL, 0444); +MODULE_PARM_DESC(video_nr, "Offset for device's minor"); + +static struct v4l2_capability pvr_capability ={ + .driver = "pvrusb2", + .card = "Hauppauge WinTV pvr-usb2", + .bus_info = "usb", + .version = KERNEL_VERSION(0,8,0), + .capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE | + V4L2_CAP_TUNER | V4L2_CAP_AUDIO | + V4L2_CAP_READWRITE), + .reserved = {0,0,0,0} +}; + +static struct v4l2_tuner pvr_v4l2_tuners[]= { + { + .index = 0, + .name = "TV Tuner", + .type = V4L2_TUNER_ANALOG_TV, + .capability = (V4L2_TUNER_CAP_NORM | + V4L2_TUNER_CAP_STEREO | + V4L2_TUNER_CAP_LANG1 | + V4L2_TUNER_CAP_LANG2), + .rangelow = 0, + .rangehigh = 0, + .rxsubchans = V4L2_TUNER_SUB_STEREO, + .audmode = V4L2_TUNER_MODE_STEREO, + .signal = 0, + .afc = 0, + .reserved = {0,0,0,0} + } +}; + +static struct v4l2_fmtdesc pvr_fmtdesc [] = { + { + .index = 0, + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .flags = V4L2_FMT_FLAG_COMPRESSED, + .description = "MPEG1/2", + // This should really be V4L2_PIX_FMT_MPEG, but xawtv + // breaks when I do that. + .pixelformat = 0, // V4L2_PIX_FMT_MPEG, + .reserved = { 0, 0, 0, 0 } + } +}; + +#define PVR_FORMAT_PIX 0 +#define PVR_FORMAT_VBI 1 + +static struct v4l2_format pvr_format [] = { + [PVR_FORMAT_PIX] = { + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, + .fmt = { + .pix = { + .width = 720, + .height = 576, + // This should really be V4L2_PIX_FMT_MPEG, + // but xawtv breaks when I do that. + .pixelformat = 0, // V4L2_PIX_FMT_MPEG, + .field = V4L2_FIELD_INTERLACED, + .bytesperline = 0, // doesn't make sense + // here + //FIXME : Don't know what to put here... + .sizeimage = (32*1024), + .colorspace = 0, // doesn't make sense here + .priv = 0 + } + } + }, + [PVR_FORMAT_VBI] = { + .type = V4L2_BUF_TYPE_VBI_CAPTURE, + .fmt = { + .vbi = { + .sampling_rate = 27000000, + .offset = 248, + .samples_per_line = 1443, + .sample_format = V4L2_PIX_FMT_GREY, + .start = { 0, 0 }, + .count = { 0, 0 }, + .flags = 0, + .reserved = { 0, 0 } + } + } + } +}; + +/* + * pvr_ioctl() + * + * This is part of Video 4 Linux API. The procedure handles ioctl() calls. + * + */ +static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + struct pvr2_v4l2_fh *fh = file->private_data; + struct pvr2_v4l2 *vp = fh->vhead; + struct pvr2_v4l2_dev *dev_info = fh->dev_info; + struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; + int ret = -EINVAL; + + if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { + v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd); + } + + if (!pvr2_hdw_dev_ok(hdw)) { + pvr2_trace(PVR2_TRACE_ERROR_LEGS, + "ioctl failed - bad or no context"); + return -EFAULT; + } + + /* check priority */ + switch (cmd) { + case VIDIOC_S_CTRL: + case VIDIOC_S_STD: + case VIDIOC_S_INPUT: + case VIDIOC_S_TUNER: + case VIDIOC_S_FREQUENCY: + ret = v4l2_prio_check(&vp->prio, &fh->prio); + if (ret) + return ret; + } + + switch (cmd) { + case VIDIOC_QUERYCAP: + { + struct v4l2_capability *cap = arg; + + memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability)); + + ret = 0; + break; + } + + case VIDIOC_G_PRIORITY: + { + enum v4l2_priority *p = arg; + + *p = v4l2_prio_max(&vp->prio); + ret = 0; + break; + } + + case VIDIOC_S_PRIORITY: + { + enum v4l2_priority *prio = arg; + + ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio); + break; + } + + case VIDIOC_ENUMSTD: + { + struct v4l2_standard *vs = (struct v4l2_standard *)arg; + int idx = vs->index; + ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1); + break; + } + + case VIDIOC_G_STD: + { + int val = 0; + ret = pvr2_ctrl_get_value( + pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val); + *(v4l2_std_id *)arg = val; + break; + } + + case VIDIOC_S_STD: + { + ret = pvr2_ctrl_set_value( + pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR), + *(v4l2_std_id *)arg); + break; + } + + case VIDIOC_ENUMINPUT: + { + struct pvr2_ctrl *cptr; + struct v4l2_input *vi = (struct v4l2_input *)arg; + struct v4l2_input tmp; + unsigned int cnt; + + cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); + + memset(&tmp,0,sizeof(tmp)); + tmp.index = vi->index; + ret = 0; + switch (vi->index) { + case PVR2_CVAL_INPUT_TV: + case PVR2_CVAL_INPUT_RADIO: + tmp.type = V4L2_INPUT_TYPE_TUNER; + break; + case PVR2_CVAL_INPUT_SVIDEO: + case PVR2_CVAL_INPUT_COMPOSITE: + tmp.type = V4L2_INPUT_TYPE_CAMERA; + break; + default: + ret = -EINVAL; + break; + } + if (ret < 0) break; + + cnt = 0; + pvr2_ctrl_get_valname(cptr,vi->index, + tmp.name,sizeof(tmp.name)-1,&cnt); + tmp.name[cnt] = 0; + + /* Don't bother with audioset, since this driver currently + always switches the audio whenever the video is + switched. */ + + /* Handling std is a tougher problem. It doesn't make + sense in cases where a device might be multi-standard. + We could just copy out the current value for the + standard, but it can change over time. For now just + leave it zero. */ + + memcpy(vi, &tmp, sizeof(tmp)); + + ret = 0; + break; + } + + case VIDIOC_G_INPUT: + { + struct pvr2_ctrl *cptr; + struct v4l2_input *vi = (struct v4l2_input *)arg; + int val; + cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT); + val = 0; + ret = pvr2_ctrl_get_value(cptr,&val); + vi->index = val; + break; + } + + case VIDIOC_S_INPUT: + { + struct v4l2_input *vi = (struct v4l2_input *)arg; + ret = pvr2_ctrl_set_value( + pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), + vi->index); + break; + } + + case VIDIOC_ENUMAUDIO: + { + ret = -EINVAL; + break; + } + + case VIDIOC_G_AUDIO: + { + ret = -EINVAL; + break; + } + + case VIDIOC_S_AUDIO: + { + ret = -EINVAL; + break; + } + case VIDIOC_G_TUNER: + { + struct v4l2_tuner *vt = (struct v4l2_tuner *)arg; + unsigned int status_mask; + int val; + if (vt->index !=0) break; + + status_mask = pvr2_hdw_get_signal_status(hdw); + + memcpy(vt, &pvr_v4l2_tuners[vt->index], + sizeof(struct v4l2_tuner)); + + vt->signal = 0; + if (status_mask & PVR2_SIGNAL_OK) { + if (status_mask & PVR2_SIGNAL_STEREO) { + vt->rxsubchans = V4L2_TUNER_SUB_STEREO; + } else { + vt->rxsubchans = V4L2_TUNER_SUB_MONO; + } + if (status_mask & PVR2_SIGNAL_SAP) { + vt->rxsubchans |= (V4L2_TUNER_SUB_LANG1 | + V4L2_TUNER_SUB_LANG2); + } + vt->signal = 65535; + } + + val = 0; + ret = pvr2_ctrl_get_value( + pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE), + &val); + vt->audmode = val; + break; + } + + case VIDIOC_S_TUNER: + { + struct v4l2_tuner *vt=(struct v4l2_tuner *)arg; + + if (vt->index != 0) + break; + + ret = pvr2_ctrl_set_value( + pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE), + vt->audmode); + } + + case VIDIOC_S_FREQUENCY: + { + const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; + ret = pvr2_ctrl_set_value( + pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY), + vf->frequency * 62500); + break; + } + + case VIDIOC_G_FREQUENCY: + { + struct v4l2_frequency *vf = (struct v4l2_frequency *)arg; + int val = 0; + ret = pvr2_ctrl_get_value( + pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY), + &val); + val /= 62500; + vf->frequency = val; + break; + } + + case VIDIOC_ENUM_FMT: + { + struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg; + + /* Only one format is supported : mpeg.*/ + if (fd->index != 0) + break; + + memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc)); + ret = 0; + break; + } + + case VIDIOC_G_FMT: + { + struct v4l2_format *vf = (struct v4l2_format *)arg; + int val; + switch(vf->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + memcpy(vf, &pvr_format[PVR_FORMAT_PIX], + sizeof(struct v4l2_format)); + val = 0; + pvr2_ctrl_get_value( + pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES), + &val); + vf->fmt.pix.width = val; + val = 0; + pvr2_ctrl_get_value( + pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES), + &val); + vf->fmt.pix.height = val; + ret = 0; + break; + case V4L2_BUF_TYPE_VBI_CAPTURE: + // ????? Still need to figure out to do VBI correctly + ret = -EINVAL; + break; + default: + ret = -EINVAL; + break; + } + break; + } + + case VIDIOC_TRY_FMT: + case VIDIOC_S_FMT: + { + struct v4l2_format *vf = (struct v4l2_format *)arg; + + ret = 0; + switch(vf->type) { + case V4L2_BUF_TYPE_VIDEO_CAPTURE: { + int lmin,lmax; + struct pvr2_ctrl *hcp,*vcp; + int h = vf->fmt.pix.height; + int w = vf->fmt.pix.width; + hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES); + vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES); + + lmin = pvr2_ctrl_get_min(hcp); + lmax = pvr2_ctrl_get_max(hcp); + if (w < lmin) { + w = lmin; + } else if (w > lmax) { + w = lmax; + } + lmin = pvr2_ctrl_get_min(vcp); + lmax = pvr2_ctrl_get_max(vcp); + if (h < lmin) { + h = lmin; + } else if (h > lmax) { + h = lmax; + } + + memcpy(vf, &pvr_format[PVR_FORMAT_PIX], + sizeof(struct v4l2_format)); + vf->fmt.pix.width = w; + vf->fmt.pix.height = h; + + if (cmd == VIDIOC_S_FMT) { + pvr2_ctrl_set_value(hcp,vf->fmt.pix.width); + pvr2_ctrl_set_value(vcp,vf->fmt.pix.height); + } + } break; + case V4L2_BUF_TYPE_VBI_CAPTURE: + // ????? Still need to figure out to do VBI correctly + ret = -EINVAL; + break; + default: + ret = -EINVAL; + break; + } + break; + } + + case VIDIOC_STREAMON: + { + ret = pvr2_hdw_set_stream_type(hdw,dev_info->config); + if (ret < 0) return ret; + ret = pvr2_hdw_set_streaming(hdw,!0); + break; + } + + case VIDIOC_STREAMOFF: + { + ret = pvr2_hdw_set_streaming(hdw,0); + break; + } + + case VIDIOC_QUERYCTRL: + { + struct pvr2_ctrl *cptr; + struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg; + ret = 0; + if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) { + cptr = pvr2_hdw_get_ctrl_nextv4l( + hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL)); + if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr); + } else { + cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id); + } + if (!cptr) { + pvr2_trace(PVR2_TRACE_V4LIOCTL, + "QUERYCTRL id=0x%x not implemented here", + vc->id); + ret = -EINVAL; + break; + } + + pvr2_trace(PVR2_TRACE_V4LIOCTL, + "QUERYCTRL id=0x%x mapping name=%s (%s)", + vc->id,pvr2_ctrl_get_name(cptr), + pvr2_ctrl_get_desc(cptr)); + strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name)); + vc->flags = pvr2_ctrl_get_v4lflags(cptr); + vc->default_value = pvr2_ctrl_get_def(cptr); + switch (pvr2_ctrl_get_type(cptr)) { + case pvr2_ctl_enum: + vc->type = V4L2_CTRL_TYPE_MENU; + vc->minimum = 0; + vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1; + vc->step = 1; + break; + case pvr2_ctl_bool: + vc->type = V4L2_CTRL_TYPE_BOOLEAN; + vc->minimum = 0; + vc->maximum = 1; + vc->step = 1; + break; + case pvr2_ctl_int: + vc->type = V4L2_CTRL_TYPE_INTEGER; + vc->minimum = pvr2_ctrl_get_min(cptr); + vc->maximum = pvr2_ctrl_get_max(cptr); + vc->step = 1; + break; + default: + pvr2_trace(PVR2_TRACE_V4LIOCTL, + "QUERYCTRL id=0x%x name=%s not mappable", + vc->id,pvr2_ctrl_get_name(cptr)); + ret = -EINVAL; + break; + } + break; + } + + case VIDIOC_QUERYMENU: + { + struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg; + unsigned int cnt = 0; + ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id), + vm->index, + vm->name,sizeof(vm->name)-1, + &cnt); + vm->name[cnt] = 0; + break; + } + + case VIDIOC_G_CTRL: + { + struct v4l2_control *vc = (struct v4l2_control *)arg; + int val = 0; + ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id), + &val); + vc->value = val; + break; + } + + case VIDIOC_S_CTRL: + { + struct v4l2_control *vc = (struct v4l2_control *)arg; + ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id), + vc->value); + break; + } + + case VIDIOC_G_EXT_CTRLS: + { + struct v4l2_ext_controls *ctls = + (struct v4l2_ext_controls *)arg; + struct v4l2_ext_control *ctrl; + unsigned int idx; + int val; + for (idx = 0; idx < ctls->count; idx++) { + ctrl = ctls->controls + idx; + ret = pvr2_ctrl_get_value( + pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val); + if (ret) { + ctls->error_idx = idx; + break; + } + /* Ensure that if read as a 64 bit value, the user + will still get a hopefully sane value */ + ctrl->value64 = 0; + ctrl->value = val; + } + break; + } + + case VIDIOC_S_EXT_CTRLS: + { + struct v4l2_ext_controls *ctls = + (struct v4l2_ext_controls *)arg; + struct v4l2_ext_control *ctrl; + unsigned int idx; + for (idx = 0; idx < ctls->count; idx++) { + ctrl = ctls->controls + idx; + ret = pvr2_ctrl_set_value( + pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id), + ctrl->value); + if (ret) { + ctls->error_idx = idx; + break; + } + } + break; + } + + case VIDIOC_TRY_EXT_CTRLS: + { + struct v4l2_ext_controls *ctls = + (struct v4l2_ext_controls *)arg; + struct v4l2_ext_control *ctrl; + struct pvr2_ctrl *pctl; + unsigned int idx; + /* For the moment just validate that the requested control + actually exists. */ + for (idx = 0; idx < ctls->count; idx++) { + ctrl = ctls->controls + idx; + pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id); + if (!pctl) { + ret = -EINVAL; + ctls->error_idx = idx; + break; + } + } + break; + } + + case VIDIOC_LOG_STATUS: + { + pvr2_hdw_trigger_module_log(hdw); + ret = 0; + break; + } + + default : + ret = v4l_compat_translate_ioctl(inode,file,cmd, + arg,pvr2_v4l2_do_ioctl); + } + + pvr2_hdw_commit_ctl(hdw); + + if (ret < 0) { + if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { + pvr2_trace(PVR2_TRACE_V4LIOCTL, + "pvr2_v4l2_do_ioctl failure, ret=%d",ret); + } else { + if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) { + pvr2_trace(PVR2_TRACE_V4LIOCTL, + "pvr2_v4l2_do_ioctl failure, ret=%d" + " command was:",ret); + v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw), + cmd); + } + } + } else { + pvr2_trace(PVR2_TRACE_V4LIOCTL, + "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)", + ret,ret); + } + return ret; +} + + +static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) +{ + printk(KERN_INFO "pvrusb2: unregistering device video%d [%s]\n", + dip->vdev->minor,pvr2_config_get_name(dip->config)); + video_unregister_device(dip->vdev); +} + + +static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp) +{ + pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,-1); + pvr2_v4l2_dev_destroy(&vp->video_dev); + + pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp); + pvr2_channel_done(&vp->channel); + kfree(vp); +} + + +static void pvr2_v4l2_internal_check(struct pvr2_channel *chp) +{ + struct pvr2_v4l2 *vp; + vp = container_of(chp,struct pvr2_v4l2,channel); + if (!vp->channel.mc_head->disconnect_flag) return; + if (vp->vfirst) return; + pvr2_v4l2_destroy_no_lock(vp); +} + + +static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + +/* Temporary hack : use ivtv api until a v4l2 one is available. */ +#define IVTV_IOC_G_CODEC 0xFFEE7703 +#define IVTV_IOC_S_CODEC 0xFFEE7704 + if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0; + return video_usercopy(inode, file, cmd, arg, pvr2_v4l2_do_ioctl); +} + + +static int pvr2_v4l2_release(struct inode *inode, struct file *file) +{ + struct pvr2_v4l2_fh *fhp = file->private_data; + struct pvr2_v4l2 *vp = fhp->vhead; + struct pvr2_context *mp = fhp->vhead->channel.mc_head; + + pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release"); + + if (fhp->rhp) { + struct pvr2_stream *sp; + struct pvr2_hdw *hdw; + hdw = fhp->channel.mc_head->hdw; + pvr2_hdw_set_streaming(hdw,0); + sp = pvr2_ioread_get_stream(fhp->rhp); + if (sp) pvr2_stream_set_callback(sp,NULL,NULL); + pvr2_ioread_destroy(fhp->rhp); + fhp->rhp = NULL; + } + v4l2_prio_close(&vp->prio, &fhp->prio); + file->private_data = NULL; + + pvr2_context_enter(mp); do { + if (fhp->vnext) { + fhp->vnext->vprev = fhp->vprev; + } else { + vp->vlast = fhp->vprev; + } + if (fhp->vprev) { + fhp->vprev->vnext = fhp->vnext; + } else { + vp->vfirst = fhp->vnext; + } + fhp->vnext = NULL; + fhp->vprev = NULL; + fhp->vhead = NULL; + pvr2_channel_done(&fhp->channel); + pvr2_trace(PVR2_TRACE_STRUCT, + "Destroying pvr_v4l2_fh id=%p",fhp); + kfree(fhp); + if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) { + pvr2_v4l2_destroy_no_lock(vp); + } + } while (0); pvr2_context_exit(mp); + return 0; +} + + +static int pvr2_v4l2_open(struct inode *inode, struct file *file) +{ + struct pvr2_v4l2_dev *dip = NULL; /* Our own context pointer */ + struct pvr2_v4l2_fh *fhp; + struct pvr2_v4l2 *vp; + struct pvr2_hdw *hdw; + + { + struct video_device *vdev = video_devdata(file); + dip = (struct pvr2_v4l2_dev *)video_get_drvdata(vdev); + } + + if (!dip) return -ENODEV; /* Should be impossible but I'm paranoid */ + + vp = dip->v4lp; + hdw = vp->channel.hdw; + + pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open"); + + if (!pvr2_hdw_dev_ok(hdw)) { + pvr2_trace(PVR2_TRACE_OPEN_CLOSE, + "pvr2_v4l2_open: hardware not ready"); + return -EIO; + } + + fhp = kmalloc(sizeof(*fhp),GFP_KERNEL); + if (!fhp) { + return -ENOMEM; + } + memset(fhp,0,sizeof(*fhp)); + + init_waitqueue_head(&fhp->wait_data); + fhp->dev_info = dip; + + pvr2_context_enter(vp->channel.mc_head); do { + pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp); + pvr2_channel_init(&fhp->channel,vp->channel.mc_head); + fhp->vnext = NULL; + fhp->vprev = vp->vlast; + if (vp->vlast) { + vp->vlast->vnext = fhp; + } else { + vp->vfirst = fhp; + } + vp->vlast = fhp; + fhp->vhead = vp; + } while (0); pvr2_context_exit(vp->channel.mc_head); + + fhp->file = file; + file->private_data = fhp; + v4l2_prio_open(&vp->prio,&fhp->prio); + + fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw); + + return 0; +} + + +static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp) +{ + wake_up(&fhp->wait_data); +} + +static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh) +{ + int ret; + struct pvr2_stream *sp; + struct pvr2_hdw *hdw; + if (fh->rhp) return 0; + + /* First read() attempt. Try to claim the stream and start + it... */ + if ((ret = pvr2_channel_claim_stream(&fh->channel, + fh->dev_info->stream)) != 0) { + /* Someone else must already have it */ + return ret; + } + + fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream); + if (!fh->rhp) { + pvr2_channel_claim_stream(&fh->channel,NULL); + return -ENOMEM; + } + + hdw = fh->channel.mc_head->hdw; + sp = fh->dev_info->stream->stream; + pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh); + pvr2_hdw_set_stream_type(hdw,fh->dev_info->config); + pvr2_hdw_set_streaming(hdw,!0); + ret = pvr2_ioread_set_enabled(fh->rhp,!0); + + return ret; +} + + +static ssize_t pvr2_v4l2_read(struct file *file, + char __user *buff, size_t count, loff_t *ppos) +{ + struct pvr2_v4l2_fh *fh = file->private_data; + int ret; + + if (fh->fw_mode_flag) { + struct pvr2_hdw *hdw = fh->channel.mc_head->hdw; + char *tbuf; + int c1,c2; + int tcnt = 0; + unsigned int offs = *ppos; + + tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL); + if (!tbuf) return -ENOMEM; + + while (count) { + c1 = count; + if (c1 > PAGE_SIZE) c1 = PAGE_SIZE; + c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1); + if (c2 < 0) { + tcnt = c2; + break; + } + if (!c2) break; + if (copy_to_user(buff,tbuf,c2)) { + tcnt = -EFAULT; + break; + } + offs += c2; + tcnt += c2; + buff += c2; + count -= c2; + *ppos += c2; + } + kfree(tbuf); + return tcnt; + } + + if (!fh->rhp) { + ret = pvr2_v4l2_iosetup(fh); + if (ret) { + return ret; + } + } + + for (;;) { + ret = pvr2_ioread_read(fh->rhp,buff,count); + if (ret >= 0) break; + if (ret != -EAGAIN) break; + if (file->f_flags & O_NONBLOCK) break; + /* Doing blocking I/O. Wait here. */ + ret = wait_event_interruptible( + fh->wait_data, + pvr2_ioread_avail(fh->rhp) >= 0); + if (ret < 0) break; + } + + return ret; +} + + +static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait) +{ + unsigned int mask = 0; + struct pvr2_v4l2_fh *fh = file->private_data; + int ret; + + if (fh->fw_mode_flag) { + mask |= POLLIN | POLLRDNORM; + return mask; + } + + if (!fh->rhp) { + ret = pvr2_v4l2_iosetup(fh); + if (ret) return POLLERR; + } + + poll_wait(file,&fh->wait_data,wait); + + if (pvr2_ioread_avail(fh->rhp) >= 0) { + mask |= POLLIN | POLLRDNORM; + } + + return mask; +} + + +static struct file_operations vdev_fops = { + .owner = THIS_MODULE, + .open = pvr2_v4l2_open, + .release = pvr2_v4l2_release, + .read = pvr2_v4l2_read, + .ioctl = pvr2_v4l2_ioctl, + .llseek = no_llseek, + .poll = pvr2_v4l2_poll, +}; + + +#define VID_HARDWARE_PVRUSB2 38 /* FIXME : need a good value */ + +static struct video_device vdev_template = { + .owner = THIS_MODULE, + .type = VID_TYPE_CAPTURE | VID_TYPE_TUNER, + .type2 = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE + | V4L2_CAP_TUNER | V4L2_CAP_AUDIO + | V4L2_CAP_READWRITE), + .hardware = VID_HARDWARE_PVRUSB2, + .fops = &vdev_fops, +}; + + +static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, + struct pvr2_v4l2 *vp, + enum pvr2_config cfg) +{ + int mindevnum; + int unit_number; + int v4l_type; + dip->v4lp = vp; + dip->config = cfg; + + + switch (cfg) { + case pvr2_config_mpeg: + v4l_type = VFL_TYPE_GRABBER; + dip->stream = &vp->channel.mc_head->video_stream; + break; + case pvr2_config_vbi: + v4l_type = VFL_TYPE_VBI; + break; + case pvr2_config_radio: + v4l_type = VFL_TYPE_RADIO; + break; + default: + /* Bail out (this should be impossible) */ + err("Failed to set up pvrusb2 v4l dev" + " due to unrecognized config"); + return; + } + + if (!dip->stream) { + err("Failed to set up pvrusb2 v4l dev" + " due to missing stream instance"); + return; + } + + dip->vdev = video_device_alloc(); + if (!dip->vdev) { + err("Alloc of pvrusb2 v4l video device failed"); + return; + } + + memcpy(dip->vdev,&vdev_template,sizeof(vdev_template)); + dip->vdev->release = video_device_release; + video_set_drvdata(dip->vdev,dip); + + mindevnum = -1; + unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw); + if ((unit_number >= 0) && (unit_number < PVR_NUM)) { + mindevnum = video_nr[unit_number]; + } + if ((video_register_device(dip->vdev, v4l_type, mindevnum) < 0) && + (video_register_device(dip->vdev, v4l_type, -1) < 0)) { + err("Failed to register pvrusb2 v4l video device"); + } else { + printk(KERN_INFO "pvrusb2: registered device video%d [%s]\n", + dip->vdev->minor,pvr2_config_get_name(dip->config)); + } + + + pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, + dip->vdev->minor); +} + + +struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) +{ + struct pvr2_v4l2 *vp; + + vp = kmalloc(sizeof(*vp),GFP_KERNEL); + if (!vp) return vp; + memset(vp,0,sizeof(*vp)); + pvr2_channel_init(&vp->channel,mnp); + pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp); + + vp->channel.check_func = pvr2_v4l2_internal_check; + + /* register streams */ + pvr2_v4l2_dev_init(&vp->video_dev,vp,pvr2_config_mpeg); + + + return vp; +} + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.h b/drivers/media/video/pvrusb2/pvrusb2-v4l2.h new file mode 100644 index 000000000..9a995e2d2 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.h @@ -0,0 +1,40 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#ifndef __PVRUSB2_V4L2_H +#define __PVRUSB2_V4L2_H + +#include "pvrusb2-context.h" + +struct pvr2_v4l2; + +struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *); + +#endif /* __PVRUSB2_V4L2_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 75 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c new file mode 100644 index 000000000..05f2cddeb --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.c @@ -0,0 +1,253 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + + This source file is specifically designed to interface with the + saa711x support that is available in the v4l available starting + with linux 2.6.15. + +*/ + +#include "pvrusb2-video-v4l.h" +#include "pvrusb2-i2c-cmd-v4l2.h" + + +#include "pvrusb2-hdw-internal.h" +#include "pvrusb2-debug.h" +#include <linux/videodev2.h> +#include <media/v4l2-common.h> +#include <media/saa7115.h> +#include <linux/errno.h> +#include <linux/slab.h> + +struct pvr2_v4l_decoder { + struct pvr2_i2c_handler handler; + struct pvr2_decoder_ctrl ctrl; + struct pvr2_i2c_client *client; + struct pvr2_hdw *hdw; + unsigned long stale_mask; +}; + + +static void set_input(struct pvr2_v4l_decoder *ctxt) +{ + struct pvr2_hdw *hdw = ctxt->hdw; + struct v4l2_routing route; + + pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_input(%d)",hdw->input_val); + switch(hdw->input_val) { + case PVR2_CVAL_INPUT_TV: + route.input = SAA7115_COMPOSITE4; + break; + case PVR2_CVAL_INPUT_COMPOSITE: + route.input = SAA7115_COMPOSITE5; + break; + case PVR2_CVAL_INPUT_SVIDEO: + route.input = SAA7115_SVIDEO2; + break; + case PVR2_CVAL_INPUT_RADIO: + // ????? No idea yet what to do here + default: + return; + } + route.output = 0; + pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_VIDEO_ROUTING,&route); +} + + +static int check_input(struct pvr2_v4l_decoder *ctxt) +{ + struct pvr2_hdw *hdw = ctxt->hdw; + return hdw->input_dirty != 0; +} + + +static void set_audio(struct pvr2_v4l_decoder *ctxt) +{ + u32 val; + struct pvr2_hdw *hdw = ctxt->hdw; + + pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 set_audio %d", + hdw->srate_val); + switch (hdw->srate_val) { + default: + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000: + val = 48000; + break; + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100: + val = 44100; + break; + case V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000: + val = 32000; + break; + } + pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_AUDIO_CLOCK_FREQ,&val); +} + + +static int check_audio(struct pvr2_v4l_decoder *ctxt) +{ + struct pvr2_hdw *hdw = ctxt->hdw; + return hdw->srate_dirty != 0; +} + + +struct pvr2_v4l_decoder_ops { + void (*update)(struct pvr2_v4l_decoder *); + int (*check)(struct pvr2_v4l_decoder *); +}; + + +static const struct pvr2_v4l_decoder_ops decoder_ops[] = { + { .update = set_input, .check = check_input}, + { .update = set_audio, .check = check_audio}, +}; + + +static void decoder_detach(struct pvr2_v4l_decoder *ctxt) +{ + ctxt->client->handler = NULL; + ctxt->hdw->decoder_ctrl = NULL; + kfree(ctxt); +} + + +static int decoder_check(struct pvr2_v4l_decoder *ctxt) +{ + unsigned long msk; + unsigned int idx; + + for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]); + idx++) { + msk = 1 << idx; + if (ctxt->stale_mask & msk) continue; + if (decoder_ops[idx].check(ctxt)) { + ctxt->stale_mask |= msk; + } + } + return ctxt->stale_mask != 0; +} + + +static void decoder_update(struct pvr2_v4l_decoder *ctxt) +{ + unsigned long msk; + unsigned int idx; + + for (idx = 0; idx < sizeof(decoder_ops)/sizeof(decoder_ops[0]); + idx++) { + msk = 1 << idx; + if (!(ctxt->stale_mask & msk)) continue; + ctxt->stale_mask &= ~msk; + decoder_ops[idx].update(ctxt); + } +} + + +static int decoder_detect(struct pvr2_i2c_client *cp) +{ + /* Attempt to query the decoder - let's see if it will answer */ + struct v4l2_tuner vt; + int ret; + + memset(&vt,0,sizeof(vt)); + ret = pvr2_i2c_client_cmd(cp,VIDIOC_G_TUNER,&vt); + return ret == 0; /* Return true if it answered */ +} + + +static void decoder_enable(struct pvr2_v4l_decoder *ctxt,int fl) +{ + pvr2_trace(PVR2_TRACE_CHIPS,"i2c v4l2 decoder_enable(%d)",fl); + pvr2_v4l2_cmd_stream(ctxt->client,fl); +} + + +static int decoder_is_tuned(struct pvr2_v4l_decoder *ctxt) +{ + struct v4l2_tuner vt; + int ret; + + memset(&vt,0,sizeof(vt)); + ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_G_TUNER,&vt); + if (ret < 0) return -EINVAL; + return vt.signal ? 1 : 0; +} + + +static unsigned int decoder_describe(struct pvr2_v4l_decoder *ctxt,char *buf,unsigned int cnt) +{ + return scnprintf(buf,cnt,"handler: pvrusb2-video-v4l"); +} + + +const static struct pvr2_i2c_handler_functions hfuncs = { + .detach = (void (*)(void *))decoder_detach, + .check = (int (*)(void *))decoder_check, + .update = (void (*)(void *))decoder_update, + .describe = (unsigned int (*)(void *,char *,unsigned int))decoder_describe, +}; + + +int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *hdw, + struct pvr2_i2c_client *cp) +{ + struct pvr2_v4l_decoder *ctxt; + + if (hdw->decoder_ctrl) return 0; + if (cp->handler) return 0; + if (!decoder_detect(cp)) return 0; + + ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL); + if (!ctxt) return 0; + memset(ctxt,0,sizeof(*ctxt)); + + ctxt->handler.func_data = ctxt; + ctxt->handler.func_table = &hfuncs; + ctxt->ctrl.ctxt = ctxt; + ctxt->ctrl.detach = (void (*)(void *))decoder_detach; + ctxt->ctrl.enable = (void (*)(void *,int))decoder_enable; + ctxt->ctrl.tuned = (int (*)(void *))decoder_is_tuned; + ctxt->client = cp; + ctxt->hdw = hdw; + ctxt->stale_mask = (1 << (sizeof(decoder_ops)/ + sizeof(decoder_ops[0]))) - 1; + hdw->decoder_ctrl = &ctxt->ctrl; + cp->handler = &ctxt->handler; + pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x saa711x V4L2 handler set up", + cp->client->addr); + return !0; +} + + + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h new file mode 100644 index 000000000..2b917fda0 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-video-v4l.h @@ -0,0 +1,52 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __PVRUSB2_VIDEO_V4L_H +#define __PVRUSB2_VIDEO_V4L_H + +/* + + This module connects the pvrusb2 driver to the I2C chip level + driver which handles device video processing. This interface is + used internally by the driver; higher level code should only + interact through the interface provided by pvrusb2-hdw.h. + +*/ + + + +#include "pvrusb2-i2c-core.h" + +int pvr2_i2c_decoder_v4l_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); + + +#endif /* __PVRUSB2_VIDEO_V4L_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.c b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c new file mode 100644 index 000000000..2413e5198 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.c @@ -0,0 +1,170 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* + + This source file is specifically designed to interface with the + wm8775. + +*/ + +#include "pvrusb2-wm8775.h" +#include "pvrusb2-i2c-cmd-v4l2.h" + + +#include "pvrusb2-hdw-internal.h" +#include "pvrusb2-debug.h" +#include <linux/videodev2.h> +#include <media/v4l2-common.h> +#include <linux/errno.h> +#include <linux/slab.h> + +struct pvr2_v4l_wm8775 { + struct pvr2_i2c_handler handler; + struct pvr2_i2c_client *client; + struct pvr2_hdw *hdw; + unsigned long stale_mask; +}; + + +static void set_input(struct pvr2_v4l_wm8775 *ctxt) +{ + struct v4l2_routing route; + struct pvr2_hdw *hdw = ctxt->hdw; + int msk = 0; + + memset(&route,0,sizeof(route)); + + pvr2_trace(PVR2_TRACE_CHIPS,"i2c wm8775 set_input(val=%d msk=0x%x)", + hdw->input_val,msk); + + // Always point to input #1 no matter what + route.input = 2; + pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route); +} + +static int check_input(struct pvr2_v4l_wm8775 *ctxt) +{ + struct pvr2_hdw *hdw = ctxt->hdw; + return hdw->input_dirty != 0; +} + + +struct pvr2_v4l_wm8775_ops { + void (*update)(struct pvr2_v4l_wm8775 *); + int (*check)(struct pvr2_v4l_wm8775 *); +}; + + +static const struct pvr2_v4l_wm8775_ops wm8775_ops[] = { + { .update = set_input, .check = check_input}, +}; + + +static unsigned int wm8775_describe(struct pvr2_v4l_wm8775 *ctxt, + char *buf,unsigned int cnt) +{ + return scnprintf(buf,cnt,"handler: pvrusb2-wm8775"); +} + + +static void wm8775_detach(struct pvr2_v4l_wm8775 *ctxt) +{ + ctxt->client->handler = NULL; + kfree(ctxt); +} + + +static int wm8775_check(struct pvr2_v4l_wm8775 *ctxt) +{ + unsigned long msk; + unsigned int idx; + + for (idx = 0; idx < sizeof(wm8775_ops)/sizeof(wm8775_ops[0]); + idx++) { + msk = 1 << idx; + if (ctxt->stale_mask & msk) continue; + if (wm8775_ops[idx].check(ctxt)) { + ctxt->stale_mask |= msk; + } + } + return ctxt->stale_mask != 0; +} + + +static void wm8775_update(struct pvr2_v4l_wm8775 *ctxt) +{ + unsigned long msk; + unsigned int idx; + + for (idx = 0; idx < sizeof(wm8775_ops)/sizeof(wm8775_ops[0]); + idx++) { + msk = 1 << idx; + if (!(ctxt->stale_mask & msk)) continue; + ctxt->stale_mask &= ~msk; + wm8775_ops[idx].update(ctxt); + } +} + + +const static struct pvr2_i2c_handler_functions hfuncs = { + .detach = (void (*)(void *))wm8775_detach, + .check = (int (*)(void *))wm8775_check, + .update = (void (*)(void *))wm8775_update, + .describe = (unsigned int (*)(void *,char *,unsigned int))wm8775_describe, +}; + + +int pvr2_i2c_wm8775_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) +{ + struct pvr2_v4l_wm8775 *ctxt; + + if (cp->handler) return 0; + + ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL); + if (!ctxt) return 0; + memset(ctxt,0,sizeof(*ctxt)); + + ctxt->handler.func_data = ctxt; + ctxt->handler.func_table = &hfuncs; + ctxt->client = cp; + ctxt->hdw = hdw; + ctxt->stale_mask = (1 << (sizeof(wm8775_ops)/ + sizeof(wm8775_ops[0]))) - 1; + cp->handler = &ctxt->handler; + pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x wm8775 V4L2 handler set up", + cp->client->addr); + return !0; +} + + + + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2-wm8775.h b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h new file mode 100644 index 000000000..8aaeff4e1 --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2-wm8775.h @@ -0,0 +1,53 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __PVRUSB2_WM8775_H +#define __PVRUSB2_WM8775_H + +/* + + This module connects the pvrusb2 driver to the I2C chip level + driver which performs analog -> digital audio conversion for + external audio inputs. This interface is used internally by the + driver; higher level code should only interact through the + interface provided by pvrusb2-hdw.h. + +*/ + + + +#include "pvrusb2-i2c-core.h" + +int pvr2_i2c_wm8775_setup(struct pvr2_hdw *,struct pvr2_i2c_client *); + + +#endif /* __PVRUSB2_WM8775_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pvrusb2/pvrusb2.h b/drivers/media/video/pvrusb2/pvrusb2.h new file mode 100644 index 000000000..074533e9c --- /dev/null +++ b/drivers/media/video/pvrusb2/pvrusb2.h @@ -0,0 +1,43 @@ +/* + * + * $Id$ + * + * Copyright (C) 2005 Mike Isely <isely@pobox.com> + * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef __PVRUSB2_H +#define __PVRUSB2_H + +/* Maximum number of pvrusb2 instances we can track at once. You + might want to increase this - however the driver operation will not + be impaired if it is too small. Instead additional units just + won't have an ID assigned and it might not be possible to specify + module paramters for those extra units. */ +#define PVR_NUM 20 + +#endif /* __PVRUSB2_H */ + +/* + Stuff for Emacs to see, in order to encourage consistent editing style: + *** Local Variables: *** + *** mode: c *** + *** fill-column: 70 *** + *** tab-width: 8 *** + *** c-basic-offset: 8 *** + *** End: *** + */ diff --git a/drivers/media/video/pwc/pwc-dec1.c b/drivers/media/video/pwc/pwc-dec1.c new file mode 100644 index 000000000..c29593f58 --- /dev/null +++ b/drivers/media/video/pwc/pwc-dec1.c @@ -0,0 +1,50 @@ +/* Linux driver for Philips webcam + Decompression for chipset version 1 + (C) 2004-2006 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to <luc@saillard.org>. + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + + +#include "pwc-dec1.h" + + +void pwc_dec1_init(int type, int release, void *buffer, void *table) +{ + +} + +void pwc_dec1_exit(void) +{ + + + +} + +int pwc_dec1_alloc(struct pwc_device *pwc) +{ + pwc->decompress_data = kmalloc(sizeof(struct pwc_dec1_private), GFP_KERNEL); + if (pwc->decompress_data == NULL) + return -ENOMEM; + return 0; +} + diff --git a/drivers/media/video/pwc/pwc-dec1.h b/drivers/media/video/pwc/pwc-dec1.h new file mode 100644 index 000000000..8b62ddcc5 --- /dev/null +++ b/drivers/media/video/pwc/pwc-dec1.h @@ -0,0 +1,43 @@ +/* Linux driver for Philips webcam + (C) 2004-2006 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to <luc@saillard.org>. + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + + +#ifndef PWC_DEC1_H +#define PWC_DEC1_H + +#include "pwc.h" + +struct pwc_dec1_private +{ + int version; + +}; + +int pwc_dec1_alloc(struct pwc_device *pwc); +void pwc_dec1_init(int type, int release, void *buffer, void *private_data); +void pwc_dec1_exit(void); + +#endif + diff --git a/drivers/media/video/pwc/pwc-dec23.c b/drivers/media/video/pwc/pwc-dec23.c new file mode 100644 index 000000000..9e2d91f26 --- /dev/null +++ b/drivers/media/video/pwc/pwc-dec23.c @@ -0,0 +1,941 @@ +/* Linux driver for Philips webcam + Decompression for chipset version 2 et 3 + (C) 2004-2006 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to <luc@saillard.org>. + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "pwc-timon.h" +#include "pwc-kiara.h" +#include "pwc-dec23.h" +#include <media/pwc-ioctl.h> + +#include <linux/string.h> + +/* + * USE_LOOKUP_TABLE_TO_CLAMP + * 0: use a C version of this tests: { a<0?0:(a>255?255:a) } + * 1: use a faster lookup table for cpu with a big cache (intel) + */ +#define USE_LOOKUP_TABLE_TO_CLAMP 1 +/* + * UNROLL_LOOP_FOR_COPYING_BLOCK + * 0: use a loop for a smaller code (but little slower) + * 1: when unrolling the loop, gcc produces some faster code (perhaps only + * valid for intel processor class). Activating this option, automaticaly + * activate USE_LOOKUP_TABLE_TO_CLAMP + */ +#define UNROLL_LOOP_FOR_COPY 1 +#if UNROLL_LOOP_FOR_COPY +# undef USE_LOOKUP_TABLE_TO_CLAMP +# define USE_LOOKUP_TABLE_TO_CLAMP 1 +#endif + +/* + * ENABLE_BAYER_DECODER + * 0: bayer decoder is not build (save some space) + * 1: bayer decoder is build and can be used + */ +#define ENABLE_BAYER_DECODER 0 + +static void build_subblock_pattern(struct pwc_dec23_private *pdec) +{ + static const unsigned int initial_values[12] = { + -0x526500, -0x221200, 0x221200, 0x526500, + -0x3de200, 0x3de200, + -0x6db480, -0x2d5d00, 0x2d5d00, 0x6db480, + -0x12c200, 0x12c200 + + }; + static const unsigned int values_derivated[12] = { + 0xa4ca, 0x4424, -0x4424, -0xa4ca, + 0x7bc4, -0x7bc4, + 0xdb69, 0x5aba, -0x5aba, -0xdb69, + 0x2584, -0x2584 + }; + unsigned int temp_values[12]; + int i, j; + + memcpy(temp_values, initial_values, sizeof(initial_values)); + for (i = 0; i < 256; i++) { + for (j = 0; j < 12; j++) { + pdec->table_subblock[i][j] = temp_values[j]; + temp_values[j] += values_derivated[j]; + } + } +} + +static void build_bit_powermask_table(struct pwc_dec23_private *pdec) +{ + unsigned char *p; + unsigned int bit, byte, mask, val; + unsigned int bitpower = 1; + + for (bit = 0; bit < 8; bit++) { + mask = bitpower - 1; + p = pdec->table_bitpowermask[bit]; + for (byte = 0; byte < 256; byte++) { + val = (byte & mask); + if (byte & bitpower) + val = -val; + *p++ = val; + } + bitpower<<=1; + } +} + + +static void build_table_color(const unsigned int romtable[16][8], + unsigned char p0004[16][1024], + unsigned char p8004[16][256]) +{ + int compression_mode, j, k, bit, pw; + unsigned char *p0, *p8; + const unsigned int *r; + + /* We have 16 compressions tables */ + for (compression_mode = 0; compression_mode < 16; compression_mode++) { + p0 = p0004[compression_mode]; + p8 = p8004[compression_mode]; + r = romtable[compression_mode]; + + for (j = 0; j < 8; j++, r++, p0 += 128) { + + for (k = 0; k < 16; k++) { + if (k == 0) + bit = 1; + else if (k >= 1 && k < 3) + bit = (r[0] >> 15) & 7; + else if (k >= 3 && k < 6) + bit = (r[0] >> 12) & 7; + else if (k >= 6 && k < 10) + bit = (r[0] >> 9) & 7; + else if (k >= 10 && k < 13) + bit = (r[0] >> 6) & 7; + else if (k >= 13 && k < 15) + bit = (r[0] >> 3) & 7; + else + bit = (r[0]) & 7; + if (k == 0) + *p8++ = 8; + else + *p8++ = j - bit; + *p8++ = bit; + + pw = 1 << bit; + p0[k + 0x00] = (1 * pw) + 0x80; + p0[k + 0x10] = (2 * pw) + 0x80; + p0[k + 0x20] = (3 * pw) + 0x80; + p0[k + 0x30] = (4 * pw) + 0x80; + p0[k + 0x40] = (-1 * pw) + 0x80; + p0[k + 0x50] = (-2 * pw) + 0x80; + p0[k + 0x60] = (-3 * pw) + 0x80; + p0[k + 0x70] = (-4 * pw) + 0x80; + } /* end of for (k=0; k<16; k++, p8++) */ + } /* end of for (j=0; j<8; j++ , table++) */ + } /* end of foreach compression_mode */ +} + +/* + * + */ +static void fill_table_dc00_d800(struct pwc_dec23_private *pdec) +{ +#define SCALEBITS 15 +#define ONE_HALF (1UL << (SCALEBITS - 1)) + int i; + unsigned int offset1 = ONE_HALF; + unsigned int offset2 = 0x0000; + + for (i=0; i<256; i++) { + pdec->table_dc00[i] = offset1 & ~(ONE_HALF); + pdec->table_d800[i] = offset2; + + offset1 += 0x7bc4; + offset2 += 0x7bc4; + } +} + +/* + * To decode the stream: + * if look_bits(2) == 0: # op == 2 in the lookup table + * skip_bits(2) + * end of the stream + * elif look_bits(3) == 7: # op == 1 in the lookup table + * skip_bits(3) + * yyyy = get_bits(4) + * xxxx = get_bits(8) + * else: # op == 0 in the lookup table + * skip_bits(x) + * + * For speedup processing, we build a lookup table and we takes the first 6 bits. + * + * struct { + * unsigned char op; // operation to execute + * unsigned char bits; // bits use to perform operation + * unsigned char offset1; // offset to add to access in the table_0004 % 16 + * unsigned char offset2; // offset to add to access in the table_0004 + * } + * + * How to build this table ? + * op == 2 when (i%4)==0 + * op == 1 when (i%8)==7 + * op == 0 otherwise + * + */ +static const unsigned char hash_table_ops[64*4] = { + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x10, + 0x00, 0x06, 0x01, 0x30, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x40, + 0x00, 0x05, 0x01, 0x20, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x50, + 0x00, 0x05, 0x02, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x40, + 0x00, 0x05, 0x03, 0x00, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x10, + 0x00, 0x06, 0x02, 0x10, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x40, + 0x00, 0x05, 0x01, 0x60, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x50, + 0x00, 0x05, 0x02, 0x40, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x40, + 0x00, 0x05, 0x03, 0x40, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x10, + 0x00, 0x06, 0x01, 0x70, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x40, + 0x00, 0x05, 0x01, 0x20, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x50, + 0x00, 0x05, 0x02, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x40, + 0x00, 0x05, 0x03, 0x00, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x10, + 0x00, 0x06, 0x02, 0x50, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x40, + 0x00, 0x05, 0x01, 0x60, + 0x01, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x00, + 0x00, 0x04, 0x01, 0x50, + 0x00, 0x05, 0x02, 0x40, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x01, 0x40, + 0x00, 0x05, 0x03, 0x40, + 0x01, 0x00, 0x00, 0x00 +}; + +/* + * + */ +static const unsigned int MulIdx[16][16] = { + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, + {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,}, + {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,}, + {4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,}, + {6, 7, 8, 9, 7, 10, 11, 8, 8, 11, 10, 7, 9, 8, 7, 6,}, + {4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,}, + {1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,}, + {0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,}, + {0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,}, + {1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,}, + {7, 10, 11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8, 11, 10, 7,}, + {4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,}, + {7, 9, 6, 8, 10, 8, 7, 11, 11, 7, 8, 10, 8, 6, 9, 7,}, + {1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,}, + {1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,}, + {10, 8, 7, 11, 8, 6, 9, 7, 7, 9, 6, 8, 11, 7, 8, 10} +}; + +#if USE_LOOKUP_TABLE_TO_CLAMP +#define MAX_OUTER_CROP_VALUE (512) +static unsigned char pwc_crop_table[256 + 2*MAX_OUTER_CROP_VALUE]; +#define CLAMP(x) (pwc_crop_table[MAX_OUTER_CROP_VALUE+(x)]) +#else +#define CLAMP(x) ((x)>255?255:((x)<0?0:x)) +#endif + + +/* If the type or the command change, we rebuild the lookup table */ +int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd) +{ + int flags, version, shift, i; + struct pwc_dec23_private *pdec; + + if (pwc->decompress_data == NULL) { + pdec = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); + if (pdec == NULL) + return -ENOMEM; + pwc->decompress_data = pdec; + } + pdec = pwc->decompress_data; + + if (DEVICE_USE_CODEC3(type)) { + flags = cmd[2] & 0x18; + if (flags == 8) + pdec->nbits = 7; /* More bits, mean more bits to encode the stream, but better quality */ + else if (flags == 0x10) + pdec->nbits = 8; + else + pdec->nbits = 6; + + version = cmd[2] >> 5; + build_table_color(KiaraRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1); + build_table_color(KiaraRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2); + + } else { + + flags = cmd[2] & 6; + if (flags == 2) + pdec->nbits = 7; + else if (flags == 4) + pdec->nbits = 8; + else + pdec->nbits = 6; + + version = cmd[2] >> 3; + build_table_color(TimonRomTable[version][0], pdec->table_0004_pass1, pdec->table_8004_pass1); + build_table_color(TimonRomTable[version][1], pdec->table_0004_pass2, pdec->table_8004_pass2); + } + + /* Informations can be coded on a variable number of bits but never less than 8 */ + shift = 8 - pdec->nbits; + pdec->scalebits = SCALEBITS - shift; + pdec->nbitsmask = 0xFF >> shift; + + fill_table_dc00_d800(pdec); + build_subblock_pattern(pdec); + build_bit_powermask_table(pdec); + +#if USE_LOOKUP_TABLE_TO_CLAMP + /* Build the static table to clamp value [0-255] */ + for (i=0;i<MAX_OUTER_CROP_VALUE;i++) + pwc_crop_table[i] = 0; + for (i=0; i<256; i++) + pwc_crop_table[MAX_OUTER_CROP_VALUE+i] = i; + for (i=0; i<MAX_OUTER_CROP_VALUE; i++) + pwc_crop_table[MAX_OUTER_CROP_VALUE+256+i] = 255; +#endif + + return 0; +} + +/* + * Copy the 4x4 image block to Y plane buffer + */ +static void copy_image_block_Y(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) +{ +#if UNROLL_LOOP_FOR_COPY + const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; + const int *c = src; + unsigned char *d = dst; + + *d++ = cm[c[0] >> scalebits]; + *d++ = cm[c[1] >> scalebits]; + *d++ = cm[c[2] >> scalebits]; + *d++ = cm[c[3] >> scalebits]; + + d = dst + bytes_per_line; + *d++ = cm[c[4] >> scalebits]; + *d++ = cm[c[5] >> scalebits]; + *d++ = cm[c[6] >> scalebits]; + *d++ = cm[c[7] >> scalebits]; + + d = dst + bytes_per_line*2; + *d++ = cm[c[8] >> scalebits]; + *d++ = cm[c[9] >> scalebits]; + *d++ = cm[c[10] >> scalebits]; + *d++ = cm[c[11] >> scalebits]; + + d = dst + bytes_per_line*3; + *d++ = cm[c[12] >> scalebits]; + *d++ = cm[c[13] >> scalebits]; + *d++ = cm[c[14] >> scalebits]; + *d++ = cm[c[15] >> scalebits]; +#else + int i; + const int *c = src; + unsigned char *d = dst; + for (i = 0; i < 4; i++, c++) + *d++ = CLAMP((*c) >> scalebits); + + d = dst + bytes_per_line; + for (i = 0; i < 4; i++, c++) + *d++ = CLAMP((*c) >> scalebits); + + d = dst + bytes_per_line*2; + for (i = 0; i < 4; i++, c++) + *d++ = CLAMP((*c) >> scalebits); + + d = dst + bytes_per_line*3; + for (i = 0; i < 4; i++, c++) + *d++ = CLAMP((*c) >> scalebits); +#endif +} + +/* + * Copy the 4x4 image block to a CrCb plane buffer + * + */ +static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) +{ +#if UNROLL_LOOP_FOR_COPY + /* Unroll all loops */ + const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; + const int *c = src; + unsigned char *d = dst; + + *d++ = cm[c[0] >> scalebits]; + *d++ = cm[c[4] >> scalebits]; + *d++ = cm[c[1] >> scalebits]; + *d++ = cm[c[5] >> scalebits]; + *d++ = cm[c[2] >> scalebits]; + *d++ = cm[c[6] >> scalebits]; + *d++ = cm[c[3] >> scalebits]; + *d++ = cm[c[7] >> scalebits]; + + d = dst + bytes_per_line; + *d++ = cm[c[12] >> scalebits]; + *d++ = cm[c[8] >> scalebits]; + *d++ = cm[c[13] >> scalebits]; + *d++ = cm[c[9] >> scalebits]; + *d++ = cm[c[14] >> scalebits]; + *d++ = cm[c[10] >> scalebits]; + *d++ = cm[c[15] >> scalebits]; + *d++ = cm[c[11] >> scalebits]; +#else + int i; + const int *c1 = src; + const int *c2 = src + 4; + unsigned char *d = dst; + + for (i = 0; i < 4; i++, c1++, c2++) { + *d++ = CLAMP((*c1) >> scalebits); + *d++ = CLAMP((*c2) >> scalebits); + } + c1 = src + 12; + d = dst + bytes_per_line; + for (i = 0; i < 4; i++, c1++, c2++) { + *d++ = CLAMP((*c1) >> scalebits); + *d++ = CLAMP((*c2) >> scalebits); + } +#endif +} + +#if ENABLE_BAYER_DECODER +/* + * Format: 8x2 pixels + * . G . G . G . G . G . G . G + * . . . . . . . . . . . . . . + * . G . G . G . G . G . G . G + * . . . . . . . . . . . . . . + * or + * . . . . . . . . . . . . . . + * G . G . G . G . G . G . G . + * . . . . . . . . . . . . . . + * G . G . G . G . G . G . G . +*/ +static void copy_image_block_Green(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) +{ +#if UNROLL_LOOP_FOR_COPY + /* Unroll all loops */ + const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; + unsigned char *d = dst; + const int *c = src; + + d[0] = cm[c[0] >> scalebits]; + d[2] = cm[c[1] >> scalebits]; + d[4] = cm[c[2] >> scalebits]; + d[6] = cm[c[3] >> scalebits]; + d[8] = cm[c[4] >> scalebits]; + d[10] = cm[c[5] >> scalebits]; + d[12] = cm[c[6] >> scalebits]; + d[14] = cm[c[7] >> scalebits]; + + d = dst + bytes_per_line; + d[0] = cm[c[8] >> scalebits]; + d[2] = cm[c[9] >> scalebits]; + d[4] = cm[c[10] >> scalebits]; + d[6] = cm[c[11] >> scalebits]; + d[8] = cm[c[12] >> scalebits]; + d[10] = cm[c[13] >> scalebits]; + d[12] = cm[c[14] >> scalebits]; + d[14] = cm[c[15] >> scalebits]; +#else + int i; + unsigned char *d; + const int *c = src; + + d = dst; + for (i = 0; i < 8; i++, c++) + d[i*2] = CLAMP((*c) >> scalebits); + + d = dst + bytes_per_line; + for (i = 0; i < 8; i++, c++) + d[i*2] = CLAMP((*c) >> scalebits); +#endif +} +#endif + +#if ENABLE_BAYER_DECODER +/* + * Format: 4x4 pixels + * R . R . R . R + * . B . B . B . + * R . R . R . R + * . B . B . B . + */ +static void copy_image_block_RedBlue(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) +{ +#if UNROLL_LOOP_FOR_COPY + /* Unroll all loops */ + const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; + unsigned char *d = dst; + const int *c = src; + + d[0] = cm[c[0] >> scalebits]; + d[2] = cm[c[1] >> scalebits]; + d[4] = cm[c[2] >> scalebits]; + d[6] = cm[c[3] >> scalebits]; + + d = dst + bytes_per_line; + d[1] = cm[c[4] >> scalebits]; + d[3] = cm[c[5] >> scalebits]; + d[5] = cm[c[6] >> scalebits]; + d[7] = cm[c[7] >> scalebits]; + + d = dst + bytes_per_line*2; + d[0] = cm[c[8] >> scalebits]; + d[2] = cm[c[9] >> scalebits]; + d[4] = cm[c[10] >> scalebits]; + d[6] = cm[c[11] >> scalebits]; + + d = dst + bytes_per_line*3; + d[1] = cm[c[12] >> scalebits]; + d[3] = cm[c[13] >> scalebits]; + d[5] = cm[c[14] >> scalebits]; + d[7] = cm[c[15] >> scalebits]; +#else + int i; + unsigned char *d; + const int *c = src; + + d = dst; + for (i = 0; i < 4; i++, c++) + d[i*2] = CLAMP((*c) >> scalebits); + + d = dst + bytes_per_line; + for (i = 0; i < 4; i++, c++) + d[i*2+1] = CLAMP((*c) >> scalebits); + + d = dst + bytes_per_line*2; + for (i = 0; i < 4; i++, c++) + d[i*2] = CLAMP((*c) >> scalebits); + + d = dst + bytes_per_line*3; + for (i = 0; i < 4; i++, c++) + d[i*2+1] = CLAMP((*c) >> scalebits); +#endif +} +#endif + +/* + * To manage the stream, we keep bits in a 32 bits register. + * fill_nbits(n): fill the reservoir with at least n bits + * skip_bits(n): discard n bits from the reservoir + * get_bits(n): fill the reservoir, returns the first n bits and discard the + * bits from the reservoir. + * __get_nbits(n): faster version of get_bits(n), but asumes that the reservoir + * contains at least n bits. bits returned is discarded. + */ +#define fill_nbits(pdec, nbits_wanted) do { \ + while (pdec->nbits_in_reservoir<(nbits_wanted)) \ + { \ + pdec->reservoir |= (*(pdec->stream)++) << (pdec->nbits_in_reservoir); \ + pdec->nbits_in_reservoir += 8; \ + } \ +} while(0); + +#define skip_nbits(pdec, nbits_to_skip) do { \ + pdec->reservoir >>= (nbits_to_skip); \ + pdec->nbits_in_reservoir -= (nbits_to_skip); \ +} while(0); + +#define get_nbits(pdec, nbits_wanted, result) do { \ + fill_nbits(pdec, nbits_wanted); \ + result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \ + skip_nbits(pdec, nbits_wanted); \ +} while(0); + +#define __get_nbits(pdec, nbits_wanted, result) do { \ + result = (pdec->reservoir) & ((1U<<(nbits_wanted))-1); \ + skip_nbits(pdec, nbits_wanted); \ +} while(0); + +#define look_nbits(pdec, nbits_wanted) \ + ((pdec->reservoir) & ((1U<<(nbits_wanted))-1)) + +/* + * Decode a 4x4 pixel block + */ +static void decode_block(struct pwc_dec23_private *pdec, + const unsigned char *ptable0004, + const unsigned char *ptable8004) +{ + unsigned int primary_color; + unsigned int channel_v, offset1, op; + int i; + + fill_nbits(pdec, 16); + __get_nbits(pdec, pdec->nbits, primary_color); + + if (look_nbits(pdec,2) == 0) { + skip_nbits(pdec, 2); + /* Very simple, the color is the same for all pixels of the square */ + for (i = 0; i < 16; i++) + pdec->temp_colors[i] = pdec->table_dc00[primary_color]; + + return; + } + + /* This block is encoded with small pattern */ + for (i = 0; i < 16; i++) + pdec->temp_colors[i] = pdec->table_d800[primary_color]; + + __get_nbits(pdec, 3, channel_v); + channel_v = ((channel_v & 1) << 2) | (channel_v & 2) | ((channel_v & 4) >> 2); + + ptable0004 += (channel_v * 128); + ptable8004 += (channel_v * 32); + + offset1 = 0; + do + { + unsigned int htable_idx, rows = 0; + const unsigned int *block; + + /* [ zzzz y x x ] + * xx == 00 :=> end of the block def, remove the two bits from the stream + * yxx == 111 + * yxx == any other value + * + */ + fill_nbits(pdec, 16); + htable_idx = look_nbits(pdec, 6); + op = hash_table_ops[htable_idx * 4]; + + if (op == 2) { + skip_nbits(pdec, 2); + + } else if (op == 1) { + /* 15bits [ xxxx xxxx yyyy 111 ] + * yyy => offset in the table8004 + * xxx => offset in the tabled004 (tree) + */ + unsigned int mask, shift; + unsigned int nbits, col1; + unsigned int yyyy; + + skip_nbits(pdec, 3); + /* offset1 += yyyy */ + __get_nbits(pdec, 4, yyyy); + offset1 += 1 + yyyy; + offset1 &= 0x0F; + nbits = ptable8004[offset1 * 2]; + + /* col1 = xxxx xxxx */ + __get_nbits(pdec, nbits+1, col1); + + /* Bit mask table */ + mask = pdec->table_bitpowermask[nbits][col1]; + shift = ptable8004[offset1 * 2 + 1]; + rows = ((mask << shift) + 0x80) & 0xFF; + + block = pdec->table_subblock[rows]; + for (i = 0; i < 16; i++) + pdec->temp_colors[i] += block[MulIdx[offset1][i]]; + + } else { + /* op == 0 + * offset1 is coded on 3 bits + */ + unsigned int shift; + + offset1 += hash_table_ops [htable_idx * 4 + 2]; + offset1 &= 0x0F; + + rows = ptable0004[offset1 + hash_table_ops [htable_idx * 4 + 3]]; + block = pdec->table_subblock[rows]; + for (i = 0; i < 16; i++) + pdec->temp_colors[i] += block[MulIdx[offset1][i]]; + + shift = hash_table_ops[htable_idx * 4 + 1]; + skip_nbits(pdec, shift); + } + + } while (op != 2); + +} + +static void DecompressBand23(struct pwc_dec23_private *pdec, + const unsigned char *rawyuv, + unsigned char *planar_y, + unsigned char *planar_u, + unsigned char *planar_v, + unsigned int compressed_image_width, + unsigned int real_image_width) +{ + int compression_index, nblocks; + const unsigned char *ptable0004; + const unsigned char *ptable8004; + + pdec->reservoir = 0; + pdec->nbits_in_reservoir = 0; + pdec->stream = rawyuv + 1; /* The first byte of the stream is skipped */ + + get_nbits(pdec, 4, compression_index); + + /* pass 1: uncompress Y component */ + nblocks = compressed_image_width / 4; + + ptable0004 = pdec->table_0004_pass1[compression_index]; + ptable8004 = pdec->table_8004_pass1[compression_index]; + + /* Each block decode a square of 4x4 */ + while (nblocks) { + decode_block(pdec, ptable0004, ptable8004); + copy_image_block_Y(pdec->temp_colors, planar_y, real_image_width, pdec->scalebits); + planar_y += 4; + nblocks--; + } + + /* pass 2: uncompress UV component */ + nblocks = compressed_image_width / 8; + + ptable0004 = pdec->table_0004_pass2[compression_index]; + ptable8004 = pdec->table_8004_pass2[compression_index]; + + /* Each block decode a square of 4x4 */ + while (nblocks) { + decode_block(pdec, ptable0004, ptable8004); + copy_image_block_CrCb(pdec->temp_colors, planar_u, real_image_width/2, pdec->scalebits); + + decode_block(pdec, ptable0004, ptable8004); + copy_image_block_CrCb(pdec->temp_colors, planar_v, real_image_width/2, pdec->scalebits); + + planar_v += 8; + planar_u += 8; + nblocks -= 2; + } + +} + +#if ENABLE_BAYER_DECODER +/* + * Size need to be a multiple of 8 in width + * + * Return a block of four line encoded like this: + * + * G R G R G R G R G R G R G R G R + * B G B G B G B G B G B G B G B G + * G R G R G R G R G R G R G R G R + * B G B G B G B G B G B G B G B G + * + */ +static void DecompressBandBayer(struct pwc_dec23_private *pdec, + const unsigned char *rawyuv, + unsigned char *rgbbayer, + unsigned int compressed_image_width, + unsigned int real_image_width) +{ + int compression_index, nblocks; + const unsigned char *ptable0004; + const unsigned char *ptable8004; + unsigned char *dest; + + pdec->reservoir = 0; + pdec->nbits_in_reservoir = 0; + pdec->stream = rawyuv + 1; /* The first byte of the stream is skipped */ + + get_nbits(pdec, 4, compression_index); + + /* pass 1: uncompress RB component */ + nblocks = compressed_image_width / 4; + + ptable0004 = pdec->table_0004_pass1[compression_index]; + ptable8004 = pdec->table_8004_pass1[compression_index]; + dest = rgbbayer; + + /* Each block decode a square of 4x4 */ + while (nblocks) { + decode_block(pdec, ptable0004, ptable8004); + copy_image_block_RedBlue(pdec->temp_colors, rgbbayer, real_image_width, pdec->scalebits); + dest += 8; + nblocks--; + } + + /* pass 2: uncompress G component */ + nblocks = compressed_image_width / 8; + + ptable0004 = pdec->table_0004_pass2[compression_index]; + ptable8004 = pdec->table_8004_pass2[compression_index]; + + /* Each block decode a square of 4x4 */ + while (nblocks) { + decode_block(pdec, ptable0004, ptable8004); + copy_image_block_Green(pdec->temp_colors, rgbbayer+1, real_image_width, pdec->scalebits); + + decode_block(pdec, ptable0004, ptable8004); + copy_image_block_Green(pdec->temp_colors, rgbbayer+real_image_width, real_image_width, pdec->scalebits); + + rgbbayer += 16; + nblocks -= 2; + } +} +#endif + + +/** + * + * Uncompress a pwc23 buffer. + * + * pwc.view: size of the image wanted + * pwc.image: size of the image returned by the camera + * pwc.offset: (x,y) to displayer image in the view + * + * src: raw data + * dst: image output + * flags: PWCX_FLAG_PLANAR or PWCX_FLAG_BAYER + */ +void pwc_dec23_decompress(const struct pwc_device *pwc, + const void *src, + void *dst, + int flags) +{ + int bandlines_left, stride, bytes_per_block; + + bandlines_left = pwc->image.y / 4; + bytes_per_block = pwc->view.x * 4; + + if (flags & PWCX_FLAG_BAYER) { +#if ENABLE_BAYER_DECODER + /* RGB Bayer format */ + unsigned char *rgbout; + + stride = pwc->view.x * pwc->offset.y; + rgbout = dst + stride + pwc->offset.x; + + + while (bandlines_left--) { + + DecompressBandBayer(pwc->decompress_data, + src, + rgbout, + pwc->image.x, pwc->view.x); + + src += pwc->vbandlength; + rgbout += bytes_per_block; + + } +#else + memset(dst, 0, pwc->view.x * pwc->view.y); +#endif + + } else { + /* YUV420P image format */ + unsigned char *pout_planar_y; + unsigned char *pout_planar_u; + unsigned char *pout_planar_v; + unsigned int plane_size; + + plane_size = pwc->view.x * pwc->view.y; + + /* offset in Y plane */ + stride = pwc->view.x * pwc->offset.y; + pout_planar_y = dst + stride + pwc->offset.x; + + /* offsets in U/V planes */ + stride = (pwc->view.x * pwc->offset.y) / 4 + pwc->offset.x / 2; + pout_planar_u = dst + plane_size + stride; + pout_planar_v = dst + plane_size + plane_size / 4 + stride; + + while (bandlines_left--) { + + DecompressBand23(pwc->decompress_data, + src, + pout_planar_y, pout_planar_u, pout_planar_v, + pwc->image.x, pwc->view.x); + src += pwc->vbandlength; + pout_planar_y += bytes_per_block; + pout_planar_u += pwc->view.x; + pout_planar_v += pwc->view.x; + + } + + } + +} + +void pwc_dec23_exit(void) +{ + /* Do nothing */ + +} + +/** + * Allocate a private structure used by lookup table. + * You must call kfree() to free the memory allocated. + */ +int pwc_dec23_alloc(struct pwc_device *pwc) +{ + pwc->decompress_data = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); + if (pwc->decompress_data == NULL) + return -ENOMEM; + return 0; +} + +/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ diff --git a/drivers/media/video/pwc/pwc-dec23.h b/drivers/media/video/pwc/pwc-dec23.h new file mode 100644 index 000000000..1c55298ad --- /dev/null +++ b/drivers/media/video/pwc/pwc-dec23.h @@ -0,0 +1,67 @@ +/* Linux driver for Philips webcam + (C) 2004-2006 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to <luc@saillard.org>. + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef PWC_DEC23_H +#define PWC_DEC23_H + +#include "pwc.h" + +struct pwc_dec23_private +{ + unsigned int scalebits; + unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */ + + unsigned int reservoir; + unsigned int nbits_in_reservoir; + const unsigned char *stream; + int temp_colors[16]; + + unsigned char table_0004_pass1[16][1024]; + unsigned char table_0004_pass2[16][1024]; + unsigned char table_8004_pass1[16][256]; + unsigned char table_8004_pass2[16][256]; + unsigned int table_subblock[256][12]; + + unsigned char table_bitpowermask[8][256]; + unsigned int table_d800[256]; + unsigned int table_dc00[256]; + +}; + + +int pwc_dec23_alloc(struct pwc_device *pwc); +int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd); +void pwc_dec23_exit(void); +void pwc_dec23_decompress(const struct pwc_device *pwc, + const void *src, + void *dst, + int flags); + + + +#endif + + +/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ + diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c new file mode 100644 index 000000000..b7eb3ce3b --- /dev/null +++ b/drivers/media/video/pwc/pwc-v4l.c @@ -0,0 +1,1202 @@ +/* Linux driver for Philips webcam + USB and Video4Linux interface part. + (C) 1999-2004 Nemosoft Unv. + (C) 2004-2006 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to <luc@saillard.org>. + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/poll.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> +#include <asm/io.h> + +#include "pwc.h" + +static struct v4l2_queryctrl pwc_controls[] = { + { + .id = V4L2_CID_BRIGHTNESS, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Brightness", + .minimum = 0, + .maximum = 128, + .step = 1, + .default_value = 64, + }, + { + .id = V4L2_CID_CONTRAST, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contrast", + .minimum = 0, + .maximum = 64, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_SATURATION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Saturation", + .minimum = -100, + .maximum = 100, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_GAMMA, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gamma", + .minimum = 0, + .maximum = 32, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_RED_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Red Gain", + .minimum = 0, + .maximum = 256, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_BLUE_BALANCE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Blue Gain", + .minimum = 0, + .maximum = 256, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_AUTO_WHITE_BALANCE, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto White Balance", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_EXPOSURE, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Shutter Speed (Exposure)", + .minimum = 0, + .maximum = 256, + .step = 1, + .default_value = 200, + }, + { + .id = V4L2_CID_AUTOGAIN, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto Gain Enabled", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 1, + }, + { + .id = V4L2_CID_GAIN, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Gain Level", + .minimum = 0, + .maximum = 256, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_SAVE_USER, + .type = V4L2_CTRL_TYPE_BUTTON, + .name = "Save User Settings", + .minimum = 0, + .maximum = 0, + .step = 0, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_RESTORE_USER, + .type = V4L2_CTRL_TYPE_BUTTON, + .name = "Restore User Settings", + .minimum = 0, + .maximum = 0, + .step = 0, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_RESTORE_FACTORY, + .type = V4L2_CTRL_TYPE_BUTTON, + .name = "Restore Factory Settings", + .minimum = 0, + .maximum = 0, + .step = 0, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_COLOUR_MODE, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Colour mode", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_AUTOCONTOUR, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Auto contour", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_CONTOUR, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Contour", + .minimum = 0, + .maximum = 63, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_BACKLIGHT, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Backlight compensation", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_FLICKERLESS, + .type = V4L2_CTRL_TYPE_BOOLEAN, + .name = "Flickerless", + .minimum = 0, + .maximum = 1, + .step = 1, + .default_value = 0, + }, + { + .id = V4L2_CID_PRIVATE_NOISE_REDUCTION, + .type = V4L2_CTRL_TYPE_INTEGER, + .name = "Noise reduction", + .minimum = 0, + .maximum = 3, + .step = 1, + .default_value = 0, + }, +}; + + +static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_format *f) +{ + memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); + f->fmt.pix.width = pdev->view.x; + f->fmt.pix.height = pdev->view.y; + f->fmt.pix.field = V4L2_FIELD_NONE; + if (pdev->vpalette == VIDEO_PALETTE_YUV420P) { + f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; + f->fmt.pix.bytesperline = (f->fmt.pix.width * 3)/2; + f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; + } else { + /* vbandlength contains 4 lines ... */ + f->fmt.pix.bytesperline = pdev->vbandlength/4; + f->fmt.pix.sizeimage = pdev->frame_size + sizeof(struct pwc_raw_frame); + if (DEVICE_USE_CODEC1(pdev->type)) + f->fmt.pix.pixelformat = V4L2_PIX_FMT_PWC1; + else + f->fmt.pix.pixelformat = V4L2_PIX_FMT_PWC2; + } + PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() " + "width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n", + f->fmt.pix.width, + f->fmt.pix.height, + f->fmt.pix.bytesperline, + f->fmt.pix.sizeimage, + (f->fmt.pix.pixelformat)&255, + (f->fmt.pix.pixelformat>>8)&255, + (f->fmt.pix.pixelformat>>16)&255, + (f->fmt.pix.pixelformat>>24)&255); +} + +/* ioctl(VIDIOC_TRY_FMT) */ +static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f) +{ + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); + return -EINVAL; + } + + switch (f->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_YUV420: + break; + case V4L2_PIX_FMT_PWC1: + if (DEVICE_USE_CODEC23(pdev->type)) { + PWC_DEBUG_IOCTL("codec1 is only supported for old pwc webcam\n"); + return -EINVAL; + } + break; + case V4L2_PIX_FMT_PWC2: + if (DEVICE_USE_CODEC1(pdev->type)) { + PWC_DEBUG_IOCTL("codec23 is only supported for new pwc webcam\n"); + return -EINVAL; + } + break; + default: + PWC_DEBUG_IOCTL("Unsupported pixel format\n"); + return -EINVAL; + + } + + if (f->fmt.pix.width > pdev->view_max.x) + f->fmt.pix.width = pdev->view_max.x; + else if (f->fmt.pix.width < pdev->view_min.x) + f->fmt.pix.width = pdev->view_min.x; + + if (f->fmt.pix.height > pdev->view_max.y) + f->fmt.pix.height = pdev->view_max.y; + else if (f->fmt.pix.height < pdev->view_min.y) + f->fmt.pix.height = pdev->view_min.y; + + return 0; +} + +/* ioctl(VIDIOC_SET_FMT) */ +static int pwc_vidioc_set_fmt(struct pwc_device *pdev, struct v4l2_format *f) +{ + int ret, fps, snapshot, compression, pixelformat; + + ret = pwc_vidioc_try_fmt(pdev, f); + if (ret<0) + return ret; + + pixelformat = f->fmt.pix.pixelformat; + compression = pdev->vcompression; + snapshot = 0; + fps = pdev->vframes; + if (f->fmt.pix.priv) { + compression = (f->fmt.pix.priv & PWC_QLT_MASK) >> PWC_QLT_SHIFT; + snapshot = !!(f->fmt.pix.priv & PWC_FPS_SNAPSHOT); + fps = (f->fmt.pix.priv & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT; + if (fps == 0) + fps = pdev->vframes; + } + + if (pixelformat == V4L2_PIX_FMT_YUV420) + pdev->vpalette = VIDEO_PALETTE_YUV420P; + else + pdev->vpalette = VIDEO_PALETTE_RAW; + + PWC_DEBUG_IOCTL("Try to change format to: width=%d height=%d fps=%d " + "compression=%d snapshot=%d format=%c%c%c%c\n", + f->fmt.pix.width, f->fmt.pix.height, fps, + compression, snapshot, + (pixelformat)&255, + (pixelformat>>8)&255, + (pixelformat>>16)&255, + (pixelformat>>24)&255); + + ret = pwc_try_video_mode(pdev, + f->fmt.pix.width, + f->fmt.pix.height, + fps, + compression, + snapshot); + + PWC_DEBUG_IOCTL("pwc_try_video_mode(), return=%d\n", ret); + + if (ret) + return ret; + + pwc_vidioc_fill_fmt(pdev, f); + + return 0; + +} + +int pwc_video_do_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, void *arg) +{ + struct video_device *vdev = video_devdata(file); + struct pwc_device *pdev; + DECLARE_WAITQUEUE(wait, current); + + if (vdev == NULL) + return -EFAULT; + pdev = vdev->priv; + if (pdev == NULL) + return -EFAULT; + +#if CONFIG_PWC_DEBUG + if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace) + v4l_printk_ioctl(cmd); +#endif + + + switch (cmd) { + /* Query cabapilities */ + case VIDIOCGCAP: + { + struct video_capability *caps = arg; + + strcpy(caps->name, vdev->name); + caps->type = VID_TYPE_CAPTURE; + caps->channels = 1; + caps->audios = 1; + caps->minwidth = pdev->view_min.x; + caps->minheight = pdev->view_min.y; + caps->maxwidth = pdev->view_max.x; + caps->maxheight = pdev->view_max.y; + break; + } + + /* Channel functions (simulate 1 channel) */ + case VIDIOCGCHAN: + { + struct video_channel *v = arg; + + if (v->channel != 0) + return -EINVAL; + v->flags = 0; + v->tuners = 0; + v->type = VIDEO_TYPE_CAMERA; + strcpy(v->name, "Webcam"); + return 0; + } + + case VIDIOCSCHAN: + { + /* The spec says the argument is an integer, but + the bttv driver uses a video_channel arg, which + makes sense becasue it also has the norm flag. + */ + struct video_channel *v = arg; + if (v->channel != 0) + return -EINVAL; + return 0; + } + + + /* Picture functions; contrast etc. */ + case VIDIOCGPICT: + { + struct video_picture *p = arg; + int val; + + val = pwc_get_brightness(pdev); + if (val >= 0) + p->brightness = (val<<9); + else + p->brightness = 0xffff; + val = pwc_get_contrast(pdev); + if (val >= 0) + p->contrast = (val<<10); + else + p->contrast = 0xffff; + /* Gamma, Whiteness, what's the difference? :) */ + val = pwc_get_gamma(pdev); + if (val >= 0) + p->whiteness = (val<<11); + else + p->whiteness = 0xffff; + if (pwc_get_saturation(pdev, &val)<0) + p->colour = 0xffff; + else + p->colour = 32768 + val * 327; + p->depth = 24; + p->palette = pdev->vpalette; + p->hue = 0xFFFF; /* N/A */ + break; + } + + case VIDIOCSPICT: + { + struct video_picture *p = arg; + /* + * FIXME: Suppose we are mid read + ANSWER: No problem: the firmware of the camera + can handle brightness/contrast/etc + changes at _any_ time, and the palette + is used exactly once in the uncompress + routine. + */ + pwc_set_brightness(pdev, p->brightness); + pwc_set_contrast(pdev, p->contrast); + pwc_set_gamma(pdev, p->whiteness); + pwc_set_saturation(pdev, (p->colour-32768)/327); + if (p->palette && p->palette != pdev->vpalette) { + switch (p->palette) { + case VIDEO_PALETTE_YUV420P: + case VIDEO_PALETTE_RAW: + pdev->vpalette = p->palette; + return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot); + break; + default: + return -EINVAL; + break; + } + } + break; + } + + /* Window/size parameters */ + case VIDIOCGWIN: + { + struct video_window *vw = arg; + + vw->x = 0; + vw->y = 0; + vw->width = pdev->view.x; + vw->height = pdev->view.y; + vw->chromakey = 0; + vw->flags = (pdev->vframes << PWC_FPS_SHIFT) | + (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0); + break; + } + + case VIDIOCSWIN: + { + struct video_window *vw = arg; + int fps, snapshot, ret; + + fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT; + snapshot = vw->flags & PWC_FPS_SNAPSHOT; + if (fps == 0) + fps = pdev->vframes; + if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot) + return 0; + ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot); + if (ret) + return ret; + break; + } + + /* We don't have overlay support (yet) */ + case VIDIOCGFBUF: + { + struct video_buffer *vb = arg; + + memset(vb,0,sizeof(*vb)); + break; + } + + /* mmap() functions */ + case VIDIOCGMBUF: + { + /* Tell the user program how much memory is needed for a mmap() */ + struct video_mbuf *vm = arg; + int i; + + memset(vm, 0, sizeof(*vm)); + vm->size = pwc_mbufs * pdev->len_per_image; + vm->frames = pwc_mbufs; /* double buffering should be enough for most applications */ + for (i = 0; i < pwc_mbufs; i++) + vm->offsets[i] = i * pdev->len_per_image; + break; + } + + case VIDIOCMCAPTURE: + { + /* Start capture into a given image buffer (called 'frame' in video_mmap structure) */ + struct video_mmap *vm = arg; + + PWC_DEBUG_READ("VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format); + if (vm->frame < 0 || vm->frame >= pwc_mbufs) + return -EINVAL; + + /* xawtv is nasty. It probes the available palettes + by setting a very small image size and trying + various palettes... The driver doesn't support + such small images, so I'm working around it. + */ + if (vm->format) + { + switch (vm->format) + { + case VIDEO_PALETTE_YUV420P: + case VIDEO_PALETTE_RAW: + break; + default: + return -EINVAL; + break; + } + } + + if ((vm->width != pdev->view.x || vm->height != pdev->view.y) && + (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) { + int ret; + + PWC_DEBUG_OPEN("VIDIOCMCAPTURE: changing size to please xawtv :-(.\n"); + ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot); + if (ret) + return ret; + } /* ... size mismatch */ + + /* FIXME: should we lock here? */ + if (pdev->image_used[vm->frame]) + return -EBUSY; /* buffer wasn't available. Bummer */ + pdev->image_used[vm->frame] = 1; + + /* Okay, we're done here. In the SYNC call we wait until a + frame comes available, then expand image into the given + buffer. + In contrast to the CPiA cam the Philips cams deliver a + constant stream, almost like a grabber card. Also, + we have separate buffers for the rawdata and the image, + meaning we can nearly always expand into the requested buffer. + */ + PWC_DEBUG_READ("VIDIOCMCAPTURE done.\n"); + break; + } + + case VIDIOCSYNC: + { + /* The doc says: "Whenever a buffer is used it should + call VIDIOCSYNC to free this frame up and continue." + + The only odd thing about this whole procedure is + that MCAPTURE flags the buffer as "in use", and + SYNC immediately unmarks it, while it isn't + after SYNC that you know that the buffer actually + got filled! So you better not start a CAPTURE in + the same frame immediately (use double buffering). + This is not a problem for this cam, since it has + extra intermediate buffers, but a hardware + grabber card will then overwrite the buffer + you're working on. + */ + int *mbuf = arg; + int ret; + + PWC_DEBUG_READ("VIDIOCSYNC called (%d).\n", *mbuf); + + /* bounds check */ + if (*mbuf < 0 || *mbuf >= pwc_mbufs) + return -EINVAL; + /* check if this buffer was requested anyway */ + if (pdev->image_used[*mbuf] == 0) + return -EINVAL; + + /* Add ourselves to the frame wait-queue. + + FIXME: needs auditing for safety. + QUESTION: In what respect? I think that using the + frameq is safe now. + */ + add_wait_queue(&pdev->frameq, &wait); + while (pdev->full_frames == NULL) { + /* Check for unplugged/etc. here */ + if (pdev->error_status) { + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + return -pdev->error_status; + } + + if (signal_pending(current)) { + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + return -ERESTARTSYS; + } + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + } + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + + /* The frame is ready. Expand in the image buffer + requested by the user. I don't care if you + mmap() 5 buffers and request data in this order: + buffer 4 2 3 0 1 2 3 0 4 3 1 . . . + Grabber hardware may not be so forgiving. + */ + PWC_DEBUG_READ("VIDIOCSYNC: frame ready.\n"); + pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */ + /* Decompress, etc */ + ret = pwc_handle_frame(pdev); + pdev->image_used[*mbuf] = 0; + if (ret) + return -EFAULT; + break; + } + + case VIDIOCGAUDIO: + { + struct video_audio *v = arg; + + strcpy(v->name, "Microphone"); + v->audio = -1; /* unknown audio minor */ + v->flags = 0; + v->mode = VIDEO_SOUND_MONO; + v->volume = 0; + v->bass = 0; + v->treble = 0; + v->balance = 0x8000; + v->step = 1; + break; + } + + case VIDIOCSAUDIO: + { + /* Dummy: nothing can be set */ + break; + } + + case VIDIOCGUNIT: + { + struct video_unit *vu = arg; + + vu->video = pdev->vdev->minor & 0x3F; + vu->audio = -1; /* not known yet */ + vu->vbi = -1; + vu->radio = -1; + vu->teletext = -1; + break; + } + + /* V4L2 Layer */ + case VIDIOC_QUERYCAP: + { + struct v4l2_capability *cap = arg; + + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCAP) This application "\ + "try to use the v4l2 layer\n"); + strcpy(cap->driver,PWC_NAME); + strlcpy(cap->card, vdev->name, sizeof(cap->card)); + usb_make_path(pdev->udev,cap->bus_info,sizeof(cap->bus_info)); + cap->version = PWC_VERSION_CODE; + cap->capabilities = + V4L2_CAP_VIDEO_CAPTURE | + V4L2_CAP_STREAMING | + V4L2_CAP_READWRITE; + return 0; + } + + case VIDIOC_ENUMINPUT: + { + struct v4l2_input *i = arg; + + if ( i->index ) /* Only one INPUT is supported */ + return -EINVAL; + + memset(i, 0, sizeof(struct v4l2_input)); + strcpy(i->name, "usb"); + return 0; + } + + case VIDIOC_G_INPUT: + { + int *i = arg; + *i = 0; /* Only one INPUT is supported */ + return 0; + } + case VIDIOC_S_INPUT: + { + int *i = arg; + + if ( *i ) { /* Only one INPUT is supported */ + PWC_DEBUG_IOCTL("Only one input source is"\ + " supported with this webcam.\n"); + return -EINVAL; + } + return 0; + } + + /* TODO: */ + case VIDIOC_QUERYCTRL: + { + struct v4l2_queryctrl *c = arg; + int i; + + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) query id=%d\n", c->id); + for (i=0; i<sizeof(pwc_controls)/sizeof(struct v4l2_queryctrl); i++) { + if (pwc_controls[i].id == c->id) { + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) found\n"); + memcpy(c,&pwc_controls[i],sizeof(struct v4l2_queryctrl)); + return 0; + } + } + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) not found\n"); + + return -EINVAL; + } + case VIDIOC_G_CTRL: + { + struct v4l2_control *c = arg; + int ret; + + switch (c->id) + { + case V4L2_CID_BRIGHTNESS: + c->value = pwc_get_brightness(pdev); + if (c->value<0) + return -EINVAL; + return 0; + case V4L2_CID_CONTRAST: + c->value = pwc_get_contrast(pdev); + if (c->value<0) + return -EINVAL; + return 0; + case V4L2_CID_SATURATION: + ret = pwc_get_saturation(pdev, &c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_GAMMA: + c->value = pwc_get_gamma(pdev); + if (c->value<0) + return -EINVAL; + return 0; + case V4L2_CID_RED_BALANCE: + ret = pwc_get_red_gain(pdev, &c->value); + if (ret<0) + return -EINVAL; + c->value >>= 8; + return 0; + case V4L2_CID_BLUE_BALANCE: + ret = pwc_get_blue_gain(pdev, &c->value); + if (ret<0) + return -EINVAL; + c->value >>= 8; + return 0; + case V4L2_CID_AUTO_WHITE_BALANCE: + ret = pwc_get_awb(pdev); + if (ret<0) + return -EINVAL; + c->value = (ret == PWC_WB_MANUAL)?0:1; + return 0; + case V4L2_CID_GAIN: + ret = pwc_get_agc(pdev, &c->value); + if (ret<0) + return -EINVAL; + c->value >>= 8; + return 0; + case V4L2_CID_AUTOGAIN: + ret = pwc_get_agc(pdev, &c->value); + if (ret<0) + return -EINVAL; + c->value = (c->value < 0)?1:0; + return 0; + case V4L2_CID_EXPOSURE: + ret = pwc_get_shutter_speed(pdev, &c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_COLOUR_MODE: + ret = pwc_get_colour_mode(pdev, &c->value); + if (ret < 0) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_AUTOCONTOUR: + ret = pwc_get_contour(pdev, &c->value); + if (ret < 0) + return -EINVAL; + c->value=(c->value == -1?1:0); + return 0; + case V4L2_CID_PRIVATE_CONTOUR: + ret = pwc_get_contour(pdev, &c->value); + if (ret < 0) + return -EINVAL; + c->value >>= 10; + return 0; + case V4L2_CID_PRIVATE_BACKLIGHT: + ret = pwc_get_backlight(pdev, &c->value); + if (ret < 0) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_FLICKERLESS: + ret = pwc_get_flicker(pdev, &c->value); + if (ret < 0) + return -EINVAL; + c->value=(c->value?1:0); + return 0; + case V4L2_CID_PRIVATE_NOISE_REDUCTION: + ret = pwc_get_dynamic_noise(pdev, &c->value); + if (ret < 0) + return -EINVAL; + return 0; + + case V4L2_CID_PRIVATE_SAVE_USER: + case V4L2_CID_PRIVATE_RESTORE_USER: + case V4L2_CID_PRIVATE_RESTORE_FACTORY: + return -EINVAL; + } + return -EINVAL; + } + case VIDIOC_S_CTRL: + { + struct v4l2_control *c = arg; + int ret; + + switch (c->id) + { + case V4L2_CID_BRIGHTNESS: + c->value <<= 9; + ret = pwc_set_brightness(pdev, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_CONTRAST: + c->value <<= 10; + ret = pwc_set_contrast(pdev, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_SATURATION: + ret = pwc_set_saturation(pdev, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_GAMMA: + c->value <<= 11; + ret = pwc_set_gamma(pdev, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_RED_BALANCE: + c->value <<= 8; + ret = pwc_set_red_gain(pdev, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_BLUE_BALANCE: + c->value <<= 8; + ret = pwc_set_blue_gain(pdev, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_AUTO_WHITE_BALANCE: + c->value = (c->value == 0)?PWC_WB_MANUAL:PWC_WB_AUTO; + ret = pwc_set_awb(pdev, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_EXPOSURE: + c->value <<= 8; + ret = pwc_set_shutter_speed(pdev, c->value?0:1, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_AUTOGAIN: + /* autogain off means nothing without a gain */ + if (c->value == 0) + return 0; + ret = pwc_set_agc(pdev, c->value, 0); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_GAIN: + c->value <<= 8; + ret = pwc_set_agc(pdev, 0, c->value); + if (ret<0) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_SAVE_USER: + if (pwc_save_user(pdev)) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_RESTORE_USER: + if (pwc_restore_user(pdev)) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_RESTORE_FACTORY: + if (pwc_restore_factory(pdev)) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_COLOUR_MODE: + ret = pwc_set_colour_mode(pdev, c->value); + if (ret < 0) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_AUTOCONTOUR: + c->value=(c->value == 1)?-1:0; + ret = pwc_set_contour(pdev, c->value); + if (ret < 0) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_CONTOUR: + c->value <<= 10; + ret = pwc_set_contour(pdev, c->value); + if (ret < 0) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_BACKLIGHT: + ret = pwc_set_backlight(pdev, c->value); + if (ret < 0) + return -EINVAL; + return 0; + case V4L2_CID_PRIVATE_FLICKERLESS: + ret = pwc_set_flicker(pdev, c->value); + if (ret < 0) + return -EINVAL; + case V4L2_CID_PRIVATE_NOISE_REDUCTION: + ret = pwc_set_dynamic_noise(pdev, c->value); + if (ret < 0) + return -EINVAL; + return 0; + + } + return -EINVAL; + } + + case VIDIOC_ENUM_FMT: + { + struct v4l2_fmtdesc *f = arg; + int index; + + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + /* We only support two format: the raw format, and YUV */ + index = f->index; + memset(f,0,sizeof(struct v4l2_fmtdesc)); + f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + f->index = index; + switch(index) + { + case 0: + /* RAW format */ + f->pixelformat = pdev->type<=646?V4L2_PIX_FMT_PWC1:V4L2_PIX_FMT_PWC2; + f->flags = V4L2_FMT_FLAG_COMPRESSED; + strlcpy(f->description,"Raw Philips Webcam",sizeof(f->description)); + break; + case 1: + f->pixelformat = V4L2_PIX_FMT_YUV420; + strlcpy(f->description,"4:2:0, planar, Y-Cb-Cr",sizeof(f->description)); + break; + default: + return -EINVAL; + } + return 0; + } + + case VIDIOC_G_FMT: + { + struct v4l2_format *f = arg; + + PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",pdev->image.x,pdev->image.y); + if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + pwc_vidioc_fill_fmt(pdev, f); + + return 0; + } + + case VIDIOC_TRY_FMT: + return pwc_vidioc_try_fmt(pdev, arg); + + case VIDIOC_S_FMT: + return pwc_vidioc_set_fmt(pdev, arg); + + case VIDIOC_G_STD: + { + v4l2_std_id *std = arg; + *std = V4L2_STD_UNKNOWN; + return 0; + } + + case VIDIOC_S_STD: + { + v4l2_std_id *std = arg; + if (*std != V4L2_STD_UNKNOWN) + return -EINVAL; + return 0; + } + + case VIDIOC_ENUMSTD: + { + struct v4l2_standard *std = arg; + if (std->index != 0) + return -EINVAL; + std->id = V4L2_STD_UNKNOWN; + strncpy(std->name, "webcam", sizeof(std->name)); + return 0; + } + + case VIDIOC_REQBUFS: + { + struct v4l2_requestbuffers *rb = arg; + int nbuffers; + + PWC_DEBUG_IOCTL("ioctl(VIDIOC_REQBUFS) count=%d\n",rb->count); + if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (rb->memory != V4L2_MEMORY_MMAP) + return -EINVAL; + + nbuffers = rb->count; + if (nbuffers < 2) + nbuffers = 2; + else if (nbuffers > pwc_mbufs) + nbuffers = pwc_mbufs; + /* Force to use our # of buffers */ + rb->count = pwc_mbufs; + return 0; + } + + case VIDIOC_QUERYBUF: + { + struct v4l2_buffer *buf = arg; + int index; + + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) index=%d\n",buf->index); + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad type\n"); + return -EINVAL; + } + if (buf->memory != V4L2_MEMORY_MMAP) { + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad memory type\n"); + return -EINVAL; + } + index = buf->index; + if (index < 0 || index >= pwc_mbufs) { + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad index %d\n", buf->index); + return -EINVAL; + } + + memset(buf, 0, sizeof(struct v4l2_buffer)); + buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf->index = index; + buf->m.offset = index * pdev->len_per_image; + if (pdev->vpalette == VIDEO_PALETTE_RAW) + buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame); + else + buf->bytesused = pdev->view.size; + buf->field = V4L2_FIELD_NONE; + buf->memory = V4L2_MEMORY_MMAP; + //buf->flags = V4L2_BUF_FLAG_MAPPED; + buf->length = pdev->len_per_image; + + PWC_DEBUG_READ("VIDIOC_QUERYBUF: index=%d\n",buf->index); + PWC_DEBUG_READ("VIDIOC_QUERYBUF: m.offset=%d\n",buf->m.offset); + PWC_DEBUG_READ("VIDIOC_QUERYBUF: bytesused=%d\n",buf->bytesused); + + return 0; + } + + case VIDIOC_QBUF: + { + struct v4l2_buffer *buf = arg; + + PWC_DEBUG_IOCTL("ioctl(VIDIOC_QBUF) index=%d\n",buf->index); + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + if (buf->memory != V4L2_MEMORY_MMAP) + return -EINVAL; + if (buf->index < 0 || buf->index >= pwc_mbufs) + return -EINVAL; + + buf->flags |= V4L2_BUF_FLAG_QUEUED; + buf->flags &= ~V4L2_BUF_FLAG_DONE; + + return 0; + } + + case VIDIOC_DQBUF: + { + struct v4l2_buffer *buf = arg; + int ret; + + PWC_DEBUG_IOCTL("ioctl(VIDIOC_DQBUF)\n"); + + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return -EINVAL; + + /* Add ourselves to the frame wait-queue. + + FIXME: needs auditing for safety. + QUESTION: In what respect? I think that using the + frameq is safe now. + */ + add_wait_queue(&pdev->frameq, &wait); + while (pdev->full_frames == NULL) { + if (pdev->error_status) { + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + return -pdev->error_status; + } + + if (signal_pending(current)) { + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + return -ERESTARTSYS; + } + schedule(); + set_current_state(TASK_INTERRUPTIBLE); + } + remove_wait_queue(&pdev->frameq, &wait); + set_current_state(TASK_RUNNING); + + PWC_DEBUG_IOCTL("VIDIOC_DQBUF: frame ready.\n"); + /* Decompress data in pdev->images[pdev->fill_image] */ + ret = pwc_handle_frame(pdev); + if (ret) + return -EFAULT; + PWC_DEBUG_IOCTL("VIDIOC_DQBUF: after pwc_handle_frame\n"); + + buf->index = pdev->fill_image; + if (pdev->vpalette == VIDEO_PALETTE_RAW) + buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame); + else + buf->bytesused = pdev->view.size; + buf->flags = V4L2_BUF_FLAG_MAPPED; + buf->field = V4L2_FIELD_NONE; + do_gettimeofday(&buf->timestamp); + buf->sequence = 0; + buf->memory = V4L2_MEMORY_MMAP; + buf->m.offset = pdev->fill_image * pdev->len_per_image; + buf->length = buf->bytesused; + pwc_next_image(pdev); + + PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->index=%d\n",buf->index); + PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->length=%d\n",buf->length); + PWC_DEBUG_IOCTL("VIDIOC_DQBUF: m.offset=%d\n",buf->m.offset); + PWC_DEBUG_IOCTL("VIDIOC_DQBUF: bytesused=%d\n",buf->bytesused); + PWC_DEBUG_IOCTL("VIDIOC_DQBUF: leaving\n"); + return 0; + + } + + case VIDIOC_STREAMON: + { + /* WARNING: pwc_try_video_mode() called pwc_isoc_init */ + pwc_isoc_init(pdev); + return 0; + } + + case VIDIOC_STREAMOFF: + { + pwc_isoc_cleanup(pdev); + return 0; + } + + default: + return pwc_ioctl(pdev, cmd, arg); + } /* ..switch */ + return 0; +} + +/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ diff --git a/drivers/media/video/tlv320aic23b.c b/drivers/media/video/tlv320aic23b.c new file mode 100644 index 000000000..76b2e9642 --- /dev/null +++ b/drivers/media/video/tlv320aic23b.c @@ -0,0 +1,217 @@ +/* + * tlv320aic23b - driver version 0.0.1 + * + * Copyright (C) 2006 Scott Alfter <salfter@ssai.us> + * + * Based on wm8775 driver + * + * Copyright (C) 2004 Ulf Eklund <ivtv at eklund.to> + * Copyright (C) 2005 Hans Verkuil <hverkuil@xs4all.nl> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/types.h> +#include <linux/ioctl.h> +#include <asm/uaccess.h> +#include <linux/i2c.h> +#include <linux/i2c-id.h> +#include <linux/videodev.h> +#include <media/v4l2-common.h> + +MODULE_DESCRIPTION("tlv320aic23b driver"); +MODULE_AUTHOR("Scott Alfter, Ulf Eklund, Hans Verkuil"); +MODULE_LICENSE("GPL"); + +static unsigned short normal_i2c[] = { 0x34 >> 1, I2C_CLIENT_END }; + + +I2C_CLIENT_INSMOD; + +/* ----------------------------------------------------------------------- */ + +struct tlv320aic23b_state { + u8 muted; +}; + +static int tlv320aic23b_write(struct i2c_client *client, int reg, u16 val) +{ + int i; + + if ((reg < 0 || reg > 9) && (reg != 15)) { + v4l_err(client, "Invalid register R%d\n", reg); + return -1; + } + + for (i = 0; i < 3; i++) { + if (i2c_smbus_write_byte_data(client, (reg << 1) | + (val >> 8), val & 0xff) == 0) { + return 0; + } + } + v4l_err(client, "I2C: cannot write %03x to register R%d\n", val, reg); + return -1; +} + +static int tlv320aic23b_command(struct i2c_client *client, unsigned int cmd, + void *arg) +{ + struct tlv320aic23b_state *state = i2c_get_clientdata(client); + struct v4l2_control *ctrl = arg; + u32* freq = arg; + + switch (cmd) { + case VIDIOC_INT_AUDIO_CLOCK_FREQ: + switch (*freq) { + case 32000: /* set sample rate to 32 kHz */ + tlv320aic23b_write(client, 8, 0x018); + break; + case 44100: /* set sample rate to 44.1 kHz */ + tlv320aic23b_write(client, 8, 0x022); + break; + case 48000: /* set sample rate to 48 kHz */ + tlv320aic23b_write(client, 8, 0x000); + break; + default: + return -EINVAL; + } + break; + + case VIDIOC_G_CTRL: + if (ctrl->id != V4L2_CID_AUDIO_MUTE) + return -EINVAL; + ctrl->value = state->muted; + break; + + case VIDIOC_S_CTRL: + if (ctrl->id != V4L2_CID_AUDIO_MUTE) + return -EINVAL; + state->muted = ctrl->value; + tlv320aic23b_write(client, 0, 0x180); /* mute both channels */ + /* set gain on both channels to +3.0 dB */ + if (!state->muted) + tlv320aic23b_write(client, 0, 0x119); + break; + + case VIDIOC_LOG_STATUS: + v4l_info(client, "Input: %s\n", + state->muted ? "muted" : "active"); + break; + + default: + return -EINVAL; + } + return 0; +} + +/* ----------------------------------------------------------------------- */ + +/* i2c implementation */ + +/* + * Generic i2c probe + * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1' + */ + +static struct i2c_driver i2c_driver; + +static int tlv320aic23b_attach(struct i2c_adapter *adapter, int address, int kind) +{ + struct i2c_client *client; + struct tlv320aic23b_state *state; + + /* Check if the adapter supports the needed features */ + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return 0; + + client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (client == 0) + return -ENOMEM; + + client->addr = address; + client->adapter = adapter; + client->driver = &i2c_driver; + snprintf(client->name, sizeof(client->name) - 1, "tlv320aic23b"); + + v4l_info(client, "chip found @ 0x%x (%s)\n", address << 1, adapter->name); + + state = kmalloc(sizeof(struct tlv320aic23b_state), GFP_KERNEL); + if (state == NULL) { + kfree(client); + return -ENOMEM; + } + state->muted = 0; + i2c_set_clientdata(client, state); + + /* initialize tlv320aic23b */ + tlv320aic23b_write(client, 15, 0x000); /* RESET */ + tlv320aic23b_write(client, 6, 0x00A); /* turn off DAC & mic input */ + tlv320aic23b_write(client, 7, 0x049); /* left-justified, 24-bit, master mode */ + tlv320aic23b_write(client, 0, 0x119); /* set gain on both channels to +3.0 dB */ + tlv320aic23b_write(client, 8, 0x000); /* set sample rate to 48 kHz */ + tlv320aic23b_write(client, 9, 0x001); /* activate digital interface */ + + i2c_attach_client(client); + + return 0; +} + +static int tlv320aic23b_probe(struct i2c_adapter *adapter) +{ + if (adapter->class & I2C_CLASS_TV_ANALOG) + return i2c_probe(adapter, &addr_data, tlv320aic23b_attach); + return 0; +} + +static int tlv320aic23b_detach(struct i2c_client *client) +{ + int err; + + err = i2c_detach_client(client); + if (err) { + return err; + } + kfree(client); + + return 0; +} + +/* ----------------------------------------------------------------------- */ + +/* i2c implementation */ +static struct i2c_driver i2c_driver = { + .driver = { + .name = "tlv320aic23b", + }, + .id = I2C_DRIVERID_TLV320AIC23B, + .attach_adapter = tlv320aic23b_probe, + .detach_client = tlv320aic23b_detach, + .command = tlv320aic23b_command, +}; + + +static int __init tlv320aic23b_init_module(void) +{ + return i2c_add_driver(&i2c_driver); +} + +static void __exit tlv320aic23b_cleanup_module(void) +{ + i2c_del_driver(&i2c_driver); +} + +module_init(tlv320aic23b_init_module); +module_exit(tlv320aic23b_cleanup_module); diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c new file mode 100644 index 000000000..56e01b622 --- /dev/null +++ b/drivers/media/video/usbvideo/quickcam_messenger.c @@ -0,0 +1,1120 @@ +/* + * Driver for Logitech Quickcam Messenger usb video camera + * Copyright (C) Jaya Kumar + * + * This work was sponsored by CIS(M) Sdn Bhd. + * History: + * 05/08/2006 - Jaya Kumar + * I wrote this based on the konicawc by Simon Evans. + * - + * Full credit for reverse engineering and creating an initial + * working linux driver for the VV6422 goes to the qce-ga project by + * Tuukka Toivonen, Jochen Hoenicke, Peter McConnell, + * Cristiano De Michele, Georg Acher, Jean-Frederic Clere as well as + * others. + * --- + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/usb/input.h> + +#include "usbvideo.h" +#include "quickcam_messenger.h" + +/* + * Version Information + */ + +#ifdef CONFIG_USB_DEBUG +static int debug; +#define DEBUG(n, format, arg...) \ + if (n <= debug) { \ + printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \ + } +#else +#define DEBUG(n, arg...) +static const int debug = 0; +#endif + +#define DRIVER_VERSION "v0.01" +#define DRIVER_DESC "Logitech Quickcam Messenger USB" + +#define USB_LOGITECH_VENDOR_ID 0x046D +#define USB_QCM_PRODUCT_ID 0x08F0 + +#define MAX_CAMERAS 1 + +#define MAX_COLOUR 32768 +#define MAX_HUE 32768 +#define MAX_BRIGHTNESS 32768 +#define MAX_CONTRAST 32768 +#define MAX_WHITENESS 32768 + +static int size = SIZE_320X240; +static int colour = MAX_COLOUR; +static int hue = MAX_HUE; +static int brightness = MAX_BRIGHTNESS; +static int contrast = MAX_CONTRAST; +static int whiteness = MAX_WHITENESS; + +static struct usbvideo *cams; + +static struct usb_device_id qcm_table [] = { + { USB_DEVICE(USB_LOGITECH_VENDOR_ID, USB_QCM_PRODUCT_ID) }, + { } +}; +MODULE_DEVICE_TABLE(usb, qcm_table); + +#ifdef CONFIG_INPUT +static void qcm_register_input(struct qcm *cam, struct usb_device *dev) +{ + struct input_dev *input_dev; + + usb_make_path(dev, cam->input_physname, sizeof(cam->input_physname)); + strncat(cam->input_physname, "/input0", sizeof(cam->input_physname)); + + cam->input = input_dev = input_allocate_device(); + if (!input_dev) { + warn("insufficient mem for cam input device"); + return; + } + + input_dev->name = "QCM button"; + input_dev->phys = cam->input_physname; + usb_to_input_id(dev, &input_dev->id); + input_dev->cdev.dev = &dev->dev; + + input_dev->evbit[0] = BIT(EV_KEY); + input_dev->keybit[LONG(BTN_0)] = BIT(BTN_0); + + input_dev->private = cam; + + input_register_device(cam->input); +} + +static void qcm_unregister_input(struct qcm *cam) +{ + if (cam->input) { + input_unregister_device(cam->input); + cam->input = NULL; + } +} + +static void qcm_report_buttonstat(struct qcm *cam) +{ + if (cam->input) { + input_report_key(cam->input, BTN_0, cam->button_sts); + input_sync(cam->input); + } +} + +static void qcm_int_irq(struct urb *urb, struct pt_regs *regs) +{ + int ret; + struct uvd *uvd = urb->context; + struct qcm *cam; + + if (!CAMERA_IS_OPERATIONAL(uvd)) + return; + + if (!uvd->streaming) + return; + + uvd->stats.urb_count++; + + if (urb->status < 0) + uvd->stats.iso_err_count++; + else { + if (urb->actual_length > 0 ) { + cam = (struct qcm *) uvd->user_data; + if (cam->button_sts_buf == 0x88) + cam->button_sts = 0x0; + else if (cam->button_sts_buf == 0x80) + cam->button_sts = 0x1; + qcm_report_buttonstat(cam); + } + } + + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret < 0) + err("usb_submit_urb error (%d)", ret); +} + +static int qcm_setup_input_int(struct qcm *cam, struct uvd *uvd) +{ + int errflag; + usb_fill_int_urb(cam->button_urb, uvd->dev, + usb_rcvintpipe(uvd->dev, uvd->video_endp + 1), + &cam->button_sts_buf, + 1, + qcm_int_irq, + uvd, 16); + + errflag = usb_submit_urb(cam->button_urb, GFP_KERNEL); + if (errflag) + err ("usb_submit_int ret %d", errflag); + return errflag; +} + +static void qcm_stop_int_data(struct qcm *cam) +{ + usb_kill_urb(cam->button_urb); +} + +static int qcm_alloc_int_urb(struct qcm *cam) +{ + cam->button_urb = usb_alloc_urb(0, GFP_KERNEL); + + if (!cam->button_urb) + return -ENOMEM; + + return 0; +} + +static void qcm_free_int(struct qcm *cam) +{ + if (cam->button_urb) + usb_free_urb(cam->button_urb); +} +#endif /* CONFIG_INPUT */ + +static int qcm_stv_setb(struct usb_device *dev, u16 reg, u8 val) +{ + int ret; + + /* we'll wait up to 3 slices but no more */ + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + 0x04, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, + reg, 0, &val, 1, 3*HZ); + return ret; +} + +static int qcm_stv_setw(struct usb_device *dev, u16 reg, u16 val) +{ + int ret; + + /* we'll wait up to 3 slices but no more */ + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + 0x04, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, + reg, 0, &val, 2, 3*HZ); + return ret; +} + +static int qcm_stv_getw(struct usb_device *dev, unsigned short reg, + __le16 *val) +{ + int ret; + + /* we'll wait up to 3 slices but no more */ + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + 0x04, USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, + reg, 0, val, 2, 3*HZ); + return ret; +} + +static int qcm_camera_on(struct uvd *uvd) +{ + int ret; + CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x01)); + return 0; +} + +static int qcm_camera_off(struct uvd *uvd) +{ + int ret; + CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x00)); + return 0; +} + +static void qcm_hsv2rgb(u16 hue, u16 sat, u16 val, u16 *r, u16 *g, u16 *b) +{ + unsigned int segment, valsat; + signed int h = (signed int) hue; + unsigned int s = (sat - 32768) * 2; /* rescale */ + unsigned int v = val; + unsigned int p; + + /* + the registers controling gain are 8 bit of which + we affect only the last 4 bits with our gain. + we know that if saturation is 0, (unsaturated) then + we're grayscale (center axis of the colour cone) so + we set rgb=value. we use a formula obtained from + wikipedia to map the cone to the RGB plane. it's + as follows for the human value case of h=0..360, + s=0..1, v=0..1 + h_i = h/60 % 6 , f = h/60 - h_i , p = v(1-s) + q = v(1 - f*s) , t = v(1 - (1-f)s) + h_i==0 => r=v , g=t, b=p + h_i==1 => r=q , g=v, b=p + h_i==2 => r=p , g=v, b=t + h_i==3 => r=p , g=q, b=v + h_i==4 => r=t , g=p, b=v + h_i==5 => r=v , g=p, b=q + the bottom side (the point) and the stuff just up + of that is black so we simplify those two cases. + */ + if (sat < 32768) { + /* anything less than this is unsaturated */ + *r = val; + *g = val; + *b = val; + return; + } + if (val <= (0xFFFF/8)) { + /* anything less than this is black */ + *r = 0; + *g = 0; + *b = 0; + return; + } + + /* the rest of this code is copying tukkat's + implementation of the hsv2rgb conversion as taken + from qc-usb-messenger code. the 10923 is 0xFFFF/6 + to divide the cone into 6 sectors. */ + + segment = (h + 10923) & 0xFFFF; + segment = segment*3 >> 16; /* 0..2: 0=R, 1=G, 2=B */ + hue -= segment * 21845; /* -10923..10923 */ + h = hue; + h *= 3; + valsat = v*s >> 16; /* 0..65534 */ + p = v - valsat; + if (h >= 0) { + unsigned int t = v - (valsat * (32769 - h) >> 15); + switch (segment) { + case 0: /* R-> */ + *r = v; + *g = t; + *b = p; + break; + case 1: /* G-> */ + *r = p; + *g = v; + *b = t; + break; + case 2: /* B-> */ + *r = t; + *g = p; + *b = v; + break; + } + } else { + unsigned int q = v - (valsat * (32769 + h) >> 15); + switch (segment) { + case 0: /* ->R */ + *r = v; + *g = p; + *b = q; + break; + case 1: /* ->G */ + *r = q; + *g = v; + *b = p; + break; + case 2: /* ->B */ + *r = p; + *g = q; + *b = v; + break; + } + } +} + +static int qcm_sensor_set_gains(struct uvd *uvd, u16 hue, + u16 saturation, u16 value) +{ + int ret; + u16 r=0,g=0,b=0; + + /* this code is based on qc-usb-messenger */ + qcm_hsv2rgb(hue, saturation, value, &r, &g, &b); + + r >>= 12; + g >>= 12; + b >>= 12; + + /* min val is 8 */ + r = max((u16) 8, r); + g = max((u16) 8, g); + b = max((u16) 8, b); + + r |= 0x30; + g |= 0x30; + b |= 0x30; + + /* set the r,g,b gain registers */ + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x0509, r)); + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050A, g)); + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050B, b)); + + /* doing as qc-usb did */ + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050C, 0x2A)); + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x050D, 0x01)); + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01)); + + return 0; +} + +static int qcm_sensor_set_exposure(struct uvd *uvd, int exposure) +{ + int ret; + int formedval; + + /* calculation was from qc-usb-messenger driver */ + formedval = ( exposure >> 12 ); + + /* max value for formedval is 14 */ + formedval = min(formedval, 14); + + CHECK_RET(ret, qcm_stv_setb(uvd->dev, + 0x143A, 0xF0 | formedval)); + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01)); + return 0; +} + +static int qcm_sensor_setlevels(struct uvd *uvd, int brightness, int contrast, + int hue, int colour) +{ + int ret; + /* brightness is exposure, contrast is gain, colour is saturation */ + CHECK_RET(ret, + qcm_sensor_set_exposure(uvd, brightness)); + CHECK_RET(ret, qcm_sensor_set_gains(uvd, hue, colour, contrast)); + + return 0; +} + +static int qcm_sensor_setsize(struct uvd *uvd, u8 size) +{ + int ret; + + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x1505, size)); + return 0; +} + +static int qcm_sensor_set_shutter(struct uvd *uvd, int whiteness) +{ + int ret; + /* some rescaling as done by the qc-usb-messenger code */ + if (whiteness > 0xC000) + whiteness = 0xC000 + (whiteness & 0x3FFF)*8; + + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143D, + (whiteness >> 8) & 0xFF)); + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143E, + (whiteness >> 16) & 0x03)); + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x143F, 0x01)); + + return 0; +} + +static int qcm_sensor_init(struct uvd *uvd) +{ + struct qcm *cam = (struct qcm *) uvd->user_data; + int ret; + int i; + + for (i=0; i < sizeof(regval_table)/sizeof(regval_table[0]) ; i++) { + CHECK_RET(ret, qcm_stv_setb(uvd->dev, + regval_table[i].reg, + regval_table[i].val)); + } + + CHECK_RET(ret, qcm_stv_setw(uvd->dev, 0x15c1, + cpu_to_le16(ISOC_PACKET_SIZE))); + CHECK_RET(ret, qcm_stv_setb(uvd->dev, 0x15c3, 0x08)); + CHECK_RET(ret, ret = qcm_stv_setb(uvd->dev, 0x143f, 0x01)); + + CHECK_RET(ret, qcm_stv_setb(uvd->dev, STV_ISO_ENABLE, 0x00)); + + CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd)); + + CHECK_RET(ret, qcm_sensor_setlevels(uvd, uvd->vpic.brightness, + uvd->vpic.contrast, uvd->vpic.hue, uvd->vpic.colour)); + + CHECK_RET(ret, qcm_sensor_set_shutter(uvd, uvd->vpic.whiteness)); + CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd)); + + return 0; +} + +static int qcm_set_camera_size(struct uvd *uvd) +{ + int ret; + struct qcm *cam = (struct qcm *) uvd->user_data; + + CHECK_RET(ret, qcm_sensor_setsize(uvd, camera_sizes[cam->size].cmd)); + cam->width = camera_sizes[cam->size].width; + cam->height = camera_sizes[cam->size].height; + uvd->videosize = VIDEOSIZE(cam->width, cam->height); + + return 0; +} + +static int qcm_setup_on_open(struct uvd *uvd) +{ + int ret; + + CHECK_RET(ret, qcm_sensor_set_gains(uvd, uvd->vpic.hue, + uvd->vpic.colour, uvd->vpic.contrast)); + CHECK_RET(ret, qcm_sensor_set_exposure(uvd, uvd->vpic.brightness)); + CHECK_RET(ret, qcm_sensor_set_shutter(uvd, uvd->vpic.whiteness)); + CHECK_RET(ret, qcm_set_camera_size(uvd)); + CHECK_RET(ret, qcm_camera_on(uvd)); + return 0; +} + +static void qcm_adjust_picture(struct uvd *uvd) +{ + int ret; + struct qcm *cam = (struct qcm *) uvd->user_data; + + ret = qcm_camera_off(uvd); + if (ret) { + err("can't turn camera off. abandoning pic adjustment"); + return; + } + + /* if there's been a change in contrast, hue, or + colour then we need to recalculate hsv in order + to update gains */ + if ((cam->contrast != uvd->vpic.contrast) || + (cam->hue != uvd->vpic.hue) || + (cam->colour != uvd->vpic.colour)) { + cam->contrast = uvd->vpic.contrast; + cam->hue = uvd->vpic.hue; + cam->colour = uvd->vpic.colour; + ret = qcm_sensor_set_gains(uvd, cam->hue, cam->colour, + cam->contrast); + if (ret) { + err("can't set gains. abandoning pic adjustment"); + return; + } + } + + if (cam->brightness != uvd->vpic.brightness) { + cam->brightness = uvd->vpic.brightness; + ret = qcm_sensor_set_exposure(uvd, cam->brightness); + if (ret) { + err("can't set exposure. abandoning pic adjustment"); + return; + } + } + + if (cam->whiteness != uvd->vpic.whiteness) { + cam->whiteness = uvd->vpic.whiteness; + qcm_sensor_set_shutter(uvd, cam->whiteness); + if (ret) { + err("can't set shutter. abandoning pic adjustment"); + return; + } + } + + ret = qcm_camera_on(uvd); + if (ret) { + err("can't reenable camera. pic adjustment failed"); + return; + } +} + +static int qcm_process_frame(struct uvd *uvd, u8 *cdata, int framelen) +{ + int datalen; + int totaldata; + struct framehdr { + __be16 id; + __be16 len; + }; + struct framehdr *fhdr; + + totaldata = 0; + while (framelen) { + fhdr = (struct framehdr *) cdata; + datalen = be16_to_cpu(fhdr->len); + framelen -= 4; + cdata += 4; + + if ((fhdr->id) == cpu_to_be16(0x8001)) { + RingQueue_Enqueue(&uvd->dp, marker, 4); + totaldata += 4; + continue; + } + if ((fhdr->id & cpu_to_be16(0xFF00)) == cpu_to_be16(0x0200)) { + RingQueue_Enqueue(&uvd->dp, cdata, datalen); + totaldata += datalen; + } + framelen -= datalen; + cdata += datalen; + } + return totaldata; +} + +static int qcm_compress_iso(struct uvd *uvd, struct urb *dataurb) +{ + int totlen; + int i; + unsigned char *cdata; + + totlen=0; + for (i = 0; i < dataurb->number_of_packets; i++) { + int n = dataurb->iso_frame_desc[i].actual_length; + int st = dataurb->iso_frame_desc[i].status; + + cdata = dataurb->transfer_buffer + + dataurb->iso_frame_desc[i].offset; + + if (st < 0) { + warn("Data error: packet=%d. len=%d. status=%d.", + i, n, st); + uvd->stats.iso_err_count++; + continue; + } + if (!n) + continue; + + totlen += qcm_process_frame(uvd, cdata, n); + } + return totlen; +} + +static void resubmit_urb(struct uvd *uvd, struct urb *urb) +{ + int ret; + + urb->dev = uvd->dev; + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) + err("usb_submit_urb error (%d)", ret); +} + +static void qcm_isoc_irq(struct urb *urb, struct pt_regs *regs) +{ + int len; + struct uvd *uvd = urb->context; + + if (!CAMERA_IS_OPERATIONAL(uvd)) + return; + + if (!uvd->streaming) + return; + + uvd->stats.urb_count++; + + if (!urb->actual_length) { + resubmit_urb(uvd, urb); + return; + } + + len = qcm_compress_iso(uvd, urb); + resubmit_urb(uvd, urb); + uvd->stats.urb_length = len; + uvd->stats.data_count += len; + if (len) + RingQueue_WakeUpInterruptible(&uvd->dp); +} + +static int qcm_start_data(struct uvd *uvd) +{ + struct qcm *cam = (struct qcm *) uvd->user_data; + int i; + int errflag; + int pktsz; + int err; + + pktsz = uvd->iso_packet_len; + if (!CAMERA_IS_OPERATIONAL(uvd)) { + err("Camera is not operational"); + return -EFAULT; + } + + err = usb_set_interface(uvd->dev, uvd->iface, uvd->ifaceAltActive); + if (err < 0) { + err("usb_set_interface error"); + uvd->last_error = err; + return -EBUSY; + } + + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + int j, k; + struct urb *urb = uvd->sbuf[i].urb; + urb->dev = uvd->dev; + urb->context = uvd; + urb->pipe = usb_rcvisocpipe(uvd->dev, uvd->video_endp); + urb->interval = 1; + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = uvd->sbuf[i].data; + urb->complete = qcm_isoc_irq; + urb->number_of_packets = FRAMES_PER_DESC; + urb->transfer_buffer_length = pktsz * FRAMES_PER_DESC; + for (j=k=0; j < FRAMES_PER_DESC; j++, k += pktsz) { + urb->iso_frame_desc[j].offset = k; + urb->iso_frame_desc[j].length = pktsz; + } + } + + uvd->streaming = 1; + uvd->curframe = -1; + for (i=0; i < USBVIDEO_NUMSBUF; i++) { + errflag = usb_submit_urb(uvd->sbuf[i].urb, GFP_KERNEL); + if (errflag) + err ("usb_submit_isoc(%d) ret %d", i, errflag); + } + + CHECK_RET(err, qcm_setup_input_int(cam, uvd)); + CHECK_RET(err, qcm_camera_on(uvd)); + return 0; +} + +static void qcm_stop_data(struct uvd *uvd) +{ + struct qcm *cam = (struct qcm *) uvd->user_data; + int i, j; + int ret; + + if ((uvd == NULL) || (!uvd->streaming) || (uvd->dev == NULL)) + return; + + ret = qcm_camera_off(uvd); + if (ret) + warn("couldn't turn the cam off."); + + uvd->streaming = 0; + + /* Unschedule all of the iso td's */ + for (i=0; i < USBVIDEO_NUMSBUF; i++) + usb_kill_urb(uvd->sbuf[i].urb); + + qcm_stop_int_data(cam); + + if (!uvd->remove_pending) { + /* Set packet size to 0 */ + j = usb_set_interface(uvd->dev, uvd->iface, + uvd->ifaceAltInactive); + if (j < 0) { + err("usb_set_interface() error %d.", j); + uvd->last_error = j; + } + } +} + +static void qcm_process_isoc(struct uvd *uvd, struct usbvideo_frame *frame) +{ + struct qcm *cam = (struct qcm *) uvd->user_data; + int x; + struct rgb *rgbL0; + struct rgb *rgbL1; + struct bayL0 *bayL0; + struct bayL1 *bayL1; + int hor,ver,hordel,verdel; + assert(frame != NULL); + + switch (cam->size) { + case SIZE_160X120: + hor = 162; ver = 124; hordel = 1; verdel = 2; + break; + case SIZE_320X240: + default: + hor = 324; ver = 248; hordel = 2; verdel = 4; + break; + } + + if (frame->scanstate == ScanState_Scanning) { + while (RingQueue_GetLength(&uvd->dp) >= + 4 + (hor*verdel + hordel)) { + if ((RING_QUEUE_PEEK(&uvd->dp, 0) == 0x00) && + (RING_QUEUE_PEEK(&uvd->dp, 1) == 0xff) && + (RING_QUEUE_PEEK(&uvd->dp, 2) == 0x00) && + (RING_QUEUE_PEEK(&uvd->dp, 3) == 0xff)) { + frame->curline = 0; + frame->scanstate = ScanState_Lines; + frame->frameState = FrameState_Grabbing; + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 4); + /* + * if we're starting, we need to discard the first + * 4 lines of y bayer data + * and the first 2 gr elements of x bayer data + */ + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, + (hor*verdel + hordel)); + break; + } + RING_QUEUE_DEQUEUE_BYTES(&uvd->dp, 1); + } + } + + if (frame->scanstate == ScanState_Scanning) + return; + + /* now we can start processing bayer data so long as we have at least + * 2 lines worth of data. this is the simplest demosaicing method that + * I could think of. I use each 2x2 bayer element without interpolation + * to generate 4 rgb pixels. + */ + while ( frame->curline < cam->height && + (RingQueue_GetLength(&uvd->dp) >= hor*2)) { + /* get 2 lines of bayer for demosaicing + * into 2 lines of RGB */ + RingQueue_Dequeue(&uvd->dp, cam->scratch, hor*2); + bayL0 = (struct bayL0 *) cam->scratch; + bayL1 = (struct bayL1 *) (cam->scratch + hor); + /* frame->curline is the rgb y line */ + rgbL0 = (struct rgb *) + ( frame->data + (cam->width*3*frame->curline)); + /* w/2 because we're already doing 2 pixels */ + rgbL1 = rgbL0 + (cam->width/2); + + for (x=0; x < cam->width; x+=2) { + rgbL0->r = bayL0->r; + rgbL0->g = bayL0->g; + rgbL0->b = bayL1->b; + + rgbL0->r2 = bayL0->r; + rgbL0->g2 = bayL1->g; + rgbL0->b2 = bayL1->b; + + rgbL1->r = bayL0->r; + rgbL1->g = bayL1->g; + rgbL1->b = bayL1->b; + + rgbL1->r2 = bayL0->r; + rgbL1->g2 = bayL1->g; + rgbL1->b2 = bayL1->b; + + rgbL0++; + rgbL1++; + + bayL0++; + bayL1++; + } + + frame->seqRead_Length += cam->width*3*2; + frame->curline += 2; + } + /* See if we filled the frame */ + if (frame->curline == cam->height) { + frame->frameState = FrameState_Done_Hold; + frame->curline = 0; + uvd->curframe = -1; + uvd->stats.frame_num++; + } +} + +/* taken from konicawc */ +static int qcm_set_video_mode(struct uvd *uvd, struct video_window *vw) +{ + int ret; + int newsize; + int oldsize; + int x = vw->width; + int y = vw->height; + struct qcm *cam = (struct qcm *) uvd->user_data; + + if (x > 0 && y > 0) { + DEBUG(2, "trying to find size %d,%d", x, y); + for (newsize = 0; newsize <= MAX_FRAME_SIZE; newsize++) { + if ((camera_sizes[newsize].width == x) && + (camera_sizes[newsize].height == y)) + break; + } + } else + newsize = cam->size; + + if (newsize > MAX_FRAME_SIZE) { + DEBUG(1, "couldn't find size %d,%d", x, y); + return -EINVAL; + } + + if (newsize == cam->size) { + DEBUG(1, "Nothing to do"); + return 0; + } + + qcm_stop_data(uvd); + + if (cam->size != newsize) { + oldsize = cam->size; + cam->size = newsize; + ret = qcm_set_camera_size(uvd); + if (ret) { + err("Couldn't set camera size, err=%d",ret); + /* restore the original size */ + cam->size = oldsize; + return ret; + } + } + + /* Flush the input queue and clear any current frame in progress */ + + RingQueue_Flush(&uvd->dp); + if (uvd->curframe != -1) { + uvd->frame[uvd->curframe].curline = 0; + uvd->frame[uvd->curframe].seqRead_Length = 0; + uvd->frame[uvd->curframe].seqRead_Index = 0; + } + + CHECK_RET(ret, qcm_start_data(uvd)); + return 0; +} + +static int qcm_configure_video(struct uvd *uvd) +{ + int ret; + memset(&uvd->vpic, 0, sizeof(uvd->vpic)); + memset(&uvd->vpic_old, 0x55, sizeof(uvd->vpic_old)); + + uvd->vpic.colour = colour; + uvd->vpic.hue = hue; + uvd->vpic.brightness = brightness; + uvd->vpic.contrast = contrast; + uvd->vpic.whiteness = whiteness; + uvd->vpic.depth = 24; + uvd->vpic.palette = VIDEO_PALETTE_RGB24; + + memset(&uvd->vcap, 0, sizeof(uvd->vcap)); + strcpy(uvd->vcap.name, "QCM USB Camera"); + uvd->vcap.type = VID_TYPE_CAPTURE; + uvd->vcap.channels = 1; + uvd->vcap.audios = 0; + + uvd->vcap.minwidth = camera_sizes[SIZE_160X120].width; + uvd->vcap.minheight = camera_sizes[SIZE_160X120].height; + uvd->vcap.maxwidth = camera_sizes[SIZE_320X240].width; + uvd->vcap.maxheight = camera_sizes[SIZE_320X240].height; + + memset(&uvd->vchan, 0, sizeof(uvd->vchan)); + uvd->vchan.flags = 0 ; + uvd->vchan.tuners = 0; + uvd->vchan.channel = 0; + uvd->vchan.type = VIDEO_TYPE_CAMERA; + strcpy(uvd->vchan.name, "Camera"); + + CHECK_RET(ret, qcm_sensor_init(uvd)); + return 0; +} + +static int qcm_probe(struct usb_interface *intf, + const struct usb_device_id *devid) +{ + int err; + struct uvd *uvd; + struct usb_device *dev = interface_to_usbdev(intf); + struct qcm *cam; + size_t buffer_size; + unsigned char video_ep; + struct usb_host_interface *interface; + struct usb_endpoint_descriptor *endpoint; + int i,j; + unsigned int ifacenum, ifacenum_inact=0; + __le16 sensor_id; + + /* we don't support multiconfig cams */ + if (dev->descriptor.bNumConfigurations != 1) + return -ENODEV; + + /* first check for the video interface and not + * the audio interface */ + interface = &intf->cur_altsetting[0]; + if ((interface->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC) + || (interface->desc.bInterfaceSubClass != + USB_CLASS_VENDOR_SPEC)) + return -ENODEV; + + /* + walk through each endpoint in each setting in the interface + stop when we find the one that's an isochronous IN endpoint. + */ + for (i=0; i < intf->num_altsetting; i++) { + interface = &intf->cur_altsetting[i]; + ifacenum = interface->desc.bAlternateSetting; + /* walk the end points */ + for (j=0; j < interface->desc.bNumEndpoints; j++) { + endpoint = &interface->endpoint[j].desc; + + if ((endpoint->bEndpointAddress & + USB_ENDPOINT_DIR_MASK) != USB_DIR_IN) + continue; /* not input then not good */ + + buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + if (!buffer_size) { + ifacenum_inact = ifacenum; + continue; /* 0 pkt size is not what we want */ + } + + if ((endpoint->bmAttributes & + USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_ISOC) { + video_ep = endpoint->bEndpointAddress; + /* break out of the search */ + goto good_videoep; + } + } + } + /* failed out since nothing useful was found */ + err("No suitable endpoint was found\n"); + return -ENODEV; + +good_videoep: + /* disable isochronous stream before doing anything else */ + err = qcm_stv_setb(dev, STV_ISO_ENABLE, 0); + if (err < 0) { + err("Failed to disable sensor stream"); + return -EIO; + } + + /* + Check that this is the same unknown sensor that is known to work. This + sensor is suspected to be the ST VV6422C001. I'll check the same value + that the qc-usb driver checks. This value is probably not even the + sensor ID since it matches the USB dev ID. Oh well. If it doesn't + match, it's probably a diff sensor so exit and apologize. + */ + err = qcm_stv_getw(dev, CMOS_SENSOR_IDREV, &sensor_id); + if (err < 0) { + err("Couldn't read sensor values. Err %d\n",err); + return err; + } + if (sensor_id != cpu_to_le16(0x08F0)) { + err("Sensor ID %x != %x. Unsupported. Sorry\n", + le16_to_cpu(sensor_id), (0x08F0)); + return -ENODEV; + } + + uvd = usbvideo_AllocateDevice(cams); + if (!uvd) + return -ENOMEM; + + cam = (struct qcm *) uvd->user_data; + + /* buf for doing demosaicing */ + cam->scratch = kmalloc(324*2, GFP_KERNEL); + if (!cam->scratch) /* uvd freed in dereg */ + return -ENOMEM; + + /* yes, if we fail after here, cam->scratch gets freed + by qcm_free_uvd */ + + err = qcm_alloc_int_urb(cam); + if (err < 0) + return err; + + /* yes, if we fail after here, int urb gets freed + by qcm_free_uvd */ + + RESTRICT_TO_RANGE(size, SIZE_160X120, SIZE_320X240); + cam->width = camera_sizes[size].width; + cam->height = camera_sizes[size].height; + cam->size = size; + + uvd->debug = debug; + uvd->flags = 0; + uvd->dev = dev; + uvd->iface = intf->altsetting->desc.bInterfaceNumber; + uvd->ifaceAltActive = ifacenum; + uvd->ifaceAltInactive = ifacenum_inact; + uvd->video_endp = video_ep; + uvd->iso_packet_len = buffer_size; + uvd->paletteBits = 1L << VIDEO_PALETTE_RGB24; + uvd->defaultPalette = VIDEO_PALETTE_RGB24; + uvd->canvas = VIDEOSIZE(320, 240); + uvd->videosize = VIDEOSIZE(cam->width, cam->height); + err = qcm_configure_video(uvd); + if (err) { + err("failed to configure video settings"); + return err; + } + + err = usbvideo_RegisterVideoDevice(uvd); + if (err) { /* the uvd gets freed in Deregister */ + err("usbvideo_RegisterVideoDevice() failed."); + return err; + } + + uvd->max_frame_size = (320 * 240 * 3); + qcm_register_input(cam, dev); + usb_set_intfdata(intf, uvd); + return 0; +} + +static void qcm_free_uvd(struct uvd *uvd) +{ + struct qcm *cam = (struct qcm *) uvd->user_data; + + kfree(cam->scratch); + qcm_unregister_input(cam); + qcm_free_int(cam); +} + +static struct usbvideo_cb qcm_driver = { + .probe = qcm_probe, + .setupOnOpen = qcm_setup_on_open, + .processData = qcm_process_isoc, + .setVideoMode = qcm_set_video_mode, + .startDataPump = qcm_start_data, + .stopDataPump = qcm_stop_data, + .adjustPicture = qcm_adjust_picture, + .userFree = qcm_free_uvd +}; + +static int __init qcm_init(void) +{ + info(DRIVER_DESC " " DRIVER_VERSION); + + return usbvideo_register( + &cams, + MAX_CAMERAS, + sizeof(struct qcm), + "QCM", + &qcm_driver, + THIS_MODULE, + qcm_table); +} + +static void __exit qcm_exit(void) +{ + usbvideo_Deregister(&cams); +} + +module_param(size, int, 0); +MODULE_PARM_DESC(size, "Initial Size 0: 160x120 1: 320x240"); +module_param(colour, int, 0); +MODULE_PARM_DESC(colour, "Initial colour"); +module_param(hue, int, 0); +MODULE_PARM_DESC(hue, "Initial hue"); +module_param(brightness, int, 0); +MODULE_PARM_DESC(brightness, "Initial brightness"); +module_param(contrast, int, 0); +MODULE_PARM_DESC(contrast, "Initial contrast"); +module_param(whiteness, int, 0); +MODULE_PARM_DESC(whiteness, "Initial whiteness"); + +#ifdef CONFIG_USB_DEBUG +module_param(debug, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug level: 0-9 (default=0)"); +#endif + +module_init(qcm_init); +module_exit(qcm_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jaya Kumar"); +MODULE_DESCRIPTION("QCM USB Camera"); +MODULE_SUPPORTED_DEVICE("QCM USB Camera"); diff --git a/drivers/media/video/usbvideo/quickcam_messenger.h b/drivers/media/video/usbvideo/quickcam_messenger.h new file mode 100644 index 000000000..baab9c081 --- /dev/null +++ b/drivers/media/video/usbvideo/quickcam_messenger.h @@ -0,0 +1,126 @@ +#ifndef quickcam_messenger_h +#define quickcam_messenger_h + +#ifndef CONFIG_INPUT +/* if we're not using input we dummy out these functions */ +#define qcm_register_input(...) +#define qcm_unregister_input(...) +#define qcm_report_buttonstat(...) +#define qcm_setup_input_int(...) 0 +#define qcm_stop_int_data(...) +#define qcm_alloc_int_urb(...) 0 +#define qcm_free_int(...) +#endif + + +#define CHECK_RET(ret, expr) \ + if ((ret = expr) < 0) return ret + +/* Control Registers for the STVV6422 ASIC + * - this define is taken from the qc-usb-messenger code + */ +#define STV_ISO_ENABLE 0x1440 +#define ISOC_PACKET_SIZE 1023 + +/* Chip identification number including revision indicator */ +#define CMOS_SENSOR_IDREV 0xE00A + +struct rgb { + u8 b; + u8 g; + u8 r; + u8 b2; + u8 g2; + u8 r2; +}; + +struct bayL0 { +#ifdef __BIG_ENDIAN + u8 r; + u8 g; +#elif __LITTLE_ENDIAN + u8 g; + u8 r; +#else +#error not byte order defined +#endif +}; + +struct bayL1 { +#ifdef __BIG_ENDIAN + u8 g; + u8 b; +#elif __LITTLE_ENDIAN + u8 b; + u8 g; +#else +#error not byte order defined +#endif +}; + +struct cam_size { + u16 width; + u16 height; + u8 cmd; +}; + +static const struct cam_size camera_sizes[] = { + { 160, 120, 0xf }, + { 320, 240, 0x2 }, +}; + +enum frame_sizes { + SIZE_160X120 = 0, + SIZE_320X240 = 1, +}; + +#define MAX_FRAME_SIZE SIZE_320X240 + +struct qcm { + u16 colour; + u16 hue; + u16 brightness; + u16 contrast; + u16 whiteness; + + u8 size; + int height; + int width; + u8 *scratch; + struct urb *button_urb; + u8 button_sts; + u8 button_sts_buf; + +#ifdef CONFIG_INPUT + struct input_dev *input; + char input_physname[64]; +#endif +}; + +struct regval { + u16 reg; + u8 val; +}; +/* this table is derived from the +qc-usb-messenger code */ +static const struct regval regval_table[] = { + { STV_ISO_ENABLE, 0x00 }, + { 0x1436, 0x00 }, { 0x1432, 0x03 }, + { 0x143a, 0xF9 }, { 0x0509, 0x38 }, + { 0x050a, 0x38 }, { 0x050b, 0x38 }, + { 0x050c, 0x2A }, { 0x050d, 0x01 }, + { 0x1431, 0x00 }, { 0x1433, 0x34 }, + { 0x1438, 0x18 }, { 0x1439, 0x00 }, + { 0x143b, 0x05 }, { 0x143c, 0x00 }, + { 0x143e, 0x01 }, { 0x143d, 0x00 }, + { 0x1442, 0xe2 }, { 0x1500, 0xd0 }, + { 0x1500, 0xd0 }, { 0x1500, 0x50 }, + { 0x1501, 0xaf }, { 0x1502, 0xc2 }, + { 0x1503, 0x45 }, { 0x1505, 0x02 }, + { 0x150e, 0x8e }, { 0x150f, 0x37 }, + { 0x15c0, 0x00 }, +}; + +static const unsigned char marker[] = { 0x00, 0xff, 0x00, 0xFF }; + +#endif /* quickcam_messenger_h */ diff --git a/drivers/media/video/zc0301/zc0301_pb0330.c b/drivers/media/video/zc0301/zc0301_pb0330.c new file mode 100644 index 000000000..ed8542e6c --- /dev/null +++ b/drivers/media/video/zc0301/zc0301_pb0330.c @@ -0,0 +1,187 @@ +/*************************************************************************** + * Plug-in for PB-0330 image sensor connected to the ZC0301[P] Image * + * Processor and Control Chip * + * * + * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * + * * + * Initialization values of the ZC0301[P] have been taken from the SPCA5XX * + * driver maintained by Michel Xhaard <mxhaard@magic.fr> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * + ***************************************************************************/ + +#include <linux/delay.h> +#include "zc0301_sensor.h" + + +static struct zc0301_sensor pb0330; + + +static int pb0330_init(struct zc0301_device* cam) +{ + int err = 0; + + err += zc0301_write_reg(cam, 0x0000, 0x01); + err += zc0301_write_reg(cam, 0x0008, 0x03); + err += zc0301_write_reg(cam, 0x0010, 0x0A); + err += zc0301_write_reg(cam, 0x0002, 0x00); + err += zc0301_write_reg(cam, 0x0003, 0x02); + err += zc0301_write_reg(cam, 0x0004, 0x80); + err += zc0301_write_reg(cam, 0x0005, 0x01); + err += zc0301_write_reg(cam, 0x0006, 0xE0); + err += zc0301_write_reg(cam, 0x0001, 0x01); + err += zc0301_write_reg(cam, 0x0012, 0x05); + err += zc0301_write_reg(cam, 0x0012, 0x07); + err += zc0301_write_reg(cam, 0x0098, 0x00); + err += zc0301_write_reg(cam, 0x009A, 0x00); + err += zc0301_write_reg(cam, 0x011A, 0x00); + err += zc0301_write_reg(cam, 0x011C, 0x00); + err += zc0301_write_reg(cam, 0x0012, 0x05); + + err += zc0301_i2c_write(cam, 0x01, 0x0006); + err += zc0301_i2c_write(cam, 0x02, 0x0011); + err += zc0301_i2c_write(cam, 0x03, 0x01E7); + err += zc0301_i2c_write(cam, 0x04, 0x0287); + err += zc0301_i2c_write(cam, 0x06, 0x0003); + err += zc0301_i2c_write(cam, 0x07, 0x3002); + err += zc0301_i2c_write(cam, 0x20, 0x1100); + err += zc0301_i2c_write(cam, 0x2F, 0xF7B0); + err += zc0301_i2c_write(cam, 0x30, 0x0005); + err += zc0301_i2c_write(cam, 0x31, 0x0000); + err += zc0301_i2c_write(cam, 0x34, 0x0100); + err += zc0301_i2c_write(cam, 0x35, 0x0060); + err += zc0301_i2c_write(cam, 0x3D, 0x068F); + err += zc0301_i2c_write(cam, 0x40, 0x01E0); + err += zc0301_i2c_write(cam, 0x58, 0x0078); + err += zc0301_i2c_write(cam, 0x62, 0x0411); + + err += zc0301_write_reg(cam, 0x0087, 0x10); + err += zc0301_write_reg(cam, 0x0101, 0x37); + err += zc0301_write_reg(cam, 0x0012, 0x05); + err += zc0301_write_reg(cam, 0x0100, 0x0D); + err += zc0301_write_reg(cam, 0x0189, 0x06); + err += zc0301_write_reg(cam, 0x01AD, 0x00); + err += zc0301_write_reg(cam, 0x01C5, 0x03); + err += zc0301_write_reg(cam, 0x01CB, 0x13); + err += zc0301_write_reg(cam, 0x0250, 0x08); + err += zc0301_write_reg(cam, 0x0301, 0x08); + err += zc0301_write_reg(cam, 0x01A8, 0x60); + err += zc0301_write_reg(cam, 0x018D, 0x6C); + err += zc0301_write_reg(cam, 0x01AD, 0x09); + err += zc0301_write_reg(cam, 0x01AE, 0x15); + err += zc0301_write_reg(cam, 0x010A, 0x50); + err += zc0301_write_reg(cam, 0x010B, 0xF8); + err += zc0301_write_reg(cam, 0x010C, 0xF8); + err += zc0301_write_reg(cam, 0x010D, 0xF8); + err += zc0301_write_reg(cam, 0x010E, 0x50); + err += zc0301_write_reg(cam, 0x010F, 0xF8); + err += zc0301_write_reg(cam, 0x0110, 0xF8); + err += zc0301_write_reg(cam, 0x0111, 0xF8); + err += zc0301_write_reg(cam, 0x0112, 0x50); + err += zc0301_write_reg(cam, 0x0008, 0x03); + err += zc0301_write_reg(cam, 0x01C6, 0x08); + err += zc0301_write_reg(cam, 0x01CB, 0x0F); + err += zc0301_write_reg(cam, 0x010A, 0x50); + err += zc0301_write_reg(cam, 0x010B, 0xF8); + err += zc0301_write_reg(cam, 0x010C, 0xF8); + err += zc0301_write_reg(cam, 0x010D, 0xF8); + err += zc0301_write_reg(cam, 0x010E, 0x50); + err += zc0301_write_reg(cam, 0x010F, 0xF8); + err += zc0301_write_reg(cam, 0x0110, 0xF8); + err += zc0301_write_reg(cam, 0x0111, 0xF8); + err += zc0301_write_reg(cam, 0x0112, 0x50); + err += zc0301_write_reg(cam, 0x0180, 0x00); + err += zc0301_write_reg(cam, 0x0019, 0x00); + + err += zc0301_i2c_write(cam, 0x05, 0x0066); + err += zc0301_i2c_write(cam, 0x09, 0x02B2); + err += zc0301_i2c_write(cam, 0x10, 0x0002); + + err += zc0301_write_reg(cam, 0x011D, 0x60); + err += zc0301_write_reg(cam, 0x0190, 0x00); + err += zc0301_write_reg(cam, 0x0191, 0x07); + err += zc0301_write_reg(cam, 0x0192, 0x8C); + err += zc0301_write_reg(cam, 0x0195, 0x00); + err += zc0301_write_reg(cam, 0x0196, 0x00); + err += zc0301_write_reg(cam, 0x0197, 0x8A); + err += zc0301_write_reg(cam, 0x018C, 0x10); + err += zc0301_write_reg(cam, 0x018F, 0x20); + err += zc0301_write_reg(cam, 0x01A9, 0x14); + err += zc0301_write_reg(cam, 0x01AA, 0x24); + err += zc0301_write_reg(cam, 0x001D, 0xD7); + err += zc0301_write_reg(cam, 0x001E, 0xF0); + err += zc0301_write_reg(cam, 0x001F, 0xF8); + err += zc0301_write_reg(cam, 0x0020, 0xFF); + err += zc0301_write_reg(cam, 0x01AD, 0x09); + err += zc0301_write_reg(cam, 0x01AE, 0x15); + err += zc0301_write_reg(cam, 0x0180, 0x40); + err += zc0301_write_reg(cam, 0x0180, 0x42); + + msleep(100); + + return err; +} + + +static struct zc0301_sensor pb0330 = { + .name = "PB-0330", + .init = &pb0330_init, + .cropcap = { + .bounds = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + .defrect = { + .left = 0, + .top = 0, + .width = 640, + .height = 480, + }, + }, + .pix_format = { + .width = 640, + .height = 480, + .pixelformat = V4L2_PIX_FMT_JPEG, + .priv = 8, + }, +}; + + +int zc0301_probe_pb0330(struct zc0301_device* cam) +{ + int r0, err = 0; + + err += zc0301_write_reg(cam, 0x0000, 0x01); + err += zc0301_write_reg(cam, 0x0010, 0x0a); + err += zc0301_write_reg(cam, 0x0001, 0x01); + err += zc0301_write_reg(cam, 0x0012, 0x03); + err += zc0301_write_reg(cam, 0x0012, 0x01); + + msleep(10); + + r0 = zc0301_i2c_read(cam, 0x00, 2); + + if (r0 < 0 || err) + return -EIO; + + if (r0 != 0x8243) + return -ENODEV; + + zc0301_attach_sensor(cam, &pb0330); + + return 0; +} diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c new file mode 100644 index 000000000..a0ba07c36 --- /dev/null +++ b/drivers/mtd/nand/ams-delta.c @@ -0,0 +1,239 @@ +/* + * drivers/mtd/nand/ams-delta.c + * + * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li> + * + * Derived from drivers/mtd/toto.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Overview: + * This is a device driver for the NAND flash device found on the + * Amstrad E3 (Delta). + */ + +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/partitions.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/sizes.h> +#include <asm/arch/gpio.h> +#include <asm/arch/board-ams-delta.h> + +/* + * MTD structure for E3 (Delta) + */ +static struct mtd_info *ams_delta_mtd = NULL; + +#define NAND_MASK (AMS_DELTA_LATCH2_NAND_NRE | AMS_DELTA_LATCH2_NAND_NWE | AMS_DELTA_LATCH2_NAND_CLE | AMS_DELTA_LATCH2_NAND_ALE | AMS_DELTA_LATCH2_NAND_NCE | AMS_DELTA_LATCH2_NAND_NWP) + +/* + * Define partitions for flash devices + */ + +static struct mtd_partition partition_info[] = { + { .name = "Kernel", + .offset = 0, + .size = 3 * SZ_1M + SZ_512K }, + { .name = "u-boot", + .offset = 3 * SZ_1M + SZ_512K, + .size = SZ_256K }, + { .name = "u-boot params", + .offset = 3 * SZ_1M + SZ_512K + SZ_256K, + .size = SZ_256K }, + { .name = "Amstrad LDR", + .offset = 4 * SZ_1M, + .size = SZ_256K }, + { .name = "File system", + .offset = 4 * SZ_1M + 1 * SZ_256K, + .size = 27 * SZ_1M }, + { .name = "PBL reserved", + .offset = 32 * SZ_1M - 3 * SZ_256K, + .size = 3 * SZ_256K }, +}; + +static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte) +{ + struct nand_chip *this = mtd->priv; + + omap_writew(0, (OMAP_MPUIO_BASE + OMAP_MPUIO_IO_CNTL)); + omap_writew(byte, this->IO_ADDR_W); + ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE, 0); + ndelay(40); + ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE, + AMS_DELTA_LATCH2_NAND_NWE); +} + +static u_char ams_delta_read_byte(struct mtd_info *mtd) +{ + u_char res; + struct nand_chip *this = mtd->priv; + + ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE, 0); + ndelay(40); + omap_writew(~0, (OMAP_MPUIO_BASE + OMAP_MPUIO_IO_CNTL)); + res = omap_readw(this->IO_ADDR_R); + ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE, + AMS_DELTA_LATCH2_NAND_NRE); + + return res; +} + +static void ams_delta_write_buf(struct mtd_info *mtd, const u_char *buf, + int len) +{ + int i; + + for (i=0; i<len; i++) + ams_delta_write_byte(mtd, buf[i]); +} + +static void ams_delta_read_buf(struct mtd_info *mtd, u_char *buf, int len) +{ + int i; + + for (i=0; i<len; i++) + buf[i] = ams_delta_read_byte(mtd); +} + +static int ams_delta_verify_buf(struct mtd_info *mtd, const u_char *buf, + int len) +{ + int i; + + for (i=0; i<len; i++) + if (buf[i] != ams_delta_read_byte(mtd)) + return -EFAULT; + + return 0; +} + +/* + * Command control function + * + * ctrl: + * NAND_NCE: bit 0 -> bit 2 + * NAND_CLE: bit 1 -> bit 7 + * NAND_ALE: bit 2 -> bit 6 + */ +static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int ctrl) +{ + + if (ctrl & NAND_CTRL_CHANGE) { + unsigned long bits; + + bits = (~ctrl & NAND_NCE) ? AMS_DELTA_LATCH2_NAND_NCE : 0; + bits |= (ctrl & NAND_CLE) ? AMS_DELTA_LATCH2_NAND_CLE : 0; + bits |= (ctrl & NAND_ALE) ? AMS_DELTA_LATCH2_NAND_ALE : 0; + + ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE | + AMS_DELTA_LATCH2_NAND_ALE | + AMS_DELTA_LATCH2_NAND_NCE, bits); + } + + if (cmd != NAND_CMD_NONE) + ams_delta_write_byte(mtd, cmd); +} + +static int ams_delta_nand_ready(struct mtd_info *mtd) +{ + return omap_get_gpio_datain(AMS_DELTA_GPIO_PIN_NAND_RB); +} + +/* + * Main initialization routine + */ +static int __init ams_delta_init(void) +{ + struct nand_chip *this; + int err = 0; + + /* Allocate memory for MTD device structure and private data */ + ams_delta_mtd = kmalloc(sizeof(struct mtd_info) + + sizeof(struct nand_chip), GFP_KERNEL); + if (!ams_delta_mtd) { + printk (KERN_WARNING "Unable to allocate E3 NAND MTD device structure.\n"); + err = -ENOMEM; + goto out; + } + + ams_delta_mtd->owner = THIS_MODULE; + + /* Get pointer to private data */ + this = (struct nand_chip *) (&ams_delta_mtd[1]); + + /* Initialize structures */ + memset(ams_delta_mtd, 0, sizeof(struct mtd_info)); + memset(this, 0, sizeof(struct nand_chip)); + + /* Link the private data with the MTD structure */ + ams_delta_mtd->priv = this; + + /* Set address of NAND IO lines */ + this->IO_ADDR_R = (OMAP_MPUIO_BASE + OMAP_MPUIO_INPUT_LATCH); + this->IO_ADDR_W = (OMAP_MPUIO_BASE + OMAP_MPUIO_OUTPUT); + this->read_byte = ams_delta_read_byte; + this->write_buf = ams_delta_write_buf; + this->read_buf = ams_delta_read_buf; + this->verify_buf = ams_delta_verify_buf; + this->cmd_ctrl = ams_delta_hwcontrol; + if (!omap_request_gpio(AMS_DELTA_GPIO_PIN_NAND_RB)) { + this->dev_ready = ams_delta_nand_ready; + } else { + this->dev_ready = NULL; + printk(KERN_NOTICE "Couldn't request gpio for Delta NAND ready.\n"); + } + /* 25 us command delay time */ + this->chip_delay = 30; + this->ecc.mode = NAND_ECC_SOFT; + + /* Set chip enabled, but */ + ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE | + AMS_DELTA_LATCH2_NAND_NWE | + AMS_DELTA_LATCH2_NAND_NCE | + AMS_DELTA_LATCH2_NAND_NWP); + + /* Scan to find existance of the device */ + if (nand_scan(ams_delta_mtd, 1)) { + err = -ENXIO; + goto out_mtd; + } + + /* Register the partitions */ + add_mtd_partitions(ams_delta_mtd, partition_info, + ARRAY_SIZE(partition_info)); + + goto out; + + out_mtd: + kfree(ams_delta_mtd); + out: + return err; +} + +module_init(ams_delta_init); + +/* + * Clean up routine + */ +static void __exit ams_delta_cleanup(void) +{ + /* Release resources, unregister device */ + nand_release(ams_delta_mtd); + + /* Free the MTD device structure */ + kfree(ams_delta_mtd); +} +module_exit(ams_delta_cleanup); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>"); +MODULE_DESCRIPTION("Glue layer for NAND flash on Amstrad E3 (Delta)"); diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c new file mode 100644 index 000000000..e0a1d386e --- /dev/null +++ b/drivers/mtd/nand/cs553x_nand.c @@ -0,0 +1,353 @@ +/* + * drivers/mtd/nand/cs553x_nand.c + * + * (C) 2005, 2006 Red Hat Inc. + * + * Author: David Woodhouse <dwmw2@infradead.org> + * Tom Sylla <tom.sylla@amd.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Overview: + * This is a device driver for the NAND flash controller found on + * the AMD CS5535/CS5536 companion chipsets for the Geode processor. + * + */ + +#include <linux/slab.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/pci.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/nand_ecc.h> +#include <linux/mtd/partitions.h> + +#include <asm/msr.h> +#include <asm/io.h> + +#define NR_CS553X_CONTROLLERS 4 + +#define MSR_DIVIL_GLD_CAP 0x51400000 /* DIVIL capabilitiies */ +#define CAP_CS5535 0x2df000ULL +#define CAP_CS5536 0x5df500ULL + +/* NAND Timing MSRs */ +#define MSR_NANDF_DATA 0x5140001b /* NAND Flash Data Timing MSR */ +#define MSR_NANDF_CTL 0x5140001c /* NAND Flash Control Timing */ +#define MSR_NANDF_RSVD 0x5140001d /* Reserved */ + +/* NAND BAR MSRs */ +#define MSR_DIVIL_LBAR_FLSH0 0x51400010 /* Flash Chip Select 0 */ +#define MSR_DIVIL_LBAR_FLSH1 0x51400011 /* Flash Chip Select 1 */ +#define MSR_DIVIL_LBAR_FLSH2 0x51400012 /* Flash Chip Select 2 */ +#define MSR_DIVIL_LBAR_FLSH3 0x51400013 /* Flash Chip Select 3 */ + /* Each made up of... */ +#define FLSH_LBAR_EN (1ULL<<32) +#define FLSH_NOR_NAND (1ULL<<33) /* 1 for NAND */ +#define FLSH_MEM_IO (1ULL<<34) /* 1 for MMIO */ + /* I/O BARs have BASE_ADDR in bits 15:4, IO_MASK in 47:36 */ + /* MMIO BARs have BASE_ADDR in bits 31:12, MEM_MASK in 63:44 */ + +/* Pin function selection MSR (IDE vs. flash on the IDE pins) */ +#define MSR_DIVIL_BALL_OPTS 0x51400015 +#define PIN_OPT_IDE (1<<0) /* 0 for flash, 1 for IDE */ + +/* Registers within the NAND flash controller BAR -- memory mapped */ +#define MM_NAND_DATA 0x00 /* 0 to 0x7ff, in fact */ +#define MM_NAND_CTL 0x800 /* Any even address 0x800-0x80e */ +#define MM_NAND_IO 0x801 /* Any odd address 0x801-0x80f */ +#define MM_NAND_STS 0x810 +#define MM_NAND_ECC_LSB 0x811 +#define MM_NAND_ECC_MSB 0x812 +#define MM_NAND_ECC_COL 0x813 +#define MM_NAND_LAC 0x814 +#define MM_NAND_ECC_CTL 0x815 + +/* Registers within the NAND flash controller BAR -- I/O mapped */ +#define IO_NAND_DATA 0x00 /* 0 to 3, in fact */ +#define IO_NAND_CTL 0x04 +#define IO_NAND_IO 0x05 +#define IO_NAND_STS 0x06 +#define IO_NAND_ECC_CTL 0x08 +#define IO_NAND_ECC_LSB 0x09 +#define IO_NAND_ECC_MSB 0x0a +#define IO_NAND_ECC_COL 0x0b +#define IO_NAND_LAC 0x0c + +#define CS_NAND_CTL_DIST_EN (1<<4) /* Enable NAND Distract interrupt */ +#define CS_NAND_CTL_RDY_INT_MASK (1<<3) /* Enable RDY/BUSY# interrupt */ +#define CS_NAND_CTL_ALE (1<<2) +#define CS_NAND_CTL_CLE (1<<1) +#define CS_NAND_CTL_CE (1<<0) /* Keep low; 1 to reset */ + +#define CS_NAND_STS_FLASH_RDY (1<<3) +#define CS_NAND_CTLR_BUSY (1<<2) +#define CS_NAND_CMD_COMP (1<<1) +#define CS_NAND_DIST_ST (1<<0) + +#define CS_NAND_ECC_PARITY (1<<2) +#define CS_NAND_ECC_CLRECC (1<<1) +#define CS_NAND_ECC_ENECC (1<<0) + +static void cs553x_read_buf(struct mtd_info *mtd, u_char *buf, int len) +{ + struct nand_chip *this = mtd->priv; + + while (unlikely(len > 0x800)) { + memcpy_fromio(buf, this->IO_ADDR_R, 0x800); + buf += 0x800; + len -= 0x800; + } + memcpy_fromio(buf, this->IO_ADDR_R, len); +} + +static void cs553x_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +{ + struct nand_chip *this = mtd->priv; + + while (unlikely(len > 0x800)) { + memcpy_toio(this->IO_ADDR_R, buf, 0x800); + buf += 0x800; + len -= 0x800; + } + memcpy_toio(this->IO_ADDR_R, buf, len); +} + +static unsigned char cs553x_read_byte(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + return readb(this->IO_ADDR_R); +} + +static void cs553x_write_byte(struct mtd_info *mtd, u_char byte) +{ + struct nand_chip *this = mtd->priv; + int i = 100000; + + while (i && readb(this->IO_ADDR_R + MM_NAND_STS) & CS_NAND_CTLR_BUSY) { + udelay(1); + i--; + } + writeb(byte, this->IO_ADDR_W + 0x801); +} + +static void cs553x_hwcontrol(struct mtd_info *mtd, int cmd, + unsigned int ctrl) +{ + struct nand_chip *this = mtd->priv; + void __iomem *mmio_base = this->IO_ADDR_R; + if (ctrl & NAND_CTRL_CHANGE) { + unsigned char ctl = (ctrl & ~NAND_CTRL_CHANGE ) ^ 0x01; + writeb(ctl, mmio_base + MM_NAND_CTL); + } + if (cmd != NAND_CMD_NONE) + cs553x_write_byte(mtd, cmd); +} + +static int cs553x_device_ready(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + void __iomem *mmio_base = this->IO_ADDR_R; + unsigned char foo = readb(mmio_base + MM_NAND_STS); + + return (foo & CS_NAND_STS_FLASH_RDY) && !(foo & CS_NAND_CTLR_BUSY); +} + +static void cs_enable_hwecc(struct mtd_info *mtd, int mode) +{ + struct nand_chip *this = mtd->priv; + void __iomem *mmio_base = this->IO_ADDR_R; + + writeb(0x07, mmio_base + MM_NAND_ECC_CTL); +} + +static int cs_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) +{ + uint32_t ecc; + struct nand_chip *this = mtd->priv; + void __iomem *mmio_base = this->IO_ADDR_R; + + ecc = readl(mmio_base + MM_NAND_STS); + + ecc_code[1] = ecc >> 8; + ecc_code[0] = ecc >> 16; + ecc_code[2] = ecc >> 24; + return 0; +} + +static struct mtd_info *cs553x_mtd[4]; + +static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) +{ + int err = 0; + struct nand_chip *this; + struct mtd_info *new_mtd; + + printk(KERN_NOTICE "Probing CS553x NAND controller CS#%d at %sIO 0x%08lx\n", cs, mmio?"MM":"P", adr); + + if (!mmio) { + printk(KERN_NOTICE "PIO mode not yet implemented for CS553X NAND controller\n"); + return -ENXIO; + } + + /* Allocate memory for MTD device structure and private data */ + new_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); + if (!new_mtd) { + printk(KERN_WARNING "Unable to allocate CS553X NAND MTD device structure.\n"); + err = -ENOMEM; + goto out; + } + + /* Get pointer to private data */ + this = (struct nand_chip *)(&new_mtd[1]); + + /* Initialize structures */ + memset(new_mtd, 0, sizeof(struct mtd_info)); + memset(this, 0, sizeof(struct nand_chip)); + + /* Link the private data with the MTD structure */ + new_mtd->priv = this; + new_mtd->owner = THIS_MODULE; + + /* map physical address */ + this->IO_ADDR_R = this->IO_ADDR_W = ioremap(adr, 4096); + if (!this->IO_ADDR_R) { + printk(KERN_WARNING "ioremap cs553x NAND @0x%08lx failed\n", adr); + err = -EIO; + goto out_mtd; + } + + this->cmd_ctrl = cs553x_hwcontrol; + this->dev_ready = cs553x_device_ready; + this->read_byte = cs553x_read_byte; + this->read_buf = cs553x_read_buf; + this->write_buf = cs553x_write_buf; + + this->chip_delay = 0; + + this->ecc.mode = NAND_ECC_HW; + this->ecc.size = 256; + this->ecc.bytes = 3; + this->ecc.hwctl = cs_enable_hwecc; + this->ecc.calculate = cs_calculate_ecc; + this->ecc.correct = nand_correct_data; + + /* Enable the following for a flash based bad block table */ + this->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR; + + /* Scan to find existance of the device */ + if (nand_scan(new_mtd, 1)) { + err = -ENXIO; + goto out_ior; + } + + cs553x_mtd[cs] = new_mtd; + goto out; + +out_ior: + iounmap((void *)this->IO_ADDR_R); +out_mtd: + kfree(new_mtd); +out: + return err; +} + +static int is_geode(void) +{ + /* These are the CPUs which will have a CS553[56] companion chip */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD && + boot_cpu_data.x86 == 5 && + boot_cpu_data.x86_model == 10) + return 1; /* Geode LX */ + + if ((boot_cpu_data.x86_vendor == X86_VENDOR_NSC || + boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX) && + boot_cpu_data.x86 == 5 && + boot_cpu_data.x86_model == 5) + return 1; /* Geode GX (née GX2) */ + + return 0; +} + +static int __init cs553x_init(void) +{ + int err = -ENXIO; + int i; + uint64_t val; + + /* If the CPU isn't a Geode GX or LX, abort */ + if (!is_geode()) + return -ENXIO; + + /* If it doesn't have the CS553[56], abort */ + rdmsrl(MSR_DIVIL_GLD_CAP, val); + val &= ~0xFFULL; + if (val != CAP_CS5535 && val != CAP_CS5536) + return -ENXIO; + + /* If it doesn't have the NAND controller enabled, abort */ + rdmsrl(MSR_DIVIL_BALL_OPTS, val); + if (val & 1) { + printk(KERN_INFO "CS553x NAND controller: Flash I/O not enabled in MSR_DIVIL_BALL_OPTS.\n"); + return -ENXIO; + } + + for (i = 0; i < NR_CS553X_CONTROLLERS; i++) { + rdmsrl(MSR_DIVIL_LBAR_FLSH0 + i, val); + + if ((val & (FLSH_LBAR_EN|FLSH_NOR_NAND)) == (FLSH_LBAR_EN|FLSH_NOR_NAND)) + err = cs553x_init_one(i, !!(val & FLSH_MEM_IO), val & 0xFFFFFFFF); + } + + /* Register all devices together here. This means we can easily hack it to + do mtdconcat etc. if we want to. */ + for (i = 0; i < NR_CS553X_CONTROLLERS; i++) { + if (cs553x_mtd[i]) { + add_mtd_device(cs553x_mtd[i]); + + /* If any devices registered, return success. Else the last error. */ + err = 0; + } + } + + return err; +} + +module_init(cs553x_init); + +static void __exit cs553x_cleanup(void) +{ + int i; + + for (i = 0; i < NR_CS553X_CONTROLLERS; i++) { + struct mtd_info *mtd = cs553x_mtd[i]; + struct nand_chip *this; + void __iomem *mmio_base; + + if (!mtd) + break; + + this = cs553x_mtd[i]->priv; + mmio_base = this->IO_ADDR_R; + + /* Release resources, unregister device */ + nand_release(cs553x_mtd[i]); + cs553x_mtd[i] = NULL; + + /* unmap physical adress */ + iounmap(mmio_base); + + /* Free the MTD device structure */ + kfree(mtd); + } +} + +module_exit(cs553x_cleanup); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); +MODULE_DESCRIPTION("NAND controller driver for AMD CS5535/CS5536 companion chip"); diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c new file mode 100644 index 000000000..e5bd88f2d --- /dev/null +++ b/drivers/mtd/nand/ndfc.c @@ -0,0 +1,311 @@ +/* + * drivers/mtd/ndfc.c + * + * Overview: + * Platform independend driver for NDFC (NanD Flash Controller) + * integrated into EP440 cores + * + * Author: Thomas Gleixner + * + * Copyright 2006 IBM + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#include <linux/module.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/nand_ecc.h> +#include <linux/mtd/partitions.h> +#include <linux/mtd/ndfc.h> +#include <linux/mtd/mtd.h> +#include <linux/platform_device.h> + +#include <asm/io.h> +#include <asm/ibm44x.h> + +struct ndfc_nand_mtd { + struct mtd_info mtd; + struct nand_chip chip; + struct platform_nand_chip *pl_chip; +}; + +static struct ndfc_nand_mtd ndfc_mtd[NDFC_MAX_BANKS]; + +struct ndfc_controller { + void __iomem *ndfcbase; + struct nand_hw_control ndfc_control; + atomic_t childs_active; +}; + +static struct ndfc_controller ndfc_ctrl; + +static void ndfc_select_chip(struct mtd_info *mtd, int chip) +{ + uint32_t ccr; + struct ndfc_controller *ndfc = &ndfc_ctrl; + struct nand_chip *nandchip = mtd->priv; + struct ndfc_nand_mtd *nandmtd = nandchip->priv; + struct platform_nand_chip *pchip = nandmtd->pl_chip; + + ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR); + if (chip >= 0) { + ccr &= ~NDFC_CCR_BS_MASK; + ccr |= NDFC_CCR_BS(chip + pchip->chip_offset); + } else + ccr |= NDFC_CCR_RESET_CE; + writel(ccr, ndfc->ndfcbase + NDFC_CCR); +} + +static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct ndfc_controller *ndfc = &ndfc_ctrl; + + if (cmd == NAND_CMD_NONE) + return; + + if (ctrl & NAND_CLE) + writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_CMD); + else + writel(cmd & 0xFF, ndfc->ndfcbase + NDFC_ALE); +} + +static int ndfc_ready(struct mtd_info *mtd) +{ + struct ndfc_controller *ndfc = &ndfc_ctrl; + + return __raw_readl(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY; +} + +static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode) +{ + uint32_t ccr; + struct ndfc_controller *ndfc = &ndfc_ctrl; + + ccr = __raw_readl(ndfc->ndfcbase + NDFC_CCR); + ccr |= NDFC_CCR_RESET_ECC; + __raw_writel(ccr, ndfc->ndfcbase + NDFC_CCR); + wmb(); +} + +static int ndfc_calculate_ecc(struct mtd_info *mtd, + const u_char *dat, u_char *ecc_code) +{ + struct ndfc_controller *ndfc = &ndfc_ctrl; + uint32_t ecc; + uint8_t *p = (uint8_t *)&ecc; + + wmb(); + ecc = __raw_readl(ndfc->ndfcbase + NDFC_ECC); + ecc_code[0] = p[1]; + ecc_code[1] = p[2]; + ecc_code[2] = p[3]; + + return 0; +} + +/* + * Speedups for buffer read/write/verify + * + * NDFC allows 32bit read/write of data. So we can speed up the buffer + * functions. No further checking, as nand_base will always read/write + * page aligned. + */ +static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) +{ + struct ndfc_controller *ndfc = &ndfc_ctrl; + uint32_t *p = (uint32_t *) buf; + + for(;len > 0; len -= 4) + *p++ = __raw_readl(ndfc->ndfcbase + NDFC_DATA); +} + +static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) +{ + struct ndfc_controller *ndfc = &ndfc_ctrl; + uint32_t *p = (uint32_t *) buf; + + for(;len > 0; len -= 4) + __raw_writel(*p++, ndfc->ndfcbase + NDFC_DATA); +} + +static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) +{ + struct ndfc_controller *ndfc = &ndfc_ctrl; + uint32_t *p = (uint32_t *) buf; + + for(;len > 0; len -= 4) + if (*p++ != __raw_readl(ndfc->ndfcbase + NDFC_DATA)) + return -EFAULT; + return 0; +} + +/* + * Initialize chip structure + */ +static void ndfc_chip_init(struct ndfc_nand_mtd *mtd) +{ + struct ndfc_controller *ndfc = &ndfc_ctrl; + struct nand_chip *chip = &mtd->chip; + + chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA; + chip->IO_ADDR_W = ndfc->ndfcbase + NDFC_DATA; + chip->cmd_ctrl = ndfc_hwcontrol; + chip->dev_ready = ndfc_ready; + chip->select_chip = ndfc_select_chip; + chip->chip_delay = 50; + chip->priv = mtd; + chip->options = mtd->pl_chip->options; + chip->controller = &ndfc->ndfc_control; + chip->read_buf = ndfc_read_buf; + chip->write_buf = ndfc_write_buf; + chip->verify_buf = ndfc_verify_buf; + chip->ecc.correct = nand_correct_data; + chip->ecc.hwctl = ndfc_enable_hwecc; + chip->ecc.calculate = ndfc_calculate_ecc; + chip->ecc.mode = NAND_ECC_HW; + chip->ecc.size = 256; + chip->ecc.bytes = 3; + chip->ecclayout = mtd->pl_chip->ecclayout; + mtd->mtd.priv = chip; + mtd->mtd.owner = THIS_MODULE; +} + +static int ndfc_chip_probe(struct platform_device *pdev) +{ + struct platform_nand_chip *nc = pdev->dev.platform_data; + struct ndfc_chip_settings *settings = nc->priv; + struct ndfc_controller *ndfc = &ndfc_ctrl; + struct ndfc_nand_mtd *nandmtd; + + if (nc->chip_offset >= NDFC_MAX_BANKS || nc->nr_chips > NDFC_MAX_BANKS) + return -EINVAL; + + /* Set the bank settings */ + __raw_writel(settings->bank_settings, + ndfc->ndfcbase + NDFC_BCFG0 + (nc->chip_offset << 2)); + + nandmtd = &ndfc_mtd[pdev->id]; + if (nandmtd->pl_chip) + return -EBUSY; + + nandmtd->pl_chip = nc; + ndfc_chip_init(nandmtd); + + /* Scan for chips */ + if (nand_scan(&nandmtd->mtd, nc->nr_chips)) { + nandmtd->pl_chip = NULL; + return -ENODEV; + } + +#ifdef CONFIG_MTD_PARTITIONS + printk("Number of partitions %d\n", nc->nr_partitions); + if (nc->nr_partitions) { + /* Add the full device, so complete dumps can be made */ + add_mtd_device(&nandmtd->mtd); + add_mtd_partitions(&nandmtd->mtd, nc->partitions, + nc->nr_partitions); + + } else +#else + add_mtd_device(&nandmtd->mtd); +#endif + + atomic_inc(&ndfc->childs_active); + return 0; +} + +static int ndfc_chip_remove(struct platform_device *pdev) +{ + return 0; +} + +static int ndfc_nand_probe(struct platform_device *pdev) +{ + struct platform_nand_ctrl *nc = pdev->dev.platform_data; + struct ndfc_controller_settings *settings = nc->priv; + struct resource *res = pdev->resource; + struct ndfc_controller *ndfc = &ndfc_ctrl; + unsigned long long phys = settings->ndfc_erpn | res->start; + + ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1); + if (!ndfc->ndfcbase) { + printk(KERN_ERR "NDFC: ioremap failed\n"); + return -EIO; + } + + __raw_writel(settings->ccr_settings, ndfc->ndfcbase + NDFC_CCR); + + spin_lock_init(&ndfc->ndfc_control.lock); + init_waitqueue_head(&ndfc->ndfc_control.wq); + + platform_set_drvdata(pdev, ndfc); + + printk("NDFC NAND Driver initialized. Chip-Rev: 0x%08x\n", + __raw_readl(ndfc->ndfcbase + NDFC_REVID)); + + return 0; +} + +static int ndfc_nand_remove(struct platform_device *pdev) +{ + struct ndfc_controller *ndfc = platform_get_drvdata(pdev); + + if (atomic_read(&ndfc->childs_active)) + return -EBUSY; + + if (ndfc) { + platform_set_drvdata(pdev, NULL); + iounmap(ndfc_ctrl.ndfcbase); + ndfc_ctrl.ndfcbase = NULL; + } + return 0; +} + +/* driver device registration */ + +static struct platform_driver ndfc_chip_driver = { + .probe = ndfc_chip_probe, + .remove = ndfc_chip_remove, + .driver = { + .name = "ndfc-chip", + .owner = THIS_MODULE, + }, +}; + +static struct platform_driver ndfc_nand_driver = { + .probe = ndfc_nand_probe, + .remove = ndfc_nand_remove, + .driver = { + .name = "ndfc-nand", + .owner = THIS_MODULE, + }, +}; + +static int __init ndfc_nand_init(void) +{ + int ret; + + spin_lock_init(&ndfc_ctrl.ndfc_control.lock); + init_waitqueue_head(&ndfc_ctrl.ndfc_control.wq); + + ret = platform_driver_register(&ndfc_nand_driver); + if (!ret) + ret = platform_driver_register(&ndfc_chip_driver); + return ret; +} + +static void __exit ndfc_nand_exit(void) +{ + platform_driver_unregister(&ndfc_chip_driver); + platform_driver_unregister(&ndfc_nand_driver); +} + +module_init(ndfc_nand_init); +module_exit(ndfc_nand_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); +MODULE_DESCRIPTION("Platform driver for NDFC"); diff --git a/drivers/mtd/nand/ts7250.c b/drivers/mtd/nand/ts7250.c new file mode 100644 index 000000000..f40081069 --- /dev/null +++ b/drivers/mtd/nand/ts7250.c @@ -0,0 +1,206 @@ +/* + * drivers/mtd/nand/ts7250.c + * + * Copyright (C) 2004 Technologic Systems (support@embeddedARM.com) + * + * Derived from drivers/mtd/nand/edb7312.c + * Copyright (C) 2004 Marius Gröger (mag@sysgo.de) + * + * Derived from drivers/mtd/nand/autcpu12.c + * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) + * + * $Id: ts7250.c,v 1.4 2004/12/30 22:02:07 joff Exp $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Overview: + * This is a device driver for the NAND flash device found on the + * TS-7250 board which utilizes a Samsung 32 Mbyte part. + */ + +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/partitions.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/sizes.h> +#include <asm/mach-types.h> + +/* + * MTD structure for TS7250 board + */ +static struct mtd_info *ts7250_mtd = NULL; + +#ifdef CONFIG_MTD_PARTITIONS +static const char *part_probes[] = { "cmdlinepart", NULL }; + +#define NUM_PARTITIONS 3 + +/* + * Define static partitions for flash device + */ +static struct mtd_partition partition_info32[] = { + { + .name = "TS-BOOTROM", + .offset = 0x00000000, + .size = 0x00004000, + }, { + .name = "Linux", + .offset = 0x00004000, + .size = 0x01d00000, + }, { + .name = "RedBoot", + .offset = 0x01d04000, + .size = 0x002fc000, + }, +}; + +/* + * Define static partitions for flash device + */ +static struct mtd_partition partition_info128[] = { + { + .name = "TS-BOOTROM", + .offset = 0x00000000, + .size = 0x00004000, + }, { + .name = "Linux", + .offset = 0x00004000, + .size = 0x07d00000, + }, { + .name = "RedBoot", + .offset = 0x07d04000, + .size = 0x002fc000, + }, +}; +#endif + + +/* + * hardware specific access to control-lines + * + * ctrl: + * NAND_NCE: bit 0 -> bit 2 + * NAND_CLE: bit 1 -> bit 1 + * NAND_ALE: bit 2 -> bit 0 + */ +static void ts7250_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *chip = mtd->priv; + + if (ctrl & NAND_CTRL_CHANGE) { + unsigned long addr = TS72XX_NAND_CONTROL_VIRT_BASE; + unsigned char bits; + + bits = (ctrl & NAND_NCE) << 2; + bits |= ctrl & NAND_CLE; + bits |= (ctrl & NAND_ALE) >> 2; + + __raw_writeb((__raw_readb(addr) & ~0x7) | bits, addr); + } + + if (cmd != NAND_CMD_NONE) + writeb(cmd, chip->IO_ADDR_W); +} + +/* + * read device ready pin + */ +static int ts7250_device_ready(struct mtd_info *mtd) +{ + return __raw_readb(TS72XX_NAND_BUSY_VIRT_BASE) & 0x20; +} + +/* + * Main initialization routine + */ +static int __init ts7250_init(void) +{ + struct nand_chip *this; + const char *part_type = 0; + int mtd_parts_nb = 0; + struct mtd_partition *mtd_parts = 0; + + if (!machine_is_ts72xx() || board_is_ts7200()) + return -ENXIO; + + /* Allocate memory for MTD device structure and private data */ + ts7250_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); + if (!ts7250_mtd) { + printk("Unable to allocate TS7250 NAND MTD device structure.\n"); + return -ENOMEM; + } + + /* Get pointer to private data */ + this = (struct nand_chip *)(&ts7250_mtd[1]); + + /* Initialize structures */ + memset(ts7250_mtd, 0, sizeof(struct mtd_info)); + memset(this, 0, sizeof(struct nand_chip)); + + /* Link the private data with the MTD structure */ + ts7250_mtd->priv = this; + ts7250_mtd->owner = THIS_MODULE; + + /* insert callbacks */ + this->IO_ADDR_R = (void *)TS72XX_NAND_DATA_VIRT_BASE; + this->IO_ADDR_W = (void *)TS72XX_NAND_DATA_VIRT_BASE; + this->cmd_ctrl = ts7250_hwcontrol; + this->dev_ready = ts7250_device_ready; + this->chip_delay = 15; + this->ecc.mode = NAND_ECC_SOFT; + + printk("Searching for NAND flash...\n"); + /* Scan to find existence of the device */ + if (nand_scan(ts7250_mtd, 1)) { + kfree(ts7250_mtd); + return -ENXIO; + } +#ifdef CONFIG_MTD_PARTITIONS + ts7250_mtd->name = "ts7250-nand"; + mtd_parts_nb = parse_mtd_partitions(ts7250_mtd, part_probes, &mtd_parts, 0); + if (mtd_parts_nb > 0) + part_type = "command line"; + else + mtd_parts_nb = 0; +#endif + if (mtd_parts_nb == 0) { + mtd_parts = partition_info32; + if (ts7250_mtd->size >= (128 * 0x100000)) + mtd_parts = partition_info128; + mtd_parts_nb = NUM_PARTITIONS; + part_type = "static"; + } + + /* Register the partitions */ + printk(KERN_NOTICE "Using %s partition definition\n", part_type); + add_mtd_partitions(ts7250_mtd, mtd_parts, mtd_parts_nb); + + /* Return happy */ + return 0; +} + +module_init(ts7250_init); + +/* + * Clean up routine + */ +static void __exit ts7250_cleanup(void) +{ + /* Unregister the device */ + del_mtd_device(ts7250_mtd); + + /* Free the MTD device structure */ + kfree(ts7250_mtd); +} + +module_exit(ts7250_cleanup); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jesse Off <joff@embeddedARM.com>"); +MODULE_DESCRIPTION("MTD map driver for Technologic Systems TS-7250 board"); diff --git a/drivers/net/fs_enet/fec.h b/drivers/net/fs_enet/fec.h new file mode 100644 index 000000000..e980527e2 --- /dev/null +++ b/drivers/net/fs_enet/fec.h @@ -0,0 +1,42 @@ +#ifndef FS_ENET_FEC_H +#define FS_ENET_FEC_H + +/* CRC polynomium used by the FEC for the multicast group filtering */ +#define FEC_CRC_POLY 0x04C11DB7 + +#define FEC_MAX_MULTICAST_ADDRS 64 + +/* Interrupt events/masks. +*/ +#define FEC_ENET_HBERR 0x80000000U /* Heartbeat error */ +#define FEC_ENET_BABR 0x40000000U /* Babbling receiver */ +#define FEC_ENET_BABT 0x20000000U /* Babbling transmitter */ +#define FEC_ENET_GRA 0x10000000U /* Graceful stop complete */ +#define FEC_ENET_TXF 0x08000000U /* Full frame transmitted */ +#define FEC_ENET_TXB 0x04000000U /* A buffer was transmitted */ +#define FEC_ENET_RXF 0x02000000U /* Full frame received */ +#define FEC_ENET_RXB 0x01000000U /* A buffer was received */ +#define FEC_ENET_MII 0x00800000U /* MII interrupt */ +#define FEC_ENET_EBERR 0x00400000U /* SDMA bus error */ + +#define FEC_ECNTRL_PINMUX 0x00000004 +#define FEC_ECNTRL_ETHER_EN 0x00000002 +#define FEC_ECNTRL_RESET 0x00000001 + +#define FEC_RCNTRL_BC_REJ 0x00000010 +#define FEC_RCNTRL_PROM 0x00000008 +#define FEC_RCNTRL_MII_MODE 0x00000004 +#define FEC_RCNTRL_DRT 0x00000002 +#define FEC_RCNTRL_LOOP 0x00000001 + +#define FEC_TCNTRL_FDEN 0x00000004 +#define FEC_TCNTRL_HBC 0x00000002 +#define FEC_TCNTRL_GTS 0x00000001 + + + +/* + * Delay to wait for FEC reset command to complete (in us) + */ +#define FEC_RESET_DELAY 50 +#endif diff --git a/drivers/net/fs_enet/mii-fec.c b/drivers/net/fs_enet/mii-fec.c new file mode 100644 index 000000000..1328e10ca --- /dev/null +++ b/drivers/net/fs_enet/mii-fec.c @@ -0,0 +1,243 @@ +/* + * Combined Ethernet driver for Motorola MPC8xx and MPC82xx. + * + * Copyright (c) 2003 Intracom S.A. + * by Pantelis Antoniou <panto@intracom.gr> + * + * 2005 (c) MontaVista Software, Inc. + * Vitaly Bordug <vbordug@ru.mvista.com> + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/string.h> +#include <linux/ptrace.h> +#include <linux/errno.h> +#include <linux/ioport.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/spinlock.h> +#include <linux/mii.h> +#include <linux/ethtool.h> +#include <linux/bitops.h> +#include <linux/platform_device.h> + +#include <asm/pgtable.h> +#include <asm/irq.h> +#include <asm/uaccess.h> + +#include "fs_enet.h" +#include "fec.h" + +/* Make MII read/write commands for the FEC. +*/ +#define mk_mii_read(REG) (0x60020000 | ((REG & 0x1f) << 18)) +#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | (VAL & 0xffff)) +#define mk_mii_end 0 + +#define FEC_MII_LOOPS 10000 + +static int match_has_phy (struct device *dev, void* data) +{ + struct platform_device* pdev = container_of(dev, struct platform_device, dev); + struct fs_platform_info* fpi; + if(strcmp(pdev->name, (char*)data)) + { + return 0; + } + + fpi = pdev->dev.platform_data; + if((fpi)&&(fpi->has_phy)) + return 1; + return 0; +} + +static int fs_mii_fec_init(struct fec_info* fec, struct fs_mii_fec_platform_info *fmpi) +{ + struct resource *r; + fec_t *fecp; + char* name = "fsl-cpm-fec"; + + /* we need fec in order to be useful */ + struct platform_device *fec_pdev = + container_of(bus_find_device(&platform_bus_type, NULL, name, match_has_phy), + struct platform_device, dev); + + if(fec_pdev == NULL) { + printk(KERN_ERR"Unable to find PHY for %s", name); + return -ENODEV; + } + + r = platform_get_resource_byname(fec_pdev, IORESOURCE_MEM, "regs"); + + fec->fecp = fecp = (fec_t*)ioremap(r->start,sizeof(fec_t)); + fec->mii_speed = fmpi->mii_speed; + + setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE); /* MII enable */ + setbits32(&fecp->fec_ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN); + out_be32(&fecp->fec_ievent, FEC_ENET_MII); + out_be32(&fecp->fec_mii_speed, fec->mii_speed); + + return 0; +} + +static int fs_enet_fec_mii_read(struct mii_bus *bus , int phy_id, int location) +{ + struct fec_info* fec = bus->priv; + fec_t *fecp = fec->fecp; + int i, ret = -1; + + if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) + BUG(); + + /* Add PHY address to register command. */ + out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_read(location)); + + for (i = 0; i < FEC_MII_LOOPS; i++) + if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0) + break; + + if (i < FEC_MII_LOOPS) { + out_be32(&fecp->fec_ievent, FEC_ENET_MII); + ret = in_be32(&fecp->fec_mii_data) & 0xffff; + } + + return ret; + +} + +static int fs_enet_fec_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val) +{ + struct fec_info* fec = bus->priv; + fec_t *fecp = fec->fecp; + int i; + + /* this must never happen */ + if ((in_be32(&fecp->fec_r_cntrl) & FEC_RCNTRL_MII_MODE) == 0) + BUG(); + + /* Add PHY address to register command. */ + out_be32(&fecp->fec_mii_data, (phy_id << 23) | mk_mii_write(location, val)); + + for (i = 0; i < FEC_MII_LOOPS; i++) + if ((in_be32(&fecp->fec_ievent) & FEC_ENET_MII) != 0) + break; + + if (i < FEC_MII_LOOPS) + out_be32(&fecp->fec_ievent, FEC_ENET_MII); + + return 0; + +} + +static int fs_enet_fec_mii_reset(struct mii_bus *bus) +{ + /* nothing here - for now */ + return 0; +} + +static int __devinit fs_enet_fec_mdio_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct fs_mii_fec_platform_info *pdata; + struct mii_bus *new_bus; + struct fec_info *fec; + int err = 0; + if (NULL == dev) + return -EINVAL; + new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); + + if (NULL == new_bus) + return -ENOMEM; + + fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL); + + if (NULL == fec) + return -ENOMEM; + + new_bus->name = "FEC MII Bus", + new_bus->read = &fs_enet_fec_mii_read, + new_bus->write = &fs_enet_fec_mii_write, + new_bus->reset = &fs_enet_fec_mii_reset, + new_bus->id = pdev->id; + + pdata = (struct fs_mii_fec_platform_info *)pdev->dev.platform_data; + + if (NULL == pdata) { + printk(KERN_ERR "fs_enet FEC mdio %d: Missing platform data!\n", pdev->id); + return -ENODEV; + } + + /*set up workspace*/ + + fs_mii_fec_init(fec, pdata); + new_bus->priv = fec; + + new_bus->irq = pdata->irq; + + new_bus->dev = dev; + dev_set_drvdata(dev, new_bus); + + err = mdiobus_register(new_bus); + + if (0 != err) { + printk (KERN_ERR "%s: Cannot register as MDIO bus\n", + new_bus->name); + goto bus_register_fail; + } + + return 0; + +bus_register_fail: + kfree(new_bus); + + return err; +} + + +static int fs_enet_fec_mdio_remove(struct device *dev) +{ + struct mii_bus *bus = dev_get_drvdata(dev); + + mdiobus_unregister(bus); + + dev_set_drvdata(dev, NULL); + kfree(bus->priv); + + bus->priv = NULL; + kfree(bus); + + return 0; +} + +static struct device_driver fs_enet_fec_mdio_driver = { + .name = "fsl-cpm-fec-mdio", + .bus = &platform_bus_type, + .probe = fs_enet_fec_mdio_probe, + .remove = fs_enet_fec_mdio_remove, +}; + +int fs_enet_mdio_fec_init(void) +{ + return driver_register(&fs_enet_fec_mdio_driver); +} + +void fs_enet_mdio_fec_exit(void) +{ + driver_unregister(&fs_enet_fec_mdio_driver); +} + diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c new file mode 100644 index 000000000..415ba8dc9 --- /dev/null +++ b/drivers/net/irda/mcs7780.c @@ -0,0 +1,1008 @@ +/***************************************************************************** +* +* Filename: mcs7780.c +* Version: 0.4-alpha +* Description: Irda MosChip USB Dongle Driver +* Authors: Lukasz Stelmach <stlman@poczta.fm> +* Brian Pugh <bpugh@cs.pdx.edu> +* Judy Fischbach <jfisch@cs.pdx.edu> +* +* Based on stir4200 driver, but some things done differently. +* Based on earlier driver by Paul Stewart <stewart@parc.com> +* +* Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at> +* Copyright (C) 2001, Dag Brattli <dag@brattli.net> +* Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com> +* Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org> +* Copyright (C) 2005, Lukasz Stelmach <stlman@poczta.fm> +* Copyright (C) 2005, Brian Pugh <bpugh@cs.pdx.edu> +* Copyright (C) 2005, Judy Fischbach <jfisch@cs.pdx.edu> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****************************************************************************/ + +/* + * MCS7780 is a simple USB to IrDA bridge by MosChip. It is neither + * compatibile with irda-usb nor with stir4200. Although it is quite + * similar to the later as far as general idea of operation is concerned. + * That is it requires the software to do all the framing job at SIR speeds. + * The hardware does take care of the framing at MIR and FIR speeds. + * It supports all speeds from 2400 through 4Mbps + */ + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/kref.h> +#include <linux/usb.h> +#include <linux/device.h> +#include <linux/crc32.h> + +#include <asm/unaligned.h> +#include <asm/byteorder.h> +#include <asm/uaccess.h> + +#include <net/irda/irda.h> +#include <net/irda/wrapper.h> +#include <net/irda/crc.h> + +#include "mcs7780.h" + +#define MCS_VENDOR_ID 0x9710 +#define MCS_PRODUCT_ID 0x7780 + +static struct usb_device_id mcs_table[] = { + /* MosChip Corp., MCS7780 FIR-USB Adapter */ + {USB_DEVICE(MCS_VENDOR_ID, MCS_PRODUCT_ID)}, + {}, +}; + +MODULE_AUTHOR("Brian Pugh <bpugh@cs.pdx.edu>"); +MODULE_DESCRIPTION("IrDA-USB Dongle Driver for MosChip MCS7780"); +MODULE_VERSION("0.3alpha"); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(usb, mcs_table); + +static int qos_mtt_bits = 0x07 /* > 1ms */ ; +module_param(qos_mtt_bits, int, 0); +MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); + +static int receive_mode = 0x1; +module_param(receive_mode, int, 0); +MODULE_PARM_DESC(receive_mode, + "Receive mode of the device (1:fast, 0:slow, default:1)"); + +static int sir_tweak = 1; +module_param(sir_tweak, int, 0444); +MODULE_PARM_DESC(sir_tweak, + "Default pulse width (1:1.6us, 0:3/16 bit, default:1)."); + +static int transceiver_type = MCS_TSC_VISHAY; +module_param(transceiver_type, int, 0444); +MODULE_PARM_DESC(transceiver_type, "IR transceiver type, see mcs7780.h."); + +static struct usb_driver mcs_driver = { + .name = "mcs7780", + .probe = mcs_probe, + .disconnect = mcs_disconnect, + .id_table = mcs_table, +}; + +/* speed flag selection by direct addressing. +addr = (speed >> 8) & 0x0f + +0x1 57600 0x2 115200 0x4 1152000 0x5 9600 +0x6 38400 0x9 2400 0xa 576000 0xb 19200 + +4Mbps (or 2400) must be checked separately. Since it also has +to be programmed in a different manner that is not a big problem. +*/ +static __u16 mcs_speed_set[16] = { 0, + MCS_SPEED_57600, + MCS_SPEED_115200, + 0, + MCS_SPEED_1152000, + MCS_SPEED_9600, + MCS_SPEED_38400, + 0, 0, + MCS_SPEED_2400, + MCS_SPEED_576000, + MCS_SPEED_19200, + 0, 0, 0, +}; + +/* Set given 16 bit register with a 16 bit value. Send control message + * to set dongle register. */ +static int mcs_set_reg(struct mcs_cb *mcs, __u16 reg, __u16 val) +{ + struct usb_device *dev = mcs->usbdev; + return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, + MCS_WR_RTYPE, val, reg, NULL, 0, + msecs_to_jiffies(MCS_CTRL_TIMEOUT)); +} + +/* Get 16 bit register value. Send contol message to read dongle register. */ +static int mcs_get_reg(struct mcs_cb *mcs, __u16 reg, __u16 * val) +{ + struct usb_device *dev = mcs->usbdev; + int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, + MCS_RD_RTYPE, 0, reg, val, 2, + msecs_to_jiffies(MCS_CTRL_TIMEOUT)); + + return ret; +} + +/* Setup a communication between mcs7780 and TFDU chips. It is described + * in more detail in the data sheet. The setup sequence puts the the + * vishay tranceiver into high speed mode. It will also receive SIR speed + * packets but at reduced sensitivity. + */ + +/* 0: OK 1:ERROR */ +static inline int mcs_setup_transceiver_vishay(struct mcs_cb *mcs) +{ + int ret = 0; + __u16 rval; + + /* mcs_get_reg should read exactly two bytes from the dongle */ + ret = mcs_get_reg(mcs, MCS_XCVR_REG, &rval); + if (unlikely(ret != 2)) { + ret = -EIO; + goto error; + } + + /* The MCS_XCVR_CONF bit puts the transceiver into configuration + * mode. The MCS_MODE0 bit must start out high (1) and then + * transition to low and the MCS_STFIR and MCS_MODE1 bits must + * be low. + */ + rval |= (MCS_MODE0 | MCS_XCVR_CONF); + rval &= ~MCS_STFIR; + rval &= ~MCS_MODE1; + ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval); + if (unlikely(ret)) + goto error; + + rval &= ~MCS_MODE0; + ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval); + if (unlikely(ret)) + goto error; + + rval &= ~MCS_XCVR_CONF; + ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval); + if (unlikely(ret)) + goto error; + + ret = 0; + error: + return ret; +} + +/* Setup a communication between mcs7780 and agilent chip. */ +static inline int mcs_setup_transceiver_agilent(struct mcs_cb *mcs) +{ + IRDA_WARNING("This transceiver type is not supported yet."); + return 1; +} + +/* Setup a communication between mcs7780 and sharp chip. */ +static inline int mcs_setup_transceiver_sharp(struct mcs_cb *mcs) +{ + IRDA_WARNING("This transceiver type is not supported yet."); + return 1; +} + +/* Common setup for all transceivers */ +static inline int mcs_setup_transceiver(struct mcs_cb *mcs) +{ + int ret = 0; + __u16 rval; + char *msg; + + msg = "Basic transceiver setup error."; + + /* read value of MODE Register, set the DRIVER and RESET bits + * and write value back out to MODE Register + */ + ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval); + if(unlikely(ret != 2)) + goto error; + rval |= MCS_DRIVER; /* put the mcs7780 into configuration mode. */ + ret = mcs_set_reg(mcs, MCS_MODE_REG, rval); + if(unlikely(ret)) + goto error; + + rval = 0; /* set min pulse width to 0 initially. */ + ret = mcs_set_reg(mcs, MCS_MINRXPW_REG, rval); + if(unlikely(ret)) + goto error; + + ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval); + if(unlikely(ret != 2)) + goto error; + + rval &= ~MCS_FIR; /* turn off fir mode. */ + if(mcs->sir_tweak) + rval |= MCS_SIR16US; /* 1.6us pulse width */ + else + rval &= ~MCS_SIR16US; /* 3/16 bit time pulse width */ + + /* make sure ask mode and back to back packets are off. */ + rval &= ~(MCS_BBTG | MCS_ASK); + + rval &= ~MCS_SPEED_MASK; + rval |= MCS_SPEED_9600; /* make sure initial speed is 9600. */ + mcs->speed = 9600; + mcs->new_speed = 0; /* new_speed is set to 0 */ + rval &= ~MCS_PLLPWDN; /* disable power down. */ + + /* make sure device determines direction and that the auto send sip + * pulse are on. + */ + rval |= MCS_DTD | MCS_SIPEN; + + ret = mcs_set_reg(mcs, MCS_MODE_REG, rval); + if(unlikely(ret)) + goto error; + + msg = "transceiver model specific setup error."; + switch (mcs->transceiver_type) { + case MCS_TSC_VISHAY: + ret = mcs_setup_transceiver_vishay(mcs); + break; + + case MCS_TSC_SHARP: + ret = mcs_setup_transceiver_sharp(mcs); + break; + + case MCS_TSC_AGILENT: + ret = mcs_setup_transceiver_agilent(mcs); + break; + + default: + IRDA_WARNING("Unknown transceiver type: %d", + mcs->transceiver_type); + ret = 1; + } + if (unlikely(ret)) + goto error; + + /* If transceiver is not SHARP, then if receive mode set + * on the RXFAST bit in the XCVR Register otherwise unset it + */ + if (mcs->transceiver_type != MCS_TSC_SHARP) { + + ret = mcs_get_reg(mcs, MCS_XCVR_REG, &rval); + if (unlikely(ret != 2)) + goto error; + if (mcs->receive_mode) + rval |= MCS_RXFAST; + else + rval &= ~MCS_RXFAST; + ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval); + if (unlikely(ret)) + goto error; + } + + msg = "transceiver reset."; + + ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval); + if (unlikely(ret != 2)) + goto error; + + /* reset the mcs7780 so all changes take effect. */ + rval &= ~MCS_RESET; + ret = mcs_set_reg(mcs, MCS_MODE_REG, rval); + if (unlikely(ret)) + goto error; + else + return ret; + +error: + IRDA_ERROR("%s", msg); + return ret; +} + +/* Wraps the data in format for SIR */ +static inline int mcs_wrap_sir_skb(struct sk_buff *skb, __u8 * buf) +{ + int wraplen; + + /* 2: full frame length, including "the length" */ + wraplen = async_wrap_skb(skb, buf + 2, 4094); + + wraplen += 2; + buf[0] = wraplen & 0xff; + buf[1] = (wraplen >> 8) & 0xff; + + return wraplen; +} + +/* Wraps the data in format for FIR */ +static unsigned mcs_wrap_fir_skb(const struct sk_buff *skb, __u8 *buf) +{ + unsigned int len = 0; + __u32 fcs = ~(crc32_le(~0, skb->data, skb->len)); + + /* add 2 bytes for length value and 4 bytes for fcs. */ + len = skb->len + 6; + + /* The mcs7780 requires that the first two bytes are the packet + * length in little endian order. Note: the length value includes + * the two bytes for the length value itself. + */ + buf[0] = len & 0xff; + buf[1] = (len >> 8) & 0xff; + /* copy the data into the tx buffer. */ + memcpy(buf+2, skb->data, skb->len); + /* put the fcs in the last four bytes in little endian order. */ + buf[len - 4] = fcs & 0xff; + buf[len - 3] = (fcs >> 8) & 0xff; + buf[len - 2] = (fcs >> 16) & 0xff; + buf[len - 1] = (fcs >> 24) & 0xff; + + return len; +} + +/* Wraps the data in format for MIR */ +static unsigned mcs_wrap_mir_skb(const struct sk_buff *skb, __u8 *buf) +{ + __u16 fcs = 0; + int len = skb->len + 4; + + fcs = ~(irda_calc_crc16(~fcs, skb->data, skb->len)); + /* put the total packet length in first. Note: packet length + * value includes the two bytes that hold the packet length + * itself. + */ + buf[0] = len & 0xff; + buf[1] = (len >> 8) & 0xff; + /* copy the data */ + memcpy(buf+2, skb->data, skb->len); + /* put the fcs in last two bytes in little endian order. */ + buf[len - 2] = fcs & 0xff; + buf[len - 1] = (fcs >> 8) & 0xff; + + return len; +} + +/* Unwrap received packets at MIR speed. A 16 bit crc_ccitt checksum is + * used for the fcs. When performed over the entire packet the result + * should be GOOD_FCS = 0xf0b8. Hands the unwrapped data off to the IrDA + * layer via a sk_buff. + */ +static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len) +{ + __u16 fcs; + int new_len; + struct sk_buff *skb; + + /* Assume that the frames are going to fill a single packet + * rather than span multiple packets. + */ + + new_len = len - 2; + if(unlikely(new_len <= 0)) { + IRDA_ERROR("%s short frame length %d\n", + mcs->netdev->name, new_len); + ++mcs->stats.rx_errors; + ++mcs->stats.rx_length_errors; + return; + } + fcs = 0; + fcs = irda_calc_crc16(~fcs, buf, len); + + if(fcs != GOOD_FCS) { + IRDA_ERROR("crc error calc 0x%x len %d\n", + fcs, new_len); + mcs->stats.rx_errors++; + mcs->stats.rx_crc_errors++; + return; + } + + skb = dev_alloc_skb(new_len + 1); + if(unlikely(!skb)) { + ++mcs->stats.rx_dropped; + return; + } + + skb_reserve(skb, 1); + memcpy(skb->data, buf, new_len); + skb_put(skb, new_len); + skb->mac.raw = skb->data; + skb->protocol = htons(ETH_P_IRDA); + skb->dev = mcs->netdev; + + netif_rx(skb); + + mcs->stats.rx_packets++; + mcs->stats.rx_bytes += new_len; + + return; +} + +/* Unwrap received packets at FIR speed. A 32 bit crc_ccitt checksum is + * used for the fcs. Hands the unwrapped data off to the IrDA + * layer via a sk_buff. + */ +static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len) +{ + __u32 fcs; + int new_len; + struct sk_buff *skb; + + /* Assume that the frames are going to fill a single packet + * rather than span multiple packets. This is most likely a false + * assumption. + */ + + new_len = len - 4; + if(unlikely(new_len <= 0)) { + IRDA_ERROR("%s short frame length %d\n", + mcs->netdev->name, new_len); + ++mcs->stats.rx_errors; + ++mcs->stats.rx_length_errors; + return; + } + + fcs = ~(crc32_le(~0, buf, new_len)); + if(fcs != le32_to_cpu(get_unaligned((u32 *)(buf+new_len)))) { + IRDA_ERROR("crc error calc 0x%x len %d\n", fcs, new_len); + mcs->stats.rx_errors++; + mcs->stats.rx_crc_errors++; + return; + } + + skb = dev_alloc_skb(new_len + 1); + if(unlikely(!skb)) { + ++mcs->stats.rx_dropped; + return; + } + + skb_reserve(skb, 1); + memcpy(skb->data, buf, new_len); + skb_put(skb, new_len); + skb->mac.raw = skb->data; + skb->protocol = htons(ETH_P_IRDA); + skb->dev = mcs->netdev; + + netif_rx(skb); + + mcs->stats.rx_packets++; + mcs->stats.rx_bytes += new_len; + + return; +} + + +/* Allocates urbs for both receive and transmit. + * If alloc fails return error code 0 (fail) otherwise + * return error code 1 (success). + */ +static inline int mcs_setup_urbs(struct mcs_cb *mcs) +{ + mcs->rx_urb = NULL; + + mcs->tx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!mcs->tx_urb) + return 0; + + mcs->rx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!mcs->rx_urb) + return 0; + + return 1; +} + +/* Sets up state to be initially outside frame, gets receive urb, + * sets status to successful and then submits the urb to start + * receiving the data. + */ +static inline int mcs_receive_start(struct mcs_cb *mcs) +{ + mcs->rx_buff.in_frame = FALSE; + mcs->rx_buff.state = OUTSIDE_FRAME; + + usb_fill_bulk_urb(mcs->rx_urb, mcs->usbdev, + usb_rcvbulkpipe(mcs->usbdev, mcs->ep_in), + mcs->in_buf, 4096, mcs_receive_irq, mcs); + + mcs->rx_urb->status = 0; + return usb_submit_urb(mcs->rx_urb, GFP_KERNEL); +} + +/* Finds the in and out endpoints for the mcs control block */ +static inline int mcs_find_endpoints(struct mcs_cb *mcs, + struct usb_host_endpoint *ep, int epnum) +{ + int i; + int ret = 0; + + /* If no place to store the endpoints just return */ + if (!ep) + return ret; + + /* cycle through all endpoints, find the first two that are DIR_IN */ + for (i = 0; i < epnum; i++) { + if (ep[i].desc.bEndpointAddress & USB_DIR_IN) + mcs->ep_in = ep[i].desc.bEndpointAddress; + else + mcs->ep_out = ep[i].desc.bEndpointAddress; + + /* MosChip says that the chip has only two bulk + * endpoints. Find one for each direction and move on. + */ + if ((mcs->ep_in != 0) && (mcs->ep_out != 0)) { + ret = 1; + break; + } + } + + return ret; +} + +static void mcs_speed_work(void *arg) +{ + struct mcs_cb *mcs = arg; + struct net_device *netdev = mcs->netdev; + + mcs_speed_change(mcs); + netif_wake_queue(netdev); +} + +/* Function to change the speed of the mcs7780. Fully supports SIR, + * MIR, and FIR speeds. + */ +static int mcs_speed_change(struct mcs_cb *mcs) +{ + int ret = 0; + int rst = 0; + int cnt = 0; + __u16 nspeed; + __u16 rval; + + nspeed = mcs_speed_set[(mcs->new_speed >> 8) & 0x0f]; + + do { + mcs_get_reg(mcs, MCS_RESV_REG, &rval); + } while(cnt++ < 100 && (rval & MCS_IRINTX)); + + if(cnt >= 100) { + IRDA_ERROR("unable to change speed"); + ret = -EIO; + goto error; + } + + mcs_get_reg(mcs, MCS_MODE_REG, &rval); + + /* MINRXPW values recomended by MosChip */ + if (mcs->new_speed <= 115200) { + rval &= ~MCS_FIR; + + if ((rst = (mcs->speed > 115200))) + mcs_set_reg(mcs, MCS_MINRXPW_REG, 0); + + } else if (mcs->new_speed <= 1152000) { + rval &= ~MCS_FIR; + + if ((rst = !(mcs->speed == 576000 || mcs->speed == 1152000))) + mcs_set_reg(mcs, MCS_MINRXPW_REG, 5); + + } else { + rval |= MCS_FIR; + + if ((rst = (mcs->speed != 4000000))) + mcs_set_reg(mcs, MCS_MINRXPW_REG, 5); + + } + + rval &= ~MCS_SPEED_MASK; + rval |= nspeed; + + ret = mcs_set_reg(mcs, MCS_MODE_REG, rval); + if (unlikely(ret)) + goto error; + + if (rst) + switch (mcs->transceiver_type) { + case MCS_TSC_VISHAY: + ret = mcs_setup_transceiver_vishay(mcs); + break; + + case MCS_TSC_SHARP: + ret = mcs_setup_transceiver_sharp(mcs); + break; + + case MCS_TSC_AGILENT: + ret = mcs_setup_transceiver_agilent(mcs); + break; + + default: + ret = 1; + IRDA_WARNING("Unknown transceiver type: %d", + mcs->transceiver_type); + } + if (unlikely(ret)) + goto error; + + mcs_get_reg(mcs, MCS_MODE_REG, &rval); + rval &= ~MCS_RESET; + ret = mcs_set_reg(mcs, MCS_MODE_REG, rval); + + mcs->speed = mcs->new_speed; + error: + mcs->new_speed = 0; + return ret; +} + +/* Ioctl calls not supported at this time. Can be an area of future work. */ +static int mcs_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) +{ + /* struct if_irda_req *irq = (struct if_irda_req *)rq; */ + /* struct mcs_cb *mcs = netdev_priv(netdev); */ + int ret = 0; + + switch (cmd) { + default: + ret = -EOPNOTSUPP; + } + + return ret; +} + +/* Network device is taken down, done by "ifconfig irda0 down" */ +static int mcs_net_close(struct net_device *netdev) +{ + int ret = 0; + struct mcs_cb *mcs = netdev_priv(netdev); + + /* Stop transmit processing */ + netif_stop_queue(netdev); + + /* kill and free the receive and transmit URBs */ + usb_kill_urb(mcs->rx_urb); + usb_free_urb(mcs->rx_urb); + usb_kill_urb(mcs->tx_urb); + usb_free_urb(mcs->tx_urb); + + /* Stop and remove instance of IrLAP */ + if (mcs->irlap) + irlap_close(mcs->irlap); + + mcs->irlap = NULL; + return ret; +} + +/* Network device is taken up, done by "ifconfig irda0 up" */ +static int mcs_net_open(struct net_device *netdev) +{ + struct mcs_cb *mcs = netdev_priv(netdev); + char hwname[16]; + int ret = 0; + + ret = usb_clear_halt(mcs->usbdev, + usb_sndbulkpipe(mcs->usbdev, mcs->ep_in)); + if (ret) + goto error1; + ret = usb_clear_halt(mcs->usbdev, + usb_rcvbulkpipe(mcs->usbdev, mcs->ep_out)); + if (ret) + goto error1; + + ret = mcs_setup_transceiver(mcs); + if (ret) + goto error1; + + ret = -ENOMEM; + + /* Initialize for SIR/FIR to copy data directly into skb. */ + mcs->receiving = 0; + mcs->rx_buff.truesize = IRDA_SKB_MAX_MTU; + mcs->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); + if (!mcs->rx_buff.skb) + goto error1; + + skb_reserve(mcs->rx_buff.skb, 1); + mcs->rx_buff.head = mcs->rx_buff.skb->data; + do_gettimeofday(&mcs->rx_time); + + /* + * Now that everything should be initialized properly, + * Open new IrLAP layer instance to take care of us... + * Note : will send immediately a speed change... + */ + sprintf(hwname, "usb#%d", mcs->usbdev->devnum); + mcs->irlap = irlap_open(netdev, &mcs->qos, hwname); + if (!mcs->irlap) { + IRDA_ERROR("mcs7780: irlap_open failed"); + goto error2; + } + + if (!mcs_setup_urbs(mcs)) + goto error3; + + ret = mcs_receive_start(mcs); + if (ret) + goto error3; + + netif_start_queue(netdev); + return 0; + + error3: + irlap_close(mcs->irlap); + error2: + kfree_skb(mcs->rx_buff.skb); + error1: + return ret; +} + + +/* Get device stats for /proc/net/dev and ifconfig */ +static struct net_device_stats *mcs_net_get_stats(struct net_device *netdev) +{ + struct mcs_cb *mcs = netdev_priv(netdev); + return &mcs->stats; +} + +/* Receive callback function. */ +static void mcs_receive_irq(struct urb *urb, struct pt_regs *regs) +{ + __u8 *bytes; + struct mcs_cb *mcs = urb->context; + int i; + int ret; + + if (!netif_running(mcs->netdev)) + return; + + if (urb->status) + return; + + if (urb->actual_length > 0) { + bytes = urb->transfer_buffer; + + /* MCS returns frames without BOF and EOF + * I assume it returns whole frames. + */ + /* SIR speed */ + if(mcs->speed < 576000) { + async_unwrap_char(mcs->netdev, &mcs->stats, + &mcs->rx_buff, 0xc0); + + for (i = 0; i < urb->actual_length; i++) + async_unwrap_char(mcs->netdev, &mcs->stats, + &mcs->rx_buff, bytes[i]); + + async_unwrap_char(mcs->netdev, &mcs->stats, + &mcs->rx_buff, 0xc1); + } + /* MIR speed */ + else if(mcs->speed == 576000 || mcs->speed == 1152000) { + mcs_unwrap_mir(mcs, urb->transfer_buffer, + urb->actual_length); + } + /* FIR speed */ + else { + mcs_unwrap_fir(mcs, urb->transfer_buffer, + urb->actual_length); + } + mcs->netdev->last_rx = jiffies; + do_gettimeofday(&mcs->rx_time); + } + + ret = usb_submit_urb(urb, GFP_ATOMIC); +} + +/* Transmit callback funtion. */ +static void mcs_send_irq(struct urb *urb, struct pt_regs *regs) +{ + struct mcs_cb *mcs = urb->context; + struct net_device *ndev = mcs->netdev; + + if (unlikely(mcs->new_speed)) + schedule_work(&mcs->work); + else + netif_wake_queue(ndev); +} + +/* Transmit callback funtion. */ +static int mcs_hard_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + unsigned long flags; + struct mcs_cb *mcs; + int wraplen; + int ret = 0; + + + if (skb == NULL || ndev == NULL) + return -EINVAL; + + netif_stop_queue(ndev); + mcs = netdev_priv(ndev); + + spin_lock_irqsave(&mcs->lock, flags); + + mcs->new_speed = irda_get_next_speed(skb); + if (likely(mcs->new_speed == mcs->speed)) + mcs->new_speed = 0; + + /* SIR speed */ + if(mcs->speed < 576000) { + wraplen = mcs_wrap_sir_skb(skb, mcs->out_buf); + } + /* MIR speed */ + else if(mcs->speed == 576000 || mcs->speed == 1152000) { + wraplen = mcs_wrap_mir_skb(skb, mcs->out_buf); + } + /* FIR speed */ + else { + wraplen = mcs_wrap_fir_skb(skb, mcs->out_buf); + } + usb_fill_bulk_urb(mcs->tx_urb, mcs->usbdev, + usb_sndbulkpipe(mcs->usbdev, mcs->ep_out), + mcs->out_buf, wraplen, mcs_send_irq, mcs); + + if ((ret = usb_submit_urb(mcs->tx_urb, GFP_ATOMIC))) { + IRDA_ERROR("failed tx_urb: %d", ret); + switch (ret) { + case -ENODEV: + case -EPIPE: + break; + default: + mcs->stats.tx_errors++; + netif_start_queue(ndev); + } + } else { + mcs->stats.tx_packets++; + mcs->stats.tx_bytes += skb->len; + } + + dev_kfree_skb(skb); + spin_unlock_irqrestore(&mcs->lock, flags); + return ret; +} + +/* + * This function is called by the USB subsystem for each new device in the + * system. Need to verify the device and if it is, then start handling it. + */ +static int mcs_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct net_device *ndev = NULL; + struct mcs_cb *mcs; + int ret = -ENOMEM; + + ndev = alloc_irdadev(sizeof(*mcs)); + if (!ndev) + goto error1; + + IRDA_DEBUG(1, "MCS7780 USB-IrDA bridge found at %d.", udev->devnum); + + /* what is it realy for? */ + SET_MODULE_OWNER(ndev); + SET_NETDEV_DEV(ndev, &intf->dev); + + ret = usb_reset_configuration(udev); + if (ret != 0) { + IRDA_ERROR("mcs7780: usb reset configuration failed"); + goto error2; + } + + mcs = netdev_priv(ndev); + mcs->usbdev = udev; + mcs->netdev = ndev; + spin_lock_init(&mcs->lock); + + /* Initialize QoS for this device */ + irda_init_max_qos_capabilies(&mcs->qos); + + /* That's the Rx capability. */ + mcs->qos.baud_rate.bits &= + IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200 + | IR_576000 | IR_1152000 | (IR_4000000 << 8); + + + mcs->qos.min_turn_time.bits &= qos_mtt_bits; + irda_qos_bits_to_value(&mcs->qos); + + /* Speed change work initialisation*/ + INIT_WORK(&mcs->work, mcs_speed_work, mcs); + + /* Override the network functions we need to use */ + ndev->hard_start_xmit = mcs_hard_xmit; + ndev->open = mcs_net_open; + ndev->stop = mcs_net_close; + ndev->get_stats = mcs_net_get_stats; + ndev->do_ioctl = mcs_net_ioctl; + + if (!intf->cur_altsetting) + goto error2; + + ret = mcs_find_endpoints(mcs, intf->cur_altsetting->endpoint, + intf->cur_altsetting->desc.bNumEndpoints); + if (!ret) { + ret = -ENODEV; + goto error2; + } + + ret = register_netdev(ndev); + if (ret != 0) + goto error2; + + IRDA_DEBUG(1, "IrDA: Registered MosChip MCS7780 device as %s", + ndev->name); + + mcs->transceiver_type = transceiver_type; + mcs->sir_tweak = sir_tweak; + mcs->receive_mode = receive_mode; + + usb_set_intfdata(intf, mcs); + return 0; + + error2: + free_netdev(ndev); + + error1: + return ret; +} + +/* The current device is removed, the USB layer tells us to shut down. */ +static void mcs_disconnect(struct usb_interface *intf) +{ + struct mcs_cb *mcs = usb_get_intfdata(intf); + + if (!mcs) + return; + + flush_scheduled_work(); + + unregister_netdev(mcs->netdev); + free_netdev(mcs->netdev); + + usb_set_intfdata(intf, NULL); + IRDA_DEBUG(0, "MCS7780 now disconnected."); +} + +/* Module insertion */ +static int __init mcs_init(void) +{ + int result; + + /* register this driver with the USB subsystem */ + result = usb_register(&mcs_driver); + if (result) + IRDA_ERROR("usb_register failed. Error number %d", result); + + return result; +} +module_init(mcs_init); + +/* Module removal */ +static void __exit mcs_exit(void) +{ + /* deregister this driver with the USB subsystem */ + usb_deregister(&mcs_driver); +} +module_exit(mcs_exit); + diff --git a/drivers/net/irda/mcs7780.h b/drivers/net/irda/mcs7780.h new file mode 100644 index 000000000..1a723d725 --- /dev/null +++ b/drivers/net/irda/mcs7780.h @@ -0,0 +1,167 @@ +/***************************************************************************** +* +* Filename: mcs7780.h +* Version: 0.2-alpha +* Description: Irda MosChip USB Dongle +* Status: Experimental +* Authors: Lukasz Stelmach <stlman@poczta.fm> +* Brian Pugh <bpugh@cs.pdx.edu> +* +* Copyright (C) 2005, Lukasz Stelmach <stlman@poczta.fm> +* Copyright (C) 2005, Brian Pugh <bpugh@cs.pdx.edu> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +*****************************************************************************/ +#ifndef _MCS7780_H +#define _MCS7780_H + +#define MCS_MODE_SIR 0 +#define MCS_MODE_MIR 1 +#define MCS_MODE_FIR 2 + +#define MCS_CTRL_TIMEOUT 500 +#define MCS_XMIT_TIMEOUT 500 +/* Possible transceiver types */ +#define MCS_TSC_VISHAY 0 /* Vishay TFD, default choice */ +#define MCS_TSC_AGILENT 1 /* Agilent 3602/3600 */ +#define MCS_TSC_SHARP 2 /* Sharp GP2W1000YP */ + +/* Requests */ +#define MCS_RD_RTYPE 0xC0 +#define MCS_WR_RTYPE 0x40 +#define MCS_RDREQ 0x0F +#define MCS_WRREQ 0x0E + +/* Register 0x00 */ +#define MCS_MODE_REG 0 +#define MCS_FIR ((__u16)0x0001) +#define MCS_SIR16US ((__u16)0x0002) +#define MCS_BBTG ((__u16)0x0004) +#define MCS_ASK ((__u16)0x0008) +#define MCS_PARITY ((__u16)0x0010) + +/* SIR/MIR speed constants */ +#define MCS_SPEED_SHIFT 5 +#define MCS_SPEED_MASK ((__u16)0x00E0) +#define MCS_SPEED(x) ((x & MCS_SPEED_MASK) >> MCS_SPEED_SHIFT) +#define MCS_SPEED_2400 ((0 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) +#define MCS_SPEED_9600 ((1 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) +#define MCS_SPEED_19200 ((2 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) +#define MCS_SPEED_38400 ((3 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) +#define MCS_SPEED_57600 ((4 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) +#define MCS_SPEED_115200 ((5 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) +#define MCS_SPEED_576000 ((6 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) +#define MCS_SPEED_1152000 ((7 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) + +#define MCS_PLLPWDN ((__u16)0x0100) +#define MCS_DRIVER ((__u16)0x0200) +#define MCS_DTD ((__u16)0x0400) +#define MCS_DIR ((__u16)0x0800) +#define MCS_SIPEN ((__u16)0x1000) +#define MCS_SENDSIP ((__u16)0x2000) +#define MCS_CHGDIR ((__u16)0x4000) +#define MCS_RESET ((__u16)0x8000) + +/* Register 0x02 */ +#define MCS_XCVR_REG 2 +#define MCS_MODE0 ((__u16)0x0001) +#define MCS_STFIR ((__u16)0x0002) +#define MCS_XCVR_CONF ((__u16)0x0004) +#define MCS_RXFAST ((__u16)0x0008) +/* TXCUR [6:4] */ +#define MCS_TXCUR_SHIFT 4 +#define MCS_TXCUR_MASK ((__u16)0x0070) +#define MCS_TXCUR(x) ((x & MCS_TXCUR_MASK) >> MCS_TXCUR_SHIFT) +#define MCS_SETTXCUR(x,y) \ + ((x & ~MCS_TXCUR_MASK) | (y << MCS_TXCUR_SHIFT) & MCS_TXCUR_MASK) + +#define MCS_MODE1 ((__u16)0x0080) +#define MCS_SMODE0 ((__u16)0x0100) +#define MCS_SMODE1 ((__u16)0x0200) +#define MCS_INVTX ((__u16)0x0400) +#define MCS_INVRX ((__u16)0x0800) + +#define MCS_MINRXPW_REG 4 + +#define MCS_RESV_REG 7 +#define MCS_IRINTX ((__u16)0x0001) +#define MCS_IRINRX ((__u16)0x0002) + +struct mcs_cb { + struct usb_device *usbdev; /* init: probe_irda */ + struct net_device *netdev; /* network layer */ + struct irlap_cb *irlap; /* The link layer we are binded to */ + struct net_device_stats stats; /* network statistics */ + struct qos_info qos; + unsigned int speed; /* Current speed */ + unsigned int new_speed; /* new speed */ + + struct work_struct work; /* Change speed work */ + + struct sk_buff *tx_pending; + char in_buf[4096]; /* transmit/receive buffer */ + char out_buf[4096]; /* transmit/receive buffer */ + __u8 *fifo_status; + + iobuff_t rx_buff; /* receive unwrap state machine */ + struct timeval rx_time; + spinlock_t lock; + int receiving; + + __u8 ep_in; + __u8 ep_out; + + struct urb *rx_urb; + struct urb *tx_urb; + + int transceiver_type; + int sir_tweak; + int receive_mode; +}; + +static int mcs_set_reg(struct mcs_cb *mcs, __u16 reg, __u16 val); +static int mcs_get_reg(struct mcs_cb *mcs, __u16 reg, __u16 * val); + +static inline int mcs_setup_transceiver_vishay(struct mcs_cb *mcs); +static inline int mcs_setup_transceiver_agilent(struct mcs_cb *mcs); +static inline int mcs_setup_transceiver_sharp(struct mcs_cb *mcs); +static inline int mcs_setup_transceiver(struct mcs_cb *mcs); +static inline int mcs_wrap_sir_skb(struct sk_buff *skb, __u8 * buf); +static unsigned mcs_wrap_fir_skb(const struct sk_buff *skb, __u8 *buf); +static unsigned mcs_wrap_mir_skb(const struct sk_buff *skb, __u8 *buf); +static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len); +static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len); +static inline int mcs_setup_urbs(struct mcs_cb *mcs); +static inline int mcs_receive_start(struct mcs_cb *mcs); +static inline int mcs_find_endpoints(struct mcs_cb *mcs, + struct usb_host_endpoint *ep, int epnum); + +static int mcs_speed_change(struct mcs_cb *mcs); + +static int mcs_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd); +static int mcs_net_close(struct net_device *netdev); +static int mcs_net_open(struct net_device *netdev); +static struct net_device_stats *mcs_net_get_stats(struct net_device *netdev); + +static void mcs_receive_irq(struct urb *urb, struct pt_regs *regs); +static void mcs_send_irq(struct urb *urb, struct pt_regs *regs); +static int mcs_hard_xmit(struct sk_buff *skb, struct net_device *netdev); + +static int mcs_probe(struct usb_interface *intf, + const struct usb_device_id *id); +static void mcs_disconnect(struct usb_interface *intf); + +#endif /* _MCS7780_H */ diff --git a/drivers/net/myri10ge/Makefile b/drivers/net/myri10ge/Makefile new file mode 100644 index 000000000..5df891647 --- /dev/null +++ b/drivers/net/myri10ge/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the Myricom Myri-10G ethernet driver +# + +obj-$(CONFIG_MYRI10GE) += myri10ge.o diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c new file mode 100644 index 000000000..9bdd43ab3 --- /dev/null +++ b/drivers/net/myri10ge/myri10ge.c @@ -0,0 +1,2866 @@ +/************************************************************************* + * myri10ge.c: Myricom Myri-10G Ethernet driver. + * + * Copyright (C) 2005, 2006 Myricom, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Myricom, Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + * If the eeprom on your board is not recent enough, you will need to get a + * newer firmware image at: + * http://www.myri.com/scs/download-Myri10GE.html + * + * Contact Information: + * <help@myri.com> + * Myricom, Inc., 325N Santa Anita Avenue, Arcadia, CA 91006 + *************************************************************************/ + +#include <linux/tcp.h> +#include <linux/netdevice.h> +#include <linux/skbuff.h> +#include <linux/string.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/dma-mapping.h> +#include <linux/etherdevice.h> +#include <linux/if_ether.h> +#include <linux/if_vlan.h> +#include <linux/ip.h> +#include <linux/inet.h> +#include <linux/in.h> +#include <linux/ethtool.h> +#include <linux/firmware.h> +#include <linux/delay.h> +#include <linux/version.h> +#include <linux/timer.h> +#include <linux/vmalloc.h> +#include <linux/crc32.h> +#include <linux/moduleparam.h> +#include <linux/io.h> +#include <net/checksum.h> +#include <asm/byteorder.h> +#include <asm/io.h> +#include <asm/processor.h> +#ifdef CONFIG_MTRR +#include <asm/mtrr.h> +#endif + +#include "myri10ge_mcp.h" +#include "myri10ge_mcp_gen_header.h" + +#define MYRI10GE_VERSION_STR "1.0.0" + +MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); +MODULE_AUTHOR("Maintainer: help@myri.com"); +MODULE_VERSION(MYRI10GE_VERSION_STR); +MODULE_LICENSE("Dual BSD/GPL"); + +#define MYRI10GE_MAX_ETHER_MTU 9014 + +#define MYRI10GE_ETH_STOPPED 0 +#define MYRI10GE_ETH_STOPPING 1 +#define MYRI10GE_ETH_STARTING 2 +#define MYRI10GE_ETH_RUNNING 3 +#define MYRI10GE_ETH_OPEN_FAILED 4 + +#define MYRI10GE_EEPROM_STRINGS_SIZE 256 +#define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2) + +#define MYRI10GE_NO_CONFIRM_DATA 0xffffffff +#define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff + +struct myri10ge_rx_buffer_state { + struct sk_buff *skb; + DECLARE_PCI_UNMAP_ADDR(bus) + DECLARE_PCI_UNMAP_LEN(len) +}; + +struct myri10ge_tx_buffer_state { + struct sk_buff *skb; + int last; + DECLARE_PCI_UNMAP_ADDR(bus) + DECLARE_PCI_UNMAP_LEN(len) +}; + +struct myri10ge_cmd { + u32 data0; + u32 data1; + u32 data2; +}; + +struct myri10ge_rx_buf { + struct mcp_kreq_ether_recv __iomem *lanai; /* lanai ptr for recv ring */ + u8 __iomem *wc_fifo; /* w/c rx dma addr fifo address */ + struct mcp_kreq_ether_recv *shadow; /* host shadow of recv ring */ + struct myri10ge_rx_buffer_state *info; + int cnt; + int alloc_fail; + int mask; /* number of rx slots -1 */ +}; + +struct myri10ge_tx_buf { + struct mcp_kreq_ether_send __iomem *lanai; /* lanai ptr for sendq */ + u8 __iomem *wc_fifo; /* w/c send fifo address */ + struct mcp_kreq_ether_send *req_list; /* host shadow of sendq */ + char *req_bytes; + struct myri10ge_tx_buffer_state *info; + int mask; /* number of transmit slots -1 */ + int boundary; /* boundary transmits cannot cross */ + int req ____cacheline_aligned; /* transmit slots submitted */ + int pkt_start; /* packets started */ + int done ____cacheline_aligned; /* transmit slots completed */ + int pkt_done; /* packets completed */ +}; + +struct myri10ge_rx_done { + struct mcp_slot *entry; + dma_addr_t bus; + int cnt; + int idx; +}; + +struct myri10ge_priv { + int running; /* running? */ + int csum_flag; /* rx_csums? */ + struct myri10ge_tx_buf tx; /* transmit ring */ + struct myri10ge_rx_buf rx_small; + struct myri10ge_rx_buf rx_big; + struct myri10ge_rx_done rx_done; + int small_bytes; + struct net_device *dev; + struct net_device_stats stats; + u8 __iomem *sram; + int sram_size; + unsigned long board_span; + unsigned long iomem_base; + u32 __iomem *irq_claim; + u32 __iomem *irq_deassert; + char *mac_addr_string; + struct mcp_cmd_response *cmd; + dma_addr_t cmd_bus; + struct mcp_irq_data *fw_stats; + dma_addr_t fw_stats_bus; + struct pci_dev *pdev; + int msi_enabled; + unsigned int link_state; + unsigned int rdma_tags_available; + int intr_coal_delay; + u32 __iomem *intr_coal_delay_ptr; + int mtrr; + int wake_queue; + int stop_queue; + int down_cnt; + wait_queue_head_t down_wq; + struct work_struct watchdog_work; + struct timer_list watchdog_timer; + int watchdog_tx_done; + int watchdog_tx_req; + int watchdog_resets; + int tx_linearized; + int pause; + char *fw_name; + char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE]; + char fw_version[128]; + u8 mac_addr[6]; /* eeprom mac address */ + unsigned long serial_number; + int vendor_specific_offset; + u32 devctl; + u16 msi_flags; + u32 read_dma; + u32 write_dma; + u32 read_write_dma; +}; + +static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat"; +static char *myri10ge_fw_aligned = "myri10ge_eth_z8e.dat"; + +static char *myri10ge_fw_name = NULL; +module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name\n"); + +static int myri10ge_ecrc_enable = 1; +module_param(myri10ge_ecrc_enable, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_ecrc_enable, "Enable Extended CRC on PCI-E\n"); + +static int myri10ge_max_intr_slots = 1024; +module_param(myri10ge_max_intr_slots, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_max_intr_slots, "Interrupt queue slots\n"); + +static int myri10ge_small_bytes = -1; /* -1 == auto */ +module_param(myri10ge_small_bytes, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(myri10ge_small_bytes, "Threshold of small packets\n"); + +static int myri10ge_msi = 1; /* enable msi by default */ +module_param(myri10ge_msi, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_msi, "Enable Message Signalled Interrupts\n"); + +static int myri10ge_intr_coal_delay = 25; +module_param(myri10ge_intr_coal_delay, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_intr_coal_delay, "Interrupt coalescing delay\n"); + +static int myri10ge_flow_control = 1; +module_param(myri10ge_flow_control, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_flow_control, "Pause parameter\n"); + +static int myri10ge_deassert_wait = 1; +module_param(myri10ge_deassert_wait, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(myri10ge_deassert_wait, + "Wait when deasserting legacy interrupts\n"); + +static int myri10ge_force_firmware = 0; +module_param(myri10ge_force_firmware, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_force_firmware, + "Force firmware to assume aligned completions\n"); + +static int myri10ge_skb_cross_4k = 0; +module_param(myri10ge_skb_cross_4k, int, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(myri10ge_skb_cross_4k, + "Can a small skb cross a 4KB boundary?\n"); + +static int myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN; +module_param(myri10ge_initial_mtu, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_initial_mtu, "Initial MTU\n"); + +static int myri10ge_napi_weight = 64; +module_param(myri10ge_napi_weight, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_napi_weight, "Set NAPI weight\n"); + +static int myri10ge_watchdog_timeout = 1; +module_param(myri10ge_watchdog_timeout, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_watchdog_timeout, "Set watchdog timeout\n"); + +static int myri10ge_max_irq_loops = 1048576; +module_param(myri10ge_max_irq_loops, int, S_IRUGO); +MODULE_PARM_DESC(myri10ge_max_irq_loops, + "Set stuck legacy IRQ detection threshold\n"); + +#define MYRI10GE_FW_OFFSET 1024*1024 +#define MYRI10GE_HIGHPART_TO_U32(X) \ +(sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0) +#define MYRI10GE_LOWPART_TO_U32(X) ((u32)(X)) + +#define myri10ge_pio_copy(to,from,size) __iowrite64_copy(to,from,size/8) + +static int +myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, + struct myri10ge_cmd *data, int atomic) +{ + struct mcp_cmd *buf; + char buf_bytes[sizeof(*buf) + 8]; + struct mcp_cmd_response *response = mgp->cmd; + char __iomem *cmd_addr = mgp->sram + MXGEFW_CMD_OFFSET; + u32 dma_low, dma_high, result, value; + int sleep_total = 0; + + /* ensure buf is aligned to 8 bytes */ + buf = (struct mcp_cmd *)ALIGN((unsigned long)buf_bytes, 8); + + buf->data0 = htonl(data->data0); + buf->data1 = htonl(data->data1); + buf->data2 = htonl(data->data2); + buf->cmd = htonl(cmd); + dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus); + dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus); + + buf->response_addr.low = htonl(dma_low); + buf->response_addr.high = htonl(dma_high); + response->result = MYRI10GE_NO_RESPONSE_RESULT; + mb(); + myri10ge_pio_copy(cmd_addr, buf, sizeof(*buf)); + + /* wait up to 15ms. Longest command is the DMA benchmark, + * which is capped at 5ms, but runs from a timeout handler + * that runs every 7.8ms. So a 15ms timeout leaves us with + * a 2.2ms margin + */ + if (atomic) { + /* if atomic is set, do not sleep, + * and try to get the completion quickly + * (1ms will be enough for those commands) */ + for (sleep_total = 0; + sleep_total < 1000 + && response->result == MYRI10GE_NO_RESPONSE_RESULT; + sleep_total += 10) + udelay(10); + } else { + /* use msleep for most command */ + for (sleep_total = 0; + sleep_total < 15 + && response->result == MYRI10GE_NO_RESPONSE_RESULT; + sleep_total++) + msleep(1); + } + + result = ntohl(response->result); + value = ntohl(response->data); + if (result != MYRI10GE_NO_RESPONSE_RESULT) { + if (result == 0) { + data->data0 = value; + return 0; + } else { + dev_err(&mgp->pdev->dev, + "command %d failed, result = %d\n", + cmd, result); + return -ENXIO; + } + } + + dev_err(&mgp->pdev->dev, "command %d timed out, result = %d\n", + cmd, result); + return -EAGAIN; +} + +/* + * The eeprom strings on the lanaiX have the format + * SN=x\0 + * MAC=x:x:x:x:x:x\0 + * PT:ddd mmm xx xx:xx:xx xx\0 + * PV:ddd mmm xx xx:xx:xx xx\0 + */ +static int myri10ge_read_mac_addr(struct myri10ge_priv *mgp) +{ + char *ptr, *limit; + int i; + + ptr = mgp->eeprom_strings; + limit = mgp->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE; + + while (*ptr != '\0' && ptr < limit) { + if (memcmp(ptr, "MAC=", 4) == 0) { + ptr += 4; + mgp->mac_addr_string = ptr; + for (i = 0; i < 6; i++) { + if ((ptr + 2) > limit) + goto abort; + mgp->mac_addr[i] = + simple_strtoul(ptr, &ptr, 16); + ptr += 1; + } + } + if (memcmp((const void *)ptr, "SN=", 3) == 0) { + ptr += 3; + mgp->serial_number = simple_strtoul(ptr, &ptr, 10); + } + while (ptr < limit && *ptr++) ; + } + + return 0; + +abort: + dev_err(&mgp->pdev->dev, "failed to parse eeprom_strings\n"); + return -ENXIO; +} + +/* + * Enable or disable periodic RDMAs from the host to make certain + * chipsets resend dropped PCIe messages + */ + +static void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable) +{ + char __iomem *submit; + u32 buf[16]; + u32 dma_low, dma_high; + int i; + + /* clear confirmation addr */ + mgp->cmd->data = 0; + mb(); + + /* send a rdma command to the PCIe engine, and wait for the + * response in the confirmation address. The firmware should + * write a -1 there to indicate it is alive and well + */ + dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus); + dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus); + + buf[0] = htonl(dma_high); /* confirm addr MSW */ + buf[1] = htonl(dma_low); /* confirm addr LSW */ + buf[2] = htonl(MYRI10GE_NO_CONFIRM_DATA); /* confirm data */ + buf[3] = htonl(dma_high); /* dummy addr MSW */ + buf[4] = htonl(dma_low); /* dummy addr LSW */ + buf[5] = htonl(enable); /* enable? */ + + submit = mgp->sram + 0xfc01c0; + + myri10ge_pio_copy(submit, &buf, sizeof(buf)); + for (i = 0; mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 20; i++) + msleep(1); + if (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA) + dev_err(&mgp->pdev->dev, "dummy rdma %s failed\n", + (enable ? "enable" : "disable")); +} + +static int +myri10ge_validate_firmware(struct myri10ge_priv *mgp, + struct mcp_gen_header *hdr) +{ + struct device *dev = &mgp->pdev->dev; + int major, minor; + + /* check firmware type */ + if (ntohl(hdr->mcp_type) != MCP_TYPE_ETH) { + dev_err(dev, "Bad firmware type: 0x%x\n", ntohl(hdr->mcp_type)); + return -EINVAL; + } + + /* save firmware version for ethtool */ + strncpy(mgp->fw_version, hdr->version, sizeof(mgp->fw_version)); + + sscanf(mgp->fw_version, "%d.%d", &major, &minor); + + if (!(major == MXGEFW_VERSION_MAJOR && minor == MXGEFW_VERSION_MINOR)) { + dev_err(dev, "Found firmware version %s\n", mgp->fw_version); + dev_err(dev, "Driver needs %d.%d\n", MXGEFW_VERSION_MAJOR, + MXGEFW_VERSION_MINOR); + return -EINVAL; + } + return 0; +} + +static int myri10ge_load_hotplug_firmware(struct myri10ge_priv *mgp, u32 * size) +{ + unsigned crc, reread_crc; + const struct firmware *fw; + struct device *dev = &mgp->pdev->dev; + struct mcp_gen_header *hdr; + size_t hdr_offset; + int status; + unsigned i; + + if ((status = request_firmware(&fw, mgp->fw_name, dev)) < 0) { + dev_err(dev, "Unable to load %s firmware image via hotplug\n", + mgp->fw_name); + status = -EINVAL; + goto abort_with_nothing; + } + + /* check size */ + + if (fw->size >= mgp->sram_size - MYRI10GE_FW_OFFSET || + fw->size < MCP_HEADER_PTR_OFFSET + 4) { + dev_err(dev, "Firmware size invalid:%d\n", (int)fw->size); + status = -EINVAL; + goto abort_with_fw; + } + + /* check id */ + hdr_offset = ntohl(*(u32 *) (fw->data + MCP_HEADER_PTR_OFFSET)); + if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > fw->size) { + dev_err(dev, "Bad firmware file\n"); + status = -EINVAL; + goto abort_with_fw; + } + hdr = (void *)(fw->data + hdr_offset); + + status = myri10ge_validate_firmware(mgp, hdr); + if (status != 0) + goto abort_with_fw; + + crc = crc32(~0, fw->data, fw->size); + for (i = 0; i < fw->size; i += 256) { + myri10ge_pio_copy(mgp->sram + MYRI10GE_FW_OFFSET + i, + fw->data + i, + min(256U, (unsigned)(fw->size - i))); + mb(); + readb(mgp->sram); + } + /* corruption checking is good for parity recovery and buggy chipset */ + memcpy_fromio(fw->data, mgp->sram + MYRI10GE_FW_OFFSET, fw->size); + reread_crc = crc32(~0, fw->data, fw->size); + if (crc != reread_crc) { + dev_err(dev, "CRC failed(fw-len=%u), got 0x%x (expect 0x%x)\n", + (unsigned)fw->size, reread_crc, crc); + status = -EIO; + goto abort_with_fw; + } + *size = (u32) fw->size; + +abort_with_fw: + release_firmware(fw); + +abort_with_nothing: + return status; +} + +static int myri10ge_adopt_running_firmware(struct myri10ge_priv *mgp) +{ + struct mcp_gen_header *hdr; + struct device *dev = &mgp->pdev->dev; + const size_t bytes = sizeof(struct mcp_gen_header); + size_t hdr_offset; + int status; + + /* find running firmware header */ + hdr_offset = ntohl(__raw_readl(mgp->sram + MCP_HEADER_PTR_OFFSET)); + + if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > mgp->sram_size) { + dev_err(dev, "Running firmware has bad header offset (%d)\n", + (int)hdr_offset); + return -EIO; + } + + /* copy header of running firmware from SRAM to host memory to + * validate firmware */ + hdr = kmalloc(bytes, GFP_KERNEL); + if (hdr == NULL) { + dev_err(dev, "could not malloc firmware hdr\n"); + return -ENOMEM; + } + memcpy_fromio(hdr, mgp->sram + hdr_offset, bytes); + status = myri10ge_validate_firmware(mgp, hdr); + kfree(hdr); + return status; +} + +static int myri10ge_load_firmware(struct myri10ge_priv *mgp) +{ + char __iomem *submit; + u32 buf[16]; + u32 dma_low, dma_high, size; + int status, i; + + size = 0; + status = myri10ge_load_hotplug_firmware(mgp, &size); + if (status) { + dev_warn(&mgp->pdev->dev, "hotplug firmware loading failed\n"); + + /* Do not attempt to adopt firmware if there + * was a bad crc */ + if (status == -EIO) + return status; + + status = myri10ge_adopt_running_firmware(mgp); + if (status != 0) { + dev_err(&mgp->pdev->dev, + "failed to adopt running firmware\n"); + return status; + } + dev_info(&mgp->pdev->dev, + "Successfully adopted running firmware\n"); + if (mgp->tx.boundary == 4096) { + dev_warn(&mgp->pdev->dev, + "Using firmware currently running on NIC" + ". For optimal\n"); + dev_warn(&mgp->pdev->dev, + "performance consider loading optimized " + "firmware\n"); + dev_warn(&mgp->pdev->dev, "via hotplug\n"); + } + + mgp->fw_name = "adopted"; + mgp->tx.boundary = 2048; + return status; + } + + /* clear confirmation addr */ + mgp->cmd->data = 0; + mb(); + + /* send a reload command to the bootstrap MCP, and wait for the + * response in the confirmation address. The firmware should + * write a -1 there to indicate it is alive and well + */ + dma_low = MYRI10GE_LOWPART_TO_U32(mgp->cmd_bus); + dma_high = MYRI10GE_HIGHPART_TO_U32(mgp->cmd_bus); + + buf[0] = htonl(dma_high); /* confirm addr MSW */ + buf[1] = htonl(dma_low); /* confirm addr LSW */ + buf[2] = htonl(MYRI10GE_NO_CONFIRM_DATA); /* confirm data */ + + /* FIX: All newest firmware should un-protect the bottom of + * the sram before handoff. However, the very first interfaces + * do not. Therefore the handoff copy must skip the first 8 bytes + */ + buf[3] = htonl(MYRI10GE_FW_OFFSET + 8); /* where the code starts */ + buf[4] = htonl(size - 8); /* length of code */ + buf[5] = htonl(8); /* where to copy to */ + buf[6] = htonl(0); /* where to jump to */ + + submit = mgp->sram + 0xfc0000; + + myri10ge_pio_copy(submit, &buf, sizeof(buf)); + mb(); + msleep(1); + mb(); + i = 0; + while (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 20) { + msleep(1); + i++; + } + if (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA) { + dev_err(&mgp->pdev->dev, "handoff failed\n"); + return -ENXIO; + } + dev_info(&mgp->pdev->dev, "handoff confirmed\n"); + myri10ge_dummy_rdma(mgp, 1); + + return 0; +} + +static int myri10ge_update_mac_address(struct myri10ge_priv *mgp, u8 * addr) +{ + struct myri10ge_cmd cmd; + int status; + + cmd.data0 = ((addr[0] << 24) | (addr[1] << 16) + | (addr[2] << 8) | addr[3]); + + cmd.data1 = ((addr[4] << 8) | (addr[5])); + + status = myri10ge_send_cmd(mgp, MXGEFW_SET_MAC_ADDRESS, &cmd, 0); + return status; +} + +static int myri10ge_change_pause(struct myri10ge_priv *mgp, int pause) +{ + struct myri10ge_cmd cmd; + int status, ctl; + + ctl = pause ? MXGEFW_ENABLE_FLOW_CONTROL : MXGEFW_DISABLE_FLOW_CONTROL; + status = myri10ge_send_cmd(mgp, ctl, &cmd, 0); + + if (status) { + printk(KERN_ERR + "myri10ge: %s: Failed to set flow control mode\n", + mgp->dev->name); + return status; + } + mgp->pause = pause; + return 0; +} + +static void +myri10ge_change_promisc(struct myri10ge_priv *mgp, int promisc, int atomic) +{ + struct myri10ge_cmd cmd; + int status, ctl; + + ctl = promisc ? MXGEFW_ENABLE_PROMISC : MXGEFW_DISABLE_PROMISC; + status = myri10ge_send_cmd(mgp, ctl, &cmd, atomic); + if (status) + printk(KERN_ERR "myri10ge: %s: Failed to set promisc mode\n", + mgp->dev->name); +} + +static int myri10ge_reset(struct myri10ge_priv *mgp) +{ + struct myri10ge_cmd cmd; + int status; + size_t bytes; + u32 len; + + /* try to send a reset command to the card to see if it + * is alive */ + memset(&cmd, 0, sizeof(cmd)); + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_RESET, &cmd, 0); + if (status != 0) { + dev_err(&mgp->pdev->dev, "failed reset\n"); + return -ENXIO; + } + + /* Now exchange information about interrupts */ + + bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry); + memset(mgp->rx_done.entry, 0, bytes); + cmd.data0 = (u32) bytes; + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_SIZE, &cmd, 0); + cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus); + status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_DMA, &cmd, 0); + + status |= + myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0); + mgp->irq_claim = (__iomem u32 *) (mgp->sram + cmd.data0); + if (!mgp->msi_enabled) { + status |= myri10ge_send_cmd + (mgp, MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, &cmd, 0); + mgp->irq_deassert = (__iomem u32 *) (mgp->sram + cmd.data0); + + } + status |= myri10ge_send_cmd + (mgp, MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, &cmd, 0); + mgp->intr_coal_delay_ptr = (__iomem u32 *) (mgp->sram + cmd.data0); + if (status != 0) { + dev_err(&mgp->pdev->dev, "failed set interrupt parameters\n"); + return status; + } + __raw_writel(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr); + + /* Run a small DMA test. + * The magic multipliers to the length tell the firmware + * to do DMA read, write, or read+write tests. The + * results are returned in cmd.data0. The upper 16 + * bits or the return is the number of transfers completed. + * The lower 16 bits is the time in 0.5us ticks that the + * transfers took to complete. + */ + + len = mgp->tx.boundary; + + cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus); + cmd.data2 = len * 0x10000; + status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0); + if (status == 0) + mgp->read_dma = ((cmd.data0 >> 16) * len * 2) / + (cmd.data0 & 0xffff); + else + dev_warn(&mgp->pdev->dev, "DMA read benchmark failed: %d\n", + status); + cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus); + cmd.data2 = len * 0x1; + status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0); + if (status == 0) + mgp->write_dma = ((cmd.data0 >> 16) * len * 2) / + (cmd.data0 & 0xffff); + else + dev_warn(&mgp->pdev->dev, "DMA write benchmark failed: %d\n", + status); + + cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus); + cmd.data2 = len * 0x10001; + status = myri10ge_send_cmd(mgp, MXGEFW_DMA_TEST, &cmd, 0); + if (status == 0) + mgp->read_write_dma = ((cmd.data0 >> 16) * len * 2 * 2) / + (cmd.data0 & 0xffff); + else + dev_warn(&mgp->pdev->dev, + "DMA read/write benchmark failed: %d\n", status); + + memset(mgp->rx_done.entry, 0, bytes); + + /* reset mcp/driver shared state back to 0 */ + mgp->tx.req = 0; + mgp->tx.done = 0; + mgp->tx.pkt_start = 0; + mgp->tx.pkt_done = 0; + mgp->rx_big.cnt = 0; + mgp->rx_small.cnt = 0; + mgp->rx_done.idx = 0; + mgp->rx_done.cnt = 0; + status = myri10ge_update_mac_address(mgp, mgp->dev->dev_addr); + myri10ge_change_promisc(mgp, 0, 0); + myri10ge_change_pause(mgp, mgp->pause); + return status; +} + +static inline void +myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst, + struct mcp_kreq_ether_recv *src) +{ + u32 low; + + low = src->addr_low; + src->addr_low = DMA_32BIT_MASK; + myri10ge_pio_copy(dst, src, 8 * sizeof(*src)); + mb(); + src->addr_low = low; + __raw_writel(low, &dst->addr_low); + mb(); +} + +/* + * Set of routines to get a new receive buffer. Any buffer which + * crosses a 4KB boundary must start on a 4KB boundary due to PCIe + * wdma restrictions. We also try to align any smaller allocation to + * at least a 16 byte boundary for efficiency. We assume the linux + * memory allocator works by powers of 2, and will not return memory + * smaller than 2KB which crosses a 4KB boundary. If it does, we fall + * back to allocating 2x as much space as required. + * + * We intend to replace large (>4KB) skb allocations by using + * pages directly and building a fraglist in the near future. + */ + +static inline struct sk_buff *myri10ge_alloc_big(int bytes) +{ + struct sk_buff *skb; + unsigned long data, roundup; + + skb = dev_alloc_skb(bytes + 4096 + MXGEFW_PAD); + if (skb == NULL) + return NULL; + + /* Correct skb->truesize so that socket buffer + * accounting is not confused the rounding we must + * do to satisfy alignment constraints. + */ + skb->truesize -= 4096; + + data = (unsigned long)(skb->data); + roundup = (-data) & (4095); + skb_reserve(skb, roundup); + return skb; +} + +/* Allocate 2x as much space as required and use whichever portion + * does not cross a 4KB boundary */ +static inline struct sk_buff *myri10ge_alloc_small_safe(unsigned int bytes) +{ + struct sk_buff *skb; + unsigned long data, boundary; + + skb = dev_alloc_skb(2 * (bytes + MXGEFW_PAD) - 1); + if (unlikely(skb == NULL)) + return NULL; + + /* Correct skb->truesize so that socket buffer + * accounting is not confused the rounding we must + * do to satisfy alignment constraints. + */ + skb->truesize -= bytes + MXGEFW_PAD; + + data = (unsigned long)(skb->data); + boundary = (data + 4095UL) & ~4095UL; + if ((boundary - data) >= (bytes + MXGEFW_PAD)) + return skb; + + skb_reserve(skb, boundary - data); + return skb; +} + +/* Allocate just enough space, and verify that the allocated + * space does not cross a 4KB boundary */ +static inline struct sk_buff *myri10ge_alloc_small(int bytes) +{ + struct sk_buff *skb; + unsigned long roundup, data, end; + + skb = dev_alloc_skb(bytes + 16 + MXGEFW_PAD); + if (unlikely(skb == NULL)) + return NULL; + + /* Round allocated buffer to 16 byte boundary */ + data = (unsigned long)(skb->data); + roundup = (-data) & 15UL; + skb_reserve(skb, roundup); + /* Verify that the data buffer does not cross a page boundary */ + data = (unsigned long)(skb->data); + end = data + bytes + MXGEFW_PAD - 1; + if (unlikely(((end >> 12) != (data >> 12)) && (data & 4095UL))) { + printk(KERN_NOTICE + "myri10ge_alloc_small: small skb crossed 4KB boundary\n"); + myri10ge_skb_cross_4k = 1; + dev_kfree_skb_any(skb); + skb = myri10ge_alloc_small_safe(bytes); + } + return skb; +} + +static inline int +myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct pci_dev *pdev, int bytes, + int idx) +{ + struct sk_buff *skb; + dma_addr_t bus; + int len, retval = 0; + + bytes += VLAN_HLEN; /* account for 802.1q vlan tag */ + + if ((bytes + MXGEFW_PAD) > (4096 - 16) /* linux overhead */ ) + skb = myri10ge_alloc_big(bytes); + else if (myri10ge_skb_cross_4k) + skb = myri10ge_alloc_small_safe(bytes); + else + skb = myri10ge_alloc_small(bytes); + + if (unlikely(skb == NULL)) { + rx->alloc_fail++; + retval = -ENOBUFS; + goto done; + } + + /* set len so that it only covers the area we + * need mapped for DMA */ + len = bytes + MXGEFW_PAD; + + bus = pci_map_single(pdev, skb->data, len, PCI_DMA_FROMDEVICE); + rx->info[idx].skb = skb; + pci_unmap_addr_set(&rx->info[idx], bus, bus); + pci_unmap_len_set(&rx->info[idx], len, len); + rx->shadow[idx].addr_low = htonl(MYRI10GE_LOWPART_TO_U32(bus)); + rx->shadow[idx].addr_high = htonl(MYRI10GE_HIGHPART_TO_U32(bus)); + +done: + /* copy 8 descriptors (64-bytes) to the mcp at a time */ + if ((idx & 7) == 7) { + if (rx->wc_fifo == NULL) + myri10ge_submit_8rx(&rx->lanai[idx - 7], + &rx->shadow[idx - 7]); + else { + mb(); + myri10ge_pio_copy(rx->wc_fifo, + &rx->shadow[idx - 7], 64); + } + } + return retval; +} + +static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, u16 hw_csum) +{ + struct vlan_hdr *vh = (struct vlan_hdr *)(skb->data); + + if ((skb->protocol == ntohs(ETH_P_8021Q)) && + (vh->h_vlan_encapsulated_proto == htons(ETH_P_IP) || + vh->h_vlan_encapsulated_proto == htons(ETH_P_IPV6))) { + skb->csum = hw_csum; + skb->ip_summed = CHECKSUM_HW; + } +} + +static inline unsigned long +myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, + int bytes, int len, int csum) +{ + dma_addr_t bus; + struct sk_buff *skb; + int idx, unmap_len; + + idx = rx->cnt & rx->mask; + rx->cnt++; + + /* save a pointer to the received skb */ + skb = rx->info[idx].skb; + bus = pci_unmap_addr(&rx->info[idx], bus); + unmap_len = pci_unmap_len(&rx->info[idx], len); + + /* try to replace the received skb */ + if (myri10ge_getbuf(rx, mgp->pdev, bytes, idx)) { + /* drop the frame -- the old skbuf is re-cycled */ + mgp->stats.rx_dropped += 1; + return 0; + } + + /* unmap the recvd skb */ + pci_unmap_single(mgp->pdev, bus, unmap_len, PCI_DMA_FROMDEVICE); + + /* mcp implicitly skips 1st bytes so that packet is properly + * aligned */ + skb_reserve(skb, MXGEFW_PAD); + + /* set the length of the frame */ + skb_put(skb, len); + + skb->protocol = eth_type_trans(skb, mgp->dev); + skb->dev = mgp->dev; + if (mgp->csum_flag) { + if ((skb->protocol == ntohs(ETH_P_IP)) || + (skb->protocol == ntohs(ETH_P_IPV6))) { + skb->csum = ntohs((u16) csum); + skb->ip_summed = CHECKSUM_HW; + } else + myri10ge_vlan_ip_csum(skb, ntohs((u16) csum)); + } + + netif_receive_skb(skb); + mgp->dev->last_rx = jiffies; + return 1; +} + +static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index) +{ + struct pci_dev *pdev = mgp->pdev; + struct myri10ge_tx_buf *tx = &mgp->tx; + struct sk_buff *skb; + int idx, len; + int limit = 0; + + while (tx->pkt_done != mcp_index) { + idx = tx->done & tx->mask; + skb = tx->info[idx].skb; + + /* Mark as free */ + tx->info[idx].skb = NULL; + if (tx->info[idx].last) { + tx->pkt_done++; + tx->info[idx].last = 0; + } + tx->done++; + len = pci_unmap_len(&tx->info[idx], len); + pci_unmap_len_set(&tx->info[idx], len, 0); + if (skb) { + mgp->stats.tx_bytes += skb->len; + mgp->stats.tx_packets++; + dev_kfree_skb_irq(skb); + if (len) + pci_unmap_single(pdev, + pci_unmap_addr(&tx->info[idx], + bus), len, + PCI_DMA_TODEVICE); + } else { + if (len) + pci_unmap_page(pdev, + pci_unmap_addr(&tx->info[idx], + bus), len, + PCI_DMA_TODEVICE); + } + + /* limit potential for livelock by only handling + * 2 full tx rings per call */ + if (unlikely(++limit > 2 * tx->mask)) + break; + } + /* start the queue if we've stopped it */ + if (netif_queue_stopped(mgp->dev) + && tx->req - tx->done < (tx->mask >> 1)) { + mgp->wake_queue++; + netif_wake_queue(mgp->dev); + } +} + +static inline void myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int *limit) +{ + struct myri10ge_rx_done *rx_done = &mgp->rx_done; + unsigned long rx_bytes = 0; + unsigned long rx_packets = 0; + unsigned long rx_ok; + + int idx = rx_done->idx; + int cnt = rx_done->cnt; + u16 length; + u16 checksum; + + while (rx_done->entry[idx].length != 0 && *limit != 0) { + length = ntohs(rx_done->entry[idx].length); + rx_done->entry[idx].length = 0; + checksum = ntohs(rx_done->entry[idx].checksum); + if (length <= mgp->small_bytes) + rx_ok = myri10ge_rx_done(mgp, &mgp->rx_small, + mgp->small_bytes, + length, checksum); + else + rx_ok = myri10ge_rx_done(mgp, &mgp->rx_big, + mgp->dev->mtu + ETH_HLEN, + length, checksum); + rx_packets += rx_ok; + rx_bytes += rx_ok * (unsigned long)length; + cnt++; + idx = cnt & (myri10ge_max_intr_slots - 1); + + /* limit potential for livelock by only handling a + * limited number of frames. */ + (*limit)--; + } + rx_done->idx = idx; + rx_done->cnt = cnt; + mgp->stats.rx_packets += rx_packets; + mgp->stats.rx_bytes += rx_bytes; +} + +static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) +{ + struct mcp_irq_data *stats = mgp->fw_stats; + + if (unlikely(stats->stats_updated)) { + if (mgp->link_state != stats->link_up) { + mgp->link_state = stats->link_up; + if (mgp->link_state) { + printk(KERN_INFO "myri10ge: %s: link up\n", + mgp->dev->name); + netif_carrier_on(mgp->dev); + } else { + printk(KERN_INFO "myri10ge: %s: link down\n", + mgp->dev->name); + netif_carrier_off(mgp->dev); + } + } + if (mgp->rdma_tags_available != + ntohl(mgp->fw_stats->rdma_tags_available)) { + mgp->rdma_tags_available = + ntohl(mgp->fw_stats->rdma_tags_available); + printk(KERN_WARNING "myri10ge: %s: RDMA timed out! " + "%d tags left\n", mgp->dev->name, + mgp->rdma_tags_available); + } + mgp->down_cnt += stats->link_down; + if (stats->link_down) + wake_up(&mgp->down_wq); + } +} + +static int myri10ge_poll(struct net_device *netdev, int *budget) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + struct myri10ge_rx_done *rx_done = &mgp->rx_done; + int limit, orig_limit, work_done; + + /* process as many rx events as NAPI will allow */ + limit = min(*budget, netdev->quota); + orig_limit = limit; + myri10ge_clean_rx_done(mgp, &limit); + work_done = orig_limit - limit; + *budget -= work_done; + netdev->quota -= work_done; + + if (rx_done->entry[rx_done->idx].length == 0 || !netif_running(netdev)) { + netif_rx_complete(netdev); + __raw_writel(htonl(3), mgp->irq_claim); + return 0; + } + return 1; +} + +static irqreturn_t myri10ge_intr(int irq, void *arg, struct pt_regs *regs) +{ + struct myri10ge_priv *mgp = arg; + struct mcp_irq_data *stats = mgp->fw_stats; + struct myri10ge_tx_buf *tx = &mgp->tx; + u32 send_done_count; + int i; + + /* make sure it is our IRQ, and that the DMA has finished */ + if (unlikely(!stats->valid)) + return (IRQ_NONE); + + /* low bit indicates receives are present, so schedule + * napi poll handler */ + if (stats->valid & 1) + netif_rx_schedule(mgp->dev); + + if (!mgp->msi_enabled) { + __raw_writel(0, mgp->irq_deassert); + if (!myri10ge_deassert_wait) + stats->valid = 0; + mb(); + } else + stats->valid = 0; + + /* Wait for IRQ line to go low, if using INTx */ + i = 0; + while (1) { + i++; + /* check for transmit completes and receives */ + send_done_count = ntohl(stats->send_done_count); + if (send_done_count != tx->pkt_done) + myri10ge_tx_done(mgp, (int)send_done_count); + if (unlikely(i > myri10ge_max_irq_loops)) { + printk(KERN_WARNING "myri10ge: %s: irq stuck?\n", + mgp->dev->name); + stats->valid = 0; + schedule_work(&mgp->watchdog_work); + } + if (likely(stats->valid == 0)) + break; + cpu_relax(); + barrier(); + } + + myri10ge_check_statblock(mgp); + + __raw_writel(htonl(3), mgp->irq_claim + 1); + return (IRQ_HANDLED); +} + +static int +myri10ge_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) +{ + cmd->autoneg = AUTONEG_DISABLE; + cmd->speed = SPEED_10000; + cmd->duplex = DUPLEX_FULL; + return 0; +} + +static void +myri10ge_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + + strlcpy(info->driver, "myri10ge", sizeof(info->driver)); + strlcpy(info->version, MYRI10GE_VERSION_STR, sizeof(info->version)); + strlcpy(info->fw_version, mgp->fw_version, sizeof(info->fw_version)); + strlcpy(info->bus_info, pci_name(mgp->pdev), sizeof(info->bus_info)); +} + +static int +myri10ge_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + coal->rx_coalesce_usecs = mgp->intr_coal_delay; + return 0; +} + +static int +myri10ge_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + + mgp->intr_coal_delay = coal->rx_coalesce_usecs; + __raw_writel(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr); + return 0; +} + +static void +myri10ge_get_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + + pause->autoneg = 0; + pause->rx_pause = mgp->pause; + pause->tx_pause = mgp->pause; +} + +static int +myri10ge_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + + if (pause->tx_pause != mgp->pause) + return myri10ge_change_pause(mgp, pause->tx_pause); + if (pause->rx_pause != mgp->pause) + return myri10ge_change_pause(mgp, pause->tx_pause); + if (pause->autoneg != 0) + return -EINVAL; + return 0; +} + +static void +myri10ge_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + + ring->rx_mini_max_pending = mgp->rx_small.mask + 1; + ring->rx_max_pending = mgp->rx_big.mask + 1; + ring->rx_jumbo_max_pending = 0; + ring->tx_max_pending = mgp->rx_small.mask + 1; + ring->rx_mini_pending = ring->rx_mini_max_pending; + ring->rx_pending = ring->rx_max_pending; + ring->rx_jumbo_pending = ring->rx_jumbo_max_pending; + ring->tx_pending = ring->tx_max_pending; +} + +static u32 myri10ge_get_rx_csum(struct net_device *netdev) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + if (mgp->csum_flag) + return 1; + else + return 0; +} + +static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + if (csum_enabled) + mgp->csum_flag = MXGEFW_FLAGS_CKSUM; + else + mgp->csum_flag = 0; + return 0; +} + +static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = { + "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", + "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", + "rx_length_errors", "rx_over_errors", "rx_crc_errors", + "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors", + "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors", + "tx_heartbeat_errors", "tx_window_errors", + /* device-specific stats */ + "tx_boundary", "WC", "irq", "MSI", + "read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs", + "serial_number", "tx_pkt_start", "tx_pkt_done", + "tx_req", "tx_done", "rx_small_cnt", "rx_big_cnt", + "wake_queue", "stop_queue", "watchdog_resets", "tx_linearized", + "link_up", "dropped_link_overflow", "dropped_link_error_or_filtered", + "dropped_runt", "dropped_overrun", "dropped_no_small_buffer", + "dropped_no_big_buffer" +}; + +#define MYRI10GE_NET_STATS_LEN 21 +#define MYRI10GE_STATS_LEN sizeof(myri10ge_gstrings_stats) / ETH_GSTRING_LEN + +static void +myri10ge_get_strings(struct net_device *netdev, u32 stringset, u8 * data) +{ + switch (stringset) { + case ETH_SS_STATS: + memcpy(data, *myri10ge_gstrings_stats, + sizeof(myri10ge_gstrings_stats)); + break; + } +} + +static int myri10ge_get_stats_count(struct net_device *netdev) +{ + return MYRI10GE_STATS_LEN; +} + +static void +myri10ge_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, u64 * data) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + int i; + + for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++) + data[i] = ((unsigned long *)&mgp->stats)[i]; + + data[i++] = (unsigned int)mgp->tx.boundary; + data[i++] = (unsigned int)(mgp->mtrr >= 0); + data[i++] = (unsigned int)mgp->pdev->irq; + data[i++] = (unsigned int)mgp->msi_enabled; + data[i++] = (unsigned int)mgp->read_dma; + data[i++] = (unsigned int)mgp->write_dma; + data[i++] = (unsigned int)mgp->read_write_dma; + data[i++] = (unsigned int)mgp->serial_number; + data[i++] = (unsigned int)mgp->tx.pkt_start; + data[i++] = (unsigned int)mgp->tx.pkt_done; + data[i++] = (unsigned int)mgp->tx.req; + data[i++] = (unsigned int)mgp->tx.done; + data[i++] = (unsigned int)mgp->rx_small.cnt; + data[i++] = (unsigned int)mgp->rx_big.cnt; + data[i++] = (unsigned int)mgp->wake_queue; + data[i++] = (unsigned int)mgp->stop_queue; + data[i++] = (unsigned int)mgp->watchdog_resets; + data[i++] = (unsigned int)mgp->tx_linearized; + data[i++] = (unsigned int)ntohl(mgp->fw_stats->link_up); + data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_link_overflow); + data[i++] = + (unsigned int)ntohl(mgp->fw_stats->dropped_link_error_or_filtered); + data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_runt); + data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_overrun); + data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_small_buffer); + data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_big_buffer); +} + +static struct ethtool_ops myri10ge_ethtool_ops = { + .get_settings = myri10ge_get_settings, + .get_drvinfo = myri10ge_get_drvinfo, + .get_coalesce = myri10ge_get_coalesce, + .set_coalesce = myri10ge_set_coalesce, + .get_pauseparam = myri10ge_get_pauseparam, + .set_pauseparam = myri10ge_set_pauseparam, + .get_ringparam = myri10ge_get_ringparam, + .get_rx_csum = myri10ge_get_rx_csum, + .set_rx_csum = myri10ge_set_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_hw_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, +#ifdef NETIF_F_TSO + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, +#endif + .get_strings = myri10ge_get_strings, + .get_stats_count = myri10ge_get_stats_count, + .get_ethtool_stats = myri10ge_get_ethtool_stats +}; + +static int myri10ge_allocate_rings(struct net_device *dev) +{ + struct myri10ge_priv *mgp; + struct myri10ge_cmd cmd; + int tx_ring_size, rx_ring_size; + int tx_ring_entries, rx_ring_entries; + int i, status; + size_t bytes; + + mgp = netdev_priv(dev); + + /* get ring sizes */ + + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_RING_SIZE, &cmd, 0); + tx_ring_size = cmd.data0; + status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd, 0); + rx_ring_size = cmd.data0; + + tx_ring_entries = tx_ring_size / sizeof(struct mcp_kreq_ether_send); + rx_ring_entries = rx_ring_size / sizeof(struct mcp_dma_addr); + mgp->tx.mask = tx_ring_entries - 1; + mgp->rx_small.mask = mgp->rx_big.mask = rx_ring_entries - 1; + + /* allocate the host shadow rings */ + + bytes = 8 + (MYRI10GE_MAX_SEND_DESC_TSO + 4) + * sizeof(*mgp->tx.req_list); + mgp->tx.req_bytes = kzalloc(bytes, GFP_KERNEL); + if (mgp->tx.req_bytes == NULL) + goto abort_with_nothing; + + /* ensure req_list entries are aligned to 8 bytes */ + mgp->tx.req_list = (struct mcp_kreq_ether_send *) + ALIGN((unsigned long)mgp->tx.req_bytes, 8); + + bytes = rx_ring_entries * sizeof(*mgp->rx_small.shadow); + mgp->rx_small.shadow = kzalloc(bytes, GFP_KERNEL); + if (mgp->rx_small.shadow == NULL) + goto abort_with_tx_req_bytes; + + bytes = rx_ring_entries * sizeof(*mgp->rx_big.shadow); + mgp->rx_big.shadow = kzalloc(bytes, GFP_KERNEL); + if (mgp->rx_big.shadow == NULL) + goto abort_with_rx_small_shadow; + + /* allocate the host info rings */ + + bytes = tx_ring_entries * sizeof(*mgp->tx.info); + mgp->tx.info = kzalloc(bytes, GFP_KERNEL); + if (mgp->tx.info == NULL) + goto abort_with_rx_big_shadow; + + bytes = rx_ring_entries * sizeof(*mgp->rx_small.info); + mgp->rx_small.info = kzalloc(bytes, GFP_KERNEL); + if (mgp->rx_small.info == NULL) + goto abort_with_tx_info; + + bytes = rx_ring_entries * sizeof(*mgp->rx_big.info); + mgp->rx_big.info = kzalloc(bytes, GFP_KERNEL); + if (mgp->rx_big.info == NULL) + goto abort_with_rx_small_info; + + /* Fill the receive rings */ + + for (i = 0; i <= mgp->rx_small.mask; i++) { + status = myri10ge_getbuf(&mgp->rx_small, mgp->pdev, + mgp->small_bytes, i); + if (status) { + printk(KERN_ERR + "myri10ge: %s: alloced only %d small bufs\n", + dev->name, i); + goto abort_with_rx_small_ring; + } + } + + for (i = 0; i <= mgp->rx_big.mask; i++) { + status = + myri10ge_getbuf(&mgp->rx_big, mgp->pdev, + dev->mtu + ETH_HLEN, i); + if (status) { + printk(KERN_ERR + "myri10ge: %s: alloced only %d big bufs\n", + dev->name, i); + goto abort_with_rx_big_ring; + } + } + + return 0; + +abort_with_rx_big_ring: + for (i = 0; i <= mgp->rx_big.mask; i++) { + if (mgp->rx_big.info[i].skb != NULL) + dev_kfree_skb_any(mgp->rx_big.info[i].skb); + if (pci_unmap_len(&mgp->rx_big.info[i], len)) + pci_unmap_single(mgp->pdev, + pci_unmap_addr(&mgp->rx_big.info[i], + bus), + pci_unmap_len(&mgp->rx_big.info[i], + len), + PCI_DMA_FROMDEVICE); + } + +abort_with_rx_small_ring: + for (i = 0; i <= mgp->rx_small.mask; i++) { + if (mgp->rx_small.info[i].skb != NULL) + dev_kfree_skb_any(mgp->rx_small.info[i].skb); + if (pci_unmap_len(&mgp->rx_small.info[i], len)) + pci_unmap_single(mgp->pdev, + pci_unmap_addr(&mgp->rx_small.info[i], + bus), + pci_unmap_len(&mgp->rx_small.info[i], + len), + PCI_DMA_FROMDEVICE); + } + kfree(mgp->rx_big.info); + +abort_with_rx_small_info: + kfree(mgp->rx_small.info); + +abort_with_tx_info: + kfree(mgp->tx.info); + +abort_with_rx_big_shadow: + kfree(mgp->rx_big.shadow); + +abort_with_rx_small_shadow: + kfree(mgp->rx_small.shadow); + +abort_with_tx_req_bytes: + kfree(mgp->tx.req_bytes); + mgp->tx.req_bytes = NULL; + mgp->tx.req_list = NULL; + +abort_with_nothing: + return status; +} + +static void myri10ge_free_rings(struct net_device *dev) +{ + struct myri10ge_priv *mgp; + struct sk_buff *skb; + struct myri10ge_tx_buf *tx; + int i, len, idx; + + mgp = netdev_priv(dev); + + for (i = 0; i <= mgp->rx_big.mask; i++) { + if (mgp->rx_big.info[i].skb != NULL) + dev_kfree_skb_any(mgp->rx_big.info[i].skb); + if (pci_unmap_len(&mgp->rx_big.info[i], len)) + pci_unmap_single(mgp->pdev, + pci_unmap_addr(&mgp->rx_big.info[i], + bus), + pci_unmap_len(&mgp->rx_big.info[i], + len), + PCI_DMA_FROMDEVICE); + } + + for (i = 0; i <= mgp->rx_small.mask; i++) { + if (mgp->rx_small.info[i].skb != NULL) + dev_kfree_skb_any(mgp->rx_small.info[i].skb); + if (pci_unmap_len(&mgp->rx_small.info[i], len)) + pci_unmap_single(mgp->pdev, + pci_unmap_addr(&mgp->rx_small.info[i], + bus), + pci_unmap_len(&mgp->rx_small.info[i], + len), + PCI_DMA_FROMDEVICE); + } + + tx = &mgp->tx; + while (tx->done != tx->req) { + idx = tx->done & tx->mask; + skb = tx->info[idx].skb; + + /* Mark as free */ + tx->info[idx].skb = NULL; + tx->done++; + len = pci_unmap_len(&tx->info[idx], len); + pci_unmap_len_set(&tx->info[idx], len, 0); + if (skb) { + mgp->stats.tx_dropped++; + dev_kfree_skb_any(skb); + if (len) + pci_unmap_single(mgp->pdev, + pci_unmap_addr(&tx->info[idx], + bus), len, + PCI_DMA_TODEVICE); + } else { + if (len) + pci_unmap_page(mgp->pdev, + pci_unmap_addr(&tx->info[idx], + bus), len, + PCI_DMA_TODEVICE); + } + } + kfree(mgp->rx_big.info); + + kfree(mgp->rx_small.info); + + kfree(mgp->tx.info); + + kfree(mgp->rx_big.shadow); + + kfree(mgp->rx_small.shadow); + + kfree(mgp->tx.req_bytes); + mgp->tx.req_bytes = NULL; + mgp->tx.req_list = NULL; +} + +static int myri10ge_open(struct net_device *dev) +{ + struct myri10ge_priv *mgp; + struct myri10ge_cmd cmd; + int status, big_pow2; + + mgp = netdev_priv(dev); + + if (mgp->running != MYRI10GE_ETH_STOPPED) + return -EBUSY; + + mgp->running = MYRI10GE_ETH_STARTING; + status = myri10ge_reset(mgp); + if (status != 0) { + printk(KERN_ERR "myri10ge: %s: failed reset\n", dev->name); + mgp->running = MYRI10GE_ETH_STOPPED; + return -ENXIO; + } + + /* decide what small buffer size to use. For good TCP rx + * performance, it is important to not receive 1514 byte + * frames into jumbo buffers, as it confuses the socket buffer + * accounting code, leading to drops and erratic performance. + */ + + if (dev->mtu <= ETH_DATA_LEN) + mgp->small_bytes = 128; /* enough for a TCP header */ + else + mgp->small_bytes = ETH_FRAME_LEN; /* enough for an ETH_DATA_LEN frame */ + + /* Override the small buffer size? */ + if (myri10ge_small_bytes > 0) + mgp->small_bytes = myri10ge_small_bytes; + + /* If the user sets an obscenely small MTU, adjust the small + * bytes down to nearly nothing */ + if (mgp->small_bytes >= (dev->mtu + ETH_HLEN)) + mgp->small_bytes = 64; + + /* get the lanai pointers to the send and receive rings */ + + status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0); + mgp->tx.lanai = + (struct mcp_kreq_ether_send __iomem *)(mgp->sram + cmd.data0); + + status |= + myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SMALL_RX_OFFSET, &cmd, 0); + mgp->rx_small.lanai = + (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0); + + status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_BIG_RX_OFFSET, &cmd, 0); + mgp->rx_big.lanai = + (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0); + + if (status != 0) { + printk(KERN_ERR + "myri10ge: %s: failed to get ring sizes or locations\n", + dev->name); + mgp->running = MYRI10GE_ETH_STOPPED; + return -ENXIO; + } + + if (mgp->mtrr >= 0) { + mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + 0x200000; + mgp->rx_small.wc_fifo = (u8 __iomem *) mgp->sram + 0x300000; + mgp->rx_big.wc_fifo = (u8 __iomem *) mgp->sram + 0x340000; + } else { + mgp->tx.wc_fifo = NULL; + mgp->rx_small.wc_fifo = NULL; + mgp->rx_big.wc_fifo = NULL; + } + + status = myri10ge_allocate_rings(dev); + if (status != 0) + goto abort_with_nothing; + + /* Firmware needs the big buff size as a power of 2. Lie and + * tell him the buffer is larger, because we only use 1 + * buffer/pkt, and the mtu will prevent overruns. + */ + big_pow2 = dev->mtu + ETH_HLEN + MXGEFW_PAD; + while ((big_pow2 & (big_pow2 - 1)) != 0) + big_pow2++; + + /* now give firmware buffers sizes, and MTU */ + cmd.data0 = dev->mtu + ETH_HLEN + VLAN_HLEN; + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_MTU, &cmd, 0); + cmd.data0 = mgp->small_bytes; + status |= + myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_SMALL_BUFFER_SIZE, &cmd, 0); + cmd.data0 = big_pow2; + status |= + myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_BIG_BUFFER_SIZE, &cmd, 0); + if (status) { + printk(KERN_ERR "myri10ge: %s: Couldn't set buffer sizes\n", + dev->name); + goto abort_with_rings; + } + + cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->fw_stats_bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->fw_stats_bus); + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA, &cmd, 0); + if (status) { + printk(KERN_ERR "myri10ge: %s: Couldn't set stats DMA\n", + dev->name); + goto abort_with_rings; + } + + mgp->link_state = -1; + mgp->rdma_tags_available = 15; + + netif_poll_enable(mgp->dev); /* must happen prior to any irq */ + + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd, 0); + if (status) { + printk(KERN_ERR "myri10ge: %s: Couldn't bring up link\n", + dev->name); + goto abort_with_rings; + } + + mgp->wake_queue = 0; + mgp->stop_queue = 0; + mgp->running = MYRI10GE_ETH_RUNNING; + mgp->watchdog_timer.expires = jiffies + myri10ge_watchdog_timeout * HZ; + add_timer(&mgp->watchdog_timer); + netif_wake_queue(dev); + return 0; + +abort_with_rings: + myri10ge_free_rings(dev); + +abort_with_nothing: + mgp->running = MYRI10GE_ETH_STOPPED; + return -ENOMEM; +} + +static int myri10ge_close(struct net_device *dev) +{ + struct myri10ge_priv *mgp; + struct myri10ge_cmd cmd; + int status, old_down_cnt; + + mgp = netdev_priv(dev); + + if (mgp->running != MYRI10GE_ETH_RUNNING) + return 0; + + if (mgp->tx.req_bytes == NULL) + return 0; + + del_timer_sync(&mgp->watchdog_timer); + mgp->running = MYRI10GE_ETH_STOPPING; + netif_poll_disable(mgp->dev); + netif_carrier_off(dev); + netif_stop_queue(dev); + old_down_cnt = mgp->down_cnt; + mb(); + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0); + if (status) + printk(KERN_ERR "myri10ge: %s: Couldn't bring down link\n", + dev->name); + + wait_event_timeout(mgp->down_wq, old_down_cnt != mgp->down_cnt, HZ); + if (old_down_cnt == mgp->down_cnt) + printk(KERN_ERR "myri10ge: %s never got down irq\n", dev->name); + + netif_tx_disable(dev); + + myri10ge_free_rings(dev); + + mgp->running = MYRI10GE_ETH_STOPPED; + return 0; +} + +/* copy an array of struct mcp_kreq_ether_send's to the mcp. Copy + * backwards one at a time and handle ring wraps */ + +static inline void +myri10ge_submit_req_backwards(struct myri10ge_tx_buf *tx, + struct mcp_kreq_ether_send *src, int cnt) +{ + int idx, starting_slot; + starting_slot = tx->req; + while (cnt > 1) { + cnt--; + idx = (starting_slot + cnt) & tx->mask; + myri10ge_pio_copy(&tx->lanai[idx], &src[cnt], sizeof(*src)); + mb(); + } +} + +/* + * copy an array of struct mcp_kreq_ether_send's to the mcp. Copy + * at most 32 bytes at a time, so as to avoid involving the software + * pio handler in the nic. We re-write the first segment's flags + * to mark them valid only after writing the entire chain. + */ + +static inline void +myri10ge_submit_req(struct myri10ge_tx_buf *tx, struct mcp_kreq_ether_send *src, + int cnt) +{ + int idx, i; + struct mcp_kreq_ether_send __iomem *dstp, *dst; + struct mcp_kreq_ether_send *srcp; + u8 last_flags; + + idx = tx->req & tx->mask; + + last_flags = src->flags; + src->flags = 0; + mb(); + dst = dstp = &tx->lanai[idx]; + srcp = src; + + if ((idx + cnt) < tx->mask) { + for (i = 0; i < (cnt - 1); i += 2) { + myri10ge_pio_copy(dstp, srcp, 2 * sizeof(*src)); + mb(); /* force write every 32 bytes */ + srcp += 2; + dstp += 2; + } + } else { + /* submit all but the first request, and ensure + * that it is submitted below */ + myri10ge_submit_req_backwards(tx, src, cnt); + i = 0; + } + if (i < cnt) { + /* submit the first request */ + myri10ge_pio_copy(dstp, srcp, sizeof(*src)); + mb(); /* barrier before setting valid flag */ + } + + /* re-write the last 32-bits with the valid flags */ + src->flags = last_flags; + __raw_writel(*((u32 *) src + 3), (u32 __iomem *) dst + 3); + tx->req += cnt; + mb(); +} + +static inline void +myri10ge_submit_req_wc(struct myri10ge_tx_buf *tx, + struct mcp_kreq_ether_send *src, int cnt) +{ + tx->req += cnt; + mb(); + while (cnt >= 4) { + myri10ge_pio_copy(tx->wc_fifo, src, 64); + mb(); + src += 4; + cnt -= 4; + } + if (cnt > 0) { + /* pad it to 64 bytes. The src is 64 bytes bigger than it + * needs to be so that we don't overrun it */ + myri10ge_pio_copy(tx->wc_fifo + (cnt << 18), src, 64); + mb(); + } +} + +/* + * Transmit a packet. We need to split the packet so that a single + * segment does not cross myri10ge->tx.boundary, so this makes segment + * counting tricky. So rather than try to count segments up front, we + * just give up if there are too few segments to hold a reasonably + * fragmented packet currently available. If we run + * out of segments while preparing a packet for DMA, we just linearize + * it and try again. + */ + +static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct myri10ge_priv *mgp = netdev_priv(dev); + struct mcp_kreq_ether_send *req; + struct myri10ge_tx_buf *tx = &mgp->tx; + struct skb_frag_struct *frag; + dma_addr_t bus; + u32 low, high_swapped; + unsigned int len; + int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments; + u16 pseudo_hdr_offset, cksum_offset; + int cum_len, seglen, boundary, rdma_count; + u8 flags, odd_flag; + +again: + req = tx->req_list; + avail = tx->mask - 1 - (tx->req - tx->done); + + mss = 0; + max_segments = MXGEFW_MAX_SEND_DESC; + +#ifdef NETIF_F_TSO + if (skb->len > (dev->mtu + ETH_HLEN)) { + mss = skb_shinfo(skb)->gso_size; + if (mss != 0) + max_segments = MYRI10GE_MAX_SEND_DESC_TSO; + } +#endif /*NETIF_F_TSO */ + + if ((unlikely(avail < max_segments))) { + /* we are out of transmit resources */ + mgp->stop_queue++; + netif_stop_queue(dev); + return 1; + } + + /* Setup checksum offloading, if needed */ + cksum_offset = 0; + pseudo_hdr_offset = 0; + odd_flag = 0; + flags = (MXGEFW_FLAGS_NO_TSO | MXGEFW_FLAGS_FIRST); + if (likely(skb->ip_summed == CHECKSUM_HW)) { + cksum_offset = (skb->h.raw - skb->data); + pseudo_hdr_offset = (skb->h.raw + skb->csum) - skb->data; + /* If the headers are excessively large, then we must + * fall back to a software checksum */ + if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) { + if (skb_checksum_help(skb, 0)) + goto drop; + cksum_offset = 0; + pseudo_hdr_offset = 0; + } else { + pseudo_hdr_offset = htons(pseudo_hdr_offset); + odd_flag = MXGEFW_FLAGS_ALIGN_ODD; + flags |= MXGEFW_FLAGS_CKSUM; + } + } + + cum_len = 0; + +#ifdef NETIF_F_TSO + if (mss) { /* TSO */ + /* this removes any CKSUM flag from before */ + flags = (MXGEFW_FLAGS_TSO_HDR | MXGEFW_FLAGS_FIRST); + + /* negative cum_len signifies to the + * send loop that we are still in the + * header portion of the TSO packet. + * TSO header must be at most 134 bytes long */ + cum_len = -((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); + + /* for TSO, pseudo_hdr_offset holds mss. + * The firmware figures out where to put + * the checksum by parsing the header. */ + pseudo_hdr_offset = htons(mss); + } else +#endif /*NETIF_F_TSO */ + /* Mark small packets, and pad out tiny packets */ + if (skb->len <= MXGEFW_SEND_SMALL_SIZE) { + flags |= MXGEFW_FLAGS_SMALL; + + /* pad frames to at least ETH_ZLEN bytes */ + if (unlikely(skb->len < ETH_ZLEN)) { + if (skb_padto(skb, ETH_ZLEN)) { + /* The packet is gone, so we must + * return 0 */ + mgp->stats.tx_dropped += 1; + return 0; + } + /* adjust the len to account for the zero pad + * so that the nic can know how long it is */ + skb->len = ETH_ZLEN; + } + } + + /* map the skb for DMA */ + len = skb->len - skb->data_len; + idx = tx->req & tx->mask; + tx->info[idx].skb = skb; + bus = pci_map_single(mgp->pdev, skb->data, len, PCI_DMA_TODEVICE); + pci_unmap_addr_set(&tx->info[idx], bus, bus); + pci_unmap_len_set(&tx->info[idx], len, len); + + frag_cnt = skb_shinfo(skb)->nr_frags; + frag_idx = 0; + count = 0; + rdma_count = 0; + + /* "rdma_count" is the number of RDMAs belonging to the + * current packet BEFORE the current send request. For + * non-TSO packets, this is equal to "count". + * For TSO packets, rdma_count needs to be reset + * to 0 after a segment cut. + * + * The rdma_count field of the send request is + * the number of RDMAs of the packet starting at + * that request. For TSO send requests with one ore more cuts + * in the middle, this is the number of RDMAs starting + * after the last cut in the request. All previous + * segments before the last cut implicitly have 1 RDMA. + * + * Since the number of RDMAs is not known beforehand, + * it must be filled-in retroactively - after each + * segmentation cut or at the end of the entire packet. + */ + + while (1) { + /* Break the SKB or Fragment up into pieces which + * do not cross mgp->tx.boundary */ + low = MYRI10GE_LOWPART_TO_U32(bus); + high_swapped = htonl(MYRI10GE_HIGHPART_TO_U32(bus)); + while (len) { + u8 flags_next; + int cum_len_next; + + if (unlikely(count == max_segments)) + goto abort_linearize; + + boundary = (low + tx->boundary) & ~(tx->boundary - 1); + seglen = boundary - low; + if (seglen > len) + seglen = len; + flags_next = flags & ~MXGEFW_FLAGS_FIRST; + cum_len_next = cum_len + seglen; +#ifdef NETIF_F_TSO + if (mss) { /* TSO */ + (req - rdma_count)->rdma_count = rdma_count + 1; + + if (likely(cum_len >= 0)) { /* payload */ + int next_is_first, chop; + + chop = (cum_len_next > mss); + cum_len_next = cum_len_next % mss; + next_is_first = (cum_len_next == 0); + flags |= chop * MXGEFW_FLAGS_TSO_CHOP; + flags_next |= next_is_first * + MXGEFW_FLAGS_FIRST; + rdma_count |= -(chop | next_is_first); + rdma_count += chop & !next_is_first; + } else if (likely(cum_len_next >= 0)) { /* header ends */ + int small; + + rdma_count = -1; + cum_len_next = 0; + seglen = -cum_len; + small = (mss <= MXGEFW_SEND_SMALL_SIZE); + flags_next = MXGEFW_FLAGS_TSO_PLD | + MXGEFW_FLAGS_FIRST | + (small * MXGEFW_FLAGS_SMALL); + } + } +#endif /* NETIF_F_TSO */ + req->addr_high = high_swapped; + req->addr_low = htonl(low); + req->pseudo_hdr_offset = pseudo_hdr_offset; + req->pad = 0; /* complete solid 16-byte block; does this matter? */ + req->rdma_count = 1; + req->length = htons(seglen); + req->cksum_offset = cksum_offset; + req->flags = flags | ((cum_len & 1) * odd_flag); + + low += seglen; + len -= seglen; + cum_len = cum_len_next; + flags = flags_next; + req++; + count++; + rdma_count++; + if (unlikely(cksum_offset > seglen)) + cksum_offset -= seglen; + else + cksum_offset = 0; + } + if (frag_idx == frag_cnt) + break; + + /* map next fragment for DMA */ + idx = (count + tx->req) & tx->mask; + frag = &skb_shinfo(skb)->frags[frag_idx]; + frag_idx++; + len = frag->size; + bus = pci_map_page(mgp->pdev, frag->page, frag->page_offset, + len, PCI_DMA_TODEVICE); + pci_unmap_addr_set(&tx->info[idx], bus, bus); + pci_unmap_len_set(&tx->info[idx], len, len); + } + + (req - rdma_count)->rdma_count = rdma_count; +#ifdef NETIF_F_TSO + if (mss) + do { + req--; + req->flags |= MXGEFW_FLAGS_TSO_LAST; + } while (!(req->flags & (MXGEFW_FLAGS_TSO_CHOP | + MXGEFW_FLAGS_FIRST))); +#endif + idx = ((count - 1) + tx->req) & tx->mask; + tx->info[idx].last = 1; + if (tx->wc_fifo == NULL) + myri10ge_submit_req(tx, tx->req_list, count); + else + myri10ge_submit_req_wc(tx, tx->req_list, count); + tx->pkt_start++; + if ((avail - count) < MXGEFW_MAX_SEND_DESC) { + mgp->stop_queue++; + netif_stop_queue(dev); + } + dev->trans_start = jiffies; + return 0; + +abort_linearize: + /* Free any DMA resources we've alloced and clear out the skb + * slot so as to not trip up assertions, and to avoid a + * double-free if linearizing fails */ + + last_idx = (idx + 1) & tx->mask; + idx = tx->req & tx->mask; + tx->info[idx].skb = NULL; + do { + len = pci_unmap_len(&tx->info[idx], len); + if (len) { + if (tx->info[idx].skb != NULL) + pci_unmap_single(mgp->pdev, + pci_unmap_addr(&tx->info[idx], + bus), len, + PCI_DMA_TODEVICE); + else + pci_unmap_page(mgp->pdev, + pci_unmap_addr(&tx->info[idx], + bus), len, + PCI_DMA_TODEVICE); + pci_unmap_len_set(&tx->info[idx], len, 0); + tx->info[idx].skb = NULL; + } + idx = (idx + 1) & tx->mask; + } while (idx != last_idx); + if (skb_is_gso(skb)) { + printk(KERN_ERR + "myri10ge: %s: TSO but wanted to linearize?!?!?\n", + mgp->dev->name); + goto drop; + } + + if (skb_linearize(skb)) + goto drop; + + mgp->tx_linearized++; + goto again; + +drop: + dev_kfree_skb_any(skb); + mgp->stats.tx_dropped += 1; + return 0; + +} + +static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) +{ + struct myri10ge_priv *mgp = netdev_priv(dev); + return &mgp->stats; +} + +static void myri10ge_set_multicast_list(struct net_device *dev) +{ + /* can be called from atomic contexts, + * pass 1 to force atomicity in myri10ge_send_cmd() */ + myri10ge_change_promisc(netdev_priv(dev), dev->flags & IFF_PROMISC, 1); +} + +static int myri10ge_set_mac_address(struct net_device *dev, void *addr) +{ + struct sockaddr *sa = addr; + struct myri10ge_priv *mgp = netdev_priv(dev); + int status; + + if (!is_valid_ether_addr(sa->sa_data)) + return -EADDRNOTAVAIL; + + status = myri10ge_update_mac_address(mgp, sa->sa_data); + if (status != 0) { + printk(KERN_ERR + "myri10ge: %s: changing mac address failed with %d\n", + dev->name, status); + return status; + } + + /* change the dev structure */ + memcpy(dev->dev_addr, sa->sa_data, 6); + return 0; +} + +static int myri10ge_change_mtu(struct net_device *dev, int new_mtu) +{ + struct myri10ge_priv *mgp = netdev_priv(dev); + int error = 0; + + if ((new_mtu < 68) || (ETH_HLEN + new_mtu > MYRI10GE_MAX_ETHER_MTU)) { + printk(KERN_ERR "myri10ge: %s: new mtu (%d) is not valid\n", + dev->name, new_mtu); + return -EINVAL; + } + printk(KERN_INFO "%s: changing mtu from %d to %d\n", + dev->name, dev->mtu, new_mtu); + if (mgp->running) { + /* if we change the mtu on an active device, we must + * reset the device so the firmware sees the change */ + myri10ge_close(dev); + dev->mtu = new_mtu; + myri10ge_open(dev); + } else + dev->mtu = new_mtu; + + return error; +} + +/* + * Enable ECRC to align PCI-E Completion packets on an 8-byte boundary. + * Only do it if the bridge is a root port since we don't want to disturb + * any other device, except if forced with myri10ge_ecrc_enable > 1. + */ + +static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp) +{ + struct pci_dev *bridge = mgp->pdev->bus->self; + struct device *dev = &mgp->pdev->dev; + unsigned cap; + unsigned err_cap; + u16 val; + u8 ext_type; + int ret; + + if (!myri10ge_ecrc_enable || !bridge) + return; + + /* check that the bridge is a root port */ + cap = pci_find_capability(bridge, PCI_CAP_ID_EXP); + pci_read_config_word(bridge, cap + PCI_CAP_FLAGS, &val); + ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4; + if (ext_type != PCI_EXP_TYPE_ROOT_PORT) { + if (myri10ge_ecrc_enable > 1) { + struct pci_dev *old_bridge = bridge; + + /* Walk the hierarchy up to the root port + * where ECRC has to be enabled */ + do { + bridge = bridge->bus->self; + if (!bridge) { + dev_err(dev, + "Failed to find root port" + " to force ECRC\n"); + return; + } + cap = + pci_find_capability(bridge, PCI_CAP_ID_EXP); + pci_read_config_word(bridge, + cap + PCI_CAP_FLAGS, &val); + ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4; + } while (ext_type != PCI_EXP_TYPE_ROOT_PORT); + + dev_info(dev, + "Forcing ECRC on non-root port %s" + " (enabling on root port %s)\n", + pci_name(old_bridge), pci_name(bridge)); + } else { + dev_err(dev, + "Not enabling ECRC on non-root port %s\n", + pci_name(bridge)); + return; + } + } + + cap = pci_find_ext_capability(bridge, PCI_EXT_CAP_ID_ERR); + if (!cap) + return; + + ret = pci_read_config_dword(bridge, cap + PCI_ERR_CAP, &err_cap); + if (ret) { + dev_err(dev, "failed reading ext-conf-space of %s\n", + pci_name(bridge)); + dev_err(dev, "\t pci=nommconf in use? " + "or buggy/incomplete/absent ACPI MCFG attr?\n"); + return; + } + if (!(err_cap & PCI_ERR_CAP_ECRC_GENC)) + return; + + err_cap |= PCI_ERR_CAP_ECRC_GENE; + pci_write_config_dword(bridge, cap + PCI_ERR_CAP, err_cap); + dev_info(dev, "Enabled ECRC on upstream bridge %s\n", pci_name(bridge)); + mgp->tx.boundary = 4096; + mgp->fw_name = myri10ge_fw_aligned; +} + +/* + * The Lanai Z8E PCI-E interface achieves higher Read-DMA throughput + * when the PCI-E Completion packets are aligned on an 8-byte + * boundary. Some PCI-E chip sets always align Completion packets; on + * the ones that do not, the alignment can be enforced by enabling + * ECRC generation (if supported). + * + * When PCI-E Completion packets are not aligned, it is actually more + * efficient to limit Read-DMA transactions to 2KB, rather than 4KB. + * + * If the driver can neither enable ECRC nor verify that it has + * already been enabled, then it must use a firmware image which works + * around unaligned completion packets (myri10ge_ethp_z8e.dat), and it + * should also ensure that it never gives the device a Read-DMA which is + * larger than 2KB by setting the tx.boundary to 2KB. If ECRC is + * enabled, then the driver should use the aligned (myri10ge_eth_z8e.dat) + * firmware image, and set tx.boundary to 4KB. + */ + +#define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE 0x0132 + +static void myri10ge_select_firmware(struct myri10ge_priv *mgp) +{ + struct pci_dev *bridge = mgp->pdev->bus->self; + + mgp->tx.boundary = 2048; + mgp->fw_name = myri10ge_fw_unaligned; + + if (myri10ge_force_firmware == 0) { + myri10ge_enable_ecrc(mgp); + + /* Check to see if the upstream bridge is known to + * provide aligned completions */ + if (bridge + /* ServerWorks HT2000/HT1000 */ + && bridge->vendor == PCI_VENDOR_ID_SERVERWORKS + && bridge->device == + PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE) { + dev_info(&mgp->pdev->dev, + "Assuming aligned completions (0x%x:0x%x)\n", + bridge->vendor, bridge->device); + mgp->tx.boundary = 4096; + mgp->fw_name = myri10ge_fw_aligned; + } + } else { + if (myri10ge_force_firmware == 1) { + dev_info(&mgp->pdev->dev, + "Assuming aligned completions (forced)\n"); + mgp->tx.boundary = 4096; + mgp->fw_name = myri10ge_fw_aligned; + } else { + dev_info(&mgp->pdev->dev, + "Assuming unaligned completions (forced)\n"); + mgp->tx.boundary = 2048; + mgp->fw_name = myri10ge_fw_unaligned; + } + } + if (myri10ge_fw_name != NULL) { + dev_info(&mgp->pdev->dev, "overriding firmware to %s\n", + myri10ge_fw_name); + mgp->fw_name = myri10ge_fw_name; + } +} + +static void myri10ge_save_state(struct myri10ge_priv *mgp) +{ + struct pci_dev *pdev = mgp->pdev; + int cap; + + pci_save_state(pdev); + /* now save PCIe and MSI state that Linux will not + * save for us */ + cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); + pci_read_config_dword(pdev, cap + PCI_EXP_DEVCTL, &mgp->devctl); + cap = pci_find_capability(pdev, PCI_CAP_ID_MSI); + pci_read_config_word(pdev, cap + PCI_MSI_FLAGS, &mgp->msi_flags); +} + +static void myri10ge_restore_state(struct myri10ge_priv *mgp) +{ + struct pci_dev *pdev = mgp->pdev; + int cap; + + /* restore PCIe and MSI state that linux will not */ + cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); + pci_write_config_dword(pdev, cap + PCI_CAP_ID_EXP, mgp->devctl); + cap = pci_find_capability(pdev, PCI_CAP_ID_MSI); + pci_write_config_word(pdev, cap + PCI_MSI_FLAGS, mgp->msi_flags); + + pci_restore_state(pdev); +} + +#ifdef CONFIG_PM + +static int myri10ge_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct myri10ge_priv *mgp; + struct net_device *netdev; + + mgp = pci_get_drvdata(pdev); + if (mgp == NULL) + return -EINVAL; + netdev = mgp->dev; + + netif_device_detach(netdev); + if (netif_running(netdev)) { + printk(KERN_INFO "myri10ge: closing %s\n", netdev->name); + rtnl_lock(); + myri10ge_close(netdev); + rtnl_unlock(); + } + myri10ge_dummy_rdma(mgp, 0); + free_irq(pdev->irq, mgp); + myri10ge_save_state(mgp); + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + return 0; +} + +static int myri10ge_resume(struct pci_dev *pdev) +{ + struct myri10ge_priv *mgp; + struct net_device *netdev; + int status; + u16 vendor; + + mgp = pci_get_drvdata(pdev); + if (mgp == NULL) + return -EINVAL; + netdev = mgp->dev; + pci_set_power_state(pdev, 0); /* zeros conf space as a side effect */ + msleep(5); /* give card time to respond */ + pci_read_config_word(mgp->pdev, PCI_VENDOR_ID, &vendor); + if (vendor == 0xffff) { + printk(KERN_ERR "myri10ge: %s: device disappeared!\n", + mgp->dev->name); + return -EIO; + } + myri10ge_restore_state(mgp); + + status = pci_enable_device(pdev); + if (status < 0) { + dev_err(&pdev->dev, "failed to enable device\n"); + return -EIO; + } + + pci_set_master(pdev); + + status = request_irq(pdev->irq, myri10ge_intr, IRQF_SHARED, + netdev->name, mgp); + if (status != 0) { + dev_err(&pdev->dev, "failed to allocate IRQ\n"); + goto abort_with_enabled; + } + + myri10ge_reset(mgp); + myri10ge_dummy_rdma(mgp, 1); + + /* Save configuration space to be restored if the + * nic resets due to a parity error */ + myri10ge_save_state(mgp); + + if (netif_running(netdev)) { + rtnl_lock(); + myri10ge_open(netdev); + rtnl_unlock(); + } + netif_device_attach(netdev); + + return 0; + +abort_with_enabled: + pci_disable_device(pdev); + return -EIO; + +} + +#endif /* CONFIG_PM */ + +static u32 myri10ge_read_reboot(struct myri10ge_priv *mgp) +{ + struct pci_dev *pdev = mgp->pdev; + int vs = mgp->vendor_specific_offset; + u32 reboot; + + /*enter read32 mode */ + pci_write_config_byte(pdev, vs + 0x10, 0x3); + + /*read REBOOT_STATUS (0xfffffff0) */ + pci_write_config_dword(pdev, vs + 0x18, 0xfffffff0); + pci_read_config_dword(pdev, vs + 0x14, &reboot); + return reboot; +} + +/* + * This watchdog is used to check whether the board has suffered + * from a parity error and needs to be recovered. + */ +static void myri10ge_watchdog(void *arg) +{ + struct myri10ge_priv *mgp = arg; + u32 reboot; + int status; + u16 cmd, vendor; + + mgp->watchdog_resets++; + pci_read_config_word(mgp->pdev, PCI_COMMAND, &cmd); + if ((cmd & PCI_COMMAND_MASTER) == 0) { + /* Bus master DMA disabled? Check to see + * if the card rebooted due to a parity error + * For now, just report it */ + reboot = myri10ge_read_reboot(mgp); + printk(KERN_ERR + "myri10ge: %s: NIC rebooted (0x%x), resetting\n", + mgp->dev->name, reboot); + /* + * A rebooted nic will come back with config space as + * it was after power was applied to PCIe bus. + * Attempt to restore config space which was saved + * when the driver was loaded, or the last time the + * nic was resumed from power saving mode. + */ + myri10ge_restore_state(mgp); + } else { + /* if we get back -1's from our slot, perhaps somebody + * powered off our card. Don't try to reset it in + * this case */ + if (cmd == 0xffff) { + pci_read_config_word(mgp->pdev, PCI_VENDOR_ID, &vendor); + if (vendor == 0xffff) { + printk(KERN_ERR + "myri10ge: %s: device disappeared!\n", + mgp->dev->name); + return; + } + } + /* Perhaps it is a software error. Try to reset */ + + printk(KERN_ERR "myri10ge: %s: device timeout, resetting\n", + mgp->dev->name); + printk(KERN_INFO "myri10ge: %s: %d %d %d %d %d\n", + mgp->dev->name, mgp->tx.req, mgp->tx.done, + mgp->tx.pkt_start, mgp->tx.pkt_done, + (int)ntohl(mgp->fw_stats->send_done_count)); + msleep(2000); + printk(KERN_INFO "myri10ge: %s: %d %d %d %d %d\n", + mgp->dev->name, mgp->tx.req, mgp->tx.done, + mgp->tx.pkt_start, mgp->tx.pkt_done, + (int)ntohl(mgp->fw_stats->send_done_count)); + } + rtnl_lock(); + myri10ge_close(mgp->dev); + status = myri10ge_load_firmware(mgp); + if (status != 0) + printk(KERN_ERR "myri10ge: %s: failed to load firmware\n", + mgp->dev->name); + else + myri10ge_open(mgp->dev); + rtnl_unlock(); +} + +/* + * We use our own timer routine rather than relying upon + * netdev->tx_timeout because we have a very large hardware transmit + * queue. Due to the large queue, the netdev->tx_timeout function + * cannot detect a NIC with a parity error in a timely fashion if the + * NIC is lightly loaded. + */ +static void myri10ge_watchdog_timer(unsigned long arg) +{ + struct myri10ge_priv *mgp; + + mgp = (struct myri10ge_priv *)arg; + if (mgp->tx.req != mgp->tx.done && + mgp->tx.done == mgp->watchdog_tx_done && + mgp->watchdog_tx_req != mgp->watchdog_tx_done) + /* nic seems like it might be stuck.. */ + schedule_work(&mgp->watchdog_work); + else + /* rearm timer */ + mod_timer(&mgp->watchdog_timer, + jiffies + myri10ge_watchdog_timeout * HZ); + + mgp->watchdog_tx_done = mgp->tx.done; + mgp->watchdog_tx_req = mgp->tx.req; +} + +static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct net_device *netdev; + struct myri10ge_priv *mgp; + struct device *dev = &pdev->dev; + size_t bytes; + int i; + int status = -ENXIO; + int cap; + int dac_enabled; + u16 val; + + netdev = alloc_etherdev(sizeof(*mgp)); + if (netdev == NULL) { + dev_err(dev, "Could not allocate ethernet device\n"); + return -ENOMEM; + } + + mgp = netdev_priv(netdev); + memset(mgp, 0, sizeof(*mgp)); + mgp->dev = netdev; + mgp->pdev = pdev; + mgp->csum_flag = MXGEFW_FLAGS_CKSUM; + mgp->pause = myri10ge_flow_control; + mgp->intr_coal_delay = myri10ge_intr_coal_delay; + init_waitqueue_head(&mgp->down_wq); + + if (pci_enable_device(pdev)) { + dev_err(&pdev->dev, "pci_enable_device call failed\n"); + status = -ENODEV; + goto abort_with_netdev; + } + myri10ge_select_firmware(mgp); + + /* Find the vendor-specific cap so we can check + * the reboot register later on */ + mgp->vendor_specific_offset + = pci_find_capability(pdev, PCI_CAP_ID_VNDR); + + /* Set our max read request to 4KB */ + cap = pci_find_capability(pdev, PCI_CAP_ID_EXP); + if (cap < 64) { + dev_err(&pdev->dev, "Bad PCI_CAP_ID_EXP location %d\n", cap); + goto abort_with_netdev; + } + status = pci_read_config_word(pdev, cap + PCI_EXP_DEVCTL, &val); + if (status != 0) { + dev_err(&pdev->dev, "Error %d reading PCI_EXP_DEVCTL\n", + status); + goto abort_with_netdev; + } + val = (val & ~PCI_EXP_DEVCTL_READRQ) | (5 << 12); + status = pci_write_config_word(pdev, cap + PCI_EXP_DEVCTL, val); + if (status != 0) { + dev_err(&pdev->dev, "Error %d writing PCI_EXP_DEVCTL\n", + status); + goto abort_with_netdev; + } + + pci_set_master(pdev); + dac_enabled = 1; + status = pci_set_dma_mask(pdev, DMA_64BIT_MASK); + if (status != 0) { + dac_enabled = 0; + dev_err(&pdev->dev, + "64-bit pci address mask was refused, trying 32-bit"); + status = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + } + if (status != 0) { + dev_err(&pdev->dev, "Error %d setting DMA mask\n", status); + goto abort_with_netdev; + } + mgp->cmd = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->cmd), + &mgp->cmd_bus, GFP_KERNEL); + if (mgp->cmd == NULL) + goto abort_with_netdev; + + mgp->fw_stats = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->fw_stats), + &mgp->fw_stats_bus, GFP_KERNEL); + if (mgp->fw_stats == NULL) + goto abort_with_cmd; + + mgp->board_span = pci_resource_len(pdev, 0); + mgp->iomem_base = pci_resource_start(pdev, 0); + mgp->mtrr = -1; +#ifdef CONFIG_MTRR + mgp->mtrr = mtrr_add(mgp->iomem_base, mgp->board_span, + MTRR_TYPE_WRCOMB, 1); +#endif + /* Hack. need to get rid of these magic numbers */ + mgp->sram_size = + 2 * 1024 * 1024 - (2 * (48 * 1024) + (32 * 1024)) - 0x100; + if (mgp->sram_size > mgp->board_span) { + dev_err(&pdev->dev, "board span %ld bytes too small\n", + mgp->board_span); + goto abort_with_wc; + } + mgp->sram = ioremap(mgp->iomem_base, mgp->board_span); + if (mgp->sram == NULL) { + dev_err(&pdev->dev, "ioremap failed for %ld bytes at 0x%lx\n", + mgp->board_span, mgp->iomem_base); + status = -ENXIO; + goto abort_with_wc; + } + memcpy_fromio(mgp->eeprom_strings, + mgp->sram + mgp->sram_size - MYRI10GE_EEPROM_STRINGS_SIZE, + MYRI10GE_EEPROM_STRINGS_SIZE); + memset(mgp->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE - 2, 0, 2); + status = myri10ge_read_mac_addr(mgp); + if (status) + goto abort_with_ioremap; + + for (i = 0; i < ETH_ALEN; i++) + netdev->dev_addr[i] = mgp->mac_addr[i]; + + /* allocate rx done ring */ + bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry); + mgp->rx_done.entry = dma_alloc_coherent(&pdev->dev, bytes, + &mgp->rx_done.bus, GFP_KERNEL); + if (mgp->rx_done.entry == NULL) + goto abort_with_ioremap; + memset(mgp->rx_done.entry, 0, bytes); + + status = myri10ge_load_firmware(mgp); + if (status != 0) { + dev_err(&pdev->dev, "failed to load firmware\n"); + goto abort_with_rx_done; + } + + status = myri10ge_reset(mgp); + if (status != 0) { + dev_err(&pdev->dev, "failed reset\n"); + goto abort_with_firmware; + } + + if (myri10ge_msi) { + status = pci_enable_msi(pdev); + if (status != 0) + dev_err(&pdev->dev, + "Error %d setting up MSI; falling back to xPIC\n", + status); + else + mgp->msi_enabled = 1; + } + + status = request_irq(pdev->irq, myri10ge_intr, IRQF_SHARED, + netdev->name, mgp); + if (status != 0) { + dev_err(&pdev->dev, "failed to allocate IRQ\n"); + goto abort_with_firmware; + } + + pci_set_drvdata(pdev, mgp); + if ((myri10ge_initial_mtu + ETH_HLEN) > MYRI10GE_MAX_ETHER_MTU) + myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN; + if ((myri10ge_initial_mtu + ETH_HLEN) < 68) + myri10ge_initial_mtu = 68; + netdev->mtu = myri10ge_initial_mtu; + netdev->open = myri10ge_open; + netdev->stop = myri10ge_close; + netdev->hard_start_xmit = myri10ge_xmit; + netdev->get_stats = myri10ge_get_stats; + netdev->base_addr = mgp->iomem_base; + netdev->irq = pdev->irq; + netdev->change_mtu = myri10ge_change_mtu; + netdev->set_multicast_list = myri10ge_set_multicast_list; + netdev->set_mac_address = myri10ge_set_mac_address; + netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO; + if (dac_enabled) + netdev->features |= NETIF_F_HIGHDMA; + netdev->poll = myri10ge_poll; + netdev->weight = myri10ge_napi_weight; + + /* Save configuration space to be restored if the + * nic resets due to a parity error */ + myri10ge_save_state(mgp); + + /* Setup the watchdog timer */ + setup_timer(&mgp->watchdog_timer, myri10ge_watchdog_timer, + (unsigned long)mgp); + + SET_ETHTOOL_OPS(netdev, &myri10ge_ethtool_ops); + INIT_WORK(&mgp->watchdog_work, myri10ge_watchdog, mgp); + status = register_netdev(netdev); + if (status != 0) { + dev_err(&pdev->dev, "register_netdev failed: %d\n", status); + goto abort_with_irq; + } + dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, WC %s\n", + (mgp->msi_enabled ? "MSI" : "xPIC"), + pdev->irq, mgp->tx.boundary, mgp->fw_name, + (mgp->mtrr >= 0 ? "Enabled" : "Disabled")); + + return 0; + +abort_with_irq: + free_irq(pdev->irq, mgp); + if (mgp->msi_enabled) + pci_disable_msi(pdev); + +abort_with_firmware: + myri10ge_dummy_rdma(mgp, 0); + +abort_with_rx_done: + bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry); + dma_free_coherent(&pdev->dev, bytes, + mgp->rx_done.entry, mgp->rx_done.bus); + +abort_with_ioremap: + iounmap(mgp->sram); + +abort_with_wc: +#ifdef CONFIG_MTRR + if (mgp->mtrr >= 0) + mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span); +#endif + dma_free_coherent(&pdev->dev, sizeof(*mgp->fw_stats), + mgp->fw_stats, mgp->fw_stats_bus); + +abort_with_cmd: + dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd), + mgp->cmd, mgp->cmd_bus); + +abort_with_netdev: + + free_netdev(netdev); + return status; +} + +/* + * myri10ge_remove + * + * Does what is necessary to shutdown one Myrinet device. Called + * once for each Myrinet card by the kernel when a module is + * unloaded. + */ +static void myri10ge_remove(struct pci_dev *pdev) +{ + struct myri10ge_priv *mgp; + struct net_device *netdev; + size_t bytes; + + mgp = pci_get_drvdata(pdev); + if (mgp == NULL) + return; + + flush_scheduled_work(); + netdev = mgp->dev; + unregister_netdev(netdev); + free_irq(pdev->irq, mgp); + if (mgp->msi_enabled) + pci_disable_msi(pdev); + + myri10ge_dummy_rdma(mgp, 0); + + bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry); + dma_free_coherent(&pdev->dev, bytes, + mgp->rx_done.entry, mgp->rx_done.bus); + + iounmap(mgp->sram); + +#ifdef CONFIG_MTRR + if (mgp->mtrr >= 0) + mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span); +#endif + dma_free_coherent(&pdev->dev, sizeof(*mgp->fw_stats), + mgp->fw_stats, mgp->fw_stats_bus); + + dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd), + mgp->cmd, mgp->cmd_bus); + + free_netdev(netdev); + pci_set_drvdata(pdev, NULL); +} + +#define PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E 0x0008 + +static struct pci_device_id myri10ge_pci_tbl[] = { + {PCI_DEVICE(PCI_VENDOR_ID_MYRICOM, PCI_DEVICE_ID_MYRICOM_MYRI10GE_Z8E)}, + {0}, +}; + +static struct pci_driver myri10ge_driver = { + .name = "myri10ge", + .probe = myri10ge_probe, + .remove = myri10ge_remove, + .id_table = myri10ge_pci_tbl, +#ifdef CONFIG_PM + .suspend = myri10ge_suspend, + .resume = myri10ge_resume, +#endif +}; + +static __init int myri10ge_init_module(void) +{ + printk(KERN_INFO "%s: Version %s\n", myri10ge_driver.name, + MYRI10GE_VERSION_STR); + return pci_register_driver(&myri10ge_driver); +} + +module_init(myri10ge_init_module); + +static __exit void myri10ge_cleanup_module(void) +{ + pci_unregister_driver(&myri10ge_driver); +} + +module_exit(myri10ge_cleanup_module); diff --git a/drivers/net/myri10ge/myri10ge_mcp.h b/drivers/net/myri10ge/myri10ge_mcp.h new file mode 100644 index 000000000..0a6cae6cb --- /dev/null +++ b/drivers/net/myri10ge/myri10ge_mcp.h @@ -0,0 +1,205 @@ +#ifndef __MYRI10GE_MCP_H__ +#define __MYRI10GE_MCP_H__ + +#define MXGEFW_VERSION_MAJOR 1 +#define MXGEFW_VERSION_MINOR 4 + +/* 8 Bytes */ +struct mcp_dma_addr { + u32 high; + u32 low; +}; + +/* 4 Bytes */ +struct mcp_slot { + u16 checksum; + u16 length; +}; + +/* 64 Bytes */ +struct mcp_cmd { + u32 cmd; + u32 data0; /* will be low portion if data > 32 bits */ + /* 8 */ + u32 data1; /* will be high portion if data > 32 bits */ + u32 data2; /* currently unused.. */ + /* 16 */ + struct mcp_dma_addr response_addr; + /* 24 */ + u8 pad[40]; +}; + +/* 8 Bytes */ +struct mcp_cmd_response { + u32 data; + u32 result; +}; + +/* + * flags used in mcp_kreq_ether_send_t: + * + * The SMALL flag is only needed in the first segment. It is raised + * for packets that are total less or equal 512 bytes. + * + * The CKSUM flag must be set in all segments. + * + * The PADDED flags is set if the packet needs to be padded, and it + * must be set for all segments. + * + * The MXGEFW_FLAGS_ALIGN_ODD must be set if the cumulative + * length of all previous segments was odd. + */ + +#define MXGEFW_FLAGS_SMALL 0x1 +#define MXGEFW_FLAGS_TSO_HDR 0x1 +#define MXGEFW_FLAGS_FIRST 0x2 +#define MXGEFW_FLAGS_ALIGN_ODD 0x4 +#define MXGEFW_FLAGS_CKSUM 0x8 +#define MXGEFW_FLAGS_TSO_LAST 0x8 +#define MXGEFW_FLAGS_NO_TSO 0x10 +#define MXGEFW_FLAGS_TSO_CHOP 0x10 +#define MXGEFW_FLAGS_TSO_PLD 0x20 + +#define MXGEFW_SEND_SMALL_SIZE 1520 +#define MXGEFW_MAX_MTU 9400 + +union mcp_pso_or_cumlen { + u16 pseudo_hdr_offset; + u16 cum_len; +}; + +#define MXGEFW_MAX_SEND_DESC 12 +#define MXGEFW_PAD 2 + +/* 16 Bytes */ +struct mcp_kreq_ether_send { + u32 addr_high; + u32 addr_low; + u16 pseudo_hdr_offset; + u16 length; + u8 pad; + u8 rdma_count; + u8 cksum_offset; /* where to start computing cksum */ + u8 flags; /* as defined above */ +}; + +/* 8 Bytes */ +struct mcp_kreq_ether_recv { + u32 addr_high; + u32 addr_low; +}; + +/* Commands */ + +#define MXGEFW_CMD_OFFSET 0xf80000 + +enum myri10ge_mcp_cmd_type { + MXGEFW_CMD_NONE = 0, + /* Reset the mcp, it is left in a safe state, waiting + * for the driver to set all its parameters */ + MXGEFW_CMD_RESET, + + /* get the version number of the current firmware.. + * (may be available in the eeprom strings..? */ + MXGEFW_GET_MCP_VERSION, + + /* Parameters which must be set by the driver before it can + * issue MXGEFW_CMD_ETHERNET_UP. They persist until the next + * MXGEFW_CMD_RESET is issued */ + + MXGEFW_CMD_SET_INTRQ_DMA, + MXGEFW_CMD_SET_BIG_BUFFER_SIZE, /* in bytes, power of 2 */ + MXGEFW_CMD_SET_SMALL_BUFFER_SIZE, /* in bytes */ + + /* Parameters which refer to lanai SRAM addresses where the + * driver must issue PIO writes for various things */ + + MXGEFW_CMD_GET_SEND_OFFSET, + MXGEFW_CMD_GET_SMALL_RX_OFFSET, + MXGEFW_CMD_GET_BIG_RX_OFFSET, + MXGEFW_CMD_GET_IRQ_ACK_OFFSET, + MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, + + /* Parameters which refer to rings stored on the MCP, + * and whose size is controlled by the mcp */ + + MXGEFW_CMD_GET_SEND_RING_SIZE, /* in bytes */ + MXGEFW_CMD_GET_RX_RING_SIZE, /* in bytes */ + + /* Parameters which refer to rings stored in the host, + * and whose size is controlled by the host. Note that + * all must be physically contiguous and must contain + * a power of 2 number of entries. */ + + MXGEFW_CMD_SET_INTRQ_SIZE, /* in bytes */ + + /* command to bring ethernet interface up. Above parameters + * (plus mtu & mac address) must have been exchanged prior + * to issuing this command */ + MXGEFW_CMD_ETHERNET_UP, + + /* command to bring ethernet interface down. No further sends + * or receives may be processed until an MXGEFW_CMD_ETHERNET_UP + * is issued, and all interrupt queues must be flushed prior + * to ack'ing this command */ + + MXGEFW_CMD_ETHERNET_DOWN, + + /* commands the driver may issue live, without resetting + * the nic. Note that increasing the mtu "live" should + * only be done if the driver has already supplied buffers + * sufficiently large to handle the new mtu. Decreasing + * the mtu live is safe */ + + MXGEFW_CMD_SET_MTU, + MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, /* in microseconds */ + MXGEFW_CMD_SET_STATS_INTERVAL, /* in microseconds */ + MXGEFW_CMD_SET_STATS_DMA, + + MXGEFW_ENABLE_PROMISC, + MXGEFW_DISABLE_PROMISC, + MXGEFW_SET_MAC_ADDRESS, + + MXGEFW_ENABLE_FLOW_CONTROL, + MXGEFW_DISABLE_FLOW_CONTROL, + + /* do a DMA test + * data0,data1 = DMA address + * data2 = RDMA length (MSH), WDMA length (LSH) + * command return data = repetitions (MSH), 0.5-ms ticks (LSH) + */ + MXGEFW_DMA_TEST +}; + +enum myri10ge_mcp_cmd_status { + MXGEFW_CMD_OK = 0, + MXGEFW_CMD_UNKNOWN, + MXGEFW_CMD_ERROR_RANGE, + MXGEFW_CMD_ERROR_BUSY, + MXGEFW_CMD_ERROR_EMPTY, + MXGEFW_CMD_ERROR_CLOSED, + MXGEFW_CMD_ERROR_HASH_ERROR, + MXGEFW_CMD_ERROR_BAD_PORT, + MXGEFW_CMD_ERROR_RESOURCES +}; + +/* 40 Bytes */ +struct mcp_irq_data { + u32 send_done_count; + + u32 link_up; + u32 dropped_link_overflow; + u32 dropped_link_error_or_filtered; + u32 dropped_runt; + u32 dropped_overrun; + u32 dropped_no_small_buffer; + u32 dropped_no_big_buffer; + u32 rdma_tags_available; + + u8 tx_stopped; + u8 link_down; + u8 stats_updated; + u8 valid; +}; + +#endif /* __MYRI10GE_MCP_H__ */ diff --git a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h new file mode 100644 index 000000000..487f7792f --- /dev/null +++ b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h @@ -0,0 +1,58 @@ +#ifndef __MYRI10GE_MCP_GEN_HEADER_H__ +#define __MYRI10GE_MCP_GEN_HEADER_H__ + +/* this file define a standard header used as a first entry point to + * exchange information between firmware/driver and driver. The + * header structure can be anywhere in the mcp. It will usually be in + * the .data section, because some fields needs to be initialized at + * compile time. + * The 32bit word at offset MX_HEADER_PTR_OFFSET in the mcp must + * contains the location of the header. + * + * Typically a MCP will start with the following: + * .text + * .space 52 ! to help catch MEMORY_INT errors + * bt start ! jump to real code + * nop + * .long _gen_mcp_header + * + * The source will have a definition like: + * + * mcp_gen_header_t gen_mcp_header = { + * .header_length = sizeof(mcp_gen_header_t), + * .mcp_type = MCP_TYPE_XXX, + * .version = "something $Id: mcp_gen_header.h,v 1.2 2006/05/13 10:04:35 bgoglin Exp $", + * .mcp_globals = (unsigned)&Globals + * }; + */ + +#define MCP_HEADER_PTR_OFFSET 0x3c + +#define MCP_TYPE_MX 0x4d582020 /* "MX " */ +#define MCP_TYPE_PCIE 0x70636965 /* "PCIE" pcie-only MCP */ +#define MCP_TYPE_ETH 0x45544820 /* "ETH " */ +#define MCP_TYPE_MCP0 0x4d435030 /* "MCP0" */ + +struct mcp_gen_header { + /* the first 4 fields are filled at compile time */ + unsigned header_length; + unsigned mcp_type; + char version[128]; + unsigned mcp_globals; /* pointer to mcp-type specific structure */ + + /* filled by the MCP at run-time */ + unsigned sram_size; + unsigned string_specs; /* either the original STRING_SPECS or a superset */ + unsigned string_specs_len; + + /* Fields above this comment are guaranteed to be present. + * + * Fields below this comment are extensions added in later versions + * of this struct, drivers should compare the header_length against + * offsetof(field) to check wether a given MCP implements them. + * + * Never remove any field. Keep everything naturally align. + */ +}; + +#endif /* __MYRI10GE_MCP_GEN_HEADER_H__ */ diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c new file mode 100644 index 000000000..30ed9a5a4 --- /dev/null +++ b/drivers/net/netx-eth.c @@ -0,0 +1,515 @@ +/* + * drivers/net/netx-eth.c + * + * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/delay.h> + +#include <linux/netdevice.h> +#include <linux/platform_device.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/mii.h> + +#include <asm/io.h> +#include <asm/hardware.h> +#include <asm/arch/hardware.h> +#include <asm/arch/netx-regs.h> +#include <asm/arch/pfifo.h> +#include <asm/arch/xc.h> +#include <asm/arch/eth.h> + +/* XC Fifo Offsets */ +#define EMPTY_PTR_FIFO(xcno) (0 + ((xcno) << 3)) /* Index of the empty pointer FIFO */ +#define IND_FIFO_PORT_HI(xcno) (1 + ((xcno) << 3)) /* Index of the FIFO where received */ + /* Data packages are indicated by XC */ +#define IND_FIFO_PORT_LO(xcno) (2 + ((xcno) << 3)) /* Index of the FIFO where received */ + /* Data packages are indicated by XC */ +#define REQ_FIFO_PORT_HI(xcno) (3 + ((xcno) << 3)) /* Index of the FIFO where Data packages */ + /* have to be indicated by ARM which */ + /* shall be sent */ +#define REQ_FIFO_PORT_LO(xcno) (4 + ((xcno) << 3)) /* Index of the FIFO where Data packages */ + /* have to be indicated by ARM which shall */ + /* be sent */ +#define CON_FIFO_PORT_HI(xcno) (5 + ((xcno) << 3)) /* Index of the FIFO where sent Data packages */ + /* are confirmed */ +#define CON_FIFO_PORT_LO(xcno) (6 + ((xcno) << 3)) /* Index of the FIFO where sent Data */ + /* packages are confirmed */ +#define PFIFO_MASK(xcno) (0x7f << (xcno*8)) + +#define FIFO_PTR_FRAMELEN_SHIFT 0 +#define FIFO_PTR_FRAMELEN_MASK (0x7ff << 0) +#define FIFO_PTR_FRAMELEN(len) (((len) << 0) & FIFO_PTR_FRAMELEN_MASK) +#define FIFO_PTR_TIMETRIG (1<<11) +#define FIFO_PTR_MULTI_REQ +#define FIFO_PTR_ORIGIN (1<<14) +#define FIFO_PTR_VLAN (1<<15) +#define FIFO_PTR_FRAMENO_SHIFT 16 +#define FIFO_PTR_FRAMENO_MASK (0x3f << 16) +#define FIFO_PTR_FRAMENO(no) (((no) << 16) & FIFO_PTR_FRAMENO_MASK) +#define FIFO_PTR_SEGMENT_SHIFT 22 +#define FIFO_PTR_SEGMENT_MASK (0xf << 22) +#define FIFO_PTR_SEGMENT(seg) (((seg) & 0xf) << 22) +#define FIFO_PTR_ERROR_SHIFT 28 +#define FIFO_PTR_ERROR_MASK (0xf << 28) + +#define ISR_LINK_STATUS_CHANGE (1<<4) +#define ISR_IND_LO (1<<3) +#define ISR_CON_LO (1<<2) +#define ISR_IND_HI (1<<1) +#define ISR_CON_HI (1<<0) + +#define ETH_MAC_LOCAL_CONFIG 0x1560 +#define ETH_MAC_4321 0x1564 +#define ETH_MAC_65 0x1568 + +#define MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT 16 +#define MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK (0xf<<MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT) +#define MAC_TRAFFIC_CLASS_ARRANGEMENT(x) (((x)<<MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT) & MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK) +#define LOCAL_CONFIG_LINK_STATUS_IRQ_EN (1<<24) +#define LOCAL_CONFIG_CON_LO_IRQ_EN (1<<23) +#define LOCAL_CONFIG_CON_HI_IRQ_EN (1<<22) +#define LOCAL_CONFIG_IND_LO_IRQ_EN (1<<21) +#define LOCAL_CONFIG_IND_HI_IRQ_EN (1<<20) + +#define CARDNAME "netx-eth" + +/* LSB must be zero */ +#define INTERNAL_PHY_ADR 0x1c + +struct netx_eth_priv { + void __iomem *sram_base, *xpec_base, *xmac_base; + int id; + struct net_device_stats stats; + struct mii_if_info mii; + u32 msg_enable; + struct xc *xc; + spinlock_t lock; +}; + +static void netx_eth_set_multicast_list(struct net_device *ndev) +{ + /* implement me */ +} + +static int +netx_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + unsigned char *buf = skb->data; + unsigned int len = skb->len; + + spin_lock_irq(&priv->lock); + memcpy_toio(priv->sram_base + 1560, (void *)buf, len); + if (len < 60) { + memset_io(priv->sram_base + 1560 + len, 0, 60 - len); + len = 60; + } + + pfifo_push(REQ_FIFO_PORT_LO(priv->id), + FIFO_PTR_SEGMENT(priv->id) | + FIFO_PTR_FRAMENO(1) | + FIFO_PTR_FRAMELEN(len)); + + ndev->trans_start = jiffies; + priv->stats.tx_packets++; + priv->stats.tx_bytes += skb->len; + + netif_stop_queue(ndev); + spin_unlock_irq(&priv->lock); + dev_kfree_skb(skb); + + return 0; +} + +static void netx_eth_receive(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + unsigned int val, frameno, seg, len; + unsigned char *data; + struct sk_buff *skb; + + val = pfifo_pop(IND_FIFO_PORT_LO(priv->id)); + + frameno = (val & FIFO_PTR_FRAMENO_MASK) >> FIFO_PTR_FRAMENO_SHIFT; + seg = (val & FIFO_PTR_SEGMENT_MASK) >> FIFO_PTR_SEGMENT_SHIFT; + len = (val & FIFO_PTR_FRAMELEN_MASK) >> FIFO_PTR_FRAMELEN_SHIFT; + + skb = dev_alloc_skb(len); + if (unlikely(skb == NULL)) { + printk(KERN_NOTICE "%s: Low memory, packet dropped.\n", + ndev->name); + priv->stats.rx_dropped++; + return; + } + + data = skb_put(skb, len); + + memcpy_fromio(data, priv->sram_base + frameno * 1560, len); + + pfifo_push(EMPTY_PTR_FIFO(priv->id), + FIFO_PTR_SEGMENT(seg) | FIFO_PTR_FRAMENO(frameno)); + + ndev->last_rx = jiffies; + skb->dev = ndev; + skb->protocol = eth_type_trans(skb, ndev); + netif_rx(skb); + priv->stats.rx_packets++; + priv->stats.rx_bytes += len; +} + +static irqreturn_t +netx_eth_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *ndev = dev_id; + struct netx_eth_priv *priv = netdev_priv(ndev); + int status; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + status = readl(NETX_PFIFO_XPEC_ISR(priv->id)); + while (status) { + int fill_level; + writel(status, NETX_PFIFO_XPEC_ISR(priv->id)); + + if ((status & ISR_CON_HI) || (status & ISR_IND_HI)) + printk("%s: unexpected status: 0x%08x\n", + __FUNCTION__, status); + + fill_level = + readl(NETX_PFIFO_FILL_LEVEL(IND_FIFO_PORT_LO(priv->id))); + while (fill_level--) + netx_eth_receive(ndev); + + if (status & ISR_CON_LO) + netif_wake_queue(ndev); + + if (status & ISR_LINK_STATUS_CHANGE) + mii_check_media(&priv->mii, netif_msg_link(priv), 1); + + status = readl(NETX_PFIFO_XPEC_ISR(priv->id)); + } + spin_unlock_irqrestore(&priv->lock, flags); + return IRQ_HANDLED; +} + +static struct net_device_stats *netx_eth_query_statistics(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + return &priv->stats; +} + +static int netx_eth_open(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + + if (request_irq + (ndev->irq, &netx_eth_interrupt, IRQF_SHARED, ndev->name, ndev)) + return -EAGAIN; + + writel(ndev->dev_addr[0] | + ndev->dev_addr[1]<<8 | + ndev->dev_addr[2]<<16 | + ndev->dev_addr[3]<<24, + priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_4321); + writel(ndev->dev_addr[4] | + ndev->dev_addr[5]<<8, + priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_65); + + writel(LOCAL_CONFIG_LINK_STATUS_IRQ_EN | + LOCAL_CONFIG_CON_LO_IRQ_EN | + LOCAL_CONFIG_CON_HI_IRQ_EN | + LOCAL_CONFIG_IND_LO_IRQ_EN | + LOCAL_CONFIG_IND_HI_IRQ_EN, + priv->xpec_base + NETX_XPEC_RAM_START_OFS + + ETH_MAC_LOCAL_CONFIG); + + mii_check_media(&priv->mii, netif_msg_link(priv), 1); + netif_start_queue(ndev); + + return 0; +} + +static int netx_eth_close(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + + netif_stop_queue(ndev); + + writel(0, + priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_LOCAL_CONFIG); + + free_irq(ndev->irq, ndev); + + return 0; +} + +static void netx_eth_timeout(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + int i; + + printk(KERN_ERR "%s: transmit timed out, resetting\n", ndev->name); + + spin_lock_irq(&priv->lock); + + xc_reset(priv->xc); + xc_start(priv->xc); + + for (i=2; i<=18; i++) + pfifo_push(EMPTY_PTR_FIFO(priv->id), + FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(priv->id)); + + spin_unlock_irq(&priv->lock); + + netif_wake_queue(ndev); +} + +static int +netx_eth_phy_read(struct net_device *ndev, int phy_id, int reg) +{ + unsigned int val; + + val = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_id) | + MIIMU_REGADDR(reg) | MIIMU_PHY_NRES; + + writel(val, NETX_MIIMU); + while (readl(NETX_MIIMU) & MIIMU_SNRDY); + + return readl(NETX_MIIMU) >> 16; + +} + +static void +netx_eth_phy_write(struct net_device *ndev, int phy_id, int reg, int value) +{ + unsigned int val; + + val = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_id) | + MIIMU_REGADDR(reg) | MIIMU_PHY_NRES | MIIMU_OPMODE_WRITE | + MIIMU_DATA(value); + + writel(val, NETX_MIIMU); + while (readl(NETX_MIIMU) & MIIMU_SNRDY); +} + +static int netx_eth_enable(struct net_device *ndev) +{ + struct netx_eth_priv *priv = netdev_priv(ndev); + unsigned int mac4321, mac65; + int running, i; + + ether_setup(ndev); + + ndev->open = netx_eth_open; + ndev->stop = netx_eth_close; + ndev->hard_start_xmit = netx_eth_hard_start_xmit; + ndev->tx_timeout = netx_eth_timeout; + ndev->watchdog_timeo = msecs_to_jiffies(5000); + ndev->get_stats = netx_eth_query_statistics; + ndev->set_multicast_list = netx_eth_set_multicast_list; + + priv->msg_enable = NETIF_MSG_LINK; + priv->mii.phy_id_mask = 0x1f; + priv->mii.reg_num_mask = 0x1f; + priv->mii.force_media = 0; + priv->mii.full_duplex = 0; + priv->mii.dev = ndev; + priv->mii.mdio_read = netx_eth_phy_read; + priv->mii.mdio_write = netx_eth_phy_write; + priv->mii.phy_id = INTERNAL_PHY_ADR + priv->id; + + running = xc_running(priv->xc); + xc_stop(priv->xc); + + /* if the xc engine is already running, assume the bootloader has + * loaded the firmware for us + */ + if (running) { + /* get Node Address from hardware */ + mac4321 = readl(priv->xpec_base + + NETX_XPEC_RAM_START_OFS + ETH_MAC_4321); + mac65 = readl(priv->xpec_base + + NETX_XPEC_RAM_START_OFS + ETH_MAC_65); + + ndev->dev_addr[0] = mac4321 & 0xff; + ndev->dev_addr[1] = (mac4321 >> 8) & 0xff; + ndev->dev_addr[2] = (mac4321 >> 16) & 0xff; + ndev->dev_addr[3] = (mac4321 >> 24) & 0xff; + ndev->dev_addr[4] = mac65 & 0xff; + ndev->dev_addr[5] = (mac65 >> 8) & 0xff; + } else { + if (xc_request_firmware(priv->xc)) { + printk(CARDNAME ": requesting firmware failed\n"); + return -ENODEV; + } + } + + xc_reset(priv->xc); + xc_start(priv->xc); + + if (!is_valid_ether_addr(ndev->dev_addr)) + printk("%s: Invalid ethernet MAC address. Please " + "set using ifconfig\n", ndev->name); + + for (i=2; i<=18; i++) + pfifo_push(EMPTY_PTR_FIFO(priv->id), + FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(priv->id)); + + return register_netdev(ndev); + +} + +static int netx_eth_drv_probe(struct platform_device *pdev) +{ + struct netx_eth_priv *priv; + struct net_device *ndev; + struct netxeth_platform_data *pdata; + int ret; + + ndev = alloc_etherdev(sizeof (struct netx_eth_priv)); + if (!ndev) { + printk("%s: could not allocate device.\n", CARDNAME); + ret = -ENOMEM; + goto exit; + } + SET_MODULE_OWNER(ndev); + SET_NETDEV_DEV(ndev, &pdev->dev); + + platform_set_drvdata(pdev, ndev); + + priv = netdev_priv(ndev); + + pdata = (struct netxeth_platform_data *)pdev->dev.platform_data; + priv->xc = request_xc(pdata->xcno, &pdev->dev); + if (!priv->xc) { + dev_err(&pdev->dev, "unable to request xc engine\n"); + ret = -ENODEV; + goto exit_free_netdev; + } + + ndev->irq = priv->xc->irq; + priv->id = pdev->id; + priv->xpec_base = priv->xc->xpec_base; + priv->xmac_base = priv->xc->xmac_base; + priv->sram_base = priv->xc->sram_base; + + ret = pfifo_request(PFIFO_MASK(priv->id)); + if (ret) { + printk("unable to request PFIFO\n"); + goto exit_free_xc; + } + + ret = netx_eth_enable(ndev); + if (ret) + goto exit_free_pfifo; + + return 0; +exit_free_pfifo: + pfifo_free(PFIFO_MASK(priv->id)); +exit_free_xc: + free_xc(priv->xc); +exit_free_netdev: + platform_set_drvdata(pdev, NULL); + free_netdev(ndev); +exit: + return ret; +} + +static int netx_eth_drv_remove(struct platform_device *pdev) +{ + struct net_device *ndev = dev_get_drvdata(&pdev->dev); + struct netx_eth_priv *priv = netdev_priv(ndev); + + platform_set_drvdata(pdev, NULL); + + unregister_netdev(ndev); + xc_stop(priv->xc); + free_xc(priv->xc); + free_netdev(ndev); + pfifo_free(PFIFO_MASK(priv->id)); + + return 0; +} + +static int netx_eth_drv_suspend(struct platform_device *pdev, pm_message_t state) +{ + dev_err(&pdev->dev, "suspend not implemented\n"); + return 0; +} + +static int netx_eth_drv_resume(struct platform_device *pdev) +{ + dev_err(&pdev->dev, "resume not implemented\n"); + return 0; +} + +static struct platform_driver netx_eth_driver = { + .probe = netx_eth_drv_probe, + .remove = netx_eth_drv_remove, + .suspend = netx_eth_drv_suspend, + .resume = netx_eth_drv_resume, + .driver = { + .name = CARDNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init netx_eth_init(void) +{ + unsigned int phy_control, val; + + printk("NetX Ethernet driver\n"); + + phy_control = PHY_CONTROL_PHY_ADDRESS(INTERNAL_PHY_ADR>>1) | + PHY_CONTROL_PHY1_MODE(PHY_MODE_ALL) | + PHY_CONTROL_PHY1_AUTOMDIX | + PHY_CONTROL_PHY1_EN | + PHY_CONTROL_PHY0_MODE(PHY_MODE_ALL) | + PHY_CONTROL_PHY0_AUTOMDIX | + PHY_CONTROL_PHY0_EN | + PHY_CONTROL_CLK_XLATIN; + + val = readl(NETX_SYSTEM_IOC_ACCESS_KEY); + writel(val, NETX_SYSTEM_IOC_ACCESS_KEY); + + writel(phy_control | PHY_CONTROL_RESET, NETX_SYSTEM_PHY_CONTROL); + udelay(100); + + val = readl(NETX_SYSTEM_IOC_ACCESS_KEY); + writel(val, NETX_SYSTEM_IOC_ACCESS_KEY); + + writel(phy_control, NETX_SYSTEM_PHY_CONTROL); + + return platform_driver_register(&netx_eth_driver); +} + +static void __exit netx_eth_cleanup(void) +{ + platform_driver_unregister(&netx_eth_driver); +} + +module_init(netx_eth_init); +module_exit(netx_eth_cleanup); + +MODULE_AUTHOR("Sascha Hauer, Pengutronix"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c new file mode 100644 index 000000000..7e3364f55 --- /dev/null +++ b/drivers/net/phy/fixed.c @@ -0,0 +1,357 @@ +/* + * drivers/net/phy/fixed.c + * + * Driver for fixed PHYs, when transceiver is able to operate in one fixed mode. + * + * Author: Vitaly Bordug + * + * Copyright (c) 2006 MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/string.h> +#include <linux/errno.h> +#include <linux/unistd.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/spinlock.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/mii.h> +#include <linux/ethtool.h> +#include <linux/phy.h> + +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/uaccess.h> + +#define MII_REGS_NUM 7 + +/* + The idea is to emulate normal phy behavior by responding with + pre-defined values to mii BMCR read, so that read_status hook could + take all the needed info. +*/ + +struct fixed_phy_status { + u8 link; + u16 speed; + u8 duplex; +}; + +/*----------------------------------------------------------------------------- + * Private information hoder for mii_bus + *-----------------------------------------------------------------------------*/ +struct fixed_info { + u16 *regs; + u8 regs_num; + struct fixed_phy_status phy_status; + struct phy_device *phydev; /* pointer to the container */ + /* link & speed cb */ + int(*link_update)(struct net_device*, struct fixed_phy_status*); + +}; + +/*----------------------------------------------------------------------------- + * If something weird is required to be done with link/speed, + * network driver is able to assign a function to implement this. + * May be useful for PHY's that need to be software-driven. + *-----------------------------------------------------------------------------*/ +int fixed_mdio_set_link_update(struct phy_device* phydev, + int(*link_update)(struct net_device*, struct fixed_phy_status*)) +{ + struct fixed_info *fixed; + + if(link_update == NULL) + return -EINVAL; + + if(phydev) { + if(phydev->bus) { + fixed = phydev->bus->priv; + fixed->link_update = link_update; + return 0; + } + } + return -EINVAL; +} +EXPORT_SYMBOL(fixed_mdio_set_link_update); + +/*----------------------------------------------------------------------------- + * This is used for updating internal mii regs from the status + *-----------------------------------------------------------------------------*/ +static int fixed_mdio_update_regs(struct fixed_info *fixed) +{ + u16 *regs = fixed->regs; + u16 bmsr = 0; + u16 bmcr = 0; + + if(!regs) { + printk(KERN_ERR "%s: regs not set up", __FUNCTION__); + return -EINVAL; + } + + if(fixed->phy_status.link) + bmsr |= BMSR_LSTATUS; + + if(fixed->phy_status.duplex) { + bmcr |= BMCR_FULLDPLX; + + switch ( fixed->phy_status.speed ) { + case 100: + bmsr |= BMSR_100FULL; + bmcr |= BMCR_SPEED100; + break; + + case 10: + bmsr |= BMSR_10FULL; + break; + } + } else { + switch ( fixed->phy_status.speed ) { + case 100: + bmsr |= BMSR_100HALF; + bmcr |= BMCR_SPEED100; + break; + + case 10: + bmsr |= BMSR_100HALF; + break; + } + } + + regs[MII_BMCR] = bmcr; + regs[MII_BMSR] = bmsr | 0x800; /*we are always capable of 10 hdx*/ + + return 0; +} + +static int fixed_mii_read(struct mii_bus *bus, int phy_id, int location) +{ + struct fixed_info *fixed = bus->priv; + + /* if user has registered link update callback, use it */ + if(fixed->phydev) + if(fixed->phydev->attached_dev) { + if(fixed->link_update) { + fixed->link_update(fixed->phydev->attached_dev, + &fixed->phy_status); + fixed_mdio_update_regs(fixed); + } + } + + if ((unsigned int)location >= fixed->regs_num) + return -1; + return fixed->regs[location]; +} + +static int fixed_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val) +{ + /* do nothing for now*/ + return 0; +} + +static int fixed_mii_reset(struct mii_bus *bus) +{ + /*nothing here - no way/need to reset it*/ + return 0; +} + +static int fixed_config_aneg(struct phy_device *phydev) +{ + /* :TODO:03/13/2006 09:45:37 PM:: + The full autoneg funcionality can be emulated, + but no need to have anything here for now + */ + return 0; +} + +/*----------------------------------------------------------------------------- + * the manual bind will do the magic - with phy_id_mask == 0 + * match will never return true... + *-----------------------------------------------------------------------------*/ +static struct phy_driver fixed_mdio_driver = { + .name = "Fixed PHY", + .features = PHY_BASIC_FEATURES, + .config_aneg = fixed_config_aneg, + .read_status = genphy_read_status, + .driver = { .owner = THIS_MODULE,}, +}; + +/*----------------------------------------------------------------------------- + * This func is used to create all the necessary stuff, bind + * the fixed phy driver and register all it on the mdio_bus_type. + * speed is either 10 or 100, duplex is boolean. + * number is used to create multiple fixed PHYs, so that several devices can + * utilize them simultaneously. + *-----------------------------------------------------------------------------*/ +static int fixed_mdio_register_device(int number, int speed, int duplex) +{ + struct mii_bus *new_bus; + struct fixed_info *fixed; + struct phy_device *phydev; + int err = 0; + + struct device* dev = kzalloc(sizeof(struct device), GFP_KERNEL); + + if (NULL == dev) + return -ENOMEM; + + new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL); + + if (NULL == new_bus) { + kfree(dev); + return -ENOMEM; + } + fixed = kzalloc(sizeof(struct fixed_info), GFP_KERNEL); + + if (NULL == fixed) { + kfree(dev); + kfree(new_bus); + return -ENOMEM; + } + + fixed->regs = kzalloc(MII_REGS_NUM*sizeof(int), GFP_KERNEL); + fixed->regs_num = MII_REGS_NUM; + fixed->phy_status.speed = speed; + fixed->phy_status.duplex = duplex; + fixed->phy_status.link = 1; + + new_bus->name = "Fixed MII Bus", + new_bus->read = &fixed_mii_read, + new_bus->write = &fixed_mii_write, + new_bus->reset = &fixed_mii_reset, + + /*set up workspace*/ + fixed_mdio_update_regs(fixed); + new_bus->priv = fixed; + + new_bus->dev = dev; + dev_set_drvdata(dev, new_bus); + + /* create phy_device and register it on the mdio bus */ + phydev = phy_device_create(new_bus, 0, 0); + + /* + Put the phydev pointer into the fixed pack so that bus read/write code could + be able to access for instance attached netdev. Well it doesn't have to do + so, only in case of utilizing user-specified link-update... + */ + fixed->phydev = phydev; + + if(NULL == phydev) { + err = -ENOMEM; + goto device_create_fail; + } + + phydev->irq = -1; + phydev->dev.bus = &mdio_bus_type; + + if(number) + snprintf(phydev->dev.bus_id, BUS_ID_SIZE, + "fixed_%d@%d:%d", number, speed, duplex); + else + snprintf(phydev->dev.bus_id, BUS_ID_SIZE, + "fixed@%d:%d", speed, duplex); + phydev->bus = new_bus; + + err = device_register(&phydev->dev); + if(err) { + printk(KERN_ERR "Phy %s failed to register\n", + phydev->dev.bus_id); + goto bus_register_fail; + } + + /* + the mdio bus has phy_id match... In order not to do it + artificially, we are binding the driver here by hand; + it will be the same for all the fixed phys anyway. + */ + down_write(&phydev->dev.bus->subsys.rwsem); + + phydev->dev.driver = &fixed_mdio_driver.driver; + + err = phydev->dev.driver->probe(&phydev->dev); + if(err < 0) { + printk(KERN_ERR "Phy %s: problems with fixed driver\n",phydev->dev.bus_id); + up_write(&phydev->dev.bus->subsys.rwsem); + goto probe_fail; + } + + device_bind_driver(&phydev->dev); + up_write(&phydev->dev.bus->subsys.rwsem); + + return 0; + +probe_fail: + device_unregister(&phydev->dev); +bus_register_fail: + kfree(phydev); +device_create_fail: + kfree(dev); + kfree(new_bus); + kfree(fixed); + + return err; +} + + +MODULE_DESCRIPTION("Fixed PHY device & driver for PAL"); +MODULE_AUTHOR("Vitaly Bordug"); +MODULE_LICENSE("GPL"); + +static int __init fixed_init(void) +{ + int ret; + int duplex = 0; + + /* register on the bus... Not expected to be matched with anything there... */ + phy_driver_register(&fixed_mdio_driver); + + /* So let the fun begin... + We will create several mdio devices here, and will bound the upper + driver to them. + + Then the external software can lookup the phy bus by searching + fixed@speed:duplex, e.g. fixed@100:1, to be connected to the + virtual 100M Fdx phy. + + In case several virtual PHYs required, the bus_id will be in form + fixed_<num>@<speed>:<duplex>, which make it able even to define + driver-specific link control callback, if for instance PHY is completely + SW-driven. + + */ + +#ifdef CONFIG_FIXED_MII_DUPLEX + duplex = 1; +#endif + +#ifdef CONFIG_FIXED_MII_100_FDX + fixed_mdio_register_device(0, 100, 1); +#endif + +#ifdef CONFIX_FIXED_MII_10_FDX + fixed_mdio_register_device(0, 10, 1); +#endif + return 0; +} + +static void __exit fixed_exit(void) +{ + phy_driver_unregister(&fixed_mdio_driver); + /* :WARNING:02/18/2006 04:32:40 AM:: Cleanup all the created stuff */ +} + +module_init(fixed_init); +module_exit(fixed_exit); diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c new file mode 100644 index 000000000..b1d8ed40a --- /dev/null +++ b/drivers/net/phy/smsc.c @@ -0,0 +1,100 @@ +/* + * drivers/net/phy/smsc.c + * + * Driver for SMSC PHYs + * + * Author: Herbert Valerio Riedel + * + * Copyright (c) 2006 Herbert Valerio Riedel <hvr@gnu.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mii.h> +#include <linux/ethtool.h> +#include <linux/phy.h> +#include <linux/netdevice.h> + +#define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */ +#define MII_LAN83C185_IM 30 /* Interrupt Mask */ + +#define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */ +#define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */ +#define MII_LAN83C185_ISF_INT3 (1<<3) /* Auto-Negotiation LP Ack */ +#define MII_LAN83C185_ISF_INT4 (1<<4) /* Link Down */ +#define MII_LAN83C185_ISF_INT5 (1<<5) /* Remote Fault Detected */ +#define MII_LAN83C185_ISF_INT6 (1<<6) /* Auto-Negotiation complete */ +#define MII_LAN83C185_ISF_INT7 (1<<7) /* ENERGYON */ + +#define MII_LAN83C185_ISF_INT_ALL (0x0e) + +#define MII_LAN83C185_ISF_INT_PHYLIB_EVENTS \ + (MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4) + + +static int lan83c185_config_intr(struct phy_device *phydev) +{ + int rc = phy_write (phydev, MII_LAN83C185_IM, + ((PHY_INTERRUPT_ENABLED == phydev->interrupts) + ? MII_LAN83C185_ISF_INT_PHYLIB_EVENTS + : 0)); + + return rc < 0 ? rc : 0; +} + +static int lan83c185_ack_interrupt(struct phy_device *phydev) +{ + int rc = phy_read (phydev, MII_LAN83C185_ISF); + + return rc < 0 ? rc : 0; +} + +static int lan83c185_config_init(struct phy_device *phydev) +{ + return lan83c185_ack_interrupt (phydev); +} + + +static struct phy_driver lan83c185_driver = { + .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */ + .phy_id_mask = 0xfffffff0, + .name = "SMSC LAN83C185", + + .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause + | SUPPORTED_Asym_Pause), + .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG, + + /* basic functions */ + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + .config_init = lan83c185_config_init, + + /* IRQ related */ + .ack_interrupt = lan83c185_ack_interrupt, + .config_intr = lan83c185_config_intr, + + .driver = { .owner = THIS_MODULE, } +}; + +static int __init smsc_init(void) +{ + return phy_driver_register (&lan83c185_driver); +} + +static void __exit smsc_exit(void) +{ + phy_driver_unregister (&lan83c185_driver); +} + +MODULE_DESCRIPTION("SMSC PHY driver"); +MODULE_AUTHOR("Herbert Valerio Riedel"); +MODULE_LICENSE("GPL"); + +module_init(smsc_init); +module_exit(smsc_exit); diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c new file mode 100644 index 000000000..792716beb --- /dev/null +++ b/drivers/net/phy/vitesse.c @@ -0,0 +1,111 @@ +/* + * Driver for Vitesse PHYs + * + * Author: Kriston Carson + * + * Copyright (c) 2005 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mii.h> +#include <linux/ethtool.h> +#include <linux/phy.h> + +/* Vitesse Extended Control Register 1 */ +#define MII_VSC8244_EXT_CON1 0x17 +#define MII_VSC8244_EXTCON1_INIT 0x0000 + +/* Vitesse Interrupt Mask Register */ +#define MII_VSC8244_IMASK 0x19 +#define MII_VSC8244_IMASK_IEN 0x8000 +#define MII_VSC8244_IMASK_SPEED 0x4000 +#define MII_VSC8244_IMASK_LINK 0x2000 +#define MII_VSC8244_IMASK_DUPLEX 0x1000 +#define MII_VSC8244_IMASK_MASK 0xf000 + +/* Vitesse Interrupt Status Register */ +#define MII_VSC8244_ISTAT 0x1a +#define MII_VSC8244_ISTAT_STATUS 0x8000 +#define MII_VSC8244_ISTAT_SPEED 0x4000 +#define MII_VSC8244_ISTAT_LINK 0x2000 +#define MII_VSC8244_ISTAT_DUPLEX 0x1000 + +/* Vitesse Auxiliary Control/Status Register */ +#define MII_VSC8244_AUX_CONSTAT 0x1c +#define MII_VSC8244_AUXCONSTAT_INIT 0x0004 +#define MII_VSC8244_AUXCONSTAT_DUPLEX 0x0020 +#define MII_VSC8244_AUXCONSTAT_SPEED 0x0018 +#define MII_VSC8244_AUXCONSTAT_GBIT 0x0010 +#define MII_VSC8244_AUXCONSTAT_100 0x0008 + +MODULE_DESCRIPTION("Vitesse PHY driver"); +MODULE_AUTHOR("Kriston Carson"); +MODULE_LICENSE("GPL"); + +static int vsc824x_config_init(struct phy_device *phydev) +{ + int err; + + err = phy_write(phydev, MII_VSC8244_AUX_CONSTAT, + MII_VSC8244_AUXCONSTAT_INIT); + if (err < 0) + return err; + + err = phy_write(phydev, MII_VSC8244_EXT_CON1, + MII_VSC8244_EXTCON1_INIT); + return err; +} + +static int vsc824x_ack_interrupt(struct phy_device *phydev) +{ + int err = phy_read(phydev, MII_VSC8244_ISTAT); + + return (err < 0) ? err : 0; +} + +static int vsc824x_config_intr(struct phy_device *phydev) +{ + int err; + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) + err = phy_write(phydev, MII_VSC8244_IMASK, + MII_VSC8244_IMASK_MASK); + else + err = phy_write(phydev, MII_VSC8244_IMASK, 0); + return err; +} + +/* Vitesse 824x */ +static struct phy_driver vsc8244_driver = { + .phy_id = 0x000fc6c2, + .name = "Vitesse VSC8244", + .phy_id_mask = 0x000fffc0, + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_init = &vsc824x_config_init, + .config_aneg = &genphy_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &vsc824x_ack_interrupt, + .config_intr = &vsc824x_config_intr, + .driver = { .owner = THIS_MODULE,}, +}; + +static int __init vsc8244_init(void) +{ + return phy_driver_register(&vsc8244_driver); +} + +static void __exit vsc8244_exit(void) +{ + phy_driver_unregister(&vsc8244_driver); +} + +module_init(vsc8244_init); +module_exit(vsc8244_exit); diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c new file mode 100644 index 000000000..4438fe8c9 --- /dev/null +++ b/drivers/net/smc911x.c @@ -0,0 +1,2306 @@ +/* + * smc911x.c + * This is a driver for SMSC's LAN911{5,6,7,8} single-chip Ethernet devices. + * + * Copyright (C) 2005 Sensoria Corp + * Derived from the unified SMC91x driver by Nicolas Pitre + * and the smsc911x.c reference driver by SMSC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Arguments: + * watchdog = TX watchdog timeout + * tx_fifo_kb = Size of TX FIFO in KB + * + * History: + * 04/16/05 Dustin McIntire Initial version + */ +static const char version[] = + "smc911x.c: v1.0 04-16-2005 by Dustin McIntire <dustin@sensoria.com>\n"; + +/* Debugging options */ +#define ENABLE_SMC_DEBUG_RX 0 +#define ENABLE_SMC_DEBUG_TX 0 +#define ENABLE_SMC_DEBUG_DMA 0 +#define ENABLE_SMC_DEBUG_PKTS 0 +#define ENABLE_SMC_DEBUG_MISC 0 +#define ENABLE_SMC_DEBUG_FUNC 0 + +#define SMC_DEBUG_RX ((ENABLE_SMC_DEBUG_RX ? 1 : 0) << 0) +#define SMC_DEBUG_TX ((ENABLE_SMC_DEBUG_TX ? 1 : 0) << 1) +#define SMC_DEBUG_DMA ((ENABLE_SMC_DEBUG_DMA ? 1 : 0) << 2) +#define SMC_DEBUG_PKTS ((ENABLE_SMC_DEBUG_PKTS ? 1 : 0) << 3) +#define SMC_DEBUG_MISC ((ENABLE_SMC_DEBUG_MISC ? 1 : 0) << 4) +#define SMC_DEBUG_FUNC ((ENABLE_SMC_DEBUG_FUNC ? 1 : 0) << 5) + +#ifndef SMC_DEBUG +#define SMC_DEBUG ( SMC_DEBUG_RX | \ + SMC_DEBUG_TX | \ + SMC_DEBUG_DMA | \ + SMC_DEBUG_PKTS | \ + SMC_DEBUG_MISC | \ + SMC_DEBUG_FUNC \ + ) +#endif + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/errno.h> +#include <linux/ioport.h> +#include <linux/crc32.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> +#include <linux/ethtool.h> +#include <linux/mii.h> +#include <linux/workqueue.h> + +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> + +#include <asm/io.h> +#include <asm/irq.h> + +#include "smc911x.h" + +/* + * Transmit timeout, default 5 seconds. + */ +static int watchdog = 5000; +module_param(watchdog, int, 0400); +MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds"); + +static int tx_fifo_kb=8; +module_param(tx_fifo_kb, int, 0400); +MODULE_PARM_DESC(tx_fifo_kb,"transmit FIFO size in KB (1<x<15)(default=8)"); + +MODULE_LICENSE("GPL"); + +/* + * The internal workings of the driver. If you are changing anything + * here with the SMC stuff, you should have the datasheet and know + * what you are doing. + */ +#define CARDNAME "smc911x" + +/* + * Use power-down feature of the chip + */ +#define POWER_DOWN 1 + + +/* store this information for the driver.. */ +struct smc911x_local { + /* + * If I have to wait until the DMA is finished and ready to reload a + * packet, I will store the skbuff here. Then, the DMA will send it + * out and free it. + */ + struct sk_buff *pending_tx_skb; + + /* + * these are things that the kernel wants me to keep, so users + * can find out semi-useless statistics of how well the card is + * performing + */ + struct net_device_stats stats; + + /* version/revision of the SMC911x chip */ + u16 version; + u16 revision; + + /* FIFO sizes */ + int tx_fifo_kb; + int tx_fifo_size; + int rx_fifo_size; + int afc_cfg; + + /* Contains the current active receive/phy mode */ + int ctl_rfduplx; + int ctl_rspeed; + + u32 msg_enable; + u32 phy_type; + struct mii_if_info mii; + + /* work queue */ + struct work_struct phy_configure; + int work_pending; + + int tx_throttle; + spinlock_t lock; + +#ifdef SMC_USE_DMA + /* DMA needs the physical address of the chip */ + u_long physaddr; + int rxdma; + int txdma; + int rxdma_active; + int txdma_active; + struct sk_buff *current_rx_skb; + struct sk_buff *current_tx_skb; + struct device *dev; +#endif +}; + +#if SMC_DEBUG > 0 +#define DBG(n, args...) \ + do { \ + if (SMC_DEBUG & (n)) \ + printk(args); \ + } while (0) + +#define PRINTK(args...) printk(args) +#else +#define DBG(n, args...) do { } while (0) +#define PRINTK(args...) printk(KERN_DEBUG args) +#endif + +#if SMC_DEBUG_PKTS > 0 +static void PRINT_PKT(u_char *buf, int length) +{ + int i; + int remainder; + int lines; + + lines = length / 16; + remainder = length % 16; + + for (i = 0; i < lines ; i ++) { + int cur; + for (cur = 0; cur < 8; cur++) { + u_char a, b; + a = *buf++; + b = *buf++; + printk("%02x%02x ", a, b); + } + printk("\n"); + } + for (i = 0; i < remainder/2 ; i++) { + u_char a, b; + a = *buf++; + b = *buf++; + printk("%02x%02x ", a, b); + } + printk("\n"); +} +#else +#define PRINT_PKT(x...) do { } while (0) +#endif + + +/* this enables an interrupt in the interrupt mask register */ +#define SMC_ENABLE_INT(x) do { \ + unsigned int __mask; \ + unsigned long __flags; \ + spin_lock_irqsave(&lp->lock, __flags); \ + __mask = SMC_GET_INT_EN(); \ + __mask |= (x); \ + SMC_SET_INT_EN(__mask); \ + spin_unlock_irqrestore(&lp->lock, __flags); \ +} while (0) + +/* this disables an interrupt from the interrupt mask register */ +#define SMC_DISABLE_INT(x) do { \ + unsigned int __mask; \ + unsigned long __flags; \ + spin_lock_irqsave(&lp->lock, __flags); \ + __mask = SMC_GET_INT_EN(); \ + __mask &= ~(x); \ + SMC_SET_INT_EN(__mask); \ + spin_unlock_irqrestore(&lp->lock, __flags); \ +} while (0) + +/* + * this does a soft reset on the device + */ +static void smc911x_reset(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); + unsigned int reg, timeout=0, resets=1; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + /* Take out of PM setting first */ + if ((SMC_GET_PMT_CTRL() & PMT_CTRL_READY_) == 0) { + /* Write to the bytetest will take out of powerdown */ + SMC_SET_BYTE_TEST(0); + timeout=10; + do { + udelay(10); + reg = SMC_GET_PMT_CTRL() & PMT_CTRL_READY_; + } while ( timeout-- && !reg); + if (timeout == 0) { + PRINTK("%s: smc911x_reset timeout waiting for PM restore\n", dev->name); + return; + } + } + + /* Disable all interrupts */ + spin_lock_irqsave(&lp->lock, flags); + SMC_SET_INT_EN(0); + spin_unlock_irqrestore(&lp->lock, flags); + + while (resets--) { + SMC_SET_HW_CFG(HW_CFG_SRST_); + timeout=10; + do { + udelay(10); + reg = SMC_GET_HW_CFG(); + /* If chip indicates reset timeout then try again */ + if (reg & HW_CFG_SRST_TO_) { + PRINTK("%s: chip reset timeout, retrying...\n", dev->name); + resets++; + break; + } + } while ( timeout-- && (reg & HW_CFG_SRST_)); + } + if (timeout == 0) { + PRINTK("%s: smc911x_reset timeout waiting for reset\n", dev->name); + return; + } + + /* make sure EEPROM has finished loading before setting GPIO_CFG */ + timeout=1000; + while ( timeout-- && (SMC_GET_E2P_CMD() & E2P_CMD_EPC_BUSY_)) { + udelay(10); + } + if (timeout == 0){ + PRINTK("%s: smc911x_reset timeout waiting for EEPROM busy\n", dev->name); + return; + } + + /* Initialize interrupts */ + SMC_SET_INT_EN(0); + SMC_ACK_INT(-1); + + /* Reset the FIFO level and flow control settings */ + SMC_SET_HW_CFG((lp->tx_fifo_kb & 0xF) << 16); +//TODO: Figure out what appropriate pause time is + SMC_SET_FLOW(FLOW_FCPT_ | FLOW_FCEN_); + SMC_SET_AFC_CFG(lp->afc_cfg); + + + /* Set to LED outputs */ + SMC_SET_GPIO_CFG(0x70070000); + + /* + * Deassert IRQ for 1*10us for edge type interrupts + * and drive IRQ pin push-pull + */ + SMC_SET_IRQ_CFG( (1 << 24) | INT_CFG_IRQ_EN_ | INT_CFG_IRQ_TYPE_ ); + + /* clear anything saved */ + if (lp->pending_tx_skb != NULL) { + dev_kfree_skb (lp->pending_tx_skb); + lp->pending_tx_skb = NULL; + lp->stats.tx_errors++; + lp->stats.tx_aborted_errors++; + } +} + +/* + * Enable Interrupts, Receive, and Transmit + */ +static void smc911x_enable(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); + unsigned mask, cfg, cr; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + SMC_SET_MAC_ADDR(dev->dev_addr); + + /* Enable TX */ + cfg = SMC_GET_HW_CFG(); + cfg &= HW_CFG_TX_FIF_SZ_ | 0xFFF; + cfg |= HW_CFG_SF_; + SMC_SET_HW_CFG(cfg); + SMC_SET_FIFO_TDA(0xFF); + /* Update TX stats on every 64 packets received or every 1 sec */ + SMC_SET_FIFO_TSL(64); + SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000); + + spin_lock_irqsave(&lp->lock, flags); + SMC_GET_MAC_CR(cr); + cr |= MAC_CR_TXEN_ | MAC_CR_HBDIS_; + SMC_SET_MAC_CR(cr); + SMC_SET_TX_CFG(TX_CFG_TX_ON_); + spin_unlock_irqrestore(&lp->lock, flags); + + /* Add 2 byte padding to start of packets */ + SMC_SET_RX_CFG((2<<8) & RX_CFG_RXDOFF_); + + /* Turn on receiver and enable RX */ + if (cr & MAC_CR_RXEN_) + DBG(SMC_DEBUG_RX, "%s: Receiver already enabled\n", dev->name); + + spin_lock_irqsave(&lp->lock, flags); + SMC_SET_MAC_CR( cr | MAC_CR_RXEN_ ); + spin_unlock_irqrestore(&lp->lock, flags); + + /* Interrupt on every received packet */ + SMC_SET_FIFO_RSA(0x01); + SMC_SET_FIFO_RSL(0x00); + + /* now, enable interrupts */ + mask = INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_ | INT_EN_RSFL_EN_ | + INT_EN_GPT_INT_EN_ | INT_EN_RXDFH_INT_EN_ | INT_EN_RXE_EN_ | + INT_EN_PHY_INT_EN_; + if (IS_REV_A(lp->revision)) + mask|=INT_EN_RDFL_EN_; + else { + mask|=INT_EN_RDFO_EN_; + } + SMC_ENABLE_INT(mask); +} + +/* + * this puts the device in an inactive state + */ +static void smc911x_shutdown(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); + unsigned cr; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", CARDNAME, __FUNCTION__); + + /* Disable IRQ's */ + SMC_SET_INT_EN(0); + + /* Turn of Rx and TX */ + spin_lock_irqsave(&lp->lock, flags); + SMC_GET_MAC_CR(cr); + cr &= ~(MAC_CR_TXEN_ | MAC_CR_RXEN_ | MAC_CR_HBDIS_); + SMC_SET_MAC_CR(cr); + SMC_SET_TX_CFG(TX_CFG_STOP_TX_); + spin_unlock_irqrestore(&lp->lock, flags); +} + +static inline void smc911x_drop_pkt(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int fifo_count, timeout, reg; + + DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", CARDNAME, __FUNCTION__); + fifo_count = SMC_GET_RX_FIFO_INF() & 0xFFFF; + if (fifo_count <= 4) { + /* Manually dump the packet data */ + while (fifo_count--) + SMC_GET_RX_FIFO(); + } else { + /* Fast forward through the bad packet */ + SMC_SET_RX_DP_CTRL(RX_DP_CTRL_FFWD_BUSY_); + timeout=50; + do { + udelay(10); + reg = SMC_GET_RX_DP_CTRL() & RX_DP_CTRL_FFWD_BUSY_; + } while ( timeout-- && reg); + if (timeout == 0) { + PRINTK("%s: timeout waiting for RX fast forward\n", dev->name); + } + } +} + +/* + * This is the procedure to handle the receipt of a packet. + * It should be called after checking for packet presence in + * the RX status FIFO. It must be called with the spin lock + * already held. + */ +static inline void smc911x_rcv(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + unsigned int pkt_len, status; + struct sk_buff *skb; + unsigned char *data; + + DBG(SMC_DEBUG_FUNC | SMC_DEBUG_RX, "%s: --> %s\n", + dev->name, __FUNCTION__); + status = SMC_GET_RX_STS_FIFO(); + DBG(SMC_DEBUG_RX, "%s: Rx pkt len %d status 0x%08x \n", + dev->name, (status & 0x3fff0000) >> 16, status & 0xc000ffff); + pkt_len = (status & RX_STS_PKT_LEN_) >> 16; + if (status & RX_STS_ES_) { + /* Deal with a bad packet */ + lp->stats.rx_errors++; + if (status & RX_STS_CRC_ERR_) + lp->stats.rx_crc_errors++; + else { + if (status & RX_STS_LEN_ERR_) + lp->stats.rx_length_errors++; + if (status & RX_STS_MCAST_) + lp->stats.multicast++; + } + /* Remove the bad packet data from the RX FIFO */ + smc911x_drop_pkt(dev); + } else { + /* Receive a valid packet */ + /* Alloc a buffer with extra room for DMA alignment */ + skb=dev_alloc_skb(pkt_len+32); + if (unlikely(skb == NULL)) { + PRINTK( "%s: Low memory, rcvd packet dropped.\n", + dev->name); + lp->stats.rx_dropped++; + smc911x_drop_pkt(dev); + return; + } + /* Align IP header to 32 bits + * Note that the device is configured to add a 2 + * byte padding to the packet start, so we really + * want to write to the orignal data pointer */ + data = skb->data; + skb_reserve(skb, 2); + skb_put(skb,pkt_len-4); +#ifdef SMC_USE_DMA + { + unsigned int fifo; + /* Lower the FIFO threshold if possible */ + fifo = SMC_GET_FIFO_INT(); + if (fifo & 0xFF) fifo--; + DBG(SMC_DEBUG_RX, "%s: Setting RX stat FIFO threshold to %d\n", + dev->name, fifo & 0xff); + SMC_SET_FIFO_INT(fifo); + /* Setup RX DMA */ + SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN16_ | ((2<<8) & RX_CFG_RXDOFF_)); + lp->rxdma_active = 1; + lp->current_rx_skb = skb; + SMC_PULL_DATA(data, (pkt_len+2+15) & ~15); + /* Packet processing deferred to DMA RX interrupt */ + } +#else + SMC_SET_RX_CFG(RX_CFG_RX_END_ALGN4_ | ((2<<8) & RX_CFG_RXDOFF_)); + SMC_PULL_DATA(data, pkt_len+2+3); + + DBG(SMC_DEBUG_PKTS, "%s: Received packet\n", dev->name,); + PRINT_PKT(data, ((pkt_len - 4) <= 64) ? pkt_len - 4 : 64); + dev->last_rx = jiffies; + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + lp->stats.rx_packets++; + lp->stats.rx_bytes += pkt_len-4; +#endif + } +} + +/* + * This is called to actually send a packet to the chip. + */ +static void smc911x_hardware_send_pkt(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + struct sk_buff *skb; + unsigned int cmdA, cmdB, len; + unsigned char *buf; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", dev->name, __FUNCTION__); + BUG_ON(lp->pending_tx_skb == NULL); + + skb = lp->pending_tx_skb; + lp->pending_tx_skb = NULL; + + /* cmdA {25:24] data alignment [20:16] start offset [10:0] buffer length */ + /* cmdB {31:16] pkt tag [10:0] length */ +#ifdef SMC_USE_DMA + /* 16 byte buffer alignment mode */ + buf = (char*)((u32)(skb->data) & ~0xF); + len = (skb->len + 0xF + ((u32)skb->data & 0xF)) & ~0xF; + cmdA = (1<<24) | (((u32)skb->data & 0xF)<<16) | + TX_CMD_A_INT_FIRST_SEG_ | TX_CMD_A_INT_LAST_SEG_ | + skb->len; +#else + buf = (char*)((u32)skb->data & ~0x3); + len = (skb->len + 3 + ((u32)skb->data & 3)) & ~0x3; + cmdA = (((u32)skb->data & 0x3) << 16) | + TX_CMD_A_INT_FIRST_SEG_ | TX_CMD_A_INT_LAST_SEG_ | + skb->len; +#endif + /* tag is packet length so we can use this in stats update later */ + cmdB = (skb->len << 16) | (skb->len & 0x7FF); + + DBG(SMC_DEBUG_TX, "%s: TX PKT LENGTH 0x%04x (%d) BUF 0x%p CMDA 0x%08x CMDB 0x%08x\n", + dev->name, len, len, buf, cmdA, cmdB); + SMC_SET_TX_FIFO(cmdA); + SMC_SET_TX_FIFO(cmdB); + + DBG(SMC_DEBUG_PKTS, "%s: Transmitted packet\n", dev->name); + PRINT_PKT(buf, len <= 64 ? len : 64); + + /* Send pkt via PIO or DMA */ +#ifdef SMC_USE_DMA + lp->current_tx_skb = skb; + SMC_PUSH_DATA(buf, len); + /* DMA complete IRQ will free buffer and set jiffies */ +#else + SMC_PUSH_DATA(buf, len); + dev->trans_start = jiffies; + dev_kfree_skb(skb); +#endif + spin_lock_irqsave(&lp->lock, flags); + if (!lp->tx_throttle) { + netif_wake_queue(dev); + } + spin_unlock_irqrestore(&lp->lock, flags); + SMC_ENABLE_INT(INT_EN_TDFA_EN_ | INT_EN_TSFL_EN_); +} + +/* + * Since I am not sure if I will have enough room in the chip's ram + * to store the packet, I call this routine which either sends it + * now, or set the card to generates an interrupt when ready + * for the packet. + */ +static int smc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + unsigned int free; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", + dev->name, __FUNCTION__); + + BUG_ON(lp->pending_tx_skb != NULL); + + free = SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TDFREE_; + DBG(SMC_DEBUG_TX, "%s: TX free space %d\n", dev->name, free); + + /* Turn off the flow when running out of space in FIFO */ + if (free <= SMC911X_TX_FIFO_LOW_THRESHOLD) { + DBG(SMC_DEBUG_TX, "%s: Disabling data flow due to low FIFO space (%d)\n", + dev->name, free); + spin_lock_irqsave(&lp->lock, flags); + /* Reenable when at least 1 packet of size MTU present */ + SMC_SET_FIFO_TDA((SMC911X_TX_FIFO_LOW_THRESHOLD)/64); + lp->tx_throttle = 1; + netif_stop_queue(dev); + spin_unlock_irqrestore(&lp->lock, flags); + } + + /* Drop packets when we run out of space in TX FIFO + * Account for overhead required for: + * + * Tx command words 8 bytes + * Start offset 15 bytes + * End padding 15 bytes + */ + if (unlikely(free < (skb->len + 8 + 15 + 15))) { + printk("%s: No Tx free space %d < %d\n", + dev->name, free, skb->len); + lp->pending_tx_skb = NULL; + lp->stats.tx_errors++; + lp->stats.tx_dropped++; + dev_kfree_skb(skb); + return 0; + } + +#ifdef SMC_USE_DMA + { + /* If the DMA is already running then defer this packet Tx until + * the DMA IRQ starts it + */ + spin_lock_irqsave(&lp->lock, flags); + if (lp->txdma_active) { + DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: Tx DMA running, deferring packet\n", dev->name); + lp->pending_tx_skb = skb; + netif_stop_queue(dev); + spin_unlock_irqrestore(&lp->lock, flags); + return 0; + } else { + DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: Activating Tx DMA\n", dev->name); + lp->txdma_active = 1; + } + spin_unlock_irqrestore(&lp->lock, flags); + } +#endif + lp->pending_tx_skb = skb; + smc911x_hardware_send_pkt(dev); + + return 0; +} + +/* + * This handles a TX status interrupt, which is only called when: + * - a TX error occurred, or + * - TX of a packet completed. + */ +static void smc911x_tx(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); + unsigned int tx_status; + + DBG(SMC_DEBUG_FUNC | SMC_DEBUG_TX, "%s: --> %s\n", + dev->name, __FUNCTION__); + + /* Collect the TX status */ + while (((SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TSUSED_) >> 16) != 0) { + DBG(SMC_DEBUG_TX, "%s: Tx stat FIFO used 0x%04x\n", + dev->name, + (SMC_GET_TX_FIFO_INF() & TX_FIFO_INF_TSUSED_) >> 16); + tx_status = SMC_GET_TX_STS_FIFO(); + lp->stats.tx_packets++; + lp->stats.tx_bytes+=tx_status>>16; + DBG(SMC_DEBUG_TX, "%s: Tx FIFO tag 0x%04x status 0x%04x\n", + dev->name, (tx_status & 0xffff0000) >> 16, + tx_status & 0x0000ffff); + /* count Tx errors, but ignore lost carrier errors when in + * full-duplex mode */ + if ((tx_status & TX_STS_ES_) && !(lp->ctl_rfduplx && + !(tx_status & 0x00000306))) { + lp->stats.tx_errors++; + } + if (tx_status & TX_STS_MANY_COLL_) { + lp->stats.collisions+=16; + lp->stats.tx_aborted_errors++; + } else { + lp->stats.collisions+=(tx_status & TX_STS_COLL_CNT_) >> 3; + } + /* carrier error only has meaning for half-duplex communication */ + if ((tx_status & (TX_STS_LOC_ | TX_STS_NO_CARR_)) && + !lp->ctl_rfduplx) { + lp->stats.tx_carrier_errors++; + } + if (tx_status & TX_STS_LATE_COLL_) { + lp->stats.collisions++; + lp->stats.tx_aborted_errors++; + } + } +} + + +/*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/ +/* + * Reads a register from the MII Management serial interface + */ + +static int smc911x_phy_read(struct net_device *dev, int phyaddr, int phyreg) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int phydata; + + SMC_GET_MII(phyreg, phyaddr, phydata); + + DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%02x, phydata=0x%04x\n", + __FUNCTION__, phyaddr, phyreg, phydata); + return phydata; +} + + +/* + * Writes a register to the MII Management serial interface + */ +static void smc911x_phy_write(struct net_device *dev, int phyaddr, int phyreg, + int phydata) +{ + unsigned long ioaddr = dev->base_addr; + + DBG(SMC_DEBUG_MISC, "%s: phyaddr=0x%x, phyreg=0x%x, phydata=0x%x\n", + __FUNCTION__, phyaddr, phyreg, phydata); + + SMC_SET_MII(phyreg, phyaddr, phydata); +} + +/* + * Finds and reports the PHY address (115 and 117 have external + * PHY interface 118 has internal only + */ +static void smc911x_phy_detect(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); + int phyaddr; + unsigned int cfg, id1, id2; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + lp->phy_type = 0; + + /* + * Scan all 32 PHY addresses if necessary, starting at + * PHY#1 to PHY#31, and then PHY#0 last. + */ + switch(lp->version) { + case 0x115: + case 0x117: + cfg = SMC_GET_HW_CFG(); + if (cfg & HW_CFG_EXT_PHY_DET_) { + cfg &= ~HW_CFG_PHY_CLK_SEL_; + cfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_; + SMC_SET_HW_CFG(cfg); + udelay(10); /* Wait for clocks to stop */ + + cfg |= HW_CFG_EXT_PHY_EN_; + SMC_SET_HW_CFG(cfg); + udelay(10); /* Wait for clocks to stop */ + + cfg &= ~HW_CFG_PHY_CLK_SEL_; + cfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_; + SMC_SET_HW_CFG(cfg); + udelay(10); /* Wait for clocks to stop */ + + cfg |= HW_CFG_SMI_SEL_; + SMC_SET_HW_CFG(cfg); + + for (phyaddr = 1; phyaddr < 32; ++phyaddr) { + + /* Read the PHY identifiers */ + SMC_GET_PHY_ID1(phyaddr & 31, id1); + SMC_GET_PHY_ID2(phyaddr & 31, id2); + + /* Make sure it is a valid identifier */ + if (id1 != 0x0000 && id1 != 0xffff && + id1 != 0x8000 && id2 != 0x0000 && + id2 != 0xffff && id2 != 0x8000) { + /* Save the PHY's address */ + lp->mii.phy_id = phyaddr & 31; + lp->phy_type = id1 << 16 | id2; + break; + } + } + } + default: + /* Internal media only */ + SMC_GET_PHY_ID1(1, id1); + SMC_GET_PHY_ID2(1, id2); + /* Save the PHY's address */ + lp->mii.phy_id = 1; + lp->phy_type = id1 << 16 | id2; + } + + DBG(SMC_DEBUG_MISC, "%s: phy_id1=0x%x, phy_id2=0x%x phyaddr=0x%d\n", + dev->name, id1, id2, lp->mii.phy_id); +} + +/* + * Sets the PHY to a configuration as determined by the user. + * Called with spin_lock held. + */ +static int smc911x_phy_fixed(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int phyaddr = lp->mii.phy_id; + int bmcr; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + /* Enter Link Disable state */ + SMC_GET_PHY_BMCR(phyaddr, bmcr); + bmcr |= BMCR_PDOWN; + SMC_SET_PHY_BMCR(phyaddr, bmcr); + + /* + * Set our fixed capabilities + * Disable auto-negotiation + */ + bmcr &= ~BMCR_ANENABLE; + if (lp->ctl_rfduplx) + bmcr |= BMCR_FULLDPLX; + + if (lp->ctl_rspeed == 100) + bmcr |= BMCR_SPEED100; + + /* Write our capabilities to the phy control register */ + SMC_SET_PHY_BMCR(phyaddr, bmcr); + + /* Re-Configure the Receive/Phy Control register */ + bmcr &= ~BMCR_PDOWN; + SMC_SET_PHY_BMCR(phyaddr, bmcr); + + return 1; +} + +/* + * smc911x_phy_reset - reset the phy + * @dev: net device + * @phy: phy address + * + * Issue a software reset for the specified PHY and + * wait up to 100ms for the reset to complete. We should + * not access the PHY for 50ms after issuing the reset. + * + * The time to wait appears to be dependent on the PHY. + * + */ +static int smc911x_phy_reset(struct net_device *dev, int phy) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int timeout; + unsigned long flags; + unsigned int reg; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__); + + spin_lock_irqsave(&lp->lock, flags); + reg = SMC_GET_PMT_CTRL(); + reg &= ~0xfffff030; + reg |= PMT_CTRL_PHY_RST_; + SMC_SET_PMT_CTRL(reg); + spin_unlock_irqrestore(&lp->lock, flags); + for (timeout = 2; timeout; timeout--) { + msleep(50); + spin_lock_irqsave(&lp->lock, flags); + reg = SMC_GET_PMT_CTRL(); + spin_unlock_irqrestore(&lp->lock, flags); + if (!(reg & PMT_CTRL_PHY_RST_)) { + /* extra delay required because the phy may + * not be completed with its reset + * when PHY_BCR_RESET_ is cleared. 256us + * should suffice, but use 500us to be safe + */ + udelay(500); + break; + } + } + + return reg & PMT_CTRL_PHY_RST_; +} + +/* + * smc911x_phy_powerdown - powerdown phy + * @dev: net device + * @phy: phy address + * + * Power down the specified PHY + */ +static void smc911x_phy_powerdown(struct net_device *dev, int phy) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int bmcr; + + /* Enter Link Disable state */ + SMC_GET_PHY_BMCR(phy, bmcr); + bmcr |= BMCR_PDOWN; + SMC_SET_PHY_BMCR(phy, bmcr); +} + +/* + * smc911x_phy_check_media - check the media status and adjust BMCR + * @dev: net device + * @init: set true for initialisation + * + * Select duplex mode depending on negotiation state. This + * also updates our carrier state. + */ +static void smc911x_phy_check_media(struct net_device *dev, int init) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int phyaddr = lp->mii.phy_id; + unsigned int bmcr, cr; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) { + /* duplex state has changed */ + SMC_GET_PHY_BMCR(phyaddr, bmcr); + SMC_GET_MAC_CR(cr); + if (lp->mii.full_duplex) { + DBG(SMC_DEBUG_MISC, "%s: Configuring for full-duplex mode\n", dev->name); + bmcr |= BMCR_FULLDPLX; + cr |= MAC_CR_RCVOWN_; + } else { + DBG(SMC_DEBUG_MISC, "%s: Configuring for half-duplex mode\n", dev->name); + bmcr &= ~BMCR_FULLDPLX; + cr &= ~MAC_CR_RCVOWN_; + } + SMC_SET_PHY_BMCR(phyaddr, bmcr); + SMC_SET_MAC_CR(cr); + } +} + +/* + * Configures the specified PHY through the MII management interface + * using Autonegotiation. + * Calls smc911x_phy_fixed() if the user has requested a certain config. + * If RPC ANEG bit is set, the media selection is dependent purely on + * the selection by the MII (either in the MII BMCR reg or the result + * of autonegotiation.) If the RPC ANEG bit is cleared, the selection + * is controlled by the RPC SPEED and RPC DPLX bits. + */ +static void smc911x_phy_configure(void *data) +{ + struct net_device *dev = data; + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int phyaddr = lp->mii.phy_id; + int my_phy_caps; /* My PHY capabilities */ + int my_ad_caps; /* My Advertised capabilities */ + int status; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s()\n", dev->name, __FUNCTION__); + + /* + * We should not be called if phy_type is zero. + */ + if (lp->phy_type == 0) + goto smc911x_phy_configure_exit; + + if (smc911x_phy_reset(dev, phyaddr)) { + printk("%s: PHY reset timed out\n", dev->name); + goto smc911x_phy_configure_exit; + } + spin_lock_irqsave(&lp->lock, flags); + + /* + * Enable PHY Interrupts (for register 18) + * Interrupts listed here are enabled + */ + SMC_SET_PHY_INT_MASK(phyaddr, PHY_INT_MASK_ENERGY_ON_ | + PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_REMOTE_FAULT_ | + PHY_INT_MASK_LINK_DOWN_); + + /* If the user requested no auto neg, then go set his request */ + if (lp->mii.force_media) { + smc911x_phy_fixed(dev); + goto smc911x_phy_configure_exit; + } + + /* Copy our capabilities from MII_BMSR to MII_ADVERTISE */ + SMC_GET_PHY_BMSR(phyaddr, my_phy_caps); + if (!(my_phy_caps & BMSR_ANEGCAPABLE)) { + printk(KERN_INFO "Auto negotiation NOT supported\n"); + smc911x_phy_fixed(dev); + goto smc911x_phy_configure_exit; + } + + /* CSMA capable w/ both pauses */ + my_ad_caps = ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + + if (my_phy_caps & BMSR_100BASE4) + my_ad_caps |= ADVERTISE_100BASE4; + if (my_phy_caps & BMSR_100FULL) + my_ad_caps |= ADVERTISE_100FULL; + if (my_phy_caps & BMSR_100HALF) + my_ad_caps |= ADVERTISE_100HALF; + if (my_phy_caps & BMSR_10FULL) + my_ad_caps |= ADVERTISE_10FULL; + if (my_phy_caps & BMSR_10HALF) + my_ad_caps |= ADVERTISE_10HALF; + + /* Disable capabilities not selected by our user */ + if (lp->ctl_rspeed != 100) + my_ad_caps &= ~(ADVERTISE_100BASE4|ADVERTISE_100FULL|ADVERTISE_100HALF); + + if (!lp->ctl_rfduplx) + my_ad_caps &= ~(ADVERTISE_100FULL|ADVERTISE_10FULL); + + /* Update our Auto-Neg Advertisement Register */ + SMC_SET_PHY_MII_ADV(phyaddr, my_ad_caps); + lp->mii.advertising = my_ad_caps; + + /* + * Read the register back. Without this, it appears that when + * auto-negotiation is restarted, sometimes it isn't ready and + * the link does not come up. + */ + udelay(10); + SMC_GET_PHY_MII_ADV(phyaddr, status); + + DBG(SMC_DEBUG_MISC, "%s: phy caps=0x%04x\n", dev->name, my_phy_caps); + DBG(SMC_DEBUG_MISC, "%s: phy advertised caps=0x%04x\n", dev->name, my_ad_caps); + + /* Restart auto-negotiation process in order to advertise my caps */ + SMC_SET_PHY_BMCR(phyaddr, BMCR_ANENABLE | BMCR_ANRESTART); + + smc911x_phy_check_media(dev, 1); + +smc911x_phy_configure_exit: + spin_unlock_irqrestore(&lp->lock, flags); + lp->work_pending = 0; +} + +/* + * smc911x_phy_interrupt + * + * Purpose: Handle interrupts relating to PHY register 18. This is + * called from the "hard" interrupt handler under our private spinlock. + */ +static void smc911x_phy_interrupt(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int phyaddr = lp->mii.phy_id; + int status; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + if (lp->phy_type == 0) + return; + + smc911x_phy_check_media(dev, 0); + /* read to clear status bits */ + SMC_GET_PHY_INT_SRC(phyaddr,status); + DBG(SMC_DEBUG_MISC, "%s: PHY interrupt status 0x%04x\n", + dev->name, status & 0xffff); + DBG(SMC_DEBUG_MISC, "%s: AFC_CFG 0x%08x\n", + dev->name, SMC_GET_AFC_CFG()); +} + +/*--- END PHY CONTROL AND CONFIGURATION-------------------------------------*/ + +/* + * This is the main routine of the driver, to handle the device when + * it needs some attention. + */ +static irqreturn_t smc911x_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = dev_id; + unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); + unsigned int status, mask, timeout; + unsigned int rx_overrun=0, cr, pkts; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + spin_lock_irqsave(&lp->lock, flags); + + /* Spurious interrupt check */ + if ((SMC_GET_IRQ_CFG() & (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) != + (INT_CFG_IRQ_INT_ | INT_CFG_IRQ_EN_)) { + spin_unlock_irqrestore(&lp->lock, flags); + return IRQ_NONE; + } + + mask = SMC_GET_INT_EN(); + SMC_SET_INT_EN(0); + + /* set a timeout value, so I don't stay here forever */ + timeout = 8; + + + do { + status = SMC_GET_INT(); + + DBG(SMC_DEBUG_MISC, "%s: INT 0x%08x MASK 0x%08x OUTSIDE MASK 0x%08x\n", + dev->name, status, mask, status & ~mask); + + status &= mask; + if (!status) + break; + + /* Handle SW interrupt condition */ + if (status & INT_STS_SW_INT_) { + SMC_ACK_INT(INT_STS_SW_INT_); + mask &= ~INT_EN_SW_INT_EN_; + } + /* Handle various error conditions */ + if (status & INT_STS_RXE_) { + SMC_ACK_INT(INT_STS_RXE_); + lp->stats.rx_errors++; + } + if (status & INT_STS_RXDFH_INT_) { + SMC_ACK_INT(INT_STS_RXDFH_INT_); + lp->stats.rx_dropped+=SMC_GET_RX_DROP(); + } + /* Undocumented interrupt-what is the right thing to do here? */ + if (status & INT_STS_RXDF_INT_) { + SMC_ACK_INT(INT_STS_RXDF_INT_); + } + + /* Rx Data FIFO exceeds set level */ + if (status & INT_STS_RDFL_) { + if (IS_REV_A(lp->revision)) { + rx_overrun=1; + SMC_GET_MAC_CR(cr); + cr &= ~MAC_CR_RXEN_; + SMC_SET_MAC_CR(cr); + DBG(SMC_DEBUG_RX, "%s: RX overrun\n", dev->name); + lp->stats.rx_errors++; + lp->stats.rx_fifo_errors++; + } + SMC_ACK_INT(INT_STS_RDFL_); + } + if (status & INT_STS_RDFO_) { + if (!IS_REV_A(lp->revision)) { + SMC_GET_MAC_CR(cr); + cr &= ~MAC_CR_RXEN_; + SMC_SET_MAC_CR(cr); + rx_overrun=1; + DBG(SMC_DEBUG_RX, "%s: RX overrun\n", dev->name); + lp->stats.rx_errors++; + lp->stats.rx_fifo_errors++; + } + SMC_ACK_INT(INT_STS_RDFO_); + } + /* Handle receive condition */ + if ((status & INT_STS_RSFL_) || rx_overrun) { + unsigned int fifo; + DBG(SMC_DEBUG_RX, "%s: RX irq\n", dev->name); + fifo = SMC_GET_RX_FIFO_INF(); + pkts = (fifo & RX_FIFO_INF_RXSUSED_) >> 16; + DBG(SMC_DEBUG_RX, "%s: Rx FIFO pkts %d, bytes %d\n", + dev->name, pkts, fifo & 0xFFFF ); + if (pkts != 0) { +#ifdef SMC_USE_DMA + unsigned int fifo; + if (lp->rxdma_active){ + DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA, + "%s: RX DMA active\n", dev->name); + /* The DMA is already running so up the IRQ threshold */ + fifo = SMC_GET_FIFO_INT() & ~0xFF; + fifo |= pkts & 0xFF; + DBG(SMC_DEBUG_RX, + "%s: Setting RX stat FIFO threshold to %d\n", + dev->name, fifo & 0xff); + SMC_SET_FIFO_INT(fifo); + } else +#endif + smc911x_rcv(dev); + } + SMC_ACK_INT(INT_STS_RSFL_); + } + /* Handle transmit FIFO available */ + if (status & INT_STS_TDFA_) { + DBG(SMC_DEBUG_TX, "%s: TX data FIFO space available irq\n", dev->name); + SMC_SET_FIFO_TDA(0xFF); + lp->tx_throttle = 0; +#ifdef SMC_USE_DMA + if (!lp->txdma_active) +#endif + netif_wake_queue(dev); + SMC_ACK_INT(INT_STS_TDFA_); + } + /* Handle transmit done condition */ +#if 1 + if (status & (INT_STS_TSFL_ | INT_STS_GPT_INT_)) { + DBG(SMC_DEBUG_TX | SMC_DEBUG_MISC, + "%s: Tx stat FIFO limit (%d) /GPT irq\n", + dev->name, (SMC_GET_FIFO_INT() & 0x00ff0000) >> 16); + smc911x_tx(dev); + SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000); + SMC_ACK_INT(INT_STS_TSFL_); + SMC_ACK_INT(INT_STS_TSFL_ | INT_STS_GPT_INT_); + } +#else + if (status & INT_STS_TSFL_) { + DBG(SMC_DEBUG_TX, "%s: TX status FIFO limit (%d) irq \n", dev->name, ); + smc911x_tx(dev); + SMC_ACK_INT(INT_STS_TSFL_); + } + + if (status & INT_STS_GPT_INT_) { + DBG(SMC_DEBUG_RX, "%s: IRQ_CFG 0x%08x FIFO_INT 0x%08x RX_CFG 0x%08x\n", + dev->name, + SMC_GET_IRQ_CFG(), + SMC_GET_FIFO_INT(), + SMC_GET_RX_CFG()); + DBG(SMC_DEBUG_RX, "%s: Rx Stat FIFO Used 0x%02x " + "Data FIFO Used 0x%04x Stat FIFO 0x%08x\n", + dev->name, + (SMC_GET_RX_FIFO_INF() & 0x00ff0000) >> 16, + SMC_GET_RX_FIFO_INF() & 0xffff, + SMC_GET_RX_STS_FIFO_PEEK()); + SMC_SET_GPT_CFG(GPT_CFG_TIMER_EN_ | 10000); + SMC_ACK_INT(INT_STS_GPT_INT_); + } +#endif + + /* Handle PHY interupt condition */ + if (status & INT_STS_PHY_INT_) { + DBG(SMC_DEBUG_MISC, "%s: PHY irq\n", dev->name); + smc911x_phy_interrupt(dev); + SMC_ACK_INT(INT_STS_PHY_INT_); + } + } while (--timeout); + + /* restore mask state */ + SMC_SET_INT_EN(mask); + + DBG(SMC_DEBUG_MISC, "%s: Interrupt done (%d loops)\n", + dev->name, 8-timeout); + + spin_unlock_irqrestore(&lp->lock, flags); + + DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, 8-timeout); + + return IRQ_HANDLED; +} + +#ifdef SMC_USE_DMA +static void +smc911x_tx_dma_irq(int dma, void *data, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *)data; + struct smc911x_local *lp = netdev_priv(dev); + struct sk_buff *skb = lp->current_tx_skb; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, "%s: TX DMA irq handler\n", dev->name); + /* Clear the DMA interrupt sources */ + SMC_DMA_ACK_IRQ(dev, dma); + BUG_ON(skb == NULL); + dma_unmap_single(NULL, tx_dmabuf, tx_dmalen, DMA_TO_DEVICE); + dev->trans_start = jiffies; + dev_kfree_skb_irq(skb); + lp->current_tx_skb = NULL; + if (lp->pending_tx_skb != NULL) + smc911x_hardware_send_pkt(dev); + else { + DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, + "%s: No pending Tx packets. DMA disabled\n", dev->name); + spin_lock_irqsave(&lp->lock, flags); + lp->txdma_active = 0; + if (!lp->tx_throttle) { + netif_wake_queue(dev); + } + spin_unlock_irqrestore(&lp->lock, flags); + } + + DBG(SMC_DEBUG_TX | SMC_DEBUG_DMA, + "%s: TX DMA irq completed\n", dev->name); +} +static void +smc911x_rx_dma_irq(int dma, void *data, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *)data; + unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); + struct sk_buff *skb = lp->current_rx_skb; + unsigned long flags; + unsigned int pkts; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA, "%s: RX DMA irq handler\n", dev->name); + /* Clear the DMA interrupt sources */ + SMC_DMA_ACK_IRQ(dev, dma); + dma_unmap_single(NULL, rx_dmabuf, rx_dmalen, DMA_FROM_DEVICE); + BUG_ON(skb == NULL); + lp->current_rx_skb = NULL; + PRINT_PKT(skb->data, skb->len); + dev->last_rx = jiffies; + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + lp->stats.rx_packets++; + lp->stats.rx_bytes += skb->len; + + spin_lock_irqsave(&lp->lock, flags); + pkts = (SMC_GET_RX_FIFO_INF() & RX_FIFO_INF_RXSUSED_) >> 16; + if (pkts != 0) { + smc911x_rcv(dev); + }else { + lp->rxdma_active = 0; + } + spin_unlock_irqrestore(&lp->lock, flags); + DBG(SMC_DEBUG_RX | SMC_DEBUG_DMA, + "%s: RX DMA irq completed. DMA RX FIFO PKTS %d\n", + dev->name, pkts); +} +#endif /* SMC_USE_DMA */ + +#ifdef CONFIG_NET_POLL_CONTROLLER +/* + * Polling receive - used by netconsole and other diagnostic tools + * to allow network i/o with interrupts disabled. + */ +static void smc911x_poll_controller(struct net_device *dev) +{ + disable_irq(dev->irq); + smc911x_interrupt(dev->irq, dev, NULL); + enable_irq(dev->irq); +} +#endif + +/* Our watchdog timed out. Called by the networking layer */ +static void smc911x_timeout(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int status, mask; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + spin_lock_irqsave(&lp->lock, flags); + status = SMC_GET_INT(); + mask = SMC_GET_INT_EN(); + spin_unlock_irqrestore(&lp->lock, flags); + DBG(SMC_DEBUG_MISC, "%s: INT 0x%02x MASK 0x%02x \n", + dev->name, status, mask); + + /* Dump the current TX FIFO contents and restart */ + mask = SMC_GET_TX_CFG(); + SMC_SET_TX_CFG(mask | TX_CFG_TXS_DUMP_ | TX_CFG_TXD_DUMP_); + /* + * Reconfiguring the PHY doesn't seem like a bad idea here, but + * smc911x_phy_configure() calls msleep() which calls schedule_timeout() + * which calls schedule(). Hence we use a work queue. + */ + if (lp->phy_type != 0) { + if (schedule_work(&lp->phy_configure)) { + lp->work_pending = 1; + } + } + + /* We can accept TX packets again */ + dev->trans_start = jiffies; + netif_wake_queue(dev); +} + +/* + * This routine will, depending on the values passed to it, + * either make it accept multicast packets, go into + * promiscuous mode (for TCPDUMP and cousins) or accept + * a select set of multicast packets + */ +static void smc911x_set_multicast_list(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + unsigned int multicast_table[2]; + unsigned int mcr, update_multicast = 0; + unsigned long flags; + /* table for flipping the order of 5 bits */ + static const unsigned char invert5[] = + {0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0C, 0x1C, + 0x02, 0x12, 0x0A, 0x1A, 0x06, 0x16, 0x0E, 0x1E, + 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0D, 0x1D, + 0x03, 0x13, 0x0B, 0x1B, 0x07, 0x17, 0x0F, 0x1F}; + + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + spin_lock_irqsave(&lp->lock, flags); + SMC_GET_MAC_CR(mcr); + spin_unlock_irqrestore(&lp->lock, flags); + + if (dev->flags & IFF_PROMISC) { + + DBG(SMC_DEBUG_MISC, "%s: RCR_PRMS\n", dev->name); + mcr |= MAC_CR_PRMS_; + } + /* + * Here, I am setting this to accept all multicast packets. + * I don't need to zero the multicast table, because the flag is + * checked before the table is + */ + else if (dev->flags & IFF_ALLMULTI || dev->mc_count > 16) { + DBG(SMC_DEBUG_MISC, "%s: RCR_ALMUL\n", dev->name); + mcr |= MAC_CR_MCPAS_; + } + + /* + * This sets the internal hardware table to filter out unwanted + * multicast packets before they take up memory. + * + * The SMC chip uses a hash table where the high 6 bits of the CRC of + * address are the offset into the table. If that bit is 1, then the + * multicast packet is accepted. Otherwise, it's dropped silently. + * + * To use the 6 bits as an offset into the table, the high 1 bit is + * the number of the 32 bit register, while the low 5 bits are the bit + * within that register. + */ + else if (dev->mc_count) { + int i; + struct dev_mc_list *cur_addr; + + /* Set the Hash perfec mode */ + mcr |= MAC_CR_HPFILT_; + + /* start with a table of all zeros: reject all */ + memset(multicast_table, 0, sizeof(multicast_table)); + + cur_addr = dev->mc_list; + for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) { + int position; + + /* do we have a pointer here? */ + if (!cur_addr) + break; + /* make sure this is a multicast address - + shouldn't this be a given if we have it here ? */ + if (!(*cur_addr->dmi_addr & 1)) + continue; + + /* only use the low order bits */ + position = crc32_le(~0, cur_addr->dmi_addr, 6) & 0x3f; + + /* do some messy swapping to put the bit in the right spot */ + multicast_table[invert5[position&0x1F]&0x1] |= + (1<<invert5[(position>>1)&0x1F]); + } + + /* be sure I get rid of flags I might have set */ + mcr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_); + + /* now, the table can be loaded into the chipset */ + update_multicast = 1; + } else { + DBG(SMC_DEBUG_MISC, "%s: ~(MAC_CR_PRMS_|MAC_CR_MCPAS_)\n", + dev->name); + mcr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_); + + /* + * since I'm disabling all multicast entirely, I need to + * clear the multicast list + */ + memset(multicast_table, 0, sizeof(multicast_table)); + update_multicast = 1; + } + + spin_lock_irqsave(&lp->lock, flags); + SMC_SET_MAC_CR(mcr); + if (update_multicast) { + DBG(SMC_DEBUG_MISC, + "%s: update mcast hash table 0x%08x 0x%08x\n", + dev->name, multicast_table[0], multicast_table[1]); + SMC_SET_HASHL(multicast_table[0]); + SMC_SET_HASHH(multicast_table[1]); + } + spin_unlock_irqrestore(&lp->lock, flags); +} + + +/* + * Open and Initialize the board + * + * Set up everything, reset the card, etc.. + */ +static int +smc911x_open(struct net_device *dev) +{ + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + /* + * Check that the address is valid. If its not, refuse + * to bring the device up. The user must specify an + * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx + */ + if (!is_valid_ether_addr(dev->dev_addr)) { + PRINTK("%s: no valid ethernet hw addr\n", __FUNCTION__); + return -EINVAL; + } + + /* reset the hardware */ + smc911x_reset(dev); + + /* Configure the PHY, initialize the link state */ + smc911x_phy_configure(dev); + + /* Turn on Tx + Rx */ + smc911x_enable(dev); + + netif_start_queue(dev); + + return 0; +} + +/* + * smc911x_close + * + * this makes the board clean up everything that it can + * and not talk to the outside world. Caused by + * an 'ifconfig ethX down' + */ +static int smc911x_close(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + netif_stop_queue(dev); + netif_carrier_off(dev); + + /* clear everything */ + smc911x_shutdown(dev); + + if (lp->phy_type != 0) { + /* We need to ensure that no calls to + * smc911x_phy_configure are pending. + + * flush_scheduled_work() cannot be called because we + * are running with the netlink semaphore held (from + * devinet_ioctl()) and the pending work queue + * contains linkwatch_event() (scheduled by + * netif_carrier_off() above). linkwatch_event() also + * wants the netlink semaphore. + */ + while (lp->work_pending) + schedule(); + smc911x_phy_powerdown(dev, lp->mii.phy_id); + } + + if (lp->pending_tx_skb) { + dev_kfree_skb(lp->pending_tx_skb); + lp->pending_tx_skb = NULL; + } + + return 0; +} + +/* + * Get the current statistics. + * This may be called with the card open or closed. + */ +static struct net_device_stats *smc911x_query_statistics(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + + return &lp->stats; +} + +/* + * Ethtool support + */ +static int +smc911x_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct smc911x_local *lp = netdev_priv(dev); + unsigned long ioaddr = dev->base_addr; + int ret, status; + unsigned long flags; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + cmd->maxtxpkt = 1; + cmd->maxrxpkt = 1; + + if (lp->phy_type != 0) { + spin_lock_irqsave(&lp->lock, flags); + ret = mii_ethtool_gset(&lp->mii, cmd); + spin_unlock_irqrestore(&lp->lock, flags); + } else { + cmd->supported = SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_TP | SUPPORTED_AUI; + + if (lp->ctl_rspeed == 10) + cmd->speed = SPEED_10; + else if (lp->ctl_rspeed == 100) + cmd->speed = SPEED_100; + + cmd->autoneg = AUTONEG_DISABLE; + if (lp->mii.phy_id==1) + cmd->transceiver = XCVR_INTERNAL; + else + cmd->transceiver = XCVR_EXTERNAL; + cmd->port = 0; + SMC_GET_PHY_SPECIAL(lp->mii.phy_id, status); + cmd->duplex = + (status & (PHY_SPECIAL_SPD_10FULL_ | PHY_SPECIAL_SPD_100FULL_)) ? + DUPLEX_FULL : DUPLEX_HALF; + ret = 0; + } + + return ret; +} + +static int +smc911x_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct smc911x_local *lp = netdev_priv(dev); + int ret; + unsigned long flags; + + if (lp->phy_type != 0) { + spin_lock_irqsave(&lp->lock, flags); + ret = mii_ethtool_sset(&lp->mii, cmd); + spin_unlock_irqrestore(&lp->lock, flags); + } else { + if (cmd->autoneg != AUTONEG_DISABLE || + cmd->speed != SPEED_10 || + (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL) || + (cmd->port != PORT_TP && cmd->port != PORT_AUI)) + return -EINVAL; + + lp->ctl_rfduplx = cmd->duplex == DUPLEX_FULL; + + ret = 0; + } + + return ret; +} + +static void +smc911x_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + strncpy(info->driver, CARDNAME, sizeof(info->driver)); + strncpy(info->version, version, sizeof(info->version)); + strncpy(info->bus_info, dev->class_dev.dev->bus_id, sizeof(info->bus_info)); +} + +static int smc911x_ethtool_nwayreset(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + int ret = -EINVAL; + unsigned long flags; + + if (lp->phy_type != 0) { + spin_lock_irqsave(&lp->lock, flags); + ret = mii_nway_restart(&lp->mii); + spin_unlock_irqrestore(&lp->lock, flags); + } + + return ret; +} + +static u32 smc911x_ethtool_getmsglevel(struct net_device *dev) +{ + struct smc911x_local *lp = netdev_priv(dev); + return lp->msg_enable; +} + +static void smc911x_ethtool_setmsglevel(struct net_device *dev, u32 level) +{ + struct smc911x_local *lp = netdev_priv(dev); + lp->msg_enable = level; +} + +static int smc911x_ethtool_getregslen(struct net_device *dev) +{ + /* System regs + MAC regs + PHY regs */ + return (((E2P_CMD - ID_REV)/4 + 1) + + (WUCSR - MAC_CR)+1 + 32) * sizeof(u32); +} + +static void smc911x_ethtool_getregs(struct net_device *dev, + struct ethtool_regs* regs, void *buf) +{ + unsigned long ioaddr = dev->base_addr; + struct smc911x_local *lp = netdev_priv(dev); + unsigned long flags; + u32 reg,i,j=0; + u32 *data = (u32*)buf; + + regs->version = lp->version; + for(i=ID_REV;i<=E2P_CMD;i+=4) { + data[j++] = SMC_inl(ioaddr,i); + } + for(i=MAC_CR;i<=WUCSR;i++) { + spin_lock_irqsave(&lp->lock, flags); + SMC_GET_MAC_CSR(i, reg); + spin_unlock_irqrestore(&lp->lock, flags); + data[j++] = reg; + } + for(i=0;i<=31;i++) { + spin_lock_irqsave(&lp->lock, flags); + SMC_GET_MII(i, lp->mii.phy_id, reg); + spin_unlock_irqrestore(&lp->lock, flags); + data[j++] = reg & 0xFFFF; + } +} + +static int smc911x_ethtool_wait_eeprom_ready(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + unsigned int timeout; + int e2p_cmd; + + e2p_cmd = SMC_GET_E2P_CMD(); + for(timeout=10;(e2p_cmd & E2P_CMD_EPC_BUSY_) && timeout; timeout--) { + if (e2p_cmd & E2P_CMD_EPC_TIMEOUT_) { + PRINTK("%s: %s timeout waiting for EEPROM to respond\n", + dev->name, __FUNCTION__); + return -EFAULT; + } + mdelay(1); + e2p_cmd = SMC_GET_E2P_CMD(); + } + if (timeout == 0) { + PRINTK("%s: %s timeout waiting for EEPROM CMD not busy\n", + dev->name, __FUNCTION__); + return -ETIMEDOUT; + } + return 0; +} + +static inline int smc911x_ethtool_write_eeprom_cmd(struct net_device *dev, + int cmd, int addr) +{ + unsigned long ioaddr = dev->base_addr; + int ret; + + if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0) + return ret; + SMC_SET_E2P_CMD(E2P_CMD_EPC_BUSY_ | + ((cmd) & (0x7<<28)) | + ((addr) & 0xFF)); + return 0; +} + +static inline int smc911x_ethtool_read_eeprom_byte(struct net_device *dev, + u8 *data) +{ + unsigned long ioaddr = dev->base_addr; + int ret; + + if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0) + return ret; + *data = SMC_GET_E2P_DATA(); + return 0; +} + +static inline int smc911x_ethtool_write_eeprom_byte(struct net_device *dev, + u8 data) +{ + unsigned long ioaddr = dev->base_addr; + int ret; + + if ((ret = smc911x_ethtool_wait_eeprom_ready(dev))!=0) + return ret; + SMC_SET_E2P_DATA(data); + return 0; +} + +static int smc911x_ethtool_geteeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + u8 eebuf[SMC911X_EEPROM_LEN]; + int i, ret; + + for(i=0;i<SMC911X_EEPROM_LEN;i++) { + if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_READ_, i ))!=0) + return ret; + if ((ret=smc911x_ethtool_read_eeprom_byte(dev, &eebuf[i]))!=0) + return ret; + } + memcpy(data, eebuf+eeprom->offset, eeprom->len); + return 0; +} + +static int smc911x_ethtool_seteeprom(struct net_device *dev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + int i, ret; + + /* Enable erase */ + if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_EWEN_, 0 ))!=0) + return ret; + for(i=eeprom->offset;i<(eeprom->offset+eeprom->len);i++) { + /* erase byte */ + if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_ERASE_, i ))!=0) + return ret; + /* write byte */ + if ((ret=smc911x_ethtool_write_eeprom_byte(dev, *data))!=0) + return ret; + if ((ret=smc911x_ethtool_write_eeprom_cmd(dev, E2P_CMD_EPC_CMD_WRITE_, i ))!=0) + return ret; + } + return 0; +} + +static int smc911x_ethtool_geteeprom_len(struct net_device *dev) +{ + return SMC911X_EEPROM_LEN; +} + +static struct ethtool_ops smc911x_ethtool_ops = { + .get_settings = smc911x_ethtool_getsettings, + .set_settings = smc911x_ethtool_setsettings, + .get_drvinfo = smc911x_ethtool_getdrvinfo, + .get_msglevel = smc911x_ethtool_getmsglevel, + .set_msglevel = smc911x_ethtool_setmsglevel, + .nway_reset = smc911x_ethtool_nwayreset, + .get_link = ethtool_op_get_link, + .get_regs_len = smc911x_ethtool_getregslen, + .get_regs = smc911x_ethtool_getregs, + .get_eeprom_len = smc911x_ethtool_geteeprom_len, + .get_eeprom = smc911x_ethtool_geteeprom, + .set_eeprom = smc911x_ethtool_seteeprom, +}; + +/* + * smc911x_findirq + * + * This routine has a simple purpose -- make the SMC chip generate an + * interrupt, so an auto-detect routine can detect it, and find the IRQ, + */ +static int __init smc911x_findirq(unsigned long ioaddr) +{ + int timeout = 20; + unsigned long cookie; + + DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + + cookie = probe_irq_on(); + + /* + * Force a SW interrupt + */ + + SMC_SET_INT_EN(INT_EN_SW_INT_EN_); + + /* + * Wait until positive that the interrupt has been generated + */ + do { + int int_status; + udelay(10); + int_status = SMC_GET_INT_EN(); + if (int_status & INT_EN_SW_INT_EN_) + break; /* got the interrupt */ + } while (--timeout); + + /* + * there is really nothing that I can do here if timeout fails, + * as autoirq_report will return a 0 anyway, which is what I + * want in this case. Plus, the clean up is needed in both + * cases. + */ + + /* and disable all interrupts again */ + SMC_SET_INT_EN(0); + + /* and return what I found */ + return probe_irq_off(cookie); +} + +/* + * Function: smc911x_probe(unsigned long ioaddr) + * + * Purpose: + * Tests to see if a given ioaddr points to an SMC911x chip. + * Returns a 0 on success + * + * Algorithm: + * (1) see if the endian word is OK + * (1) see if I recognize the chip ID in the appropriate register + * + * Here I do typical initialization tasks. + * + * o Initialize the structure if needed + * o print out my vanity message if not done so already + * o print out what type of hardware is detected + * o print out the ethernet address + * o find the IRQ + * o set up my private data + * o configure the dev structure with my subroutines + * o actually GRAB the irq. + * o GRAB the region + */ +static int __init smc911x_probe(struct net_device *dev, unsigned long ioaddr) +{ + struct smc911x_local *lp = netdev_priv(dev); + int i, retval; + unsigned int val, chip_id, revision; + const char *version_string; + + DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __FUNCTION__); + + /* First, see if the endian word is recognized */ + val = SMC_GET_BYTE_TEST(); + DBG(SMC_DEBUG_MISC, "%s: endian probe returned 0x%04x\n", CARDNAME, val); + if (val != 0x87654321) { + printk(KERN_ERR "Invalid chip endian 0x08%x\n",val); + retval = -ENODEV; + goto err_out; + } + + /* + * check if the revision register is something that I + * recognize. These might need to be added to later, + * as future revisions could be added. + */ + chip_id = SMC_GET_PN(); + DBG(SMC_DEBUG_MISC, "%s: id probe returned 0x%04x\n", CARDNAME, chip_id); + for(i=0;chip_ids[i].id != 0; i++) { + if (chip_ids[i].id == chip_id) break; + } + if (!chip_ids[i].id) { + printk(KERN_ERR "Unknown chip ID %04x\n", chip_id); + retval = -ENODEV; + goto err_out; + } + version_string = chip_ids[i].name; + + revision = SMC_GET_REV(); + DBG(SMC_DEBUG_MISC, "%s: revision = 0x%04x\n", CARDNAME, revision); + + /* At this point I'll assume that the chip is an SMC911x. */ + DBG(SMC_DEBUG_MISC, "%s: Found a %s\n", CARDNAME, chip_ids[i].name); + + /* Validate the TX FIFO size requested */ + if ((tx_fifo_kb < 2) || (tx_fifo_kb > 14)) { + printk(KERN_ERR "Invalid TX FIFO size requested %d\n", tx_fifo_kb); + retval = -EINVAL; + goto err_out; + } + + /* fill in some of the fields */ + dev->base_addr = ioaddr; + lp->version = chip_ids[i].id; + lp->revision = revision; + lp->tx_fifo_kb = tx_fifo_kb; + /* Reverse calculate the RX FIFO size from the TX */ + lp->tx_fifo_size=(lp->tx_fifo_kb<<10) - 512; + lp->rx_fifo_size= ((0x4000 - 512 - lp->tx_fifo_size) / 16) * 15; + + /* Set the automatic flow control values */ + switch(lp->tx_fifo_kb) { + /* + * AFC_HI is about ((Rx Data Fifo Size)*2/3)/64 + * AFC_LO is AFC_HI/2 + * BACK_DUR is about 5uS*(AFC_LO) rounded down + */ + case 2:/* 13440 Rx Data Fifo Size */ + lp->afc_cfg=0x008C46AF;break; + case 3:/* 12480 Rx Data Fifo Size */ + lp->afc_cfg=0x0082419F;break; + case 4:/* 11520 Rx Data Fifo Size */ + lp->afc_cfg=0x00783C9F;break; + case 5:/* 10560 Rx Data Fifo Size */ + lp->afc_cfg=0x006E374F;break; + case 6:/* 9600 Rx Data Fifo Size */ + lp->afc_cfg=0x0064328F;break; + case 7:/* 8640 Rx Data Fifo Size */ + lp->afc_cfg=0x005A2D7F;break; + case 8:/* 7680 Rx Data Fifo Size */ + lp->afc_cfg=0x0050287F;break; + case 9:/* 6720 Rx Data Fifo Size */ + lp->afc_cfg=0x0046236F;break; + case 10:/* 5760 Rx Data Fifo Size */ + lp->afc_cfg=0x003C1E6F;break; + case 11:/* 4800 Rx Data Fifo Size */ + lp->afc_cfg=0x0032195F;break; + /* + * AFC_HI is ~1520 bytes less than RX Data Fifo Size + * AFC_LO is AFC_HI/2 + * BACK_DUR is about 5uS*(AFC_LO) rounded down + */ + case 12:/* 3840 Rx Data Fifo Size */ + lp->afc_cfg=0x0024124F;break; + case 13:/* 2880 Rx Data Fifo Size */ + lp->afc_cfg=0x0015073F;break; + case 14:/* 1920 Rx Data Fifo Size */ + lp->afc_cfg=0x0006032F;break; + default: + PRINTK("%s: ERROR -- no AFC_CFG setting found", + dev->name); + break; + } + + DBG(SMC_DEBUG_MISC | SMC_DEBUG_TX | SMC_DEBUG_RX, + "%s: tx_fifo %d rx_fifo %d afc_cfg 0x%08x\n", CARDNAME, + lp->tx_fifo_size, lp->rx_fifo_size, lp->afc_cfg); + + spin_lock_init(&lp->lock); + + /* Get the MAC address */ + SMC_GET_MAC_ADDR(dev->dev_addr); + + /* now, reset the chip, and put it into a known state */ + smc911x_reset(dev); + + /* + * If dev->irq is 0, then the device has to be banged on to see + * what the IRQ is. + * + * Specifying an IRQ is done with the assumption that the user knows + * what (s)he is doing. No checking is done!!!! + */ + if (dev->irq < 1) { + int trials; + + trials = 3; + while (trials--) { + dev->irq = smc911x_findirq(ioaddr); + if (dev->irq) + break; + /* kick the card and try again */ + smc911x_reset(dev); + } + } + if (dev->irq == 0) { + printk("%s: Couldn't autodetect your IRQ. Use irq=xx.\n", + dev->name); + retval = -ENODEV; + goto err_out; + } + dev->irq = irq_canonicalize(dev->irq); + + /* Fill in the fields of the device structure with ethernet values. */ + ether_setup(dev); + + dev->open = smc911x_open; + dev->stop = smc911x_close; + dev->hard_start_xmit = smc911x_hard_start_xmit; + dev->tx_timeout = smc911x_timeout; + dev->watchdog_timeo = msecs_to_jiffies(watchdog); + dev->get_stats = smc911x_query_statistics; + dev->set_multicast_list = smc911x_set_multicast_list; + dev->ethtool_ops = &smc911x_ethtool_ops; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = smc911x_poll_controller; +#endif + + INIT_WORK(&lp->phy_configure, smc911x_phy_configure, dev); + lp->mii.phy_id_mask = 0x1f; + lp->mii.reg_num_mask = 0x1f; + lp->mii.force_media = 0; + lp->mii.full_duplex = 0; + lp->mii.dev = dev; + lp->mii.mdio_read = smc911x_phy_read; + lp->mii.mdio_write = smc911x_phy_write; + + /* + * Locate the phy, if any. + */ + smc911x_phy_detect(dev); + + /* Set default parameters */ + lp->msg_enable = NETIF_MSG_LINK; + lp->ctl_rfduplx = 1; + lp->ctl_rspeed = 100; + + /* Grab the IRQ */ + retval = request_irq(dev->irq, &smc911x_interrupt, IRQF_SHARED, dev->name, dev); + if (retval) + goto err_out; + + set_irq_type(dev->irq, IRQT_FALLING); + +#ifdef SMC_USE_DMA + lp->rxdma = SMC_DMA_REQUEST(dev, smc911x_rx_dma_irq); + lp->txdma = SMC_DMA_REQUEST(dev, smc911x_tx_dma_irq); + lp->rxdma_active = 0; + lp->txdma_active = 0; + dev->dma = lp->rxdma; +#endif + + retval = register_netdev(dev); + if (retval == 0) { + /* now, print out the card info, in a short format.. */ + printk("%s: %s (rev %d) at %#lx IRQ %d", + dev->name, version_string, lp->revision, + dev->base_addr, dev->irq); + +#ifdef SMC_USE_DMA + if (lp->rxdma != -1) + printk(" RXDMA %d ", lp->rxdma); + + if (lp->txdma != -1) + printk("TXDMA %d", lp->txdma); +#endif + printk("\n"); + if (!is_valid_ether_addr(dev->dev_addr)) { + printk("%s: Invalid ethernet MAC address. Please " + "set using ifconfig\n", dev->name); + } else { + /* Print the Ethernet address */ + printk("%s: Ethernet addr: ", dev->name); + for (i = 0; i < 5; i++) + printk("%2.2x:", dev->dev_addr[i]); + printk("%2.2x\n", dev->dev_addr[5]); + } + + if (lp->phy_type == 0) { + PRINTK("%s: No PHY found\n", dev->name); + } else if ((lp->phy_type & ~0xff) == LAN911X_INTERNAL_PHY_ID) { + PRINTK("%s: LAN911x Internal PHY\n", dev->name); + } else { + PRINTK("%s: External PHY 0x%08x\n", dev->name, lp->phy_type); + } + } + +err_out: +#ifdef SMC_USE_DMA + if (retval) { + if (lp->rxdma != -1) { + SMC_DMA_FREE(dev, lp->rxdma); + } + if (lp->txdma != -1) { + SMC_DMA_FREE(dev, lp->txdma); + } + } +#endif + return retval; +} + +/* + * smc911x_init(void) + * + * Output: + * 0 --> there is a device + * anything else, error + */ +static int smc911x_drv_probe(struct platform_device *pdev) +{ + struct net_device *ndev; + struct resource *res; + unsigned int *addr; + int ret; + + DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ret = -ENODEV; + goto out; + } + + /* + * Request the regions. + */ + if (!request_mem_region(res->start, SMC911X_IO_EXTENT, CARDNAME)) { + ret = -EBUSY; + goto out; + } + + ndev = alloc_etherdev(sizeof(struct smc911x_local)); + if (!ndev) { + printk("%s: could not allocate device.\n", CARDNAME); + ret = -ENOMEM; + goto release_1; + } + SET_MODULE_OWNER(ndev); + SET_NETDEV_DEV(ndev, &pdev->dev); + + ndev->dma = (unsigned char)-1; + ndev->irq = platform_get_irq(pdev, 0); + + addr = ioremap(res->start, SMC911X_IO_EXTENT); + if (!addr) { + ret = -ENOMEM; + goto release_both; + } + + platform_set_drvdata(pdev, ndev); + ret = smc911x_probe(ndev, (unsigned long)addr); + if (ret != 0) { + platform_set_drvdata(pdev, NULL); + iounmap(addr); +release_both: + free_netdev(ndev); +release_1: + release_mem_region(res->start, SMC911X_IO_EXTENT); +out: + printk("%s: not found (%d).\n", CARDNAME, ret); + } +#ifdef SMC_USE_DMA + else { + struct smc911x_local *lp = netdev_priv(ndev); + lp->physaddr = res->start; + lp->dev = &pdev->dev; + } +#endif + + return ret; +} + +static int smc911x_drv_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct resource *res; + + DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + platform_set_drvdata(pdev, NULL); + + unregister_netdev(ndev); + + free_irq(ndev->irq, ndev); + +#ifdef SMC_USE_DMA + { + struct smc911x_local *lp = netdev_priv(ndev); + if (lp->rxdma != -1) { + SMC_DMA_FREE(dev, lp->rxdma); + } + if (lp->txdma != -1) { + SMC_DMA_FREE(dev, lp->txdma); + } + } +#endif + iounmap((void *)ndev->base_addr); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, SMC911X_IO_EXTENT); + + free_netdev(ndev); + return 0; +} + +static int smc911x_drv_suspend(struct platform_device *dev, pm_message_t state) +{ + struct net_device *ndev = platform_get_drvdata(dev); + unsigned long ioaddr = ndev->base_addr; + + DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + if (ndev) { + if (netif_running(ndev)) { + netif_device_detach(ndev); + smc911x_shutdown(ndev); +#if POWER_DOWN + /* Set D2 - Energy detect only setting */ + SMC_SET_PMT_CTRL(2<<12); +#endif + } + } + return 0; +} + +static int smc911x_drv_resume(struct platform_device *dev) +{ + struct net_device *ndev = platform_get_drvdata(dev); + + DBG(SMC_DEBUG_FUNC, "--> %s\n", __FUNCTION__); + if (ndev) { + struct smc911x_local *lp = netdev_priv(ndev); + + if (netif_running(ndev)) { + smc911x_reset(ndev); + smc911x_enable(ndev); + if (lp->phy_type != 0) + smc911x_phy_configure(ndev); + netif_device_attach(ndev); + } + } + return 0; +} + +static struct platform_driver smc911x_driver = { + .probe = smc911x_drv_probe, + .remove = smc911x_drv_remove, + .suspend = smc911x_drv_suspend, + .resume = smc911x_drv_resume, + .driver = { + .name = CARDNAME, + }, +}; + +static int __init smc911x_init(void) +{ + return platform_driver_register(&smc911x_driver); +} + +static void __exit smc911x_cleanup(void) +{ + platform_driver_unregister(&smc911x_driver); +} + +module_init(smc911x_init); +module_exit(smc911x_cleanup); diff --git a/drivers/net/smc911x.h b/drivers/net/smc911x.h new file mode 100644 index 000000000..962a71045 --- /dev/null +++ b/drivers/net/smc911x.h @@ -0,0 +1,835 @@ +/*------------------------------------------------------------------------ + . smc911x.h - macros for SMSC's LAN911{5,6,7,8} single-chip Ethernet device. + . + . Copyright (C) 2005 Sensoria Corp. + . Derived from the unified SMC91x driver by Nicolas Pitre + . + . This program is free software; you can redistribute it and/or modify + . it under the terms of the GNU General Public License as published by + . the Free Software Foundation; either version 2 of the License, or + . (at your option) any later version. + . + . This program is distributed in the hope that it will be useful, + . but WITHOUT ANY WARRANTY; without even the implied warranty of + . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + . GNU General Public License for more details. + . + . You should have received a copy of the GNU General Public License + . along with this program; if not, write to the Free Software + . Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + . + . Information contained in this file was obtained from the LAN9118 + . manual from SMC. To get a copy, if you really want one, you can find + . information under www.smsc.com. + . + . Authors + . Dustin McIntire <dustin@sensoria.com> + . + ---------------------------------------------------------------------------*/ +#ifndef _SMC911X_H_ +#define _SMC911X_H_ + +/* + * Use the DMA feature on PXA chips + */ +#ifdef CONFIG_ARCH_PXA + #define SMC_USE_PXA_DMA 1 + #define SMC_USE_16BIT 0 + #define SMC_USE_32BIT 1 +#endif + + +/* + * Define the bus width specific IO macros + */ + +#if SMC_USE_16BIT +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) ((SMC_inw(a, r) & 0xFFFF)+(SMC_inw(a+2, r)<<16)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_outl(v, a, r) \ + do{ \ + writel(v & 0xFFFF, (a) + (r)); \ + writel(v >> 16, (a) + (r) + 2); \ + } while (0) +#define SMC_insl(a, r, p, l) readsw((short*)((a) + (r)), p, l*2) +#define SMC_outsl(a, r, p, l) writesw((short*)((a) + (r)), p, l*2) + +#elif SMC_USE_32BIT +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) readl((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outl(v, a, r) writel(v, (a) + (r)) +#define SMC_insl(a, r, p, l) readsl((int*)((a) + (r)), p, l) +#define SMC_outsl(a, r, p, l) writesl((int*)((a) + (r)), p, l) + +#endif /* SMC_USE_16BIT */ + + + +#if SMC_USE_PXA_DMA +#define SMC_USE_DMA + +/* + * Define the request and free functions + * These are unfortunately architecture specific as no generic allocation + * mechanism exits + */ +#define SMC_DMA_REQUEST(dev, handler) \ + pxa_request_dma(dev->name, DMA_PRIO_LOW, handler, dev) + +#define SMC_DMA_FREE(dev, dma) \ + pxa_free_dma(dma) + +#define SMC_DMA_ACK_IRQ(dev, dma) \ +{ \ + if (DCSR(dma) & DCSR_BUSERR) { \ + printk("%s: DMA %d bus error!\n", dev->name, dma); \ + } \ + DCSR(dma) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR; \ +} + +/* + * Use a DMA for RX and TX packets. + */ +#include <linux/dma-mapping.h> +#include <asm/dma.h> +#include <asm/arch/pxa-regs.h> + +static dma_addr_t rx_dmabuf, tx_dmabuf; +static int rx_dmalen, tx_dmalen; + +#ifdef SMC_insl +#undef SMC_insl +#define SMC_insl(a, r, p, l) \ + smc_pxa_dma_insl(lp->dev, a, lp->physaddr, r, lp->rxdma, p, l) + +static inline void +smc_pxa_dma_insl(struct device *dev, u_long ioaddr, u_long physaddr, + int reg, int dma, u_char *buf, int len) +{ + /* 64 bit alignment is required for memory to memory DMA */ + if ((long)buf & 4) { + *((u32 *)buf) = SMC_inl(ioaddr, reg); + buf += 4; + len--; + } + + len *= 4; + rx_dmabuf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE); + rx_dmalen = len; + DCSR(dma) = DCSR_NODESC; + DTADR(dma) = rx_dmabuf; + DSADR(dma) = physaddr + reg; + DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 | + DCMD_WIDTH4 | DCMD_ENDIRQEN | (DCMD_LENGTH & rx_dmalen)); + DCSR(dma) = DCSR_NODESC | DCSR_RUN; +} +#endif + +#ifdef SMC_insw +#undef SMC_insw +#define SMC_insw(a, r, p, l) \ + smc_pxa_dma_insw(lp->dev, a, lp->physaddr, r, lp->rxdma, p, l) + +static inline void +smc_pxa_dma_insw(struct device *dev, u_long ioaddr, u_long physaddr, + int reg, int dma, u_char *buf, int len) +{ + /* 64 bit alignment is required for memory to memory DMA */ + while ((long)buf & 6) { + *((u16 *)buf) = SMC_inw(ioaddr, reg); + buf += 2; + len--; + } + + len *= 2; + rx_dmabuf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE); + rx_dmalen = len; + DCSR(dma) = DCSR_NODESC; + DTADR(dma) = rx_dmabuf; + DSADR(dma) = physaddr + reg; + DCMD(dma) = (DCMD_INCTRGADDR | DCMD_BURST32 | + DCMD_WIDTH2 | DCMD_ENDIRQEN | (DCMD_LENGTH & rx_dmalen)); + DCSR(dma) = DCSR_NODESC | DCSR_RUN; +} +#endif + +#ifdef SMC_outsl +#undef SMC_outsl +#define SMC_outsl(a, r, p, l) \ + smc_pxa_dma_outsl(lp->dev, a, lp->physaddr, r, lp->txdma, p, l) + +static inline void +smc_pxa_dma_outsl(struct device *dev, u_long ioaddr, u_long physaddr, + int reg, int dma, u_char *buf, int len) +{ + /* 64 bit alignment is required for memory to memory DMA */ + if ((long)buf & 4) { + SMC_outl(*((u32 *)buf), ioaddr, reg); + buf += 4; + len--; + } + + len *= 4; + tx_dmabuf = dma_map_single(dev, buf, len, DMA_TO_DEVICE); + tx_dmalen = len; + DCSR(dma) = DCSR_NODESC; + DSADR(dma) = tx_dmabuf; + DTADR(dma) = physaddr + reg; + DCMD(dma) = (DCMD_INCSRCADDR | DCMD_BURST32 | + DCMD_WIDTH4 | DCMD_ENDIRQEN | (DCMD_LENGTH & tx_dmalen)); + DCSR(dma) = DCSR_NODESC | DCSR_RUN; +} +#endif + +#ifdef SMC_outsw +#undef SMC_outsw +#define SMC_outsw(a, r, p, l) \ + smc_pxa_dma_outsw(lp->dev, a, lp->physaddr, r, lp->txdma, p, l) + +static inline void +smc_pxa_dma_outsw(struct device *dev, u_long ioaddr, u_long physaddr, + int reg, int dma, u_char *buf, int len) +{ + /* 64 bit alignment is required for memory to memory DMA */ + while ((long)buf & 6) { + SMC_outw(*((u16 *)buf), ioaddr, reg); + buf += 2; + len--; + } + + len *= 2; + tx_dmabuf = dma_map_single(dev, buf, len, DMA_TO_DEVICE); + tx_dmalen = len; + DCSR(dma) = DCSR_NODESC; + DSADR(dma) = tx_dmabuf; + DTADR(dma) = physaddr + reg; + DCMD(dma) = (DCMD_INCSRCADDR | DCMD_BURST32 | + DCMD_WIDTH2 | DCMD_ENDIRQEN | (DCMD_LENGTH & tx_dmalen)); + DCSR(dma) = DCSR_NODESC | DCSR_RUN; +} +#endif + +#endif /* SMC_USE_PXA_DMA */ + + +/* Chip Parameters and Register Definitions */ + +#define SMC911X_TX_FIFO_LOW_THRESHOLD (1536*2) + +#define SMC911X_IO_EXTENT 0x100 + +#define SMC911X_EEPROM_LEN 7 + +/* Below are the register offsets and bit definitions + * of the Lan911x memory space + */ +#define RX_DATA_FIFO (0x00) + +#define TX_DATA_FIFO (0x20) +#define TX_CMD_A_INT_ON_COMP_ (0x80000000) +#define TX_CMD_A_INT_BUF_END_ALGN_ (0x03000000) +#define TX_CMD_A_INT_4_BYTE_ALGN_ (0x00000000) +#define TX_CMD_A_INT_16_BYTE_ALGN_ (0x01000000) +#define TX_CMD_A_INT_32_BYTE_ALGN_ (0x02000000) +#define TX_CMD_A_INT_DATA_OFFSET_ (0x001F0000) +#define TX_CMD_A_INT_FIRST_SEG_ (0x00002000) +#define TX_CMD_A_INT_LAST_SEG_ (0x00001000) +#define TX_CMD_A_BUF_SIZE_ (0x000007FF) +#define TX_CMD_B_PKT_TAG_ (0xFFFF0000) +#define TX_CMD_B_ADD_CRC_DISABLE_ (0x00002000) +#define TX_CMD_B_DISABLE_PADDING_ (0x00001000) +#define TX_CMD_B_PKT_BYTE_LENGTH_ (0x000007FF) + +#define RX_STATUS_FIFO (0x40) +#define RX_STS_PKT_LEN_ (0x3FFF0000) +#define RX_STS_ES_ (0x00008000) +#define RX_STS_BCST_ (0x00002000) +#define RX_STS_LEN_ERR_ (0x00001000) +#define RX_STS_RUNT_ERR_ (0x00000800) +#define RX_STS_MCAST_ (0x00000400) +#define RX_STS_TOO_LONG_ (0x00000080) +#define RX_STS_COLL_ (0x00000040) +#define RX_STS_ETH_TYPE_ (0x00000020) +#define RX_STS_WDOG_TMT_ (0x00000010) +#define RX_STS_MII_ERR_ (0x00000008) +#define RX_STS_DRIBBLING_ (0x00000004) +#define RX_STS_CRC_ERR_ (0x00000002) +#define RX_STATUS_FIFO_PEEK (0x44) +#define TX_STATUS_FIFO (0x48) +#define TX_STS_TAG_ (0xFFFF0000) +#define TX_STS_ES_ (0x00008000) +#define TX_STS_LOC_ (0x00000800) +#define TX_STS_NO_CARR_ (0x00000400) +#define TX_STS_LATE_COLL_ (0x00000200) +#define TX_STS_MANY_COLL_ (0x00000100) +#define TX_STS_COLL_CNT_ (0x00000078) +#define TX_STS_MANY_DEFER_ (0x00000004) +#define TX_STS_UNDERRUN_ (0x00000002) +#define TX_STS_DEFERRED_ (0x00000001) +#define TX_STATUS_FIFO_PEEK (0x4C) +#define ID_REV (0x50) +#define ID_REV_CHIP_ID_ (0xFFFF0000) /* RO */ +#define ID_REV_REV_ID_ (0x0000FFFF) /* RO */ + +#define INT_CFG (0x54) +#define INT_CFG_INT_DEAS_ (0xFF000000) /* R/W */ +#define INT_CFG_INT_DEAS_CLR_ (0x00004000) +#define INT_CFG_INT_DEAS_STS_ (0x00002000) +#define INT_CFG_IRQ_INT_ (0x00001000) /* RO */ +#define INT_CFG_IRQ_EN_ (0x00000100) /* R/W */ +#define INT_CFG_IRQ_POL_ (0x00000010) /* R/W Not Affected by SW Reset */ +#define INT_CFG_IRQ_TYPE_ (0x00000001) /* R/W Not Affected by SW Reset */ + +#define INT_STS (0x58) +#define INT_STS_SW_INT_ (0x80000000) /* R/WC */ +#define INT_STS_TXSTOP_INT_ (0x02000000) /* R/WC */ +#define INT_STS_RXSTOP_INT_ (0x01000000) /* R/WC */ +#define INT_STS_RXDFH_INT_ (0x00800000) /* R/WC */ +#define INT_STS_RXDF_INT_ (0x00400000) /* R/WC */ +#define INT_STS_TX_IOC_ (0x00200000) /* R/WC */ +#define INT_STS_RXD_INT_ (0x00100000) /* R/WC */ +#define INT_STS_GPT_INT_ (0x00080000) /* R/WC */ +#define INT_STS_PHY_INT_ (0x00040000) /* RO */ +#define INT_STS_PME_INT_ (0x00020000) /* R/WC */ +#define INT_STS_TXSO_ (0x00010000) /* R/WC */ +#define INT_STS_RWT_ (0x00008000) /* R/WC */ +#define INT_STS_RXE_ (0x00004000) /* R/WC */ +#define INT_STS_TXE_ (0x00002000) /* R/WC */ +//#define INT_STS_ERX_ (0x00001000) /* R/WC */ +#define INT_STS_TDFU_ (0x00000800) /* R/WC */ +#define INT_STS_TDFO_ (0x00000400) /* R/WC */ +#define INT_STS_TDFA_ (0x00000200) /* R/WC */ +#define INT_STS_TSFF_ (0x00000100) /* R/WC */ +#define INT_STS_TSFL_ (0x00000080) /* R/WC */ +//#define INT_STS_RXDF_ (0x00000040) /* R/WC */ +#define INT_STS_RDFO_ (0x00000040) /* R/WC */ +#define INT_STS_RDFL_ (0x00000020) /* R/WC */ +#define INT_STS_RSFF_ (0x00000010) /* R/WC */ +#define INT_STS_RSFL_ (0x00000008) /* R/WC */ +#define INT_STS_GPIO2_INT_ (0x00000004) /* R/WC */ +#define INT_STS_GPIO1_INT_ (0x00000002) /* R/WC */ +#define INT_STS_GPIO0_INT_ (0x00000001) /* R/WC */ + +#define INT_EN (0x5C) +#define INT_EN_SW_INT_EN_ (0x80000000) /* R/W */ +#define INT_EN_TXSTOP_INT_EN_ (0x02000000) /* R/W */ +#define INT_EN_RXSTOP_INT_EN_ (0x01000000) /* R/W */ +#define INT_EN_RXDFH_INT_EN_ (0x00800000) /* R/W */ +//#define INT_EN_RXDF_INT_EN_ (0x00400000) /* R/W */ +#define INT_EN_TIOC_INT_EN_ (0x00200000) /* R/W */ +#define INT_EN_RXD_INT_EN_ (0x00100000) /* R/W */ +#define INT_EN_GPT_INT_EN_ (0x00080000) /* R/W */ +#define INT_EN_PHY_INT_EN_ (0x00040000) /* R/W */ +#define INT_EN_PME_INT_EN_ (0x00020000) /* R/W */ +#define INT_EN_TXSO_EN_ (0x00010000) /* R/W */ +#define INT_EN_RWT_EN_ (0x00008000) /* R/W */ +#define INT_EN_RXE_EN_ (0x00004000) /* R/W */ +#define INT_EN_TXE_EN_ (0x00002000) /* R/W */ +//#define INT_EN_ERX_EN_ (0x00001000) /* R/W */ +#define INT_EN_TDFU_EN_ (0x00000800) /* R/W */ +#define INT_EN_TDFO_EN_ (0x00000400) /* R/W */ +#define INT_EN_TDFA_EN_ (0x00000200) /* R/W */ +#define INT_EN_TSFF_EN_ (0x00000100) /* R/W */ +#define INT_EN_TSFL_EN_ (0x00000080) /* R/W */ +//#define INT_EN_RXDF_EN_ (0x00000040) /* R/W */ +#define INT_EN_RDFO_EN_ (0x00000040) /* R/W */ +#define INT_EN_RDFL_EN_ (0x00000020) /* R/W */ +#define INT_EN_RSFF_EN_ (0x00000010) /* R/W */ +#define INT_EN_RSFL_EN_ (0x00000008) /* R/W */ +#define INT_EN_GPIO2_INT_ (0x00000004) /* R/W */ +#define INT_EN_GPIO1_INT_ (0x00000002) /* R/W */ +#define INT_EN_GPIO0_INT_ (0x00000001) /* R/W */ + +#define BYTE_TEST (0x64) +#define FIFO_INT (0x68) +#define FIFO_INT_TX_AVAIL_LEVEL_ (0xFF000000) /* R/W */ +#define FIFO_INT_TX_STS_LEVEL_ (0x00FF0000) /* R/W */ +#define FIFO_INT_RX_AVAIL_LEVEL_ (0x0000FF00) /* R/W */ +#define FIFO_INT_RX_STS_LEVEL_ (0x000000FF) /* R/W */ + +#define RX_CFG (0x6C) +#define RX_CFG_RX_END_ALGN_ (0xC0000000) /* R/W */ +#define RX_CFG_RX_END_ALGN4_ (0x00000000) /* R/W */ +#define RX_CFG_RX_END_ALGN16_ (0x40000000) /* R/W */ +#define RX_CFG_RX_END_ALGN32_ (0x80000000) /* R/W */ +#define RX_CFG_RX_DMA_CNT_ (0x0FFF0000) /* R/W */ +#define RX_CFG_RX_DUMP_ (0x00008000) /* R/W */ +#define RX_CFG_RXDOFF_ (0x00001F00) /* R/W */ +//#define RX_CFG_RXBAD_ (0x00000001) /* R/W */ + +#define TX_CFG (0x70) +//#define TX_CFG_TX_DMA_LVL_ (0xE0000000) /* R/W */ +//#define TX_CFG_TX_DMA_CNT_ (0x0FFF0000) /* R/W Self Clearing */ +#define TX_CFG_TXS_DUMP_ (0x00008000) /* Self Clearing */ +#define TX_CFG_TXD_DUMP_ (0x00004000) /* Self Clearing */ +#define TX_CFG_TXSAO_ (0x00000004) /* R/W */ +#define TX_CFG_TX_ON_ (0x00000002) /* R/W */ +#define TX_CFG_STOP_TX_ (0x00000001) /* Self Clearing */ + +#define HW_CFG (0x74) +#define HW_CFG_TTM_ (0x00200000) /* R/W */ +#define HW_CFG_SF_ (0x00100000) /* R/W */ +#define HW_CFG_TX_FIF_SZ_ (0x000F0000) /* R/W */ +#define HW_CFG_TR_ (0x00003000) /* R/W */ +#define HW_CFG_PHY_CLK_SEL_ (0x00000060) /* R/W */ +#define HW_CFG_PHY_CLK_SEL_INT_PHY_ (0x00000000) /* R/W */ +#define HW_CFG_PHY_CLK_SEL_EXT_PHY_ (0x00000020) /* R/W */ +#define HW_CFG_PHY_CLK_SEL_CLK_DIS_ (0x00000040) /* R/W */ +#define HW_CFG_SMI_SEL_ (0x00000010) /* R/W */ +#define HW_CFG_EXT_PHY_DET_ (0x00000008) /* RO */ +#define HW_CFG_EXT_PHY_EN_ (0x00000004) /* R/W */ +#define HW_CFG_32_16_BIT_MODE_ (0x00000004) /* RO */ +#define HW_CFG_SRST_TO_ (0x00000002) /* RO */ +#define HW_CFG_SRST_ (0x00000001) /* Self Clearing */ + +#define RX_DP_CTRL (0x78) +#define RX_DP_CTRL_RX_FFWD_ (0x80000000) /* R/W */ +#define RX_DP_CTRL_FFWD_BUSY_ (0x80000000) /* RO */ + +#define RX_FIFO_INF (0x7C) +#define RX_FIFO_INF_RXSUSED_ (0x00FF0000) /* RO */ +#define RX_FIFO_INF_RXDUSED_ (0x0000FFFF) /* RO */ + +#define TX_FIFO_INF (0x80) +#define TX_FIFO_INF_TSUSED_ (0x00FF0000) /* RO */ +#define TX_FIFO_INF_TDFREE_ (0x0000FFFF) /* RO */ + +#define PMT_CTRL (0x84) +#define PMT_CTRL_PM_MODE_ (0x00003000) /* Self Clearing */ +#define PMT_CTRL_PHY_RST_ (0x00000400) /* Self Clearing */ +#define PMT_CTRL_WOL_EN_ (0x00000200) /* R/W */ +#define PMT_CTRL_ED_EN_ (0x00000100) /* R/W */ +#define PMT_CTRL_PME_TYPE_ (0x00000040) /* R/W Not Affected by SW Reset */ +#define PMT_CTRL_WUPS_ (0x00000030) /* R/WC */ +#define PMT_CTRL_WUPS_NOWAKE_ (0x00000000) /* R/WC */ +#define PMT_CTRL_WUPS_ED_ (0x00000010) /* R/WC */ +#define PMT_CTRL_WUPS_WOL_ (0x00000020) /* R/WC */ +#define PMT_CTRL_WUPS_MULTI_ (0x00000030) /* R/WC */ +#define PMT_CTRL_PME_IND_ (0x00000008) /* R/W */ +#define PMT_CTRL_PME_POL_ (0x00000004) /* R/W */ +#define PMT_CTRL_PME_EN_ (0x00000002) /* R/W Not Affected by SW Reset */ +#define PMT_CTRL_READY_ (0x00000001) /* RO */ + +#define GPIO_CFG (0x88) +#define GPIO_CFG_LED3_EN_ (0x40000000) /* R/W */ +#define GPIO_CFG_LED2_EN_ (0x20000000) /* R/W */ +#define GPIO_CFG_LED1_EN_ (0x10000000) /* R/W */ +#define GPIO_CFG_GPIO2_INT_POL_ (0x04000000) /* R/W */ +#define GPIO_CFG_GPIO1_INT_POL_ (0x02000000) /* R/W */ +#define GPIO_CFG_GPIO0_INT_POL_ (0x01000000) /* R/W */ +#define GPIO_CFG_EEPR_EN_ (0x00700000) /* R/W */ +#define GPIO_CFG_GPIOBUF2_ (0x00040000) /* R/W */ +#define GPIO_CFG_GPIOBUF1_ (0x00020000) /* R/W */ +#define GPIO_CFG_GPIOBUF0_ (0x00010000) /* R/W */ +#define GPIO_CFG_GPIODIR2_ (0x00000400) /* R/W */ +#define GPIO_CFG_GPIODIR1_ (0x00000200) /* R/W */ +#define GPIO_CFG_GPIODIR0_ (0x00000100) /* R/W */ +#define GPIO_CFG_GPIOD4_ (0x00000010) /* R/W */ +#define GPIO_CFG_GPIOD3_ (0x00000008) /* R/W */ +#define GPIO_CFG_GPIOD2_ (0x00000004) /* R/W */ +#define GPIO_CFG_GPIOD1_ (0x00000002) /* R/W */ +#define GPIO_CFG_GPIOD0_ (0x00000001) /* R/W */ + +#define GPT_CFG (0x8C) +#define GPT_CFG_TIMER_EN_ (0x20000000) /* R/W */ +#define GPT_CFG_GPT_LOAD_ (0x0000FFFF) /* R/W */ + +#define GPT_CNT (0x90) +#define GPT_CNT_GPT_CNT_ (0x0000FFFF) /* RO */ + +#define ENDIAN (0x98) +#define FREE_RUN (0x9C) +#define RX_DROP (0xA0) +#define MAC_CSR_CMD (0xA4) +#define MAC_CSR_CMD_CSR_BUSY_ (0x80000000) /* Self Clearing */ +#define MAC_CSR_CMD_R_NOT_W_ (0x40000000) /* R/W */ +#define MAC_CSR_CMD_CSR_ADDR_ (0x000000FF) /* R/W */ + +#define MAC_CSR_DATA (0xA8) +#define AFC_CFG (0xAC) +#define AFC_CFG_AFC_HI_ (0x00FF0000) /* R/W */ +#define AFC_CFG_AFC_LO_ (0x0000FF00) /* R/W */ +#define AFC_CFG_BACK_DUR_ (0x000000F0) /* R/W */ +#define AFC_CFG_FCMULT_ (0x00000008) /* R/W */ +#define AFC_CFG_FCBRD_ (0x00000004) /* R/W */ +#define AFC_CFG_FCADD_ (0x00000002) /* R/W */ +#define AFC_CFG_FCANY_ (0x00000001) /* R/W */ + +#define E2P_CMD (0xB0) +#define E2P_CMD_EPC_BUSY_ (0x80000000) /* Self Clearing */ +#define E2P_CMD_EPC_CMD_ (0x70000000) /* R/W */ +#define E2P_CMD_EPC_CMD_READ_ (0x00000000) /* R/W */ +#define E2P_CMD_EPC_CMD_EWDS_ (0x10000000) /* R/W */ +#define E2P_CMD_EPC_CMD_EWEN_ (0x20000000) /* R/W */ +#define E2P_CMD_EPC_CMD_WRITE_ (0x30000000) /* R/W */ +#define E2P_CMD_EPC_CMD_WRAL_ (0x40000000) /* R/W */ +#define E2P_CMD_EPC_CMD_ERASE_ (0x50000000) /* R/W */ +#define E2P_CMD_EPC_CMD_ERAL_ (0x60000000) /* R/W */ +#define E2P_CMD_EPC_CMD_RELOAD_ (0x70000000) /* R/W */ +#define E2P_CMD_EPC_TIMEOUT_ (0x00000200) /* RO */ +#define E2P_CMD_MAC_ADDR_LOADED_ (0x00000100) /* RO */ +#define E2P_CMD_EPC_ADDR_ (0x000000FF) /* R/W */ + +#define E2P_DATA (0xB4) +#define E2P_DATA_EEPROM_DATA_ (0x000000FF) /* R/W */ +/* end of LAN register offsets and bit definitions */ + +/* + **************************************************************************** + **************************************************************************** + * MAC Control and Status Register (Indirect Address) + * Offset (through the MAC_CSR CMD and DATA port) + **************************************************************************** + **************************************************************************** + * + */ +#define MAC_CR (0x01) /* R/W */ + +/* MAC_CR - MAC Control Register */ +#define MAC_CR_RXALL_ (0x80000000) +// TODO: delete this bit? It is not described in the data sheet. +#define MAC_CR_HBDIS_ (0x10000000) +#define MAC_CR_RCVOWN_ (0x00800000) +#define MAC_CR_LOOPBK_ (0x00200000) +#define MAC_CR_FDPX_ (0x00100000) +#define MAC_CR_MCPAS_ (0x00080000) +#define MAC_CR_PRMS_ (0x00040000) +#define MAC_CR_INVFILT_ (0x00020000) +#define MAC_CR_PASSBAD_ (0x00010000) +#define MAC_CR_HFILT_ (0x00008000) +#define MAC_CR_HPFILT_ (0x00002000) +#define MAC_CR_LCOLL_ (0x00001000) +#define MAC_CR_BCAST_ (0x00000800) +#define MAC_CR_DISRTY_ (0x00000400) +#define MAC_CR_PADSTR_ (0x00000100) +#define MAC_CR_BOLMT_MASK_ (0x000000C0) +#define MAC_CR_DFCHK_ (0x00000020) +#define MAC_CR_TXEN_ (0x00000008) +#define MAC_CR_RXEN_ (0x00000004) + +#define ADDRH (0x02) /* R/W mask 0x0000FFFFUL */ +#define ADDRL (0x03) /* R/W mask 0xFFFFFFFFUL */ +#define HASHH (0x04) /* R/W */ +#define HASHL (0x05) /* R/W */ + +#define MII_ACC (0x06) /* R/W */ +#define MII_ACC_PHY_ADDR_ (0x0000F800) +#define MII_ACC_MIIRINDA_ (0x000007C0) +#define MII_ACC_MII_WRITE_ (0x00000002) +#define MII_ACC_MII_BUSY_ (0x00000001) + +#define MII_DATA (0x07) /* R/W mask 0x0000FFFFUL */ + +#define FLOW (0x08) /* R/W */ +#define FLOW_FCPT_ (0xFFFF0000) +#define FLOW_FCPASS_ (0x00000004) +#define FLOW_FCEN_ (0x00000002) +#define FLOW_FCBSY_ (0x00000001) + +#define VLAN1 (0x09) /* R/W mask 0x0000FFFFUL */ +#define VLAN1_VTI1_ (0x0000ffff) + +#define VLAN2 (0x0A) /* R/W mask 0x0000FFFFUL */ +#define VLAN2_VTI2_ (0x0000ffff) + +#define WUFF (0x0B) /* WO */ + +#define WUCSR (0x0C) /* R/W */ +#define WUCSR_GUE_ (0x00000200) +#define WUCSR_WUFR_ (0x00000040) +#define WUCSR_MPR_ (0x00000020) +#define WUCSR_WAKE_EN_ (0x00000004) +#define WUCSR_MPEN_ (0x00000002) + +/* + **************************************************************************** + * Chip Specific MII Defines + **************************************************************************** + * + * Phy register offsets and bit definitions + * + */ + +#define PHY_MODE_CTRL_STS ((u32)17) /* Mode Control/Status Register */ +//#define MODE_CTRL_STS_FASTRIP_ ((u16)0x4000) +#define MODE_CTRL_STS_EDPWRDOWN_ ((u16)0x2000) +//#define MODE_CTRL_STS_LOWSQEN_ ((u16)0x0800) +//#define MODE_CTRL_STS_MDPREBP_ ((u16)0x0400) +//#define MODE_CTRL_STS_FARLOOPBACK_ ((u16)0x0200) +//#define MODE_CTRL_STS_FASTEST_ ((u16)0x0100) +//#define MODE_CTRL_STS_REFCLKEN_ ((u16)0x0010) +//#define MODE_CTRL_STS_PHYADBP_ ((u16)0x0008) +//#define MODE_CTRL_STS_FORCE_G_LINK_ ((u16)0x0004) +#define MODE_CTRL_STS_ENERGYON_ ((u16)0x0002) + +#define PHY_INT_SRC ((u32)29) +#define PHY_INT_SRC_ENERGY_ON_ ((u16)0x0080) +#define PHY_INT_SRC_ANEG_COMP_ ((u16)0x0040) +#define PHY_INT_SRC_REMOTE_FAULT_ ((u16)0x0020) +#define PHY_INT_SRC_LINK_DOWN_ ((u16)0x0010) +#define PHY_INT_SRC_ANEG_LP_ACK_ ((u16)0x0008) +#define PHY_INT_SRC_PAR_DET_FAULT_ ((u16)0x0004) +#define PHY_INT_SRC_ANEG_PGRX_ ((u16)0x0002) + +#define PHY_INT_MASK ((u32)30) +#define PHY_INT_MASK_ENERGY_ON_ ((u16)0x0080) +#define PHY_INT_MASK_ANEG_COMP_ ((u16)0x0040) +#define PHY_INT_MASK_REMOTE_FAULT_ ((u16)0x0020) +#define PHY_INT_MASK_LINK_DOWN_ ((u16)0x0010) +#define PHY_INT_MASK_ANEG_LP_ACK_ ((u16)0x0008) +#define PHY_INT_MASK_PAR_DET_FAULT_ ((u16)0x0004) +#define PHY_INT_MASK_ANEG_PGRX_ ((u16)0x0002) + +#define PHY_SPECIAL ((u32)31) +#define PHY_SPECIAL_ANEG_DONE_ ((u16)0x1000) +#define PHY_SPECIAL_RES_ ((u16)0x0040) +#define PHY_SPECIAL_RES_MASK_ ((u16)0x0FE1) +#define PHY_SPECIAL_SPD_ ((u16)0x001C) +#define PHY_SPECIAL_SPD_10HALF_ ((u16)0x0004) +#define PHY_SPECIAL_SPD_10FULL_ ((u16)0x0014) +#define PHY_SPECIAL_SPD_100HALF_ ((u16)0x0008) +#define PHY_SPECIAL_SPD_100FULL_ ((u16)0x0018) + +#define LAN911X_INTERNAL_PHY_ID (0x0007C000) + +/* Chip ID values */ +#define CHIP_9115 0x115 +#define CHIP_9116 0x116 +#define CHIP_9117 0x117 +#define CHIP_9118 0x118 + +struct chip_id { + u16 id; + char *name; +}; + +static const struct chip_id chip_ids[] = { + { CHIP_9115, "LAN9115" }, + { CHIP_9116, "LAN9116" }, + { CHIP_9117, "LAN9117" }, + { CHIP_9118, "LAN9118" }, + { 0, NULL }, +}; + +#define IS_REV_A(x) ((x & 0xFFFF)==0) + +/* + * Macros to abstract register access according to the data bus + * capabilities. Please use those and not the in/out primitives. + */ +/* FIFO read/write macros */ +#define SMC_PUSH_DATA(p, l) SMC_outsl( ioaddr, TX_DATA_FIFO, p, (l) >> 2 ) +#define SMC_PULL_DATA(p, l) SMC_insl ( ioaddr, RX_DATA_FIFO, p, (l) >> 2 ) +#define SMC_SET_TX_FIFO(x) SMC_outl( x, ioaddr, TX_DATA_FIFO ) +#define SMC_GET_RX_FIFO() SMC_inl( ioaddr, RX_DATA_FIFO ) + + +/* I/O mapped register read/write macros */ +#define SMC_GET_TX_STS_FIFO() SMC_inl( ioaddr, TX_STATUS_FIFO ) +#define SMC_GET_RX_STS_FIFO() SMC_inl( ioaddr, RX_STATUS_FIFO ) +#define SMC_GET_RX_STS_FIFO_PEEK() SMC_inl( ioaddr, RX_STATUS_FIFO_PEEK ) +#define SMC_GET_PN() (SMC_inl( ioaddr, ID_REV ) >> 16) +#define SMC_GET_REV() (SMC_inl( ioaddr, ID_REV ) & 0xFFFF) +#define SMC_GET_IRQ_CFG() SMC_inl( ioaddr, INT_CFG ) +#define SMC_SET_IRQ_CFG(x) SMC_outl( x, ioaddr, INT_CFG ) +#define SMC_GET_INT() SMC_inl( ioaddr, INT_STS ) +#define SMC_ACK_INT(x) SMC_outl( x, ioaddr, INT_STS ) +#define SMC_GET_INT_EN() SMC_inl( ioaddr, INT_EN ) +#define SMC_SET_INT_EN(x) SMC_outl( x, ioaddr, INT_EN ) +#define SMC_GET_BYTE_TEST() SMC_inl( ioaddr, BYTE_TEST ) +#define SMC_SET_BYTE_TEST(x) SMC_outl( x, ioaddr, BYTE_TEST ) +#define SMC_GET_FIFO_INT() SMC_inl( ioaddr, FIFO_INT ) +#define SMC_SET_FIFO_INT(x) SMC_outl( x, ioaddr, FIFO_INT ) +#define SMC_SET_FIFO_TDA(x) \ + do { \ + unsigned long __flags; \ + int __mask; \ + local_irq_save(__flags); \ + __mask = SMC_GET_FIFO_INT() & ~(0xFF<<24); \ + SMC_SET_FIFO_INT( __mask | (x)<<24 ); \ + local_irq_restore(__flags); \ + } while (0) +#define SMC_SET_FIFO_TSL(x) \ + do { \ + unsigned long __flags; \ + int __mask; \ + local_irq_save(__flags); \ + __mask = SMC_GET_FIFO_INT() & ~(0xFF<<16); \ + SMC_SET_FIFO_INT( __mask | (((x) & 0xFF)<<16)); \ + local_irq_restore(__flags); \ + } while (0) +#define SMC_SET_FIFO_RSA(x) \ + do { \ + unsigned long __flags; \ + int __mask; \ + local_irq_save(__flags); \ + __mask = SMC_GET_FIFO_INT() & ~(0xFF<<8); \ + SMC_SET_FIFO_INT( __mask | (((x) & 0xFF)<<8)); \ + local_irq_restore(__flags); \ + } while (0) +#define SMC_SET_FIFO_RSL(x) \ + do { \ + unsigned long __flags; \ + int __mask; \ + local_irq_save(__flags); \ + __mask = SMC_GET_FIFO_INT() & ~0xFF; \ + SMC_SET_FIFO_INT( __mask | ((x) & 0xFF)); \ + local_irq_restore(__flags); \ + } while (0) +#define SMC_GET_RX_CFG() SMC_inl( ioaddr, RX_CFG ) +#define SMC_SET_RX_CFG(x) SMC_outl( x, ioaddr, RX_CFG ) +#define SMC_GET_TX_CFG() SMC_inl( ioaddr, TX_CFG ) +#define SMC_SET_TX_CFG(x) SMC_outl( x, ioaddr, TX_CFG ) +#define SMC_GET_HW_CFG() SMC_inl( ioaddr, HW_CFG ) +#define SMC_SET_HW_CFG(x) SMC_outl( x, ioaddr, HW_CFG ) +#define SMC_GET_RX_DP_CTRL() SMC_inl( ioaddr, RX_DP_CTRL ) +#define SMC_SET_RX_DP_CTRL(x) SMC_outl( x, ioaddr, RX_DP_CTRL ) +#define SMC_GET_PMT_CTRL() SMC_inl( ioaddr, PMT_CTRL ) +#define SMC_SET_PMT_CTRL(x) SMC_outl( x, ioaddr, PMT_CTRL ) +#define SMC_GET_GPIO_CFG() SMC_inl( ioaddr, GPIO_CFG ) +#define SMC_SET_GPIO_CFG(x) SMC_outl( x, ioaddr, GPIO_CFG ) +#define SMC_GET_RX_FIFO_INF() SMC_inl( ioaddr, RX_FIFO_INF ) +#define SMC_SET_RX_FIFO_INF(x) SMC_outl( x, ioaddr, RX_FIFO_INF ) +#define SMC_GET_TX_FIFO_INF() SMC_inl( ioaddr, TX_FIFO_INF ) +#define SMC_SET_TX_FIFO_INF(x) SMC_outl( x, ioaddr, TX_FIFO_INF ) +#define SMC_GET_GPT_CFG() SMC_inl( ioaddr, GPT_CFG ) +#define SMC_SET_GPT_CFG(x) SMC_outl( x, ioaddr, GPT_CFG ) +#define SMC_GET_RX_DROP() SMC_inl( ioaddr, RX_DROP ) +#define SMC_SET_RX_DROP(x) SMC_outl( x, ioaddr, RX_DROP ) +#define SMC_GET_MAC_CMD() SMC_inl( ioaddr, MAC_CSR_CMD ) +#define SMC_SET_MAC_CMD(x) SMC_outl( x, ioaddr, MAC_CSR_CMD ) +#define SMC_GET_MAC_DATA() SMC_inl( ioaddr, MAC_CSR_DATA ) +#define SMC_SET_MAC_DATA(x) SMC_outl( x, ioaddr, MAC_CSR_DATA ) +#define SMC_GET_AFC_CFG() SMC_inl( ioaddr, AFC_CFG ) +#define SMC_SET_AFC_CFG(x) SMC_outl( x, ioaddr, AFC_CFG ) +#define SMC_GET_E2P_CMD() SMC_inl( ioaddr, E2P_CMD ) +#define SMC_SET_E2P_CMD(x) SMC_outl( x, ioaddr, E2P_CMD ) +#define SMC_GET_E2P_DATA() SMC_inl( ioaddr, E2P_DATA ) +#define SMC_SET_E2P_DATA(x) SMC_outl( x, ioaddr, E2P_DATA ) + +/* MAC register read/write macros */ +#define SMC_GET_MAC_CSR(a,v) \ + do { \ + while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ + SMC_SET_MAC_CMD(MAC_CSR_CMD_CSR_BUSY_ | \ + MAC_CSR_CMD_R_NOT_W_ | (a) ); \ + while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ + v = SMC_GET_MAC_DATA(); \ + } while (0) +#define SMC_SET_MAC_CSR(a,v) \ + do { \ + while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ + SMC_SET_MAC_DATA(v); \ + SMC_SET_MAC_CMD(MAC_CSR_CMD_CSR_BUSY_ | (a) ); \ + while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ + } while (0) +#define SMC_GET_MAC_CR(x) SMC_GET_MAC_CSR( MAC_CR, x ) +#define SMC_SET_MAC_CR(x) SMC_SET_MAC_CSR( MAC_CR, x ) +#define SMC_GET_ADDRH(x) SMC_GET_MAC_CSR( ADDRH, x ) +#define SMC_SET_ADDRH(x) SMC_SET_MAC_CSR( ADDRH, x ) +#define SMC_GET_ADDRL(x) SMC_GET_MAC_CSR( ADDRL, x ) +#define SMC_SET_ADDRL(x) SMC_SET_MAC_CSR( ADDRL, x ) +#define SMC_GET_HASHH(x) SMC_GET_MAC_CSR( HASHH, x ) +#define SMC_SET_HASHH(x) SMC_SET_MAC_CSR( HASHH, x ) +#define SMC_GET_HASHL(x) SMC_GET_MAC_CSR( HASHL, x ) +#define SMC_SET_HASHL(x) SMC_SET_MAC_CSR( HASHL, x ) +#define SMC_GET_MII_ACC(x) SMC_GET_MAC_CSR( MII_ACC, x ) +#define SMC_SET_MII_ACC(x) SMC_SET_MAC_CSR( MII_ACC, x ) +#define SMC_GET_MII_DATA(x) SMC_GET_MAC_CSR( MII_DATA, x ) +#define SMC_SET_MII_DATA(x) SMC_SET_MAC_CSR( MII_DATA, x ) +#define SMC_GET_FLOW(x) SMC_GET_MAC_CSR( FLOW, x ) +#define SMC_SET_FLOW(x) SMC_SET_MAC_CSR( FLOW, x ) +#define SMC_GET_VLAN1(x) SMC_GET_MAC_CSR( VLAN1, x ) +#define SMC_SET_VLAN1(x) SMC_SET_MAC_CSR( VLAN1, x ) +#define SMC_GET_VLAN2(x) SMC_GET_MAC_CSR( VLAN2, x ) +#define SMC_SET_VLAN2(x) SMC_SET_MAC_CSR( VLAN2, x ) +#define SMC_SET_WUFF(x) SMC_SET_MAC_CSR( WUFF, x ) +#define SMC_GET_WUCSR(x) SMC_GET_MAC_CSR( WUCSR, x ) +#define SMC_SET_WUCSR(x) SMC_SET_MAC_CSR( WUCSR, x ) + +/* PHY register read/write macros */ +#define SMC_GET_MII(a,phy,v) \ + do { \ + u32 __v; \ + do { \ + SMC_GET_MII_ACC(__v); \ + } while ( __v & MII_ACC_MII_BUSY_ ); \ + SMC_SET_MII_ACC( ((phy)<<11) | ((a)<<6) | \ + MII_ACC_MII_BUSY_); \ + do { \ + SMC_GET_MII_ACC(__v); \ + } while ( __v & MII_ACC_MII_BUSY_ ); \ + SMC_GET_MII_DATA(v); \ + } while (0) +#define SMC_SET_MII(a,phy,v) \ + do { \ + u32 __v; \ + do { \ + SMC_GET_MII_ACC(__v); \ + } while ( __v & MII_ACC_MII_BUSY_ ); \ + SMC_SET_MII_DATA(v); \ + SMC_SET_MII_ACC( ((phy)<<11) | ((a)<<6) | \ + MII_ACC_MII_BUSY_ | \ + MII_ACC_MII_WRITE_ ); \ + do { \ + SMC_GET_MII_ACC(__v); \ + } while ( __v & MII_ACC_MII_BUSY_ ); \ + } while (0) +#define SMC_GET_PHY_BMCR(phy,x) SMC_GET_MII( MII_BMCR, phy, x ) +#define SMC_SET_PHY_BMCR(phy,x) SMC_SET_MII( MII_BMCR, phy, x ) +#define SMC_GET_PHY_BMSR(phy,x) SMC_GET_MII( MII_BMSR, phy, x ) +#define SMC_GET_PHY_ID1(phy,x) SMC_GET_MII( MII_PHYSID1, phy, x ) +#define SMC_GET_PHY_ID2(phy,x) SMC_GET_MII( MII_PHYSID2, phy, x ) +#define SMC_GET_PHY_MII_ADV(phy,x) SMC_GET_MII( MII_ADVERTISE, phy, x ) +#define SMC_SET_PHY_MII_ADV(phy,x) SMC_SET_MII( MII_ADVERTISE, phy, x ) +#define SMC_GET_PHY_MII_LPA(phy,x) SMC_GET_MII( MII_LPA, phy, x ) +#define SMC_SET_PHY_MII_LPA(phy,x) SMC_SET_MII( MII_LPA, phy, x ) +#define SMC_GET_PHY_CTRL_STS(phy,x) SMC_GET_MII( PHY_MODE_CTRL_STS, phy, x ) +#define SMC_SET_PHY_CTRL_STS(phy,x) SMC_SET_MII( PHY_MODE_CTRL_STS, phy, x ) +#define SMC_GET_PHY_INT_SRC(phy,x) SMC_GET_MII( PHY_INT_SRC, phy, x ) +#define SMC_SET_PHY_INT_SRC(phy,x) SMC_SET_MII( PHY_INT_SRC, phy, x ) +#define SMC_GET_PHY_INT_MASK(phy,x) SMC_GET_MII( PHY_INT_MASK, phy, x ) +#define SMC_SET_PHY_INT_MASK(phy,x) SMC_SET_MII( PHY_INT_MASK, phy, x ) +#define SMC_GET_PHY_SPECIAL(phy,x) SMC_GET_MII( PHY_SPECIAL, phy, x ) + + + +/* Misc read/write macros */ + +#ifndef SMC_GET_MAC_ADDR +#define SMC_GET_MAC_ADDR(addr) \ + do { \ + unsigned int __v; \ + \ + SMC_GET_MAC_CSR(ADDRL, __v); \ + addr[0] = __v; addr[1] = __v >> 8; \ + addr[2] = __v >> 16; addr[3] = __v >> 24; \ + SMC_GET_MAC_CSR(ADDRH, __v); \ + addr[4] = __v; addr[5] = __v >> 8; \ + } while (0) +#endif + +#define SMC_SET_MAC_ADDR(addr) \ + do { \ + SMC_SET_MAC_CSR(ADDRL, \ + addr[0] | \ + (addr[1] << 8) | \ + (addr[2] << 16) | \ + (addr[3] << 24)); \ + SMC_SET_MAC_CSR(ADDRH, addr[4]|(addr[5] << 8));\ + } while (0) + + +#define SMC_WRITE_EEPROM_CMD(cmd, addr) \ + do { \ + while (SMC_GET_E2P_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ + SMC_SET_MAC_CMD(MAC_CSR_CMD_R_NOT_W_ | a ); \ + while (SMC_GET_MAC_CMD() & MAC_CSR_CMD_CSR_BUSY_); \ + } while (0) + +#endif /* _SMC911X_H_ */ diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c new file mode 100644 index 000000000..47f49ef72 --- /dev/null +++ b/drivers/net/ucc_geth.c @@ -0,0 +1,4278 @@ +/* + * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved. + * + * Author: Shlomi Gridish <gridish@freescale.com> + * + * Description: + * QE UCC Gigabit Ethernet Driver + * + * Changelog: + * Jul 6, 2006 Li Yang <LeoLi@freescale.com> + * - Rearrange code and style fixes + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/stddef.h> +#include <linux/interrupt.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/spinlock.h> +#include <linux/mm.h> +#include <linux/ethtool.h> +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <linux/fsl_devices.h> +#include <linux/ethtool.h> +#include <linux/platform_device.h> +#include <linux/mii.h> + +#include <asm/uaccess.h> +#include <asm/irq.h> +#include <asm/io.h> +#include <asm/immap_qe.h> +#include <asm/qe.h> +#include <asm/ucc.h> +#include <asm/ucc_fast.h> + +#include "ucc_geth.h" +#include "ucc_geth_phy.h" + +#undef DEBUG + +#define DRV_DESC "QE UCC Gigabit Ethernet Controller version:June 20, 2006" +#define DRV_NAME "ucc_geth" + +#define ugeth_printk(level, format, arg...) \ + printk(level format "\n", ## arg) + +#define ugeth_dbg(format, arg...) \ + ugeth_printk(KERN_DEBUG , format , ## arg) +#define ugeth_err(format, arg...) \ + ugeth_printk(KERN_ERR , format , ## arg) +#define ugeth_info(format, arg...) \ + ugeth_printk(KERN_INFO , format , ## arg) +#define ugeth_warn(format, arg...) \ + ugeth_printk(KERN_WARNING , format , ## arg) + +#ifdef UGETH_VERBOSE_DEBUG +#define ugeth_vdbg ugeth_dbg +#else +#define ugeth_vdbg(fmt, args...) do { } while (0) +#endif /* UGETH_VERBOSE_DEBUG */ + +static DEFINE_SPINLOCK(ugeth_lock); + +static ucc_geth_info_t ugeth_primary_info = { + .uf_info = { + .bd_mem_part = MEM_PART_SYSTEM, + .rtsm = UCC_FAST_SEND_IDLES_BETWEEN_FRAMES, + .max_rx_buf_length = 1536, +/* FIXME: should be changed in run time for 1G and 100M */ +#ifdef CONFIG_UGETH_HAS_GIGA + .urfs = UCC_GETH_URFS_GIGA_INIT, + .urfet = UCC_GETH_URFET_GIGA_INIT, + .urfset = UCC_GETH_URFSET_GIGA_INIT, + .utfs = UCC_GETH_UTFS_GIGA_INIT, + .utfet = UCC_GETH_UTFET_GIGA_INIT, + .utftt = UCC_GETH_UTFTT_GIGA_INIT, +#else + .urfs = UCC_GETH_URFS_INIT, + .urfet = UCC_GETH_URFET_INIT, + .urfset = UCC_GETH_URFSET_INIT, + .utfs = UCC_GETH_UTFS_INIT, + .utfet = UCC_GETH_UTFET_INIT, + .utftt = UCC_GETH_UTFTT_INIT, +#endif + .ufpt = 256, + .mode = UCC_FAST_PROTOCOL_MODE_ETHERNET, + .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL, + .tenc = UCC_FAST_TX_ENCODING_NRZ, + .renc = UCC_FAST_RX_ENCODING_NRZ, + .tcrc = UCC_FAST_16_BIT_CRC, + .synl = UCC_FAST_SYNC_LEN_NOT_USED, + }, + .numQueuesTx = 1, + .numQueuesRx = 1, + .extendedFilteringChainPointer = ((uint32_t) NULL), + .typeorlen = 3072 /*1536 */ , + .nonBackToBackIfgPart1 = 0x40, + .nonBackToBackIfgPart2 = 0x60, + .miminumInterFrameGapEnforcement = 0x50, + .backToBackInterFrameGap = 0x60, + .mblinterval = 128, + .nortsrbytetime = 5, + .fracsiz = 1, + .strictpriorityq = 0xff, + .altBebTruncation = 0xa, + .excessDefer = 1, + .maxRetransmission = 0xf, + .collisionWindow = 0x37, + .receiveFlowControl = 1, + .maxGroupAddrInHash = 4, + .maxIndAddrInHash = 4, + .prel = 7, + .maxFrameLength = 1518, + .minFrameLength = 64, + .maxD1Length = 1520, + .maxD2Length = 1520, + .vlantype = 0x8100, + .ecamptr = ((uint32_t) NULL), + .eventRegMask = UCCE_OTHER, + .pausePeriod = 0xf000, + .interruptcoalescingmaxvalue = {1, 1, 1, 1, 1, 1, 1, 1}, + .bdRingLenTx = { + TX_BD_RING_LEN, + TX_BD_RING_LEN, + TX_BD_RING_LEN, + TX_BD_RING_LEN, + TX_BD_RING_LEN, + TX_BD_RING_LEN, + TX_BD_RING_LEN, + TX_BD_RING_LEN}, + + .bdRingLenRx = { + RX_BD_RING_LEN, + RX_BD_RING_LEN, + RX_BD_RING_LEN, + RX_BD_RING_LEN, + RX_BD_RING_LEN, + RX_BD_RING_LEN, + RX_BD_RING_LEN, + RX_BD_RING_LEN}, + + .numStationAddresses = UCC_GETH_NUM_OF_STATION_ADDRESSES_1, + .largestexternallookupkeysize = + QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE, + .statisticsMode = UCC_GETH_STATISTICS_GATHERING_MODE_NONE, + .vlanOperationTagged = UCC_GETH_VLAN_OPERATION_TAGGED_NOP, + .vlanOperationNonTagged = UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP, + .rxQoSMode = UCC_GETH_QOS_MODE_DEFAULT, + .aufc = UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE, + .padAndCrc = MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC, + .numThreadsTx = UCC_GETH_NUM_OF_THREADS_4, + .numThreadsRx = UCC_GETH_NUM_OF_THREADS_4, + .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, + .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, +}; + +static ucc_geth_info_t ugeth_info[8]; + +#ifdef DEBUG +static void mem_disp(u8 *addr, int size) +{ + u8 *i; + int size16Aling = (size >> 4) << 4; + int size4Aling = (size >> 2) << 2; + int notAlign = 0; + if (size % 16) + notAlign = 1; + + for (i = addr; (u32) i < (u32) addr + size16Aling; i += 16) + printk("0x%08x: %08x %08x %08x %08x\r\n", + (u32) i, + *((u32 *) (i)), + *((u32 *) (i + 4)), + *((u32 *) (i + 8)), *((u32 *) (i + 12))); + if (notAlign == 1) + printk("0x%08x: ", (u32) i); + for (; (u32) i < (u32) addr + size4Aling; i += 4) + printk("%08x ", *((u32 *) (i))); + for (; (u32) i < (u32) addr + size; i++) + printk("%02x", *((u8 *) (i))); + if (notAlign == 1) + printk("\r\n"); +} +#endif /* DEBUG */ + +#ifdef CONFIG_UGETH_FILTERING +static void enqueue(struct list_head *node, struct list_head *lh) +{ + unsigned long flags; + + spin_lock_irqsave(ugeth_lock, flags); + list_add_tail(node, lh); + spin_unlock_irqrestore(ugeth_lock, flags); +} +#endif /* CONFIG_UGETH_FILTERING */ + +static struct list_head *dequeue(struct list_head *lh) +{ + unsigned long flags; + + spin_lock_irqsave(ugeth_lock, flags); + if (!list_empty(lh)) { + struct list_head *node = lh->next; + list_del(node); + spin_unlock_irqrestore(ugeth_lock, flags); + return node; + } else { + spin_unlock_irqrestore(ugeth_lock, flags); + return NULL; + } +} + +static int get_interface_details(enet_interface_e enet_interface, + enet_speed_e *speed, + int *r10m, + int *rmm, + int *rpm, + int *tbi, int *limited_to_full_duplex) +{ + /* Analyze enet_interface according to Interface Mode + Configuration table */ + switch (enet_interface) { + case ENET_10_MII: + *speed = ENET_SPEED_10BT; + break; + case ENET_10_RMII: + *speed = ENET_SPEED_10BT; + *r10m = 1; + *rmm = 1; + break; + case ENET_10_RGMII: + *speed = ENET_SPEED_10BT; + *rpm = 1; + *r10m = 1; + *limited_to_full_duplex = 1; + break; + case ENET_100_MII: + *speed = ENET_SPEED_100BT; + break; + case ENET_100_RMII: + *speed = ENET_SPEED_100BT; + *rmm = 1; + break; + case ENET_100_RGMII: + *speed = ENET_SPEED_100BT; + *rpm = 1; + *limited_to_full_duplex = 1; + break; + case ENET_1000_GMII: + *speed = ENET_SPEED_1000BT; + *limited_to_full_duplex = 1; + break; + case ENET_1000_RGMII: + *speed = ENET_SPEED_1000BT; + *rpm = 1; + *limited_to_full_duplex = 1; + break; + case ENET_1000_TBI: + *speed = ENET_SPEED_1000BT; + *tbi = 1; + *limited_to_full_duplex = 1; + break; + case ENET_1000_RTBI: + *speed = ENET_SPEED_1000BT; + *rpm = 1; + *tbi = 1; + *limited_to_full_duplex = 1; + break; + default: + return -EINVAL; + break; + } + + return 0; +} + +static struct sk_buff *get_new_skb(ucc_geth_private_t *ugeth, u8 *bd) +{ + struct sk_buff *skb = NULL; + + skb = dev_alloc_skb(ugeth->ug_info->uf_info.max_rx_buf_length + + UCC_GETH_RX_DATA_BUF_ALIGNMENT); + + if (skb == NULL) + return NULL; + + /* We need the data buffer to be aligned properly. We will reserve + * as many bytes as needed to align the data properly + */ + skb_reserve(skb, + UCC_GETH_RX_DATA_BUF_ALIGNMENT - + (((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT - + 1))); + + skb->dev = ugeth->dev; + + BD_BUFFER_SET(bd, + dma_map_single(NULL, + skb->data, + ugeth->ug_info->uf_info.max_rx_buf_length + + UCC_GETH_RX_DATA_BUF_ALIGNMENT, + DMA_FROM_DEVICE)); + + BD_STATUS_AND_LENGTH_SET(bd, + (R_E | R_I | + (BD_STATUS_AND_LENGTH(bd) & R_W))); + + return skb; +} + +static int rx_bd_buffer_set(ucc_geth_private_t *ugeth, u8 rxQ) +{ + u8 *bd; + u32 bd_status; + struct sk_buff *skb; + int i; + + bd = ugeth->p_rx_bd_ring[rxQ]; + i = 0; + + do { + bd_status = BD_STATUS_AND_LENGTH(bd); + skb = get_new_skb(ugeth, bd); + + if (!skb) /* If can not allocate data buffer, + abort. Cleanup will be elsewhere */ + return -ENOMEM; + + ugeth->rx_skbuff[rxQ][i] = skb; + + /* advance the BD pointer */ + bd += UCC_GETH_SIZE_OF_BD; + i++; + } while (!(bd_status & R_W)); + + return 0; +} + +static int fill_init_enet_entries(ucc_geth_private_t *ugeth, + volatile u32 *p_start, + u8 num_entries, + u32 thread_size, + u32 thread_alignment, + qe_risc_allocation_e risc, + int skip_page_for_first_entry) +{ + u32 init_enet_offset; + u8 i; + int snum; + + for (i = 0; i < num_entries; i++) { + if ((snum = qe_get_snum()) < 0) { + ugeth_err("fill_init_enet_entries: Can not get SNUM."); + return snum; + } + if ((i == 0) && skip_page_for_first_entry) + /* First entry of Rx does not have page */ + init_enet_offset = 0; + else { + init_enet_offset = + qe_muram_alloc(thread_size, thread_alignment); + if (IS_MURAM_ERR(init_enet_offset)) { + ugeth_err + ("fill_init_enet_entries: Can not allocate DPRAM memory."); + qe_put_snum((u8) snum); + return -ENOMEM; + } + } + *(p_start++) = + ((u8) snum << ENET_INIT_PARAM_SNUM_SHIFT) | init_enet_offset + | risc; + } + + return 0; +} + +static int return_init_enet_entries(ucc_geth_private_t *ugeth, + volatile u32 *p_start, + u8 num_entries, + qe_risc_allocation_e risc, + int skip_page_for_first_entry) +{ + u32 init_enet_offset; + u8 i; + int snum; + + for (i = 0; i < num_entries; i++) { + /* Check that this entry was actually valid -- + needed in case failed in allocations */ + if ((*p_start & ENET_INIT_PARAM_RISC_MASK) == risc) { + snum = + (u32) (*p_start & ENET_INIT_PARAM_SNUM_MASK) >> + ENET_INIT_PARAM_SNUM_SHIFT; + qe_put_snum((u8) snum); + if (!((i == 0) && skip_page_for_first_entry)) { + /* First entry of Rx does not have page */ + init_enet_offset = + (in_be32(p_start) & + ENET_INIT_PARAM_PTR_MASK); + qe_muram_free(init_enet_offset); + } + *(p_start++) = 0; /* Just for cosmetics */ + } + } + + return 0; +} + +#ifdef DEBUG +static int dump_init_enet_entries(ucc_geth_private_t *ugeth, + volatile u32 *p_start, + u8 num_entries, + u32 thread_size, + qe_risc_allocation_e risc, + int skip_page_for_first_entry) +{ + u32 init_enet_offset; + u8 i; + int snum; + + for (i = 0; i < num_entries; i++) { + /* Check that this entry was actually valid -- + needed in case failed in allocations */ + if ((*p_start & ENET_INIT_PARAM_RISC_MASK) == risc) { + snum = + (u32) (*p_start & ENET_INIT_PARAM_SNUM_MASK) >> + ENET_INIT_PARAM_SNUM_SHIFT; + qe_put_snum((u8) snum); + if (!((i == 0) && skip_page_for_first_entry)) { + /* First entry of Rx does not have page */ + init_enet_offset = + (in_be32(p_start) & + ENET_INIT_PARAM_PTR_MASK); + ugeth_info("Init enet entry %d:", i); + ugeth_info("Base address: 0x%08x", + (u32) + qe_muram_addr(init_enet_offset)); + mem_disp(qe_muram_addr(init_enet_offset), + thread_size); + } + p_start++; + } + } + + return 0; +} +#endif + +#ifdef CONFIG_UGETH_FILTERING +static enet_addr_container_t *get_enet_addr_container(void) +{ + enet_addr_container_t *enet_addr_cont; + + /* allocate memory */ + enet_addr_cont = kmalloc(sizeof(enet_addr_container_t), GFP_KERNEL); + if (!enet_addr_cont) { + ugeth_err("%s: No memory for enet_addr_container_t object.", + __FUNCTION__); + return NULL; + } + + return enet_addr_cont; +} +#endif /* CONFIG_UGETH_FILTERING */ + +static void put_enet_addr_container(enet_addr_container_t *enet_addr_cont) +{ + kfree(enet_addr_cont); +} + +#ifdef CONFIG_UGETH_FILTERING +static int hw_add_addr_in_paddr(ucc_geth_private_t *ugeth, + enet_addr_t *p_enet_addr, u8 paddr_num) +{ + ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; + + if (!(paddr_num < NUM_OF_PADDRS)) { + ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__); + return -EINVAL; + } + + p_82xx_addr_filt = + (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram-> + addressfiltering; + + /* Ethernet frames are defined in Little Endian mode, */ + /* therefore to insert the address we reverse the bytes. */ + out_be16(&p_82xx_addr_filt->paddr[paddr_num].h, + (u16) (((u16) (((u16) ((*p_enet_addr)[5])) << 8)) | + (u16) (*p_enet_addr)[4])); + out_be16(&p_82xx_addr_filt->paddr[paddr_num].m, + (u16) (((u16) (((u16) ((*p_enet_addr)[3])) << 8)) | + (u16) (*p_enet_addr)[2])); + out_be16(&p_82xx_addr_filt->paddr[paddr_num].l, + (u16) (((u16) (((u16) ((*p_enet_addr)[1])) << 8)) | + (u16) (*p_enet_addr)[0])); + + return 0; +} +#endif /* CONFIG_UGETH_FILTERING */ + +static int hw_clear_addr_in_paddr(ucc_geth_private_t *ugeth, u8 paddr_num) +{ + ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; + + if (!(paddr_num < NUM_OF_PADDRS)) { + ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__); + return -EINVAL; + } + + p_82xx_addr_filt = + (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram-> + addressfiltering; + + /* Writing address ff.ff.ff.ff.ff.ff disables address + recognition for this register */ + out_be16(&p_82xx_addr_filt->paddr[paddr_num].h, 0xffff); + out_be16(&p_82xx_addr_filt->paddr[paddr_num].m, 0xffff); + out_be16(&p_82xx_addr_filt->paddr[paddr_num].l, 0xffff); + + return 0; +} + +static void hw_add_addr_in_hash(ucc_geth_private_t *ugeth, + enet_addr_t *p_enet_addr) +{ + ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; + u32 cecr_subblock; + + p_82xx_addr_filt = + (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram-> + addressfiltering; + + cecr_subblock = + ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); + + /* Ethernet frames are defined in Little Endian mode, + therefor to insert */ + /* the address to the hash (Big Endian mode), we reverse the bytes.*/ + out_be16(&p_82xx_addr_filt->taddr.h, + (u16) (((u16) (((u16) ((*p_enet_addr)[5])) << 8)) | + (u16) (*p_enet_addr)[4])); + out_be16(&p_82xx_addr_filt->taddr.m, + (u16) (((u16) (((u16) ((*p_enet_addr)[3])) << 8)) | + (u16) (*p_enet_addr)[2])); + out_be16(&p_82xx_addr_filt->taddr.l, + (u16) (((u16) (((u16) ((*p_enet_addr)[1])) << 8)) | + (u16) (*p_enet_addr)[0])); + + qe_issue_cmd(QE_SET_GROUP_ADDRESS, cecr_subblock, + (u8) QE_CR_PROTOCOL_ETHERNET, 0); +} + +#ifdef CONFIG_UGETH_MAGIC_PACKET +static void magic_packet_detection_enable(ucc_geth_private_t *ugeth) +{ + ucc_fast_private_t *uccf; + ucc_geth_t *ug_regs; + u32 maccfg2, uccm; + + uccf = ugeth->uccf; + ug_regs = ugeth->ug_regs; + + /* Enable interrupts for magic packet detection */ + uccm = in_be32(uccf->p_uccm); + uccm |= UCCE_MPD; + out_be32(uccf->p_uccm, uccm); + + /* Enable magic packet detection */ + maccfg2 = in_be32(&ug_regs->maccfg2); + maccfg2 |= MACCFG2_MPE; + out_be32(&ug_regs->maccfg2, maccfg2); +} + +static void magic_packet_detection_disable(ucc_geth_private_t *ugeth) +{ + ucc_fast_private_t *uccf; + ucc_geth_t *ug_regs; + u32 maccfg2, uccm; + + uccf = ugeth->uccf; + ug_regs = ugeth->ug_regs; + + /* Disable interrupts for magic packet detection */ + uccm = in_be32(uccf->p_uccm); + uccm &= ~UCCE_MPD; + out_be32(uccf->p_uccm, uccm); + + /* Disable magic packet detection */ + maccfg2 = in_be32(&ug_regs->maccfg2); + maccfg2 &= ~MACCFG2_MPE; + out_be32(&ug_regs->maccfg2, maccfg2); +} +#endif /* MAGIC_PACKET */ + +static inline int compare_addr(enet_addr_t *addr1, enet_addr_t *addr2) +{ + return memcmp(addr1, addr2, ENET_NUM_OCTETS_PER_ADDRESS); +} + +#ifdef DEBUG +static void get_statistics(ucc_geth_private_t *ugeth, + ucc_geth_tx_firmware_statistics_t * + tx_firmware_statistics, + ucc_geth_rx_firmware_statistics_t * + rx_firmware_statistics, + ucc_geth_hardware_statistics_t *hardware_statistics) +{ + ucc_fast_t *uf_regs; + ucc_geth_t *ug_regs; + ucc_geth_tx_firmware_statistics_pram_t *p_tx_fw_statistics_pram; + ucc_geth_rx_firmware_statistics_pram_t *p_rx_fw_statistics_pram; + + ug_regs = ugeth->ug_regs; + uf_regs = (ucc_fast_t *) ug_regs; + p_tx_fw_statistics_pram = ugeth->p_tx_fw_statistics_pram; + p_rx_fw_statistics_pram = ugeth->p_rx_fw_statistics_pram; + + /* Tx firmware only if user handed pointer and driver actually + gathers Tx firmware statistics */ + if (tx_firmware_statistics && p_tx_fw_statistics_pram) { + tx_firmware_statistics->sicoltx = + in_be32(&p_tx_fw_statistics_pram->sicoltx); + tx_firmware_statistics->mulcoltx = + in_be32(&p_tx_fw_statistics_pram->mulcoltx); + tx_firmware_statistics->latecoltxfr = + in_be32(&p_tx_fw_statistics_pram->latecoltxfr); + tx_firmware_statistics->frabortduecol = + in_be32(&p_tx_fw_statistics_pram->frabortduecol); + tx_firmware_statistics->frlostinmactxer = + in_be32(&p_tx_fw_statistics_pram->frlostinmactxer); + tx_firmware_statistics->carriersenseertx = + in_be32(&p_tx_fw_statistics_pram->carriersenseertx); + tx_firmware_statistics->frtxok = + in_be32(&p_tx_fw_statistics_pram->frtxok); + tx_firmware_statistics->txfrexcessivedefer = + in_be32(&p_tx_fw_statistics_pram->txfrexcessivedefer); + tx_firmware_statistics->txpkts256 = + in_be32(&p_tx_fw_statistics_pram->txpkts256); + tx_firmware_statistics->txpkts512 = + in_be32(&p_tx_fw_statistics_pram->txpkts512); + tx_firmware_statistics->txpkts1024 = + in_be32(&p_tx_fw_statistics_pram->txpkts1024); + tx_firmware_statistics->txpktsjumbo = + in_be32(&p_tx_fw_statistics_pram->txpktsjumbo); + } + + /* Rx firmware only if user handed pointer and driver actually + * gathers Rx firmware statistics */ + if (rx_firmware_statistics && p_rx_fw_statistics_pram) { + int i; + rx_firmware_statistics->frrxfcser = + in_be32(&p_rx_fw_statistics_pram->frrxfcser); + rx_firmware_statistics->fraligner = + in_be32(&p_rx_fw_statistics_pram->fraligner); + rx_firmware_statistics->inrangelenrxer = + in_be32(&p_rx_fw_statistics_pram->inrangelenrxer); + rx_firmware_statistics->outrangelenrxer = + in_be32(&p_rx_fw_statistics_pram->outrangelenrxer); + rx_firmware_statistics->frtoolong = + in_be32(&p_rx_fw_statistics_pram->frtoolong); + rx_firmware_statistics->runt = + in_be32(&p_rx_fw_statistics_pram->runt); + rx_firmware_statistics->verylongevent = + in_be32(&p_rx_fw_statistics_pram->verylongevent); + rx_firmware_statistics->symbolerror = + in_be32(&p_rx_fw_statistics_pram->symbolerror); + rx_firmware_statistics->dropbsy = + in_be32(&p_rx_fw_statistics_pram->dropbsy); + for (i = 0; i < 0x8; i++) + rx_firmware_statistics->res0[i] = + p_rx_fw_statistics_pram->res0[i]; + rx_firmware_statistics->mismatchdrop = + in_be32(&p_rx_fw_statistics_pram->mismatchdrop); + rx_firmware_statistics->underpkts = + in_be32(&p_rx_fw_statistics_pram->underpkts); + rx_firmware_statistics->pkts256 = + in_be32(&p_rx_fw_statistics_pram->pkts256); + rx_firmware_statistics->pkts512 = + in_be32(&p_rx_fw_statistics_pram->pkts512); + rx_firmware_statistics->pkts1024 = + in_be32(&p_rx_fw_statistics_pram->pkts1024); + rx_firmware_statistics->pktsjumbo = + in_be32(&p_rx_fw_statistics_pram->pktsjumbo); + rx_firmware_statistics->frlossinmacer = + in_be32(&p_rx_fw_statistics_pram->frlossinmacer); + rx_firmware_statistics->pausefr = + in_be32(&p_rx_fw_statistics_pram->pausefr); + for (i = 0; i < 0x4; i++) + rx_firmware_statistics->res1[i] = + p_rx_fw_statistics_pram->res1[i]; + rx_firmware_statistics->removevlan = + in_be32(&p_rx_fw_statistics_pram->removevlan); + rx_firmware_statistics->replacevlan = + in_be32(&p_rx_fw_statistics_pram->replacevlan); + rx_firmware_statistics->insertvlan = + in_be32(&p_rx_fw_statistics_pram->insertvlan); + } + + /* Hardware only if user handed pointer and driver actually + gathers hardware statistics */ + if (hardware_statistics && (in_be32(&uf_regs->upsmr) & UPSMR_HSE)) { + hardware_statistics->tx64 = in_be32(&ug_regs->tx64); + hardware_statistics->tx127 = in_be32(&ug_regs->tx127); + hardware_statistics->tx255 = in_be32(&ug_regs->tx255); + hardware_statistics->rx64 = in_be32(&ug_regs->rx64); + hardware_statistics->rx127 = in_be32(&ug_regs->rx127); + hardware_statistics->rx255 = in_be32(&ug_regs->rx255); + hardware_statistics->txok = in_be32(&ug_regs->txok); + hardware_statistics->txcf = in_be16(&ug_regs->txcf); + hardware_statistics->tmca = in_be32(&ug_regs->tmca); + hardware_statistics->tbca = in_be32(&ug_regs->tbca); + hardware_statistics->rxfok = in_be32(&ug_regs->rxfok); + hardware_statistics->rxbok = in_be32(&ug_regs->rxbok); + hardware_statistics->rbyt = in_be32(&ug_regs->rbyt); + hardware_statistics->rmca = in_be32(&ug_regs->rmca); + hardware_statistics->rbca = in_be32(&ug_regs->rbca); + } +} + +static void dump_bds(ucc_geth_private_t *ugeth) +{ + int i; + int length; + + for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) { + if (ugeth->p_tx_bd_ring[i]) { + length = + (ugeth->ug_info->bdRingLenTx[i] * + UCC_GETH_SIZE_OF_BD); + ugeth_info("TX BDs[%d]", i); + mem_disp(ugeth->p_tx_bd_ring[i], length); + } + } + for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) { + if (ugeth->p_rx_bd_ring[i]) { + length = + (ugeth->ug_info->bdRingLenRx[i] * + UCC_GETH_SIZE_OF_BD); + ugeth_info("RX BDs[%d]", i); + mem_disp(ugeth->p_rx_bd_ring[i], length); + } + } +} + +static void dump_regs(ucc_geth_private_t *ugeth) +{ + int i; + + ugeth_info("UCC%d Geth registers:", ugeth->ug_info->uf_info.ucc_num); + ugeth_info("Base address: 0x%08x", (u32) ugeth->ug_regs); + + ugeth_info("maccfg1 : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->maccfg1, + in_be32(&ugeth->ug_regs->maccfg1)); + ugeth_info("maccfg2 : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->maccfg2, + in_be32(&ugeth->ug_regs->maccfg2)); + ugeth_info("ipgifg : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->ipgifg, + in_be32(&ugeth->ug_regs->ipgifg)); + ugeth_info("hafdup : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->hafdup, + in_be32(&ugeth->ug_regs->hafdup)); + ugeth_info("miimcfg : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->miimng.miimcfg, + in_be32(&ugeth->ug_regs->miimng.miimcfg)); + ugeth_info("miimcom : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->miimng.miimcom, + in_be32(&ugeth->ug_regs->miimng.miimcom)); + ugeth_info("miimadd : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->miimng.miimadd, + in_be32(&ugeth->ug_regs->miimng.miimadd)); + ugeth_info("miimcon : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->miimng.miimcon, + in_be32(&ugeth->ug_regs->miimng.miimcon)); + ugeth_info("miimstat : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->miimng.miimstat, + in_be32(&ugeth->ug_regs->miimng.miimstat)); + ugeth_info("miimmind : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->miimng.miimind, + in_be32(&ugeth->ug_regs->miimng.miimind)); + ugeth_info("ifctl : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->ifctl, + in_be32(&ugeth->ug_regs->ifctl)); + ugeth_info("ifstat : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->ifstat, + in_be32(&ugeth->ug_regs->ifstat)); + ugeth_info("macstnaddr1: addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->macstnaddr1, + in_be32(&ugeth->ug_regs->macstnaddr1)); + ugeth_info("macstnaddr2: addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->macstnaddr2, + in_be32(&ugeth->ug_regs->macstnaddr2)); + ugeth_info("uempr : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->uempr, + in_be32(&ugeth->ug_regs->uempr)); + ugeth_info("utbipar : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->utbipar, + in_be32(&ugeth->ug_regs->utbipar)); + ugeth_info("uescr : addr - 0x%08x, val - 0x%04x", + (u32) & ugeth->ug_regs->uescr, + in_be16(&ugeth->ug_regs->uescr)); + ugeth_info("tx64 : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->tx64, + in_be32(&ugeth->ug_regs->tx64)); + ugeth_info("tx127 : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->tx127, + in_be32(&ugeth->ug_regs->tx127)); + ugeth_info("tx255 : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->tx255, + in_be32(&ugeth->ug_regs->tx255)); + ugeth_info("rx64 : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->rx64, + in_be32(&ugeth->ug_regs->rx64)); + ugeth_info("rx127 : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->rx127, + in_be32(&ugeth->ug_regs->rx127)); + ugeth_info("rx255 : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->rx255, + in_be32(&ugeth->ug_regs->rx255)); + ugeth_info("txok : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->txok, + in_be32(&ugeth->ug_regs->txok)); + ugeth_info("txcf : addr - 0x%08x, val - 0x%04x", + (u32) & ugeth->ug_regs->txcf, + in_be16(&ugeth->ug_regs->txcf)); + ugeth_info("tmca : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->tmca, + in_be32(&ugeth->ug_regs->tmca)); + ugeth_info("tbca : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->tbca, + in_be32(&ugeth->ug_regs->tbca)); + ugeth_info("rxfok : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->rxfok, + in_be32(&ugeth->ug_regs->rxfok)); + ugeth_info("rxbok : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->rxbok, + in_be32(&ugeth->ug_regs->rxbok)); + ugeth_info("rbyt : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->rbyt, + in_be32(&ugeth->ug_regs->rbyt)); + ugeth_info("rmca : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->rmca, + in_be32(&ugeth->ug_regs->rmca)); + ugeth_info("rbca : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->rbca, + in_be32(&ugeth->ug_regs->rbca)); + ugeth_info("scar : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->scar, + in_be32(&ugeth->ug_regs->scar)); + ugeth_info("scam : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->ug_regs->scam, + in_be32(&ugeth->ug_regs->scam)); + + if (ugeth->p_thread_data_tx) { + int numThreadsTxNumerical; + switch (ugeth->ug_info->numThreadsTx) { + case UCC_GETH_NUM_OF_THREADS_1: + numThreadsTxNumerical = 1; + break; + case UCC_GETH_NUM_OF_THREADS_2: + numThreadsTxNumerical = 2; + break; + case UCC_GETH_NUM_OF_THREADS_4: + numThreadsTxNumerical = 4; + break; + case UCC_GETH_NUM_OF_THREADS_6: + numThreadsTxNumerical = 6; + break; + case UCC_GETH_NUM_OF_THREADS_8: + numThreadsTxNumerical = 8; + break; + default: + numThreadsTxNumerical = 0; + break; + } + + ugeth_info("Thread data TXs:"); + ugeth_info("Base address: 0x%08x", + (u32) ugeth->p_thread_data_tx); + for (i = 0; i < numThreadsTxNumerical; i++) { + ugeth_info("Thread data TX[%d]:", i); + ugeth_info("Base address: 0x%08x", + (u32) & ugeth->p_thread_data_tx[i]); + mem_disp((u8 *) & ugeth->p_thread_data_tx[i], + sizeof(ucc_geth_thread_data_tx_t)); + } + } + if (ugeth->p_thread_data_rx) { + int numThreadsRxNumerical; + switch (ugeth->ug_info->numThreadsRx) { + case UCC_GETH_NUM_OF_THREADS_1: + numThreadsRxNumerical = 1; + break; + case UCC_GETH_NUM_OF_THREADS_2: + numThreadsRxNumerical = 2; + break; + case UCC_GETH_NUM_OF_THREADS_4: + numThreadsRxNumerical = 4; + break; + case UCC_GETH_NUM_OF_THREADS_6: + numThreadsRxNumerical = 6; + break; + case UCC_GETH_NUM_OF_THREADS_8: + numThreadsRxNumerical = 8; + break; + default: + numThreadsRxNumerical = 0; + break; + } + + ugeth_info("Thread data RX:"); + ugeth_info("Base address: 0x%08x", + (u32) ugeth->p_thread_data_rx); + for (i = 0; i < numThreadsRxNumerical; i++) { + ugeth_info("Thread data RX[%d]:", i); + ugeth_info("Base address: 0x%08x", + (u32) & ugeth->p_thread_data_rx[i]); + mem_disp((u8 *) & ugeth->p_thread_data_rx[i], + sizeof(ucc_geth_thread_data_rx_t)); + } + } + if (ugeth->p_exf_glbl_param) { + ugeth_info("EXF global param:"); + ugeth_info("Base address: 0x%08x", + (u32) ugeth->p_exf_glbl_param); + mem_disp((u8 *) ugeth->p_exf_glbl_param, + sizeof(*ugeth->p_exf_glbl_param)); + } + if (ugeth->p_tx_glbl_pram) { + ugeth_info("TX global param:"); + ugeth_info("Base address: 0x%08x", (u32) ugeth->p_tx_glbl_pram); + ugeth_info("temoder : addr - 0x%08x, val - 0x%04x", + (u32) & ugeth->p_tx_glbl_pram->temoder, + in_be16(&ugeth->p_tx_glbl_pram->temoder)); + ugeth_info("sqptr : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_tx_glbl_pram->sqptr, + in_be32(&ugeth->p_tx_glbl_pram->sqptr)); + ugeth_info("schedulerbasepointer: addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_tx_glbl_pram->schedulerbasepointer, + in_be32(&ugeth->p_tx_glbl_pram-> + schedulerbasepointer)); + ugeth_info("txrmonbaseptr: addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_tx_glbl_pram->txrmonbaseptr, + in_be32(&ugeth->p_tx_glbl_pram->txrmonbaseptr)); + ugeth_info("tstate : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_tx_glbl_pram->tstate, + in_be32(&ugeth->p_tx_glbl_pram->tstate)); + ugeth_info("iphoffset[0] : addr - 0x%08x, val - 0x%02x", + (u32) & ugeth->p_tx_glbl_pram->iphoffset[0], + ugeth->p_tx_glbl_pram->iphoffset[0]); + ugeth_info("iphoffset[1] : addr - 0x%08x, val - 0x%02x", + (u32) & ugeth->p_tx_glbl_pram->iphoffset[1], + ugeth->p_tx_glbl_pram->iphoffset[1]); + ugeth_info("iphoffset[2] : addr - 0x%08x, val - 0x%02x", + (u32) & ugeth->p_tx_glbl_pram->iphoffset[2], + ugeth->p_tx_glbl_pram->iphoffset[2]); + ugeth_info("iphoffset[3] : addr - 0x%08x, val - 0x%02x", + (u32) & ugeth->p_tx_glbl_pram->iphoffset[3], + ugeth->p_tx_glbl_pram->iphoffset[3]); + ugeth_info("iphoffset[4] : addr - 0x%08x, val - 0x%02x", + (u32) & ugeth->p_tx_glbl_pram->iphoffset[4], + ugeth->p_tx_glbl_pram->iphoffset[4]); + ugeth_info("iphoffset[5] : addr - 0x%08x, val - 0x%02x", + (u32) & ugeth->p_tx_glbl_pram->iphoffset[5], + ugeth->p_tx_glbl_pram->iphoffset[5]); + ugeth_info("iphoffset[6] : addr - 0x%08x, val - 0x%02x", + (u32) & ugeth->p_tx_glbl_pram->iphoffset[6], + ugeth->p_tx_glbl_pram->iphoffset[6]); + ugeth_info("iphoffset[7] : addr - 0x%08x, val - 0x%02x", + (u32) & ugeth->p_tx_glbl_pram->iphoffset[7], + ugeth->p_tx_glbl_pram->iphoffset[7]); + ugeth_info("vtagtable[0] : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_tx_glbl_pram->vtagtable[0], + in_be32(&ugeth->p_tx_glbl_pram->vtagtable[0])); + ugeth_info("vtagtable[1] : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_tx_glbl_pram->vtagtable[1], + in_be32(&ugeth->p_tx_glbl_pram->vtagtable[1])); + ugeth_info("vtagtable[2] : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_tx_glbl_pram->vtagtable[2], + in_be32(&ugeth->p_tx_glbl_pram->vtagtable[2])); + ugeth_info("vtagtable[3] : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_tx_glbl_pram->vtagtable[3], + in_be32(&ugeth->p_tx_glbl_pram->vtagtable[3])); + ugeth_info("vtagtable[4] : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_tx_glbl_pram->vtagtable[4], + in_be32(&ugeth->p_tx_glbl_pram->vtagtable[4])); + ugeth_info("vtagtable[5] : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_tx_glbl_pram->vtagtable[5], + in_be32(&ugeth->p_tx_glbl_pram->vtagtable[5])); + ugeth_info("vtagtable[6] : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_tx_glbl_pram->vtagtable[6], + in_be32(&ugeth->p_tx_glbl_pram->vtagtable[6])); + ugeth_info("vtagtable[7] : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_tx_glbl_pram->vtagtable[7], + in_be32(&ugeth->p_tx_glbl_pram->vtagtable[7])); + ugeth_info("tqptr : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_tx_glbl_pram->tqptr, + in_be32(&ugeth->p_tx_glbl_pram->tqptr)); + } + if (ugeth->p_rx_glbl_pram) { + ugeth_info("RX global param:"); + ugeth_info("Base address: 0x%08x", (u32) ugeth->p_rx_glbl_pram); + ugeth_info("remoder : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_glbl_pram->remoder, + in_be32(&ugeth->p_rx_glbl_pram->remoder)); + ugeth_info("rqptr : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_glbl_pram->rqptr, + in_be32(&ugeth->p_rx_glbl_pram->rqptr)); + ugeth_info("typeorlen : addr - 0x%08x, val - 0x%04x", + (u32) & ugeth->p_rx_glbl_pram->typeorlen, + in_be16(&ugeth->p_rx_glbl_pram->typeorlen)); + ugeth_info("rxgstpack : addr - 0x%08x, val - 0x%02x", + (u32) & ugeth->p_rx_glbl_pram->rxgstpack, + ugeth->p_rx_glbl_pram->rxgstpack); + ugeth_info("rxrmonbaseptr : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_glbl_pram->rxrmonbaseptr, + in_be32(&ugeth->p_rx_glbl_pram->rxrmonbaseptr)); + ugeth_info("intcoalescingptr: addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_glbl_pram->intcoalescingptr, + in_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr)); + ugeth_info("rstate : addr - 0x%08x, val - 0x%02x", + (u32) & ugeth->p_rx_glbl_pram->rstate, + ugeth->p_rx_glbl_pram->rstate); + ugeth_info("mrblr : addr - 0x%08x, val - 0x%04x", + (u32) & ugeth->p_rx_glbl_pram->mrblr, + in_be16(&ugeth->p_rx_glbl_pram->mrblr)); + ugeth_info("rbdqptr : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_glbl_pram->rbdqptr, + in_be32(&ugeth->p_rx_glbl_pram->rbdqptr)); + ugeth_info("mflr : addr - 0x%08x, val - 0x%04x", + (u32) & ugeth->p_rx_glbl_pram->mflr, + in_be16(&ugeth->p_rx_glbl_pram->mflr)); + ugeth_info("minflr : addr - 0x%08x, val - 0x%04x", + (u32) & ugeth->p_rx_glbl_pram->minflr, + in_be16(&ugeth->p_rx_glbl_pram->minflr)); + ugeth_info("maxd1 : addr - 0x%08x, val - 0x%04x", + (u32) & ugeth->p_rx_glbl_pram->maxd1, + in_be16(&ugeth->p_rx_glbl_pram->maxd1)); + ugeth_info("maxd2 : addr - 0x%08x, val - 0x%04x", + (u32) & ugeth->p_rx_glbl_pram->maxd2, + in_be16(&ugeth->p_rx_glbl_pram->maxd2)); + ugeth_info("ecamptr : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_glbl_pram->ecamptr, + in_be32(&ugeth->p_rx_glbl_pram->ecamptr)); + ugeth_info("l2qt : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_glbl_pram->l2qt, + in_be32(&ugeth->p_rx_glbl_pram->l2qt)); + ugeth_info("l3qt[0] : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_glbl_pram->l3qt[0], + in_be32(&ugeth->p_rx_glbl_pram->l3qt[0])); + ugeth_info("l3qt[1] : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_glbl_pram->l3qt[1], + in_be32(&ugeth->p_rx_glbl_pram->l3qt[1])); + ugeth_info("l3qt[2] : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_glbl_pram->l3qt[2], + in_be32(&ugeth->p_rx_glbl_pram->l3qt[2])); + ugeth_info("l3qt[3] : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_glbl_pram->l3qt[3], + in_be32(&ugeth->p_rx_glbl_pram->l3qt[3])); + ugeth_info("l3qt[4] : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_glbl_pram->l3qt[4], + in_be32(&ugeth->p_rx_glbl_pram->l3qt[4])); + ugeth_info("l3qt[5] : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_glbl_pram->l3qt[5], + in_be32(&ugeth->p_rx_glbl_pram->l3qt[5])); + ugeth_info("l3qt[6] : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_glbl_pram->l3qt[6], + in_be32(&ugeth->p_rx_glbl_pram->l3qt[6])); + ugeth_info("l3qt[7] : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_glbl_pram->l3qt[7], + in_be32(&ugeth->p_rx_glbl_pram->l3qt[7])); + ugeth_info("vlantype : addr - 0x%08x, val - 0x%04x", + (u32) & ugeth->p_rx_glbl_pram->vlantype, + in_be16(&ugeth->p_rx_glbl_pram->vlantype)); + ugeth_info("vlantci : addr - 0x%08x, val - 0x%04x", + (u32) & ugeth->p_rx_glbl_pram->vlantci, + in_be16(&ugeth->p_rx_glbl_pram->vlantci)); + for (i = 0; i < 64; i++) + ugeth_info + ("addressfiltering[%d]: addr - 0x%08x, val - 0x%02x", + i, + (u32) & ugeth->p_rx_glbl_pram->addressfiltering[i], + ugeth->p_rx_glbl_pram->addressfiltering[i]); + ugeth_info("exfGlobalParam : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_glbl_pram->exfGlobalParam, + in_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam)); + } + if (ugeth->p_send_q_mem_reg) { + ugeth_info("Send Q memory registers:"); + ugeth_info("Base address: 0x%08x", + (u32) ugeth->p_send_q_mem_reg); + for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) { + ugeth_info("SQQD[%d]:", i); + ugeth_info("Base address: 0x%08x", + (u32) & ugeth->p_send_q_mem_reg->sqqd[i]); + mem_disp((u8 *) & ugeth->p_send_q_mem_reg->sqqd[i], + sizeof(ucc_geth_send_queue_qd_t)); + } + } + if (ugeth->p_scheduler) { + ugeth_info("Scheduler:"); + ugeth_info("Base address: 0x%08x", (u32) ugeth->p_scheduler); + mem_disp((u8 *) ugeth->p_scheduler, + sizeof(*ugeth->p_scheduler)); + } + if (ugeth->p_tx_fw_statistics_pram) { + ugeth_info("TX FW statistics pram:"); + ugeth_info("Base address: 0x%08x", + (u32) ugeth->p_tx_fw_statistics_pram); + mem_disp((u8 *) ugeth->p_tx_fw_statistics_pram, + sizeof(*ugeth->p_tx_fw_statistics_pram)); + } + if (ugeth->p_rx_fw_statistics_pram) { + ugeth_info("RX FW statistics pram:"); + ugeth_info("Base address: 0x%08x", + (u32) ugeth->p_rx_fw_statistics_pram); + mem_disp((u8 *) ugeth->p_rx_fw_statistics_pram, + sizeof(*ugeth->p_rx_fw_statistics_pram)); + } + if (ugeth->p_rx_irq_coalescing_tbl) { + ugeth_info("RX IRQ coalescing tables:"); + ugeth_info("Base address: 0x%08x", + (u32) ugeth->p_rx_irq_coalescing_tbl); + for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) { + ugeth_info("RX IRQ coalescing table entry[%d]:", i); + ugeth_info("Base address: 0x%08x", + (u32) & ugeth->p_rx_irq_coalescing_tbl-> + coalescingentry[i]); + ugeth_info + ("interruptcoalescingmaxvalue: addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_irq_coalescing_tbl-> + coalescingentry[i].interruptcoalescingmaxvalue, + in_be32(&ugeth->p_rx_irq_coalescing_tbl-> + coalescingentry[i]. + interruptcoalescingmaxvalue)); + ugeth_info + ("interruptcoalescingcounter : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_irq_coalescing_tbl-> + coalescingentry[i].interruptcoalescingcounter, + in_be32(&ugeth->p_rx_irq_coalescing_tbl-> + coalescingentry[i]. + interruptcoalescingcounter)); + } + } + if (ugeth->p_rx_bd_qs_tbl) { + ugeth_info("RX BD QS tables:"); + ugeth_info("Base address: 0x%08x", (u32) ugeth->p_rx_bd_qs_tbl); + for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) { + ugeth_info("RX BD QS table[%d]:", i); + ugeth_info("Base address: 0x%08x", + (u32) & ugeth->p_rx_bd_qs_tbl[i]); + ugeth_info + ("bdbaseptr : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_bd_qs_tbl[i].bdbaseptr, + in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdbaseptr)); + ugeth_info + ("bdptr : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_bd_qs_tbl[i].bdptr, + in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdptr)); + ugeth_info + ("externalbdbaseptr: addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr, + in_be32(&ugeth->p_rx_bd_qs_tbl[i]. + externalbdbaseptr)); + ugeth_info + ("externalbdptr : addr - 0x%08x, val - 0x%08x", + (u32) & ugeth->p_rx_bd_qs_tbl[i].externalbdptr, + in_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdptr)); + ugeth_info("ucode RX Prefetched BDs:"); + ugeth_info("Base address: 0x%08x", + (u32) + qe_muram_addr(in_be32 + (&ugeth->p_rx_bd_qs_tbl[i]. + bdbaseptr))); + mem_disp((u8 *) + qe_muram_addr(in_be32 + (&ugeth->p_rx_bd_qs_tbl[i]. + bdbaseptr)), + sizeof(ucc_geth_rx_prefetched_bds_t)); + } + } + if (ugeth->p_init_enet_param_shadow) { + int size; + ugeth_info("Init enet param shadow:"); + ugeth_info("Base address: 0x%08x", + (u32) ugeth->p_init_enet_param_shadow); + mem_disp((u8 *) ugeth->p_init_enet_param_shadow, + sizeof(*ugeth->p_init_enet_param_shadow)); + + size = sizeof(ucc_geth_thread_rx_pram_t); + if (ugeth->ug_info->rxExtendedFiltering) { + size += + THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING; + if (ugeth->ug_info->largestexternallookupkeysize == + QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES) + size += + THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8; + if (ugeth->ug_info->largestexternallookupkeysize == + QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES) + size += + THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16; + } + + dump_init_enet_entries(ugeth, + &(ugeth->p_init_enet_param_shadow-> + txthread[0]), + ENET_INIT_PARAM_MAX_ENTRIES_TX, + sizeof(ucc_geth_thread_tx_pram_t), + ugeth->ug_info->riscTx, 0); + dump_init_enet_entries(ugeth, + &(ugeth->p_init_enet_param_shadow-> + rxthread[0]), + ENET_INIT_PARAM_MAX_ENTRIES_RX, size, + ugeth->ug_info->riscRx, 1); + } +} +#endif /* DEBUG */ + +static void init_default_reg_vals(volatile u32 *upsmr_register, + volatile u32 *maccfg1_register, + volatile u32 *maccfg2_register) +{ + out_be32(upsmr_register, UCC_GETH_UPSMR_INIT); + out_be32(maccfg1_register, UCC_GETH_MACCFG1_INIT); + out_be32(maccfg2_register, UCC_GETH_MACCFG2_INIT); +} + +static int init_half_duplex_params(int alt_beb, + int back_pressure_no_backoff, + int no_backoff, + int excess_defer, + u8 alt_beb_truncation, + u8 max_retransmissions, + u8 collision_window, + volatile u32 *hafdup_register) +{ + u32 value = 0; + + if ((alt_beb_truncation > HALFDUP_ALT_BEB_TRUNCATION_MAX) || + (max_retransmissions > HALFDUP_MAX_RETRANSMISSION_MAX) || + (collision_window > HALFDUP_COLLISION_WINDOW_MAX)) + return -EINVAL; + + value = (u32) (alt_beb_truncation << HALFDUP_ALT_BEB_TRUNCATION_SHIFT); + + if (alt_beb) + value |= HALFDUP_ALT_BEB; + if (back_pressure_no_backoff) + value |= HALFDUP_BACK_PRESSURE_NO_BACKOFF; + if (no_backoff) + value |= HALFDUP_NO_BACKOFF; + if (excess_defer) + value |= HALFDUP_EXCESSIVE_DEFER; + + value |= (max_retransmissions << HALFDUP_MAX_RETRANSMISSION_SHIFT); + + value |= collision_window; + + out_be32(hafdup_register, value); + return 0; +} + +static int init_inter_frame_gap_params(u8 non_btb_cs_ipg, + u8 non_btb_ipg, + u8 min_ifg, + u8 btb_ipg, + volatile u32 *ipgifg_register) +{ + u32 value = 0; + + /* Non-Back-to-back IPG part 1 should be <= Non-Back-to-back + IPG part 2 */ + if (non_btb_cs_ipg > non_btb_ipg) + return -EINVAL; + + if ((non_btb_cs_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART1_MAX) || + (non_btb_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART2_MAX) || + /*(min_ifg > IPGIFG_MINIMUM_IFG_ENFORCEMENT_MAX) || */ + (btb_ipg > IPGIFG_BACK_TO_BACK_IFG_MAX)) + return -EINVAL; + + value |= + ((non_btb_cs_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART1_SHIFT) & + IPGIFG_NBTB_CS_IPG_MASK); + value |= + ((non_btb_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART2_SHIFT) & + IPGIFG_NBTB_IPG_MASK); + value |= + ((min_ifg << IPGIFG_MINIMUM_IFG_ENFORCEMENT_SHIFT) & + IPGIFG_MIN_IFG_MASK); + value |= (btb_ipg & IPGIFG_BTB_IPG_MASK); + + out_be32(ipgifg_register, value); + return 0; +} + +static int init_flow_control_params(u32 automatic_flow_control_mode, + int rx_flow_control_enable, + int tx_flow_control_enable, + u16 pause_period, + u16 extension_field, + volatile u32 *upsmr_register, + volatile u32 *uempr_register, + volatile u32 *maccfg1_register) +{ + u32 value = 0; + + /* Set UEMPR register */ + value = (u32) pause_period << UEMPR_PAUSE_TIME_VALUE_SHIFT; + value |= (u32) extension_field << UEMPR_EXTENDED_PAUSE_TIME_VALUE_SHIFT; + out_be32(uempr_register, value); + + /* Set UPSMR register */ + value = in_be32(upsmr_register); + value |= automatic_flow_control_mode; + out_be32(upsmr_register, value); + + value = in_be32(maccfg1_register); + if (rx_flow_control_enable) + value |= MACCFG1_FLOW_RX; + if (tx_flow_control_enable) + value |= MACCFG1_FLOW_TX; + out_be32(maccfg1_register, value); + + return 0; +} + +static int init_hw_statistics_gathering_mode(int enable_hardware_statistics, + int auto_zero_hardware_statistics, + volatile u32 *upsmr_register, + volatile u16 *uescr_register) +{ + u32 upsmr_value = 0; + u16 uescr_value = 0; + /* Enable hardware statistics gathering if requested */ + if (enable_hardware_statistics) { + upsmr_value = in_be32(upsmr_register); + upsmr_value |= UPSMR_HSE; + out_be32(upsmr_register, upsmr_value); + } + + /* Clear hardware statistics counters */ + uescr_value = in_be16(uescr_register); + uescr_value |= UESCR_CLRCNT; + /* Automatically zero hardware statistics counters on read, + if requested */ + if (auto_zero_hardware_statistics) + uescr_value |= UESCR_AUTOZ; + out_be16(uescr_register, uescr_value); + + return 0; +} + +static int init_firmware_statistics_gathering_mode(int + enable_tx_firmware_statistics, + int enable_rx_firmware_statistics, + volatile u32 *tx_rmon_base_ptr, + u32 tx_firmware_statistics_structure_address, + volatile u32 *rx_rmon_base_ptr, + u32 rx_firmware_statistics_structure_address, + volatile u16 *temoder_register, + volatile u32 *remoder_register) +{ + /* Note: this function does not check if */ + /* the parameters it receives are NULL */ + u16 temoder_value; + u32 remoder_value; + + if (enable_tx_firmware_statistics) { + out_be32(tx_rmon_base_ptr, + tx_firmware_statistics_structure_address); + temoder_value = in_be16(temoder_register); + temoder_value |= TEMODER_TX_RMON_STATISTICS_ENABLE; + out_be16(temoder_register, temoder_value); + } + + if (enable_rx_firmware_statistics) { + out_be32(rx_rmon_base_ptr, + rx_firmware_statistics_structure_address); + remoder_value = in_be32(remoder_register); + remoder_value |= REMODER_RX_RMON_STATISTICS_ENABLE; + out_be32(remoder_register, remoder_value); + } + + return 0; +} + +static int init_mac_station_addr_regs(u8 address_byte_0, + u8 address_byte_1, + u8 address_byte_2, + u8 address_byte_3, + u8 address_byte_4, + u8 address_byte_5, + volatile u32 *macstnaddr1_register, + volatile u32 *macstnaddr2_register) +{ + u32 value = 0; + + /* Example: for a station address of 0x12345678ABCD, */ + /* 0x12 is byte 0, 0x34 is byte 1 and so on and 0xCD is byte 5 */ + + /* MACSTNADDR1 Register: */ + + /* 0 7 8 15 */ + /* station address byte 5 station address byte 4 */ + /* 16 23 24 31 */ + /* station address byte 3 station address byte 2 */ + value |= (u32) ((address_byte_2 << 0) & 0x000000FF); + value |= (u32) ((address_byte_3 << 8) & 0x0000FF00); + value |= (u32) ((address_byte_4 << 16) & 0x00FF0000); + value |= (u32) ((address_byte_5 << 24) & 0xFF000000); + + out_be32(macstnaddr1_register, value); + + /* MACSTNADDR2 Register: */ + + /* 0 7 8 15 */ + /* station address byte 1 station address byte 0 */ + /* 16 23 24 31 */ + /* reserved reserved */ + value = 0; + value |= (u32) ((address_byte_0 << 16) & 0x00FF0000); + value |= (u32) ((address_byte_1 << 24) & 0xFF000000); + + out_be32(macstnaddr2_register, value); + + return 0; +} + +static int init_mac_duplex_mode(int full_duplex, + int limited_to_full_duplex, + volatile u32 *maccfg2_register) +{ + u32 value = 0; + + /* some interfaces must work in full duplex mode */ + if ((full_duplex == 0) && (limited_to_full_duplex == 1)) + return -EINVAL; + + value = in_be32(maccfg2_register); + + if (full_duplex) + value |= MACCFG2_FDX; + else + value &= ~MACCFG2_FDX; + + out_be32(maccfg2_register, value); + return 0; +} + +static int init_check_frame_length_mode(int length_check, + volatile u32 *maccfg2_register) +{ + u32 value = 0; + + value = in_be32(maccfg2_register); + + if (length_check) + value |= MACCFG2_LC; + else + value &= ~MACCFG2_LC; + + out_be32(maccfg2_register, value); + return 0; +} + +static int init_preamble_length(u8 preamble_length, + volatile u32 *maccfg2_register) +{ + u32 value = 0; + + if ((preamble_length < 3) || (preamble_length > 7)) + return -EINVAL; + + value = in_be32(maccfg2_register); + value &= ~MACCFG2_PREL_MASK; + value |= (preamble_length << MACCFG2_PREL_SHIFT); + out_be32(maccfg2_register, value); + return 0; +} + +static int init_mii_management_configuration(int reset_mgmt, + int preamble_supress, + volatile u32 *miimcfg_register, + volatile u32 *miimind_register) +{ + unsigned int timeout = PHY_INIT_TIMEOUT; + u32 value = 0; + + value = in_be32(miimcfg_register); + if (reset_mgmt) { + value |= MIIMCFG_RESET_MANAGEMENT; + out_be32(miimcfg_register, value); + } + + value = 0; + + if (preamble_supress) + value |= MIIMCFG_NO_PREAMBLE; + + value |= UCC_GETH_MIIMCFG_MNGMNT_CLC_DIV_INIT; + out_be32(miimcfg_register, value); + + /* Wait until the bus is free */ + while ((in_be32(miimind_register) & MIIMIND_BUSY) && timeout--) + cpu_relax(); + + if (timeout <= 0) { + ugeth_err("%s: The MII Bus is stuck!", __FUNCTION__); + return -ETIMEDOUT; + } + + return 0; +} + +static int init_rx_parameters(int reject_broadcast, + int receive_short_frames, + int promiscuous, volatile u32 *upsmr_register) +{ + u32 value = 0; + + value = in_be32(upsmr_register); + + if (reject_broadcast) + value |= UPSMR_BRO; + else + value &= ~UPSMR_BRO; + + if (receive_short_frames) + value |= UPSMR_RSH; + else + value &= ~UPSMR_RSH; + + if (promiscuous) + value |= UPSMR_PRO; + else + value &= ~UPSMR_PRO; + + out_be32(upsmr_register, value); + + return 0; +} + +static int init_max_rx_buff_len(u16 max_rx_buf_len, + volatile u16 *mrblr_register) +{ + /* max_rx_buf_len value must be a multiple of 128 */ + if ((max_rx_buf_len == 0) + || (max_rx_buf_len % UCC_GETH_MRBLR_ALIGNMENT)) + return -EINVAL; + + out_be16(mrblr_register, max_rx_buf_len); + return 0; +} + +static int init_min_frame_len(u16 min_frame_length, + volatile u16 *minflr_register, + volatile u16 *mrblr_register) +{ + u16 mrblr_value = 0; + + mrblr_value = in_be16(mrblr_register); + if (min_frame_length >= (mrblr_value - 4)) + return -EINVAL; + + out_be16(minflr_register, min_frame_length); + return 0; +} + +static int adjust_enet_interface(ucc_geth_private_t *ugeth) +{ + ucc_geth_info_t *ug_info; + ucc_geth_t *ug_regs; + ucc_fast_t *uf_regs; + enet_speed_e speed; + int ret_val, rpm = 0, tbi = 0, r10m = 0, rmm = + 0, limited_to_full_duplex = 0; + u32 upsmr, maccfg2, utbipar, tbiBaseAddress; + u16 value; + + ugeth_vdbg("%s: IN", __FUNCTION__); + + ug_info = ugeth->ug_info; + ug_regs = ugeth->ug_regs; + uf_regs = ugeth->uccf->uf_regs; + + /* Analyze enet_interface according to Interface Mode Configuration + table */ + ret_val = + get_interface_details(ug_info->enet_interface, &speed, &r10m, &rmm, + &rpm, &tbi, &limited_to_full_duplex); + if (ret_val != 0) { + ugeth_err + ("%s: half duplex not supported in requested configuration.", + __FUNCTION__); + return ret_val; + } + + /* Set MACCFG2 */ + maccfg2 = in_be32(&ug_regs->maccfg2); + maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK; + if ((speed == ENET_SPEED_10BT) || (speed == ENET_SPEED_100BT)) + maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE; + else if (speed == ENET_SPEED_1000BT) + maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE; + maccfg2 |= ug_info->padAndCrc; + out_be32(&ug_regs->maccfg2, maccfg2); + + /* Set UPSMR */ + upsmr = in_be32(&uf_regs->upsmr); + upsmr &= ~(UPSMR_RPM | UPSMR_R10M | UPSMR_TBIM | UPSMR_RMM); + if (rpm) + upsmr |= UPSMR_RPM; + if (r10m) + upsmr |= UPSMR_R10M; + if (tbi) + upsmr |= UPSMR_TBIM; + if (rmm) + upsmr |= UPSMR_RMM; + out_be32(&uf_regs->upsmr, upsmr); + + /* Set UTBIPAR */ + utbipar = in_be32(&ug_regs->utbipar); + utbipar &= ~UTBIPAR_PHY_ADDRESS_MASK; + if (tbi) + utbipar |= + (ug_info->phy_address + + ugeth->ug_info->uf_info. + ucc_num) << UTBIPAR_PHY_ADDRESS_SHIFT; + else + utbipar |= + (0x10 + + ugeth->ug_info->uf_info. + ucc_num) << UTBIPAR_PHY_ADDRESS_SHIFT; + out_be32(&ug_regs->utbipar, utbipar); + + /* Disable autonegotiation in tbi mode, because by default it + comes up in autonegotiation mode. */ + /* Note that this depends on proper setting in utbipar register. */ + if (tbi) { + tbiBaseAddress = in_be32(&ug_regs->utbipar); + tbiBaseAddress &= UTBIPAR_PHY_ADDRESS_MASK; + tbiBaseAddress >>= UTBIPAR_PHY_ADDRESS_SHIFT; + value = + ugeth->mii_info->mdio_read(ugeth->dev, (u8) tbiBaseAddress, + ENET_TBI_MII_CR); + value &= ~0x1000; /* Turn off autonegotiation */ + ugeth->mii_info->mdio_write(ugeth->dev, (u8) tbiBaseAddress, + ENET_TBI_MII_CR, value); + } + + ret_val = init_mac_duplex_mode(1, + limited_to_full_duplex, + &ug_regs->maccfg2); + if (ret_val != 0) { + ugeth_err + ("%s: half duplex not supported in requested configuration.", + __FUNCTION__); + return ret_val; + } + + init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2); + + ret_val = init_preamble_length(ug_info->prel, &ug_regs->maccfg2); + if (ret_val != 0) { + ugeth_err + ("%s: Preamble length must be between 3 and 7 inclusive.", + __FUNCTION__); + return ret_val; + } + + return 0; +} + +/* Called every time the controller might need to be made + * aware of new link state. The PHY code conveys this + * information through variables in the ugeth structure, and this + * function converts those variables into the appropriate + * register values, and can bring down the device if needed. + */ +static void adjust_link(struct net_device *dev) +{ + ucc_geth_private_t *ugeth = netdev_priv(dev); + ucc_geth_t *ug_regs; + u32 tempval; + struct ugeth_mii_info *mii_info = ugeth->mii_info; + + ug_regs = ugeth->ug_regs; + + if (mii_info->link) { + /* Now we make sure that we can be in full duplex mode. + * If not, we operate in half-duplex mode. */ + if (mii_info->duplex != ugeth->oldduplex) { + if (!(mii_info->duplex)) { + tempval = in_be32(&ug_regs->maccfg2); + tempval &= ~(MACCFG2_FDX); + out_be32(&ug_regs->maccfg2, tempval); + + ugeth_info("%s: Half Duplex", dev->name); + } else { + tempval = in_be32(&ug_regs->maccfg2); + tempval |= MACCFG2_FDX; + out_be32(&ug_regs->maccfg2, tempval); + + ugeth_info("%s: Full Duplex", dev->name); + } + + ugeth->oldduplex = mii_info->duplex; + } + + if (mii_info->speed != ugeth->oldspeed) { + switch (mii_info->speed) { + case 1000: +#ifdef CONFIG_MPC836x +/* FIXME: This code is for 100Mbs BUG fixing, +remove this when it is fixed!!! */ + if (ugeth->ug_info->enet_interface == + ENET_1000_GMII) + /* Run the commands which initialize the PHY */ + { + tempval = + (u32) mii_info->mdio_read(ugeth-> + dev, mii_info->mii_id, 0x1b); + tempval |= 0x000f; + mii_info->mdio_write(ugeth->dev, + mii_info->mii_id, 0x1b, + (u16) tempval); + tempval = + (u32) mii_info->mdio_read(ugeth-> + dev, mii_info->mii_id, + MII_BMCR); + mii_info->mdio_write(ugeth->dev, + mii_info->mii_id, MII_BMCR, + (u16) (tempval | BMCR_RESET)); + } else if (ugeth->ug_info->enet_interface == + ENET_1000_RGMII) + /* Run the commands which initialize the PHY */ + { + tempval = + (u32) mii_info->mdio_read(ugeth-> + dev, mii_info->mii_id, 0x1b); + tempval = (tempval & ~0x000f) | 0x000b; + mii_info->mdio_write(ugeth->dev, + mii_info->mii_id, 0x1b, + (u16) tempval); + tempval = + (u32) mii_info->mdio_read(ugeth-> + dev, mii_info->mii_id, + MII_BMCR); + mii_info->mdio_write(ugeth->dev, + mii_info->mii_id, MII_BMCR, + (u16) (tempval | BMCR_RESET)); + } + msleep(4000); +#endif /* CONFIG_MPC8360 */ + adjust_enet_interface(ugeth); + break; + case 100: + case 10: +#ifdef CONFIG_MPC836x +/* FIXME: This code is for 100Mbs BUG fixing, +remove this lines when it will be fixed!!! */ + ugeth->ug_info->enet_interface = ENET_100_RGMII; + tempval = + (u32) mii_info->mdio_read(ugeth->dev, + mii_info->mii_id, + 0x1b); + tempval = (tempval & ~0x000f) | 0x000b; + mii_info->mdio_write(ugeth->dev, + mii_info->mii_id, 0x1b, + (u16) tempval); + tempval = + (u32) mii_info->mdio_read(ugeth->dev, + mii_info->mii_id, + MII_BMCR); + mii_info->mdio_write(ugeth->dev, + mii_info->mii_id, MII_BMCR, + (u16) (tempval | + BMCR_RESET)); + msleep(4000); +#endif /* CONFIG_MPC8360 */ + adjust_enet_interface(ugeth); + break; + default: + ugeth_warn + ("%s: Ack! Speed (%d) is not 10/100/1000!", + dev->name, mii_info->speed); + break; + } + + ugeth_info("%s: Speed %dBT", dev->name, + mii_info->speed); + + ugeth->oldspeed = mii_info->speed; + } + + if (!ugeth->oldlink) { + ugeth_info("%s: Link is up", dev->name); + ugeth->oldlink = 1; + netif_carrier_on(dev); + netif_schedule(dev); + } + } else { + if (ugeth->oldlink) { + ugeth_info("%s: Link is down", dev->name); + ugeth->oldlink = 0; + ugeth->oldspeed = 0; + ugeth->oldduplex = -1; + netif_carrier_off(dev); + } + } +} + +/* Configure the PHY for dev. + * returns 0 if success. -1 if failure + */ +static int init_phy(struct net_device *dev) +{ + ucc_geth_private_t *ugeth = netdev_priv(dev); + struct phy_info *curphy; + ucc_mii_mng_t *mii_regs; + struct ugeth_mii_info *mii_info; + int err; + + mii_regs = &ugeth->ug_regs->miimng; + + ugeth->oldlink = 0; + ugeth->oldspeed = 0; + ugeth->oldduplex = -1; + + mii_info = kmalloc(sizeof(struct ugeth_mii_info), GFP_KERNEL); + + if (NULL == mii_info) { + ugeth_err("%s: Could not allocate mii_info", dev->name); + return -ENOMEM; + } + + mii_info->mii_regs = mii_regs; + mii_info->speed = SPEED_1000; + mii_info->duplex = DUPLEX_FULL; + mii_info->pause = 0; + mii_info->link = 0; + + mii_info->advertising = (ADVERTISED_10baseT_Half | + ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Full); + mii_info->autoneg = 1; + + mii_info->mii_id = ugeth->ug_info->phy_address; + + mii_info->dev = dev; + + mii_info->mdio_read = &read_phy_reg; + mii_info->mdio_write = &write_phy_reg; + + ugeth->mii_info = mii_info; + + spin_lock_irq(&ugeth->lock); + + /* Set this UCC to be the master of the MII managment */ + ucc_set_qe_mux_mii_mng(ugeth->ug_info->uf_info.ucc_num); + + if (init_mii_management_configuration(1, + ugeth->ug_info-> + miiPreambleSupress, + &mii_regs->miimcfg, + &mii_regs->miimind)) { + ugeth_err("%s: The MII Bus is stuck!", dev->name); + err = -1; + goto bus_fail; + } + + spin_unlock_irq(&ugeth->lock); + + /* get info for this PHY */ + curphy = get_phy_info(ugeth->mii_info); + + if (curphy == NULL) { + ugeth_err("%s: No PHY found", dev->name); + err = -1; + goto no_phy; + } + + mii_info->phyinfo = curphy; + + /* Run the commands which initialize the PHY */ + if (curphy->init) { + err = curphy->init(ugeth->mii_info); + if (err) + goto phy_init_fail; + } + + return 0; + + phy_init_fail: + no_phy: + bus_fail: + kfree(mii_info); + + return err; +} + +#ifdef CONFIG_UGETH_TX_ON_DEMOND +static int ugeth_transmit_on_demand(ucc_geth_private_t *ugeth) +{ + ucc_fast_transmit_on_demand(ugeth->uccf); + + return 0; +} +#endif + +static int ugeth_graceful_stop_tx(ucc_geth_private_t *ugeth) +{ + ucc_fast_private_t *uccf; + u32 cecr_subblock; + u32 temp; + + uccf = ugeth->uccf; + + /* Mask GRACEFUL STOP TX interrupt bit and clear it */ + temp = in_be32(uccf->p_uccm); + temp &= ~UCCE_GRA; + out_be32(uccf->p_uccm, temp); + out_be32(uccf->p_ucce, UCCE_GRA); /* clear by writing 1 */ + + /* Issue host command */ + cecr_subblock = + ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); + qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock, + (u8) QE_CR_PROTOCOL_ETHERNET, 0); + + /* Wait for command to complete */ + do { + temp = in_be32(uccf->p_ucce); + } while (!(temp & UCCE_GRA)); + + uccf->stopped_tx = 1; + + return 0; +} + +static int ugeth_graceful_stop_rx(ucc_geth_private_t * ugeth) +{ + ucc_fast_private_t *uccf; + u32 cecr_subblock; + u8 temp; + + uccf = ugeth->uccf; + + /* Clear acknowledge bit */ + temp = ugeth->p_rx_glbl_pram->rxgstpack; + temp &= ~GRACEFUL_STOP_ACKNOWLEDGE_RX; + ugeth->p_rx_glbl_pram->rxgstpack = temp; + + /* Keep issuing command and checking acknowledge bit until + it is asserted, according to spec */ + do { + /* Issue host command */ + cecr_subblock = + ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info. + ucc_num); + qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock, + (u8) QE_CR_PROTOCOL_ETHERNET, 0); + + temp = ugeth->p_rx_glbl_pram->rxgstpack; + } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX)); + + uccf->stopped_rx = 1; + + return 0; +} + +static int ugeth_restart_tx(ucc_geth_private_t *ugeth) +{ + ucc_fast_private_t *uccf; + u32 cecr_subblock; + + uccf = ugeth->uccf; + + cecr_subblock = + ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); + qe_issue_cmd(QE_RESTART_TX, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET, + 0); + uccf->stopped_tx = 0; + + return 0; +} + +static int ugeth_restart_rx(ucc_geth_private_t *ugeth) +{ + ucc_fast_private_t *uccf; + u32 cecr_subblock; + + uccf = ugeth->uccf; + + cecr_subblock = + ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); + qe_issue_cmd(QE_RESTART_RX, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET, + 0); + uccf->stopped_rx = 0; + + return 0; +} + +static int ugeth_enable(ucc_geth_private_t *ugeth, comm_dir_e mode) +{ + ucc_fast_private_t *uccf; + int enabled_tx, enabled_rx; + + uccf = ugeth->uccf; + + /* check if the UCC number is in range. */ + if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { + ugeth_err("%s: ucc_num out of range.", __FUNCTION__); + return -EINVAL; + } + + enabled_tx = uccf->enabled_tx; + enabled_rx = uccf->enabled_rx; + + /* Get Tx and Rx going again, in case this channel was actively + disabled. */ + if ((mode & COMM_DIR_TX) && (!enabled_tx) && uccf->stopped_tx) + ugeth_restart_tx(ugeth); + if ((mode & COMM_DIR_RX) && (!enabled_rx) && uccf->stopped_rx) + ugeth_restart_rx(ugeth); + + ucc_fast_enable(uccf, mode); /* OK to do even if not disabled */ + + return 0; + +} + +static int ugeth_disable(ucc_geth_private_t * ugeth, comm_dir_e mode) +{ + ucc_fast_private_t *uccf; + + uccf = ugeth->uccf; + + /* check if the UCC number is in range. */ + if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) { + ugeth_err("%s: ucc_num out of range.", __FUNCTION__); + return -EINVAL; + } + + /* Stop any transmissions */ + if ((mode & COMM_DIR_TX) && uccf->enabled_tx && !uccf->stopped_tx) + ugeth_graceful_stop_tx(ugeth); + + /* Stop any receptions */ + if ((mode & COMM_DIR_RX) && uccf->enabled_rx && !uccf->stopped_rx) + ugeth_graceful_stop_rx(ugeth); + + ucc_fast_disable(ugeth->uccf, mode); /* OK to do even if not enabled */ + + return 0; +} + +static void ugeth_dump_regs(ucc_geth_private_t *ugeth) +{ +#ifdef DEBUG + ucc_fast_dump_regs(ugeth->uccf); + dump_regs(ugeth); + dump_bds(ugeth); +#endif +} + +#ifdef CONFIG_UGETH_FILTERING +static int ugeth_ext_filtering_serialize_tad(ucc_geth_tad_params_t * + p_UccGethTadParams, + qe_fltr_tad_t *qe_fltr_tad) +{ + u16 temp; + + /* Zero serialized TAD */ + memset(qe_fltr_tad, 0, QE_FLTR_TAD_SIZE); + + qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_V; /* Must have this */ + if (p_UccGethTadParams->rx_non_dynamic_extended_features_mode || + (p_UccGethTadParams->vtag_op != UCC_GETH_VLAN_OPERATION_TAGGED_NOP) + || (p_UccGethTadParams->vnontag_op != + UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP) + ) + qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_EF; + if (p_UccGethTadParams->reject_frame) + qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_REJ; + temp = + (u16) (((u16) p_UccGethTadParams-> + vtag_op) << UCC_GETH_TAD_VTAG_OP_SHIFT); + qe_fltr_tad->serialized[0] |= (u8) (temp >> 8); /* upper bits */ + + qe_fltr_tad->serialized[1] |= (u8) (temp & 0x00ff); /* lower bits */ + if (p_UccGethTadParams->vnontag_op == + UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT) + qe_fltr_tad->serialized[1] |= UCC_GETH_TAD_V_NON_VTAG_OP; + qe_fltr_tad->serialized[1] |= + p_UccGethTadParams->rqos << UCC_GETH_TAD_RQOS_SHIFT; + + qe_fltr_tad->serialized[2] |= + p_UccGethTadParams->vpri << UCC_GETH_TAD_V_PRIORITY_SHIFT; + /* upper bits */ + qe_fltr_tad->serialized[2] |= (u8) (p_UccGethTadParams->vid >> 8); + /* lower bits */ + qe_fltr_tad->serialized[3] |= (u8) (p_UccGethTadParams->vid & 0x00ff); + + return 0; +} + +static enet_addr_container_t + *ugeth_82xx_filtering_get_match_addr_in_hash(ucc_geth_private_t *ugeth, + enet_addr_t *p_enet_addr) +{ + enet_addr_container_t *enet_addr_cont; + struct list_head *p_lh; + u16 i, num; + int32_t j; + u8 *p_counter; + + if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) { + p_lh = &ugeth->group_hash_q; + p_counter = &(ugeth->numGroupAddrInHash); + } else { + p_lh = &ugeth->ind_hash_q; + p_counter = &(ugeth->numIndAddrInHash); + } + + if (!p_lh) + return NULL; + + num = *p_counter; + + for (i = 0; i < num; i++) { + enet_addr_cont = + (enet_addr_container_t *) + ENET_ADDR_CONT_ENTRY(dequeue(p_lh)); + for (j = ENET_NUM_OCTETS_PER_ADDRESS - 1; j >= 0; j--) { + if ((*p_enet_addr)[j] != (enet_addr_cont->address)[j]) + break; + if (j == 0) + return enet_addr_cont; /* Found */ + } + enqueue(p_lh, &enet_addr_cont->node); /* Put it back */ + } + return NULL; +} + +static int ugeth_82xx_filtering_add_addr_in_hash(ucc_geth_private_t *ugeth, + enet_addr_t *p_enet_addr) +{ + ucc_geth_enet_address_recognition_location_e location; + enet_addr_container_t *enet_addr_cont; + struct list_head *p_lh; + u8 i; + u32 limit; + u8 *p_counter; + + if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) { + p_lh = &ugeth->group_hash_q; + limit = ugeth->ug_info->maxGroupAddrInHash; + location = + UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH; + p_counter = &(ugeth->numGroupAddrInHash); + } else { + p_lh = &ugeth->ind_hash_q; + limit = ugeth->ug_info->maxIndAddrInHash; + location = + UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH; + p_counter = &(ugeth->numIndAddrInHash); + } + + if ((enet_addr_cont = + ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr))) { + list_add(p_lh, &enet_addr_cont->node); /* Put it back */ + return 0; + } + if ((!p_lh) || (!(*p_counter < limit))) + return -EBUSY; + if (!(enet_addr_cont = get_enet_addr_container())) + return -ENOMEM; + for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++) + (enet_addr_cont->address)[i] = (*p_enet_addr)[i]; + enet_addr_cont->location = location; + enqueue(p_lh, &enet_addr_cont->node); /* Put it back */ + ++(*p_counter); + + hw_add_addr_in_hash(ugeth, &(enet_addr_cont->address)); + + return 0; +} + +static int ugeth_82xx_filtering_clear_addr_in_hash(ucc_geth_private_t *ugeth, + enet_addr_t *p_enet_addr) +{ + ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; + enet_addr_container_t *enet_addr_cont; + ucc_fast_private_t *uccf; + comm_dir_e comm_dir; + u16 i, num; + struct list_head *p_lh; + u32 *addr_h, *addr_l; + u8 *p_counter; + + uccf = ugeth->uccf; + + p_82xx_addr_filt = + (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram-> + addressfiltering; + + if (! + (enet_addr_cont = + ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr))) + return -ENOENT; + + /* It's been found and removed from the CQ. */ + /* Now destroy its container */ + put_enet_addr_container(enet_addr_cont); + + if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) { + addr_h = &(p_82xx_addr_filt->gaddr_h); + addr_l = &(p_82xx_addr_filt->gaddr_l); + p_lh = &ugeth->group_hash_q; + p_counter = &(ugeth->numGroupAddrInHash); + } else { + addr_h = &(p_82xx_addr_filt->iaddr_h); + addr_l = &(p_82xx_addr_filt->iaddr_l); + p_lh = &ugeth->ind_hash_q; + p_counter = &(ugeth->numIndAddrInHash); + } + + comm_dir = 0; + if (uccf->enabled_tx) + comm_dir |= COMM_DIR_TX; + if (uccf->enabled_rx) + comm_dir |= COMM_DIR_RX; + if (comm_dir) + ugeth_disable(ugeth, comm_dir); + + /* Clear the hash table. */ + out_be32(addr_h, 0x00000000); + out_be32(addr_l, 0x00000000); + + /* Add all remaining CQ elements back into hash */ + num = --(*p_counter); + for (i = 0; i < num; i++) { + enet_addr_cont = + (enet_addr_container_t *) + ENET_ADDR_CONT_ENTRY(dequeue(p_lh)); + hw_add_addr_in_hash(ugeth, &(enet_addr_cont->address)); + enqueue(p_lh, &enet_addr_cont->node); /* Put it back */ + } + + if (comm_dir) + ugeth_enable(ugeth, comm_dir); + + return 0; +} +#endif /* CONFIG_UGETH_FILTERING */ + +static int ugeth_82xx_filtering_clear_all_addr_in_hash(ucc_geth_private_t * + ugeth, + enet_addr_type_e + enet_addr_type) +{ + ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; + ucc_fast_private_t *uccf; + comm_dir_e comm_dir; + struct list_head *p_lh; + u16 i, num; + u32 *addr_h, *addr_l; + u8 *p_counter; + + uccf = ugeth->uccf; + + p_82xx_addr_filt = + (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram-> + addressfiltering; + + if (enet_addr_type == ENET_ADDR_TYPE_GROUP) { + addr_h = &(p_82xx_addr_filt->gaddr_h); + addr_l = &(p_82xx_addr_filt->gaddr_l); + p_lh = &ugeth->group_hash_q; + p_counter = &(ugeth->numGroupAddrInHash); + } else if (enet_addr_type == ENET_ADDR_TYPE_INDIVIDUAL) { + addr_h = &(p_82xx_addr_filt->iaddr_h); + addr_l = &(p_82xx_addr_filt->iaddr_l); + p_lh = &ugeth->ind_hash_q; + p_counter = &(ugeth->numIndAddrInHash); + } else + return -EINVAL; + + comm_dir = 0; + if (uccf->enabled_tx) + comm_dir |= COMM_DIR_TX; + if (uccf->enabled_rx) + comm_dir |= COMM_DIR_RX; + if (comm_dir) + ugeth_disable(ugeth, comm_dir); + + /* Clear the hash table. */ + out_be32(addr_h, 0x00000000); + out_be32(addr_l, 0x00000000); + + if (!p_lh) + return 0; + + num = *p_counter; + + /* Delete all remaining CQ elements */ + for (i = 0; i < num; i++) + put_enet_addr_container(ENET_ADDR_CONT_ENTRY(dequeue(p_lh))); + + *p_counter = 0; + + if (comm_dir) + ugeth_enable(ugeth, comm_dir); + + return 0; +} + +#ifdef CONFIG_UGETH_FILTERING +static int ugeth_82xx_filtering_add_addr_in_paddr(ucc_geth_private_t *ugeth, + enet_addr_t *p_enet_addr, + u8 paddr_num) +{ + int i; + + if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) + ugeth_warn + ("%s: multicast address added to paddr will have no " + "effect - is this what you wanted?", + __FUNCTION__); + + ugeth->indAddrRegUsed[paddr_num] = 1; /* mark this paddr as used */ + /* store address in our database */ + for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++) + ugeth->paddr[paddr_num][i] = (*p_enet_addr)[i]; + /* put in hardware */ + return hw_add_addr_in_paddr(ugeth, p_enet_addr, paddr_num); +} +#endif /* CONFIG_UGETH_FILTERING */ + +static int ugeth_82xx_filtering_clear_addr_in_paddr(ucc_geth_private_t *ugeth, + u8 paddr_num) +{ + ugeth->indAddrRegUsed[paddr_num] = 0; /* mark this paddr as not used */ + return hw_clear_addr_in_paddr(ugeth, paddr_num);/* clear in hardware */ +} + +static void ucc_geth_memclean(ucc_geth_private_t *ugeth) +{ + u16 i, j; + u8 *bd; + + if (!ugeth) + return; + + if (ugeth->uccf) + ucc_fast_free(ugeth->uccf); + + if (ugeth->p_thread_data_tx) { + qe_muram_free(ugeth->thread_dat_tx_offset); + ugeth->p_thread_data_tx = NULL; + } + if (ugeth->p_thread_data_rx) { + qe_muram_free(ugeth->thread_dat_rx_offset); + ugeth->p_thread_data_rx = NULL; + } + if (ugeth->p_exf_glbl_param) { + qe_muram_free(ugeth->exf_glbl_param_offset); + ugeth->p_exf_glbl_param = NULL; + } + if (ugeth->p_rx_glbl_pram) { + qe_muram_free(ugeth->rx_glbl_pram_offset); + ugeth->p_rx_glbl_pram = NULL; + } + if (ugeth->p_tx_glbl_pram) { + qe_muram_free(ugeth->tx_glbl_pram_offset); + ugeth->p_tx_glbl_pram = NULL; + } + if (ugeth->p_send_q_mem_reg) { + qe_muram_free(ugeth->send_q_mem_reg_offset); + ugeth->p_send_q_mem_reg = NULL; + } + if (ugeth->p_scheduler) { + qe_muram_free(ugeth->scheduler_offset); + ugeth->p_scheduler = NULL; + } + if (ugeth->p_tx_fw_statistics_pram) { + qe_muram_free(ugeth->tx_fw_statistics_pram_offset); + ugeth->p_tx_fw_statistics_pram = NULL; + } + if (ugeth->p_rx_fw_statistics_pram) { + qe_muram_free(ugeth->rx_fw_statistics_pram_offset); + ugeth->p_rx_fw_statistics_pram = NULL; + } + if (ugeth->p_rx_irq_coalescing_tbl) { + qe_muram_free(ugeth->rx_irq_coalescing_tbl_offset); + ugeth->p_rx_irq_coalescing_tbl = NULL; + } + if (ugeth->p_rx_bd_qs_tbl) { + qe_muram_free(ugeth->rx_bd_qs_tbl_offset); + ugeth->p_rx_bd_qs_tbl = NULL; + } + if (ugeth->p_init_enet_param_shadow) { + return_init_enet_entries(ugeth, + &(ugeth->p_init_enet_param_shadow-> + rxthread[0]), + ENET_INIT_PARAM_MAX_ENTRIES_RX, + ugeth->ug_info->riscRx, 1); + return_init_enet_entries(ugeth, + &(ugeth->p_init_enet_param_shadow-> + txthread[0]), + ENET_INIT_PARAM_MAX_ENTRIES_TX, + ugeth->ug_info->riscTx, 0); + kfree(ugeth->p_init_enet_param_shadow); + ugeth->p_init_enet_param_shadow = NULL; + } + for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) { + bd = ugeth->p_tx_bd_ring[i]; + for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) { + if (ugeth->tx_skbuff[i][j]) { + dma_unmap_single(NULL, + BD_BUFFER_ARG(bd), + (BD_STATUS_AND_LENGTH(bd) & + BD_LENGTH_MASK), + DMA_TO_DEVICE); + dev_kfree_skb_any(ugeth->tx_skbuff[i][j]); + ugeth->tx_skbuff[i][j] = NULL; + } + } + + kfree(ugeth->tx_skbuff[i]); + + if (ugeth->p_tx_bd_ring[i]) { + if (ugeth->ug_info->uf_info.bd_mem_part == + MEM_PART_SYSTEM) + kfree((void *)ugeth->tx_bd_ring_offset[i]); + else if (ugeth->ug_info->uf_info.bd_mem_part == + MEM_PART_MURAM) + qe_muram_free(ugeth->tx_bd_ring_offset[i]); + ugeth->p_tx_bd_ring[i] = NULL; + } + } + for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) { + if (ugeth->p_rx_bd_ring[i]) { + /* Return existing data buffers in ring */ + bd = ugeth->p_rx_bd_ring[i]; + for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) { + if (ugeth->rx_skbuff[i][j]) { + dma_unmap_single(NULL, BD_BUFFER(bd), + ugeth->ug_info-> + uf_info. + max_rx_buf_length + + UCC_GETH_RX_DATA_BUF_ALIGNMENT, + DMA_FROM_DEVICE); + + dev_kfree_skb_any(ugeth-> + rx_skbuff[i][j]); + ugeth->rx_skbuff[i][j] = NULL; + } + bd += UCC_GETH_SIZE_OF_BD; + } + + kfree(ugeth->rx_skbuff[i]); + + if (ugeth->ug_info->uf_info.bd_mem_part == + MEM_PART_SYSTEM) + kfree((void *)ugeth->rx_bd_ring_offset[i]); + else if (ugeth->ug_info->uf_info.bd_mem_part == + MEM_PART_MURAM) + qe_muram_free(ugeth->rx_bd_ring_offset[i]); + ugeth->p_rx_bd_ring[i] = NULL; + } + } + while (!list_empty(&ugeth->group_hash_q)) + put_enet_addr_container(ENET_ADDR_CONT_ENTRY + (dequeue(&ugeth->group_hash_q))); + while (!list_empty(&ugeth->ind_hash_q)) + put_enet_addr_container(ENET_ADDR_CONT_ENTRY + (dequeue(&ugeth->ind_hash_q))); + +} + +static void ucc_geth_set_multi(struct net_device *dev) +{ + ucc_geth_private_t *ugeth; + struct dev_mc_list *dmi; + ucc_fast_t *uf_regs; + ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; + enet_addr_t tempaddr; + u8 *mcptr, *tdptr; + int i, j; + + ugeth = netdev_priv(dev); + + uf_regs = ugeth->uccf->uf_regs; + + if (dev->flags & IFF_PROMISC) { + + /* Log any net taps. */ + printk("%s: Promiscuous mode enabled.\n", dev->name); + uf_regs->upsmr |= UPSMR_PRO; + + } else { + + uf_regs->upsmr &= ~UPSMR_PRO; + + p_82xx_addr_filt = + (ucc_geth_82xx_address_filtering_pram_t *) ugeth-> + p_rx_glbl_pram->addressfiltering; + + if (dev->flags & IFF_ALLMULTI) { + /* Catch all multicast addresses, so set the + * filter to all 1's. + */ + out_be32(&p_82xx_addr_filt->gaddr_h, 0xffffffff); + out_be32(&p_82xx_addr_filt->gaddr_l, 0xffffffff); + } else { + /* Clear filter and add the addresses in the list. + */ + out_be32(&p_82xx_addr_filt->gaddr_h, 0x0); + out_be32(&p_82xx_addr_filt->gaddr_l, 0x0); + + dmi = dev->mc_list; + + for (i = 0; i < dev->mc_count; i++, dmi = dmi->next) { + + /* Only support group multicast for now. + */ + if (!(dmi->dmi_addr[0] & 1)) + continue; + + /* The address in dmi_addr is LSB first, + * and taddr is MSB first. We have to + * copy bytes MSB first from dmi_addr. + */ + mcptr = (u8 *) dmi->dmi_addr + 5; + tdptr = (u8 *) & tempaddr; + for (j = 0; j < 6; j++) + *tdptr++ = *mcptr--; + + /* Ask CPM to run CRC and set bit in + * filter mask. + */ + hw_add_addr_in_hash(ugeth, &tempaddr); + + } + } + } +} + +static void ucc_geth_stop(ucc_geth_private_t *ugeth) +{ + ucc_geth_t *ug_regs = ugeth->ug_regs; + u32 tempval; + + ugeth_vdbg("%s: IN", __FUNCTION__); + + /* Disable the controller */ + ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); + + /* Tell the kernel the link is down */ + ugeth->mii_info->link = 0; + adjust_link(ugeth->dev); + + /* Mask all interrupts */ + out_be32(ugeth->uccf->p_ucce, 0x00000000); + + /* Clear all interrupts */ + out_be32(ugeth->uccf->p_ucce, 0xffffffff); + + /* Disable Rx and Tx */ + tempval = in_be32(&ug_regs->maccfg1); + tempval &= ~(MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); + out_be32(&ug_regs->maccfg1, tempval); + + if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) { + /* Clear any pending interrupts */ + mii_clear_phy_interrupt(ugeth->mii_info); + + /* Disable PHY Interrupts */ + mii_configure_phy_interrupt(ugeth->mii_info, + MII_INTERRUPT_DISABLED); + } + + free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev); + + if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) { + free_irq(ugeth->ug_info->phy_interrupt, ugeth->dev); + } else { + del_timer_sync(&ugeth->phy_info_timer); + } + + ucc_geth_memclean(ugeth); +} + +static int ucc_geth_startup(ucc_geth_private_t *ugeth) +{ + ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; + ucc_geth_init_pram_t *p_init_enet_pram; + ucc_fast_private_t *uccf; + ucc_geth_info_t *ug_info; + ucc_fast_info_t *uf_info; + ucc_fast_t *uf_regs; + ucc_geth_t *ug_regs; + int ret_val = -EINVAL; + u32 remoder = UCC_GETH_REMODER_INIT; + u32 init_enet_pram_offset, cecr_subblock, command, maccfg1; + u32 ifstat, i, j, size, l2qt, l3qt, length; + u16 temoder = UCC_GETH_TEMODER_INIT; + u16 test; + u8 function_code = 0; + u8 *bd, *endOfRing; + u8 numThreadsRxNumerical, numThreadsTxNumerical; + + ugeth_vdbg("%s: IN", __FUNCTION__); + + ug_info = ugeth->ug_info; + uf_info = &ug_info->uf_info; + + if (!((uf_info->bd_mem_part == MEM_PART_SYSTEM) || + (uf_info->bd_mem_part == MEM_PART_MURAM))) { + ugeth_err("%s: Bad memory partition value.", __FUNCTION__); + return -EINVAL; + } + + /* Rx BD lengths */ + for (i = 0; i < ug_info->numQueuesRx; i++) { + if ((ug_info->bdRingLenRx[i] < UCC_GETH_RX_BD_RING_SIZE_MIN) || + (ug_info->bdRingLenRx[i] % + UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT)) { + ugeth_err + ("%s: Rx BD ring length must be multiple of 4," + " no smaller than 8.", __FUNCTION__); + return -EINVAL; + } + } + + /* Tx BD lengths */ + for (i = 0; i < ug_info->numQueuesTx; i++) { + if (ug_info->bdRingLenTx[i] < UCC_GETH_TX_BD_RING_SIZE_MIN) { + ugeth_err + ("%s: Tx BD ring length must be no smaller than 2.", + __FUNCTION__); + return -EINVAL; + } + } + + /* mrblr */ + if ((uf_info->max_rx_buf_length == 0) || + (uf_info->max_rx_buf_length % UCC_GETH_MRBLR_ALIGNMENT)) { + ugeth_err + ("%s: max_rx_buf_length must be non-zero multiple of 128.", + __FUNCTION__); + return -EINVAL; + } + + /* num Tx queues */ + if (ug_info->numQueuesTx > NUM_TX_QUEUES) { + ugeth_err("%s: number of tx queues too large.", __FUNCTION__); + return -EINVAL; + } + + /* num Rx queues */ + if (ug_info->numQueuesRx > NUM_RX_QUEUES) { + ugeth_err("%s: number of rx queues too large.", __FUNCTION__); + return -EINVAL; + } + + /* l2qt */ + for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++) { + if (ug_info->l2qt[i] >= ug_info->numQueuesRx) { + ugeth_err + ("%s: VLAN priority table entry must not be" + " larger than number of Rx queues.", + __FUNCTION__); + return -EINVAL; + } + } + + /* l3qt */ + for (i = 0; i < UCC_GETH_IP_PRIORITY_MAX; i++) { + if (ug_info->l3qt[i] >= ug_info->numQueuesRx) { + ugeth_err + ("%s: IP priority table entry must not be" + " larger than number of Rx queues.", + __FUNCTION__); + return -EINVAL; + } + } + + if (ug_info->cam && !ug_info->ecamptr) { + ugeth_err("%s: If cam mode is chosen, must supply cam ptr.", + __FUNCTION__); + return -EINVAL; + } + + if ((ug_info->numStationAddresses != + UCC_GETH_NUM_OF_STATION_ADDRESSES_1) + && ug_info->rxExtendedFiltering) { + ugeth_err("%s: Number of station addresses greater than 1 " + "not allowed in extended parsing mode.", + __FUNCTION__); + return -EINVAL; + } + + /* Generate uccm_mask for receive */ + uf_info->uccm_mask = ug_info->eventRegMask & UCCE_OTHER;/* Errors */ + for (i = 0; i < ug_info->numQueuesRx; i++) + uf_info->uccm_mask |= (UCCE_RXBF_SINGLE_MASK << i); + + for (i = 0; i < ug_info->numQueuesTx; i++) + uf_info->uccm_mask |= (UCCE_TXBF_SINGLE_MASK << i); + /* Initialize the general fast UCC block. */ + if (ucc_fast_init(uf_info, &uccf)) { + ugeth_err("%s: Failed to init uccf.", __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + ugeth->uccf = uccf; + + switch (ug_info->numThreadsRx) { + case UCC_GETH_NUM_OF_THREADS_1: + numThreadsRxNumerical = 1; + break; + case UCC_GETH_NUM_OF_THREADS_2: + numThreadsRxNumerical = 2; + break; + case UCC_GETH_NUM_OF_THREADS_4: + numThreadsRxNumerical = 4; + break; + case UCC_GETH_NUM_OF_THREADS_6: + numThreadsRxNumerical = 6; + break; + case UCC_GETH_NUM_OF_THREADS_8: + numThreadsRxNumerical = 8; + break; + default: + ugeth_err("%s: Bad number of Rx threads value.", __FUNCTION__); + ucc_geth_memclean(ugeth); + return -EINVAL; + break; + } + + switch (ug_info->numThreadsTx) { + case UCC_GETH_NUM_OF_THREADS_1: + numThreadsTxNumerical = 1; + break; + case UCC_GETH_NUM_OF_THREADS_2: + numThreadsTxNumerical = 2; + break; + case UCC_GETH_NUM_OF_THREADS_4: + numThreadsTxNumerical = 4; + break; + case UCC_GETH_NUM_OF_THREADS_6: + numThreadsTxNumerical = 6; + break; + case UCC_GETH_NUM_OF_THREADS_8: + numThreadsTxNumerical = 8; + break; + default: + ugeth_err("%s: Bad number of Tx threads value.", __FUNCTION__); + ucc_geth_memclean(ugeth); + return -EINVAL; + break; + } + + /* Calculate rx_extended_features */ + ugeth->rx_non_dynamic_extended_features = ug_info->ipCheckSumCheck || + ug_info->ipAddressAlignment || + (ug_info->numStationAddresses != + UCC_GETH_NUM_OF_STATION_ADDRESSES_1); + + ugeth->rx_extended_features = ugeth->rx_non_dynamic_extended_features || + (ug_info->vlanOperationTagged != UCC_GETH_VLAN_OPERATION_TAGGED_NOP) + || (ug_info->vlanOperationNonTagged != + UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP); + + uf_regs = uccf->uf_regs; + ug_regs = (ucc_geth_t *) (uccf->uf_regs); + ugeth->ug_regs = ug_regs; + + init_default_reg_vals(&uf_regs->upsmr, + &ug_regs->maccfg1, &ug_regs->maccfg2); + + /* Set UPSMR */ + /* For more details see the hardware spec. */ + init_rx_parameters(ug_info->bro, + ug_info->rsh, ug_info->pro, &uf_regs->upsmr); + + /* We're going to ignore other registers for now, */ + /* except as needed to get up and running */ + + /* Set MACCFG1 */ + /* For more details see the hardware spec. */ + init_flow_control_params(ug_info->aufc, + ug_info->receiveFlowControl, + 1, + ug_info->pausePeriod, + ug_info->extensionField, + &uf_regs->upsmr, + &ug_regs->uempr, &ug_regs->maccfg1); + + maccfg1 = in_be32(&ug_regs->maccfg1); + maccfg1 |= MACCFG1_ENABLE_RX; + maccfg1 |= MACCFG1_ENABLE_TX; + out_be32(&ug_regs->maccfg1, maccfg1); + + /* Set IPGIFG */ + /* For more details see the hardware spec. */ + ret_val = init_inter_frame_gap_params(ug_info->nonBackToBackIfgPart1, + ug_info->nonBackToBackIfgPart2, + ug_info-> + miminumInterFrameGapEnforcement, + ug_info->backToBackInterFrameGap, + &ug_regs->ipgifg); + if (ret_val != 0) { + ugeth_err("%s: IPGIFG initialization parameter too large.", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return ret_val; + } + + /* Set HAFDUP */ + /* For more details see the hardware spec. */ + ret_val = init_half_duplex_params(ug_info->altBeb, + ug_info->backPressureNoBackoff, + ug_info->noBackoff, + ug_info->excessDefer, + ug_info->altBebTruncation, + ug_info->maxRetransmission, + ug_info->collisionWindow, + &ug_regs->hafdup); + if (ret_val != 0) { + ugeth_err("%s: Half Duplex initialization parameter too large.", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return ret_val; + } + + /* Set IFSTAT */ + /* For more details see the hardware spec. */ + /* Read only - resets upon read */ + ifstat = in_be32(&ug_regs->ifstat); + + /* Clear UEMPR */ + /* For more details see the hardware spec. */ + out_be32(&ug_regs->uempr, 0); + + /* Set UESCR */ + /* For more details see the hardware spec. */ + init_hw_statistics_gathering_mode((ug_info->statisticsMode & + UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE), + 0, &uf_regs->upsmr, &ug_regs->uescr); + + /* Allocate Tx bds */ + for (j = 0; j < ug_info->numQueuesTx; j++) { + /* Allocate in multiple of + UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT, + according to spec */ + length = ((ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD) + / UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT) + * UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT; + if ((ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD) % + UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT) + length += UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT; + if (uf_info->bd_mem_part == MEM_PART_SYSTEM) { + u32 align = 4; + if (UCC_GETH_TX_BD_RING_ALIGNMENT > 4) + align = UCC_GETH_TX_BD_RING_ALIGNMENT; + ugeth->tx_bd_ring_offset[j] = + (u32) (kmalloc((u32) (length + align), + GFP_KERNEL)); + if (ugeth->tx_bd_ring_offset[j] != 0) + ugeth->p_tx_bd_ring[j] = + (void*)((ugeth->tx_bd_ring_offset[j] + + align) & ~(align - 1)); + } else if (uf_info->bd_mem_part == MEM_PART_MURAM) { + ugeth->tx_bd_ring_offset[j] = + qe_muram_alloc(length, + UCC_GETH_TX_BD_RING_ALIGNMENT); + if (!IS_MURAM_ERR(ugeth->tx_bd_ring_offset[j])) + ugeth->p_tx_bd_ring[j] = + (u8 *) qe_muram_addr(ugeth-> + tx_bd_ring_offset[j]); + } + if (!ugeth->p_tx_bd_ring[j]) { + ugeth_err + ("%s: Can not allocate memory for Tx bd rings.", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + /* Zero unused end of bd ring, according to spec */ + memset(ugeth->p_tx_bd_ring[j] + + ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD, 0, + length - ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD); + } + + /* Allocate Rx bds */ + for (j = 0; j < ug_info->numQueuesRx; j++) { + length = ug_info->bdRingLenRx[j] * UCC_GETH_SIZE_OF_BD; + if (uf_info->bd_mem_part == MEM_PART_SYSTEM) { + u32 align = 4; + if (UCC_GETH_RX_BD_RING_ALIGNMENT > 4) + align = UCC_GETH_RX_BD_RING_ALIGNMENT; + ugeth->rx_bd_ring_offset[j] = + (u32) (kmalloc((u32) (length + align), GFP_KERNEL)); + if (ugeth->rx_bd_ring_offset[j] != 0) + ugeth->p_rx_bd_ring[j] = + (void*)((ugeth->rx_bd_ring_offset[j] + + align) & ~(align - 1)); + } else if (uf_info->bd_mem_part == MEM_PART_MURAM) { + ugeth->rx_bd_ring_offset[j] = + qe_muram_alloc(length, + UCC_GETH_RX_BD_RING_ALIGNMENT); + if (!IS_MURAM_ERR(ugeth->rx_bd_ring_offset[j])) + ugeth->p_rx_bd_ring[j] = + (u8 *) qe_muram_addr(ugeth-> + rx_bd_ring_offset[j]); + } + if (!ugeth->p_rx_bd_ring[j]) { + ugeth_err + ("%s: Can not allocate memory for Rx bd rings.", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + } + + /* Init Tx bds */ + for (j = 0; j < ug_info->numQueuesTx; j++) { + /* Setup the skbuff rings */ + ugeth->tx_skbuff[j] = + (struct sk_buff **)kmalloc(sizeof(struct sk_buff *) * + ugeth->ug_info->bdRingLenTx[j], + GFP_KERNEL); + + if (ugeth->tx_skbuff[j] == NULL) { + ugeth_err("%s: Could not allocate tx_skbuff", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + + for (i = 0; i < ugeth->ug_info->bdRingLenTx[j]; i++) + ugeth->tx_skbuff[j][i] = NULL; + + ugeth->skb_curtx[j] = ugeth->skb_dirtytx[j] = 0; + bd = ugeth->confBd[j] = ugeth->txBd[j] = ugeth->p_tx_bd_ring[j]; + for (i = 0; i < ug_info->bdRingLenTx[j]; i++) { + BD_BUFFER_CLEAR(bd); + BD_STATUS_AND_LENGTH_SET(bd, 0); + bd += UCC_GETH_SIZE_OF_BD; + } + bd -= UCC_GETH_SIZE_OF_BD; + BD_STATUS_AND_LENGTH_SET(bd, T_W);/* for last BD set Wrap bit */ + } + + /* Init Rx bds */ + for (j = 0; j < ug_info->numQueuesRx; j++) { + /* Setup the skbuff rings */ + ugeth->rx_skbuff[j] = + (struct sk_buff **)kmalloc(sizeof(struct sk_buff *) * + ugeth->ug_info->bdRingLenRx[j], + GFP_KERNEL); + + if (ugeth->rx_skbuff[j] == NULL) { + ugeth_err("%s: Could not allocate rx_skbuff", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + + for (i = 0; i < ugeth->ug_info->bdRingLenRx[j]; i++) + ugeth->rx_skbuff[j][i] = NULL; + + ugeth->skb_currx[j] = 0; + bd = ugeth->rxBd[j] = ugeth->p_rx_bd_ring[j]; + for (i = 0; i < ug_info->bdRingLenRx[j]; i++) { + BD_STATUS_AND_LENGTH_SET(bd, R_I); + BD_BUFFER_CLEAR(bd); + bd += UCC_GETH_SIZE_OF_BD; + } + bd -= UCC_GETH_SIZE_OF_BD; + BD_STATUS_AND_LENGTH_SET(bd, R_W);/* for last BD set Wrap bit */ + } + + /* + * Global PRAM + */ + /* Tx global PRAM */ + /* Allocate global tx parameter RAM page */ + ugeth->tx_glbl_pram_offset = + qe_muram_alloc(sizeof(ucc_geth_tx_global_pram_t), + UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT); + if (IS_MURAM_ERR(ugeth->tx_glbl_pram_offset)) { + ugeth_err + ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + ugeth->p_tx_glbl_pram = + (ucc_geth_tx_global_pram_t *) qe_muram_addr(ugeth-> + tx_glbl_pram_offset); + /* Zero out p_tx_glbl_pram */ + memset(ugeth->p_tx_glbl_pram, 0, sizeof(ucc_geth_tx_global_pram_t)); + + /* Fill global PRAM */ + + /* TQPTR */ + /* Size varies with number of Tx threads */ + ugeth->thread_dat_tx_offset = + qe_muram_alloc(numThreadsTxNumerical * + sizeof(ucc_geth_thread_data_tx_t) + + 32 * (numThreadsTxNumerical == 1), + UCC_GETH_THREAD_DATA_ALIGNMENT); + if (IS_MURAM_ERR(ugeth->thread_dat_tx_offset)) { + ugeth_err + ("%s: Can not allocate DPRAM memory for p_thread_data_tx.", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + + ugeth->p_thread_data_tx = + (ucc_geth_thread_data_tx_t *) qe_muram_addr(ugeth-> + thread_dat_tx_offset); + out_be32(&ugeth->p_tx_glbl_pram->tqptr, ugeth->thread_dat_tx_offset); + + /* vtagtable */ + for (i = 0; i < UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX; i++) + out_be32(&ugeth->p_tx_glbl_pram->vtagtable[i], + ug_info->vtagtable[i]); + + /* iphoffset */ + for (i = 0; i < TX_IP_OFFSET_ENTRY_MAX; i++) + ugeth->p_tx_glbl_pram->iphoffset[i] = ug_info->iphoffset[i]; + + /* SQPTR */ + /* Size varies with number of Tx queues */ + ugeth->send_q_mem_reg_offset = + qe_muram_alloc(ug_info->numQueuesTx * + sizeof(ucc_geth_send_queue_qd_t), + UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT); + if (IS_MURAM_ERR(ugeth->send_q_mem_reg_offset)) { + ugeth_err + ("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + + ugeth->p_send_q_mem_reg = + (ucc_geth_send_queue_mem_region_t *) qe_muram_addr(ugeth-> + send_q_mem_reg_offset); + out_be32(&ugeth->p_tx_glbl_pram->sqptr, ugeth->send_q_mem_reg_offset); + + /* Setup the table */ + /* Assume BD rings are already established */ + for (i = 0; i < ug_info->numQueuesTx; i++) { + endOfRing = + ugeth->p_tx_bd_ring[i] + (ug_info->bdRingLenTx[i] - + 1) * UCC_GETH_SIZE_OF_BD; + if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) { + out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base, + (u32) virt_to_phys(ugeth->p_tx_bd_ring[i])); + out_be32(&ugeth->p_send_q_mem_reg->sqqd[i]. + last_bd_completed_address, + (u32) virt_to_phys(endOfRing)); + } else if (ugeth->ug_info->uf_info.bd_mem_part == + MEM_PART_MURAM) { + out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base, + (u32) immrbar_virt_to_phys(ugeth-> + p_tx_bd_ring[i])); + out_be32(&ugeth->p_send_q_mem_reg->sqqd[i]. + last_bd_completed_address, + (u32) immrbar_virt_to_phys(endOfRing)); + } + } + + /* schedulerbasepointer */ + + if (ug_info->numQueuesTx > 1) { + /* scheduler exists only if more than 1 tx queue */ + ugeth->scheduler_offset = + qe_muram_alloc(sizeof(ucc_geth_scheduler_t), + UCC_GETH_SCHEDULER_ALIGNMENT); + if (IS_MURAM_ERR(ugeth->scheduler_offset)) { + ugeth_err + ("%s: Can not allocate DPRAM memory for p_scheduler.", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + + ugeth->p_scheduler = + (ucc_geth_scheduler_t *) qe_muram_addr(ugeth-> + scheduler_offset); + out_be32(&ugeth->p_tx_glbl_pram->schedulerbasepointer, + ugeth->scheduler_offset); + /* Zero out p_scheduler */ + memset(ugeth->p_scheduler, 0, sizeof(ucc_geth_scheduler_t)); + + /* Set values in scheduler */ + out_be32(&ugeth->p_scheduler->mblinterval, + ug_info->mblinterval); + out_be16(&ugeth->p_scheduler->nortsrbytetime, + ug_info->nortsrbytetime); + ugeth->p_scheduler->fracsiz = ug_info->fracsiz; + ugeth->p_scheduler->strictpriorityq = ug_info->strictpriorityq; + ugeth->p_scheduler->txasap = ug_info->txasap; + ugeth->p_scheduler->extrabw = ug_info->extrabw; + for (i = 0; i < NUM_TX_QUEUES; i++) + ugeth->p_scheduler->weightfactor[i] = + ug_info->weightfactor[i]; + + /* Set pointers to cpucount registers in scheduler */ + ugeth->p_cpucount[0] = &(ugeth->p_scheduler->cpucount0); + ugeth->p_cpucount[1] = &(ugeth->p_scheduler->cpucount1); + ugeth->p_cpucount[2] = &(ugeth->p_scheduler->cpucount2); + ugeth->p_cpucount[3] = &(ugeth->p_scheduler->cpucount3); + ugeth->p_cpucount[4] = &(ugeth->p_scheduler->cpucount4); + ugeth->p_cpucount[5] = &(ugeth->p_scheduler->cpucount5); + ugeth->p_cpucount[6] = &(ugeth->p_scheduler->cpucount6); + ugeth->p_cpucount[7] = &(ugeth->p_scheduler->cpucount7); + } + + /* schedulerbasepointer */ + /* TxRMON_PTR (statistics) */ + if (ug_info-> + statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) { + ugeth->tx_fw_statistics_pram_offset = + qe_muram_alloc(sizeof + (ucc_geth_tx_firmware_statistics_pram_t), + UCC_GETH_TX_STATISTICS_ALIGNMENT); + if (IS_MURAM_ERR(ugeth->tx_fw_statistics_pram_offset)) { + ugeth_err + ("%s: Can not allocate DPRAM memory for" + " p_tx_fw_statistics_pram.", __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + ugeth->p_tx_fw_statistics_pram = + (ucc_geth_tx_firmware_statistics_pram_t *) + qe_muram_addr(ugeth->tx_fw_statistics_pram_offset); + /* Zero out p_tx_fw_statistics_pram */ + memset(ugeth->p_tx_fw_statistics_pram, + 0, sizeof(ucc_geth_tx_firmware_statistics_pram_t)); + } + + /* temoder */ + /* Already has speed set */ + + if (ug_info->numQueuesTx > 1) + temoder |= TEMODER_SCHEDULER_ENABLE; + if (ug_info->ipCheckSumGenerate) + temoder |= TEMODER_IP_CHECKSUM_GENERATE; + temoder |= ((ug_info->numQueuesTx - 1) << TEMODER_NUM_OF_QUEUES_SHIFT); + out_be16(&ugeth->p_tx_glbl_pram->temoder, temoder); + + test = in_be16(&ugeth->p_tx_glbl_pram->temoder); + + /* Function code register value to be used later */ + function_code = QE_BMR_BYTE_ORDER_BO_MOT | UCC_FAST_FUNCTION_CODE_GBL; + /* Required for QE */ + + /* function code register */ + out_be32(&ugeth->p_tx_glbl_pram->tstate, ((u32) function_code) << 24); + + /* Rx global PRAM */ + /* Allocate global rx parameter RAM page */ + ugeth->rx_glbl_pram_offset = + qe_muram_alloc(sizeof(ucc_geth_rx_global_pram_t), + UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT); + if (IS_MURAM_ERR(ugeth->rx_glbl_pram_offset)) { + ugeth_err + ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + ugeth->p_rx_glbl_pram = + (ucc_geth_rx_global_pram_t *) qe_muram_addr(ugeth-> + rx_glbl_pram_offset); + /* Zero out p_rx_glbl_pram */ + memset(ugeth->p_rx_glbl_pram, 0, sizeof(ucc_geth_rx_global_pram_t)); + + /* Fill global PRAM */ + + /* RQPTR */ + /* Size varies with number of Rx threads */ + ugeth->thread_dat_rx_offset = + qe_muram_alloc(numThreadsRxNumerical * + sizeof(ucc_geth_thread_data_rx_t), + UCC_GETH_THREAD_DATA_ALIGNMENT); + if (IS_MURAM_ERR(ugeth->thread_dat_rx_offset)) { + ugeth_err + ("%s: Can not allocate DPRAM memory for p_thread_data_rx.", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + + ugeth->p_thread_data_rx = + (ucc_geth_thread_data_rx_t *) qe_muram_addr(ugeth-> + thread_dat_rx_offset); + out_be32(&ugeth->p_rx_glbl_pram->rqptr, ugeth->thread_dat_rx_offset); + + /* typeorlen */ + out_be16(&ugeth->p_rx_glbl_pram->typeorlen, ug_info->typeorlen); + + /* rxrmonbaseptr (statistics) */ + if (ug_info-> + statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) { + ugeth->rx_fw_statistics_pram_offset = + qe_muram_alloc(sizeof + (ucc_geth_rx_firmware_statistics_pram_t), + UCC_GETH_RX_STATISTICS_ALIGNMENT); + if (IS_MURAM_ERR(ugeth->rx_fw_statistics_pram_offset)) { + ugeth_err + ("%s: Can not allocate DPRAM memory for" + " p_rx_fw_statistics_pram.", __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + ugeth->p_rx_fw_statistics_pram = + (ucc_geth_rx_firmware_statistics_pram_t *) + qe_muram_addr(ugeth->rx_fw_statistics_pram_offset); + /* Zero out p_rx_fw_statistics_pram */ + memset(ugeth->p_rx_fw_statistics_pram, 0, + sizeof(ucc_geth_rx_firmware_statistics_pram_t)); + } + + /* intCoalescingPtr */ + + /* Size varies with number of Rx queues */ + ugeth->rx_irq_coalescing_tbl_offset = + qe_muram_alloc(ug_info->numQueuesRx * + sizeof(ucc_geth_rx_interrupt_coalescing_entry_t), + UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT); + if (IS_MURAM_ERR(ugeth->rx_irq_coalescing_tbl_offset)) { + ugeth_err + ("%s: Can not allocate DPRAM memory for" + " p_rx_irq_coalescing_tbl.", __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + + ugeth->p_rx_irq_coalescing_tbl = + (ucc_geth_rx_interrupt_coalescing_table_t *) + qe_muram_addr(ugeth->rx_irq_coalescing_tbl_offset); + out_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr, + ugeth->rx_irq_coalescing_tbl_offset); + + /* Fill interrupt coalescing table */ + for (i = 0; i < ug_info->numQueuesRx; i++) { + out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i]. + interruptcoalescingmaxvalue, + ug_info->interruptcoalescingmaxvalue[i]); + out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i]. + interruptcoalescingcounter, + ug_info->interruptcoalescingmaxvalue[i]); + } + + /* MRBLR */ + init_max_rx_buff_len(uf_info->max_rx_buf_length, + &ugeth->p_rx_glbl_pram->mrblr); + /* MFLR */ + out_be16(&ugeth->p_rx_glbl_pram->mflr, ug_info->maxFrameLength); + /* MINFLR */ + init_min_frame_len(ug_info->minFrameLength, + &ugeth->p_rx_glbl_pram->minflr, + &ugeth->p_rx_glbl_pram->mrblr); + /* MAXD1 */ + out_be16(&ugeth->p_rx_glbl_pram->maxd1, ug_info->maxD1Length); + /* MAXD2 */ + out_be16(&ugeth->p_rx_glbl_pram->maxd2, ug_info->maxD2Length); + + /* l2qt */ + l2qt = 0; + for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++) + l2qt |= (ug_info->l2qt[i] << (28 - 4 * i)); + out_be32(&ugeth->p_rx_glbl_pram->l2qt, l2qt); + + /* l3qt */ + for (j = 0; j < UCC_GETH_IP_PRIORITY_MAX; j += 8) { + l3qt = 0; + for (i = 0; i < 8; i++) + l3qt |= (ug_info->l3qt[j + i] << (28 - 4 * i)); + out_be32(&ugeth->p_rx_glbl_pram->l3qt[j], l3qt); + } + + /* vlantype */ + out_be16(&ugeth->p_rx_glbl_pram->vlantype, ug_info->vlantype); + + /* vlantci */ + out_be16(&ugeth->p_rx_glbl_pram->vlantci, ug_info->vlantci); + + /* ecamptr */ + out_be32(&ugeth->p_rx_glbl_pram->ecamptr, ug_info->ecamptr); + + /* RBDQPTR */ + /* Size varies with number of Rx queues */ + ugeth->rx_bd_qs_tbl_offset = + qe_muram_alloc(ug_info->numQueuesRx * + (sizeof(ucc_geth_rx_bd_queues_entry_t) + + sizeof(ucc_geth_rx_prefetched_bds_t)), + UCC_GETH_RX_BD_QUEUES_ALIGNMENT); + if (IS_MURAM_ERR(ugeth->rx_bd_qs_tbl_offset)) { + ugeth_err + ("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + + ugeth->p_rx_bd_qs_tbl = + (ucc_geth_rx_bd_queues_entry_t *) qe_muram_addr(ugeth-> + rx_bd_qs_tbl_offset); + out_be32(&ugeth->p_rx_glbl_pram->rbdqptr, ugeth->rx_bd_qs_tbl_offset); + /* Zero out p_rx_bd_qs_tbl */ + memset(ugeth->p_rx_bd_qs_tbl, + 0, + ug_info->numQueuesRx * (sizeof(ucc_geth_rx_bd_queues_entry_t) + + sizeof(ucc_geth_rx_prefetched_bds_t))); + + /* Setup the table */ + /* Assume BD rings are already established */ + for (i = 0; i < ug_info->numQueuesRx; i++) { + if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) { + out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr, + (u32) virt_to_phys(ugeth->p_rx_bd_ring[i])); + } else if (ugeth->ug_info->uf_info.bd_mem_part == + MEM_PART_MURAM) { + out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr, + (u32) immrbar_virt_to_phys(ugeth-> + p_rx_bd_ring[i])); + } + /* rest of fields handled by QE */ + } + + /* remoder */ + /* Already has speed set */ + + if (ugeth->rx_extended_features) + remoder |= REMODER_RX_EXTENDED_FEATURES; + if (ug_info->rxExtendedFiltering) + remoder |= REMODER_RX_EXTENDED_FILTERING; + if (ug_info->dynamicMaxFrameLength) + remoder |= REMODER_DYNAMIC_MAX_FRAME_LENGTH; + if (ug_info->dynamicMinFrameLength) + remoder |= REMODER_DYNAMIC_MIN_FRAME_LENGTH; + remoder |= + ug_info->vlanOperationTagged << REMODER_VLAN_OPERATION_TAGGED_SHIFT; + remoder |= + ug_info-> + vlanOperationNonTagged << REMODER_VLAN_OPERATION_NON_TAGGED_SHIFT; + remoder |= ug_info->rxQoSMode << REMODER_RX_QOS_MODE_SHIFT; + remoder |= ((ug_info->numQueuesRx - 1) << REMODER_NUM_OF_QUEUES_SHIFT); + if (ug_info->ipCheckSumCheck) + remoder |= REMODER_IP_CHECKSUM_CHECK; + if (ug_info->ipAddressAlignment) + remoder |= REMODER_IP_ADDRESS_ALIGNMENT; + out_be32(&ugeth->p_rx_glbl_pram->remoder, remoder); + + /* Note that this function must be called */ + /* ONLY AFTER p_tx_fw_statistics_pram */ + /* andp_UccGethRxFirmwareStatisticsPram are allocated ! */ + init_firmware_statistics_gathering_mode((ug_info-> + statisticsMode & + UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX), + (ug_info->statisticsMode & + UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX), + &ugeth->p_tx_glbl_pram->txrmonbaseptr, + ugeth->tx_fw_statistics_pram_offset, + &ugeth->p_rx_glbl_pram->rxrmonbaseptr, + ugeth->rx_fw_statistics_pram_offset, + &ugeth->p_tx_glbl_pram->temoder, + &ugeth->p_rx_glbl_pram->remoder); + + /* function code register */ + ugeth->p_rx_glbl_pram->rstate = function_code; + + /* initialize extended filtering */ + if (ug_info->rxExtendedFiltering) { + if (!ug_info->extendedFilteringChainPointer) { + ugeth_err("%s: Null Extended Filtering Chain Pointer.", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return -EINVAL; + } + + /* Allocate memory for extended filtering Mode Global + Parameters */ + ugeth->exf_glbl_param_offset = + qe_muram_alloc(sizeof(ucc_geth_exf_global_pram_t), + UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT); + if (IS_MURAM_ERR(ugeth->exf_glbl_param_offset)) { + ugeth_err + ("%s: Can not allocate DPRAM memory for" + " p_exf_glbl_param.", __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + + ugeth->p_exf_glbl_param = + (ucc_geth_exf_global_pram_t *) qe_muram_addr(ugeth-> + exf_glbl_param_offset); + out_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam, + ugeth->exf_glbl_param_offset); + out_be32(&ugeth->p_exf_glbl_param->l2pcdptr, + (u32) ug_info->extendedFilteringChainPointer); + + } else { /* initialize 82xx style address filtering */ + + /* Init individual address recognition registers to disabled */ + + for (j = 0; j < NUM_OF_PADDRS; j++) + ugeth_82xx_filtering_clear_addr_in_paddr(ugeth, (u8) j); + + /* Create CQs for hash tables */ + if (ug_info->maxGroupAddrInHash > 0) { + INIT_LIST_HEAD(&ugeth->group_hash_q); + } + if (ug_info->maxIndAddrInHash > 0) { + INIT_LIST_HEAD(&ugeth->ind_hash_q); + } + p_82xx_addr_filt = + (ucc_geth_82xx_address_filtering_pram_t *) ugeth-> + p_rx_glbl_pram->addressfiltering; + + ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth, + ENET_ADDR_TYPE_GROUP); + ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth, + ENET_ADDR_TYPE_INDIVIDUAL); + } + + /* + * Initialize UCC at QE level + */ + + command = QE_INIT_TX_RX; + + /* Allocate shadow InitEnet command parameter structure. + * This is needed because after the InitEnet command is executed, + * the structure in DPRAM is released, because DPRAM is a premium + * resource. + * This shadow structure keeps a copy of what was done so that the + * allocated resources can be released when the channel is freed. + */ + if (!(ugeth->p_init_enet_param_shadow = + (ucc_geth_init_pram_t *) kmalloc(sizeof(ucc_geth_init_pram_t), + GFP_KERNEL))) { + ugeth_err + ("%s: Can not allocate memory for" + " p_UccInitEnetParamShadows.", __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + /* Zero out *p_init_enet_param_shadow */ + memset((char *)ugeth->p_init_enet_param_shadow, + 0, sizeof(ucc_geth_init_pram_t)); + + /* Fill shadow InitEnet command parameter structure */ + + ugeth->p_init_enet_param_shadow->resinit1 = + ENET_INIT_PARAM_MAGIC_RES_INIT1; + ugeth->p_init_enet_param_shadow->resinit2 = + ENET_INIT_PARAM_MAGIC_RES_INIT2; + ugeth->p_init_enet_param_shadow->resinit3 = + ENET_INIT_PARAM_MAGIC_RES_INIT3; + ugeth->p_init_enet_param_shadow->resinit4 = + ENET_INIT_PARAM_MAGIC_RES_INIT4; + ugeth->p_init_enet_param_shadow->resinit5 = + ENET_INIT_PARAM_MAGIC_RES_INIT5; + ugeth->p_init_enet_param_shadow->rgftgfrxglobal |= + ((u32) ug_info->numThreadsRx) << ENET_INIT_PARAM_RGF_SHIFT; + ugeth->p_init_enet_param_shadow->rgftgfrxglobal |= + ((u32) ug_info->numThreadsTx) << ENET_INIT_PARAM_TGF_SHIFT; + + ugeth->p_init_enet_param_shadow->rgftgfrxglobal |= + ugeth->rx_glbl_pram_offset | ug_info->riscRx; + if ((ug_info->largestexternallookupkeysize != + QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE) + && (ug_info->largestexternallookupkeysize != + QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES) + && (ug_info->largestexternallookupkeysize != + QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES)) { + ugeth_err("%s: Invalid largest External Lookup Key Size.", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return -EINVAL; + } + ugeth->p_init_enet_param_shadow->largestexternallookupkeysize = + ug_info->largestexternallookupkeysize; + size = sizeof(ucc_geth_thread_rx_pram_t); + if (ug_info->rxExtendedFiltering) { + size += THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING; + if (ug_info->largestexternallookupkeysize == + QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES) + size += + THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8; + if (ug_info->largestexternallookupkeysize == + QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES) + size += + THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16; + } + + if ((ret_val = fill_init_enet_entries(ugeth, &(ugeth-> + p_init_enet_param_shadow->rxthread[0]), + (u8) (numThreadsRxNumerical + 1) + /* Rx needs one extra for terminator */ + , size, UCC_GETH_THREAD_RX_PRAM_ALIGNMENT, + ug_info->riscRx, 1)) != 0) { + ugeth_err("%s: Can not fill p_init_enet_param_shadow.", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return ret_val; + } + + ugeth->p_init_enet_param_shadow->txglobal = + ugeth->tx_glbl_pram_offset | ug_info->riscTx; + if ((ret_val = + fill_init_enet_entries(ugeth, + &(ugeth->p_init_enet_param_shadow-> + txthread[0]), numThreadsTxNumerical, + sizeof(ucc_geth_thread_tx_pram_t), + UCC_GETH_THREAD_TX_PRAM_ALIGNMENT, + ug_info->riscTx, 0)) != 0) { + ugeth_err("%s: Can not fill p_init_enet_param_shadow.", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return ret_val; + } + + /* Load Rx bds with buffers */ + for (i = 0; i < ug_info->numQueuesRx; i++) { + if ((ret_val = rx_bd_buffer_set(ugeth, (u8) i)) != 0) { + ugeth_err("%s: Can not fill Rx bds with buffers.", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return ret_val; + } + } + + /* Allocate InitEnet command parameter structure */ + init_enet_pram_offset = qe_muram_alloc(sizeof(ucc_geth_init_pram_t), 4); + if (IS_MURAM_ERR(init_enet_pram_offset)) { + ugeth_err + ("%s: Can not allocate DPRAM memory for p_init_enet_pram.", + __FUNCTION__); + ucc_geth_memclean(ugeth); + return -ENOMEM; + } + p_init_enet_pram = + (ucc_geth_init_pram_t *) qe_muram_addr(init_enet_pram_offset); + + /* Copy shadow InitEnet command parameter structure into PRAM */ + p_init_enet_pram->resinit1 = ugeth->p_init_enet_param_shadow->resinit1; + p_init_enet_pram->resinit2 = ugeth->p_init_enet_param_shadow->resinit2; + p_init_enet_pram->resinit3 = ugeth->p_init_enet_param_shadow->resinit3; + p_init_enet_pram->resinit4 = ugeth->p_init_enet_param_shadow->resinit4; + out_be16(&p_init_enet_pram->resinit5, + ugeth->p_init_enet_param_shadow->resinit5); + p_init_enet_pram->largestexternallookupkeysize = + ugeth->p_init_enet_param_shadow->largestexternallookupkeysize; + out_be32(&p_init_enet_pram->rgftgfrxglobal, + ugeth->p_init_enet_param_shadow->rgftgfrxglobal); + for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_RX; i++) + out_be32(&p_init_enet_pram->rxthread[i], + ugeth->p_init_enet_param_shadow->rxthread[i]); + out_be32(&p_init_enet_pram->txglobal, + ugeth->p_init_enet_param_shadow->txglobal); + for (i = 0; i < ENET_INIT_PARAM_MAX_ENTRIES_TX; i++) + out_be32(&p_init_enet_pram->txthread[i], + ugeth->p_init_enet_param_shadow->txthread[i]); + + /* Issue QE command */ + cecr_subblock = + ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); + qe_issue_cmd(command, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET, + init_enet_pram_offset); + + /* Free InitEnet command parameter */ + qe_muram_free(init_enet_pram_offset); + + return 0; +} + +/* returns a net_device_stats structure pointer */ +static struct net_device_stats *ucc_geth_get_stats(struct net_device *dev) +{ + ucc_geth_private_t *ugeth = netdev_priv(dev); + + return &(ugeth->stats); +} + +/* ucc_geth_timeout gets called when a packet has not been + * transmitted after a set amount of time. + * For now, assume that clearing out all the structures, and + * starting over will fix the problem. */ +static void ucc_geth_timeout(struct net_device *dev) +{ + ucc_geth_private_t *ugeth = netdev_priv(dev); + + ugeth_vdbg("%s: IN", __FUNCTION__); + + ugeth->stats.tx_errors++; + + ugeth_dump_regs(ugeth); + + if (dev->flags & IFF_UP) { + ucc_geth_stop(ugeth); + ucc_geth_startup(ugeth); + } + + netif_schedule(dev); +} + +/* This is called by the kernel when a frame is ready for transmission. */ +/* It is pointed to by the dev->hard_start_xmit function pointer */ +static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + ucc_geth_private_t *ugeth = netdev_priv(dev); + u8 *bd; /* BD pointer */ + u32 bd_status; + u8 txQ = 0; + + ugeth_vdbg("%s: IN", __FUNCTION__); + + spin_lock_irq(&ugeth->lock); + + ugeth->stats.tx_bytes += skb->len; + + /* Start from the next BD that should be filled */ + bd = ugeth->txBd[txQ]; + bd_status = BD_STATUS_AND_LENGTH(bd); + /* Save the skb pointer so we can free it later */ + ugeth->tx_skbuff[txQ][ugeth->skb_curtx[txQ]] = skb; + + /* Update the current skb pointer (wrapping if this was the last) */ + ugeth->skb_curtx[txQ] = + (ugeth->skb_curtx[txQ] + + 1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]); + + /* set up the buffer descriptor */ + BD_BUFFER_SET(bd, + dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE)); + + //printk(KERN_DEBUG"skb->data is 0x%x\n",skb->data); + + bd_status = (bd_status & T_W) | T_R | T_I | T_L | skb->len; + + BD_STATUS_AND_LENGTH_SET(bd, bd_status); + + dev->trans_start = jiffies; + + /* Move to next BD in the ring */ + if (!(bd_status & T_W)) + ugeth->txBd[txQ] = bd + UCC_GETH_SIZE_OF_BD; + else + ugeth->txBd[txQ] = ugeth->p_tx_bd_ring[txQ]; + + /* If the next BD still needs to be cleaned up, then the bds + are full. We need to tell the kernel to stop sending us stuff. */ + if (bd == ugeth->confBd[txQ]) { + if (!netif_queue_stopped(dev)) + netif_stop_queue(dev); + } + + if (ugeth->p_scheduler) { + ugeth->cpucount[txQ]++; + /* Indicate to QE that there are more Tx bds ready for + transmission */ + /* This is done by writing a running counter of the bd + count to the scheduler PRAM. */ + out_be16(ugeth->p_cpucount[txQ], ugeth->cpucount[txQ]); + } + + spin_unlock_irq(&ugeth->lock); + + return 0; +} + +static int ucc_geth_rx(ucc_geth_private_t *ugeth, u8 rxQ, int rx_work_limit) +{ + struct sk_buff *skb; + u8 *bd; + u16 length, howmany = 0; + u32 bd_status; + u8 *bdBuffer; + + ugeth_vdbg("%s: IN", __FUNCTION__); + + spin_lock(&ugeth->lock); + /* collect received buffers */ + bd = ugeth->rxBd[rxQ]; + + bd_status = BD_STATUS_AND_LENGTH(bd); + + /* while there are received buffers and BD is full (~R_E) */ + while (!((bd_status & (R_E)) || (--rx_work_limit < 0))) { + bdBuffer = (u8 *) BD_BUFFER(bd); + length = (u16) ((bd_status & BD_LENGTH_MASK) - 4); + skb = ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]]; + + /* determine whether buffer is first, last, first and last + (single buffer frame) or middle (not first and not last) */ + if (!skb || + (!(bd_status & (R_F | R_L))) || + (bd_status & R_ERRORS_FATAL)) { + ugeth_vdbg("%s, %d: ERROR!!! skb - 0x%08x", + __FUNCTION__, __LINE__, (u32) skb); + if (skb) + dev_kfree_skb_any(skb); + + ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = NULL; + ugeth->stats.rx_dropped++; + } else { + ugeth->stats.rx_packets++; + howmany++; + + /* Prep the skb for the packet */ + skb_put(skb, length); + + /* Tell the skb what kind of packet this is */ + skb->protocol = eth_type_trans(skb, ugeth->dev); + + ugeth->stats.rx_bytes += length; + /* Send the packet up the stack */ +#ifdef CONFIG_UGETH_NAPI + netif_receive_skb(skb); +#else + netif_rx(skb); +#endif /* CONFIG_UGETH_NAPI */ + } + + ugeth->dev->last_rx = jiffies; + + skb = get_new_skb(ugeth, bd); + if (!skb) { + ugeth_warn("%s: No Rx Data Buffer", __FUNCTION__); + spin_unlock(&ugeth->lock); + ugeth->stats.rx_dropped++; + break; + } + + ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]] = skb; + + /* update to point at the next skb */ + ugeth->skb_currx[rxQ] = + (ugeth->skb_currx[rxQ] + + 1) & RX_RING_MOD_MASK(ugeth->ug_info->bdRingLenRx[rxQ]); + + if (bd_status & R_W) + bd = ugeth->p_rx_bd_ring[rxQ]; + else + bd += UCC_GETH_SIZE_OF_BD; + + bd_status = BD_STATUS_AND_LENGTH(bd); + } + + ugeth->rxBd[rxQ] = bd; + spin_unlock(&ugeth->lock); + return howmany; +} + +static int ucc_geth_tx(struct net_device *dev, u8 txQ) +{ + /* Start from the next BD that should be filled */ + ucc_geth_private_t *ugeth = netdev_priv(dev); + u8 *bd; /* BD pointer */ + u32 bd_status; + + bd = ugeth->confBd[txQ]; + bd_status = BD_STATUS_AND_LENGTH(bd); + + /* Normal processing. */ + while ((bd_status & T_R) == 0) { + /* BD contains already transmitted buffer. */ + /* Handle the transmitted buffer and release */ + /* the BD to be used with the current frame */ + + if ((bd = ugeth->txBd[txQ]) && (netif_queue_stopped(dev) == 0)) + break; + + ugeth->stats.tx_packets++; + + /* Free the sk buffer associated with this TxBD */ + dev_kfree_skb_irq(ugeth-> + tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]]); + ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]] = NULL; + ugeth->skb_dirtytx[txQ] = + (ugeth->skb_dirtytx[txQ] + + 1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]); + + /* We freed a buffer, so now we can restart transmission */ + if (netif_queue_stopped(dev)) + netif_wake_queue(dev); + + /* Advance the confirmation BD pointer */ + if (!(bd_status & T_W)) + ugeth->confBd[txQ] += UCC_GETH_SIZE_OF_BD; + else + ugeth->confBd[txQ] = ugeth->p_tx_bd_ring[txQ]; + } + return 0; +} + +#ifdef CONFIG_UGETH_NAPI +static int ucc_geth_poll(struct net_device *dev, int *budget) +{ + ucc_geth_private_t *ugeth = netdev_priv(dev); + int howmany; + int rx_work_limit = *budget; + u8 rxQ = 0; + + if (rx_work_limit > dev->quota) + rx_work_limit = dev->quota; + + howmany = ucc_geth_rx(ugeth, rxQ, rx_work_limit); + + dev->quota -= howmany; + rx_work_limit -= howmany; + *budget -= howmany; + + if (rx_work_limit >= 0) + netif_rx_complete(dev); + + return (rx_work_limit < 0) ? 1 : 0; +} +#endif /* CONFIG_UGETH_NAPI */ + +static irqreturn_t ucc_geth_irq_handler(int irq, void *info, + struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *)info; + ucc_geth_private_t *ugeth = netdev_priv(dev); + ucc_fast_private_t *uccf; + ucc_geth_info_t *ug_info; + register u32 ucce = 0; + register u32 bit_mask = UCCE_RXBF_SINGLE_MASK; + register u32 tx_mask = UCCE_TXBF_SINGLE_MASK; + register u8 i; + + ugeth_vdbg("%s: IN", __FUNCTION__); + + if (!ugeth) + return IRQ_NONE; + + uccf = ugeth->uccf; + ug_info = ugeth->ug_info; + + do { + ucce |= (u32) (in_be32(uccf->p_ucce) & in_be32(uccf->p_uccm)); + + /* clear event bits for next time */ + /* Side effect here is to mask ucce variable + for future processing below. */ + out_be32(uccf->p_ucce, ucce); /* Clear with ones, + but only bits in UCCM */ + + /* We ignore Tx interrupts because Tx confirmation is + done inside Tx routine */ + + for (i = 0; i < ug_info->numQueuesRx; i++) { + if (ucce & bit_mask) + ucc_geth_rx(ugeth, i, + (int)ugeth->ug_info-> + bdRingLenRx[i]); + ucce &= ~bit_mask; + bit_mask <<= 1; + } + + for (i = 0; i < ug_info->numQueuesTx; i++) { + if (ucce & tx_mask) + ucc_geth_tx(dev, i); + ucce &= ~tx_mask; + tx_mask <<= 1; + } + + /* Exceptions */ + if (ucce & UCCE_BSY) { + ugeth_vdbg("Got BUSY irq!!!!"); + ugeth->stats.rx_errors++; + ucce &= ~UCCE_BSY; + } + if (ucce & UCCE_OTHER) { + ugeth_vdbg("Got frame with error (ucce - 0x%08x)!!!!", + ucce); + ugeth->stats.rx_errors++; + ucce &= ~ucce; + } + } + while (ucce); + + return IRQ_HANDLED; +} + +static irqreturn_t phy_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *)dev_id; + ucc_geth_private_t *ugeth = netdev_priv(dev); + + ugeth_vdbg("%s: IN", __FUNCTION__); + + /* Clear the interrupt */ + mii_clear_phy_interrupt(ugeth->mii_info); + + /* Disable PHY interrupts */ + mii_configure_phy_interrupt(ugeth->mii_info, MII_INTERRUPT_DISABLED); + + /* Schedule the phy change */ + schedule_work(&ugeth->tq); + + return IRQ_HANDLED; +} + +/* Scheduled by the phy_interrupt/timer to handle PHY changes */ +static void ugeth_phy_change(void *data) +{ + struct net_device *dev = (struct net_device *)data; + ucc_geth_private_t *ugeth = netdev_priv(dev); + ucc_geth_t *ug_regs; + int result = 0; + + ugeth_vdbg("%s: IN", __FUNCTION__); + + ug_regs = ugeth->ug_regs; + + /* Delay to give the PHY a chance to change the + * register state */ + msleep(1); + + /* Update the link, speed, duplex */ + result = ugeth->mii_info->phyinfo->read_status(ugeth->mii_info); + + /* Adjust the known status as long as the link + * isn't still coming up */ + if ((0 == result) || (ugeth->mii_info->link == 0)) + adjust_link(dev); + + /* Reenable interrupts, if needed */ + if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) + mii_configure_phy_interrupt(ugeth->mii_info, + MII_INTERRUPT_ENABLED); +} + +/* Called every so often on systems that don't interrupt + * the core for PHY changes */ +static void ugeth_phy_timer(unsigned long data) +{ + struct net_device *dev = (struct net_device *)data; + ucc_geth_private_t *ugeth = netdev_priv(dev); + + schedule_work(&ugeth->tq); + + mod_timer(&ugeth->phy_info_timer, jiffies + PHY_CHANGE_TIME * HZ); +} + +/* Keep trying aneg for some time + * If, after GFAR_AN_TIMEOUT seconds, it has not + * finished, we switch to forced. + * Either way, once the process has completed, we either + * request the interrupt, or switch the timer over to + * using ugeth_phy_timer to check status */ +static void ugeth_phy_startup_timer(unsigned long data) +{ + struct ugeth_mii_info *mii_info = (struct ugeth_mii_info *)data; + ucc_geth_private_t *ugeth = netdev_priv(mii_info->dev); + static int secondary = UGETH_AN_TIMEOUT; + int result; + + /* Configure the Auto-negotiation */ + result = mii_info->phyinfo->config_aneg(mii_info); + + /* If autonegotiation failed to start, and + * we haven't timed out, reset the timer, and return */ + if (result && secondary--) { + mod_timer(&ugeth->phy_info_timer, jiffies + HZ); + return; + } else if (result) { + /* Couldn't start autonegotiation. + * Try switching to forced */ + mii_info->autoneg = 0; + result = mii_info->phyinfo->config_aneg(mii_info); + + /* Forcing failed! Give up */ + if (result) { + ugeth_err("%s: Forcing failed!", mii_info->dev->name); + return; + } + } + + /* Kill the timer so it can be restarted */ + del_timer_sync(&ugeth->phy_info_timer); + + /* Grab the PHY interrupt, if necessary/possible */ + if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) { + if (request_irq(ugeth->ug_info->phy_interrupt, + phy_interrupt, + SA_SHIRQ, "phy_interrupt", mii_info->dev) < 0) { + ugeth_err("%s: Can't get IRQ %d (PHY)", + mii_info->dev->name, + ugeth->ug_info->phy_interrupt); + } else { + mii_configure_phy_interrupt(ugeth->mii_info, + MII_INTERRUPT_ENABLED); + return; + } + } + + /* Start the timer again, this time in order to + * handle a change in status */ + init_timer(&ugeth->phy_info_timer); + ugeth->phy_info_timer.function = &ugeth_phy_timer; + ugeth->phy_info_timer.data = (unsigned long)mii_info->dev; + mod_timer(&ugeth->phy_info_timer, jiffies + PHY_CHANGE_TIME * HZ); +} + +/* Called when something needs to use the ethernet device */ +/* Returns 0 for success. */ +static int ucc_geth_open(struct net_device *dev) +{ + ucc_geth_private_t *ugeth = netdev_priv(dev); + int err; + + ugeth_vdbg("%s: IN", __FUNCTION__); + + /* Test station address */ + if (dev->dev_addr[0] & ENET_GROUP_ADDR) { + ugeth_err("%s: Multicast address used for station address" + " - is this what you wanted?", __FUNCTION__); + return -EINVAL; + } + + err = ucc_geth_startup(ugeth); + if (err) { + ugeth_err("%s: Cannot configure net device, aborting.", + dev->name); + return err; + } + + err = adjust_enet_interface(ugeth); + if (err) { + ugeth_err("%s: Cannot configure net device, aborting.", + dev->name); + return err; + } + + /* Set MACSTNADDR1, MACSTNADDR2 */ + /* For more details see the hardware spec. */ + init_mac_station_addr_regs(dev->dev_addr[0], + dev->dev_addr[1], + dev->dev_addr[2], + dev->dev_addr[3], + dev->dev_addr[4], + dev->dev_addr[5], + &ugeth->ug_regs->macstnaddr1, + &ugeth->ug_regs->macstnaddr2); + + err = init_phy(dev); + if (err) { + ugeth_err("%s: Cannot initialzie PHY, aborting.", dev->name); + return err; + } +#ifndef CONFIG_UGETH_NAPI + err = + request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, 0, + "UCC Geth", dev); + if (err) { + ugeth_err("%s: Cannot get IRQ for net device, aborting.", + dev->name); + ucc_geth_stop(ugeth); + return err; + } +#endif /* CONFIG_UGETH_NAPI */ + + /* Set up the PHY change work queue */ + INIT_WORK(&ugeth->tq, ugeth_phy_change, dev); + + init_timer(&ugeth->phy_info_timer); + ugeth->phy_info_timer.function = &ugeth_phy_startup_timer; + ugeth->phy_info_timer.data = (unsigned long)ugeth->mii_info; + mod_timer(&ugeth->phy_info_timer, jiffies + HZ); + + err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); + if (err) { + ugeth_err("%s: Cannot enable net device, aborting.", dev->name); + ucc_geth_stop(ugeth); + return err; + } + + netif_start_queue(dev); + + return err; +} + +/* Stops the kernel queue, and halts the controller */ +static int ucc_geth_close(struct net_device *dev) +{ + ucc_geth_private_t *ugeth = netdev_priv(dev); + + ugeth_vdbg("%s: IN", __FUNCTION__); + + ucc_geth_stop(ugeth); + + /* Shutdown the PHY */ + if (ugeth->mii_info->phyinfo->close) + ugeth->mii_info->phyinfo->close(ugeth->mii_info); + + kfree(ugeth->mii_info); + + netif_stop_queue(dev); + + return 0; +} + +struct ethtool_ops ucc_geth_ethtool_ops = { + .get_settings = NULL, + .get_drvinfo = NULL, + .get_regs_len = NULL, + .get_regs = NULL, + .get_link = NULL, + .get_coalesce = NULL, + .set_coalesce = NULL, + .get_ringparam = NULL, + .set_ringparam = NULL, + .get_strings = NULL, + .get_stats_count = NULL, + .get_ethtool_stats = NULL, +}; + +static int ucc_geth_probe(struct device *device) +{ + struct platform_device *pdev = to_platform_device(device); + struct ucc_geth_platform_data *ugeth_pdata; + struct net_device *dev = NULL; + struct ucc_geth_private *ugeth = NULL; + struct ucc_geth_info *ug_info; + int err; + static int mii_mng_configured = 0; + + ugeth_vdbg("%s: IN", __FUNCTION__); + + ugeth_pdata = (struct ucc_geth_platform_data *)pdev->dev.platform_data; + + ug_info = &ugeth_info[pdev->id]; + ug_info->uf_info.ucc_num = pdev->id; + ug_info->uf_info.rx_clock = ugeth_pdata->rx_clock; + ug_info->uf_info.tx_clock = ugeth_pdata->tx_clock; + ug_info->uf_info.regs = ugeth_pdata->phy_reg_addr; + ug_info->uf_info.irq = platform_get_irq(pdev, 0); + ug_info->phy_address = ugeth_pdata->phy_id; + ug_info->enet_interface = ugeth_pdata->phy_interface; + ug_info->board_flags = ugeth_pdata->board_flags; + ug_info->phy_interrupt = ugeth_pdata->phy_interrupt; + + printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n", + ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs, + ug_info->uf_info.irq); + + if (ug_info == NULL) { + ugeth_err("%s: [%d] Missing additional data!", __FUNCTION__, + pdev->id); + return -ENODEV; + } + + if (!mii_mng_configured) { + ucc_set_qe_mux_mii_mng(ug_info->uf_info.ucc_num); + mii_mng_configured = 1; + } + + /* Create an ethernet device instance */ + dev = alloc_etherdev(sizeof(*ugeth)); + + if (dev == NULL) + return -ENOMEM; + + ugeth = netdev_priv(dev); + spin_lock_init(&ugeth->lock); + + dev_set_drvdata(device, dev); + + /* Set the dev->base_addr to the gfar reg region */ + dev->base_addr = (unsigned long)(ug_info->uf_info.regs); + + SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, device); + + /* Fill in the dev structure */ + dev->open = ucc_geth_open; + dev->hard_start_xmit = ucc_geth_start_xmit; + dev->tx_timeout = ucc_geth_timeout; + dev->watchdog_timeo = TX_TIMEOUT; +#ifdef CONFIG_UGETH_NAPI + dev->poll = ucc_geth_poll; + dev->weight = UCC_GETH_DEV_WEIGHT; +#endif /* CONFIG_UGETH_NAPI */ + dev->stop = ucc_geth_close; + dev->get_stats = ucc_geth_get_stats; +// dev->change_mtu = ucc_geth_change_mtu; + dev->mtu = 1500; + dev->set_multicast_list = ucc_geth_set_multi; + dev->ethtool_ops = &ucc_geth_ethtool_ops; + + err = register_netdev(dev); + if (err) { + ugeth_err("%s: Cannot register net device, aborting.", + dev->name); + free_netdev(dev); + return err; + } + + ugeth->ug_info = ug_info; + ugeth->dev = dev; + memcpy(dev->dev_addr, ugeth_pdata->mac_addr, 6); + + return 0; +} + +static int ucc_geth_remove(struct device *device) +{ + struct net_device *dev = dev_get_drvdata(device); + struct ucc_geth_private *ugeth = netdev_priv(dev); + + dev_set_drvdata(device, NULL); + ucc_geth_memclean(ugeth); + free_netdev(dev); + + return 0; +} + +/* Structure for a device driver */ +static struct device_driver ucc_geth_driver = { + .name = DRV_NAME, + .bus = &platform_bus_type, + .probe = ucc_geth_probe, + .remove = ucc_geth_remove, +}; + +static int __init ucc_geth_init(void) +{ + int i; + printk(KERN_INFO "ucc_geth: " DRV_DESC "\n"); + for (i = 0; i < 8; i++) + memcpy(&(ugeth_info[i]), &ugeth_primary_info, + sizeof(ugeth_primary_info)); + + return driver_register(&ucc_geth_driver); +} + +static void __exit ucc_geth_exit(void) +{ + driver_unregister(&ucc_geth_driver); +} + +module_init(ucc_geth_init); +module_exit(ucc_geth_exit); + +MODULE_AUTHOR("Freescale Semiconductor, Inc"); +MODULE_DESCRIPTION(DRV_DESC); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h new file mode 100644 index 000000000..005965f5d --- /dev/null +++ b/drivers/net/ucc_geth.h @@ -0,0 +1,1339 @@ +/* + * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved. + * + * Author: Shlomi Gridish <gridish@freescale.com> + * + * Description: + * Internal header file for UCC Gigabit Ethernet unit routines. + * + * Changelog: + * Jun 28, 2006 Li Yang <LeoLi@freescale.com> + * - Rearrange code and style fixes + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#ifndef __UCC_GETH_H__ +#define __UCC_GETH_H__ + +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/fsl_devices.h> + +#include <asm/immap_qe.h> +#include <asm/qe.h> + +#include <asm/ucc.h> +#include <asm/ucc_fast.h> + +#define NUM_TX_QUEUES 8 +#define NUM_RX_QUEUES 8 +#define NUM_BDS_IN_PREFETCHED_BDS 4 +#define TX_IP_OFFSET_ENTRY_MAX 8 +#define NUM_OF_PADDRS 4 +#define ENET_INIT_PARAM_MAX_ENTRIES_RX 9 +#define ENET_INIT_PARAM_MAX_ENTRIES_TX 8 + +typedef struct ucc_mii_mng { + u32 miimcfg; /* MII management configuration reg */ + u32 miimcom; /* MII management command reg */ + u32 miimadd; /* MII management address reg */ + u32 miimcon; /* MII management control reg */ + u32 miimstat; /* MII management status reg */ + u32 miimind; /* MII management indication reg */ +} __attribute__ ((packed)) ucc_mii_mng_t; + +typedef struct ucc_geth { + ucc_fast_t uccf; + + u32 maccfg1; /* mac configuration reg. 1 */ + u32 maccfg2; /* mac configuration reg. 2 */ + u32 ipgifg; /* interframe gap reg. */ + u32 hafdup; /* half-duplex reg. */ + u8 res1[0x10]; + ucc_mii_mng_t miimng; /* MII management structure */ + u32 ifctl; /* interface control reg */ + u32 ifstat; /* interface statux reg */ + u32 macstnaddr1; /* mac station address part 1 reg */ + u32 macstnaddr2; /* mac station address part 2 reg */ + u8 res2[0x8]; + u32 uempr; /* UCC Ethernet Mac parameter reg */ + u32 utbipar; /* UCC tbi address reg */ + u16 uescr; /* UCC Ethernet statistics control reg */ + u8 res3[0x180 - 0x15A]; + u32 tx64; /* Total number of frames (including bad + frames) transmitted that were exactly of the + minimal length (64 for un tagged, 68 for + tagged, or with length exactly equal to the + parameter MINLength */ + u32 tx127; /* Total number of frames (including bad + frames) transmitted that were between + MINLength (Including FCS length==4) and 127 + octets */ + u32 tx255; /* Total number of frames (including bad + frames) transmitted that were between 128 + (Including FCS length==4) and 255 octets */ + u32 rx64; /* Total number of frames received including + bad frames that were exactly of the mninimal + length (64 bytes) */ + u32 rx127; /* Total number of frames (including bad + frames) received that were between MINLength + (Including FCS length==4) and 127 octets */ + u32 rx255; /* Total number of frames (including bad + frames) received that were between 128 + (Including FCS length==4) and 255 octets */ + u32 txok; /* Total number of octets residing in frames + that where involved in succesfull + transmission */ + u16 txcf; /* Total number of PAUSE control frames + transmitted by this MAC */ + u8 res4[0x2]; + u32 tmca; /* Total number of frames that were transmitted + succesfully with the group address bit set + that are not broadcast frames */ + u32 tbca; /* Total number of frames transmitted + succesfully that had destination address + field equal to the broadcast address */ + u32 rxfok; /* Total number of frames received OK */ + u32 rxbok; /* Total number of octets received OK */ + u32 rbyt; /* Total number of octets received including + octets in bad frames. Must be implemented in + HW because it includes octets in frames that + never even reach the UCC */ + u32 rmca; /* Total number of frames that were received + succesfully with the group address bit set + that are not broadcast frames */ + u32 rbca; /* Total number of frames received succesfully + that had destination address equal to the + broadcast address */ + u32 scar; /* Statistics carry register */ + u32 scam; /* Statistics caryy mask register */ + u8 res5[0x200 - 0x1c4]; +} __attribute__ ((packed)) ucc_geth_t; + +/* UCC GETH TEMODR Register */ +#define TEMODER_TX_RMON_STATISTICS_ENABLE 0x0100 /* enable Tx statistics + */ +#define TEMODER_SCHEDULER_ENABLE 0x2000 /* enable scheduler */ +#define TEMODER_IP_CHECKSUM_GENERATE 0x0400 /* generate IPv4 + checksums */ +#define TEMODER_PERFORMANCE_OPTIMIZATION_MODE1 0x0200 /* enable performance + optimization + enhancement (mode1) */ +#define TEMODER_RMON_STATISTICS 0x0100 /* enable tx statistics + */ +#define TEMODER_NUM_OF_QUEUES_SHIFT (15-15) /* Number of queues << + shift */ + +/* UCC GETH TEMODR Register */ +#define REMODER_RX_RMON_STATISTICS_ENABLE 0x00001000 /* enable Rx + statistics */ +#define REMODER_RX_EXTENDED_FEATURES 0x80000000 /* enable + extended + features */ +#define REMODER_VLAN_OPERATION_TAGGED_SHIFT (31-9 ) /* vlan operation + tagged << shift */ +#define REMODER_VLAN_OPERATION_NON_TAGGED_SHIFT (31-10) /* vlan operation non + tagged << shift */ +#define REMODER_RX_QOS_MODE_SHIFT (31-15) /* rx QoS mode << shift + */ +#define REMODER_RMON_STATISTICS 0x00001000 /* enable rx + statistics */ +#define REMODER_RX_EXTENDED_FILTERING 0x00000800 /* extended + filtering + vs. + mpc82xx-like + filtering */ +#define REMODER_NUM_OF_QUEUES_SHIFT (31-23) /* Number of queues << + shift */ +#define REMODER_DYNAMIC_MAX_FRAME_LENGTH 0x00000008 /* enable + dynamic max + frame length + */ +#define REMODER_DYNAMIC_MIN_FRAME_LENGTH 0x00000004 /* enable + dynamic min + frame length + */ +#define REMODER_IP_CHECKSUM_CHECK 0x00000002 /* check IPv4 + checksums */ +#define REMODER_IP_ADDRESS_ALIGNMENT 0x00000001 /* align ip + address to + 4-byte + boundary */ + +/* UCC GETH Event Register */ +#define UCCE_MPD 0x80000000 /* Magic packet + detection */ +#define UCCE_SCAR 0x40000000 +#define UCCE_GRA 0x20000000 /* Tx graceful + stop + complete */ +#define UCCE_CBPR 0x10000000 +#define UCCE_BSY 0x08000000 +#define UCCE_RXC 0x04000000 +#define UCCE_TXC 0x02000000 +#define UCCE_TXE 0x01000000 +#define UCCE_TXB7 0x00800000 +#define UCCE_TXB6 0x00400000 +#define UCCE_TXB5 0x00200000 +#define UCCE_TXB4 0x00100000 +#define UCCE_TXB3 0x00080000 +#define UCCE_TXB2 0x00040000 +#define UCCE_TXB1 0x00020000 +#define UCCE_TXB0 0x00010000 +#define UCCE_RXB7 0x00008000 +#define UCCE_RXB6 0x00004000 +#define UCCE_RXB5 0x00002000 +#define UCCE_RXB4 0x00001000 +#define UCCE_RXB3 0x00000800 +#define UCCE_RXB2 0x00000400 +#define UCCE_RXB1 0x00000200 +#define UCCE_RXB0 0x00000100 +#define UCCE_RXF7 0x00000080 +#define UCCE_RXF6 0x00000040 +#define UCCE_RXF5 0x00000020 +#define UCCE_RXF4 0x00000010 +#define UCCE_RXF3 0x00000008 +#define UCCE_RXF2 0x00000004 +#define UCCE_RXF1 0x00000002 +#define UCCE_RXF0 0x00000001 + +#define UCCE_RXBF_SINGLE_MASK (UCCE_RXF0) +#define UCCE_TXBF_SINGLE_MASK (UCCE_TXB0) + +#define UCCE_TXB (UCCE_TXB7 | UCCE_TXB6 | UCCE_TXB5 | UCCE_TXB4 |\ + UCCE_TXB3 | UCCE_TXB2 | UCCE_TXB1 | UCCE_TXB0) +#define UCCE_RXB (UCCE_RXB7 | UCCE_RXB6 | UCCE_RXB5 | UCCE_RXB4 |\ + UCCE_RXB3 | UCCE_RXB2 | UCCE_RXB1 | UCCE_RXB0) +#define UCCE_RXF (UCCE_RXF7 | UCCE_RXF6 | UCCE_RXF5 | UCCE_RXF4 |\ + UCCE_RXF3 | UCCE_RXF2 | UCCE_RXF1 | UCCE_RXF0) +#define UCCE_OTHER (UCCE_SCAR | UCCE_GRA | UCCE_CBPR | UCCE_BSY |\ + UCCE_RXC | UCCE_TXC | UCCE_TXE) + +/* UCC GETH UPSMR (Protocol Specific Mode Register) */ +#define UPSMR_ECM 0x04000000 /* Enable CAM + Miss or + Enable + Filtering + Miss */ +#define UPSMR_HSE 0x02000000 /* Hardware + Statistics + Enable */ +#define UPSMR_PRO 0x00400000 /* Promiscuous*/ +#define UPSMR_CAP 0x00200000 /* CAM polarity + */ +#define UPSMR_RSH 0x00100000 /* Receive + Short Frames + */ +#define UPSMR_RPM 0x00080000 /* Reduced Pin + Mode + interfaces */ +#define UPSMR_R10M 0x00040000 /* RGMII/RMII + 10 Mode */ +#define UPSMR_RLPB 0x00020000 /* RMII + Loopback + Mode */ +#define UPSMR_TBIM 0x00010000 /* Ten-bit + Interface + Mode */ +#define UPSMR_RMM 0x00001000 /* RMII/RGMII + Mode */ +#define UPSMR_CAM 0x00000400 /* CAM Address + Matching */ +#define UPSMR_BRO 0x00000200 /* Broadcast + Address */ +#define UPSMR_RES1 0x00002000 /* Reserved + feild - must + be 1 */ + +/* UCC GETH MACCFG1 (MAC Configuration 1 Register) */ +#define MACCFG1_FLOW_RX 0x00000020 /* Flow Control + Rx */ +#define MACCFG1_FLOW_TX 0x00000010 /* Flow Control + Tx */ +#define MACCFG1_ENABLE_SYNCHED_RX 0x00000008 /* Rx Enable + synchronized + to Rx stream + */ +#define MACCFG1_ENABLE_RX 0x00000004 /* Enable Rx */ +#define MACCFG1_ENABLE_SYNCHED_TX 0x00000002 /* Tx Enable + synchronized + to Tx stream + */ +#define MACCFG1_ENABLE_TX 0x00000001 /* Enable Tx */ + +/* UCC GETH MACCFG2 (MAC Configuration 2 Register) */ +#define MACCFG2_PREL_SHIFT (31 - 19) /* Preamble + Length << + shift */ +#define MACCFG2_PREL_MASK 0x0000f000 /* Preamble + Length mask */ +#define MACCFG2_SRP 0x00000080 /* Soft Receive + Preamble */ +#define MACCFG2_STP 0x00000040 /* Soft + Transmit + Preamble */ +#define MACCFG2_RESERVED_1 0x00000020 /* Reserved - + must be set + to 1 */ +#define MACCFG2_LC 0x00000010 /* Length Check + */ +#define MACCFG2_MPE 0x00000008 /* Magic packet + detect */ +#define MACCFG2_FDX 0x00000001 /* Full Duplex */ +#define MACCFG2_FDX_MASK 0x00000001 /* Full Duplex + mask */ +#define MACCFG2_PAD_CRC 0x00000004 +#define MACCFG2_CRC_EN 0x00000002 +#define MACCFG2_PAD_AND_CRC_MODE_NONE 0x00000000 /* Neither + Padding + short frames + nor CRC */ +#define MACCFG2_PAD_AND_CRC_MODE_CRC_ONLY 0x00000002 /* Append CRC + only */ +#define MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC 0x00000004 +#define MACCFG2_INTERFACE_MODE_NIBBLE 0x00000100 /* nibble mode + (MII/RMII/RGMII + 10/100bps) */ +#define MACCFG2_INTERFACE_MODE_BYTE 0x00000200 /* byte mode + (GMII/TBI/RTB/RGMII + 1000bps ) */ +#define MACCFG2_INTERFACE_MODE_MASK 0x00000300 /* mask + covering all + relevant + bits */ + +/* UCC GETH IPGIFG (Inter-frame Gap / Inter-Frame Gap Register) */ +#define IPGIFG_NON_BACK_TO_BACK_IFG_PART1_SHIFT (31 - 7) /* Non + back-to-back + inter frame + gap part 1. + << shift */ +#define IPGIFG_NON_BACK_TO_BACK_IFG_PART2_SHIFT (31 - 15) /* Non + back-to-back + inter frame + gap part 2. + << shift */ +#define IPGIFG_MINIMUM_IFG_ENFORCEMENT_SHIFT (31 - 23) /* Mimimum IFG + Enforcement + << shift */ +#define IPGIFG_BACK_TO_BACK_IFG_SHIFT (31 - 31) /* back-to-back + inter frame + gap << shift + */ +#define IPGIFG_NON_BACK_TO_BACK_IFG_PART1_MAX 127 /* Non back-to-back + inter frame gap part + 1. max val */ +#define IPGIFG_NON_BACK_TO_BACK_IFG_PART2_MAX 127 /* Non back-to-back + inter frame gap part + 2. max val */ +#define IPGIFG_MINIMUM_IFG_ENFORCEMENT_MAX 255 /* Mimimum IFG + Enforcement max val */ +#define IPGIFG_BACK_TO_BACK_IFG_MAX 127 /* back-to-back inter + frame gap max val */ +#define IPGIFG_NBTB_CS_IPG_MASK 0x7F000000 +#define IPGIFG_NBTB_IPG_MASK 0x007F0000 +#define IPGIFG_MIN_IFG_MASK 0x0000FF00 +#define IPGIFG_BTB_IPG_MASK 0x0000007F + +/* UCC GETH HAFDUP (Half Duplex Register) */ +#define HALFDUP_ALT_BEB_TRUNCATION_SHIFT (31 - 11) /* Alternate + Binary + Exponential + Backoff + Truncation + << shift */ +#define HALFDUP_ALT_BEB_TRUNCATION_MAX 0xf /* Alternate Binary + Exponential Backoff + Truncation max val */ +#define HALFDUP_ALT_BEB 0x00080000 /* Alternate + Binary + Exponential + Backoff */ +#define HALFDUP_BACK_PRESSURE_NO_BACKOFF 0x00040000 /* Back + pressure no + backoff */ +#define HALFDUP_NO_BACKOFF 0x00020000 /* No Backoff */ +#define HALFDUP_EXCESSIVE_DEFER 0x00010000 /* Excessive + Defer */ +#define HALFDUP_MAX_RETRANSMISSION_SHIFT (31 - 19) /* Maximum + Retransmission + << shift */ +#define HALFDUP_MAX_RETRANSMISSION_MAX 0xf /* Maximum + Retransmission max + val */ +#define HALFDUP_COLLISION_WINDOW_SHIFT (31 - 31) /* Collision + Window << + shift */ +#define HALFDUP_COLLISION_WINDOW_MAX 0x3f /* Collision Window max + val */ +#define HALFDUP_ALT_BEB_TR_MASK 0x00F00000 +#define HALFDUP_RETRANS_MASK 0x0000F000 +#define HALFDUP_COL_WINDOW_MASK 0x0000003F + +/* UCC GETH UCCS (Ethernet Status Register) */ +#define UCCS_BPR 0x02 /* Back pressure (in + half duplex mode) */ +#define UCCS_PAU 0x02 /* Pause state (in full + duplex mode) */ +#define UCCS_MPD 0x01 /* Magic Packet + Detected */ + +/* UCC GETH MIIMCFG (MII Management Configuration Register) */ +#define MIIMCFG_RESET_MANAGEMENT 0x80000000 /* Reset + management */ +#define MIIMCFG_NO_PREAMBLE 0x00000010 /* Preamble + suppress */ +#define MIIMCFG_CLOCK_DIVIDE_SHIFT (31 - 31) /* clock divide + << shift */ +#define MIIMCFG_CLOCK_DIVIDE_MAX 0xf /* clock divide max val + */ +#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_2 0x00000000 /* divide by 2 */ +#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_4 0x00000001 /* divide by 4 */ +#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_6 0x00000002 /* divide by 6 */ +#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_8 0x00000003 /* divide by 8 */ +#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_10 0x00000004 /* divide by 10 + */ +#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_14 0x00000005 /* divide by 14 + */ +#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_16 0x00000008 /* divide by 16 + */ +#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_20 0x00000006 /* divide by 20 + */ +#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_28 0x00000007 /* divide by 28 + */ +#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_32 0x00000009 /* divide by 32 + */ +#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_48 0x0000000a /* divide by 48 + */ +#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_64 0x0000000b /* divide by 64 + */ +#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_80 0x0000000c /* divide by 80 + */ +#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112 0x0000000d /* divide by + 112 */ +#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_160 0x0000000e /* divide by + 160 */ +#define MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_224 0x0000000f /* divide by + 224 */ + +/* UCC GETH MIIMCOM (MII Management Command Register) */ +#define MIIMCOM_SCAN_CYCLE 0x00000002 /* Scan cycle */ +#define MIIMCOM_READ_CYCLE 0x00000001 /* Read cycle */ + +/* UCC GETH MIIMADD (MII Management Address Register) */ +#define MIIMADD_PHY_ADDRESS_SHIFT (31 - 23) /* PHY Address + << shift */ +#define MIIMADD_PHY_REGISTER_SHIFT (31 - 31) /* PHY Register + << shift */ + +/* UCC GETH MIIMCON (MII Management Control Register) */ +#define MIIMCON_PHY_CONTROL_SHIFT (31 - 31) /* PHY Control + << shift */ +#define MIIMCON_PHY_STATUS_SHIFT (31 - 31) /* PHY Status + << shift */ + +/* UCC GETH MIIMIND (MII Management Indicator Register) */ +#define MIIMIND_NOT_VALID 0x00000004 /* Not valid */ +#define MIIMIND_SCAN 0x00000002 /* Scan in + progress */ +#define MIIMIND_BUSY 0x00000001 + +/* UCC GETH IFSTAT (Interface Status Register) */ +#define IFSTAT_EXCESS_DEFER 0x00000200 /* Excessive + transmission + defer */ + +/* UCC GETH MACSTNADDR1 (Station Address Part 1 Register) */ +#define MACSTNADDR1_OCTET_6_SHIFT (31 - 7) /* Station + address 6th + octet << + shift */ +#define MACSTNADDR1_OCTET_5_SHIFT (31 - 15) /* Station + address 5th + octet << + shift */ +#define MACSTNADDR1_OCTET_4_SHIFT (31 - 23) /* Station + address 4th + octet << + shift */ +#define MACSTNADDR1_OCTET_3_SHIFT (31 - 31) /* Station + address 3rd + octet << + shift */ + +/* UCC GETH MACSTNADDR2 (Station Address Part 2 Register) */ +#define MACSTNADDR2_OCTET_2_SHIFT (31 - 7) /* Station + address 2nd + octet << + shift */ +#define MACSTNADDR2_OCTET_1_SHIFT (31 - 15) /* Station + address 1st + octet << + shift */ + +/* UCC GETH UEMPR (Ethernet Mac Parameter Register) */ +#define UEMPR_PAUSE_TIME_VALUE_SHIFT (31 - 15) /* Pause time + value << + shift */ +#define UEMPR_EXTENDED_PAUSE_TIME_VALUE_SHIFT (31 - 31) /* Extended + pause time + value << + shift */ + +/* UCC GETH UTBIPAR (Ten Bit Interface Physical Address Register) */ +#define UTBIPAR_PHY_ADDRESS_SHIFT (31 - 31) /* Phy address + << shift */ +#define UTBIPAR_PHY_ADDRESS_MASK 0x0000001f /* Phy address + mask */ + +/* UCC GETH UESCR (Ethernet Statistics Control Register) */ +#define UESCR_AUTOZ 0x8000 /* Automatically zero + addressed + statistical counter + values */ +#define UESCR_CLRCNT 0x4000 /* Clear all statistics + counters */ +#define UESCR_MAXCOV_SHIFT (15 - 7) /* Max + Coalescing + Value << + shift */ +#define UESCR_SCOV_SHIFT (15 - 15) /* Status + Coalescing + Value << + shift */ + +/* UCC GETH UDSR (Data Synchronization Register) */ +#define UDSR_MAGIC 0x067E + +typedef struct ucc_geth_thread_data_tx { + u8 res0[104]; +} __attribute__ ((packed)) ucc_geth_thread_data_tx_t; + +typedef struct ucc_geth_thread_data_rx { + u8 res0[40]; +} __attribute__ ((packed)) ucc_geth_thread_data_rx_t; + +/* Send Queue Queue-Descriptor */ +typedef struct ucc_geth_send_queue_qd { + u32 bd_ring_base; /* pointer to BD ring base address */ + u8 res0[0x8]; + u32 last_bd_completed_address;/* initialize to last entry in BD ring */ + u8 res1[0x30]; +} __attribute__ ((packed)) ucc_geth_send_queue_qd_t; + +typedef struct ucc_geth_send_queue_mem_region { + ucc_geth_send_queue_qd_t sqqd[NUM_TX_QUEUES]; +} __attribute__ ((packed)) ucc_geth_send_queue_mem_region_t; + +typedef struct ucc_geth_thread_tx_pram { + u8 res0[64]; +} __attribute__ ((packed)) ucc_geth_thread_tx_pram_t; + +typedef struct ucc_geth_thread_rx_pram { + u8 res0[128]; +} __attribute__ ((packed)) ucc_geth_thread_rx_pram_t; + +#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING 64 +#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8 64 +#define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16 96 + +typedef struct ucc_geth_scheduler { + u16 cpucount0; /* CPU packet counter */ + u16 cpucount1; /* CPU packet counter */ + u16 cecount0; /* QE packet counter */ + u16 cecount1; /* QE packet counter */ + u16 cpucount2; /* CPU packet counter */ + u16 cpucount3; /* CPU packet counter */ + u16 cecount2; /* QE packet counter */ + u16 cecount3; /* QE packet counter */ + u16 cpucount4; /* CPU packet counter */ + u16 cpucount5; /* CPU packet counter */ + u16 cecount4; /* QE packet counter */ + u16 cecount5; /* QE packet counter */ + u16 cpucount6; /* CPU packet counter */ + u16 cpucount7; /* CPU packet counter */ + u16 cecount6; /* QE packet counter */ + u16 cecount7; /* QE packet counter */ + u32 weightstatus[NUM_TX_QUEUES]; /* accumulated weight factor */ + u32 rtsrshadow; /* temporary variable handled by QE */ + u32 time; /* temporary variable handled by QE */ + u32 ttl; /* temporary variable handled by QE */ + u32 mblinterval; /* max burst length interval */ + u16 nortsrbytetime; /* normalized value of byte time in tsr units */ + u8 fracsiz; /* radix 2 log value of denom. of + NorTSRByteTime */ + u8 res0[1]; + u8 strictpriorityq; /* Strict Priority Mask register */ + u8 txasap; /* Transmit ASAP register */ + u8 extrabw; /* Extra BandWidth register */ + u8 oldwfqmask; /* temporary variable handled by QE */ + u8 weightfactor[NUM_TX_QUEUES]; + /**< weight factor for queues */ + u32 minw; /* temporary variable handled by QE */ + u8 res1[0x70 - 0x64]; +} __attribute__ ((packed)) ucc_geth_scheduler_t; + +typedef struct ucc_geth_tx_firmware_statistics_pram { + u32 sicoltx; /* single collision */ + u32 mulcoltx; /* multiple collision */ + u32 latecoltxfr; /* late collision */ + u32 frabortduecol; /* frames aborted due to transmit collision */ + u32 frlostinmactxer; /* frames lost due to internal MAC error + transmission that are not counted on any + other counter */ + u32 carriersenseertx; /* carrier sense error */ + u32 frtxok; /* frames transmitted OK */ + u32 txfrexcessivedefer; /* frames with defferal time greater than + specified threshold */ + u32 txpkts256; /* total packets (including bad) between 256 + and 511 octets */ + u32 txpkts512; /* total packets (including bad) between 512 + and 1023 octets */ + u32 txpkts1024; /* total packets (including bad) between 1024 + and 1518 octets */ + u32 txpktsjumbo; /* total packets (including bad) between 1024 + and MAXLength octets */ +} __attribute__ ((packed)) ucc_geth_tx_firmware_statistics_pram_t; + +typedef struct ucc_geth_rx_firmware_statistics_pram { + u32 frrxfcser; /* frames with crc error */ + u32 fraligner; /* frames with alignment error */ + u32 inrangelenrxer; /* in range length error */ + u32 outrangelenrxer; /* out of range length error */ + u32 frtoolong; /* frame too long */ + u32 runt; /* runt */ + u32 verylongevent; /* very long event */ + u32 symbolerror; /* symbol error */ + u32 dropbsy; /* drop because of BD not ready */ + u8 res0[0x8]; + u32 mismatchdrop; /* drop because of MAC filtering (e.g. address + or type mismatch) */ + u32 underpkts; /* total frames less than 64 octets */ + u32 pkts256; /* total frames (including bad) between 256 and + 511 octets */ + u32 pkts512; /* total frames (including bad) between 512 and + 1023 octets */ + u32 pkts1024; /* total frames (including bad) between 1024 + and 1518 octets */ + u32 pktsjumbo; /* total frames (including bad) between 1024 + and MAXLength octets */ + u32 frlossinmacer; /* frames lost because of internal MAC error + that is not counted in any other counter */ + u32 pausefr; /* pause frames */ + u8 res1[0x4]; + u32 removevlan; /* total frames that had their VLAN tag removed + */ + u32 replacevlan; /* total frames that had their VLAN tag + replaced */ + u32 insertvlan; /* total frames that had their VLAN tag + inserted */ +} __attribute__ ((packed)) ucc_geth_rx_firmware_statistics_pram_t; + +typedef struct ucc_geth_rx_interrupt_coalescing_entry { + u32 interruptcoalescingmaxvalue; /* interrupt coalescing max + value */ + u32 interruptcoalescingcounter; /* interrupt coalescing counter, + initialize to + interruptcoalescingmaxvalue */ +} __attribute__ ((packed)) ucc_geth_rx_interrupt_coalescing_entry_t; + +typedef struct ucc_geth_rx_interrupt_coalescing_table { + ucc_geth_rx_interrupt_coalescing_entry_t coalescingentry[NUM_RX_QUEUES]; + /**< interrupt coalescing entry */ +} __attribute__ ((packed)) ucc_geth_rx_interrupt_coalescing_table_t; + +typedef struct ucc_geth_rx_prefetched_bds { + qe_bd_t bd[NUM_BDS_IN_PREFETCHED_BDS]; /* prefetched bd */ +} __attribute__ ((packed)) ucc_geth_rx_prefetched_bds_t; + +typedef struct ucc_geth_rx_bd_queues_entry { + u32 bdbaseptr; /* BD base pointer */ + u32 bdptr; /* BD pointer */ + u32 externalbdbaseptr; /* external BD base pointer */ + u32 externalbdptr; /* external BD pointer */ +} __attribute__ ((packed)) ucc_geth_rx_bd_queues_entry_t; + +typedef struct ucc_geth_tx_global_pram { + u16 temoder; + u8 res0[0x38 - 0x02]; + u32 sqptr; /* a base pointer to send queue memory region */ + u32 schedulerbasepointer; /* a base pointer to scheduler memory + region */ + u32 txrmonbaseptr; /* base pointer to Tx RMON statistics counter */ + u32 tstate; /* tx internal state. High byte contains + function code */ + u8 iphoffset[TX_IP_OFFSET_ENTRY_MAX]; + u32 vtagtable[0x8]; /* 8 4-byte VLAN tags */ + u32 tqptr; /* a base pointer to the Tx Queues Memory + Region */ + u8 res2[0x80 - 0x74]; +} __attribute__ ((packed)) ucc_geth_tx_global_pram_t; + +/* structure representing Extended Filtering Global Parameters in PRAM */ +typedef struct ucc_geth_exf_global_pram { + u32 l2pcdptr; /* individual address filter, high */ + u8 res0[0x10 - 0x04]; +} __attribute__ ((packed)) ucc_geth_exf_global_pram_t; + +typedef struct ucc_geth_rx_global_pram { + u32 remoder; /* ethernet mode reg. */ + u32 rqptr; /* base pointer to the Rx Queues Memory Region*/ + u32 res0[0x1]; + u8 res1[0x20 - 0xC]; + u16 typeorlen; /* cutoff point less than which, type/len field + is considered length */ + u8 res2[0x1]; + u8 rxgstpack; /* acknowledgement on GRACEFUL STOP RX command*/ + u32 rxrmonbaseptr; /* base pointer to Rx RMON statistics counter */ + u8 res3[0x30 - 0x28]; + u32 intcoalescingptr; /* Interrupt coalescing table pointer */ + u8 res4[0x36 - 0x34]; + u8 rstate; /* rx internal state. High byte contains + function code */ + u8 res5[0x46 - 0x37]; + u16 mrblr; /* max receive buffer length reg. */ + u32 rbdqptr; /* base pointer to RxBD parameter table + description */ + u16 mflr; /* max frame length reg. */ + u16 minflr; /* min frame length reg. */ + u16 maxd1; /* max dma1 length reg. */ + u16 maxd2; /* max dma2 length reg. */ + u32 ecamptr; /* external CAM address */ + u32 l2qt; /* VLAN priority mapping table. */ + u32 l3qt[0x8]; /* IP priority mapping table. */ + u16 vlantype; /* vlan type */ + u16 vlantci; /* default vlan tci */ + u8 addressfiltering[64]; /* address filtering data structure */ + u32 exfGlobalParam; /* base address for extended filtering global + parameters */ + u8 res6[0x100 - 0xC4]; /* Initialize to zero */ +} __attribute__ ((packed)) ucc_geth_rx_global_pram_t; + +#define GRACEFUL_STOP_ACKNOWLEDGE_RX 0x01 + +/* structure representing InitEnet command */ +typedef struct ucc_geth_init_pram { + u8 resinit1; + u8 resinit2; + u8 resinit3; + u8 resinit4; + u16 resinit5; + u8 res1[0x1]; + u8 largestexternallookupkeysize; + u32 rgftgfrxglobal; + u32 rxthread[ENET_INIT_PARAM_MAX_ENTRIES_RX]; /* rx threads */ + u8 res2[0x38 - 0x30]; + u32 txglobal; /* tx global */ + u32 txthread[ENET_INIT_PARAM_MAX_ENTRIES_TX]; /* tx threads */ + u8 res3[0x1]; +} __attribute__ ((packed)) ucc_geth_init_pram_t; + +#define ENET_INIT_PARAM_RGF_SHIFT (32 - 4) +#define ENET_INIT_PARAM_TGF_SHIFT (32 - 8) + +#define ENET_INIT_PARAM_RISC_MASK 0x0000003f +#define ENET_INIT_PARAM_PTR_MASK 0x00ffffc0 +#define ENET_INIT_PARAM_SNUM_MASK 0xff000000 +#define ENET_INIT_PARAM_SNUM_SHIFT 24 + +#define ENET_INIT_PARAM_MAGIC_RES_INIT1 0x06 +#define ENET_INIT_PARAM_MAGIC_RES_INIT2 0x30 +#define ENET_INIT_PARAM_MAGIC_RES_INIT3 0xff +#define ENET_INIT_PARAM_MAGIC_RES_INIT4 0x00 +#define ENET_INIT_PARAM_MAGIC_RES_INIT5 0x0400 + +/* structure representing 82xx Address Filtering Enet Address in PRAM */ +typedef struct ucc_geth_82xx_enet_address { + u8 res1[0x2]; + u16 h; /* address (MSB) */ + u16 m; /* address */ + u16 l; /* address (LSB) */ +} __attribute__ ((packed)) ucc_geth_82xx_enet_address_t; + +/* structure representing 82xx Address Filtering PRAM */ +typedef struct ucc_geth_82xx_address_filtering_pram { + u32 iaddr_h; /* individual address filter, high */ + u32 iaddr_l; /* individual address filter, low */ + u32 gaddr_h; /* group address filter, high */ + u32 gaddr_l; /* group address filter, low */ + ucc_geth_82xx_enet_address_t taddr; + ucc_geth_82xx_enet_address_t paddr[NUM_OF_PADDRS]; + u8 res0[0x40 - 0x38]; +} __attribute__ ((packed)) ucc_geth_82xx_address_filtering_pram_t; + +/* GETH Tx firmware statistics structure, used when calling + UCC_GETH_GetStatistics. */ +typedef struct ucc_geth_tx_firmware_statistics { + u32 sicoltx; /* single collision */ + u32 mulcoltx; /* multiple collision */ + u32 latecoltxfr; /* late collision */ + u32 frabortduecol; /* frames aborted due to transmit collision */ + u32 frlostinmactxer; /* frames lost due to internal MAC error + transmission that are not counted on any + other counter */ + u32 carriersenseertx; /* carrier sense error */ + u32 frtxok; /* frames transmitted OK */ + u32 txfrexcessivedefer; /* frames with defferal time greater than + specified threshold */ + u32 txpkts256; /* total packets (including bad) between 256 + and 511 octets */ + u32 txpkts512; /* total packets (including bad) between 512 + and 1023 octets */ + u32 txpkts1024; /* total packets (including bad) between 1024 + and 1518 octets */ + u32 txpktsjumbo; /* total packets (including bad) between 1024 + and MAXLength octets */ +} __attribute__ ((packed)) ucc_geth_tx_firmware_statistics_t; + +/* GETH Rx firmware statistics structure, used when calling + UCC_GETH_GetStatistics. */ +typedef struct ucc_geth_rx_firmware_statistics { + u32 frrxfcser; /* frames with crc error */ + u32 fraligner; /* frames with alignment error */ + u32 inrangelenrxer; /* in range length error */ + u32 outrangelenrxer; /* out of range length error */ + u32 frtoolong; /* frame too long */ + u32 runt; /* runt */ + u32 verylongevent; /* very long event */ + u32 symbolerror; /* symbol error */ + u32 dropbsy; /* drop because of BD not ready */ + u8 res0[0x8]; + u32 mismatchdrop; /* drop because of MAC filtering (e.g. address + or type mismatch) */ + u32 underpkts; /* total frames less than 64 octets */ + u32 pkts256; /* total frames (including bad) between 256 and + 511 octets */ + u32 pkts512; /* total frames (including bad) between 512 and + 1023 octets */ + u32 pkts1024; /* total frames (including bad) between 1024 + and 1518 octets */ + u32 pktsjumbo; /* total frames (including bad) between 1024 + and MAXLength octets */ + u32 frlossinmacer; /* frames lost because of internal MAC error + that is not counted in any other counter */ + u32 pausefr; /* pause frames */ + u8 res1[0x4]; + u32 removevlan; /* total frames that had their VLAN tag removed + */ + u32 replacevlan; /* total frames that had their VLAN tag + replaced */ + u32 insertvlan; /* total frames that had their VLAN tag + inserted */ +} __attribute__ ((packed)) ucc_geth_rx_firmware_statistics_t; + +/* GETH hardware statistics structure, used when calling + UCC_GETH_GetStatistics. */ +typedef struct ucc_geth_hardware_statistics { + u32 tx64; /* Total number of frames (including bad + frames) transmitted that were exactly of the + minimal length (64 for un tagged, 68 for + tagged, or with length exactly equal to the + parameter MINLength */ + u32 tx127; /* Total number of frames (including bad + frames) transmitted that were between + MINLength (Including FCS length==4) and 127 + octets */ + u32 tx255; /* Total number of frames (including bad + frames) transmitted that were between 128 + (Including FCS length==4) and 255 octets */ + u32 rx64; /* Total number of frames received including + bad frames that were exactly of the mninimal + length (64 bytes) */ + u32 rx127; /* Total number of frames (including bad + frames) received that were between MINLength + (Including FCS length==4) and 127 octets */ + u32 rx255; /* Total number of frames (including bad + frames) received that were between 128 + (Including FCS length==4) and 255 octets */ + u32 txok; /* Total number of octets residing in frames + that where involved in succesfull + transmission */ + u16 txcf; /* Total number of PAUSE control frames + transmitted by this MAC */ + u32 tmca; /* Total number of frames that were transmitted + succesfully with the group address bit set + that are not broadcast frames */ + u32 tbca; /* Total number of frames transmitted + succesfully that had destination address + field equal to the broadcast address */ + u32 rxfok; /* Total number of frames received OK */ + u32 rxbok; /* Total number of octets received OK */ + u32 rbyt; /* Total number of octets received including + octets in bad frames. Must be implemented in + HW because it includes octets in frames that + never even reach the UCC */ + u32 rmca; /* Total number of frames that were received + succesfully with the group address bit set + that are not broadcast frames */ + u32 rbca; /* Total number of frames received succesfully + that had destination address equal to the + broadcast address */ +} __attribute__ ((packed)) ucc_geth_hardware_statistics_t; + +/* UCC GETH Tx errors returned via TxConf callback */ +#define TX_ERRORS_DEF 0x0200 +#define TX_ERRORS_EXDEF 0x0100 +#define TX_ERRORS_LC 0x0080 +#define TX_ERRORS_RL 0x0040 +#define TX_ERRORS_RC_MASK 0x003C +#define TX_ERRORS_RC_SHIFT 2 +#define TX_ERRORS_UN 0x0002 +#define TX_ERRORS_CSL 0x0001 + +/* UCC GETH Rx errors returned via RxStore callback */ +#define RX_ERRORS_CMR 0x0200 +#define RX_ERRORS_M 0x0100 +#define RX_ERRORS_BC 0x0080 +#define RX_ERRORS_MC 0x0040 + +/* Transmit BD. These are in addition to values defined in uccf. */ +#define T_VID 0x003c0000 /* insert VLAN id index mask. */ +#define T_DEF (((u32) TX_ERRORS_DEF ) << 16) +#define T_EXDEF (((u32) TX_ERRORS_EXDEF ) << 16) +#define T_LC (((u32) TX_ERRORS_LC ) << 16) +#define T_RL (((u32) TX_ERRORS_RL ) << 16) +#define T_RC_MASK (((u32) TX_ERRORS_RC_MASK ) << 16) +#define T_UN (((u32) TX_ERRORS_UN ) << 16) +#define T_CSL (((u32) TX_ERRORS_CSL ) << 16) +#define T_ERRORS_REPORT (T_DEF | T_EXDEF | T_LC | T_RL | T_RC_MASK \ + | T_UN | T_CSL) /* transmit errors to report */ + +/* Receive BD. These are in addition to values defined in uccf. */ +#define R_LG 0x00200000 /* Frame length violation. */ +#define R_NO 0x00100000 /* Non-octet aligned frame. */ +#define R_SH 0x00080000 /* Short frame. */ +#define R_CR 0x00040000 /* CRC error. */ +#define R_OV 0x00020000 /* Overrun. */ +#define R_IPCH 0x00010000 /* IP checksum check failed. */ +#define R_CMR (((u32) RX_ERRORS_CMR ) << 16) +#define R_M (((u32) RX_ERRORS_M ) << 16) +#define R_BC (((u32) RX_ERRORS_BC ) << 16) +#define R_MC (((u32) RX_ERRORS_MC ) << 16) +#define R_ERRORS_REPORT (R_CMR | R_M | R_BC | R_MC) /* receive errors to + report */ +#define R_ERRORS_FATAL (R_LG | R_NO | R_SH | R_CR | \ + R_OV | R_IPCH) /* receive errors to discard */ + +/* Alignments */ +#define UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT 256 +#define UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT 128 +#define UCC_GETH_THREAD_RX_PRAM_ALIGNMENT 128 +#define UCC_GETH_THREAD_TX_PRAM_ALIGNMENT 64 +#define UCC_GETH_THREAD_DATA_ALIGNMENT 256 /* spec gives values + based on num of + threads, but always + using the maximum is + easier */ +#define UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT 32 +#define UCC_GETH_SCHEDULER_ALIGNMENT 4 /* This is a guess */ +#define UCC_GETH_TX_STATISTICS_ALIGNMENT 4 /* This is a guess */ +#define UCC_GETH_RX_STATISTICS_ALIGNMENT 4 /* This is a guess */ +#define UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT 4 /* This is a + guess */ +#define UCC_GETH_RX_BD_QUEUES_ALIGNMENT 8 /* This is a guess */ +#define UCC_GETH_RX_PREFETCHED_BDS_ALIGNMENT 128 /* This is a guess */ +#define UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT 4 /* This + is a + guess + */ +#define UCC_GETH_RX_BD_RING_ALIGNMENT 32 +#define UCC_GETH_TX_BD_RING_ALIGNMENT 32 +#define UCC_GETH_MRBLR_ALIGNMENT 128 +#define UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT 4 +#define UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT 32 +#define UCC_GETH_RX_DATA_BUF_ALIGNMENT 64 + +#define UCC_GETH_TAD_EF 0x80 +#define UCC_GETH_TAD_V 0x40 +#define UCC_GETH_TAD_REJ 0x20 +#define UCC_GETH_TAD_VTAG_OP_RIGHT_SHIFT 2 +#define UCC_GETH_TAD_VTAG_OP_SHIFT 6 +#define UCC_GETH_TAD_V_NON_VTAG_OP 0x20 +#define UCC_GETH_TAD_RQOS_SHIFT 0 +#define UCC_GETH_TAD_V_PRIORITY_SHIFT 5 +#define UCC_GETH_TAD_CFI 0x10 + +#define UCC_GETH_VLAN_PRIORITY_MAX 8 +#define UCC_GETH_IP_PRIORITY_MAX 64 +#define UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX 8 +#define UCC_GETH_RX_BD_RING_SIZE_MIN 8 +#define UCC_GETH_TX_BD_RING_SIZE_MIN 2 + +#define UCC_GETH_SIZE_OF_BD QE_SIZEOF_BD + +/* Driver definitions */ +#define TX_BD_RING_LEN 0x10 +#define RX_BD_RING_LEN 0x10 +#define UCC_GETH_DEV_WEIGHT TX_BD_RING_LEN + +#define TX_RING_MOD_MASK(size) (size-1) +#define RX_RING_MOD_MASK(size) (size-1) + +#define ENET_NUM_OCTETS_PER_ADDRESS 6 +#define ENET_GROUP_ADDR 0x01 /* Group address mask + for ethernet + addresses */ + +#define TX_TIMEOUT (1*HZ) +#define SKB_ALLOC_TIMEOUT 100000 +#define PHY_INIT_TIMEOUT 100000 +#define PHY_CHANGE_TIME 2 + +/* Fast Ethernet (10/100 Mbps) */ +#define UCC_GETH_URFS_INIT 512 /* Rx virtual FIFO size + */ +#define UCC_GETH_URFET_INIT 256 /* 1/2 urfs */ +#define UCC_GETH_URFSET_INIT 384 /* 3/4 urfs */ +#define UCC_GETH_UTFS_INIT 512 /* Tx virtual FIFO size + */ +#define UCC_GETH_UTFET_INIT 256 /* 1/2 utfs */ +#define UCC_GETH_UTFTT_INIT 128 +/* Gigabit Ethernet (1000 Mbps) */ +#define UCC_GETH_URFS_GIGA_INIT 4096/*2048*/ /* Rx virtual + FIFO size */ +#define UCC_GETH_URFET_GIGA_INIT 2048/*1024*/ /* 1/2 urfs */ +#define UCC_GETH_URFSET_GIGA_INIT 3072/*1536*/ /* 3/4 urfs */ +#define UCC_GETH_UTFS_GIGA_INIT 8192/*2048*/ /* Tx virtual + FIFO size */ +#define UCC_GETH_UTFET_GIGA_INIT 4096/*1024*/ /* 1/2 utfs */ +#define UCC_GETH_UTFTT_GIGA_INIT 0x400/*0x40*/ /* */ + +#define UCC_GETH_REMODER_INIT 0 /* bits that must be + set */ +#define UCC_GETH_TEMODER_INIT 0xC000 /* bits that must */ +#define UCC_GETH_UPSMR_INIT (UPSMR_RES1) /* Start value + for this + register */ +#define UCC_GETH_MACCFG1_INIT 0 +#define UCC_GETH_MACCFG2_INIT (MACCFG2_RESERVED_1) +#define UCC_GETH_MIIMCFG_MNGMNT_CLC_DIV_INIT \ + (MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112) + +/* Ethernet speed */ +typedef enum enet_speed { + ENET_SPEED_10BT, /* 10 Base T */ + ENET_SPEED_100BT, /* 100 Base T */ + ENET_SPEED_1000BT /* 1000 Base T */ +} enet_speed_e; + +/* Ethernet Address Type. */ +typedef enum enet_addr_type { + ENET_ADDR_TYPE_INDIVIDUAL, + ENET_ADDR_TYPE_GROUP, + ENET_ADDR_TYPE_BROADCAST +} enet_addr_type_e; + +/* TBI / MII Set Register */ +typedef enum enet_tbi_mii_reg { + ENET_TBI_MII_CR = 0x00, /* Control (CR ) */ + ENET_TBI_MII_SR = 0x01, /* Status (SR ) */ + ENET_TBI_MII_ANA = 0x04, /* AN advertisement (ANA ) */ + ENET_TBI_MII_ANLPBPA = 0x05, /* AN link partner base page ability + (ANLPBPA) */ + ENET_TBI_MII_ANEX = 0x06, /* AN expansion (ANEX ) */ + ENET_TBI_MII_ANNPT = 0x07, /* AN next page transmit (ANNPT ) */ + ENET_TBI_MII_ANLPANP = 0x08, /* AN link partner ability next page + (ANLPANP) */ + ENET_TBI_MII_EXST = 0x0F, /* Extended status (EXST ) */ + ENET_TBI_MII_JD = 0x10, /* Jitter diagnostics (JD ) */ + ENET_TBI_MII_TBICON = 0x11 /* TBI control (TBICON ) */ +} enet_tbi_mii_reg_e; + +/* UCC GETH 82xx Ethernet Address Recognition Location */ +typedef enum ucc_geth_enet_address_recognition_location { + UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_STATION_ADDRESS,/* station + address */ + UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR_FIRST, /* additional + station + address + paddr1 */ + UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR2, /* additional + station + address + paddr2 */ + UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR3, /* additional + station + address + paddr3 */ + UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR_LAST, /* additional + station + address + paddr4 */ + UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH, /* group hash */ + UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH /* individual + hash */ +} ucc_geth_enet_address_recognition_location_e; + +/* UCC GETH vlan operation tagged */ +typedef enum ucc_geth_vlan_operation_tagged { + UCC_GETH_VLAN_OPERATION_TAGGED_NOP = 0x0, /* Tagged - nop */ + UCC_GETH_VLAN_OPERATION_TAGGED_REPLACE_VID_PORTION_OF_Q_TAG + = 0x1, /* Tagged - replace vid portion of q tag */ + UCC_GETH_VLAN_OPERATION_TAGGED_IF_VID0_REPLACE_VID_WITH_DEFAULT_VALUE + = 0x2, /* Tagged - if vid0 replace vid with default value */ + UCC_GETH_VLAN_OPERATION_TAGGED_EXTRACT_Q_TAG_FROM_FRAME + = 0x3 /* Tagged - extract q tag from frame */ +} ucc_geth_vlan_operation_tagged_e; + +/* UCC GETH vlan operation non-tagged */ +typedef enum ucc_geth_vlan_operation_non_tagged { + UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP = 0x0, /* Non tagged - nop */ + UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT = 0x1 /* Non tagged - + q tag insert + */ +} ucc_geth_vlan_operation_non_tagged_e; + +/* UCC GETH Rx Quality of Service Mode */ +typedef enum ucc_geth_qos_mode { + UCC_GETH_QOS_MODE_DEFAULT = 0x0, /* default queue */ + UCC_GETH_QOS_MODE_QUEUE_NUM_FROM_L2_CRITERIA = 0x1, /* queue + determined + by L2 + criteria */ + UCC_GETH_QOS_MODE_QUEUE_NUM_FROM_L3_CRITERIA = 0x2 /* queue + determined + by L3 + criteria */ +} ucc_geth_qos_mode_e; + +/* UCC GETH Statistics Gathering Mode - These are bit flags, 'or' them together + for combined functionality */ +typedef enum ucc_geth_statistics_gathering_mode { + UCC_GETH_STATISTICS_GATHERING_MODE_NONE = 0x00000000, /* No + statistics + gathering */ + UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE = 0x00000001,/* Enable + hardware + statistics + gathering + */ + UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX = 0x00000004,/*Enable + firmware + tx + statistics + gathering + */ + UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX = 0x00000008/* Enable + firmware + rx + statistics + gathering + */ +} ucc_geth_statistics_gathering_mode_e; + +/* UCC GETH Pad and CRC Mode - Note, Padding without CRC is not possible */ +typedef enum ucc_geth_maccfg2_pad_and_crc_mode { + UCC_GETH_PAD_AND_CRC_MODE_NONE + = MACCFG2_PAD_AND_CRC_MODE_NONE, /* Neither Padding + short frames + nor CRC */ + UCC_GETH_PAD_AND_CRC_MODE_CRC_ONLY + = MACCFG2_PAD_AND_CRC_MODE_CRC_ONLY, /* Append + CRC only */ + UCC_GETH_PAD_AND_CRC_MODE_PAD_AND_CRC = + MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC +} ucc_geth_maccfg2_pad_and_crc_mode_e; + +/* UCC GETH upsmr Flow Control Mode */ +typedef enum ucc_geth_flow_control_mode { + UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE = 0x00000000, /* No automatic + flow control + */ + UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_PAUSE_WHEN_EMERGENCY + = 0x00004000 /* Send pause frame when RxFIFO reaches its + emergency threshold */ +} ucc_geth_flow_control_mode_e; + +/* UCC GETH number of threads */ +typedef enum ucc_geth_num_of_threads { + UCC_GETH_NUM_OF_THREADS_1 = 0x1, /* 1 */ + UCC_GETH_NUM_OF_THREADS_2 = 0x2, /* 2 */ + UCC_GETH_NUM_OF_THREADS_4 = 0x0, /* 4 */ + UCC_GETH_NUM_OF_THREADS_6 = 0x3, /* 6 */ + UCC_GETH_NUM_OF_THREADS_8 = 0x4 /* 8 */ +} ucc_geth_num_of_threads_e; + +/* UCC GETH number of station addresses */ +typedef enum ucc_geth_num_of_station_addresses { + UCC_GETH_NUM_OF_STATION_ADDRESSES_1, /* 1 */ + UCC_GETH_NUM_OF_STATION_ADDRESSES_5 /* 5 */ +} ucc_geth_num_of_station_addresses_e; + +typedef u8 enet_addr_t[ENET_NUM_OCTETS_PER_ADDRESS]; + +/* UCC GETH 82xx Ethernet Address Container */ +typedef struct enet_addr_container { + enet_addr_t address; /* ethernet address */ + ucc_geth_enet_address_recognition_location_e location; /* location in + 82xx address + recognition + hardware */ + struct list_head node; +} enet_addr_container_t; + +#define ENET_ADDR_CONT_ENTRY(ptr) list_entry(ptr, enet_addr_container_t, node) + +/* UCC GETH Termination Action Descriptor (TAD) structure. */ +typedef struct ucc_geth_tad_params { + int rx_non_dynamic_extended_features_mode; + int reject_frame; + ucc_geth_vlan_operation_tagged_e vtag_op; + ucc_geth_vlan_operation_non_tagged_e vnontag_op; + ucc_geth_qos_mode_e rqos; + u8 vpri; + u16 vid; +} ucc_geth_tad_params_t; + +/* GETH protocol initialization structure */ +typedef struct ucc_geth_info { + ucc_fast_info_t uf_info; + u8 numQueuesTx; + u8 numQueuesRx; + int ipCheckSumCheck; + int ipCheckSumGenerate; + int rxExtendedFiltering; + u32 extendedFilteringChainPointer; + u16 typeorlen; + int dynamicMaxFrameLength; + int dynamicMinFrameLength; + u8 nonBackToBackIfgPart1; + u8 nonBackToBackIfgPart2; + u8 miminumInterFrameGapEnforcement; + u8 backToBackInterFrameGap; + int ipAddressAlignment; + int lengthCheckRx; + u32 mblinterval; + u16 nortsrbytetime; + u8 fracsiz; + u8 strictpriorityq; + u8 txasap; + u8 extrabw; + int miiPreambleSupress; + u8 altBebTruncation; + int altBeb; + int backPressureNoBackoff; + int noBackoff; + int excessDefer; + u8 maxRetransmission; + u8 collisionWindow; + int pro; + int cap; + int rsh; + int rlpb; + int cam; + int bro; + int ecm; + int receiveFlowControl; + u8 maxGroupAddrInHash; + u8 maxIndAddrInHash; + u8 prel; + u16 maxFrameLength; + u16 minFrameLength; + u16 maxD1Length; + u16 maxD2Length; + u16 vlantype; + u16 vlantci; + u32 ecamptr; + u32 eventRegMask; + u16 pausePeriod; + u16 extensionField; + u8 phy_address; + u32 board_flags; + u32 phy_interrupt; + u8 weightfactor[NUM_TX_QUEUES]; + u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES]; + u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX]; + u8 l3qt[UCC_GETH_IP_PRIORITY_MAX]; + u32 vtagtable[UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX]; + u8 iphoffset[TX_IP_OFFSET_ENTRY_MAX]; + u16 bdRingLenTx[NUM_TX_QUEUES]; + u16 bdRingLenRx[NUM_RX_QUEUES]; + enet_interface_e enet_interface; + ucc_geth_num_of_station_addresses_e numStationAddresses; + qe_fltr_largest_external_tbl_lookup_key_size_e + largestexternallookupkeysize; + ucc_geth_statistics_gathering_mode_e statisticsMode; + ucc_geth_vlan_operation_tagged_e vlanOperationTagged; + ucc_geth_vlan_operation_non_tagged_e vlanOperationNonTagged; + ucc_geth_qos_mode_e rxQoSMode; + ucc_geth_flow_control_mode_e aufc; + ucc_geth_maccfg2_pad_and_crc_mode_e padAndCrc; + ucc_geth_num_of_threads_e numThreadsTx; + ucc_geth_num_of_threads_e numThreadsRx; + qe_risc_allocation_e riscTx; + qe_risc_allocation_e riscRx; +} ucc_geth_info_t; + +/* structure representing UCC GETH */ +typedef struct ucc_geth_private { + ucc_geth_info_t *ug_info; + ucc_fast_private_t *uccf; + struct net_device *dev; + struct net_device_stats stats; /* linux network statistics */ + ucc_geth_t *ug_regs; + ucc_geth_init_pram_t *p_init_enet_param_shadow; + ucc_geth_exf_global_pram_t *p_exf_glbl_param; + u32 exf_glbl_param_offset; + ucc_geth_rx_global_pram_t *p_rx_glbl_pram; + u32 rx_glbl_pram_offset; + ucc_geth_tx_global_pram_t *p_tx_glbl_pram; + u32 tx_glbl_pram_offset; + ucc_geth_send_queue_mem_region_t *p_send_q_mem_reg; + u32 send_q_mem_reg_offset; + ucc_geth_thread_data_tx_t *p_thread_data_tx; + u32 thread_dat_tx_offset; + ucc_geth_thread_data_rx_t *p_thread_data_rx; + u32 thread_dat_rx_offset; + ucc_geth_scheduler_t *p_scheduler; + u32 scheduler_offset; + ucc_geth_tx_firmware_statistics_pram_t *p_tx_fw_statistics_pram; + u32 tx_fw_statistics_pram_offset; + ucc_geth_rx_firmware_statistics_pram_t *p_rx_fw_statistics_pram; + u32 rx_fw_statistics_pram_offset; + ucc_geth_rx_interrupt_coalescing_table_t *p_rx_irq_coalescing_tbl; + u32 rx_irq_coalescing_tbl_offset; + ucc_geth_rx_bd_queues_entry_t *p_rx_bd_qs_tbl; + u32 rx_bd_qs_tbl_offset; + u8 *p_tx_bd_ring[NUM_TX_QUEUES]; + u32 tx_bd_ring_offset[NUM_TX_QUEUES]; + u8 *p_rx_bd_ring[NUM_RX_QUEUES]; + u32 rx_bd_ring_offset[NUM_RX_QUEUES]; + u8 *confBd[NUM_TX_QUEUES]; + u8 *txBd[NUM_TX_QUEUES]; + u8 *rxBd[NUM_RX_QUEUES]; + int badFrame[NUM_RX_QUEUES]; + u16 cpucount[NUM_TX_QUEUES]; + volatile u16 *p_cpucount[NUM_TX_QUEUES]; + int indAddrRegUsed[NUM_OF_PADDRS]; + enet_addr_t paddr[NUM_OF_PADDRS]; + u8 numGroupAddrInHash; + u8 numIndAddrInHash; + u8 numIndAddrInReg; + int rx_extended_features; + int rx_non_dynamic_extended_features; + struct list_head conf_skbs; + struct list_head group_hash_q; + struct list_head ind_hash_q; + u32 saved_uccm; + spinlock_t lock; + /* pointers to arrays of skbuffs for tx and rx */ + struct sk_buff **tx_skbuff[NUM_TX_QUEUES]; + struct sk_buff **rx_skbuff[NUM_RX_QUEUES]; + /* indices pointing to the next free sbk in skb arrays */ + u16 skb_curtx[NUM_TX_QUEUES]; + u16 skb_currx[NUM_RX_QUEUES]; + /* index of the first skb which hasn't been transmitted yet. */ + u16 skb_dirtytx[NUM_TX_QUEUES]; + + struct work_struct tq; + struct timer_list phy_info_timer; + struct ugeth_mii_info *mii_info; + int oldspeed; + int oldduplex; + int oldlink; +} ucc_geth_private_t; + +#endif /* __UCC_GETH_H__ */ diff --git a/drivers/net/ucc_geth_phy.c b/drivers/net/ucc_geth_phy.c new file mode 100644 index 000000000..f91028c53 --- /dev/null +++ b/drivers/net/ucc_geth_phy.c @@ -0,0 +1,801 @@ +/* + * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved. + * + * Author: Shlomi Gridish <gridish@freescale.com> + * + * Description: + * UCC GETH Driver -- PHY handling + * + * Changelog: + * Jun 28, 2006 Li Yang <LeoLi@freescale.com> + * - Rearrange code and style fixes + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/string.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/interrupt.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/spinlock.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/version.h> +#include <linux/crc32.h> +#include <linux/mii.h> +#include <linux/ethtool.h> + +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/uaccess.h> + +#include "ucc_geth.h" +#include "ucc_geth_phy.h" +#include <platforms/83xx/mpc8360e_pb.h> + +#define ugphy_printk(level, format, arg...) \ + printk(level format "\n", ## arg) + +#define ugphy_dbg(format, arg...) \ + ugphy_printk(KERN_DEBUG, format , ## arg) +#define ugphy_err(format, arg...) \ + ugphy_printk(KERN_ERR, format , ## arg) +#define ugphy_info(format, arg...) \ + ugphy_printk(KERN_INFO, format , ## arg) +#define ugphy_warn(format, arg...) \ + ugphy_printk(KERN_WARNING, format , ## arg) + +#ifdef UGETH_VERBOSE_DEBUG +#define ugphy_vdbg ugphy_dbg +#else +#define ugphy_vdbg(fmt, args...) do { } while (0) +#endif /* UGETH_VERBOSE_DEBUG */ + +static void config_genmii_advert(struct ugeth_mii_info *mii_info); +static void genmii_setup_forced(struct ugeth_mii_info *mii_info); +static void genmii_restart_aneg(struct ugeth_mii_info *mii_info); +static int gbit_config_aneg(struct ugeth_mii_info *mii_info); +static int genmii_config_aneg(struct ugeth_mii_info *mii_info); +static int genmii_update_link(struct ugeth_mii_info *mii_info); +static int genmii_read_status(struct ugeth_mii_info *mii_info); +u16 phy_read(struct ugeth_mii_info *mii_info, u16 regnum); +void phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val); + +static u8 *bcsr_regs = NULL; + +/* Write value to the PHY for this device to the register at regnum, */ +/* waiting until the write is done before it returns. All PHY */ +/* configuration has to be done through the TSEC1 MIIM regs */ +void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value) +{ + ucc_geth_private_t *ugeth = netdev_priv(dev); + ucc_mii_mng_t *mii_regs; + enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum; + u32 tmp_reg; + + ugphy_vdbg("%s: IN", __FUNCTION__); + + spin_lock_irq(&ugeth->lock); + + mii_regs = ugeth->mii_info->mii_regs; + + /* Set this UCC to be the master of the MII managment */ + ucc_set_qe_mux_mii_mng(ugeth->ug_info->uf_info.ucc_num); + + /* Stop the MII management read cycle */ + out_be32(&mii_regs->miimcom, 0); + /* Setting up the MII Mangement Address Register */ + tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg; + out_be32(&mii_regs->miimadd, tmp_reg); + + /* Setting up the MII Mangement Control Register with the value */ + out_be32(&mii_regs->miimcon, (u32) value); + + /* Wait till MII management write is complete */ + while ((in_be32(&mii_regs->miimind)) & MIIMIND_BUSY) + cpu_relax(); + + spin_unlock_irq(&ugeth->lock); + + udelay(10000); +} + +/* Reads from register regnum in the PHY for device dev, */ +/* returning the value. Clears miimcom first. All PHY */ +/* configuration has to be done through the TSEC1 MIIM regs */ +int read_phy_reg(struct net_device *dev, int mii_id, int regnum) +{ + ucc_geth_private_t *ugeth = netdev_priv(dev); + ucc_mii_mng_t *mii_regs; + enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum; + u32 tmp_reg; + u16 value; + + ugphy_vdbg("%s: IN", __FUNCTION__); + + spin_lock_irq(&ugeth->lock); + + mii_regs = ugeth->mii_info->mii_regs; + + /* Setting up the MII Mangement Address Register */ + tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg; + out_be32(&mii_regs->miimadd, tmp_reg); + + /* Perform an MII management read cycle */ + out_be32(&mii_regs->miimcom, MIIMCOM_READ_CYCLE); + + /* Wait till MII management write is complete */ + while ((in_be32(&mii_regs->miimind)) & MIIMIND_BUSY) + cpu_relax(); + + udelay(10000); + + /* Read MII management status */ + value = (u16) in_be32(&mii_regs->miimstat); + out_be32(&mii_regs->miimcom, 0); + if (value == 0xffff) + ugphy_warn("read wrong value : mii_id %d,mii_reg %d, base %08x", + mii_id, mii_reg, (u32) & (mii_regs->miimcfg)); + + spin_unlock_irq(&ugeth->lock); + + return (value); +} + +void mii_clear_phy_interrupt(struct ugeth_mii_info *mii_info) +{ + ugphy_vdbg("%s: IN", __FUNCTION__); + + if (mii_info->phyinfo->ack_interrupt) + mii_info->phyinfo->ack_interrupt(mii_info); +} + +void mii_configure_phy_interrupt(struct ugeth_mii_info *mii_info, + u32 interrupts) +{ + ugphy_vdbg("%s: IN", __FUNCTION__); + + mii_info->interrupts = interrupts; + if (mii_info->phyinfo->config_intr) + mii_info->phyinfo->config_intr(mii_info); +} + +/* Writes MII_ADVERTISE with the appropriate values, after + * sanitizing advertise to make sure only supported features + * are advertised + */ +static void config_genmii_advert(struct ugeth_mii_info *mii_info) +{ + u32 advertise; + u16 adv; + + ugphy_vdbg("%s: IN", __FUNCTION__); + + /* Only allow advertising what this PHY supports */ + mii_info->advertising &= mii_info->phyinfo->features; + advertise = mii_info->advertising; + + /* Setup standard advertisement */ + adv = phy_read(mii_info, 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(mii_info, MII_ADVERTISE, adv); +} + +static void genmii_setup_forced(struct ugeth_mii_info *mii_info) +{ + u16 ctrl; + u32 features = mii_info->phyinfo->features; + + ugphy_vdbg("%s: IN", __FUNCTION__); + + ctrl = phy_read(mii_info, MII_BMCR); + + ctrl &= + ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE); + ctrl |= BMCR_RESET; + + switch (mii_info->speed) { + case SPEED_1000: + if (features & (SUPPORTED_1000baseT_Half + | SUPPORTED_1000baseT_Full)) { + ctrl |= BMCR_SPEED1000; + break; + } + mii_info->speed = SPEED_100; + case SPEED_100: + if (features & (SUPPORTED_100baseT_Half + | SUPPORTED_100baseT_Full)) { + ctrl |= BMCR_SPEED100; + break; + } + mii_info->speed = SPEED_10; + case SPEED_10: + if (features & (SUPPORTED_10baseT_Half + | SUPPORTED_10baseT_Full)) + break; + default: /* Unsupported speed! */ + ugphy_err("%s: Bad speed!", mii_info->dev->name); + break; + } + + phy_write(mii_info, MII_BMCR, ctrl); +} + +/* Enable and Restart Autonegotiation */ +static void genmii_restart_aneg(struct ugeth_mii_info *mii_info) +{ + u16 ctl; + + ugphy_vdbg("%s: IN", __FUNCTION__); + + ctl = phy_read(mii_info, MII_BMCR); + ctl |= (BMCR_ANENABLE | BMCR_ANRESTART); + phy_write(mii_info, MII_BMCR, ctl); +} + +static int gbit_config_aneg(struct ugeth_mii_info *mii_info) +{ + u16 adv; + u32 advertise; + + ugphy_vdbg("%s: IN", __FUNCTION__); + + if (mii_info->autoneg) { + /* Configure the ADVERTISE register */ + config_genmii_advert(mii_info); + advertise = mii_info->advertising; + + adv = phy_read(mii_info, 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(mii_info, MII_1000BASETCONTROL, adv); + + /* Start/Restart aneg */ + genmii_restart_aneg(mii_info); + } else + genmii_setup_forced(mii_info); + + return 0; +} + +static int genmii_config_aneg(struct ugeth_mii_info *mii_info) +{ + ugphy_vdbg("%s: IN", __FUNCTION__); + + if (mii_info->autoneg) { + config_genmii_advert(mii_info); + genmii_restart_aneg(mii_info); + } else + genmii_setup_forced(mii_info); + + return 0; +} + +static int genmii_update_link(struct ugeth_mii_info *mii_info) +{ + u16 status; + + ugphy_vdbg("%s: IN", __FUNCTION__); + + /* Do a fake read */ + phy_read(mii_info, MII_BMSR); + + /* Read link and autonegotiation status */ + status = phy_read(mii_info, MII_BMSR); + if ((status & BMSR_LSTATUS) == 0) + mii_info->link = 0; + else + mii_info->link = 1; + + /* If we are autonegotiating, and not done, + * return an error */ + if (mii_info->autoneg && !(status & BMSR_ANEGCOMPLETE)) + return -EAGAIN; + + return 0; +} + +static int genmii_read_status(struct ugeth_mii_info *mii_info) +{ + u16 status; + int err; + + ugphy_vdbg("%s: IN", __FUNCTION__); + + /* Update the link, but return if there + * was an error */ + err = genmii_update_link(mii_info); + if (err) + return err; + + if (mii_info->autoneg) { + status = phy_read(mii_info, MII_LPA); + + if (status & (LPA_10FULL | LPA_100FULL)) + mii_info->duplex = DUPLEX_FULL; + else + mii_info->duplex = DUPLEX_HALF; + if (status & (LPA_100FULL | LPA_100HALF)) + mii_info->speed = SPEED_100; + else + mii_info->speed = SPEED_10; + mii_info->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_init(struct ugeth_mii_info *mii_info) +{ + ugphy_vdbg("%s: IN", __FUNCTION__); + + phy_write(mii_info, 0x14, 0x0cd2); + phy_write(mii_info, MII_BMCR, + phy_read(mii_info, MII_BMCR) | BMCR_RESET); + msleep(4000); + + return 0; +} + +static int marvell_config_aneg(struct ugeth_mii_info *mii_info) +{ + ugphy_vdbg("%s: IN", __FUNCTION__); + + /* The Marvell PHY has an errata which requires + * that certain registers get written in order + * to restart autonegotiation */ + phy_write(mii_info, MII_BMCR, BMCR_RESET); + + phy_write(mii_info, 0x1d, 0x1f); + phy_write(mii_info, 0x1e, 0x200c); + phy_write(mii_info, 0x1d, 0x5); + phy_write(mii_info, 0x1e, 0); + phy_write(mii_info, 0x1e, 0x100); + + gbit_config_aneg(mii_info); + + return 0; +} + +static int marvell_read_status(struct ugeth_mii_info *mii_info) +{ + u16 status; + int err; + + ugphy_vdbg("%s: IN", __FUNCTION__); + + /* Update the link, but return if there + * was an error */ + err = genmii_update_link(mii_info); + if (err) + return err; + + /* If the link is up, read the speed and duplex */ + /* If we aren't autonegotiating, assume speeds + * are as set */ + if (mii_info->autoneg && mii_info->link) { + int speed; + status = phy_read(mii_info, MII_M1011_PHY_SPEC_STATUS); + + /* Get the duplexity */ + if (status & MII_M1011_PHY_SPEC_STATUS_FULLDUPLEX) + mii_info->duplex = DUPLEX_FULL; + else + mii_info->duplex = DUPLEX_HALF; + + /* Get the speed */ + speed = status & MII_M1011_PHY_SPEC_STATUS_SPD_MASK; + switch (speed) { + case MII_M1011_PHY_SPEC_STATUS_1000: + mii_info->speed = SPEED_1000; + break; + case MII_M1011_PHY_SPEC_STATUS_100: + mii_info->speed = SPEED_100; + break; + default: + mii_info->speed = SPEED_10; + break; + } + mii_info->pause = 0; + } + + return 0; +} + +static int marvell_ack_interrupt(struct ugeth_mii_info *mii_info) +{ + ugphy_vdbg("%s: IN", __FUNCTION__); + + /* Clear the interrupts by reading the reg */ + phy_read(mii_info, MII_M1011_IEVENT); + + return 0; +} + +static int marvell_config_intr(struct ugeth_mii_info *mii_info) +{ + ugphy_vdbg("%s: IN", __FUNCTION__); + + if (mii_info->interrupts == MII_INTERRUPT_ENABLED) + phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_INIT); + else + phy_write(mii_info, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR); + + return 0; +} + +static int cis820x_init(struct ugeth_mii_info *mii_info) +{ + ugphy_vdbg("%s: IN", __FUNCTION__); + + phy_write(mii_info, MII_CIS8201_AUX_CONSTAT, + MII_CIS8201_AUXCONSTAT_INIT); + phy_write(mii_info, MII_CIS8201_EXT_CON1, MII_CIS8201_EXTCON1_INIT); + + return 0; +} + +static int cis820x_read_status(struct ugeth_mii_info *mii_info) +{ + u16 status; + int err; + + ugphy_vdbg("%s: IN", __FUNCTION__); + + /* Update the link, but return if there + * was an error */ + err = genmii_update_link(mii_info); + if (err) + return err; + + /* If the link is up, read the speed and duplex */ + /* If we aren't autonegotiating, assume speeds + * are as set */ + if (mii_info->autoneg && mii_info->link) { + int speed; + + status = phy_read(mii_info, MII_CIS8201_AUX_CONSTAT); + if (status & MII_CIS8201_AUXCONSTAT_DUPLEX) + mii_info->duplex = DUPLEX_FULL; + else + mii_info->duplex = DUPLEX_HALF; + + speed = status & MII_CIS8201_AUXCONSTAT_SPEED; + + switch (speed) { + case MII_CIS8201_AUXCONSTAT_GBIT: + mii_info->speed = SPEED_1000; + break; + case MII_CIS8201_AUXCONSTAT_100: + mii_info->speed = SPEED_100; + break; + default: + mii_info->speed = SPEED_10; + break; + } + } + + return 0; +} + +static int cis820x_ack_interrupt(struct ugeth_mii_info *mii_info) +{ + ugphy_vdbg("%s: IN", __FUNCTION__); + + phy_read(mii_info, MII_CIS8201_ISTAT); + + return 0; +} + +static int cis820x_config_intr(struct ugeth_mii_info *mii_info) +{ + ugphy_vdbg("%s: IN", __FUNCTION__); + + if (mii_info->interrupts == MII_INTERRUPT_ENABLED) + phy_write(mii_info, MII_CIS8201_IMASK, MII_CIS8201_IMASK_MASK); + else + phy_write(mii_info, MII_CIS8201_IMASK, 0); + + return 0; +} + +#define DM9161_DELAY 10 + +static int dm9161_read_status(struct ugeth_mii_info *mii_info) +{ + u16 status; + int err; + + ugphy_vdbg("%s: IN", __FUNCTION__); + + /* Update the link, but return if there + * was an error */ + err = genmii_update_link(mii_info); + if (err) + return err; + + /* If the link is up, read the speed and duplex */ + /* If we aren't autonegotiating, assume speeds + * are as set */ + if (mii_info->autoneg && mii_info->link) { + status = phy_read(mii_info, MII_DM9161_SCSR); + if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_100H)) + mii_info->speed = SPEED_100; + else + mii_info->speed = SPEED_10; + + if (status & (MII_DM9161_SCSR_100F | MII_DM9161_SCSR_10F)) + mii_info->duplex = DUPLEX_FULL; + else + mii_info->duplex = DUPLEX_HALF; + } + + return 0; +} + +static int dm9161_config_aneg(struct ugeth_mii_info *mii_info) +{ + struct dm9161_private *priv = mii_info->priv; + + ugphy_vdbg("%s: IN", __FUNCTION__); + + if (0 == priv->resetdone) + return -EAGAIN; + + return 0; +} + +static void dm9161_timer(unsigned long data) +{ + struct ugeth_mii_info *mii_info = (struct ugeth_mii_info *)data; + struct dm9161_private *priv = mii_info->priv; + u16 status = phy_read(mii_info, MII_BMSR); + + ugphy_vdbg("%s: IN", __FUNCTION__); + + if (status & BMSR_ANEGCOMPLETE) { + priv->resetdone = 1; + } else + mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ); +} + +static int dm9161_init(struct ugeth_mii_info *mii_info) +{ + struct dm9161_private *priv; + + ugphy_vdbg("%s: IN", __FUNCTION__); + + /* Allocate the private data structure */ + priv = kmalloc(sizeof(struct dm9161_private), GFP_KERNEL); + + if (NULL == priv) + return -ENOMEM; + + mii_info->priv = priv; + + /* Reset is not done yet */ + priv->resetdone = 0; + + phy_write(mii_info, MII_BMCR, + phy_read(mii_info, MII_BMCR) | BMCR_RESET); + + phy_write(mii_info, MII_BMCR, + phy_read(mii_info, MII_BMCR) & ~BMCR_ISOLATE); + + config_genmii_advert(mii_info); + /* Start/Restart aneg */ + genmii_config_aneg(mii_info); + + /* Start a timer for DM9161_DELAY seconds to wait + * for the PHY to be ready */ + init_timer(&priv->timer); + priv->timer.function = &dm9161_timer; + priv->timer.data = (unsigned long)mii_info; + mod_timer(&priv->timer, jiffies + DM9161_DELAY * HZ); + + return 0; +} + +static void dm9161_close(struct ugeth_mii_info *mii_info) +{ + struct dm9161_private *priv = mii_info->priv; + + ugphy_vdbg("%s: IN", __FUNCTION__); + + del_timer_sync(&priv->timer); + kfree(priv); +} + +static int dm9161_ack_interrupt(struct ugeth_mii_info *mii_info) +{ +/* FIXME: This lines are for BUG fixing in the mpc8325. +Remove this from here when it's fixed */ + if (bcsr_regs == NULL) + bcsr_regs = (u8 *) ioremap(BCSR_PHYS_ADDR, BCSR_SIZE); + bcsr_regs[14] |= 0x40; + ugphy_vdbg("%s: IN", __FUNCTION__); + + /* Clear the interrupts by reading the reg */ + phy_read(mii_info, MII_DM9161_INTR); + + + return 0; +} + +static int dm9161_config_intr(struct ugeth_mii_info *mii_info) +{ +/* FIXME: This lines are for BUG fixing in the mpc8325. +Remove this from here when it's fixed */ + if (bcsr_regs == NULL) { + bcsr_regs = (u8 *) ioremap(BCSR_PHYS_ADDR, BCSR_SIZE); + bcsr_regs[14] &= ~0x40; + } + ugphy_vdbg("%s: IN", __FUNCTION__); + + if (mii_info->interrupts == MII_INTERRUPT_ENABLED) + phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_INIT); + else + phy_write(mii_info, MII_DM9161_INTR, MII_DM9161_INTR_STOP); + + return 0; +} + +/* Cicada 820x */ +static struct phy_info phy_info_cis820x = { + .phy_id = 0x000fc440, + .name = "Cicada Cis8204", + .phy_id_mask = 0x000fffc0, + .features = MII_GBIT_FEATURES, + .init = &cis820x_init, + .config_aneg = &gbit_config_aneg, + .read_status = &cis820x_read_status, + .ack_interrupt = &cis820x_ack_interrupt, + .config_intr = &cis820x_config_intr, +}; + +static struct phy_info phy_info_dm9161 = { + .phy_id = 0x0181b880, + .phy_id_mask = 0x0ffffff0, + .name = "Davicom DM9161E", + .init = dm9161_init, + .config_aneg = dm9161_config_aneg, + .read_status = dm9161_read_status, + .close = dm9161_close, +}; + +static struct phy_info phy_info_dm9161a = { + .phy_id = 0x0181b8a0, + .phy_id_mask = 0x0ffffff0, + .name = "Davicom DM9161A", + .features = MII_BASIC_FEATURES, + .init = dm9161_init, + .config_aneg = dm9161_config_aneg, + .read_status = dm9161_read_status, + .ack_interrupt = dm9161_ack_interrupt, + .config_intr = dm9161_config_intr, + .close = dm9161_close, +}; + +static struct phy_info phy_info_marvell = { + .phy_id = 0x01410c00, + .phy_id_mask = 0xffffff00, + .name = "Marvell 88E11x1", + .features = MII_GBIT_FEATURES, + .init = &marvell_init, + .config_aneg = &marvell_config_aneg, + .read_status = &marvell_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, +}; + +static struct phy_info phy_info_genmii = { + .phy_id = 0x00000000, + .phy_id_mask = 0x00000000, + .name = "Generic MII", + .features = MII_BASIC_FEATURES, + .config_aneg = genmii_config_aneg, + .read_status = genmii_read_status, +}; + +static struct phy_info *phy_info[] = { + &phy_info_cis820x, + &phy_info_marvell, + &phy_info_dm9161, + &phy_info_dm9161a, + &phy_info_genmii, + NULL +}; + +u16 phy_read(struct ugeth_mii_info *mii_info, u16 regnum) +{ + u16 retval; + unsigned long flags; + + ugphy_vdbg("%s: IN", __FUNCTION__); + + spin_lock_irqsave(&mii_info->mdio_lock, flags); + retval = mii_info->mdio_read(mii_info->dev, mii_info->mii_id, regnum); + spin_unlock_irqrestore(&mii_info->mdio_lock, flags); + + return retval; +} + +void phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val) +{ + unsigned long flags; + + ugphy_vdbg("%s: IN", __FUNCTION__); + + spin_lock_irqsave(&mii_info->mdio_lock, flags); + mii_info->mdio_write(mii_info->dev, mii_info->mii_id, regnum, val); + spin_unlock_irqrestore(&mii_info->mdio_lock, flags); +} + +/* Use the PHY ID registers to determine what type of PHY is attached + * to device dev. return a struct phy_info structure describing that PHY + */ +struct phy_info *get_phy_info(struct ugeth_mii_info *mii_info) +{ + u16 phy_reg; + u32 phy_ID; + int i; + struct phy_info *theInfo = NULL; + struct net_device *dev = mii_info->dev; + + ugphy_vdbg("%s: IN", __FUNCTION__); + + /* Grab the bits from PHYIR1, and put them in the upper half */ + phy_reg = phy_read(mii_info, MII_PHYSID1); + phy_ID = (phy_reg & 0xffff) << 16; + + /* Grab the bits from PHYIR2, and put them in the lower half */ + phy_reg = phy_read(mii_info, MII_PHYSID2); + phy_ID |= (phy_reg & 0xffff); + + /* loop through all the known PHY types, and find one that */ + /* matches the ID we read from the PHY. */ + for (i = 0; phy_info[i]; i++) + if (phy_info[i]->phy_id == (phy_ID & phy_info[i]->phy_id_mask)){ + theInfo = phy_info[i]; + break; + } + + /* This shouldn't happen, as we have generic PHY support */ + if (theInfo == NULL) { + ugphy_info("%s: PHY id %x is not supported!", dev->name, + phy_ID); + return NULL; + } else { + ugphy_info("%s: PHY is %s (%x)", dev->name, theInfo->name, + phy_ID); + } + + return theInfo; +} diff --git a/drivers/net/ucc_geth_phy.h b/drivers/net/ucc_geth_phy.h new file mode 100644 index 000000000..2f98b8f1b --- /dev/null +++ b/drivers/net/ucc_geth_phy.h @@ -0,0 +1,217 @@ +/* + * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved. + * + * Author: Shlomi Gridish <gridish@freescale.com> + * + * Description: + * UCC GETH Driver -- PHY handling + * + * Changelog: + * Jun 28, 2006 Li Yang <LeoLi@freescale.com> + * - Rearrange code and style fixes + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#ifndef __UCC_GETH_PHY_H__ +#define __UCC_GETH_PHY_H__ + +#define MII_end ((u32)-2) +#define MII_read ((u32)-1) + +#define MIIMIND_BUSY 0x00000001 +#define MIIMIND_NOTVALID 0x00000004 + +#define UGETH_AN_TIMEOUT 2000 + +/* 1000BT control (Marvell & BCM54xx at least) */ +#define MII_1000BASETCONTROL 0x09 +#define MII_1000BASETCONTROL_FULLDUPLEXCAP 0x0200 +#define MII_1000BASETCONTROL_HALFDUPLEXCAP 0x0100 + +/* Cicada Extended Control Register 1 */ +#define MII_CIS8201_EXT_CON1 0x17 +#define MII_CIS8201_EXTCON1_INIT 0x0000 + +/* Cicada Interrupt Mask Register */ +#define MII_CIS8201_IMASK 0x19 +#define MII_CIS8201_IMASK_IEN 0x8000 +#define MII_CIS8201_IMASK_SPEED 0x4000 +#define MII_CIS8201_IMASK_LINK 0x2000 +#define MII_CIS8201_IMASK_DUPLEX 0x1000 +#define MII_CIS8201_IMASK_MASK 0xf000 + +/* Cicada Interrupt Status Register */ +#define MII_CIS8201_ISTAT 0x1a +#define MII_CIS8201_ISTAT_STATUS 0x8000 +#define MII_CIS8201_ISTAT_SPEED 0x4000 +#define MII_CIS8201_ISTAT_LINK 0x2000 +#define MII_CIS8201_ISTAT_DUPLEX 0x1000 + +/* Cicada Auxiliary Control/Status Register */ +#define MII_CIS8201_AUX_CONSTAT 0x1c +#define MII_CIS8201_AUXCONSTAT_INIT 0x0004 +#define MII_CIS8201_AUXCONSTAT_DUPLEX 0x0020 +#define MII_CIS8201_AUXCONSTAT_SPEED 0x0018 +#define MII_CIS8201_AUXCONSTAT_GBIT 0x0010 +#define MII_CIS8201_AUXCONSTAT_100 0x0008 + +/* 88E1011 PHY Status Register */ +#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 +#define MII_M1011_PHY_SPEC_STATUS_LINK 0x0400 + +#define MII_M1011_IEVENT 0x13 +#define MII_M1011_IEVENT_CLEAR 0x0000 + +#define MII_M1011_IMASK 0x12 +#define MII_M1011_IMASK_INIT 0x6400 +#define MII_M1011_IMASK_CLEAR 0x0000 + +#define MII_DM9161_SCR 0x10 +#define MII_DM9161_SCR_INIT 0x0610 + +/* DM9161 Specified Configuration and Status Register */ +#define MII_DM9161_SCSR 0x11 +#define MII_DM9161_SCSR_100F 0x8000 +#define MII_DM9161_SCSR_100H 0x4000 +#define MII_DM9161_SCSR_10F 0x2000 +#define MII_DM9161_SCSR_10H 0x1000 + +/* DM9161 Interrupt Register */ +#define MII_DM9161_INTR 0x15 +#define MII_DM9161_INTR_PEND 0x8000 +#define MII_DM9161_INTR_DPLX_MASK 0x0800 +#define MII_DM9161_INTR_SPD_MASK 0x0400 +#define MII_DM9161_INTR_LINK_MASK 0x0200 +#define MII_DM9161_INTR_MASK 0x0100 +#define MII_DM9161_INTR_DPLX_CHANGE 0x0010 +#define MII_DM9161_INTR_SPD_CHANGE 0x0008 +#define MII_DM9161_INTR_LINK_CHANGE 0x0004 +#define MII_DM9161_INTR_INIT 0x0000 +#define MII_DM9161_INTR_STOP \ +(MII_DM9161_INTR_DPLX_MASK | MII_DM9161_INTR_SPD_MASK \ + | MII_DM9161_INTR_LINK_MASK | MII_DM9161_INTR_MASK) + +/* DM9161 10BT Configuration/Status */ +#define MII_DM9161_10BTCSR 0x12 +#define MII_DM9161_10BTCSR_INIT 0x7800 + +#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) + +#define MII_READ_COMMAND 0x00000001 + +#define MII_INTERRUPT_DISABLED 0x0 +#define MII_INTERRUPT_ENABLED 0x1 +/* Taken from mii_if_info and sungem_phy.h */ +struct ugeth_mii_info { + /* Information about the PHY type */ + /* And management functions */ + struct phy_info *phyinfo; + + ucc_mii_mng_t *mii_regs; + + /* forced speed & duplex (no autoneg) + * partner speed & duplex & pause (autoneg) + */ + int speed; + int duplex; + int pause; + + /* The most recently read link state */ + int link; + + /* Enabled Interrupts */ + u32 interrupts; + + u32 advertising; + int autoneg; + int mii_id; + + /* private data pointer */ + /* For use by PHYs to maintain extra state */ + void *priv; + + /* Provided by host chip */ + struct net_device *dev; + + /* A lock to ensure that only one thing can read/write + * the MDIO bus at a time */ + spinlock_t mdio_lock; + + /* Provided by ethernet driver */ + 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); +}; + +/* struct phy_info: a structure which defines attributes for a PHY + * + * id will contain a number which represents the PHY. During + * startup, the driver will poll the PHY to find out what its + * UID--as defined by registers 2 and 3--is. The 32-bit result + * gotten from the PHY will be ANDed with phy_id_mask to + * discard any bits which may change based on revision numbers + * unimportant to functionality + * + * There are 6 commands which take a ugeth_mii_info structure. + * Each PHY must declare config_aneg, and read_status. + */ +struct phy_info { + u32 phy_id; + char *name; + unsigned int phy_id_mask; + u32 features; + + /* Called to initialize the PHY */ + int (*init) (struct ugeth_mii_info * mii_info); + + /* Called to suspend the PHY for power */ + int (*suspend) (struct ugeth_mii_info * mii_info); + + /* Reconfigures autonegotiation (or disables it) */ + int (*config_aneg) (struct ugeth_mii_info * mii_info); + + /* Determines the negotiated speed and duplex */ + int (*read_status) (struct ugeth_mii_info * mii_info); + + /* Clears any pending interrupts */ + int (*ack_interrupt) (struct ugeth_mii_info * mii_info); + + /* Enables or disables interrupts */ + int (*config_intr) (struct ugeth_mii_info * mii_info); + + /* Clears up any memory if needed */ + void (*close) (struct ugeth_mii_info * mii_info); +}; + +struct phy_info *get_phy_info(struct ugeth_mii_info *mii_info); +void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value); +int read_phy_reg(struct net_device *dev, int mii_id, int regnum); +void mii_clear_phy_interrupt(struct ugeth_mii_info *mii_info); +void mii_configure_phy_interrupt(struct ugeth_mii_info *mii_info, + u32 interrupts); + +struct dm9161_private { + struct timer_list timer; + int resetdone; +}; + +#endif /* __UCC_GETH_PHY_H__ */ diff --git a/drivers/net/wireless/orinoco_pci.h b/drivers/net/wireless/orinoco_pci.h new file mode 100644 index 000000000..be1abea4b --- /dev/null +++ b/drivers/net/wireless/orinoco_pci.h @@ -0,0 +1,104 @@ +/* orinoco_pci.h + * + * Common code for all Orinoco drivers for PCI devices, including + * both native PCI and PCMCIA-to-PCI bridges. + * + * Copyright (C) 2005, Pavel Roskin. + * See orinoco.c for license. + */ + +#ifndef _ORINOCO_PCI_H +#define _ORINOCO_PCI_H + +#include <linux/netdevice.h> + +/* Driver specific data */ +struct orinoco_pci_card { + void __iomem *bridge_io; + void __iomem *attr_io; +}; + +#ifdef CONFIG_PM +static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct orinoco_private *priv = netdev_priv(dev); + unsigned long flags; + int err; + + err = orinoco_lock(priv, &flags); + if (err) { + printk(KERN_ERR "%s: cannot lock hardware for suspend\n", + dev->name); + return err; + } + + err = __orinoco_down(dev); + if (err) + printk(KERN_WARNING "%s: error %d bringing interface down " + "for suspend\n", dev->name, err); + + netif_device_detach(dev); + + priv->hw_unavailable++; + + orinoco_unlock(priv, &flags); + + free_irq(pdev->irq, dev); + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); + + return 0; +} + +static int orinoco_pci_resume(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct orinoco_private *priv = netdev_priv(dev); + unsigned long flags; + int err; + + pci_set_power_state(pdev, 0); + pci_enable_device(pdev); + pci_restore_state(pdev); + + err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED, + dev->name, dev); + if (err) { + printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n", + dev->name); + pci_disable_device(pdev); + return -EBUSY; + } + + err = orinoco_reinit_firmware(dev); + if (err) { + printk(KERN_ERR "%s: error %d re-initializing firmware " + "on resume\n", dev->name, err); + return err; + } + + spin_lock_irqsave(&priv->lock, flags); + + netif_device_attach(dev); + + priv->hw_unavailable--; + + if (priv->open && (! priv->hw_unavailable)) { + err = __orinoco_up(dev); + if (err) + printk(KERN_ERR "%s: Error %d restarting card on resume\n", + dev->name, err); + } + + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} +#else +#define orinoco_pci_suspend NULL +#define orinoco_pci_resume NULL +#endif + +#endif /* _ORINOCO_PCI_H */ diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c new file mode 100644 index 000000000..c52e9bcf8 --- /dev/null +++ b/drivers/net/wireless/zd1201.c @@ -0,0 +1,1931 @@ +/* + * Driver for ZyDAS zd1201 based wireless USB devices. + * + * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * Parts of this driver have been derived from a wlan-ng version + * modified by ZyDAS. They also made documentation available, thanks! + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + */ + +#include <linux/module.h> +#include <linux/usb.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/wireless.h> +#include <net/iw_handler.h> +#include <linux/string.h> +#include <linux/if_arp.h> +#include <linux/firmware.h> +#include <net/ieee80211.h> +#include "zd1201.h" + +static struct usb_device_id zd1201_table[] = { + {USB_DEVICE(0x0586, 0x3400)}, /* Peabird Wireless USB Adapter */ + {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */ + {USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb adapter */ + {USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb adapter */ + {USB_DEVICE(0x1044, 0x8005)}, /* GIGABYTE GN-WLBZ201 usb adapter */ + {} +}; + +static int ap; /* Are we an AP or a normal station? */ + +#define ZD1201_VERSION "0.15" + +MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>"); +MODULE_DESCRIPTION("Driver for ZyDAS ZD1201 based USB Wireless adapters"); +MODULE_VERSION(ZD1201_VERSION); +MODULE_LICENSE("GPL"); +module_param(ap, int, 0); +MODULE_PARM_DESC(ap, "If non-zero Access Point firmware will be loaded"); +MODULE_DEVICE_TABLE(usb, zd1201_table); + + +static int zd1201_fw_upload(struct usb_device *dev, int apfw) +{ + const struct firmware *fw_entry; + char *data; + unsigned long len; + int err; + unsigned char ret; + char *buf; + char *fwfile; + + if (apfw) + fwfile = "zd1201-ap.fw"; + else + fwfile = "zd1201.fw"; + + err = request_firmware(&fw_entry, fwfile, &dev->dev); + if (err) { + dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile); + dev_err(&dev->dev, "Make sure the hotplug firmware loader is installed.\n"); + dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info.\n"); + return err; + } + + data = fw_entry->data; + len = fw_entry->size; + + buf = kmalloc(1024, GFP_ATOMIC); + if (!buf) + goto exit; + + while (len > 0) { + int translen = (len > 1024) ? 1024 : len; + memcpy(buf, data, translen); + + err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0, + USB_DIR_OUT | 0x40, 0, 0, buf, translen, + ZD1201_FW_TIMEOUT); + if (err < 0) + goto exit; + + len -= translen; + data += translen; + } + + err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x2, + USB_DIR_OUT | 0x40, 0, 0, NULL, 0, ZD1201_FW_TIMEOUT); + if (err < 0) + goto exit; + + err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4, + USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT); + if (err < 0) + goto exit; + + if (ret & 0x80) { + err = -EIO; + goto exit; + } + + err = 0; +exit: + kfree(buf); + release_firmware(fw_entry); + return err; +} + +static void zd1201_usbfree(struct urb *urb, struct pt_regs *regs) +{ + struct zd1201 *zd = urb->context; + + switch(urb->status) { + case -EILSEQ: + case -ENODEV: + case -ETIMEDOUT: + case -ENOENT: + case -EPIPE: + case -EOVERFLOW: + case -ESHUTDOWN: + dev_warn(&zd->usb->dev, "%s: urb failed: %d\n", + zd->dev->name, urb->status); + } + + kfree(urb->transfer_buffer); + usb_free_urb(urb); + return; +} + +/* cmdreq message: + u32 type + u16 cmd + u16 parm0 + u16 parm1 + u16 parm2 + u8 pad[4] + + total: 4 + 2 + 2 + 2 + 2 + 4 = 16 +*/ +static int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0, + int parm1, int parm2) +{ + unsigned char *command; + int ret; + struct urb *urb; + + command = kmalloc(16, GFP_ATOMIC); + if (!command) + return -ENOMEM; + + *((__le32*)command) = cpu_to_le32(ZD1201_USB_CMDREQ); + *((__le16*)&command[4]) = cpu_to_le16(cmd); + *((__le16*)&command[6]) = cpu_to_le16(parm0); + *((__le16*)&command[8]) = cpu_to_le16(parm1); + *((__le16*)&command[10])= cpu_to_le16(parm2); + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + kfree(command); + return -ENOMEM; + } + usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2), + command, 16, zd1201_usbfree, zd); + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) { + kfree(command); + usb_free_urb(urb); + } + + return ret; +} + +/* Callback after sending out a packet */ +static void zd1201_usbtx(struct urb *urb, struct pt_regs *regs) +{ + struct zd1201 *zd = urb->context; + netif_wake_queue(zd->dev); + return; +} + +/* Incoming data */ +static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs) +{ + struct zd1201 *zd = urb->context; + int free = 0; + unsigned char *data = urb->transfer_buffer; + struct sk_buff *skb; + unsigned char type; + + if (!zd) { + free = 1; + goto exit; + } + + switch(urb->status) { + case -EILSEQ: + case -ENODEV: + case -ETIMEDOUT: + case -ENOENT: + case -EPIPE: + case -EOVERFLOW: + case -ESHUTDOWN: + dev_warn(&zd->usb->dev, "%s: rx urb failed: %d\n", + zd->dev->name, urb->status); + free = 1; + goto exit; + } + + if (urb->status != 0 || urb->actual_length == 0) + goto resubmit; + + type = data[0]; + if (type == ZD1201_PACKET_EVENTSTAT || type == ZD1201_PACKET_RESOURCE) { + memcpy(zd->rxdata, data, urb->actual_length); + zd->rxlen = urb->actual_length; + zd->rxdatas = 1; + wake_up(&zd->rxdataq); + } + /* Info frame */ + if (type == ZD1201_PACKET_INQUIRE) { + int i = 0; + unsigned short infotype, framelen, copylen; + framelen = le16_to_cpu(*(__le16*)&data[4]); + infotype = le16_to_cpu(*(__le16*)&data[6]); + + if (infotype == ZD1201_INF_LINKSTATUS) { + short linkstatus; + + linkstatus = le16_to_cpu(*(__le16*)&data[8]); + switch(linkstatus) { + case 1: + netif_carrier_on(zd->dev); + break; + case 2: + netif_carrier_off(zd->dev); + break; + case 3: + netif_carrier_off(zd->dev); + break; + case 4: + netif_carrier_on(zd->dev); + break; + default: + netif_carrier_off(zd->dev); + } + goto resubmit; + } + if (infotype == ZD1201_INF_ASSOCSTATUS) { + short status = le16_to_cpu(*(__le16*)(data+8)); + int event; + union iwreq_data wrqu; + + switch (status) { + case ZD1201_ASSOCSTATUS_STAASSOC: + case ZD1201_ASSOCSTATUS_REASSOC: + event = IWEVREGISTERED; + break; + case ZD1201_ASSOCSTATUS_DISASSOC: + case ZD1201_ASSOCSTATUS_ASSOCFAIL: + case ZD1201_ASSOCSTATUS_AUTHFAIL: + default: + event = IWEVEXPIRED; + } + memcpy(wrqu.addr.sa_data, data+10, ETH_ALEN); + wrqu.addr.sa_family = ARPHRD_ETHER; + + /* Send event to user space */ + wireless_send_event(zd->dev, event, &wrqu, NULL); + + goto resubmit; + } + if (infotype == ZD1201_INF_AUTHREQ) { + union iwreq_data wrqu; + + memcpy(wrqu.addr.sa_data, data+8, ETH_ALEN); + wrqu.addr.sa_family = ARPHRD_ETHER; + /* There isn't a event that trully fits this request. + We assume that userspace will be smart enough to + see a new station being expired and sends back a + authstation ioctl to authorize it. */ + wireless_send_event(zd->dev, IWEVEXPIRED, &wrqu, NULL); + goto resubmit; + } + /* Other infotypes are handled outside this handler */ + zd->rxlen = 0; + while (i < urb->actual_length) { + copylen = le16_to_cpu(*(__le16*)&data[i+2]); + /* Sanity check, sometimes we get junk */ + if (copylen+zd->rxlen > sizeof(zd->rxdata)) + break; + memcpy(zd->rxdata+zd->rxlen, data+i+4, copylen); + zd->rxlen += copylen; + i += 64; + } + if (i >= urb->actual_length) { + zd->rxdatas = 1; + wake_up(&zd->rxdataq); + } + goto resubmit; + } + /* Actual data */ + if (data[urb->actual_length-1] == ZD1201_PACKET_RXDATA) { + int datalen = urb->actual_length-1; + unsigned short len, fc, seq; + struct hlist_node *node; + + len = ntohs(*(__be16 *)&data[datalen-2]); + if (len>datalen) + len=datalen; + fc = le16_to_cpu(*(__le16 *)&data[datalen-16]); + seq = le16_to_cpu(*(__le16 *)&data[datalen-24]); + + if (zd->monitor) { + if (datalen < 24) + goto resubmit; + if (!(skb = dev_alloc_skb(datalen+24))) + goto resubmit; + + memcpy(skb_put(skb, 2), &data[datalen-16], 2); + memcpy(skb_put(skb, 2), &data[datalen-2], 2); + memcpy(skb_put(skb, 6), &data[datalen-14], 6); + memcpy(skb_put(skb, 6), &data[datalen-22], 6); + memcpy(skb_put(skb, 6), &data[datalen-8], 6); + memcpy(skb_put(skb, 2), &data[datalen-24], 2); + memcpy(skb_put(skb, len), data, len); + skb->dev = zd->dev; + skb->dev->last_rx = jiffies; + skb->protocol = eth_type_trans(skb, zd->dev); + zd->stats.rx_packets++; + zd->stats.rx_bytes += skb->len; + netif_rx(skb); + goto resubmit; + } + + if ((seq & IEEE80211_SCTL_FRAG) || + (fc & IEEE80211_FCTL_MOREFRAGS)) { + struct zd1201_frag *frag = NULL; + char *ptr; + + if (datalen<14) + goto resubmit; + if ((seq & IEEE80211_SCTL_FRAG) == 0) { + frag = kmalloc(sizeof(*frag), GFP_ATOMIC); + if (!frag) + goto resubmit; + skb = dev_alloc_skb(IEEE80211_DATA_LEN +14+2); + if (!skb) { + kfree(frag); + goto resubmit; + } + frag->skb = skb; + frag->seq = seq & IEEE80211_SCTL_SEQ; + skb_reserve(skb, 2); + memcpy(skb_put(skb, 12), &data[datalen-14], 12); + memcpy(skb_put(skb, 2), &data[6], 2); + memcpy(skb_put(skb, len), data+8, len); + hlist_add_head(&frag->fnode, &zd->fraglist); + goto resubmit; + } + hlist_for_each_entry(frag, node, &zd->fraglist, fnode) + if (frag->seq == (seq&IEEE80211_SCTL_SEQ)) + break; + if (!frag) + goto resubmit; + skb = frag->skb; + ptr = skb_put(skb, len); + if (ptr) + memcpy(ptr, data+8, len); + if (fc & IEEE80211_FCTL_MOREFRAGS) + goto resubmit; + hlist_del_init(&frag->fnode); + kfree(frag); + } else { + if (datalen<14) + goto resubmit; + skb = dev_alloc_skb(len + 14 + 2); + if (!skb) + goto resubmit; + skb_reserve(skb, 2); + memcpy(skb_put(skb, 12), &data[datalen-14], 12); + memcpy(skb_put(skb, 2), &data[6], 2); + memcpy(skb_put(skb, len), data+8, len); + } + skb->dev = zd->dev; + skb->dev->last_rx = jiffies; + skb->protocol = eth_type_trans(skb, zd->dev); + zd->stats.rx_packets++; + zd->stats.rx_bytes += skb->len; + netif_rx(skb); + } +resubmit: + memset(data, 0, ZD1201_RXSIZE); + + urb->status = 0; + urb->dev = zd->usb; + if(usb_submit_urb(urb, GFP_ATOMIC)) + free = 1; + +exit: + if (free) { + zd->rxlen = 0; + zd->rxdatas = 1; + wake_up(&zd->rxdataq); + kfree(urb->transfer_buffer); + } + return; +} + +static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata, + unsigned int riddatalen) +{ + int err; + int i = 0; + int code; + int rid_fid; + int length; + unsigned char *pdata; + + zd->rxdatas = 0; + err = zd1201_docmd(zd, ZD1201_CMDCODE_ACCESS, rid, 0, 0); + if (err) + return err; + + wait_event_interruptible(zd->rxdataq, zd->rxdatas); + if (!zd->rxlen) + return -EIO; + + code = le16_to_cpu(*(__le16*)(&zd->rxdata[4])); + rid_fid = le16_to_cpu(*(__le16*)(&zd->rxdata[6])); + length = le16_to_cpu(*(__le16*)(&zd->rxdata[8])); + if (length > zd->rxlen) + length = zd->rxlen-6; + + /* If access bit is not on, then error */ + if ((code & ZD1201_ACCESSBIT) != ZD1201_ACCESSBIT || rid_fid != rid ) + return -EINVAL; + + /* Not enough buffer for allocating data */ + if (riddatalen != (length - 4)) { + dev_dbg(&zd->usb->dev, "riddatalen mismatches, expected=%u, (packet=%u) length=%u, rid=0x%04X, rid_fid=0x%04X\n", + riddatalen, zd->rxlen, length, rid, rid_fid); + return -ENODATA; + } + + zd->rxdatas = 0; + /* Issue SetRxRid commnd */ + err = zd1201_docmd(zd, ZD1201_CMDCODE_SETRXRID, rid, 0, length); + if (err) + return err; + + /* Receive RID record from resource packets */ + wait_event_interruptible(zd->rxdataq, zd->rxdatas); + if (!zd->rxlen) + return -EIO; + + if (zd->rxdata[zd->rxlen - 1] != ZD1201_PACKET_RESOURCE) { + dev_dbg(&zd->usb->dev, "Packet type mismatch: 0x%x not 0x3\n", + zd->rxdata[zd->rxlen-1]); + return -EINVAL; + } + + /* Set the data pointer and received data length */ + pdata = zd->rxdata; + length = zd->rxlen; + + do { + int actual_length; + + actual_length = (length > 64) ? 64 : length; + + if (pdata[0] != 0x3) { + dev_dbg(&zd->usb->dev, "Rx Resource packet type error: %02X\n", + pdata[0]); + return -EINVAL; + } + + if (actual_length != 64) { + /* Trim the last packet type byte */ + actual_length--; + } + + /* Skip the 4 bytes header (RID length and RID) */ + if (i == 0) { + pdata += 8; + actual_length -= 8; + } else { + pdata += 4; + actual_length -= 4; + } + + memcpy(riddata, pdata, actual_length); + riddata += actual_length; + pdata += actual_length; + length -= 64; + i++; + } while (length > 0); + + return 0; +} + +/* + * resreq: + * byte type + * byte sequence + * u16 reserved + * byte data[12] + * total: 16 + */ +static int zd1201_setconfig(struct zd1201 *zd, int rid, void *buf, int len, int wait) +{ + int err; + unsigned char *request; + int reqlen; + char seq=0; + struct urb *urb; + gfp_t gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC; + + len += 4; /* first 4 are for header */ + + zd->rxdatas = 0; + zd->rxlen = 0; + for (seq=0; len > 0; seq++) { + request = kmalloc(16, gfp_mask); + if (!request) + return -ENOMEM; + urb = usb_alloc_urb(0, gfp_mask); + if (!urb) { + kfree(request); + return -ENOMEM; + } + memset(request, 0, 16); + reqlen = len>12 ? 12 : len; + request[0] = ZD1201_USB_RESREQ; + request[1] = seq; + request[2] = 0; + request[3] = 0; + if (request[1] == 0) { + /* add header */ + *(__le16*)&request[4] = cpu_to_le16((len-2+1)/2); + *(__le16*)&request[6] = cpu_to_le16(rid); + memcpy(request+8, buf, reqlen-4); + buf += reqlen-4; + } else { + memcpy(request+4, buf, reqlen); + buf += reqlen; + } + + len -= reqlen; + + usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, + zd->endp_out2), request, 16, zd1201_usbfree, zd); + err = usb_submit_urb(urb, gfp_mask); + if (err) + goto err; + } + + request = kmalloc(16, gfp_mask); + if (!request) + return -ENOMEM; + urb = usb_alloc_urb(0, gfp_mask); + if (!urb) { + kfree(request); + return -ENOMEM; + } + *((__le32*)request) = cpu_to_le32(ZD1201_USB_CMDREQ); + *((__le16*)&request[4]) = + cpu_to_le16(ZD1201_CMDCODE_ACCESS|ZD1201_ACCESSBIT); + *((__le16*)&request[6]) = cpu_to_le16(rid); + *((__le16*)&request[8]) = cpu_to_le16(0); + *((__le16*)&request[10]) = cpu_to_le16(0); + usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2), + request, 16, zd1201_usbfree, zd); + err = usb_submit_urb(urb, gfp_mask); + if (err) + goto err; + + if (wait) { + wait_event_interruptible(zd->rxdataq, zd->rxdatas); + if (!zd->rxlen || le16_to_cpu(*(__le16*)&zd->rxdata[6]) != rid) { + dev_dbg(&zd->usb->dev, "wrong or no RID received\n"); + } + } + + return 0; +err: + kfree(request); + usb_free_urb(urb); + return err; +} + +static inline int zd1201_getconfig16(struct zd1201 *zd, int rid, short *val) +{ + int err; + __le16 zdval; + + err = zd1201_getconfig(zd, rid, &zdval, sizeof(__le16)); + if (err) + return err; + *val = le16_to_cpu(zdval); + return 0; +} + +static inline int zd1201_setconfig16(struct zd1201 *zd, int rid, short val) +{ + __le16 zdval = cpu_to_le16(val); + return (zd1201_setconfig(zd, rid, &zdval, sizeof(__le16), 1)); +} + +static int zd1201_drvr_start(struct zd1201 *zd) +{ + int err, i; + short max; + __le16 zdmax; + unsigned char *buffer; + + buffer = kzalloc(ZD1201_RXSIZE, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + usb_fill_bulk_urb(zd->rx_urb, zd->usb, + usb_rcvbulkpipe(zd->usb, zd->endp_in), buffer, ZD1201_RXSIZE, + zd1201_usbrx, zd); + + err = usb_submit_urb(zd->rx_urb, GFP_KERNEL); + if (err) + goto err_buffer; + + err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); + if (err) + goto err_urb; + + err = zd1201_getconfig(zd, ZD1201_RID_CNFMAXTXBUFFERNUMBER, &zdmax, + sizeof(__le16)); + if (err) + goto err_urb; + + max = le16_to_cpu(zdmax); + for (i=0; i<max; i++) { + err = zd1201_docmd(zd, ZD1201_CMDCODE_ALLOC, 1514, 0, 0); + if (err) + goto err_urb; + } + + return 0; + +err_urb: + usb_kill_urb(zd->rx_urb); + return err; +err_buffer: + kfree(buffer); + return err; +} + +/* Magic alert: The firmware doesn't seem to like the MAC state being + * toggled in promisc (aka monitor) mode. + * (It works a number of times, but will halt eventually) + * So we turn it of before disabling and on after enabling if needed. + */ +static int zd1201_enable(struct zd1201 *zd) +{ + int err; + + if (zd->mac_enabled) + return 0; + + err = zd1201_docmd(zd, ZD1201_CMDCODE_ENABLE, 0, 0, 0); + if (!err) + zd->mac_enabled = 1; + + if (zd->monitor) + err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 1); + + return err; +} + +static int zd1201_disable(struct zd1201 *zd) +{ + int err; + + if (!zd->mac_enabled) + return 0; + if (zd->monitor) { + err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0); + if (err) + return err; + } + + err = zd1201_docmd(zd, ZD1201_CMDCODE_DISABLE, 0, 0, 0); + if (!err) + zd->mac_enabled = 0; + return err; +} + +static int zd1201_mac_reset(struct zd1201 *zd) +{ + if (!zd->mac_enabled) + return 0; + zd1201_disable(zd); + return zd1201_enable(zd); +} + +static int zd1201_join(struct zd1201 *zd, char *essid, int essidlen) +{ + int err, val; + char buf[IW_ESSID_MAX_SIZE+2]; + + err = zd1201_disable(zd); + if (err) + return err; + + val = ZD1201_CNFAUTHENTICATION_OPENSYSTEM; + val |= ZD1201_CNFAUTHENTICATION_SHAREDKEY; + err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, val); + if (err) + return err; + + *(__le16 *)buf = cpu_to_le16(essidlen); + memcpy(buf+2, essid, essidlen); + if (!zd->ap) { /* Normal station */ + err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, + IW_ESSID_MAX_SIZE+2, 1); + if (err) + return err; + } else { /* AP */ + err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNSSID, buf, + IW_ESSID_MAX_SIZE+2, 1); + if (err) + return err; + } + + err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, + zd->dev->dev_addr, zd->dev->addr_len, 1); + if (err) + return err; + + err = zd1201_enable(zd); + if (err) + return err; + + msleep(100); + return 0; +} + +static int zd1201_net_open(struct net_device *dev) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + + /* Start MAC with wildcard if no essid set */ + if (!zd->mac_enabled) + zd1201_join(zd, zd->essid, zd->essidlen); + netif_start_queue(dev); + + return 0; +} + +static int zd1201_net_stop(struct net_device *dev) +{ + netif_stop_queue(dev); + return 0; +} + +/* + RFC 1042 encapsulates Ethernet frames in 802.11 frames + by prefixing them with 0xaa, 0xaa, 0x03) followed by a SNAP OID of 0 + (0x00, 0x00, 0x00). Zd requires an additional padding, copy + of ethernet addresses, length of the standard RFC 1042 packet + and a command byte (which is nul for tx). + + tx frame (from Wlan NG): + RFC 1042: + llc 0xAA 0xAA 0x03 (802.2 LLC) + snap 0x00 0x00 0x00 (Ethernet encapsulated) + type 2 bytes, Ethernet type field + payload (minus eth header) + Zydas specific: + padding 1B if (skb->len+8+1)%64==0 + Eth MAC addr 12 bytes, Ethernet MAC addresses + length 2 bytes, RFC 1042 packet length + (llc+snap+type+payload) + zd 1 null byte, zd1201 packet type + */ +static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + unsigned char *txbuf = zd->txdata; + int txbuflen, pad = 0, err; + struct urb *urb = zd->tx_urb; + + if (!zd->mac_enabled || zd->monitor) { + zd->stats.tx_dropped++; + kfree_skb(skb); + return 0; + } + netif_stop_queue(dev); + + txbuflen = skb->len + 8 + 1; + if (txbuflen%64 == 0) { + pad = 1; + txbuflen++; + } + txbuf[0] = 0xAA; + txbuf[1] = 0xAA; + txbuf[2] = 0x03; + txbuf[3] = 0x00; /* rfc1042 */ + txbuf[4] = 0x00; + txbuf[5] = 0x00; + + memcpy(txbuf+6, skb->data+12, skb->len-12); + if (pad) + txbuf[skb->len-12+6]=0; + memcpy(txbuf+skb->len-12+6+pad, skb->data, 12); + *(__be16*)&txbuf[skb->len+6+pad] = htons(skb->len-12+6); + txbuf[txbuflen-1] = 0; + + usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out), + txbuf, txbuflen, zd1201_usbtx, zd); + + err = usb_submit_urb(zd->tx_urb, GFP_ATOMIC); + if (err) { + zd->stats.tx_errors++; + netif_start_queue(dev); + return err; + } + zd->stats.tx_packets++; + zd->stats.tx_bytes += skb->len; + dev->trans_start = jiffies; + kfree_skb(skb); + + return 0; +} + +static void zd1201_tx_timeout(struct net_device *dev) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + + if (!zd) + return; + dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n", + dev->name); + usb_unlink_urb(zd->tx_urb); + zd->stats.tx_errors++; + /* Restart the timeout to quiet the watchdog: */ + dev->trans_start = jiffies; +} + +static int zd1201_set_mac_address(struct net_device *dev, void *p) +{ + struct sockaddr *addr = p; + struct zd1201 *zd = (struct zd1201 *)dev->priv; + int err; + + if (!zd) + return -ENODEV; + + err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, + addr->sa_data, dev->addr_len, 1); + if (err) + return err; + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + + return zd1201_mac_reset(zd); +} + +static struct net_device_stats *zd1201_get_stats(struct net_device *dev) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + + return &zd->stats; +} + +static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + + return &zd->iwstats; +} + +static void zd1201_set_multicast(struct net_device *dev) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + struct dev_mc_list *mc = dev->mc_list; + unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI]; + int i; + + if (dev->mc_count > ZD1201_MAXMULTI) + return; + + for (i=0; i<dev->mc_count; i++) { + memcpy(reqbuf+i*ETH_ALEN, mc->dmi_addr, ETH_ALEN); + mc = mc->next; + } + zd1201_setconfig(zd, ZD1201_RID_CNFGROUPADDRESS, reqbuf, + dev->mc_count*ETH_ALEN, 0); + +} + +static int zd1201_config_commit(struct net_device *dev, + struct iw_request_info *info, struct iw_point *data, char *essid) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + + return zd1201_mac_reset(zd); +} + +static int zd1201_get_name(struct net_device *dev, + struct iw_request_info *info, char *name, char *extra) +{ + strcpy(name, "IEEE 802.11b"); + return 0; +} + +static int zd1201_set_freq(struct net_device *dev, + struct iw_request_info *info, struct iw_freq *freq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short channel = 0; + int err; + + if (freq->e == 0) + channel = freq->m; + else { + if (freq->m >= 2482) + channel = 14; + if (freq->m >= 2407) + channel = (freq->m-2407)/5; + } + + err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel); + if (err) + return err; + + zd1201_mac_reset(zd); + + return 0; +} + +static int zd1201_get_freq(struct net_device *dev, + struct iw_request_info *info, struct iw_freq *freq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short channel; + int err; + + err = zd1201_getconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, &channel); + if (err) + return err; + freq->e = 0; + freq->m = channel; + + return 0; +} + +static int zd1201_set_mode(struct net_device *dev, + struct iw_request_info *info, __u32 *mode, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short porttype, monitor = 0; + unsigned char buffer[IW_ESSID_MAX_SIZE+2]; + int err; + + if (zd->ap) { + if (*mode != IW_MODE_MASTER) + return -EINVAL; + return 0; + } + + err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0); + if (err) + return err; + zd->dev->type = ARPHRD_ETHER; + switch(*mode) { + case IW_MODE_MONITOR: + monitor = 1; + zd->dev->type = ARPHRD_IEEE80211; + /* Make sure we are no longer associated with by + setting an 'impossible' essid. + (otherwise we mess up firmware) + */ + zd1201_join(zd, "\0-*#\0", 5); + /* Put port in pIBSS */ + case 8: /* No pseudo-IBSS in wireless extensions (yet) */ + porttype = ZD1201_PORTTYPE_PSEUDOIBSS; + break; + case IW_MODE_ADHOC: + porttype = ZD1201_PORTTYPE_IBSS; + break; + case IW_MODE_INFRA: + porttype = ZD1201_PORTTYPE_BSS; + break; + default: + return -EINVAL; + } + + err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); + if (err) + return err; + if (zd->monitor && !monitor) { + zd1201_disable(zd); + *(__le16 *)buffer = cpu_to_le16(zd->essidlen); + memcpy(buffer+2, zd->essid, zd->essidlen); + err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, + buffer, IW_ESSID_MAX_SIZE+2, 1); + if (err) + return err; + } + zd->monitor = monitor; + /* If monitor mode is set we don't actually turn it on here since it + * is done during mac reset anyway (see zd1201_mac_enable). + */ + zd1201_mac_reset(zd); + + return 0; +} + +static int zd1201_get_mode(struct net_device *dev, + struct iw_request_info *info, __u32 *mode, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short porttype; + int err; + + err = zd1201_getconfig16(zd, ZD1201_RID_CNFPORTTYPE, &porttype); + if (err) + return err; + switch(porttype) { + case ZD1201_PORTTYPE_IBSS: + *mode = IW_MODE_ADHOC; + break; + case ZD1201_PORTTYPE_BSS: + *mode = IW_MODE_INFRA; + break; + case ZD1201_PORTTYPE_WDS: + *mode = IW_MODE_REPEAT; + break; + case ZD1201_PORTTYPE_PSEUDOIBSS: + *mode = 8;/* No Pseudo-IBSS... */ + break; + case ZD1201_PORTTYPE_AP: + *mode = IW_MODE_MASTER; + break; + default: + dev_dbg(&zd->usb->dev, "Unknown porttype: %d\n", + porttype); + *mode = IW_MODE_AUTO; + } + if (zd->monitor) + *mode = IW_MODE_MONITOR; + + return 0; +} + +static int zd1201_get_range(struct net_device *dev, + struct iw_request_info *info, struct iw_point *wrq, char *extra) +{ + struct iw_range *range = (struct iw_range *)extra; + + wrq->length = sizeof(struct iw_range); + memset(range, 0, sizeof(struct iw_range)); + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = WIRELESS_EXT; + + range->max_qual.qual = 128; + range->max_qual.level = 128; + range->max_qual.noise = 128; + range->max_qual.updated = 7; + + range->encoding_size[0] = 5; + range->encoding_size[1] = 13; + range->num_encoding_sizes = 2; + range->max_encoding_tokens = ZD1201_NUMKEYS; + + range->num_bitrates = 4; + range->bitrate[0] = 1000000; + range->bitrate[1] = 2000000; + range->bitrate[2] = 5500000; + range->bitrate[3] = 11000000; + + range->min_rts = 0; + range->min_frag = ZD1201_FRAGMIN; + range->max_rts = ZD1201_RTSMAX; + range->min_frag = ZD1201_FRAGMAX; + + return 0; +} + +/* Little bit of magic here: we only get the quality if we poll + * for it, and we never get an actual request to trigger such + * a poll. Therefore we 'assume' that the user will soon ask for + * the stats after asking the bssid. + */ +static int zd1201_get_wap(struct net_device *dev, + struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + unsigned char buffer[6]; + + if (!zd1201_getconfig(zd, ZD1201_RID_COMMSQUALITY, buffer, 6)) { + /* Unfortunately the quality and noise reported is useless. + they seem to be accumulators that increase until you + read them, unless we poll on a fixed interval we can't + use them + */ + /*zd->iwstats.qual.qual = le16_to_cpu(((__le16 *)buffer)[0]);*/ + zd->iwstats.qual.level = le16_to_cpu(((__le16 *)buffer)[1]); + /*zd->iwstats.qual.noise = le16_to_cpu(((__le16 *)buffer)[2]);*/ + zd->iwstats.qual.updated = 2; + } + + return zd1201_getconfig(zd, ZD1201_RID_CURRENTBSSID, ap_addr->sa_data, 6); +} + +static int zd1201_set_scan(struct net_device *dev, + struct iw_request_info *info, struct iw_point *srq, char *extra) +{ + /* We do everything in get_scan */ + return 0; +} + +static int zd1201_get_scan(struct net_device *dev, + struct iw_request_info *info, struct iw_point *srq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + int err, i, j, enabled_save; + struct iw_event iwe; + char *cev = extra; + char *end_buf = extra + IW_SCAN_MAX_DATA; + + /* No scanning in AP mode */ + if (zd->ap) + return -EOPNOTSUPP; + + /* Scan doesn't seem to work if disabled */ + enabled_save = zd->mac_enabled; + zd1201_enable(zd); + + zd->rxdatas = 0; + err = zd1201_docmd(zd, ZD1201_CMDCODE_INQUIRE, + ZD1201_INQ_SCANRESULTS, 0, 0); + if (err) + return err; + + wait_event_interruptible(zd->rxdataq, zd->rxdatas); + if (!zd->rxlen) + return -EIO; + + if (le16_to_cpu(*(__le16*)&zd->rxdata[2]) != ZD1201_INQ_SCANRESULTS) + return -EIO; + + for(i=8; i<zd->rxlen; i+=62) { + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6); + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN); + + iwe.cmd = SIOCGIWESSID; + iwe.u.data.length = zd->rxdata[i+16]; + iwe.u.data.flags = 1; + cev = iwe_stream_add_point(cev, end_buf, &iwe, zd->rxdata+i+18); + + iwe.cmd = SIOCGIWMODE; + if (zd->rxdata[i+14]&0x01) + iwe.u.mode = IW_MODE_MASTER; + else + iwe.u.mode = IW_MODE_ADHOC; + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN); + + iwe.cmd = SIOCGIWFREQ; + iwe.u.freq.m = zd->rxdata[i+0]; + iwe.u.freq.e = 0; + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN); + + iwe.cmd = SIOCGIWRATE; + iwe.u.bitrate.fixed = 0; + iwe.u.bitrate.disabled = 0; + for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) { + iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000; + cev=iwe_stream_add_event(cev, end_buf, &iwe, + IW_EV_PARAM_LEN); + } + + iwe.cmd = SIOCGIWENCODE; + iwe.u.data.length = 0; + if (zd->rxdata[i+14]&0x10) + iwe.u.data.flags = IW_ENCODE_ENABLED; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL); + + iwe.cmd = IWEVQUAL; + iwe.u.qual.qual = zd->rxdata[i+4]; + iwe.u.qual.noise= zd->rxdata[i+2]/10-100; + iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100; + iwe.u.qual.updated = 7; + cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN); + } + + if (!enabled_save) + zd1201_disable(zd); + + srq->length = cev - extra; + srq->flags = 0; + + return 0; +} + +static int zd1201_set_essid(struct net_device *dev, + struct iw_request_info *info, struct iw_point *data, char *essid) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + + if (data->length > IW_ESSID_MAX_SIZE) + return -EINVAL; + if (data->length < 1) + data->length = 1; + zd->essidlen = data->length-1; + memset(zd->essid, 0, IW_ESSID_MAX_SIZE+1); + memcpy(zd->essid, essid, data->length); + return zd1201_join(zd, zd->essid, zd->essidlen); +} + +static int zd1201_get_essid(struct net_device *dev, + struct iw_request_info *info, struct iw_point *data, char *essid) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + + memcpy(essid, zd->essid, zd->essidlen); + data->flags = 1; + data->length = zd->essidlen; + + return 0; +} + +static int zd1201_get_nick(struct net_device *dev, struct iw_request_info *info, + struct iw_point *data, char *nick) +{ + strcpy(nick, "zd1201"); + data->flags = 1; + data->length = strlen(nick); + return 0; +} + +static int zd1201_set_rate(struct net_device *dev, + struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short rate; + int err; + + switch (rrq->value) { + case 1000000: + rate = ZD1201_RATEB1; + break; + case 2000000: + rate = ZD1201_RATEB2; + break; + case 5500000: + rate = ZD1201_RATEB5; + break; + case 11000000: + default: + rate = ZD1201_RATEB11; + break; + } + if (!rrq->fixed) { /* Also enable all lower bitrates */ + rate |= rate-1; + } + + err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate); + if (err) + return err; + + return zd1201_mac_reset(zd); +} + +static int zd1201_get_rate(struct net_device *dev, + struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short rate; + int err; + + err = zd1201_getconfig16(zd, ZD1201_RID_CURRENTTXRATE, &rate); + if (err) + return err; + + switch(rate) { + case 1: + rrq->value = 1000000; + break; + case 2: + rrq->value = 2000000; + break; + case 5: + rrq->value = 5500000; + break; + case 11: + rrq->value = 11000000; + break; + default: + rrq->value = 0; + } + rrq->fixed = 0; + rrq->disabled = 0; + + return 0; +} + +static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info, + struct iw_param *rts, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + int err; + short val = rts->value; + + if (rts->disabled || !rts->fixed) + val = ZD1201_RTSMAX; + if (val > ZD1201_RTSMAX) + return -EINVAL; + if (val < 0) + return -EINVAL; + + err = zd1201_setconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, val); + if (err) + return err; + return zd1201_mac_reset(zd); +} + +static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info, + struct iw_param *rts, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short rtst; + int err; + + err = zd1201_getconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, &rtst); + if (err) + return err; + rts->value = rtst; + rts->disabled = (rts->value == ZD1201_RTSMAX); + rts->fixed = 1; + + return 0; +} + +static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + int err; + short val = frag->value; + + if (frag->disabled || !frag->fixed) + val = ZD1201_FRAGMAX; + if (val > ZD1201_FRAGMAX) + return -EINVAL; + if (val < ZD1201_FRAGMIN) + return -EINVAL; + if (val & 1) + return -EINVAL; + err = zd1201_setconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, val); + if (err) + return err; + return zd1201_mac_reset(zd); +} + +static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info, + struct iw_param *frag, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short fragt; + int err; + + err = zd1201_getconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, &fragt); + if (err) + return err; + frag->value = fragt; + frag->disabled = (frag->value == ZD1201_FRAGMAX); + frag->fixed = 1; + + return 0; +} + +static int zd1201_set_retry(struct net_device *dev, + struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + return 0; +} + +static int zd1201_get_retry(struct net_device *dev, + struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + return 0; +} + +static int zd1201_set_encode(struct net_device *dev, + struct iw_request_info *info, struct iw_point *erq, char *key) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short i; + int err, rid; + + if (erq->length > ZD1201_MAXKEYLEN) + return -EINVAL; + + i = (erq->flags & IW_ENCODE_INDEX)-1; + if (i == -1) { + err = zd1201_getconfig16(zd,ZD1201_RID_CNFDEFAULTKEYID,&i); + if (err) + return err; + } else { + err = zd1201_setconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, i); + if (err) + return err; + } + + if (i < 0 || i >= ZD1201_NUMKEYS) + return -EINVAL; + + rid = ZD1201_RID_CNFDEFAULTKEY0 + i; + err = zd1201_setconfig(zd, rid, key, erq->length, 1); + if (err) + return err; + zd->encode_keylen[i] = erq->length; + memcpy(zd->encode_keys[i], key, erq->length); + + i=0; + if (!(erq->flags & IW_ENCODE_DISABLED & IW_ENCODE_MODE)) { + i |= 0x01; + zd->encode_enabled = 1; + } else + zd->encode_enabled = 0; + if (erq->flags & IW_ENCODE_RESTRICTED & IW_ENCODE_MODE) { + i |= 0x02; + zd->encode_restricted = 1; + } else + zd->encode_restricted = 0; + err = zd1201_setconfig16(zd, ZD1201_RID_CNFWEBFLAGS, i); + if (err) + return err; + + if (zd->encode_enabled) + i = ZD1201_CNFAUTHENTICATION_SHAREDKEY; + else + i = ZD1201_CNFAUTHENTICATION_OPENSYSTEM; + err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, i); + if (err) + return err; + + return zd1201_mac_reset(zd); +} + +static int zd1201_get_encode(struct net_device *dev, + struct iw_request_info *info, struct iw_point *erq, char *key) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short i; + int err; + + if (zd->encode_enabled) + erq->flags = IW_ENCODE_ENABLED; + else + erq->flags = IW_ENCODE_DISABLED; + if (zd->encode_restricted) + erq->flags |= IW_ENCODE_RESTRICTED; + else + erq->flags |= IW_ENCODE_OPEN; + + i = (erq->flags & IW_ENCODE_INDEX) -1; + if (i == -1) { + err = zd1201_getconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, &i); + if (err) + return err; + } + if (i<0 || i>= ZD1201_NUMKEYS) + return -EINVAL; + + erq->flags |= i+1; + + erq->length = zd->encode_keylen[i]; + memcpy(key, zd->encode_keys[i], erq->length); + + return 0; +} + +static int zd1201_set_power(struct net_device *dev, + struct iw_request_info *info, struct iw_param *vwrq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short enabled, duration, level; + int err; + + enabled = vwrq->disabled ? 0 : 1; + if (enabled) { + if (vwrq->flags & IW_POWER_PERIOD) { + duration = vwrq->value; + err = zd1201_setconfig16(zd, + ZD1201_RID_CNFMAXSLEEPDURATION, duration); + if (err) + return err; + goto out; + } + if (vwrq->flags & IW_POWER_TIMEOUT) { + err = zd1201_getconfig16(zd, + ZD1201_RID_CNFMAXSLEEPDURATION, &duration); + if (err) + return err; + level = vwrq->value * 4 / duration; + if (level > 4) + level = 4; + if (level < 0) + level = 0; + err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMEPS, + level); + if (err) + return err; + goto out; + } + return -EINVAL; + } +out: + return zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled); +} + +static int zd1201_get_power(struct net_device *dev, + struct iw_request_info *info, struct iw_param *vwrq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short enabled, level, duration; + int err; + + err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMENABLED, &enabled); + if (err) + return err; + err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMEPS, &level); + if (err) + return err; + err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXSLEEPDURATION, &duration); + if (err) + return err; + vwrq->disabled = enabled ? 0 : 1; + if (vwrq->flags & IW_POWER_TYPE) { + if (vwrq->flags & IW_POWER_PERIOD) { + vwrq->value = duration; + vwrq->flags = IW_POWER_PERIOD; + } else { + vwrq->value = duration * level / 4; + vwrq->flags = IW_POWER_TIMEOUT; + } + } + if (vwrq->flags & IW_POWER_MODE) { + if (enabled && level) + vwrq->flags = IW_POWER_UNICAST_R; + else + vwrq->flags = IW_POWER_ALL_R; + } + + return 0; +} + + +static const iw_handler zd1201_iw_handler[] = +{ + (iw_handler) zd1201_config_commit, /* SIOCSIWCOMMIT */ + (iw_handler) zd1201_get_name, /* SIOCGIWNAME */ + (iw_handler) NULL, /* SIOCSIWNWID */ + (iw_handler) NULL, /* SIOCGIWNWID */ + (iw_handler) zd1201_set_freq, /* SIOCSIWFREQ */ + (iw_handler) zd1201_get_freq, /* SIOCGIWFREQ */ + (iw_handler) zd1201_set_mode, /* SIOCSIWMODE */ + (iw_handler) zd1201_get_mode, /* SIOCGIWMODE */ + (iw_handler) NULL, /* SIOCSIWSENS */ + (iw_handler) NULL, /* SIOCGIWSENS */ + (iw_handler) NULL, /* SIOCSIWRANGE */ + (iw_handler) zd1201_get_range, /* SIOCGIWRANGE */ + (iw_handler) NULL, /* SIOCSIWPRIV */ + (iw_handler) NULL, /* SIOCGIWPRIV */ + (iw_handler) NULL, /* SIOCSIWSTATS */ + (iw_handler) NULL, /* SIOCGIWSTATS */ + (iw_handler) NULL, /* SIOCSIWSPY */ + (iw_handler) NULL, /* SIOCGIWSPY */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL/*zd1201_set_wap*/, /* SIOCSIWAP */ + (iw_handler) zd1201_get_wap, /* SIOCGIWAP */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* SIOCGIWAPLIST */ + (iw_handler) zd1201_set_scan, /* SIOCSIWSCAN */ + (iw_handler) zd1201_get_scan, /* SIOCGIWSCAN */ + (iw_handler) zd1201_set_essid, /* SIOCSIWESSID */ + (iw_handler) zd1201_get_essid, /* SIOCGIWESSID */ + (iw_handler) NULL, /* SIOCSIWNICKN */ + (iw_handler) zd1201_get_nick, /* SIOCGIWNICKN */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) NULL, /* -- hole -- */ + (iw_handler) zd1201_set_rate, /* SIOCSIWRATE */ + (iw_handler) zd1201_get_rate, /* SIOCGIWRATE */ + (iw_handler) zd1201_set_rts, /* SIOCSIWRTS */ + (iw_handler) zd1201_get_rts, /* SIOCGIWRTS */ + (iw_handler) zd1201_set_frag, /* SIOCSIWFRAG */ + (iw_handler) zd1201_get_frag, /* SIOCGIWFRAG */ + (iw_handler) NULL, /* SIOCSIWTXPOW */ + (iw_handler) NULL, /* SIOCGIWTXPOW */ + (iw_handler) zd1201_set_retry, /* SIOCSIWRETRY */ + (iw_handler) zd1201_get_retry, /* SIOCGIWRETRY */ + (iw_handler) zd1201_set_encode, /* SIOCSIWENCODE */ + (iw_handler) zd1201_get_encode, /* SIOCGIWENCODE */ + (iw_handler) zd1201_set_power, /* SIOCSIWPOWER */ + (iw_handler) zd1201_get_power, /* SIOCGIWPOWER */ +}; + +static int zd1201_set_hostauth(struct net_device *dev, + struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + + if (!zd->ap) + return -EOPNOTSUPP; + + return zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value); +} + +static int zd1201_get_hostauth(struct net_device *dev, + struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short hostauth; + int err; + + if (!zd->ap) + return -EOPNOTSUPP; + + err = zd1201_getconfig16(zd, ZD1201_RID_CNFHOSTAUTH, &hostauth); + if (err) + return err; + rrq->value = hostauth; + rrq->fixed = 1; + + return 0; +} + +static int zd1201_auth_sta(struct net_device *dev, + struct iw_request_info *info, struct sockaddr *sta, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + unsigned char buffer[10]; + + if (!zd->ap) + return -EOPNOTSUPP; + + memcpy(buffer, sta->sa_data, ETH_ALEN); + *(short*)(buffer+6) = 0; /* 0==success, 1==failure */ + *(short*)(buffer+8) = 0; + + return zd1201_setconfig(zd, ZD1201_RID_AUTHENTICATESTA, buffer, 10, 1); +} + +static int zd1201_set_maxassoc(struct net_device *dev, + struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + int err; + + if (!zd->ap) + return -EOPNOTSUPP; + + err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, rrq->value); + if (err) + return err; + return 0; +} + +static int zd1201_get_maxassoc(struct net_device *dev, + struct iw_request_info *info, struct iw_param *rrq, char *extra) +{ + struct zd1201 *zd = (struct zd1201 *)dev->priv; + short maxassoc; + int err; + + if (!zd->ap) + return -EOPNOTSUPP; + + err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, &maxassoc); + if (err) + return err; + rrq->value = maxassoc; + rrq->fixed = 1; + + return 0; +} + +static const iw_handler zd1201_private_handler[] = { + (iw_handler) zd1201_set_hostauth, /* ZD1201SIWHOSTAUTH */ + (iw_handler) zd1201_get_hostauth, /* ZD1201GIWHOSTAUTH */ + (iw_handler) zd1201_auth_sta, /* ZD1201SIWAUTHSTA */ + (iw_handler) NULL, /* nothing to get */ + (iw_handler) zd1201_set_maxassoc, /* ZD1201SIMAXASSOC */ + (iw_handler) zd1201_get_maxassoc, /* ZD1201GIMAXASSOC */ +}; + +static const struct iw_priv_args zd1201_private_args[] = { + { ZD1201SIWHOSTAUTH, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_NONE, "sethostauth" }, + { ZD1201GIWHOSTAUTH, IW_PRIV_TYPE_NONE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostauth" }, + { ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_NONE, "authstation" }, + { ZD1201SIWMAXASSOC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + IW_PRIV_TYPE_NONE, "setmaxassoc" }, + { ZD1201GIWMAXASSOC, IW_PRIV_TYPE_NONE, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmaxassoc" }, +}; + +static const struct iw_handler_def zd1201_iw_handlers = { + .num_standard = ARRAY_SIZE(zd1201_iw_handler), + .num_private = ARRAY_SIZE(zd1201_private_handler), + .num_private_args = ARRAY_SIZE(zd1201_private_args), + .standard = (iw_handler *)zd1201_iw_handler, + .private = (iw_handler *)zd1201_private_handler, + .private_args = (struct iw_priv_args *) zd1201_private_args, + .get_wireless_stats = zd1201_get_wireless_stats, +}; + +static int zd1201_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct zd1201 *zd; + struct usb_device *usb; + int err; + short porttype; + char buf[IW_ESSID_MAX_SIZE+2]; + + usb = interface_to_usbdev(interface); + + zd = kzalloc(sizeof(struct zd1201), GFP_KERNEL); + if (!zd) + return -ENOMEM; + zd->ap = ap; + zd->usb = usb; + zd->removed = 0; + init_waitqueue_head(&zd->rxdataq); + INIT_HLIST_HEAD(&zd->fraglist); + + err = zd1201_fw_upload(usb, zd->ap); + if (err) { + dev_err(&usb->dev, "zd1201 firmware upload failed: %d\n", err); + goto err_zd; + } + + zd->endp_in = 1; + zd->endp_out = 1; + zd->endp_out2 = 2; + zd->rx_urb = usb_alloc_urb(0, GFP_KERNEL); + zd->tx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!zd->rx_urb || !zd->tx_urb) + goto err_zd; + + mdelay(100); + err = zd1201_drvr_start(zd); + if (err) + goto err_zd; + + err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXDATALEN, 2312); + if (err) + goto err_start; + + err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, + ZD1201_RATEB1 | ZD1201_RATEB2 | ZD1201_RATEB5 | ZD1201_RATEB11); + if (err) + goto err_start; + + zd->dev = alloc_etherdev(0); + if (!zd->dev) + goto err_start; + + zd->dev->priv = zd; + zd->dev->open = zd1201_net_open; + zd->dev->stop = zd1201_net_stop; + zd->dev->get_stats = zd1201_get_stats; + zd->dev->wireless_handlers = + (struct iw_handler_def *)&zd1201_iw_handlers; + zd->dev->hard_start_xmit = zd1201_hard_start_xmit; + zd->dev->watchdog_timeo = ZD1201_TX_TIMEOUT; + zd->dev->tx_timeout = zd1201_tx_timeout; + zd->dev->set_multicast_list = zd1201_set_multicast; + zd->dev->set_mac_address = zd1201_set_mac_address; + strcpy(zd->dev->name, "wlan%d"); + + err = zd1201_getconfig(zd, ZD1201_RID_CNFOWNMACADDR, + zd->dev->dev_addr, zd->dev->addr_len); + if (err) + goto err_net; + + /* Set wildcard essid to match zd->essid */ + *(__le16 *)buf = cpu_to_le16(0); + err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, + IW_ESSID_MAX_SIZE+2, 1); + if (err) + goto err_net; + + if (zd->ap) + porttype = ZD1201_PORTTYPE_AP; + else + porttype = ZD1201_PORTTYPE_BSS; + err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); + if (err) + goto err_net; + + SET_NETDEV_DEV(zd->dev, &usb->dev); + + err = register_netdev(zd->dev); + if (err) + goto err_net; + dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n", + zd->dev->name); + + usb_set_intfdata(interface, zd); + zd1201_enable(zd); /* zd1201 likes to startup enabled, */ + zd1201_disable(zd); /* interfering with all the wifis in range */ + return 0; + +err_net: + free_netdev(zd->dev); +err_start: + /* Leave the device in reset state */ + zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); +err_zd: + if (zd->tx_urb) + usb_free_urb(zd->tx_urb); + if (zd->rx_urb) + usb_free_urb(zd->rx_urb); + kfree(zd); + return err; +} + +static void zd1201_disconnect(struct usb_interface *interface) +{ + struct zd1201 *zd=(struct zd1201 *)usb_get_intfdata(interface); + struct hlist_node *node, *node2; + struct zd1201_frag *frag; + + if (!zd) + return; + usb_set_intfdata(interface, NULL); + if (zd->dev) { + unregister_netdev(zd->dev); + free_netdev(zd->dev); + } + + hlist_for_each_entry_safe(frag, node, node2, &zd->fraglist, fnode) { + hlist_del_init(&frag->fnode); + kfree_skb(frag->skb); + kfree(frag); + } + + if (zd->tx_urb) { + usb_kill_urb(zd->tx_urb); + usb_free_urb(zd->tx_urb); + } + if (zd->rx_urb) { + usb_kill_urb(zd->rx_urb); + usb_free_urb(zd->rx_urb); + } + kfree(zd); +} + +#ifdef CONFIG_PM + +static int zd1201_suspend(struct usb_interface *interface, + pm_message_t message) +{ + struct zd1201 *zd = usb_get_intfdata(interface); + + netif_device_detach(zd->dev); + + zd->was_enabled = zd->mac_enabled; + + if (zd->was_enabled) + return zd1201_disable(zd); + else + return 0; +} + +static int zd1201_resume(struct usb_interface *interface) +{ + struct zd1201 *zd = usb_get_intfdata(interface); + + if (!zd || !zd->dev) + return -ENODEV; + + netif_device_attach(zd->dev); + + if (zd->was_enabled) + return zd1201_enable(zd); + else + return 0; +} + +#else + +#define zd1201_suspend NULL +#define zd1201_resume NULL + +#endif + +static struct usb_driver zd1201_usb = { + .name = "zd1201", + .probe = zd1201_probe, + .disconnect = zd1201_disconnect, + .id_table = zd1201_table, + .suspend = zd1201_suspend, + .resume = zd1201_resume, +}; + +static int __init zd1201_init(void) +{ + return usb_register(&zd1201_usb); +} + +static void __exit zd1201_cleanup(void) +{ + usb_deregister(&zd1201_usb); +} + +module_init(zd1201_init); +module_exit(zd1201_cleanup); diff --git a/drivers/net/wireless/zd1201.h b/drivers/net/wireless/zd1201.h new file mode 100644 index 000000000..235f0ee34 --- /dev/null +++ b/drivers/net/wireless/zd1201.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * Parts of this driver have been derived from a wlan-ng version + * modified by ZyDAS. + * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. + */ + +#ifndef _INCLUDE_ZD1201_H_ +#define _INCLUDE_ZD1201_H_ + +#define ZD1201_NUMKEYS 4 +#define ZD1201_MAXKEYLEN 13 +#define ZD1201_MAXMULTI 16 +#define ZD1201_FRAGMAX 2500 +#define ZD1201_FRAGMIN 256 +#define ZD1201_RTSMAX 2500 + +#define ZD1201_RXSIZE 3000 + +struct zd1201 { + struct usb_device *usb; + int removed; + struct net_device *dev; + struct net_device_stats stats; + struct iw_statistics iwstats; + + int endp_in; + int endp_out; + int endp_out2; + struct urb *rx_urb; + struct urb *tx_urb; + + unsigned char rxdata[ZD1201_RXSIZE]; + int rxlen; + wait_queue_head_t rxdataq; + int rxdatas; + struct hlist_head fraglist; + unsigned char txdata[ZD1201_RXSIZE]; + + int ap; + char essid[IW_ESSID_MAX_SIZE+1]; + int essidlen; + int mac_enabled; + int was_enabled; + int monitor; + int encode_enabled; + int encode_restricted; + unsigned char encode_keys[ZD1201_NUMKEYS][ZD1201_MAXKEYLEN]; + int encode_keylen[ZD1201_NUMKEYS]; +}; + +struct zd1201_frag { + struct hlist_node fnode; + int seq; + struct sk_buff *skb; +}; + +#define ZD1201SIWHOSTAUTH SIOCIWFIRSTPRIV +#define ZD1201GIWHOSTAUTH ZD1201SIWHOSTAUTH+1 +#define ZD1201SIWAUTHSTA SIOCIWFIRSTPRIV+2 +#define ZD1201SIWMAXASSOC SIOCIWFIRSTPRIV+4 +#define ZD1201GIWMAXASSOC ZD1201SIWMAXASSOC+1 + +#define ZD1201_FW_TIMEOUT (1000) + +#define ZD1201_TX_TIMEOUT (2000) + +#define ZD1201_USB_CMDREQ 0 +#define ZD1201_USB_RESREQ 1 + +#define ZD1201_CMDCODE_INIT 0x00 +#define ZD1201_CMDCODE_ENABLE 0x01 +#define ZD1201_CMDCODE_DISABLE 0x02 +#define ZD1201_CMDCODE_ALLOC 0x0a +#define ZD1201_CMDCODE_INQUIRE 0x11 +#define ZD1201_CMDCODE_SETRXRID 0x17 +#define ZD1201_CMDCODE_ACCESS 0x21 + +#define ZD1201_PACKET_EVENTSTAT 0x0 +#define ZD1201_PACKET_RXDATA 0x1 +#define ZD1201_PACKET_INQUIRE 0x2 +#define ZD1201_PACKET_RESOURCE 0x3 + +#define ZD1201_ACCESSBIT 0x0100 + +#define ZD1201_RID_CNFPORTTYPE 0xfc00 +#define ZD1201_RID_CNFOWNMACADDR 0xfc01 +#define ZD1201_RID_CNFDESIREDSSID 0xfc02 +#define ZD1201_RID_CNFOWNCHANNEL 0xfc03 +#define ZD1201_RID_CNFOWNSSID 0xfc04 +#define ZD1201_RID_CNFMAXDATALEN 0xfc07 +#define ZD1201_RID_CNFPMENABLED 0xfc09 +#define ZD1201_RID_CNFPMEPS 0xfc0a +#define ZD1201_RID_CNFMAXSLEEPDURATION 0xfc0c +#define ZD1201_RID_CNFDEFAULTKEYID 0xfc23 +#define ZD1201_RID_CNFDEFAULTKEY0 0xfc24 +#define ZD1201_RID_CNFDEFAULTKEY1 0xfc25 +#define ZD1201_RID_CNFDEFAULTKEY2 0xfc26 +#define ZD1201_RID_CNFDEFAULTKEY3 0xfc27 +#define ZD1201_RID_CNFWEBFLAGS 0xfc28 +#define ZD1201_RID_CNFAUTHENTICATION 0xfc2a +#define ZD1201_RID_CNFMAXASSOCSTATIONS 0xfc2b +#define ZD1201_RID_CNFHOSTAUTH 0xfc2e +#define ZD1201_RID_CNFGROUPADDRESS 0xfc80 +#define ZD1201_RID_CNFFRAGTHRESHOLD 0xfc82 +#define ZD1201_RID_CNFRTSTHRESHOLD 0xfc83 +#define ZD1201_RID_TXRATECNTL 0xfc84 +#define ZD1201_RID_PROMISCUOUSMODE 0xfc85 +#define ZD1201_RID_CNFBASICRATES 0xfcb3 +#define ZD1201_RID_AUTHENTICATESTA 0xfce3 +#define ZD1201_RID_CURRENTBSSID 0xfd42 +#define ZD1201_RID_COMMSQUALITY 0xfd43 +#define ZD1201_RID_CURRENTTXRATE 0xfd44 +#define ZD1201_RID_CNFMAXTXBUFFERNUMBER 0xfda0 +#define ZD1201_RID_CURRENTCHANNEL 0xfdc1 + +#define ZD1201_INQ_SCANRESULTS 0xf101 + +#define ZD1201_INF_LINKSTATUS 0xf200 +#define ZD1201_INF_ASSOCSTATUS 0xf201 +#define ZD1201_INF_AUTHREQ 0xf202 + +#define ZD1201_ASSOCSTATUS_STAASSOC 0x1 +#define ZD1201_ASSOCSTATUS_REASSOC 0x2 +#define ZD1201_ASSOCSTATUS_DISASSOC 0x3 +#define ZD1201_ASSOCSTATUS_ASSOCFAIL 0x4 +#define ZD1201_ASSOCSTATUS_AUTHFAIL 0x5 + +#define ZD1201_PORTTYPE_IBSS 0 +#define ZD1201_PORTTYPE_BSS 1 +#define ZD1201_PORTTYPE_WDS 2 +#define ZD1201_PORTTYPE_PSEUDOIBSS 3 +#define ZD1201_PORTTYPE_AP 6 + +#define ZD1201_RATEB1 1 +#define ZD1201_RATEB2 2 +#define ZD1201_RATEB5 4 /* 5.5 really, but 5 is shorter :) */ +#define ZD1201_RATEB11 8 + +#define ZD1201_CNFAUTHENTICATION_OPENSYSTEM 0x0001 +#define ZD1201_CNFAUTHENTICATION_SHAREDKEY 0x0002 + +#endif /* _INCLUDE_ZD1201_H_ */ diff --git a/drivers/net/wireless/zd1211rw/Kconfig b/drivers/net/wireless/zd1211rw/Kconfig new file mode 100644 index 000000000..66ed55bc5 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/Kconfig @@ -0,0 +1,19 @@ +config ZD1211RW + tristate "ZyDAS ZD1211/ZD1211B USB-wireless support" + depends on USB && IEEE80211 && IEEE80211_SOFTMAC && NET_RADIO && EXPERIMENTAL + select FW_LOADER + ---help--- + This is an experimental driver for the ZyDAS ZD1211/ZD1211B wireless + chip, present in many USB-wireless adapters. + + Device firmware is required alongside this driver. You can download the + firmware distribution from http://zd1211.ath.cx/get-firmware + +config ZD1211RW_DEBUG + bool "ZyDAS ZD1211 debugging" + depends on ZD1211RW + ---help--- + ZD1211 debugging messages. Choosing Y will result in additional debug + messages being saved to your kernel logs, which may help debug any + problems. + diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile new file mode 100644 index 000000000..500314fc7 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/Makefile @@ -0,0 +1,11 @@ +obj-$(CONFIG_ZD1211RW) += zd1211rw.o + +zd1211rw-objs := zd_chip.o zd_ieee80211.o \ + zd_mac.o zd_netdev.o \ + zd_rf_al2230.o zd_rf_rf2959.o \ + zd_rf.o zd_usb.o zd_util.o + +ifeq ($(CONFIG_ZD1211RW_DEBUG),y) +EXTRA_CFLAGS += -DDEBUG +endif + diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c new file mode 100644 index 000000000..4b971a997 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -0,0 +1,1646 @@ +/* zd_chip.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* This file implements all the hardware specific functions for the ZD1211 + * and ZD1211B chips. Support for the ZD1211B was possible after Timothy + * Legge sent me a ZD1211B device. Thank you Tim. -- Uli + */ + +#include <linux/kernel.h> +#include <linux/errno.h> + +#include "zd_def.h" +#include "zd_chip.h" +#include "zd_ieee80211.h" +#include "zd_mac.h" +#include "zd_rf.h" +#include "zd_util.h" + +void zd_chip_init(struct zd_chip *chip, + struct net_device *netdev, + struct usb_interface *intf) +{ + memset(chip, 0, sizeof(*chip)); + mutex_init(&chip->mutex); + zd_usb_init(&chip->usb, netdev, intf); + zd_rf_init(&chip->rf); +} + +void zd_chip_clear(struct zd_chip *chip) +{ + mutex_lock(&chip->mutex); + zd_usb_clear(&chip->usb); + zd_rf_clear(&chip->rf); + mutex_unlock(&chip->mutex); + mutex_destroy(&chip->mutex); + memset(chip, 0, sizeof(*chip)); +} + +static int scnprint_mac_oui(const u8 *addr, char *buffer, size_t size) +{ + return scnprintf(buffer, size, "%02x-%02x-%02x", + addr[0], addr[1], addr[2]); +} + +/* Prints an identifier line, which will support debugging. */ +static int scnprint_id(struct zd_chip *chip, char *buffer, size_t size) +{ + int i = 0; + + i = scnprintf(buffer, size, "zd1211%s chip ", + chip->is_zd1211b ? "b" : ""); + i += zd_usb_scnprint_id(&chip->usb, buffer+i, size-i); + i += scnprintf(buffer+i, size-i, " "); + i += scnprint_mac_oui(chip->e2p_mac, buffer+i, size-i); + i += scnprintf(buffer+i, size-i, " "); + i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i); + i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c", chip->pa_type, + chip->patch_cck_gain ? 'g' : '-', + chip->patch_cr157 ? '7' : '-', + chip->patch_6m_band_edge ? '6' : '-'); + return i; +} + +static void print_id(struct zd_chip *chip) +{ + char buffer[80]; + + scnprint_id(chip, buffer, sizeof(buffer)); + buffer[sizeof(buffer)-1] = 0; + dev_info(zd_chip_dev(chip), "%s\n", buffer); +} + +/* Read a variable number of 32-bit values. Parameter count is not allowed to + * exceed USB_MAX_IOREAD32_COUNT. + */ +int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr, + unsigned int count) +{ + int r; + int i; + zd_addr_t *a16 = (zd_addr_t *)NULL; + u16 *v16; + unsigned int count16; + + if (count > USB_MAX_IOREAD32_COUNT) + return -EINVAL; + + /* Allocate a single memory block for values and addresses. */ + count16 = 2*count; + a16 = (zd_addr_t *)kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)), + GFP_NOFS); + if (!a16) { + dev_dbg_f(zd_chip_dev(chip), + "error ENOMEM in allocation of a16\n"); + r = -ENOMEM; + goto out; + } + v16 = (u16 *)(a16 + count16); + + for (i = 0; i < count; i++) { + int j = 2*i; + /* We read the high word always first. */ + a16[j] = zd_inc_word(addr[i]); + a16[j+1] = addr[i]; + } + + r = zd_ioread16v_locked(chip, v16, a16, count16); + if (r) { + dev_dbg_f(zd_chip_dev(chip), + "error: zd_ioread16v_locked. Error number %d\n", r); + goto out; + } + + for (i = 0; i < count; i++) { + int j = 2*i; + values[i] = (v16[j] << 16) | v16[j+1]; + } + +out: + kfree((void *)a16); + return r; +} + +int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, + unsigned int count) +{ + int i, j, r; + struct zd_ioreq16 *ioreqs16; + unsigned int count16; + + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + + if (count == 0) + return 0; + if (count > USB_MAX_IOWRITE32_COUNT) + return -EINVAL; + + /* Allocate a single memory block for values and addresses. */ + count16 = 2*count; + ioreqs16 = kmalloc(count16 * sizeof(struct zd_ioreq16), GFP_NOFS); + if (!ioreqs16) { + r = -ENOMEM; + dev_dbg_f(zd_chip_dev(chip), + "error %d in ioreqs16 allocation\n", r); + goto out; + } + + for (i = 0; i < count; i++) { + j = 2*i; + /* We write the high word always first. */ + ioreqs16[j].value = ioreqs[i].value >> 16; + ioreqs16[j].addr = zd_inc_word(ioreqs[i].addr); + ioreqs16[j+1].value = ioreqs[i].value; + ioreqs16[j+1].addr = ioreqs[i].addr; + } + + r = zd_usb_iowrite16v(&chip->usb, ioreqs16, count16); +#ifdef DEBUG + if (r) { + dev_dbg_f(zd_chip_dev(chip), + "error %d in zd_usb_write16v\n", r); + } +#endif /* DEBUG */ +out: + kfree(ioreqs16); + return r; +} + +int zd_iowrite16a_locked(struct zd_chip *chip, + const struct zd_ioreq16 *ioreqs, unsigned int count) +{ + int r; + unsigned int i, j, t, max; + + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + for (i = 0; i < count; i += j + t) { + t = 0; + max = count-i; + if (max > USB_MAX_IOWRITE16_COUNT) + max = USB_MAX_IOWRITE16_COUNT; + for (j = 0; j < max; j++) { + if (!ioreqs[i+j].addr) { + t = 1; + break; + } + } + + r = zd_usb_iowrite16v(&chip->usb, &ioreqs[i], j); + if (r) { + dev_dbg_f(zd_chip_dev(chip), + "error zd_usb_iowrite16v. Error number %d\n", + r); + return r; + } + } + + return 0; +} + +/* Writes a variable number of 32 bit registers. The functions will split + * that in several USB requests. A split can be forced by inserting an IO + * request with an zero address field. + */ +int zd_iowrite32a_locked(struct zd_chip *chip, + const struct zd_ioreq32 *ioreqs, unsigned int count) +{ + int r; + unsigned int i, j, t, max; + + for (i = 0; i < count; i += j + t) { + t = 0; + max = count-i; + if (max > USB_MAX_IOWRITE32_COUNT) + max = USB_MAX_IOWRITE32_COUNT; + for (j = 0; j < max; j++) { + if (!ioreqs[i+j].addr) { + t = 1; + break; + } + } + + r = _zd_iowrite32v_locked(chip, &ioreqs[i], j); + if (r) { + dev_dbg_f(zd_chip_dev(chip), + "error _zd_iowrite32v_locked." + " Error number %d\n", r); + return r; + } + } + + return 0; +} + +int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value) +{ + int r; + + ZD_ASSERT(!mutex_is_locked(&chip->mutex)); + mutex_lock(&chip->mutex); + r = zd_ioread16_locked(chip, value, addr); + mutex_unlock(&chip->mutex); + return r; +} + +int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value) +{ + int r; + + ZD_ASSERT(!mutex_is_locked(&chip->mutex)); + mutex_lock(&chip->mutex); + r = zd_ioread32_locked(chip, value, addr); + mutex_unlock(&chip->mutex); + return r; +} + +int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value) +{ + int r; + + ZD_ASSERT(!mutex_is_locked(&chip->mutex)); + mutex_lock(&chip->mutex); + r = zd_iowrite16_locked(chip, value, addr); + mutex_unlock(&chip->mutex); + return r; +} + +int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value) +{ + int r; + + ZD_ASSERT(!mutex_is_locked(&chip->mutex)); + mutex_lock(&chip->mutex); + r = zd_iowrite32_locked(chip, value, addr); + mutex_unlock(&chip->mutex); + return r; +} + +int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses, + u32 *values, unsigned int count) +{ + int r; + + ZD_ASSERT(!mutex_is_locked(&chip->mutex)); + mutex_lock(&chip->mutex); + r = zd_ioread32v_locked(chip, values, addresses, count); + mutex_unlock(&chip->mutex); + return r; +} + +int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, + unsigned int count) +{ + int r; + + ZD_ASSERT(!mutex_is_locked(&chip->mutex)); + mutex_lock(&chip->mutex); + r = zd_iowrite32a_locked(chip, ioreqs, count); + mutex_unlock(&chip->mutex); + return r; +} + +static int read_pod(struct zd_chip *chip, u8 *rf_type) +{ + int r; + u32 value; + + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + r = zd_ioread32_locked(chip, &value, E2P_POD); + if (r) + goto error; + dev_dbg_f(zd_chip_dev(chip), "E2P_POD %#010x\n", value); + + /* FIXME: AL2230 handling (Bit 7 in POD) */ + *rf_type = value & 0x0f; + chip->pa_type = (value >> 16) & 0x0f; + chip->patch_cck_gain = (value >> 8) & 0x1; + chip->patch_cr157 = (value >> 13) & 0x1; + chip->patch_6m_band_edge = (value >> 21) & 0x1; + + dev_dbg_f(zd_chip_dev(chip), + "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d " + "patch 6M %d\n", + zd_rf_name(*rf_type), *rf_type, + chip->pa_type, chip->patch_cck_gain, + chip->patch_cr157, chip->patch_6m_band_edge); + return 0; +error: + *rf_type = 0; + chip->pa_type = 0; + chip->patch_cck_gain = 0; + chip->patch_cr157 = 0; + chip->patch_6m_band_edge = 0; + return r; +} + +static int _read_mac_addr(struct zd_chip *chip, u8 *mac_addr, + const zd_addr_t *addr) +{ + int r; + u32 parts[2]; + + r = zd_ioread32v_locked(chip, parts, (const zd_addr_t *)addr, 2); + if (r) { + dev_dbg_f(zd_chip_dev(chip), + "error: couldn't read e2p macs. Error number %d\n", r); + return r; + } + + mac_addr[0] = parts[0]; + mac_addr[1] = parts[0] >> 8; + mac_addr[2] = parts[0] >> 16; + mac_addr[3] = parts[0] >> 24; + mac_addr[4] = parts[1]; + mac_addr[5] = parts[1] >> 8; + + return 0; +} + +static int read_e2p_mac_addr(struct zd_chip *chip) +{ + static const zd_addr_t addr[2] = { E2P_MAC_ADDR_P1, E2P_MAC_ADDR_P2 }; + + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + return _read_mac_addr(chip, chip->e2p_mac, (const zd_addr_t *)addr); +} + +/* MAC address: if custom mac addresses are to to be used CR_MAC_ADDR_P1 and + * CR_MAC_ADDR_P2 must be overwritten + */ +void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr) +{ + mutex_lock(&chip->mutex); + memcpy(mac_addr, chip->e2p_mac, ETH_ALEN); + mutex_unlock(&chip->mutex); +} + +static int read_mac_addr(struct zd_chip *chip, u8 *mac_addr) +{ + static const zd_addr_t addr[2] = { CR_MAC_ADDR_P1, CR_MAC_ADDR_P2 }; + return _read_mac_addr(chip, mac_addr, (const zd_addr_t *)addr); +} + +int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr) +{ + int r; + + dev_dbg_f(zd_chip_dev(chip), "\n"); + mutex_lock(&chip->mutex); + r = read_mac_addr(chip, mac_addr); + mutex_unlock(&chip->mutex); + return r; +} + +int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr) +{ + int r; + struct zd_ioreq32 reqs[2] = { + [0] = { .addr = CR_MAC_ADDR_P1 }, + [1] = { .addr = CR_MAC_ADDR_P2 }, + }; + + reqs[0].value = (mac_addr[3] << 24) + | (mac_addr[2] << 16) + | (mac_addr[1] << 8) + | mac_addr[0]; + reqs[1].value = (mac_addr[5] << 8) + | mac_addr[4]; + + dev_dbg_f(zd_chip_dev(chip), + "mac addr " MAC_FMT "\n", MAC_ARG(mac_addr)); + + mutex_lock(&chip->mutex); + r = zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs)); +#ifdef DEBUG + { + u8 tmp[ETH_ALEN]; + read_mac_addr(chip, tmp); + } +#endif /* DEBUG */ + mutex_unlock(&chip->mutex); + return r; +} + +int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain) +{ + int r; + u32 value; + + mutex_lock(&chip->mutex); + r = zd_ioread32_locked(chip, &value, E2P_SUBID); + mutex_unlock(&chip->mutex); + if (r) + return r; + + *regdomain = value >> 16; + dev_dbg_f(zd_chip_dev(chip), "regdomain: %#04x\n", *regdomain); + + return 0; +} + +static int read_values(struct zd_chip *chip, u8 *values, size_t count, + zd_addr_t e2p_addr, u32 guard) +{ + int r; + int i; + u32 v; + + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + for (i = 0;;) { + r = zd_ioread32_locked(chip, &v, e2p_addr+i/2); + if (r) + return r; + v -= guard; + if (i+4 < count) { + values[i++] = v; + values[i++] = v >> 8; + values[i++] = v >> 16; + values[i++] = v >> 24; + continue; + } + for (;i < count; i++) + values[i] = v >> (8*(i%3)); + return 0; + } +} + +static int read_pwr_cal_values(struct zd_chip *chip) +{ + return read_values(chip, chip->pwr_cal_values, + E2P_CHANNEL_COUNT, E2P_PWR_CAL_VALUE1, + 0); +} + +static int read_pwr_int_values(struct zd_chip *chip) +{ + return read_values(chip, chip->pwr_int_values, + E2P_CHANNEL_COUNT, E2P_PWR_INT_VALUE1, + E2P_PWR_INT_GUARD); +} + +static int read_ofdm_cal_values(struct zd_chip *chip) +{ + int r; + int i; + static const zd_addr_t addresses[] = { + E2P_36M_CAL_VALUE1, + E2P_48M_CAL_VALUE1, + E2P_54M_CAL_VALUE1, + }; + + for (i = 0; i < 3; i++) { + r = read_values(chip, chip->ofdm_cal_values[i], + E2P_CHANNEL_COUNT, addresses[i], 0); + if (r) + return r; + } + return 0; +} + +static int read_cal_int_tables(struct zd_chip *chip) +{ + int r; + + r = read_pwr_cal_values(chip); + if (r) + return r; + r = read_pwr_int_values(chip); + if (r) + return r; + r = read_ofdm_cal_values(chip); + if (r) + return r; + return 0; +} + +/* phy means physical registers */ +int zd_chip_lock_phy_regs(struct zd_chip *chip) +{ + int r; + u32 tmp; + + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + r = zd_ioread32_locked(chip, &tmp, CR_REG1); + if (r) { + dev_err(zd_chip_dev(chip), "error ioread32(CR_REG1): %d\n", r); + return r; + } + + dev_dbg_f(zd_chip_dev(chip), + "CR_REG1: 0x%02x -> 0x%02x\n", tmp, tmp & ~UNLOCK_PHY_REGS); + tmp &= ~UNLOCK_PHY_REGS; + + r = zd_iowrite32_locked(chip, tmp, CR_REG1); + if (r) + dev_err(zd_chip_dev(chip), "error iowrite32(CR_REG1): %d\n", r); + return r; +} + +int zd_chip_unlock_phy_regs(struct zd_chip *chip) +{ + int r; + u32 tmp; + + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + r = zd_ioread32_locked(chip, &tmp, CR_REG1); + if (r) { + dev_err(zd_chip_dev(chip), + "error ioread32(CR_REG1): %d\n", r); + return r; + } + + dev_dbg_f(zd_chip_dev(chip), + "CR_REG1: 0x%02x -> 0x%02x\n", tmp, tmp | UNLOCK_PHY_REGS); + tmp |= UNLOCK_PHY_REGS; + + r = zd_iowrite32_locked(chip, tmp, CR_REG1); + if (r) + dev_err(zd_chip_dev(chip), "error iowrite32(CR_REG1): %d\n", r); + return r; +} + +/* CR157 can be optionally patched by the EEPROM */ +static int patch_cr157(struct zd_chip *chip) +{ + int r; + u32 value; + + if (!chip->patch_cr157) + return 0; + + r = zd_ioread32_locked(chip, &value, E2P_PHY_REG); + if (r) + return r; + + dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value >> 8); + return zd_iowrite32_locked(chip, value >> 8, CR157); +} + +/* + * 6M band edge can be optionally overwritten for certain RF's + * Vendor driver says: for FCC regulation, enabled per HWFeature 6M band edge + * bit (for AL2230, AL2230S) + */ +static int patch_6m_band_edge(struct zd_chip *chip, int channel) +{ + struct zd_ioreq16 ioreqs[] = { + { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, + { CR47, 0x1e }, + }; + + if (!chip->patch_6m_band_edge || !chip->rf.patch_6m_band_edge) + return 0; + + /* FIXME: Channel 11 is not the edge for all regulatory domains. */ + if (channel == 1 || channel == 11) + ioreqs[0].value = 0x12; + + dev_dbg_f(zd_chip_dev(chip), "patching for channel %d\n", channel); + return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); +} + +static int zd1211_hw_reset_phy(struct zd_chip *chip) +{ + static const struct zd_ioreq16 ioreqs[] = { + { CR0, 0x0a }, { CR1, 0x06 }, { CR2, 0x26 }, + { CR3, 0x38 }, { CR4, 0x80 }, { CR9, 0xa0 }, + { CR10, 0x81 }, { CR11, 0x00 }, { CR12, 0x7f }, + { CR13, 0x8c }, { CR14, 0x80 }, { CR15, 0x3d }, + { CR16, 0x20 }, { CR17, 0x1e }, { CR18, 0x0a }, + { CR19, 0x48 }, { CR20, 0x0c }, { CR21, 0x0c }, + { CR22, 0x23 }, { CR23, 0x90 }, { CR24, 0x14 }, + { CR25, 0x40 }, { CR26, 0x10 }, { CR27, 0x19 }, + { CR28, 0x7f }, { CR29, 0x80 }, { CR30, 0x4b }, + { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, + { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, + { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, + { CR40, 0x84 }, { CR41, 0x2a }, { CR42, 0x80 }, + { CR43, 0x10 }, { CR44, 0x12 }, { CR46, 0xff }, + { CR47, 0x1E }, { CR48, 0x26 }, { CR49, 0x5b }, + { CR64, 0xd0 }, { CR65, 0x04 }, { CR66, 0x58 }, + { CR67, 0xc9 }, { CR68, 0x88 }, { CR69, 0x41 }, + { CR70, 0x23 }, { CR71, 0x10 }, { CR72, 0xff }, + { CR73, 0x32 }, { CR74, 0x30 }, { CR75, 0x65 }, + { CR76, 0x41 }, { CR77, 0x1b }, { CR78, 0x30 }, + { CR79, 0x68 }, { CR80, 0x64 }, { CR81, 0x64 }, + { CR82, 0x00 }, { CR83, 0x00 }, { CR84, 0x00 }, + { CR85, 0x02 }, { CR86, 0x00 }, { CR87, 0x00 }, + { CR88, 0xff }, { CR89, 0xfc }, { CR90, 0x00 }, + { CR91, 0x00 }, { CR92, 0x00 }, { CR93, 0x08 }, + { CR94, 0x00 }, { CR95, 0x00 }, { CR96, 0xff }, + { CR97, 0xe7 }, { CR98, 0x00 }, { CR99, 0x00 }, + { CR100, 0x00 }, { CR101, 0xae }, { CR102, 0x02 }, + { CR103, 0x00 }, { CR104, 0x03 }, { CR105, 0x65 }, + { CR106, 0x04 }, { CR107, 0x00 }, { CR108, 0x0a }, + { CR109, 0xaa }, { CR110, 0xaa }, { CR111, 0x25 }, + { CR112, 0x25 }, { CR113, 0x00 }, { CR119, 0x1e }, + { CR125, 0x90 }, { CR126, 0x00 }, { CR127, 0x00 }, + { }, + { CR5, 0x00 }, { CR6, 0x00 }, { CR7, 0x00 }, + { CR8, 0x00 }, { CR9, 0x20 }, { CR12, 0xf0 }, + { CR20, 0x0e }, { CR21, 0x0e }, { CR27, 0x10 }, + { CR44, 0x33 }, { CR47, 0x1E }, { CR83, 0x24 }, + { CR84, 0x04 }, { CR85, 0x00 }, { CR86, 0x0C }, + { CR87, 0x12 }, { CR88, 0x0C }, { CR89, 0x00 }, + { CR90, 0x10 }, { CR91, 0x08 }, { CR93, 0x00 }, + { CR94, 0x01 }, { CR95, 0x00 }, { CR96, 0x50 }, + { CR97, 0x37 }, { CR98, 0x35 }, { CR101, 0x13 }, + { CR102, 0x27 }, { CR103, 0x27 }, { CR104, 0x18 }, + { CR105, 0x12 }, { CR109, 0x27 }, { CR110, 0x27 }, + { CR111, 0x27 }, { CR112, 0x27 }, { CR113, 0x27 }, + { CR114, 0x27 }, { CR115, 0x26 }, { CR116, 0x24 }, + { CR117, 0xfc }, { CR118, 0xfa }, { CR120, 0x4f }, + { CR123, 0x27 }, { CR125, 0xaa }, { CR127, 0x03 }, + { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, + { CR131, 0x0C }, { CR136, 0xdf }, { CR137, 0x40 }, + { CR138, 0xa0 }, { CR139, 0xb0 }, { CR140, 0x99 }, + { CR141, 0x82 }, { CR142, 0x54 }, { CR143, 0x1c }, + { CR144, 0x6c }, { CR147, 0x07 }, { CR148, 0x4c }, + { CR149, 0x50 }, { CR150, 0x0e }, { CR151, 0x18 }, + { CR160, 0xfe }, { CR161, 0xee }, { CR162, 0xaa }, + { CR163, 0xfa }, { CR164, 0xfa }, { CR165, 0xea }, + { CR166, 0xbe }, { CR167, 0xbe }, { CR168, 0x6a }, + { CR169, 0xba }, { CR170, 0xba }, { CR171, 0xba }, + /* Note: CR204 must lead the CR203 */ + { CR204, 0x7d }, + { }, + { CR203, 0x30 }, + }; + + int r, t; + + dev_dbg_f(zd_chip_dev(chip), "\n"); + + r = zd_chip_lock_phy_regs(chip); + if (r) + goto out; + + r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); + if (r) + goto unlock; + + r = patch_cr157(chip); +unlock: + t = zd_chip_unlock_phy_regs(chip); + if (t && !r) + r = t; +out: + return r; +} + +static int zd1211b_hw_reset_phy(struct zd_chip *chip) +{ + static const struct zd_ioreq16 ioreqs[] = { + { CR0, 0x14 }, { CR1, 0x06 }, { CR2, 0x26 }, + { CR3, 0x38 }, { CR4, 0x80 }, { CR9, 0xe0 }, + { CR10, 0x81 }, + /* power control { { CR11, 1 << 6 }, */ + { CR11, 0x00 }, + { CR12, 0xf0 }, { CR13, 0x8c }, { CR14, 0x80 }, + { CR15, 0x3d }, { CR16, 0x20 }, { CR17, 0x1e }, + { CR18, 0x0a }, { CR19, 0x48 }, + { CR20, 0x10 }, /* Org:0x0E, ComTrend:RalLink AP */ + { CR21, 0x0e }, { CR22, 0x23 }, { CR23, 0x90 }, + { CR24, 0x14 }, { CR25, 0x40 }, { CR26, 0x10 }, + { CR27, 0x10 }, { CR28, 0x7f }, { CR29, 0x80 }, + { CR30, 0x4b }, /* ASIC/FWT, no jointly decoder */ + { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, + { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, + { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, + { CR40, 0x84 }, { CR41, 0x2a }, { CR42, 0x80 }, + { CR43, 0x10 }, { CR44, 0x33 }, { CR46, 0xff }, + { CR47, 0x1E }, { CR48, 0x26 }, { CR49, 0x5b }, + { CR64, 0xd0 }, { CR65, 0x04 }, { CR66, 0x58 }, + { CR67, 0xc9 }, { CR68, 0x88 }, { CR69, 0x41 }, + { CR70, 0x23 }, { CR71, 0x10 }, { CR72, 0xff }, + { CR73, 0x32 }, { CR74, 0x30 }, { CR75, 0x65 }, + { CR76, 0x41 }, { CR77, 0x1b }, { CR78, 0x30 }, + { CR79, 0xf0 }, { CR80, 0x64 }, { CR81, 0x64 }, + { CR82, 0x00 }, { CR83, 0x24 }, { CR84, 0x04 }, + { CR85, 0x00 }, { CR86, 0x0c }, { CR87, 0x12 }, + { CR88, 0x0c }, { CR89, 0x00 }, { CR90, 0x58 }, + { CR91, 0x04 }, { CR92, 0x00 }, { CR93, 0x00 }, + { CR94, 0x01 }, + { CR95, 0x20 }, /* ZD1211B */ + { CR96, 0x50 }, { CR97, 0x37 }, { CR98, 0x35 }, + { CR99, 0x00 }, { CR100, 0x01 }, { CR101, 0x13 }, + { CR102, 0x27 }, { CR103, 0x27 }, { CR104, 0x18 }, + { CR105, 0x12 }, { CR106, 0x04 }, { CR107, 0x00 }, + { CR108, 0x0a }, { CR109, 0x27 }, { CR110, 0x27 }, + { CR111, 0x27 }, { CR112, 0x27 }, { CR113, 0x27 }, + { CR114, 0x27 }, { CR115, 0x26 }, { CR116, 0x24 }, + { CR117, 0xfc }, { CR118, 0xfa }, { CR119, 0x1e }, + { CR125, 0x90 }, { CR126, 0x00 }, { CR127, 0x00 }, + { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, + { CR131, 0x0c }, { CR136, 0xdf }, { CR137, 0xa0 }, + { CR138, 0xa8 }, { CR139, 0xb4 }, { CR140, 0x98 }, + { CR141, 0x82 }, { CR142, 0x53 }, { CR143, 0x1c }, + { CR144, 0x6c }, { CR147, 0x07 }, { CR148, 0x40 }, + { CR149, 0x40 }, /* Org:0x50 ComTrend:RalLink AP */ + { CR150, 0x14 }, /* Org:0x0E ComTrend:RalLink AP */ + { CR151, 0x18 }, { CR159, 0x70 }, { CR160, 0xfe }, + { CR161, 0xee }, { CR162, 0xaa }, { CR163, 0xfa }, + { CR164, 0xfa }, { CR165, 0xea }, { CR166, 0xbe }, + { CR167, 0xbe }, { CR168, 0x6a }, { CR169, 0xba }, + { CR170, 0xba }, { CR171, 0xba }, + /* Note: CR204 must lead the CR203 */ + { CR204, 0x7d }, + {}, + { CR203, 0x30 }, + }; + + int r, t; + + dev_dbg_f(zd_chip_dev(chip), "\n"); + + r = zd_chip_lock_phy_regs(chip); + if (r) + goto out; + + r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); + if (r) + goto unlock; + + r = patch_cr157(chip); +unlock: + t = zd_chip_unlock_phy_regs(chip); + if (t && !r) + r = t; +out: + return r; +} + +static int hw_reset_phy(struct zd_chip *chip) +{ + return chip->is_zd1211b ? zd1211b_hw_reset_phy(chip) : + zd1211_hw_reset_phy(chip); +} + +static int zd1211_hw_init_hmac(struct zd_chip *chip) +{ + static const struct zd_ioreq32 ioreqs[] = { + { CR_ACK_TIMEOUT_EXT, 0x20 }, + { CR_ADDA_MBIAS_WARMTIME, 0x30000808 }, + { CR_ZD1211_RETRY_MAX, 0x2 }, + { CR_SNIFFER_ON, 0 }, + { CR_RX_FILTER, STA_RX_FILTER }, + { CR_GROUP_HASH_P1, 0x00 }, + { CR_GROUP_HASH_P2, 0x80000000 }, + { CR_REG1, 0xa4 }, + { CR_ADDA_PWR_DWN, 0x7f }, + { CR_BCN_PLCP_CFG, 0x00f00401 }, + { CR_PHY_DELAY, 0x00 }, + { CR_ACK_TIMEOUT_EXT, 0x80 }, + { CR_ADDA_PWR_DWN, 0x00 }, + { CR_ACK_TIME_80211, 0x100 }, + { CR_IFS_VALUE, 0x547c032 }, + { CR_RX_PE_DELAY, 0x70 }, + { CR_PS_CTRL, 0x10000000 }, + { CR_RTS_CTS_RATE, 0x02030203 }, + { CR_RX_THRESHOLD, 0x000c0640 }, + { CR_AFTER_PNP, 0x1 }, + { CR_WEP_PROTECT, 0x114 }, + }; + + int r; + + dev_dbg_f(zd_chip_dev(chip), "\n"); + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); +#ifdef DEBUG + if (r) { + dev_err(zd_chip_dev(chip), + "error in zd_iowrite32a_locked. Error number %d\n", r); + } +#endif /* DEBUG */ + return r; +} + +static int zd1211b_hw_init_hmac(struct zd_chip *chip) +{ + static const struct zd_ioreq32 ioreqs[] = { + { CR_ACK_TIMEOUT_EXT, 0x20 }, + { CR_ADDA_MBIAS_WARMTIME, 0x30000808 }, + { CR_ZD1211B_RETRY_MAX, 0x02020202 }, + { CR_ZD1211B_TX_PWR_CTL4, 0x007f003f }, + { CR_ZD1211B_TX_PWR_CTL3, 0x007f003f }, + { CR_ZD1211B_TX_PWR_CTL2, 0x003f001f }, + { CR_ZD1211B_TX_PWR_CTL1, 0x001f000f }, + { CR_ZD1211B_AIFS_CTL1, 0x00280028 }, + { CR_ZD1211B_AIFS_CTL2, 0x008C003C }, + { CR_ZD1211B_TXOP, 0x01800824 }, + { CR_SNIFFER_ON, 0 }, + { CR_RX_FILTER, STA_RX_FILTER }, + { CR_GROUP_HASH_P1, 0x00 }, + { CR_GROUP_HASH_P2, 0x80000000 }, + { CR_REG1, 0xa4 }, + { CR_ADDA_PWR_DWN, 0x7f }, + { CR_BCN_PLCP_CFG, 0x00f00401 }, + { CR_PHY_DELAY, 0x00 }, + { CR_ACK_TIMEOUT_EXT, 0x80 }, + { CR_ADDA_PWR_DWN, 0x00 }, + { CR_ACK_TIME_80211, 0x100 }, + { CR_IFS_VALUE, 0x547c032 }, + { CR_RX_PE_DELAY, 0x70 }, + { CR_PS_CTRL, 0x10000000 }, + { CR_RTS_CTS_RATE, 0x02030203 }, + { CR_RX_THRESHOLD, 0x000c0640 }, + { CR_AFTER_PNP, 0x1 }, + { CR_WEP_PROTECT, 0x114 }, + }; + + int r; + + dev_dbg_f(zd_chip_dev(chip), "\n"); + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); + if (r) { + dev_dbg_f(zd_chip_dev(chip), + "error in zd_iowrite32a_locked. Error number %d\n", r); + } + return r; +} + +static int hw_init_hmac(struct zd_chip *chip) +{ + return chip->is_zd1211b ? + zd1211b_hw_init_hmac(chip) : zd1211_hw_init_hmac(chip); +} + +struct aw_pt_bi { + u32 atim_wnd_period; + u32 pre_tbtt; + u32 beacon_interval; +}; + +static int get_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s) +{ + int r; + static const zd_addr_t aw_pt_bi_addr[] = + { CR_ATIM_WND_PERIOD, CR_PRE_TBTT, CR_BCN_INTERVAL }; + u32 values[3]; + + r = zd_ioread32v_locked(chip, values, (const zd_addr_t *)aw_pt_bi_addr, + ARRAY_SIZE(aw_pt_bi_addr)); + if (r) { + memset(s, 0, sizeof(*s)); + return r; + } + + s->atim_wnd_period = values[0]; + s->pre_tbtt = values[1]; + s->beacon_interval = values[2]; + dev_dbg_f(zd_chip_dev(chip), "aw %u pt %u bi %u\n", + s->atim_wnd_period, s->pre_tbtt, s->beacon_interval); + return 0; +} + +static int set_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s) +{ + struct zd_ioreq32 reqs[3]; + + if (s->beacon_interval <= 5) + s->beacon_interval = 5; + if (s->pre_tbtt < 4 || s->pre_tbtt >= s->beacon_interval) + s->pre_tbtt = s->beacon_interval - 1; + if (s->atim_wnd_period >= s->pre_tbtt) + s->atim_wnd_period = s->pre_tbtt - 1; + + reqs[0].addr = CR_ATIM_WND_PERIOD; + reqs[0].value = s->atim_wnd_period; + reqs[1].addr = CR_PRE_TBTT; + reqs[1].value = s->pre_tbtt; + reqs[2].addr = CR_BCN_INTERVAL; + reqs[2].value = s->beacon_interval; + + dev_dbg_f(zd_chip_dev(chip), + "aw %u pt %u bi %u\n", s->atim_wnd_period, s->pre_tbtt, + s->beacon_interval); + return zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs)); +} + + +static int set_beacon_interval(struct zd_chip *chip, u32 interval) +{ + int r; + struct aw_pt_bi s; + + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + r = get_aw_pt_bi(chip, &s); + if (r) + return r; + s.beacon_interval = interval; + return set_aw_pt_bi(chip, &s); +} + +int zd_set_beacon_interval(struct zd_chip *chip, u32 interval) +{ + int r; + + mutex_lock(&chip->mutex); + r = set_beacon_interval(chip, interval); + mutex_unlock(&chip->mutex); + return r; +} + +static int hw_init(struct zd_chip *chip) +{ + int r; + + dev_dbg_f(zd_chip_dev(chip), "\n"); + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + r = hw_reset_phy(chip); + if (r) + return r; + + r = hw_init_hmac(chip); + if (r) + return r; + r = set_beacon_interval(chip, 100); + if (r) + return r; + return 0; +} + +#ifdef DEBUG +static int dump_cr(struct zd_chip *chip, const zd_addr_t addr, + const char *addr_string) +{ + int r; + u32 value; + + r = zd_ioread32_locked(chip, &value, addr); + if (r) { + dev_dbg_f(zd_chip_dev(chip), + "error reading %s. Error number %d\n", addr_string, r); + return r; + } + + dev_dbg_f(zd_chip_dev(chip), "%s %#010x\n", + addr_string, (unsigned int)value); + return 0; +} + +static int test_init(struct zd_chip *chip) +{ + int r; + + r = dump_cr(chip, CR_AFTER_PNP, "CR_AFTER_PNP"); + if (r) + return r; + r = dump_cr(chip, CR_GPI_EN, "CR_GPI_EN"); + if (r) + return r; + return dump_cr(chip, CR_INTERRUPT, "CR_INTERRUPT"); +} + +static void dump_fw_registers(struct zd_chip *chip) +{ + static const zd_addr_t addr[4] = { + FW_FIRMWARE_VER, FW_USB_SPEED, FW_FIX_TX_RATE, + FW_LINK_STATUS + }; + + int r; + u16 values[4]; + + r = zd_ioread16v_locked(chip, values, (const zd_addr_t*)addr, + ARRAY_SIZE(addr)); + if (r) { + dev_dbg_f(zd_chip_dev(chip), "error %d zd_ioread16v_locked\n", + r); + return; + } + + dev_dbg_f(zd_chip_dev(chip), "FW_FIRMWARE_VER %#06hx\n", values[0]); + dev_dbg_f(zd_chip_dev(chip), "FW_USB_SPEED %#06hx\n", values[1]); + dev_dbg_f(zd_chip_dev(chip), "FW_FIX_TX_RATE %#06hx\n", values[2]); + dev_dbg_f(zd_chip_dev(chip), "FW_LINK_STATUS %#06hx\n", values[3]); +} +#endif /* DEBUG */ + +static int print_fw_version(struct zd_chip *chip) +{ + int r; + u16 version; + + r = zd_ioread16_locked(chip, &version, FW_FIRMWARE_VER); + if (r) + return r; + + dev_info(zd_chip_dev(chip),"firmware version %04hx\n", version); + return 0; +} + +static int set_mandatory_rates(struct zd_chip *chip, enum ieee80211_std std) +{ + u32 rates; + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + /* This sets the mandatory rates, which only depend from the standard + * that the device is supporting. Until further notice we should try + * to support 802.11g also for full speed USB. + */ + switch (std) { + case IEEE80211B: + rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M; + break; + case IEEE80211G: + rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M| + CR_RATE_6M|CR_RATE_12M|CR_RATE_24M; + break; + default: + return -EINVAL; + } + return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL); +} + +int zd_chip_enable_hwint(struct zd_chip *chip) +{ + int r; + + mutex_lock(&chip->mutex); + r = zd_iowrite32_locked(chip, HWINT_ENABLED, CR_INTERRUPT); + mutex_unlock(&chip->mutex); + return r; +} + +static int disable_hwint(struct zd_chip *chip) +{ + return zd_iowrite32_locked(chip, HWINT_DISABLED, CR_INTERRUPT); +} + +int zd_chip_disable_hwint(struct zd_chip *chip) +{ + int r; + + mutex_lock(&chip->mutex); + r = disable_hwint(chip); + mutex_unlock(&chip->mutex); + return r; +} + +int zd_chip_init_hw(struct zd_chip *chip, u8 device_type) +{ + int r; + u8 rf_type; + + dev_dbg_f(zd_chip_dev(chip), "\n"); + + mutex_lock(&chip->mutex); + chip->is_zd1211b = (device_type == DEVICE_ZD1211B) != 0; + +#ifdef DEBUG + r = test_init(chip); + if (r) + goto out; +#endif + r = zd_iowrite32_locked(chip, 1, CR_AFTER_PNP); + if (r) + goto out; + + r = zd_usb_init_hw(&chip->usb); + if (r) + goto out; + + /* GPI is always disabled, also in the other driver. + */ + r = zd_iowrite32_locked(chip, 0, CR_GPI_EN); + if (r) + goto out; + r = zd_iowrite32_locked(chip, CWIN_SIZE, CR_CWMIN_CWMAX); + if (r) + goto out; + /* Currently we support IEEE 802.11g for full and high speed USB. + * It might be discussed, whether we should suppport pure b mode for + * full speed USB. + */ + r = set_mandatory_rates(chip, IEEE80211G); + if (r) + goto out; + /* Disabling interrupts is certainly a smart thing here. + */ + r = disable_hwint(chip); + if (r) + goto out; + r = read_pod(chip, &rf_type); + if (r) + goto out; + r = hw_init(chip); + if (r) + goto out; + r = zd_rf_init_hw(&chip->rf, rf_type); + if (r) + goto out; + + r = print_fw_version(chip); + if (r) + goto out; + +#ifdef DEBUG + dump_fw_registers(chip); + r = test_init(chip); + if (r) + goto out; +#endif /* DEBUG */ + + r = read_e2p_mac_addr(chip); + if (r) + goto out; + + r = read_cal_int_tables(chip); + if (r) + goto out; + + print_id(chip); +out: + mutex_unlock(&chip->mutex); + return r; +} + +static int update_pwr_int(struct zd_chip *chip, u8 channel) +{ + u8 value = chip->pwr_int_values[channel - 1]; + dev_dbg_f(zd_chip_dev(chip), "channel %d pwr_int %#04x\n", + channel, value); + return zd_iowrite32_locked(chip, value, CR31); +} + +static int update_pwr_cal(struct zd_chip *chip, u8 channel) +{ + u8 value = chip->pwr_cal_values[channel-1]; + dev_dbg_f(zd_chip_dev(chip), "channel %d pwr_cal %#04x\n", + channel, value); + return zd_iowrite32_locked(chip, value, CR68); +} + +static int update_ofdm_cal(struct zd_chip *chip, u8 channel) +{ + struct zd_ioreq32 ioreqs[3]; + + ioreqs[0].addr = CR67; + ioreqs[0].value = chip->ofdm_cal_values[OFDM_36M_INDEX][channel-1]; + ioreqs[1].addr = CR66; + ioreqs[1].value = chip->ofdm_cal_values[OFDM_48M_INDEX][channel-1]; + ioreqs[2].addr = CR65; + ioreqs[2].value = chip->ofdm_cal_values[OFDM_54M_INDEX][channel-1]; + + dev_dbg_f(zd_chip_dev(chip), + "channel %d ofdm_cal 36M %#04x 48M %#04x 54M %#04x\n", + channel, ioreqs[0].value, ioreqs[1].value, ioreqs[2].value); + return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); +} + +static int update_channel_integration_and_calibration(struct zd_chip *chip, + u8 channel) +{ + int r; + + r = update_pwr_int(chip, channel); + if (r) + return r; + if (chip->is_zd1211b) { + static const struct zd_ioreq32 ioreqs[] = { + { CR69, 0x28 }, + {}, + { CR69, 0x2a }, + }; + + r = update_ofdm_cal(chip, channel); + if (r) + return r; + r = update_pwr_cal(chip, channel); + if (r) + return r; + r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); + if (r) + return r; + } + + return 0; +} + +/* The CCK baseband gain can be optionally patched by the EEPROM */ +static int patch_cck_gain(struct zd_chip *chip) +{ + int r; + u32 value; + + if (!chip->patch_cck_gain) + return 0; + + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + r = zd_ioread32_locked(chip, &value, E2P_PHY_REG); + if (r) + return r; + dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value & 0xff); + return zd_iowrite32_locked(chip, value & 0xff, CR47); +} + +int zd_chip_set_channel(struct zd_chip *chip, u8 channel) +{ + int r, t; + + mutex_lock(&chip->mutex); + r = zd_chip_lock_phy_regs(chip); + if (r) + goto out; + r = zd_rf_set_channel(&chip->rf, channel); + if (r) + goto unlock; + r = update_channel_integration_and_calibration(chip, channel); + if (r) + goto unlock; + r = patch_cck_gain(chip); + if (r) + goto unlock; + r = patch_6m_band_edge(chip, channel); + if (r) + goto unlock; + r = zd_iowrite32_locked(chip, 0, CR_CONFIG_PHILIPS); +unlock: + t = zd_chip_unlock_phy_regs(chip); + if (t && !r) + r = t; +out: + mutex_unlock(&chip->mutex); + return r; +} + +u8 zd_chip_get_channel(struct zd_chip *chip) +{ + u8 channel; + + mutex_lock(&chip->mutex); + channel = chip->rf.channel; + mutex_unlock(&chip->mutex); + return channel; +} + +static u16 led_mask(int led) +{ + switch (led) { + case 1: + return LED1; + case 2: + return LED2; + default: + return 0; + } +} + +static int read_led_reg(struct zd_chip *chip, u16 *status) +{ + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + return zd_ioread16_locked(chip, status, CR_LED); +} + +static int write_led_reg(struct zd_chip *chip, u16 status) +{ + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + return zd_iowrite16_locked(chip, status, CR_LED); +} + +int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status) +{ + int r, ret; + u16 mask = led_mask(led); + u16 reg; + + if (!mask) + return -EINVAL; + mutex_lock(&chip->mutex); + r = read_led_reg(chip, ®); + if (r) + return r; + switch (status) { + case LED_STATUS: + return (reg & mask) ? LED_ON : LED_OFF; + case LED_OFF: + reg &= ~mask; + ret = LED_OFF; + break; + case LED_FLIP: + reg ^= mask; + ret = (reg&mask) ? LED_ON : LED_OFF; + break; + case LED_ON: + reg |= mask; + ret = LED_ON; + break; + default: + return -EINVAL; + } + r = write_led_reg(chip, reg); + if (r) { + ret = r; + goto out; + } +out: + mutex_unlock(&chip->mutex); + return r; +} + +int zd_chip_led_flip(struct zd_chip *chip, int led, + const unsigned int *phases_msecs, unsigned int count) +{ + int i, r; + enum led_status status; + + r = zd_chip_led_status(chip, led, LED_STATUS); + if (r) + return r; + status = r; + for (i = 0; i < count; i++) { + r = zd_chip_led_status(chip, led, LED_FLIP); + if (r < 0) + goto out; + msleep(phases_msecs[i]); + } + +out: + zd_chip_led_status(chip, led, status); + return r; +} + +int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates) +{ + int r; + + if (cr_rates & ~(CR_RATES_80211B|CR_RATES_80211G)) + return -EINVAL; + + mutex_lock(&chip->mutex); + r = zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL); + mutex_unlock(&chip->mutex); + return r; +} + +static int ofdm_qual_db(u8 status_quality, u8 rate, unsigned int size) +{ + static const u16 constants[] = { + 715, 655, 585, 540, 470, 410, 360, 315, + 270, 235, 205, 175, 150, 125, 105, 85, + 65, 50, 40, 25, 15 + }; + + int i; + u32 x; + + /* It seems that their quality parameter is somehow per signal + * and is now transferred per bit. + */ + switch (rate) { + case ZD_OFDM_RATE_6M: + case ZD_OFDM_RATE_12M: + case ZD_OFDM_RATE_24M: + size *= 2; + break; + case ZD_OFDM_RATE_9M: + case ZD_OFDM_RATE_18M: + case ZD_OFDM_RATE_36M: + case ZD_OFDM_RATE_54M: + size *= 4; + size /= 3; + break; + case ZD_OFDM_RATE_48M: + size *= 3; + size /= 2; + break; + default: + return -EINVAL; + } + + x = (10000 * status_quality)/size; + for (i = 0; i < ARRAY_SIZE(constants); i++) { + if (x > constants[i]) + break; + } + + switch (rate) { + case ZD_OFDM_RATE_6M: + case ZD_OFDM_RATE_9M: + i += 3; + break; + case ZD_OFDM_RATE_12M: + case ZD_OFDM_RATE_18M: + i += 5; + break; + case ZD_OFDM_RATE_24M: + case ZD_OFDM_RATE_36M: + i += 9; + break; + case ZD_OFDM_RATE_48M: + case ZD_OFDM_RATE_54M: + i += 15; + break; + default: + return -EINVAL; + } + + return i; +} + +static int ofdm_qual_percent(u8 status_quality, u8 rate, unsigned int size) +{ + int r; + + r = ofdm_qual_db(status_quality, rate, size); + ZD_ASSERT(r >= 0); + if (r < 0) + r = 0; + + r = (r * 100)/29; + return r <= 100 ? r : 100; +} + +static unsigned int log10times100(unsigned int x) +{ + static const u8 log10[] = { + 0, + 0, 30, 47, 60, 69, 77, 84, 90, 95, 100, + 104, 107, 111, 114, 117, 120, 123, 125, 127, 130, + 132, 134, 136, 138, 139, 141, 143, 144, 146, 147, + 149, 150, 151, 153, 154, 155, 156, 157, 159, 160, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 169, + 170, 171, 172, 173, 174, 174, 175, 176, 177, 177, + 178, 179, 179, 180, 181, 181, 182, 183, 183, 184, + 185, 185, 186, 186, 187, 188, 188, 189, 189, 190, + 190, 191, 191, 192, 192, 193, 193, 194, 194, 195, + 195, 196, 196, 197, 197, 198, 198, 199, 199, 200, + 200, 200, 201, 201, 202, 202, 202, 203, 203, 204, + 204, 204, 205, 205, 206, 206, 206, 207, 207, 207, + 208, 208, 208, 209, 209, 210, 210, 210, 211, 211, + 211, 212, 212, 212, 213, 213, 213, 213, 214, 214, + 214, 215, 215, 215, 216, 216, 216, 217, 217, 217, + 217, 218, 218, 218, 219, 219, 219, 219, 220, 220, + 220, 220, 221, 221, 221, 222, 222, 222, 222, 223, + 223, 223, 223, 224, 224, 224, 224, + }; + + return x < ARRAY_SIZE(log10) ? log10[x] : 225; +} + +enum { + MAX_CCK_EVM_DB = 45, +}; + +static int cck_evm_db(u8 status_quality) +{ + return (20 * log10times100(status_quality)) / 100; +} + +static int cck_snr_db(u8 status_quality) +{ + int r = MAX_CCK_EVM_DB - cck_evm_db(status_quality); + ZD_ASSERT(r >= 0); + return r; +} + +static int cck_qual_percent(u8 status_quality) +{ + int r; + + r = cck_snr_db(status_quality); + r = (100*r)/17; + return r <= 100 ? r : 100; +} + +u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, + const struct rx_status *status) +{ + return (status->frame_status&ZD_RX_OFDM) ? + ofdm_qual_percent(status->signal_quality_ofdm, + zd_ofdm_plcp_header_rate(rx_frame), + size) : + cck_qual_percent(status->signal_quality_cck); +} + +u8 zd_rx_strength_percent(u8 rssi) +{ + int r = (rssi*100) / 41; + if (r > 100) + r = 100; + return (u8) r; +} + +u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status) +{ + static const u16 ofdm_rates[] = { + [ZD_OFDM_RATE_6M] = 60, + [ZD_OFDM_RATE_9M] = 90, + [ZD_OFDM_RATE_12M] = 120, + [ZD_OFDM_RATE_18M] = 180, + [ZD_OFDM_RATE_24M] = 240, + [ZD_OFDM_RATE_36M] = 360, + [ZD_OFDM_RATE_48M] = 480, + [ZD_OFDM_RATE_54M] = 540, + }; + u16 rate; + if (status->frame_status & ZD_RX_OFDM) { + u8 ofdm_rate = zd_ofdm_plcp_header_rate(rx_frame); + rate = ofdm_rates[ofdm_rate & 0xf]; + } else { + u8 cck_rate = zd_cck_plcp_header_rate(rx_frame); + switch (cck_rate) { + case ZD_CCK_SIGNAL_1M: + rate = 10; + break; + case ZD_CCK_SIGNAL_2M: + rate = 20; + break; + case ZD_CCK_SIGNAL_5M5: + rate = 55; + break; + case ZD_CCK_SIGNAL_11M: + rate = 110; + break; + default: + rate = 0; + } + } + + return rate; +} + +int zd_chip_switch_radio_on(struct zd_chip *chip) +{ + int r; + + mutex_lock(&chip->mutex); + r = zd_switch_radio_on(&chip->rf); + mutex_unlock(&chip->mutex); + return r; +} + +int zd_chip_switch_radio_off(struct zd_chip *chip) +{ + int r; + + mutex_lock(&chip->mutex); + r = zd_switch_radio_off(&chip->rf); + mutex_unlock(&chip->mutex); + return r; +} + +int zd_chip_enable_int(struct zd_chip *chip) +{ + int r; + + mutex_lock(&chip->mutex); + r = zd_usb_enable_int(&chip->usb); + mutex_unlock(&chip->mutex); + return r; +} + +void zd_chip_disable_int(struct zd_chip *chip) +{ + mutex_lock(&chip->mutex); + zd_usb_disable_int(&chip->usb); + mutex_unlock(&chip->mutex); +} + +int zd_chip_enable_rx(struct zd_chip *chip) +{ + int r; + + mutex_lock(&chip->mutex); + r = zd_usb_enable_rx(&chip->usb); + mutex_unlock(&chip->mutex); + return r; +} + +void zd_chip_disable_rx(struct zd_chip *chip) +{ + mutex_lock(&chip->mutex); + zd_usb_disable_rx(&chip->usb); + mutex_unlock(&chip->mutex); +} + +int zd_rfwritev_locked(struct zd_chip *chip, + const u32* values, unsigned int count, u8 bits) +{ + int r; + unsigned int i; + + for (i = 0; i < count; i++) { + r = zd_rfwrite_locked(chip, values[i], bits); + if (r) + return r; + } + + return 0; +} diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h new file mode 100644 index 000000000..069d2b467 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_chip.h @@ -0,0 +1,827 @@ +/* zd_chip.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ZD_CHIP_H +#define _ZD_CHIP_H + +#include "zd_types.h" +#include "zd_rf.h" +#include "zd_usb.h" + +/* Header for the Media Access Controller (MAC) and the Baseband Processor + * (BBP). It appears that the ZD1211 wraps the old ZD1205 with USB glue and + * adds a processor for handling the USB protocol. + */ + +/* 8-bit hardware registers */ +#define CR0 CTL_REG(0x0000) +#define CR1 CTL_REG(0x0004) +#define CR2 CTL_REG(0x0008) +#define CR3 CTL_REG(0x000C) + +#define CR5 CTL_REG(0x0010) +/* bit 5: if set short preamble used + * bit 6: filter band - Japan channel 14 on, else off + */ +#define CR6 CTL_REG(0x0014) +#define CR7 CTL_REG(0x0018) +#define CR8 CTL_REG(0x001C) + +#define CR4 CTL_REG(0x0020) + +#define CR9 CTL_REG(0x0024) +/* bit 2: antenna switch (together with CR10) */ +#define CR10 CTL_REG(0x0028) +/* bit 1: antenna switch (together with CR9) + * RF2959 controls with CR11 radion on and off + */ +#define CR11 CTL_REG(0x002C) +/* bit 6: TX power control for OFDM + * RF2959 controls with CR10 radio on and off + */ +#define CR12 CTL_REG(0x0030) +#define CR13 CTL_REG(0x0034) +#define CR14 CTL_REG(0x0038) +#define CR15 CTL_REG(0x003C) +#define CR16 CTL_REG(0x0040) +#define CR17 CTL_REG(0x0044) +#define CR18 CTL_REG(0x0048) +#define CR19 CTL_REG(0x004C) +#define CR20 CTL_REG(0x0050) +#define CR21 CTL_REG(0x0054) +#define CR22 CTL_REG(0x0058) +#define CR23 CTL_REG(0x005C) +#define CR24 CTL_REG(0x0060) /* CCA threshold */ +#define CR25 CTL_REG(0x0064) +#define CR26 CTL_REG(0x0068) +#define CR27 CTL_REG(0x006C) +#define CR28 CTL_REG(0x0070) +#define CR29 CTL_REG(0x0074) +#define CR30 CTL_REG(0x0078) +#define CR31 CTL_REG(0x007C) /* TX power control for RF in CCK mode */ +#define CR32 CTL_REG(0x0080) +#define CR33 CTL_REG(0x0084) +#define CR34 CTL_REG(0x0088) +#define CR35 CTL_REG(0x008C) +#define CR36 CTL_REG(0x0090) +#define CR37 CTL_REG(0x0094) +#define CR38 CTL_REG(0x0098) +#define CR39 CTL_REG(0x009C) +#define CR40 CTL_REG(0x00A0) +#define CR41 CTL_REG(0x00A4) +#define CR42 CTL_REG(0x00A8) +#define CR43 CTL_REG(0x00AC) +#define CR44 CTL_REG(0x00B0) +#define CR45 CTL_REG(0x00B4) +#define CR46 CTL_REG(0x00B8) +#define CR47 CTL_REG(0x00BC) /* CCK baseband gain + * (patch value might be in EEPROM) + */ +#define CR48 CTL_REG(0x00C0) +#define CR49 CTL_REG(0x00C4) +#define CR50 CTL_REG(0x00C8) +#define CR51 CTL_REG(0x00CC) /* TX power control for RF in 6-36M modes */ +#define CR52 CTL_REG(0x00D0) /* TX power control for RF in 48M mode */ +#define CR53 CTL_REG(0x00D4) /* TX power control for RF in 54M mode */ +#define CR54 CTL_REG(0x00D8) +#define CR55 CTL_REG(0x00DC) +#define CR56 CTL_REG(0x00E0) +#define CR57 CTL_REG(0x00E4) +#define CR58 CTL_REG(0x00E8) +#define CR59 CTL_REG(0x00EC) +#define CR60 CTL_REG(0x00F0) +#define CR61 CTL_REG(0x00F4) +#define CR62 CTL_REG(0x00F8) +#define CR63 CTL_REG(0x00FC) +#define CR64 CTL_REG(0x0100) +#define CR65 CTL_REG(0x0104) /* OFDM 54M calibration */ +#define CR66 CTL_REG(0x0108) /* OFDM 48M calibration */ +#define CR67 CTL_REG(0x010C) /* OFDM 36M calibration */ +#define CR68 CTL_REG(0x0110) /* CCK calibration */ +#define CR69 CTL_REG(0x0114) +#define CR70 CTL_REG(0x0118) +#define CR71 CTL_REG(0x011C) +#define CR72 CTL_REG(0x0120) +#define CR73 CTL_REG(0x0124) +#define CR74 CTL_REG(0x0128) +#define CR75 CTL_REG(0x012C) +#define CR76 CTL_REG(0x0130) +#define CR77 CTL_REG(0x0134) +#define CR78 CTL_REG(0x0138) +#define CR79 CTL_REG(0x013C) +#define CR80 CTL_REG(0x0140) +#define CR81 CTL_REG(0x0144) +#define CR82 CTL_REG(0x0148) +#define CR83 CTL_REG(0x014C) +#define CR84 CTL_REG(0x0150) +#define CR85 CTL_REG(0x0154) +#define CR86 CTL_REG(0x0158) +#define CR87 CTL_REG(0x015C) +#define CR88 CTL_REG(0x0160) +#define CR89 CTL_REG(0x0164) +#define CR90 CTL_REG(0x0168) +#define CR91 CTL_REG(0x016C) +#define CR92 CTL_REG(0x0170) +#define CR93 CTL_REG(0x0174) +#define CR94 CTL_REG(0x0178) +#define CR95 CTL_REG(0x017C) +#define CR96 CTL_REG(0x0180) +#define CR97 CTL_REG(0x0184) +#define CR98 CTL_REG(0x0188) +#define CR99 CTL_REG(0x018C) +#define CR100 CTL_REG(0x0190) +#define CR101 CTL_REG(0x0194) +#define CR102 CTL_REG(0x0198) +#define CR103 CTL_REG(0x019C) +#define CR104 CTL_REG(0x01A0) +#define CR105 CTL_REG(0x01A4) +#define CR106 CTL_REG(0x01A8) +#define CR107 CTL_REG(0x01AC) +#define CR108 CTL_REG(0x01B0) +#define CR109 CTL_REG(0x01B4) +#define CR110 CTL_REG(0x01B8) +#define CR111 CTL_REG(0x01BC) +#define CR112 CTL_REG(0x01C0) +#define CR113 CTL_REG(0x01C4) +#define CR114 CTL_REG(0x01C8) +#define CR115 CTL_REG(0x01CC) +#define CR116 CTL_REG(0x01D0) +#define CR117 CTL_REG(0x01D4) +#define CR118 CTL_REG(0x01D8) +#define CR119 CTL_REG(0x01DC) +#define CR120 CTL_REG(0x01E0) +#define CR121 CTL_REG(0x01E4) +#define CR122 CTL_REG(0x01E8) +#define CR123 CTL_REG(0x01EC) +#define CR124 CTL_REG(0x01F0) +#define CR125 CTL_REG(0x01F4) +#define CR126 CTL_REG(0x01F8) +#define CR127 CTL_REG(0x01FC) +#define CR128 CTL_REG(0x0200) +#define CR129 CTL_REG(0x0204) +#define CR130 CTL_REG(0x0208) +#define CR131 CTL_REG(0x020C) +#define CR132 CTL_REG(0x0210) +#define CR133 CTL_REG(0x0214) +#define CR134 CTL_REG(0x0218) +#define CR135 CTL_REG(0x021C) +#define CR136 CTL_REG(0x0220) +#define CR137 CTL_REG(0x0224) +#define CR138 CTL_REG(0x0228) +#define CR139 CTL_REG(0x022C) +#define CR140 CTL_REG(0x0230) +#define CR141 CTL_REG(0x0234) +#define CR142 CTL_REG(0x0238) +#define CR143 CTL_REG(0x023C) +#define CR144 CTL_REG(0x0240) +#define CR145 CTL_REG(0x0244) +#define CR146 CTL_REG(0x0248) +#define CR147 CTL_REG(0x024C) +#define CR148 CTL_REG(0x0250) +#define CR149 CTL_REG(0x0254) +#define CR150 CTL_REG(0x0258) +#define CR151 CTL_REG(0x025C) +#define CR152 CTL_REG(0x0260) +#define CR153 CTL_REG(0x0264) +#define CR154 CTL_REG(0x0268) +#define CR155 CTL_REG(0x026C) +#define CR156 CTL_REG(0x0270) +#define CR157 CTL_REG(0x0274) +#define CR158 CTL_REG(0x0278) +#define CR159 CTL_REG(0x027C) +#define CR160 CTL_REG(0x0280) +#define CR161 CTL_REG(0x0284) +#define CR162 CTL_REG(0x0288) +#define CR163 CTL_REG(0x028C) +#define CR164 CTL_REG(0x0290) +#define CR165 CTL_REG(0x0294) +#define CR166 CTL_REG(0x0298) +#define CR167 CTL_REG(0x029C) +#define CR168 CTL_REG(0x02A0) +#define CR169 CTL_REG(0x02A4) +#define CR170 CTL_REG(0x02A8) +#define CR171 CTL_REG(0x02AC) +#define CR172 CTL_REG(0x02B0) +#define CR173 CTL_REG(0x02B4) +#define CR174 CTL_REG(0x02B8) +#define CR175 CTL_REG(0x02BC) +#define CR176 CTL_REG(0x02C0) +#define CR177 CTL_REG(0x02C4) +#define CR178 CTL_REG(0x02C8) +#define CR179 CTL_REG(0x02CC) +#define CR180 CTL_REG(0x02D0) +#define CR181 CTL_REG(0x02D4) +#define CR182 CTL_REG(0x02D8) +#define CR183 CTL_REG(0x02DC) +#define CR184 CTL_REG(0x02E0) +#define CR185 CTL_REG(0x02E4) +#define CR186 CTL_REG(0x02E8) +#define CR187 CTL_REG(0x02EC) +#define CR188 CTL_REG(0x02F0) +#define CR189 CTL_REG(0x02F4) +#define CR190 CTL_REG(0x02F8) +#define CR191 CTL_REG(0x02FC) +#define CR192 CTL_REG(0x0300) +#define CR193 CTL_REG(0x0304) +#define CR194 CTL_REG(0x0308) +#define CR195 CTL_REG(0x030C) +#define CR196 CTL_REG(0x0310) +#define CR197 CTL_REG(0x0314) +#define CR198 CTL_REG(0x0318) +#define CR199 CTL_REG(0x031C) +#define CR200 CTL_REG(0x0320) +#define CR201 CTL_REG(0x0324) +#define CR202 CTL_REG(0x0328) +#define CR203 CTL_REG(0x032C) /* I2C bus template value & flash control */ +#define CR204 CTL_REG(0x0330) +#define CR205 CTL_REG(0x0334) +#define CR206 CTL_REG(0x0338) +#define CR207 CTL_REG(0x033C) +#define CR208 CTL_REG(0x0340) +#define CR209 CTL_REG(0x0344) +#define CR210 CTL_REG(0x0348) +#define CR211 CTL_REG(0x034C) +#define CR212 CTL_REG(0x0350) +#define CR213 CTL_REG(0x0354) +#define CR214 CTL_REG(0x0358) +#define CR215 CTL_REG(0x035C) +#define CR216 CTL_REG(0x0360) +#define CR217 CTL_REG(0x0364) +#define CR218 CTL_REG(0x0368) +#define CR219 CTL_REG(0x036C) +#define CR220 CTL_REG(0x0370) +#define CR221 CTL_REG(0x0374) +#define CR222 CTL_REG(0x0378) +#define CR223 CTL_REG(0x037C) +#define CR224 CTL_REG(0x0380) +#define CR225 CTL_REG(0x0384) +#define CR226 CTL_REG(0x0388) +#define CR227 CTL_REG(0x038C) +#define CR228 CTL_REG(0x0390) +#define CR229 CTL_REG(0x0394) +#define CR230 CTL_REG(0x0398) +#define CR231 CTL_REG(0x039C) +#define CR232 CTL_REG(0x03A0) +#define CR233 CTL_REG(0x03A4) +#define CR234 CTL_REG(0x03A8) +#define CR235 CTL_REG(0x03AC) +#define CR236 CTL_REG(0x03B0) + +#define CR240 CTL_REG(0x03C0) +/* bit 7: host-controlled RF register writes + * CR241-CR245: for hardware controlled writing of RF bits, not needed for + * USB + */ +#define CR241 CTL_REG(0x03C4) +#define CR242 CTL_REG(0x03C8) +#define CR243 CTL_REG(0x03CC) +#define CR244 CTL_REG(0x03D0) +#define CR245 CTL_REG(0x03D4) + +#define CR251 CTL_REG(0x03EC) /* only used for activation and deactivation of + * Airoha RFs AL2230 and AL7230B + */ +#define CR252 CTL_REG(0x03F0) +#define CR253 CTL_REG(0x03F4) +#define CR254 CTL_REG(0x03F8) +#define CR255 CTL_REG(0x03FC) + +#define CR_MAX_PHY_REG 255 + +/* Taken from the ZYDAS driver, not all of them are relevant for the ZSD1211 + * driver. + */ + +#define CR_RF_IF_CLK CTL_REG(0x0400) +#define CR_RF_IF_DATA CTL_REG(0x0404) +#define CR_PE1_PE2 CTL_REG(0x0408) +#define CR_PE2_DLY CTL_REG(0x040C) +#define CR_LE1 CTL_REG(0x0410) +#define CR_LE2 CTL_REG(0x0414) +/* Seems to enable/disable GPI (General Purpose IO?) */ +#define CR_GPI_EN CTL_REG(0x0418) +#define CR_RADIO_PD CTL_REG(0x042C) +#define CR_RF2948_PD CTL_REG(0x042C) +#define CR_ENABLE_PS_MANUAL_AGC CTL_REG(0x043C) +#define CR_CONFIG_PHILIPS CTL_REG(0x0440) +#define CR_SA2400_SER_AP CTL_REG(0x0444) +#define CR_I2C_WRITE CTL_REG(0x0444) +#define CR_SA2400_SER_RP CTL_REG(0x0448) +#define CR_RADIO_PE CTL_REG(0x0458) +#define CR_RST_BUS_MASTER CTL_REG(0x045C) +#define CR_RFCFG CTL_REG(0x0464) +#define CR_HSTSCHG CTL_REG(0x046C) +#define CR_PHY_ON CTL_REG(0x0474) +#define CR_RX_DELAY CTL_REG(0x0478) +#define CR_RX_PE_DELAY CTL_REG(0x047C) +#define CR_GPIO_1 CTL_REG(0x0490) +#define CR_GPIO_2 CTL_REG(0x0494) +#define CR_EncryBufMux CTL_REG(0x04A8) +#define CR_PS_CTRL CTL_REG(0x0500) +#define CR_ADDA_PWR_DWN CTL_REG(0x0504) +#define CR_ADDA_MBIAS_WARMTIME CTL_REG(0x0508) +#define CR_MAC_PS_STATE CTL_REG(0x050C) + +#define CR_INTERRUPT CTL_REG(0x0510) +#define INT_TX_COMPLETE 0x00000001 +#define INT_RX_COMPLETE 0x00000002 +#define INT_RETRY_FAIL 0x00000004 +#define INT_WAKEUP 0x00000008 +#define INT_DTIM_NOTIFY 0x00000020 +#define INT_CFG_NEXT_BCN 0x00000040 +#define INT_BUS_ABORT 0x00000080 +#define INT_TX_FIFO_READY 0x00000100 +#define INT_UART 0x00000200 +#define INT_TX_COMPLETE_EN 0x00010000 +#define INT_RX_COMPLETE_EN 0x00020000 +#define INT_RETRY_FAIL_EN 0x00040000 +#define INT_WAKEUP_EN 0x00080000 +#define INT_DTIM_NOTIFY_EN 0x00200000 +#define INT_CFG_NEXT_BCN_EN 0x00400000 +#define INT_BUS_ABORT_EN 0x00800000 +#define INT_TX_FIFO_READY_EN 0x01000000 +#define INT_UART_EN 0x02000000 + +#define CR_TSF_LOW_PART CTL_REG(0x0514) +#define CR_TSF_HIGH_PART CTL_REG(0x0518) + +/* Following three values are in time units (1024us) + * Following condition must be met: + * atim < tbtt < bcn + */ +#define CR_ATIM_WND_PERIOD CTL_REG(0x051C) +#define CR_BCN_INTERVAL CTL_REG(0x0520) +#define CR_PRE_TBTT CTL_REG(0x0524) +/* in units of TU(1024us) */ + +/* for UART support */ +#define CR_UART_RBR_THR_DLL CTL_REG(0x0540) +#define CR_UART_DLM_IER CTL_REG(0x0544) +#define CR_UART_IIR_FCR CTL_REG(0x0548) +#define CR_UART_LCR CTL_REG(0x054c) +#define CR_UART_MCR CTL_REG(0x0550) +#define CR_UART_LSR CTL_REG(0x0554) +#define CR_UART_MSR CTL_REG(0x0558) +#define CR_UART_ECR CTL_REG(0x055c) +#define CR_UART_STATUS CTL_REG(0x0560) + +#define CR_PCI_TX_ADDR_P1 CTL_REG(0x0600) +#define CR_PCI_TX_AddR_P2 CTL_REG(0x0604) +#define CR_PCI_RX_AddR_P1 CTL_REG(0x0608) +#define CR_PCI_RX_AddR_P2 CTL_REG(0x060C) + +/* must be overwritten if custom MAC address will be used */ +#define CR_MAC_ADDR_P1 CTL_REG(0x0610) +#define CR_MAC_ADDR_P2 CTL_REG(0x0614) +#define CR_BSSID_P1 CTL_REG(0x0618) +#define CR_BSSID_P2 CTL_REG(0x061C) +#define CR_BCN_PLCP_CFG CTL_REG(0x0620) +#define CR_GROUP_HASH_P1 CTL_REG(0x0624) +#define CR_GROUP_HASH_P2 CTL_REG(0x0628) +#define CR_RX_TIMEOUT CTL_REG(0x062C) + +/* Basic rates supported by the BSS. When producing ACK or CTS messages, the + * device will use a rate in this table that is less than or equal to the rate + * of the incoming frame which prompted the response */ +#define CR_BASIC_RATE_TBL CTL_REG(0x0630) +#define CR_RATE_1M 0x0001 /* 802.11b */ +#define CR_RATE_2M 0x0002 /* 802.11b */ +#define CR_RATE_5_5M 0x0004 /* 802.11b */ +#define CR_RATE_11M 0x0008 /* 802.11b */ +#define CR_RATE_6M 0x0100 /* 802.11g */ +#define CR_RATE_9M 0x0200 /* 802.11g */ +#define CR_RATE_12M 0x0400 /* 802.11g */ +#define CR_RATE_18M 0x0800 /* 802.11g */ +#define CR_RATE_24M 0x1000 /* 802.11g */ +#define CR_RATE_36M 0x2000 /* 802.11g */ +#define CR_RATE_48M 0x4000 /* 802.11g */ +#define CR_RATE_54M 0x8000 /* 802.11g */ +#define CR_RATES_80211G 0xff00 +#define CR_RATES_80211B 0x000f + +/* Mandatory rates required in the BSS. When producing ACK or CTS messages, if + * the device could not find an appropriate rate in CR_BASIC_RATE_TBL, it will + * look for a rate in this table that is less than or equal to the rate of + * the incoming frame. */ +#define CR_MANDATORY_RATE_TBL CTL_REG(0x0634) +#define CR_RTS_CTS_RATE CTL_REG(0x0638) + +#define CR_WEP_PROTECT CTL_REG(0x063C) +#define CR_RX_THRESHOLD CTL_REG(0x0640) + +/* register for controlling the LEDS */ +#define CR_LED CTL_REG(0x0644) +/* masks for controlling LEDs */ +#define LED1 0x0100 +#define LED2 0x0200 + +/* Seems to indicate that the configuration is over. + */ +#define CR_AFTER_PNP CTL_REG(0x0648) +#define CR_ACK_TIME_80211 CTL_REG(0x0658) + +#define CR_RX_OFFSET CTL_REG(0x065c) + +#define CR_PHY_DELAY CTL_REG(0x066C) +#define CR_BCN_FIFO CTL_REG(0x0670) +#define CR_SNIFFER_ON CTL_REG(0x0674) + +#define CR_ENCRYPTION_TYPE CTL_REG(0x0678) +#define NO_WEP 0 +#define WEP64 1 +#define WEP128 5 +#define WEP256 6 +#define ENC_SNIFFER 8 + +#define CR_ZD1211_RETRY_MAX CTL_REG(0x067C) + +#define CR_REG1 CTL_REG(0x0680) +/* Setting the bit UNLOCK_PHY_REGS disallows the write access to physical + * registers, so one could argue it is a LOCK bit. But calling it + * LOCK_PHY_REGS makes it confusing. + */ +#define UNLOCK_PHY_REGS 0x0080 + +#define CR_DEVICE_STATE CTL_REG(0x0684) +#define CR_UNDERRUN_CNT CTL_REG(0x0688) + +#define CR_RX_FILTER CTL_REG(0x068c) +#define RX_FILTER_ASSOC_RESPONSE 0x0002 +#define RX_FILTER_REASSOC_RESPONSE 0x0008 +#define RX_FILTER_PROBE_RESPONSE 0x0020 +#define RX_FILTER_BEACON 0x0100 +#define RX_FILTER_DISASSOC 0x0400 +#define RX_FILTER_AUTH 0x0800 +#define AP_RX_FILTER 0x0400feff +#define STA_RX_FILTER 0x0000ffff + +/* Monitor mode sets filter to 0xfffff */ + +#define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690) +#define CR_BCN_FIFO_SEMAPHORE CTL_REG(0x0694) +#define CR_IFS_VALUE CTL_REG(0x0698) +#define CR_RX_TIME_OUT CTL_REG(0x069C) +#define CR_TOTAL_RX_FRM CTL_REG(0x06A0) +#define CR_CRC32_CNT CTL_REG(0x06A4) +#define CR_CRC16_CNT CTL_REG(0x06A8) +#define CR_DECRYPTION_ERR_UNI CTL_REG(0x06AC) +#define CR_RX_FIFO_OVERRUN CTL_REG(0x06B0) + +#define CR_DECRYPTION_ERR_MUL CTL_REG(0x06BC) + +#define CR_NAV_CNT CTL_REG(0x06C4) +#define CR_NAV_CCA CTL_REG(0x06C8) +#define CR_RETRY_CNT CTL_REG(0x06CC) + +#define CR_READ_TCB_ADDR CTL_REG(0x06E8) +#define CR_READ_RFD_ADDR CTL_REG(0x06EC) +#define CR_CWMIN_CWMAX CTL_REG(0x06F0) +#define CR_TOTAL_TX_FRM CTL_REG(0x06F4) + +/* CAM: Continuous Access Mode (power management) */ +#define CR_CAM_MODE CTL_REG(0x0700) +#define CR_CAM_ROLL_TB_LOW CTL_REG(0x0704) +#define CR_CAM_ROLL_TB_HIGH CTL_REG(0x0708) +#define CR_CAM_ADDRESS CTL_REG(0x070C) +#define CR_CAM_DATA CTL_REG(0x0710) + +#define CR_ROMDIR CTL_REG(0x0714) + +#define CR_DECRY_ERR_FLG_LOW CTL_REG(0x0714) +#define CR_DECRY_ERR_FLG_HIGH CTL_REG(0x0718) + +#define CR_WEPKEY0 CTL_REG(0x0720) +#define CR_WEPKEY1 CTL_REG(0x0724) +#define CR_WEPKEY2 CTL_REG(0x0728) +#define CR_WEPKEY3 CTL_REG(0x072C) +#define CR_WEPKEY4 CTL_REG(0x0730) +#define CR_WEPKEY5 CTL_REG(0x0734) +#define CR_WEPKEY6 CTL_REG(0x0738) +#define CR_WEPKEY7 CTL_REG(0x073C) +#define CR_WEPKEY8 CTL_REG(0x0740) +#define CR_WEPKEY9 CTL_REG(0x0744) +#define CR_WEPKEY10 CTL_REG(0x0748) +#define CR_WEPKEY11 CTL_REG(0x074C) +#define CR_WEPKEY12 CTL_REG(0x0750) +#define CR_WEPKEY13 CTL_REG(0x0754) +#define CR_WEPKEY14 CTL_REG(0x0758) +#define CR_WEPKEY15 CTL_REG(0x075c) +#define CR_TKIP_MODE CTL_REG(0x0760) + +#define CR_EEPROM_PROTECT0 CTL_REG(0x0758) +#define CR_EEPROM_PROTECT1 CTL_REG(0x075C) + +#define CR_DBG_FIFO_RD CTL_REG(0x0800) +#define CR_DBG_SELECT CTL_REG(0x0804) +#define CR_FIFO_Length CTL_REG(0x0808) + + +#define CR_RSSI_MGC CTL_REG(0x0810) + +#define CR_PON CTL_REG(0x0818) +#define CR_RX_ON CTL_REG(0x081C) +#define CR_TX_ON CTL_REG(0x0820) +#define CR_CHIP_EN CTL_REG(0x0824) +#define CR_LO_SW CTL_REG(0x0828) +#define CR_TXRX_SW CTL_REG(0x082C) +#define CR_S_MD CTL_REG(0x0830) + +#define CR_USB_DEBUG_PORT CTL_REG(0x0888) + +#define CR_ZD1211B_TX_PWR_CTL1 CTL_REG(0x0b00) +#define CR_ZD1211B_TX_PWR_CTL2 CTL_REG(0x0b04) +#define CR_ZD1211B_TX_PWR_CTL3 CTL_REG(0x0b08) +#define CR_ZD1211B_TX_PWR_CTL4 CTL_REG(0x0b0c) +#define CR_ZD1211B_AIFS_CTL1 CTL_REG(0x0b10) +#define CR_ZD1211B_AIFS_CTL2 CTL_REG(0x0b14) +#define CR_ZD1211B_TXOP CTL_REG(0x0b20) +#define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28) + +#define CWIN_SIZE 0x007f043f + + +#define HWINT_ENABLED 0x004f0000 +#define HWINT_DISABLED 0 + +#define E2P_PWR_INT_GUARD 8 +#define E2P_CHANNEL_COUNT 14 + +/* If you compare this addresses with the ZYDAS orignal driver, please notify + * that we use word mapping for the EEPROM. + */ + +/* + * Upper 16 bit contains the regulatory domain. + */ +#define E2P_SUBID E2P_REG(0x00) +#define E2P_POD E2P_REG(0x02) +#define E2P_MAC_ADDR_P1 E2P_REG(0x04) +#define E2P_MAC_ADDR_P2 E2P_REG(0x06) +#define E2P_PWR_CAL_VALUE1 E2P_REG(0x08) +#define E2P_PWR_CAL_VALUE2 E2P_REG(0x0a) +#define E2P_PWR_CAL_VALUE3 E2P_REG(0x0c) +#define E2P_PWR_CAL_VALUE4 E2P_REG(0x0e) +#define E2P_PWR_INT_VALUE1 E2P_REG(0x10) +#define E2P_PWR_INT_VALUE2 E2P_REG(0x12) +#define E2P_PWR_INT_VALUE3 E2P_REG(0x14) +#define E2P_PWR_INT_VALUE4 E2P_REG(0x16) + +/* Contains a bit for each allowed channel. It gives for Europe (ETSI 0x30) + * also only 11 channels. */ +#define E2P_ALLOWED_CHANNEL E2P_REG(0x18) + +#define E2P_PHY_REG E2P_REG(0x1a) +#define E2P_DEVICE_VER E2P_REG(0x20) +#define E2P_36M_CAL_VALUE1 E2P_REG(0x28) +#define E2P_36M_CAL_VALUE2 E2P_REG(0x2a) +#define E2P_36M_CAL_VALUE3 E2P_REG(0x2c) +#define E2P_36M_CAL_VALUE4 E2P_REG(0x2e) +#define E2P_11A_INT_VALUE1 E2P_REG(0x30) +#define E2P_11A_INT_VALUE2 E2P_REG(0x32) +#define E2P_11A_INT_VALUE3 E2P_REG(0x34) +#define E2P_11A_INT_VALUE4 E2P_REG(0x36) +#define E2P_48M_CAL_VALUE1 E2P_REG(0x38) +#define E2P_48M_CAL_VALUE2 E2P_REG(0x3a) +#define E2P_48M_CAL_VALUE3 E2P_REG(0x3c) +#define E2P_48M_CAL_VALUE4 E2P_REG(0x3e) +#define E2P_48M_INT_VALUE1 E2P_REG(0x40) +#define E2P_48M_INT_VALUE2 E2P_REG(0x42) +#define E2P_48M_INT_VALUE3 E2P_REG(0x44) +#define E2P_48M_INT_VALUE4 E2P_REG(0x46) +#define E2P_54M_CAL_VALUE1 E2P_REG(0x48) /* ??? */ +#define E2P_54M_CAL_VALUE2 E2P_REG(0x4a) +#define E2P_54M_CAL_VALUE3 E2P_REG(0x4c) +#define E2P_54M_CAL_VALUE4 E2P_REG(0x4e) +#define E2P_54M_INT_VALUE1 E2P_REG(0x50) +#define E2P_54M_INT_VALUE2 E2P_REG(0x52) +#define E2P_54M_INT_VALUE3 E2P_REG(0x54) +#define E2P_54M_INT_VALUE4 E2P_REG(0x56) + +/* All 16 bit values */ +#define FW_FIRMWARE_VER FW_REG(0) +/* non-zero if USB high speed connection */ +#define FW_USB_SPEED FW_REG(1) +#define FW_FIX_TX_RATE FW_REG(2) +/* Seems to be able to control LEDs over the firmware */ +#define FW_LINK_STATUS FW_REG(3) +#define FW_SOFT_RESET FW_REG(4) +#define FW_FLASH_CHK FW_REG(5) + +enum { + CR_BASE_OFFSET = 0x9000, + FW_START_OFFSET = 0xee00, + FW_BASE_ADDR_OFFSET = FW_START_OFFSET + 0x1d, + EEPROM_START_OFFSET = 0xf800, + EEPROM_SIZE = 0x800, /* words */ + LOAD_CODE_SIZE = 0xe, /* words */ + LOAD_VECT_SIZE = 0x10000 - 0xfff7, /* words */ + EEPROM_REGS_OFFSET = LOAD_CODE_SIZE + LOAD_VECT_SIZE, + E2P_BASE_OFFSET = EEPROM_START_OFFSET + + EEPROM_REGS_OFFSET, +}; + +#define FW_REG_TABLE_ADDR USB_ADDR(FW_START_OFFSET + 0x1d) + +enum { + /* indices for ofdm_cal_values */ + OFDM_36M_INDEX = 0, + OFDM_48M_INDEX = 1, + OFDM_54M_INDEX = 2, +}; + +struct zd_chip { + struct zd_usb usb; + struct zd_rf rf; + struct mutex mutex; + u8 e2p_mac[ETH_ALEN]; + /* EepSetPoint in the vendor driver */ + u8 pwr_cal_values[E2P_CHANNEL_COUNT]; + /* integration values in the vendor driver */ + u8 pwr_int_values[E2P_CHANNEL_COUNT]; + /* SetPointOFDM in the vendor driver */ + u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT]; + u8 pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1, + is_zd1211b:1; +}; + +static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb) +{ + return container_of(usb, struct zd_chip, usb); +} + +static inline struct zd_chip *zd_rf_to_chip(struct zd_rf *rf) +{ + return container_of(rf, struct zd_chip, rf); +} + +#define zd_chip_dev(chip) (&(chip)->usb.intf->dev) + +void zd_chip_init(struct zd_chip *chip, + struct net_device *netdev, + struct usb_interface *intf); +void zd_chip_clear(struct zd_chip *chip); +int zd_chip_init_hw(struct zd_chip *chip, u8 device_type); +int zd_chip_reset(struct zd_chip *chip); + +static inline int zd_ioread16v_locked(struct zd_chip *chip, u16 *values, + const zd_addr_t *addresses, + unsigned int count) +{ + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + return zd_usb_ioread16v(&chip->usb, values, addresses, count); +} + +static inline int zd_ioread16_locked(struct zd_chip *chip, u16 *value, + const zd_addr_t addr) +{ + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + return zd_usb_ioread16(&chip->usb, value, addr); +} + +int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, + const zd_addr_t *addresses, unsigned int count); + +static inline int zd_ioread32_locked(struct zd_chip *chip, u32 *value, + const zd_addr_t addr) +{ + return zd_ioread32v_locked(chip, value, (const zd_addr_t *)&addr, 1); +} + +static inline int zd_iowrite16_locked(struct zd_chip *chip, u16 value, + zd_addr_t addr) +{ + struct zd_ioreq16 ioreq; + + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + ioreq.addr = addr; + ioreq.value = value; + + return zd_usb_iowrite16v(&chip->usb, &ioreq, 1); +} + +int zd_iowrite16a_locked(struct zd_chip *chip, + const struct zd_ioreq16 *ioreqs, unsigned int count); + +int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, + unsigned int count); + +static inline int zd_iowrite32_locked(struct zd_chip *chip, u32 value, + zd_addr_t addr) +{ + struct zd_ioreq32 ioreq; + + ioreq.addr = addr; + ioreq.value = value; + + return _zd_iowrite32v_locked(chip, &ioreq, 1); +} + +int zd_iowrite32a_locked(struct zd_chip *chip, + const struct zd_ioreq32 *ioreqs, unsigned int count); + +static inline int zd_rfwrite_locked(struct zd_chip *chip, u32 value, u8 bits) +{ + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + return zd_usb_rfwrite(&chip->usb, value, bits); +} + +int zd_rfwritev_locked(struct zd_chip *chip, + const u32* values, unsigned int count, u8 bits); + +/* Locking functions for reading and writing registers. + * The different parameters are intentional. + */ +int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value); +int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value); +int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value); +int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value); +int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses, + u32 *values, unsigned int count); +int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, + unsigned int count); + +int zd_chip_set_channel(struct zd_chip *chip, u8 channel); +static inline u8 _zd_chip_get_channel(struct zd_chip *chip) +{ + return chip->rf.channel; +} +u8 zd_chip_get_channel(struct zd_chip *chip); +int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain); +void zd_get_e2p_mac_addr(struct zd_chip *chip, u8 *mac_addr); +int zd_read_mac_addr(struct zd_chip *chip, u8 *mac_addr); +int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr); +int zd_chip_switch_radio_on(struct zd_chip *chip); +int zd_chip_switch_radio_off(struct zd_chip *chip); +int zd_chip_enable_int(struct zd_chip *chip); +void zd_chip_disable_int(struct zd_chip *chip); +int zd_chip_enable_rx(struct zd_chip *chip); +void zd_chip_disable_rx(struct zd_chip *chip); +int zd_chip_enable_hwint(struct zd_chip *chip); +int zd_chip_disable_hwint(struct zd_chip *chip); + +static inline int zd_get_encryption_type(struct zd_chip *chip, u32 *type) +{ + return zd_ioread32(chip, CR_ENCRYPTION_TYPE, type); +} + +static inline int zd_set_encryption_type(struct zd_chip *chip, u32 type) +{ + return zd_iowrite32(chip, CR_ENCRYPTION_TYPE, type); +} + +static inline int zd_chip_get_basic_rates(struct zd_chip *chip, u16 *cr_rates) +{ + return zd_ioread16(chip, CR_BASIC_RATE_TBL, cr_rates); +} + +int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates); + +static inline int zd_chip_set_rx_filter(struct zd_chip *chip, u32 filter) +{ + return zd_iowrite32(chip, CR_RX_FILTER, filter); +} + +int zd_chip_lock_phy_regs(struct zd_chip *chip); +int zd_chip_unlock_phy_regs(struct zd_chip *chip); + +enum led_status { + LED_OFF = 0, + LED_ON = 1, + LED_FLIP = 2, + LED_STATUS = 3, +}; + +int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status); +int zd_chip_led_flip(struct zd_chip *chip, int led, + const unsigned int *phases_msecs, unsigned int count); + +int zd_set_beacon_interval(struct zd_chip *chip, u32 interval); + +static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval) +{ + return zd_ioread32(chip, CR_BCN_INTERVAL, interval); +} + +struct rx_status; + +u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, + const struct rx_status *status); +u8 zd_rx_strength_percent(u8 rssi); + +u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status); + +#endif /* _ZD_CHIP_H */ diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h new file mode 100644 index 000000000..465906812 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_def.h @@ -0,0 +1,48 @@ +/* zd_def.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ZD_DEF_H +#define _ZD_DEF_H + +#include <linux/kernel.h> +#include <linux/stringify.h> +#include <linux/device.h> +#include <linux/kernel.h> + +#define dev_printk_f(level, dev, fmt, args...) \ + dev_printk(level, dev, "%s() " fmt, __func__, ##args) + +#ifdef DEBUG +# define dev_dbg_f(dev, fmt, args...) \ + dev_printk_f(KERN_DEBUG, dev, fmt, ## args) +#else +# define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0) +#endif /* DEBUG */ + +#ifdef DEBUG +# define ZD_ASSERT(x) \ +do { \ + if (!(x)) { \ + pr_debug("%s:%d ASSERT %s VIOLATED!\n", \ + __FILE__, __LINE__, __stringify(x)); \ + } \ +} while (0) +#else +# define ZD_ASSERT(x) do { } while (0) +#endif + +#endif /* _ZD_DEF_H */ diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.c b/drivers/net/wireless/zd1211rw/zd_ieee80211.c new file mode 100644 index 000000000..66905f7b6 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.c @@ -0,0 +1,191 @@ +/* zd_ieee80211.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * A lot of this code is generic and should be moved into the upper layers + * at some point. + */ + +#include <linux/errno.h> +#include <linux/wireless.h> +#include <linux/kernel.h> +#include <net/ieee80211.h> + +#include "zd_def.h" +#include "zd_ieee80211.h" +#include "zd_mac.h" + +static const struct channel_range channel_ranges[] = { + [0] = { 0, 0}, + [ZD_REGDOMAIN_FCC] = { 1, 12}, + [ZD_REGDOMAIN_IC] = { 1, 12}, + [ZD_REGDOMAIN_ETSI] = { 1, 14}, + [ZD_REGDOMAIN_JAPAN] = { 1, 14}, + [ZD_REGDOMAIN_SPAIN] = { 1, 14}, + [ZD_REGDOMAIN_FRANCE] = { 1, 14}, + [ZD_REGDOMAIN_JAPAN_ADD] = {14, 15}, +}; + +const struct channel_range *zd_channel_range(u8 regdomain) +{ + if (regdomain >= ARRAY_SIZE(channel_ranges)) + regdomain = 0; + return &channel_ranges[regdomain]; +} + +int zd_regdomain_supports_channel(u8 regdomain, u8 channel) +{ + const struct channel_range *range = zd_channel_range(regdomain); + return range->start <= channel && channel < range->end; +} + +int zd_regdomain_supported(u8 regdomain) +{ + const struct channel_range *range = zd_channel_range(regdomain); + return range->start != 0; +} + +/* Stores channel frequencies in MHz. */ +static const u16 channel_frequencies[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, + 2452, 2457, 2462, 2467, 2472, 2484, +}; + +#define NUM_CHANNELS ARRAY_SIZE(channel_frequencies) + +static int compute_freq(struct iw_freq *freq, u32 mhz, u32 hz) +{ + u32 factor; + + freq->e = 0; + if (mhz >= 1000000000U) { + pr_debug("zd1211 mhz %u to large\n", mhz); + freq->m = 0; + return -EINVAL; + } + + factor = 1000; + while (mhz >= factor) { + + freq->e += 1; + factor *= 10; + } + + factor /= 1000U; + freq->m = mhz * (1000000U/factor) + hz/factor; + + return 0; +} + +int zd_channel_to_freq(struct iw_freq *freq, u8 channel) +{ + if (channel > NUM_CHANNELS) { + freq->m = 0; + freq->e = 0; + return -EINVAL; + } + if (!channel) { + freq->m = 0; + freq->e = 0; + return -EINVAL; + } + return compute_freq(freq, channel_frequencies[channel-1], 0); +} + +static int freq_to_mhz(const struct iw_freq *freq) +{ + u32 factor; + int e; + + /* Such high frequencies are not supported. */ + if (freq->e > 6) + return -EINVAL; + + factor = 1; + for (e = freq->e; e > 0; --e) { + factor *= 10; + } + factor = 1000000U / factor; + + if (freq->m % factor) { + return -EINVAL; + } + + return freq->m / factor; +} + +int zd_find_channel(u8 *channel, const struct iw_freq *freq) +{ + int i, r; + u32 mhz; + + if (!(freq->flags & IW_FREQ_FIXED)) + return 0; + + if (freq->m < 1000) { + if (freq->m > NUM_CHANNELS || freq->m == 0) + return -EINVAL; + *channel = freq->m; + return 1; + } + + r = freq_to_mhz(freq); + if (r < 0) + return r; + mhz = r; + + for (i = 0; i < NUM_CHANNELS; i++) { + if (mhz == channel_frequencies[i]) { + *channel = i+1; + return 1; + } + } + + return -EINVAL; +} + +int zd_geo_init(struct ieee80211_device *ieee, u8 regdomain) +{ + struct ieee80211_geo geo; + const struct channel_range *range; + int i; + u8 channel; + + dev_dbg(zd_mac_dev(zd_netdev_mac(ieee->dev)), + "regdomain %#04x\n", regdomain); + + range = zd_channel_range(regdomain); + if (range->start == 0) { + dev_err(zd_mac_dev(zd_netdev_mac(ieee->dev)), + "zd1211 regdomain %#04x not supported\n", + regdomain); + return -EINVAL; + } + + memset(&geo, 0, sizeof(geo)); + + for (i = 0, channel = range->start; channel < range->end; channel++) { + struct ieee80211_channel *chan = &geo.bg[i++]; + chan->freq = channel_frequencies[channel - 1]; + chan->channel = channel; + } + + geo.bg_channels = i; + memcpy(geo.name, "XX ", 4); + ieee80211_set_geo(ieee, &geo); + return 0; +} diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.h b/drivers/net/wireless/zd1211rw/zd_ieee80211.h new file mode 100644 index 000000000..36329890d --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.h @@ -0,0 +1,85 @@ +#ifndef _ZD_IEEE80211_H +#define _ZD_IEEE80211_H + +#include <net/ieee80211.h> +#include "zd_types.h" + +/* Additional definitions from the standards. + */ + +#define ZD_REGDOMAIN_FCC 0x10 +#define ZD_REGDOMAIN_IC 0x20 +#define ZD_REGDOMAIN_ETSI 0x30 +#define ZD_REGDOMAIN_SPAIN 0x31 +#define ZD_REGDOMAIN_FRANCE 0x32 +#define ZD_REGDOMAIN_JAPAN_ADD 0x40 +#define ZD_REGDOMAIN_JAPAN 0x41 + +enum { + MIN_CHANNEL24 = 1, + MAX_CHANNEL24 = 14, +}; + +struct channel_range { + u8 start; + u8 end; /* exclusive (channel must be less than end) */ +}; + +struct iw_freq; + +int zd_geo_init(struct ieee80211_device *ieee, u8 regdomain); + +const struct channel_range *zd_channel_range(u8 regdomain); +int zd_regdomain_supports_channel(u8 regdomain, u8 channel); +int zd_regdomain_supported(u8 regdomain); + +/* for 2.4 GHz band */ +int zd_channel_to_freq(struct iw_freq *freq, u8 channel); +int zd_find_channel(u8 *channel, const struct iw_freq *freq); + +#define ZD_PLCP_SERVICE_LENGTH_EXTENSION 0x80 + +struct ofdm_plcp_header { + u8 prefix[3]; + __le16 service; +} __attribute__((packed)); + +static inline u8 zd_ofdm_plcp_header_rate( + const struct ofdm_plcp_header *header) +{ + return header->prefix[0] & 0xf; +} + +#define ZD_OFDM_RATE_6M 0xb +#define ZD_OFDM_RATE_9M 0xf +#define ZD_OFDM_RATE_12M 0xa +#define ZD_OFDM_RATE_18M 0xe +#define ZD_OFDM_RATE_24M 0x9 +#define ZD_OFDM_RATE_36M 0xd +#define ZD_OFDM_RATE_48M 0x8 +#define ZD_OFDM_RATE_54M 0xc + +struct cck_plcp_header { + u8 signal; + u8 service; + __le16 length; + __le16 crc16; +} __attribute__((packed)); + +static inline u8 zd_cck_plcp_header_rate(const struct cck_plcp_header *header) +{ + return header->signal; +} + +#define ZD_CCK_SIGNAL_1M 0x0a +#define ZD_CCK_SIGNAL_2M 0x14 +#define ZD_CCK_SIGNAL_5M5 0x37 +#define ZD_CCK_SIGNAL_11M 0x6e + +enum ieee80211_std { + IEEE80211B = 0x01, + IEEE80211A = 0x02, + IEEE80211G = 0x04, +}; + +#endif /* _ZD_IEEE80211_H */ diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c new file mode 100644 index 000000000..a9bd80a08 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -0,0 +1,1084 @@ +/* zd_mac.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/wireless.h> +#include <linux/usb.h> +#include <linux/jiffies.h> +#include <net/ieee80211_radiotap.h> + +#include "zd_def.h" +#include "zd_chip.h" +#include "zd_mac.h" +#include "zd_ieee80211.h" +#include "zd_netdev.h" +#include "zd_rf.h" +#include "zd_util.h" + +static void ieee_init(struct ieee80211_device *ieee); +static void softmac_init(struct ieee80211softmac_device *sm); + +int zd_mac_init(struct zd_mac *mac, + struct net_device *netdev, + struct usb_interface *intf) +{ + struct ieee80211_device *ieee = zd_netdev_ieee80211(netdev); + + memset(mac, 0, sizeof(*mac)); + spin_lock_init(&mac->lock); + mac->netdev = netdev; + + ieee_init(ieee); + softmac_init(ieee80211_priv(netdev)); + zd_chip_init(&mac->chip, netdev, intf); + return 0; +} + +static int reset_channel(struct zd_mac *mac) +{ + int r; + unsigned long flags; + const struct channel_range *range; + + spin_lock_irqsave(&mac->lock, flags); + range = zd_channel_range(mac->regdomain); + if (!range->start) { + r = -EINVAL; + goto out; + } + mac->requested_channel = range->start; + r = 0; +out: + spin_unlock_irqrestore(&mac->lock, flags); + return r; +} + +int zd_mac_init_hw(struct zd_mac *mac, u8 device_type) +{ + int r; + struct zd_chip *chip = &mac->chip; + u8 addr[ETH_ALEN]; + u8 default_regdomain; + + r = zd_chip_enable_int(chip); + if (r) + goto out; + r = zd_chip_init_hw(chip, device_type); + if (r) + goto disable_int; + + zd_get_e2p_mac_addr(chip, addr); + r = zd_write_mac_addr(chip, addr); + if (r) + goto disable_int; + ZD_ASSERT(!irqs_disabled()); + spin_lock_irq(&mac->lock); + memcpy(mac->netdev->dev_addr, addr, ETH_ALEN); + spin_unlock_irq(&mac->lock); + + r = zd_read_regdomain(chip, &default_regdomain); + if (r) + goto disable_int; + if (!zd_regdomain_supported(default_regdomain)) { + dev_dbg_f(zd_mac_dev(mac), + "Regulatory Domain %#04x is not supported.\n", + default_regdomain); + r = -EINVAL; + goto disable_int; + } + spin_lock_irq(&mac->lock); + mac->regdomain = mac->default_regdomain = default_regdomain; + spin_unlock_irq(&mac->lock); + r = reset_channel(mac); + if (r) + goto disable_int; + + /* We must inform the device that we are doing encryption/decryption in + * software at the moment. */ + r = zd_set_encryption_type(chip, ENC_SNIFFER); + if (r) + goto disable_int; + + r = zd_geo_init(zd_mac_to_ieee80211(mac), mac->regdomain); + if (r) + goto disable_int; + + r = 0; +disable_int: + zd_chip_disable_int(chip); +out: + return r; +} + +void zd_mac_clear(struct zd_mac *mac) +{ + /* Aquire the lock. */ + spin_lock(&mac->lock); + spin_unlock(&mac->lock); + zd_chip_clear(&mac->chip); + memset(mac, 0, sizeof(*mac)); +} + +static int reset_mode(struct zd_mac *mac) +{ + struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); + struct zd_ioreq32 ioreqs[3] = { + { CR_RX_FILTER, STA_RX_FILTER }, + { CR_SNIFFER_ON, 0U }, + }; + + if (ieee->iw_mode == IW_MODE_MONITOR) { + ioreqs[0].value = 0xffffffff; + ioreqs[1].value = 0x1; + ioreqs[2].value = ENC_SNIFFER; + } + + return zd_iowrite32a(&mac->chip, ioreqs, 3); +} + +int zd_mac_open(struct net_device *netdev) +{ + struct zd_mac *mac = zd_netdev_mac(netdev); + struct zd_chip *chip = &mac->chip; + int r; + + r = zd_chip_enable_int(chip); + if (r < 0) + goto out; + + r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G); + if (r < 0) + goto disable_int; + r = reset_mode(mac); + if (r) + goto disable_int; + r = zd_chip_switch_radio_on(chip); + if (r < 0) + goto disable_int; + r = zd_chip_set_channel(chip, mac->requested_channel); + if (r < 0) + goto disable_radio; + r = zd_chip_enable_rx(chip); + if (r < 0) + goto disable_radio; + r = zd_chip_enable_hwint(chip); + if (r < 0) + goto disable_rx; + + ieee80211softmac_start(netdev); + return 0; +disable_rx: + zd_chip_disable_rx(chip); +disable_radio: + zd_chip_switch_radio_off(chip); +disable_int: + zd_chip_disable_int(chip); +out: + return r; +} + +int zd_mac_stop(struct net_device *netdev) +{ + struct zd_mac *mac = zd_netdev_mac(netdev); + struct zd_chip *chip = &mac->chip; + + netif_stop_queue(netdev); + + /* + * The order here deliberately is a little different from the open() + * method, since we need to make sure there is no opportunity for RX + * frames to be processed by softmac after we have stopped it. + */ + + zd_chip_disable_rx(chip); + ieee80211softmac_stop(netdev); + + zd_chip_disable_hwint(chip); + zd_chip_switch_radio_off(chip); + zd_chip_disable_int(chip); + + return 0; +} + +int zd_mac_set_mac_address(struct net_device *netdev, void *p) +{ + int r; + unsigned long flags; + struct sockaddr *addr = p; + struct zd_mac *mac = zd_netdev_mac(netdev); + struct zd_chip *chip = &mac->chip; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + dev_dbg_f(zd_mac_dev(mac), + "Setting MAC to " MAC_FMT "\n", MAC_ARG(addr->sa_data)); + + r = zd_write_mac_addr(chip, addr->sa_data); + if (r) + return r; + + spin_lock_irqsave(&mac->lock, flags); + memcpy(netdev->dev_addr, addr->sa_data, ETH_ALEN); + spin_unlock_irqrestore(&mac->lock, flags); + + return 0; +} + +int zd_mac_set_regdomain(struct zd_mac *mac, u8 regdomain) +{ + int r; + u8 channel; + + ZD_ASSERT(!irqs_disabled()); + spin_lock_irq(&mac->lock); + if (regdomain == 0) { + regdomain = mac->default_regdomain; + } + if (!zd_regdomain_supported(regdomain)) { + spin_unlock_irq(&mac->lock); + return -EINVAL; + } + mac->regdomain = regdomain; + channel = mac->requested_channel; + spin_unlock_irq(&mac->lock); + + r = zd_geo_init(zd_mac_to_ieee80211(mac), regdomain); + if (r) + return r; + if (!zd_regdomain_supports_channel(regdomain, channel)) { + r = reset_channel(mac); + if (r) + return r; + } + + return 0; +} + +u8 zd_mac_get_regdomain(struct zd_mac *mac) +{ + unsigned long flags; + u8 regdomain; + + spin_lock_irqsave(&mac->lock, flags); + regdomain = mac->regdomain; + spin_unlock_irqrestore(&mac->lock, flags); + return regdomain; +} + +static void set_channel(struct net_device *netdev, u8 channel) +{ + struct zd_mac *mac = zd_netdev_mac(netdev); + + dev_dbg_f(zd_mac_dev(mac), "channel %d\n", channel); + + zd_chip_set_channel(&mac->chip, channel); +} + +/* TODO: Should not work in Managed mode. */ +int zd_mac_request_channel(struct zd_mac *mac, u8 channel) +{ + unsigned long lock_flags; + struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); + + if (ieee->iw_mode == IW_MODE_INFRA) + return -EPERM; + + spin_lock_irqsave(&mac->lock, lock_flags); + if (!zd_regdomain_supports_channel(mac->regdomain, channel)) { + spin_unlock_irqrestore(&mac->lock, lock_flags); + return -EINVAL; + } + mac->requested_channel = channel; + spin_unlock_irqrestore(&mac->lock, lock_flags); + if (netif_running(mac->netdev)) + return zd_chip_set_channel(&mac->chip, channel); + else + return 0; +} + +int zd_mac_get_channel(struct zd_mac *mac, u8 *channel, u8 *flags) +{ + struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); + + *channel = zd_chip_get_channel(&mac->chip); + if (ieee->iw_mode != IW_MODE_INFRA) { + spin_lock_irq(&mac->lock); + *flags = *channel == mac->requested_channel ? + MAC_FIXED_CHANNEL : 0; + spin_unlock(&mac->lock); + } else { + *flags = 0; + } + dev_dbg_f(zd_mac_dev(mac), "channel %u flags %u\n", *channel, *flags); + return 0; +} + +/* If wrong rate is given, we are falling back to the slowest rate: 1MBit/s */ +static u8 cs_typed_rate(u8 cs_rate) +{ + static const u8 typed_rates[16] = { + [ZD_CS_CCK_RATE_1M] = ZD_CS_CCK|ZD_CS_CCK_RATE_1M, + [ZD_CS_CCK_RATE_2M] = ZD_CS_CCK|ZD_CS_CCK_RATE_2M, + [ZD_CS_CCK_RATE_5_5M] = ZD_CS_CCK|ZD_CS_CCK_RATE_5_5M, + [ZD_CS_CCK_RATE_11M] = ZD_CS_CCK|ZD_CS_CCK_RATE_11M, + [ZD_OFDM_RATE_6M] = ZD_CS_OFDM|ZD_OFDM_RATE_6M, + [ZD_OFDM_RATE_9M] = ZD_CS_OFDM|ZD_OFDM_RATE_9M, + [ZD_OFDM_RATE_12M] = ZD_CS_OFDM|ZD_OFDM_RATE_12M, + [ZD_OFDM_RATE_18M] = ZD_CS_OFDM|ZD_OFDM_RATE_18M, + [ZD_OFDM_RATE_24M] = ZD_CS_OFDM|ZD_OFDM_RATE_24M, + [ZD_OFDM_RATE_36M] = ZD_CS_OFDM|ZD_OFDM_RATE_36M, + [ZD_OFDM_RATE_48M] = ZD_CS_OFDM|ZD_OFDM_RATE_48M, + [ZD_OFDM_RATE_54M] = ZD_CS_OFDM|ZD_OFDM_RATE_54M, + }; + + ZD_ASSERT(ZD_CS_RATE_MASK == 0x0f); + return typed_rates[cs_rate & ZD_CS_RATE_MASK]; +} + +/* Fallback to lowest rate, if rate is unknown. */ +static u8 rate_to_cs_rate(u8 rate) +{ + switch (rate) { + case IEEE80211_CCK_RATE_2MB: + return ZD_CS_CCK_RATE_2M; + case IEEE80211_CCK_RATE_5MB: + return ZD_CS_CCK_RATE_5_5M; + case IEEE80211_CCK_RATE_11MB: + return ZD_CS_CCK_RATE_11M; + case IEEE80211_OFDM_RATE_6MB: + return ZD_OFDM_RATE_6M; + case IEEE80211_OFDM_RATE_9MB: + return ZD_OFDM_RATE_9M; + case IEEE80211_OFDM_RATE_12MB: + return ZD_OFDM_RATE_12M; + case IEEE80211_OFDM_RATE_18MB: + return ZD_OFDM_RATE_18M; + case IEEE80211_OFDM_RATE_24MB: + return ZD_OFDM_RATE_24M; + case IEEE80211_OFDM_RATE_36MB: + return ZD_OFDM_RATE_36M; + case IEEE80211_OFDM_RATE_48MB: + return ZD_OFDM_RATE_48M; + case IEEE80211_OFDM_RATE_54MB: + return ZD_OFDM_RATE_54M; + } + return ZD_CS_CCK_RATE_1M; +} + +int zd_mac_set_mode(struct zd_mac *mac, u32 mode) +{ + struct ieee80211_device *ieee; + + switch (mode) { + case IW_MODE_AUTO: + case IW_MODE_ADHOC: + case IW_MODE_INFRA: + mac->netdev->type = ARPHRD_ETHER; + break; + case IW_MODE_MONITOR: + mac->netdev->type = ARPHRD_IEEE80211_RADIOTAP; + break; + default: + dev_dbg_f(zd_mac_dev(mac), "wrong mode %u\n", mode); + return -EINVAL; + } + + ieee = zd_mac_to_ieee80211(mac); + ZD_ASSERT(!irqs_disabled()); + spin_lock_irq(&ieee->lock); + ieee->iw_mode = mode; + spin_unlock_irq(&ieee->lock); + + if (netif_running(mac->netdev)) + return reset_mode(mac); + + return 0; +} + +int zd_mac_get_mode(struct zd_mac *mac, u32 *mode) +{ + unsigned long flags; + struct ieee80211_device *ieee; + + ieee = zd_mac_to_ieee80211(mac); + spin_lock_irqsave(&ieee->lock, flags); + *mode = ieee->iw_mode; + spin_unlock_irqrestore(&ieee->lock, flags); + return 0; +} + +int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range) +{ + int i; + const struct channel_range *channel_range; + u8 regdomain; + + memset(range, 0, sizeof(*range)); + + /* FIXME: Not so important and depends on the mode. For 802.11g + * usually this value is used. It seems to be that Bit/s number is + * given here. + */ + range->throughput = 27 * 1000 * 1000; + + range->max_qual.qual = 100; + range->max_qual.level = 100; + + /* FIXME: Needs still to be tuned. */ + range->avg_qual.qual = 71; + range->avg_qual.level = 80; + + /* FIXME: depends on standard? */ + range->min_rts = 256; + range->max_rts = 2346; + + range->min_frag = MIN_FRAG_THRESHOLD; + range->max_frag = MAX_FRAG_THRESHOLD; + + range->max_encoding_tokens = WEP_KEYS; + range->num_encoding_sizes = 2; + range->encoding_size[0] = 5; + range->encoding_size[1] = WEP_KEY_LEN; + + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 20; + + ZD_ASSERT(!irqs_disabled()); + spin_lock_irq(&mac->lock); + regdomain = mac->regdomain; + spin_unlock_irq(&mac->lock); + channel_range = zd_channel_range(regdomain); + + range->num_channels = channel_range->end - channel_range->start; + range->old_num_channels = range->num_channels; + range->num_frequency = range->num_channels; + range->old_num_frequency = range->num_frequency; + + for (i = 0; i < range->num_frequency; i++) { + struct iw_freq *freq = &range->freq[i]; + freq->i = channel_range->start + i; + zd_channel_to_freq(freq, freq->i); + } + + return 0; +} + +static int zd_calc_tx_length_us(u8 *service, u8 cs_rate, u16 tx_length) +{ + static const u8 rate_divisor[] = { + [ZD_CS_CCK_RATE_1M] = 1, + [ZD_CS_CCK_RATE_2M] = 2, + [ZD_CS_CCK_RATE_5_5M] = 11, /* bits must be doubled */ + [ZD_CS_CCK_RATE_11M] = 11, + [ZD_OFDM_RATE_6M] = 6, + [ZD_OFDM_RATE_9M] = 9, + [ZD_OFDM_RATE_12M] = 12, + [ZD_OFDM_RATE_18M] = 18, + [ZD_OFDM_RATE_24M] = 24, + [ZD_OFDM_RATE_36M] = 36, + [ZD_OFDM_RATE_48M] = 48, + [ZD_OFDM_RATE_54M] = 54, + }; + + u32 bits = (u32)tx_length * 8; + u32 divisor; + + divisor = rate_divisor[cs_rate]; + if (divisor == 0) + return -EINVAL; + + switch (cs_rate) { + case ZD_CS_CCK_RATE_5_5M: + bits = (2*bits) + 10; /* round up to the next integer */ + break; + case ZD_CS_CCK_RATE_11M: + if (service) { + u32 t = bits % 11; + *service &= ~ZD_PLCP_SERVICE_LENGTH_EXTENSION; + if (0 < t && t <= 3) { + *service |= ZD_PLCP_SERVICE_LENGTH_EXTENSION; + } + } + bits += 10; /* round up to the next integer */ + break; + } + + return bits/divisor; +} + +enum { + R2M_SHORT_PREAMBLE = 0x01, + R2M_11A = 0x02, +}; + +static u8 cs_rate_to_modulation(u8 cs_rate, int flags) +{ + u8 modulation; + + modulation = cs_typed_rate(cs_rate); + if (flags & R2M_SHORT_PREAMBLE) { + switch (ZD_CS_RATE(modulation)) { + case ZD_CS_CCK_RATE_2M: + case ZD_CS_CCK_RATE_5_5M: + case ZD_CS_CCK_RATE_11M: + modulation |= ZD_CS_CCK_PREA_SHORT; + return modulation; + } + } + if (flags & R2M_11A) { + if (ZD_CS_TYPE(modulation) == ZD_CS_OFDM) + modulation |= ZD_CS_OFDM_MODE_11A; + } + return modulation; +} + +static void cs_set_modulation(struct zd_mac *mac, struct zd_ctrlset *cs, + struct ieee80211_hdr_4addr *hdr) +{ + struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev); + u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(hdr->frame_ctl)); + u8 rate, cs_rate; + int is_mgt = (ftype == IEEE80211_FTYPE_MGMT) != 0; + + /* FIXME: 802.11a? short preamble? */ + rate = ieee80211softmac_suggest_txrate(softmac, + is_multicast_ether_addr(hdr->addr1), is_mgt); + + cs_rate = rate_to_cs_rate(rate); + cs->modulation = cs_rate_to_modulation(cs_rate, 0); +} + +static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, + struct ieee80211_hdr_4addr *header) +{ + unsigned int tx_length = le16_to_cpu(cs->tx_length); + u16 fctl = le16_to_cpu(header->frame_ctl); + u16 ftype = WLAN_FC_GET_TYPE(fctl); + u16 stype = WLAN_FC_GET_STYPE(fctl); + + /* + * CONTROL: + * - start at 0x00 + * - if fragment 0, enable bit 0 + * - if backoff needed, enable bit 0 + * - if burst (backoff not needed) disable bit 0 + * - if multicast, enable bit 1 + * - if PS-POLL frame, enable bit 2 + * - if in INDEPENDENT_BSS mode and zd1205_DestPowerSave, then enable + * bit 4 (FIXME: wtf) + * - if frag_len > RTS threshold, set bit 5 as long if it isnt + * multicast or mgt + * - if bit 5 is set, and we are in OFDM mode, unset bit 5 and set bit + * 7 + */ + + cs->control = 0; + + /* First fragment */ + if (WLAN_GET_SEQ_FRAG(le16_to_cpu(header->seq_ctl)) == 0) + cs->control |= ZD_CS_NEED_RANDOM_BACKOFF; + + /* Multicast */ + if (is_multicast_ether_addr(header->addr1)) + cs->control |= ZD_CS_MULTICAST; + + /* PS-POLL */ + if (stype == IEEE80211_STYPE_PSPOLL) + cs->control |= ZD_CS_PS_POLL_FRAME; + + if (!is_multicast_ether_addr(header->addr1) && + ftype != IEEE80211_FTYPE_MGMT && + tx_length > zd_netdev_ieee80211(mac->netdev)->rts) + { + /* FIXME: check the logic */ + if (ZD_CS_TYPE(cs->modulation) == ZD_CS_OFDM) { + /* 802.11g */ + cs->control |= ZD_CS_SELF_CTS; + } else { /* 802.11b */ + cs->control |= ZD_CS_RTS; + } + } + + /* FIXME: Management frame? */ +} + +static int fill_ctrlset(struct zd_mac *mac, + struct ieee80211_txb *txb, + int frag_num) +{ + int r; + struct sk_buff *skb = txb->fragments[frag_num]; + struct ieee80211_hdr_4addr *hdr = + (struct ieee80211_hdr_4addr *) skb->data; + unsigned int frag_len = skb->len + IEEE80211_FCS_LEN; + unsigned int next_frag_len; + unsigned int packet_length; + struct zd_ctrlset *cs = (struct zd_ctrlset *) + skb_push(skb, sizeof(struct zd_ctrlset)); + + if (frag_num+1 < txb->nr_frags) { + next_frag_len = txb->fragments[frag_num+1]->len + + IEEE80211_FCS_LEN; + } else { + next_frag_len = 0; + } + ZD_ASSERT(frag_len <= 0xffff); + ZD_ASSERT(next_frag_len <= 0xffff); + + cs_set_modulation(mac, cs, hdr); + + cs->tx_length = cpu_to_le16(frag_len); + + cs_set_control(mac, cs, hdr); + + packet_length = frag_len + sizeof(struct zd_ctrlset) + 10; + ZD_ASSERT(packet_length <= 0xffff); + /* ZD1211B: Computing the length difference this way, gives us + * flexibility to compute the packet length. + */ + cs->packet_length = cpu_to_le16(mac->chip.is_zd1211b ? + packet_length - frag_len : packet_length); + + /* + * CURRENT LENGTH: + * - transmit frame length in microseconds + * - seems to be derived from frame length + * - see Cal_Us_Service() in zdinlinef.h + * - if macp->bTxBurstEnable is enabled, then multiply by 4 + * - bTxBurstEnable is never set in the vendor driver + * + * SERVICE: + * - "for PLCP configuration" + * - always 0 except in some situations at 802.11b 11M + * - see line 53 of zdinlinef.h + */ + cs->service = 0; + r = zd_calc_tx_length_us(&cs->service, ZD_CS_RATE(cs->modulation), + le16_to_cpu(cs->tx_length)); + if (r < 0) + return r; + cs->current_length = cpu_to_le16(r); + + if (next_frag_len == 0) { + cs->next_frame_length = 0; + } else { + r = zd_calc_tx_length_us(NULL, ZD_CS_RATE(cs->modulation), + next_frag_len); + if (r < 0) + return r; + cs->next_frame_length = cpu_to_le16(r); + } + + return 0; +} + +static int zd_mac_tx(struct zd_mac *mac, struct ieee80211_txb *txb, int pri) +{ + int i, r; + + for (i = 0; i < txb->nr_frags; i++) { + struct sk_buff *skb = txb->fragments[i]; + + r = fill_ctrlset(mac, txb, i); + if (r) + return r; + r = zd_usb_tx(&mac->chip.usb, skb->data, skb->len); + if (r) + return r; + } + + /* FIXME: shouldn't this be handled by the upper layers? */ + mac->netdev->trans_start = jiffies; + + ieee80211_txb_free(txb); + return 0; +} + +struct zd_rt_hdr { + struct ieee80211_radiotap_header rt_hdr; + u8 rt_flags; + u8 rt_rate; + u16 rt_channel; + u16 rt_chbitmask; +} __attribute__((packed)); + +static void fill_rt_header(void *buffer, struct zd_mac *mac, + const struct ieee80211_rx_stats *stats, + const struct rx_status *status) +{ + struct zd_rt_hdr *hdr = buffer; + + hdr->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; + hdr->rt_hdr.it_pad = 0; + hdr->rt_hdr.it_len = cpu_to_le16(sizeof(struct zd_rt_hdr)); + hdr->rt_hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | + (1 << IEEE80211_RADIOTAP_CHANNEL) | + (1 << IEEE80211_RADIOTAP_RATE)); + + hdr->rt_flags = 0; + if (status->decryption_type & (ZD_RX_WEP64|ZD_RX_WEP128|ZD_RX_WEP256)) + hdr->rt_flags |= IEEE80211_RADIOTAP_F_WEP; + + hdr->rt_rate = stats->rate / 5; + + /* FIXME: 802.11a */ + hdr->rt_channel = cpu_to_le16(ieee80211chan2mhz( + _zd_chip_get_channel(&mac->chip))); + hdr->rt_chbitmask = cpu_to_le16(IEEE80211_CHAN_2GHZ | + ((status->frame_status & ZD_RX_FRAME_MODULATION_MASK) == + ZD_RX_OFDM ? IEEE80211_CHAN_OFDM : IEEE80211_CHAN_CCK)); +} + +/* Returns 1 if the data packet is for us and 0 otherwise. */ +static int is_data_packet_for_us(struct ieee80211_device *ieee, + struct ieee80211_hdr_4addr *hdr) +{ + struct net_device *netdev = ieee->dev; + u16 fc = le16_to_cpu(hdr->frame_ctl); + + ZD_ASSERT(WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA); + + switch (ieee->iw_mode) { + case IW_MODE_ADHOC: + if ((fc & (IEEE80211_FCTL_TODS|IEEE80211_FCTL_FROMDS)) != 0 || + memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) != 0) + return 0; + break; + case IW_MODE_AUTO: + case IW_MODE_INFRA: + if ((fc & (IEEE80211_FCTL_TODS|IEEE80211_FCTL_FROMDS)) != + IEEE80211_FCTL_FROMDS || + memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) != 0) + return 0; + break; + default: + ZD_ASSERT(ieee->iw_mode != IW_MODE_MONITOR); + return 0; + } + + return memcmp(hdr->addr1, netdev->dev_addr, ETH_ALEN) == 0 || + is_multicast_ether_addr(hdr->addr1) || + (netdev->flags & IFF_PROMISC); +} + +/* Filters receiving packets. If it returns 1 send it to ieee80211_rx, if 0 + * return. If an error is detected -EINVAL is returned. ieee80211_rx_mgt() is + * called here. + * + * It has been based on ieee80211_rx_any. + */ +static int filter_rx(struct ieee80211_device *ieee, + const u8 *buffer, unsigned int length, + struct ieee80211_rx_stats *stats) +{ + struct ieee80211_hdr_4addr *hdr; + u16 fc; + + if (ieee->iw_mode == IW_MODE_MONITOR) + return 1; + + hdr = (struct ieee80211_hdr_4addr *)buffer; + fc = le16_to_cpu(hdr->frame_ctl); + if ((fc & IEEE80211_FCTL_VERS) != 0) + return -EINVAL; + + switch (WLAN_FC_GET_TYPE(fc)) { + case IEEE80211_FTYPE_MGMT: + if (length < sizeof(struct ieee80211_hdr_3addr)) + return -EINVAL; + ieee80211_rx_mgt(ieee, hdr, stats); + return 0; + case IEEE80211_FTYPE_CTL: + /* Ignore invalid short buffers */ + return 0; + case IEEE80211_FTYPE_DATA: + if (length < sizeof(struct ieee80211_hdr_3addr)) + return -EINVAL; + return is_data_packet_for_us(ieee, hdr); + } + + return -EINVAL; +} + +static void update_qual_rssi(struct zd_mac *mac, + const u8 *buffer, unsigned int length, + u8 qual_percent, u8 rssi_percent) +{ + unsigned long flags; + struct ieee80211_hdr_3addr *hdr; + int i; + + hdr = (struct ieee80211_hdr_3addr *)buffer; + if (length < offsetof(struct ieee80211_hdr_3addr, addr3)) + return; + if (memcmp(hdr->addr2, zd_mac_to_ieee80211(mac)->bssid, ETH_ALEN) != 0) + return; + + spin_lock_irqsave(&mac->lock, flags); + i = mac->stats_count % ZD_MAC_STATS_BUFFER_SIZE; + mac->qual_buffer[i] = qual_percent; + mac->rssi_buffer[i] = rssi_percent; + mac->stats_count++; + spin_unlock_irqrestore(&mac->lock, flags); +} + +static int fill_rx_stats(struct ieee80211_rx_stats *stats, + const struct rx_status **pstatus, + struct zd_mac *mac, + const u8 *buffer, unsigned int length) +{ + const struct rx_status *status; + + *pstatus = status = zd_tail(buffer, length, sizeof(struct rx_status)); + if (status->frame_status & ZD_RX_ERROR) { + /* FIXME: update? */ + return -EINVAL; + } + memset(stats, 0, sizeof(struct ieee80211_rx_stats)); + stats->len = length - (ZD_PLCP_HEADER_SIZE + IEEE80211_FCS_LEN + + + sizeof(struct rx_status)); + /* FIXME: 802.11a */ + stats->freq = IEEE80211_24GHZ_BAND; + stats->received_channel = _zd_chip_get_channel(&mac->chip); + stats->rssi = zd_rx_strength_percent(status->signal_strength); + stats->signal = zd_rx_qual_percent(buffer, + length - sizeof(struct rx_status), + status); + stats->mask = IEEE80211_STATMASK_RSSI | IEEE80211_STATMASK_SIGNAL; + stats->rate = zd_rx_rate(buffer, status); + if (stats->rate) + stats->mask |= IEEE80211_STATMASK_RATE; + + return 0; +} + +int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length) +{ + int r; + struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); + struct ieee80211_rx_stats stats; + const struct rx_status *status; + struct sk_buff *skb; + + if (length < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN + + IEEE80211_FCS_LEN + sizeof(struct rx_status)) + return -EINVAL; + + r = fill_rx_stats(&stats, &status, mac, buffer, length); + if (r) + return r; + + length -= ZD_PLCP_HEADER_SIZE+IEEE80211_FCS_LEN+ + sizeof(struct rx_status); + buffer += ZD_PLCP_HEADER_SIZE; + + update_qual_rssi(mac, buffer, length, stats.signal, stats.rssi); + + r = filter_rx(ieee, buffer, length, &stats); + if (r <= 0) + return r; + + skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length); + if (!skb) + return -ENOMEM; + if (ieee->iw_mode == IW_MODE_MONITOR) + fill_rt_header(skb_put(skb, sizeof(struct zd_rt_hdr)), mac, + &stats, status); + memcpy(skb_put(skb, length), buffer, length); + + r = ieee80211_rx(ieee, skb, &stats); + if (!r) { + ZD_ASSERT(in_irq()); + dev_kfree_skb_irq(skb); + } + return 0; +} + +static int netdev_tx(struct ieee80211_txb *txb, struct net_device *netdev, + int pri) +{ + return zd_mac_tx(zd_netdev_mac(netdev), txb, pri); +} + +static void set_security(struct net_device *netdev, + struct ieee80211_security *sec) +{ + struct ieee80211_device *ieee = zd_netdev_ieee80211(netdev); + struct ieee80211_security *secinfo = &ieee->sec; + int keyidx; + + dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), "\n"); + + for (keyidx = 0; keyidx<WEP_KEYS; keyidx++) + if (sec->flags & (1<<keyidx)) { + secinfo->encode_alg[keyidx] = sec->encode_alg[keyidx]; + secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx]; + memcpy(secinfo->keys[keyidx], sec->keys[keyidx], + SCM_KEY_LEN); + } + + if (sec->flags & SEC_ACTIVE_KEY) { + secinfo->active_key = sec->active_key; + dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), + " .active_key = %d\n", sec->active_key); + } + if (sec->flags & SEC_UNICAST_GROUP) { + secinfo->unicast_uses_group = sec->unicast_uses_group; + dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), + " .unicast_uses_group = %d\n", + sec->unicast_uses_group); + } + if (sec->flags & SEC_LEVEL) { + secinfo->level = sec->level; + dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), + " .level = %d\n", sec->level); + } + if (sec->flags & SEC_ENABLED) { + secinfo->enabled = sec->enabled; + dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), + " .enabled = %d\n", sec->enabled); + } + if (sec->flags & SEC_ENCRYPT) { + secinfo->encrypt = sec->encrypt; + dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), + " .encrypt = %d\n", sec->encrypt); + } + if (sec->flags & SEC_AUTH_MODE) { + secinfo->auth_mode = sec->auth_mode; + dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), + " .auth_mode = %d\n", sec->auth_mode); + } +} + +static void ieee_init(struct ieee80211_device *ieee) +{ + ieee->mode = IEEE_B | IEEE_G; + ieee->freq_band = IEEE80211_24GHZ_BAND; + ieee->modulation = IEEE80211_OFDM_MODULATION | IEEE80211_CCK_MODULATION; + ieee->tx_headroom = sizeof(struct zd_ctrlset); + ieee->set_security = set_security; + ieee->hard_start_xmit = netdev_tx; + + /* Software encryption/decryption for now */ + ieee->host_build_iv = 0; + ieee->host_encrypt = 1; + ieee->host_decrypt = 1; + + /* FIXME: default to managed mode, until ieee80211 and zd1211rw can + * correctly support AUTO */ + ieee->iw_mode = IW_MODE_INFRA; +} + +static void softmac_init(struct ieee80211softmac_device *sm) +{ + sm->set_channel = set_channel; +} + +struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev) +{ + struct zd_mac *mac = zd_netdev_mac(ndev); + struct iw_statistics *iw_stats = &mac->iw_stats; + unsigned int i, count, qual_total, rssi_total; + + memset(iw_stats, 0, sizeof(struct iw_statistics)); + /* We are not setting the status, because ieee->state is not updated + * at all and this driver doesn't track authentication state. + */ + spin_lock_irq(&mac->lock); + count = mac->stats_count < ZD_MAC_STATS_BUFFER_SIZE ? + mac->stats_count : ZD_MAC_STATS_BUFFER_SIZE; + qual_total = rssi_total = 0; + for (i = 0; i < count; i++) { + qual_total += mac->qual_buffer[i]; + rssi_total += mac->rssi_buffer[i]; + } + spin_unlock_irq(&mac->lock); + iw_stats->qual.updated = IW_QUAL_NOISE_INVALID; + if (count > 0) { + iw_stats->qual.qual = qual_total / count; + iw_stats->qual.level = rssi_total / count; + iw_stats->qual.updated |= + IW_QUAL_QUAL_UPDATED|IW_QUAL_LEVEL_UPDATED; + } else { + iw_stats->qual.updated |= + IW_QUAL_QUAL_INVALID|IW_QUAL_LEVEL_INVALID; + } + /* TODO: update counter */ + return iw_stats; +} + +#ifdef DEBUG +static const char* decryption_types[] = { + [ZD_RX_NO_WEP] = "none", + [ZD_RX_WEP64] = "WEP64", + [ZD_RX_TKIP] = "TKIP", + [ZD_RX_AES] = "AES", + [ZD_RX_WEP128] = "WEP128", + [ZD_RX_WEP256] = "WEP256", +}; + +static const char *decryption_type_string(u8 type) +{ + const char *s; + + if (type < ARRAY_SIZE(decryption_types)) { + s = decryption_types[type]; + } else { + s = NULL; + } + return s ? s : "unknown"; +} + +static int is_ofdm(u8 frame_status) +{ + return (frame_status & ZD_RX_OFDM); +} + +void zd_dump_rx_status(const struct rx_status *status) +{ + const char* modulation; + u8 quality; + + if (is_ofdm(status->frame_status)) { + modulation = "ofdm"; + quality = status->signal_quality_ofdm; + } else { + modulation = "cck"; + quality = status->signal_quality_cck; + } + pr_debug("rx status %s strength %#04x qual %#04x decryption %s\n", + modulation, status->signal_strength, quality, + decryption_type_string(status->decryption_type)); + if (status->frame_status & ZD_RX_ERROR) { + pr_debug("rx error %s%s%s%s%s%s\n", + (status->frame_status & ZD_RX_TIMEOUT_ERROR) ? + "timeout " : "", + (status->frame_status & ZD_RX_FIFO_OVERRUN_ERROR) ? + "fifo " : "", + (status->frame_status & ZD_RX_DECRYPTION_ERROR) ? + "decryption " : "", + (status->frame_status & ZD_RX_CRC32_ERROR) ? + "crc32 " : "", + (status->frame_status & ZD_RX_NO_ADDR1_MATCH_ERROR) ? + "addr1 " : "", + (status->frame_status & ZD_RX_CRC16_ERROR) ? + "crc16" : ""); + } +} +#endif /* DEBUG */ diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h new file mode 100644 index 000000000..b3ba49b84 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_mac.h @@ -0,0 +1,193 @@ +/* zd_mac.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ZD_MAC_H +#define _ZD_MAC_H + +#include <linux/wireless.h> +#include <linux/kernel.h> +#include <net/ieee80211.h> +#include <net/ieee80211softmac.h> + +#include "zd_chip.h" +#include "zd_netdev.h" + +struct zd_ctrlset { + u8 modulation; + __le16 tx_length; + u8 control; + /* stores only the difference to tx_length on ZD1211B */ + __le16 packet_length; + __le16 current_length; + u8 service; + __le16 next_frame_length; +} __attribute__((packed)); + +#define ZD_CS_RESERVED_SIZE 25 + +/* zd_crtlset field modulation */ +#define ZD_CS_RATE_MASK 0x0f +#define ZD_CS_TYPE_MASK 0x10 +#define ZD_CS_RATE(modulation) ((modulation) & ZD_CS_RATE_MASK) +#define ZD_CS_TYPE(modulation) ((modulation) & ZD_CS_TYPE_MASK) + +#define ZD_CS_CCK 0x00 +#define ZD_CS_OFDM 0x10 + +#define ZD_CS_CCK_RATE_1M 0x00 +#define ZD_CS_CCK_RATE_2M 0x01 +#define ZD_CS_CCK_RATE_5_5M 0x02 +#define ZD_CS_CCK_RATE_11M 0x03 +/* The rates for OFDM are encoded as in the PLCP header. Use ZD_OFDM_RATE_*. + */ + +/* bit 5 is preamble (when in CCK mode), or a/g selection (when in OFDM mode) */ +#define ZD_CS_CCK_PREA_LONG 0x00 +#define ZD_CS_CCK_PREA_SHORT 0x20 +#define ZD_CS_OFDM_MODE_11G 0x00 +#define ZD_CS_OFDM_MODE_11A 0x20 + +/* zd_ctrlset control field */ +#define ZD_CS_NEED_RANDOM_BACKOFF 0x01 +#define ZD_CS_MULTICAST 0x02 + +#define ZD_CS_FRAME_TYPE_MASK 0x0c +#define ZD_CS_DATA_FRAME 0x00 +#define ZD_CS_PS_POLL_FRAME 0x04 +#define ZD_CS_MANAGEMENT_FRAME 0x08 +#define ZD_CS_NO_SEQUENCE_CTL_FRAME 0x0c + +#define ZD_CS_WAKE_DESTINATION 0x10 +#define ZD_CS_RTS 0x20 +#define ZD_CS_ENCRYPT 0x40 +#define ZD_CS_SELF_CTS 0x80 + +/* Incoming frames are prepended by a PLCP header */ +#define ZD_PLCP_HEADER_SIZE 5 + +struct rx_length_info { + __le16 length[3]; + __le16 tag; +} __attribute__((packed)); + +#define RX_LENGTH_INFO_TAG 0x697e + +struct rx_status { + u8 signal_quality_cck; + /* rssi */ + u8 signal_strength; + u8 signal_quality_ofdm; + u8 decryption_type; + u8 frame_status; +} __attribute__((packed)); + +/* rx_status field decryption_type */ +#define ZD_RX_NO_WEP 0 +#define ZD_RX_WEP64 1 +#define ZD_RX_TKIP 2 +#define ZD_RX_AES 4 +#define ZD_RX_WEP128 5 +#define ZD_RX_WEP256 6 + +/* rx_status field frame_status */ +#define ZD_RX_FRAME_MODULATION_MASK 0x01 +#define ZD_RX_CCK 0x00 +#define ZD_RX_OFDM 0x01 + +#define ZD_RX_TIMEOUT_ERROR 0x02 +#define ZD_RX_FIFO_OVERRUN_ERROR 0x04 +#define ZD_RX_DECRYPTION_ERROR 0x08 +#define ZD_RX_CRC32_ERROR 0x10 +#define ZD_RX_NO_ADDR1_MATCH_ERROR 0x20 +#define ZD_RX_CRC16_ERROR 0x40 +#define ZD_RX_ERROR 0x80 + +enum mac_flags { + MAC_FIXED_CHANNEL = 0x01, +}; + +#define ZD_MAC_STATS_BUFFER_SIZE 16 + +struct zd_mac { + struct net_device *netdev; + struct zd_chip chip; + spinlock_t lock; + /* Unlocked reading possible */ + struct iw_statistics iw_stats; + unsigned int stats_count; + u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE]; + u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE]; + u8 regdomain; + u8 default_regdomain; + u8 requested_channel; +}; + +static inline struct ieee80211_device *zd_mac_to_ieee80211(struct zd_mac *mac) +{ + return zd_netdev_ieee80211(mac->netdev); +} + +static inline struct zd_mac *zd_netdev_mac(struct net_device *netdev) +{ + return ieee80211softmac_priv(netdev); +} + +static inline struct zd_mac *zd_chip_to_mac(struct zd_chip *chip) +{ + return container_of(chip, struct zd_mac, chip); +} + +static inline struct zd_mac *zd_usb_to_mac(struct zd_usb *usb) +{ + return zd_chip_to_mac(zd_usb_to_chip(usb)); +} + +#define zd_mac_dev(mac) (zd_chip_dev(&(mac)->chip)) + +int zd_mac_init(struct zd_mac *mac, + struct net_device *netdev, + struct usb_interface *intf); +void zd_mac_clear(struct zd_mac *mac); + +int zd_mac_init_hw(struct zd_mac *mac, u8 device_type); + +int zd_mac_open(struct net_device *netdev); +int zd_mac_stop(struct net_device *netdev); +int zd_mac_set_mac_address(struct net_device *dev, void *p); + +int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length); + +int zd_mac_set_regdomain(struct zd_mac *zd_mac, u8 regdomain); +u8 zd_mac_get_regdomain(struct zd_mac *zd_mac); + +int zd_mac_request_channel(struct zd_mac *mac, u8 channel); +int zd_mac_get_channel(struct zd_mac *mac, u8 *channel, u8 *flags); + +int zd_mac_set_mode(struct zd_mac *mac, u32 mode); +int zd_mac_get_mode(struct zd_mac *mac, u32 *mode); + +int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range); + +struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev); + +#ifdef DEBUG +void zd_dump_rx_status(const struct rx_status *status); +#else +#define zd_dump_rx_status(status) +#endif /* DEBUG */ + +#endif /* _ZD_MAC_H */ diff --git a/drivers/net/wireless/zd1211rw/zd_netdev.c b/drivers/net/wireless/zd1211rw/zd_netdev.c new file mode 100644 index 000000000..9df232c2c --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_netdev.c @@ -0,0 +1,267 @@ +/* zd_netdev.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <net/ieee80211.h> +#include <net/ieee80211softmac.h> +#include <net/ieee80211softmac_wx.h> +#include <net/iw_handler.h> + +#include "zd_def.h" +#include "zd_netdev.h" +#include "zd_mac.h" +#include "zd_ieee80211.h" + +/* Region 0 means reset regdomain to default. */ +static int zd_set_regdomain(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *req, char *extra) +{ + const u8 *regdomain = (u8 *)req; + return zd_mac_set_regdomain(zd_netdev_mac(netdev), *regdomain); +} + +static int zd_get_regdomain(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *req, char *extra) +{ + u8 *regdomain = (u8 *)req; + if (!regdomain) + return -EINVAL; + *regdomain = zd_mac_get_regdomain(zd_netdev_mac(netdev)); + return 0; +} + +static const struct iw_priv_args zd_priv_args[] = { + { + .cmd = ZD_PRIV_SET_REGDOMAIN, + .set_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, + .name = "set_regdomain", + }, + { + .cmd = ZD_PRIV_GET_REGDOMAIN, + .get_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, + .name = "get_regdomain", + }, +}; + +#define PRIV_OFFSET(x) [(x)-SIOCIWFIRSTPRIV] + +static const iw_handler zd_priv_handler[] = { + PRIV_OFFSET(ZD_PRIV_SET_REGDOMAIN) = zd_set_regdomain, + PRIV_OFFSET(ZD_PRIV_GET_REGDOMAIN) = zd_get_regdomain, +}; + +static int iw_get_name(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *req, char *extra) +{ + /* FIXME: check whether 802.11a will also supported, add also + * zd1211B, if we support it. + */ + strlcpy(req->name, "802.11g zd1211", IFNAMSIZ); + return 0; +} + +static int iw_set_freq(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *req, char *extra) +{ + int r; + struct zd_mac *mac = zd_netdev_mac(netdev); + struct iw_freq *freq = &req->freq; + u8 channel; + + r = zd_find_channel(&channel, freq); + if (r < 0) + return r; + r = zd_mac_request_channel(mac, channel); + return r; +} + +static int iw_get_freq(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *req, char *extra) +{ + int r; + struct zd_mac *mac = zd_netdev_mac(netdev); + struct iw_freq *freq = &req->freq; + u8 channel; + u8 flags; + + r = zd_mac_get_channel(mac, &channel, &flags); + if (r) + return r; + + freq->flags = (flags & MAC_FIXED_CHANNEL) ? + IW_FREQ_FIXED : IW_FREQ_AUTO; + dev_dbg_f(zd_mac_dev(mac), "channel %s\n", + (flags & MAC_FIXED_CHANNEL) ? "fixed" : "auto"); + return zd_channel_to_freq(freq, channel); +} + +static int iw_set_mode(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *req, char *extra) +{ + return zd_mac_set_mode(zd_netdev_mac(netdev), req->mode); +} + +static int iw_get_mode(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *req, char *extra) +{ + return zd_mac_get_mode(zd_netdev_mac(netdev), &req->mode); +} + +static int iw_get_range(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *req, char *extra) +{ + struct iw_range *range = (struct iw_range *)extra; + + dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), "\n"); + req->data.length = sizeof(*range); + return zd_mac_get_range(zd_netdev_mac(netdev), range); +} + +static int iw_set_encode(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + return ieee80211_wx_set_encode(zd_netdev_ieee80211(netdev), info, + data, extra); +} + +static int iw_get_encode(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + return ieee80211_wx_get_encode(zd_netdev_ieee80211(netdev), info, + data, extra); +} + +static int iw_set_encodeext(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + return ieee80211_wx_set_encodeext(zd_netdev_ieee80211(netdev), info, + data, extra); +} + +static int iw_get_encodeext(struct net_device *netdev, + struct iw_request_info *info, + union iwreq_data *data, + char *extra) +{ + return ieee80211_wx_get_encodeext(zd_netdev_ieee80211(netdev), info, + data, extra); +} + +#define WX(x) [(x)-SIOCIWFIRST] + +static const iw_handler zd_standard_iw_handlers[] = { + WX(SIOCGIWNAME) = iw_get_name, + WX(SIOCSIWFREQ) = iw_set_freq, + WX(SIOCGIWFREQ) = iw_get_freq, + WX(SIOCSIWMODE) = iw_set_mode, + WX(SIOCGIWMODE) = iw_get_mode, + WX(SIOCGIWRANGE) = iw_get_range, + WX(SIOCSIWENCODE) = iw_set_encode, + WX(SIOCGIWENCODE) = iw_get_encode, + WX(SIOCSIWENCODEEXT) = iw_set_encodeext, + WX(SIOCGIWENCODEEXT) = iw_get_encodeext, + WX(SIOCSIWAUTH) = ieee80211_wx_set_auth, + WX(SIOCGIWAUTH) = ieee80211_wx_get_auth, + WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan, + WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results, + WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid, + WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid, + WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap, + WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap, + WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate, + WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate, + WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie, + WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie, + WX(SIOCSIWMLME) = ieee80211softmac_wx_set_mlme, +}; + +static const struct iw_handler_def iw_handler_def = { + .standard = zd_standard_iw_handlers, + .num_standard = ARRAY_SIZE(zd_standard_iw_handlers), + .private = zd_priv_handler, + .num_private = ARRAY_SIZE(zd_priv_handler), + .private_args = zd_priv_args, + .num_private_args = ARRAY_SIZE(zd_priv_args), + .get_wireless_stats = zd_mac_get_wireless_stats, +}; + +struct net_device *zd_netdev_alloc(struct usb_interface *intf) +{ + int r; + struct net_device *netdev; + struct zd_mac *mac; + + netdev = alloc_ieee80211softmac(sizeof(struct zd_mac)); + if (!netdev) { + dev_dbg_f(&intf->dev, "out of memory\n"); + return NULL; + } + + mac = zd_netdev_mac(netdev); + r = zd_mac_init(mac, netdev, intf); + if (r) { + usb_set_intfdata(intf, NULL); + free_ieee80211(netdev); + return NULL; + } + + SET_MODULE_OWNER(netdev); + SET_NETDEV_DEV(netdev, &intf->dev); + + dev_dbg_f(&intf->dev, "netdev->flags %#06hx\n", netdev->flags); + dev_dbg_f(&intf->dev, "netdev->features %#010lx\n", netdev->features); + + netdev->open = zd_mac_open; + netdev->stop = zd_mac_stop; + /* netdev->get_stats = */ + /* netdev->set_multicast_list = */ + netdev->set_mac_address = zd_mac_set_mac_address; + netdev->wireless_handlers = &iw_handler_def; + /* netdev->ethtool_ops = */ + + return netdev; +} + +void zd_netdev_free(struct net_device *netdev) +{ + if (!netdev) + return; + + zd_mac_clear(zd_netdev_mac(netdev)); + free_ieee80211(netdev); +} + +void zd_netdev_disconnect(struct net_device *netdev) +{ + unregister_netdev(netdev); +} diff --git a/drivers/net/wireless/zd1211rw/zd_netdev.h b/drivers/net/wireless/zd1211rw/zd_netdev.h new file mode 100644 index 000000000..374a95707 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_netdev.h @@ -0,0 +1,45 @@ +/* zd_netdev.h: Header for net device related functions. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ZD_NETDEV_H +#define _ZD_NETDEV_H + +#include <linux/usb.h> +#include <linux/netdevice.h> +#include <net/ieee80211.h> + +#define ZD_PRIV_SET_REGDOMAIN (SIOCIWFIRSTPRIV) +#define ZD_PRIV_GET_REGDOMAIN (SIOCIWFIRSTPRIV+1) + +static inline struct ieee80211_device *zd_netdev_ieee80211( + struct net_device *ndev) +{ + return netdev_priv(ndev); +} + +static inline struct net_device *zd_ieee80211_to_netdev( + struct ieee80211_device *ieee) +{ + return ieee->dev; +} + +struct net_device *zd_netdev_alloc(struct usb_interface *intf); +void zd_netdev_free(struct net_device *netdev); + +void zd_netdev_disconnect(struct net_device *netdev); + +#endif /* _ZD_NETDEV_H */ diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c new file mode 100644 index 000000000..d3770d2c6 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_rf.c @@ -0,0 +1,151 @@ +/* zd_rf.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/errno.h> +#include <linux/string.h> + +#include "zd_def.h" +#include "zd_rf.h" +#include "zd_ieee80211.h" +#include "zd_chip.h" + +static const char *rfs[] = { + [0] = "unknown RF0", + [1] = "unknown RF1", + [UW2451_RF] = "UW2451_RF", + [UCHIP_RF] = "UCHIP_RF", + [AL2230_RF] = "AL2230_RF", + [AL7230B_RF] = "AL7230B_RF", + [THETA_RF] = "THETA_RF", + [AL2210_RF] = "AL2210_RF", + [MAXIM_NEW_RF] = "MAXIM_NEW_RF", + [UW2453_RF] = "UW2453_RF", + [AL2230S_RF] = "AL2230S_RF", + [RALINK_RF] = "RALINK_RF", + [INTERSIL_RF] = "INTERSIL_RF", + [RF2959_RF] = "RF2959_RF", + [MAXIM_NEW2_RF] = "MAXIM_NEW2_RF", + [PHILIPS_RF] = "PHILIPS_RF", +}; + +const char *zd_rf_name(u8 type) +{ + if (type & 0xf0) + type = 0; + return rfs[type]; +} + +void zd_rf_init(struct zd_rf *rf) +{ + memset(rf, 0, sizeof(*rf)); +} + +void zd_rf_clear(struct zd_rf *rf) +{ + memset(rf, 0, sizeof(*rf)); +} + +int zd_rf_init_hw(struct zd_rf *rf, u8 type) +{ + int r, t; + struct zd_chip *chip = zd_rf_to_chip(rf); + + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + switch (type) { + case RF2959_RF: + r = zd_rf_init_rf2959(rf); + if (r) + return r; + break; + case AL2230_RF: + r = zd_rf_init_al2230(rf); + if (r) + return r; + break; + default: + dev_err(zd_chip_dev(chip), + "RF %s %#x is not supported\n", zd_rf_name(type), type); + rf->type = 0; + return -ENODEV; + } + + rf->type = type; + + r = zd_chip_lock_phy_regs(chip); + if (r) + return r; + t = rf->init_hw(rf); + r = zd_chip_unlock_phy_regs(chip); + if (t) + r = t; + return r; +} + +int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size) +{ + return scnprintf(buffer, size, "%s", zd_rf_name(rf->type)); +} + +int zd_rf_set_channel(struct zd_rf *rf, u8 channel) +{ + int r; + + ZD_ASSERT(mutex_is_locked(&zd_rf_to_chip(rf)->mutex)); + if (channel < MIN_CHANNEL24) + return -EINVAL; + if (channel > MAX_CHANNEL24) + return -EINVAL; + dev_dbg_f(zd_chip_dev(zd_rf_to_chip(rf)), "channel: %d\n", channel); + + r = rf->set_channel(rf, channel); + if (r >= 0) + rf->channel = channel; + return r; +} + +int zd_switch_radio_on(struct zd_rf *rf) +{ + int r, t; + struct zd_chip *chip = zd_rf_to_chip(rf); + + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + r = zd_chip_lock_phy_regs(chip); + if (r) + return r; + t = rf->switch_radio_on(rf); + r = zd_chip_unlock_phy_regs(chip); + if (t) + r = t; + return r; +} + +int zd_switch_radio_off(struct zd_rf *rf) +{ + int r, t; + struct zd_chip *chip = zd_rf_to_chip(rf); + + /* TODO: move phy regs handling to zd_chip */ + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + r = zd_chip_lock_phy_regs(chip); + if (r) + return r; + t = rf->switch_radio_off(rf); + r = zd_chip_unlock_phy_regs(chip); + if (t) + r = t; + return r; +} diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h new file mode 100644 index 000000000..ea30f693f --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_rf.h @@ -0,0 +1,82 @@ +/* zd_rf.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ZD_RF_H +#define _ZD_RF_H + +#include "zd_types.h" + +#define UW2451_RF 0x2 +#define UCHIP_RF 0x3 +#define AL2230_RF 0x4 +#define AL7230B_RF 0x5 /* a,b,g */ +#define THETA_RF 0x6 +#define AL2210_RF 0x7 +#define MAXIM_NEW_RF 0x8 +#define UW2453_RF 0x9 +#define AL2230S_RF 0xa +#define RALINK_RF 0xb +#define INTERSIL_RF 0xc +#define RF2959_RF 0xd +#define MAXIM_NEW2_RF 0xe +#define PHILIPS_RF 0xf + +#define RF_CHANNEL(ch) [(ch)-1] + +/* Provides functions of the RF transceiver. */ + +enum { + RF_REG_BITS = 6, + RF_VALUE_BITS = 18, + RF_RV_BITS = RF_REG_BITS + RF_VALUE_BITS, +}; + +struct zd_rf { + u8 type; + + u8 channel; + /* + * Whether this RF should patch the 6M band edge + * (assuming E2P_POD agrees) + */ + u8 patch_6m_band_edge:1; + + /* RF-specific functions */ + int (*init_hw)(struct zd_rf *rf); + int (*set_channel)(struct zd_rf *rf, u8 channel); + int (*switch_radio_on)(struct zd_rf *rf); + int (*switch_radio_off)(struct zd_rf *rf); +}; + +const char *zd_rf_name(u8 type); +void zd_rf_init(struct zd_rf *rf); +void zd_rf_clear(struct zd_rf *rf); +int zd_rf_init_hw(struct zd_rf *rf, u8 type); + +int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size); + +int zd_rf_set_channel(struct zd_rf *rf, u8 channel); + +int zd_switch_radio_on(struct zd_rf *rf); +int zd_switch_radio_off(struct zd_rf *rf); + +/* Functions for individual RF chips */ + +int zd_rf_init_rf2959(struct zd_rf *rf); +int zd_rf_init_al2230(struct zd_rf *rf); + +#endif /* _ZD_RF_H */ diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c new file mode 100644 index 000000000..0948b25f6 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c @@ -0,0 +1,308 @@ +/* zd_rf_al2230.c: Functions for the AL2230 RF controller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/kernel.h> + +#include "zd_rf.h" +#include "zd_usb.h" +#include "zd_chip.h" + +static const u32 al2230_table[][3] = { + RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, }, + RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, }, + RF_CHANNEL( 3) = { 0x03e790, 0x033331, 0x00000d, }, + RF_CHANNEL( 4) = { 0x03e790, 0x0b3331, 0x00000d, }, + RF_CHANNEL( 5) = { 0x03f7a0, 0x033331, 0x00000d, }, + RF_CHANNEL( 6) = { 0x03f7a0, 0x0b3331, 0x00000d, }, + RF_CHANNEL( 7) = { 0x03e7a0, 0x033331, 0x00000d, }, + RF_CHANNEL( 8) = { 0x03e7a0, 0x0b3331, 0x00000d, }, + RF_CHANNEL( 9) = { 0x03f7b0, 0x033331, 0x00000d, }, + RF_CHANNEL(10) = { 0x03f7b0, 0x0b3331, 0x00000d, }, + RF_CHANNEL(11) = { 0x03e7b0, 0x033331, 0x00000d, }, + RF_CHANNEL(12) = { 0x03e7b0, 0x0b3331, 0x00000d, }, + RF_CHANNEL(13) = { 0x03f7c0, 0x033331, 0x00000d, }, + RF_CHANNEL(14) = { 0x03e7c0, 0x066661, 0x00000d, }, +}; + +static int zd1211_al2230_init_hw(struct zd_rf *rf) +{ + int r; + struct zd_chip *chip = zd_rf_to_chip(rf); + + static const struct zd_ioreq16 ioreqs[] = { + { CR15, 0x20 }, { CR23, 0x40 }, { CR24, 0x20 }, + { CR26, 0x11 }, { CR28, 0x3e }, { CR29, 0x00 }, + { CR44, 0x33 }, { CR106, 0x2a }, { CR107, 0x1a }, + { CR109, 0x09 }, { CR110, 0x27 }, { CR111, 0x2b }, + { CR112, 0x2b }, { CR119, 0x0a }, { CR10, 0x89 }, + /* for newest (3rd cut) AL2300 */ + { CR17, 0x28 }, + { CR26, 0x93 }, { CR34, 0x30 }, + /* for newest (3rd cut) AL2300 */ + { CR35, 0x3e }, + { CR41, 0x24 }, { CR44, 0x32 }, + /* for newest (3rd cut) AL2300 */ + { CR46, 0x96 }, + { CR47, 0x1e }, { CR79, 0x58 }, { CR80, 0x30 }, + { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, + { CR92, 0x0a }, { CR99, 0x28 }, { CR100, 0x00 }, + { CR101, 0x13 }, { CR102, 0x27 }, { CR106, 0x24 }, + { CR107, 0x2a }, { CR109, 0x09 }, { CR110, 0x13 }, + { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, + { CR114, 0x27 }, + /* for newest (3rd cut) AL2300 */ + { CR115, 0x24 }, + { CR116, 0x24 }, { CR117, 0xf4 }, { CR118, 0xfc }, + { CR119, 0x10 }, { CR120, 0x4f }, { CR121, 0x77 }, + { CR122, 0xe0 }, { CR137, 0x88 }, { CR252, 0xff }, + { CR253, 0xff }, + + /* These following happen separately in the vendor driver */ + { }, + + /* shdnb(PLL_ON)=0 */ + { CR251, 0x2f }, + /* shdnb(PLL_ON)=1 */ + { CR251, 0x3f }, + { CR138, 0x28 }, { CR203, 0x06 }, + }; + + static const u32 rv[] = { + /* Channel 1 */ + 0x03f790, + 0x033331, + 0x00000d, + + 0x0b3331, + 0x03b812, + 0x00fff3, + 0x000da4, + 0x0f4dc5, /* fix freq shift, 0x04edc5 */ + 0x0805b6, + 0x011687, + 0x000688, + 0x0403b9, /* external control TX power (CR31) */ + 0x00dbba, + 0x00099b, + 0x0bdffc, + 0x00000d, + 0x00500f, + + /* These writes happen separately in the vendor driver */ + 0x00d00f, + 0x004c0f, + 0x00540f, + 0x00700f, + 0x00500f, + }; + + r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); + if (r) + return r; + + r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS); + if (r) + return r; + + return 0; +} + +static int zd1211b_al2230_init_hw(struct zd_rf *rf) +{ + int r; + struct zd_chip *chip = zd_rf_to_chip(rf); + + static const struct zd_ioreq16 ioreqs1[] = { + { CR10, 0x89 }, { CR15, 0x20 }, + { CR17, 0x2B }, /* for newest(3rd cut) AL2230 */ + { CR23, 0x40 }, { CR24, 0x20 }, { CR26, 0x93 }, + { CR28, 0x3e }, { CR29, 0x00 }, + { CR33, 0x28 }, /* 5621 */ + { CR34, 0x30 }, + { CR35, 0x3e }, /* for newest(3rd cut) AL2230 */ + { CR41, 0x24 }, { CR44, 0x32 }, + { CR46, 0x99 }, /* for newest(3rd cut) AL2230 */ + { CR47, 0x1e }, + + /* ZD1211B 05.06.10 */ + { CR48, 0x00 }, { CR49, 0x00 }, { CR51, 0x01 }, + { CR52, 0x80 }, { CR53, 0x7e }, { CR65, 0x00 }, + { CR66, 0x00 }, { CR67, 0x00 }, { CR68, 0x00 }, + { CR69, 0x28 }, + + { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, + { CR87, 0x0a }, { CR89, 0x04 }, + { CR91, 0x00 }, /* 5621 */ + { CR92, 0x0a }, + { CR98, 0x8d }, /* 4804, for 1212 new algorithm */ + { CR99, 0x00 }, /* 5621 */ + { CR101, 0x13 }, { CR102, 0x27 }, + { CR106, 0x24 }, /* for newest(3rd cut) AL2230 */ + { CR107, 0x2a }, + { CR109, 0x13 }, /* 4804, for 1212 new algorithm */ + { CR110, 0x1f }, /* 4804, for 1212 new algorithm */ + { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, + { CR114, 0x27 }, + { CR115, 0x26 }, /* 24->26 at 4902 for newest(3rd cut) AL2230 */ + { CR116, 0x24 }, + { CR117, 0xfa }, /* for 1211b */ + { CR118, 0xfa }, /* for 1211b */ + { CR119, 0x10 }, + { CR120, 0x4f }, + { CR121, 0x6c }, /* for 1211b */ + { CR122, 0xfc }, /* E0->FC at 4902 */ + { CR123, 0x57 }, /* 5623 */ + { CR125, 0xad }, /* 4804, for 1212 new algorithm */ + { CR126, 0x6c }, /* 5614 */ + { CR127, 0x03 }, /* 4804, for 1212 new algorithm */ + { CR137, 0x50 }, /* 5614 */ + { CR138, 0xa8 }, + { CR144, 0xac }, /* 5621 */ + { CR150, 0x0d }, { CR252, 0x00 }, { CR253, 0x00 }, + }; + + static const u32 rv1[] = { + /* channel 1 */ + 0x03f790, + 0x033331, + 0x00000d, + + 0x0b3331, + 0x03b812, + 0x00fff3, + 0x0005a4, + 0x0f4dc5, /* fix freq shift 0x044dc5 */ + 0x0805b6, + 0x0146c7, + 0x000688, + 0x0403b9, /* External control TX power (CR31) */ + 0x00dbba, + 0x00099b, + 0x0bdffc, + 0x00000d, + 0x00580f, + }; + + static const struct zd_ioreq16 ioreqs2[] = { + { CR47, 0x1e }, { CR_RFCFG, 0x03 }, + }; + + static const u32 rv2[] = { + 0x00880f, + 0x00080f, + }; + + static const struct zd_ioreq16 ioreqs3[] = { + { CR_RFCFG, 0x00 }, { CR47, 0x1e }, { CR251, 0x7f }, + }; + + static const u32 rv3[] = { + 0x00d80f, + 0x00780f, + 0x00580f, + }; + + static const struct zd_ioreq16 ioreqs4[] = { + { CR138, 0x28 }, { CR203, 0x06 }, + }; + + r = zd_iowrite16a_locked(chip, ioreqs1, ARRAY_SIZE(ioreqs1)); + if (r) + return r; + r = zd_rfwritev_locked(chip, rv1, ARRAY_SIZE(rv1), RF_RV_BITS); + if (r) + return r; + r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2)); + if (r) + return r; + r = zd_rfwritev_locked(chip, rv2, ARRAY_SIZE(rv2), RF_RV_BITS); + if (r) + return r; + r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3)); + if (r) + return r; + r = zd_rfwritev_locked(chip, rv3, ARRAY_SIZE(rv3), RF_RV_BITS); + if (r) + return r; + return zd_iowrite16a_locked(chip, ioreqs4, ARRAY_SIZE(ioreqs4)); +} + +static int al2230_set_channel(struct zd_rf *rf, u8 channel) +{ + int r; + const u32 *rv = al2230_table[channel-1]; + struct zd_chip *chip = zd_rf_to_chip(rf); + static const struct zd_ioreq16 ioreqs[] = { + { CR138, 0x28 }, + { CR203, 0x06 }, + }; + + r = zd_rfwritev_locked(chip, rv, 3, RF_RV_BITS); + if (r) + return r; + return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); +} + +static int zd1211_al2230_switch_radio_on(struct zd_rf *rf) +{ + struct zd_chip *chip = zd_rf_to_chip(rf); + static const struct zd_ioreq16 ioreqs[] = { + { CR11, 0x00 }, + { CR251, 0x3f }, + }; + + return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); +} + +static int zd1211b_al2230_switch_radio_on(struct zd_rf *rf) +{ + struct zd_chip *chip = zd_rf_to_chip(rf); + static const struct zd_ioreq16 ioreqs[] = { + { CR11, 0x00 }, + { CR251, 0x7f }, + }; + + return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); +} + +static int al2230_switch_radio_off(struct zd_rf *rf) +{ + struct zd_chip *chip = zd_rf_to_chip(rf); + static const struct zd_ioreq16 ioreqs[] = { + { CR11, 0x04 }, + { CR251, 0x2f }, + }; + + return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); +} + +int zd_rf_init_al2230(struct zd_rf *rf) +{ + struct zd_chip *chip = zd_rf_to_chip(rf); + + rf->set_channel = al2230_set_channel; + rf->switch_radio_off = al2230_switch_radio_off; + if (chip->is_zd1211b) { + rf->init_hw = zd1211b_al2230_init_hw; + rf->switch_radio_on = zd1211b_al2230_switch_radio_on; + } else { + rf->init_hw = zd1211_al2230_init_hw; + rf->switch_radio_on = zd1211_al2230_switch_radio_on; + } + rf->patch_6m_band_edge = 1; + return 0; +} diff --git a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c new file mode 100644 index 000000000..58247271c --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c @@ -0,0 +1,279 @@ +/* zd_rf_rfmd.c: Functions for the RFMD RF controller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/kernel.h> + +#include "zd_rf.h" +#include "zd_usb.h" +#include "zd_chip.h" + +static u32 rf2959_table[][2] = { + RF_CHANNEL( 1) = { 0x181979, 0x1e6666 }, + RF_CHANNEL( 2) = { 0x181989, 0x1e6666 }, + RF_CHANNEL( 3) = { 0x181999, 0x1e6666 }, + RF_CHANNEL( 4) = { 0x1819a9, 0x1e6666 }, + RF_CHANNEL( 5) = { 0x1819b9, 0x1e6666 }, + RF_CHANNEL( 6) = { 0x1819c9, 0x1e6666 }, + RF_CHANNEL( 7) = { 0x1819d9, 0x1e6666 }, + RF_CHANNEL( 8) = { 0x1819e9, 0x1e6666 }, + RF_CHANNEL( 9) = { 0x1819f9, 0x1e6666 }, + RF_CHANNEL(10) = { 0x181a09, 0x1e6666 }, + RF_CHANNEL(11) = { 0x181a19, 0x1e6666 }, + RF_CHANNEL(12) = { 0x181a29, 0x1e6666 }, + RF_CHANNEL(13) = { 0x181a39, 0x1e6666 }, + RF_CHANNEL(14) = { 0x181a60, 0x1c0000 }, +}; + +#if 0 +static int bits(u32 rw, int from, int to) +{ + rw &= ~(0xffffffffU << (to+1)); + rw >>= from; + return rw; +} + +static int bit(u32 rw, int bit) +{ + return bits(rw, bit, bit); +} + +static void dump_regwrite(u32 rw) +{ + int reg = bits(rw, 18, 22); + int rw_flag = bits(rw, 23, 23); + PDEBUG("rf2959 %#010x reg %d rw %d", rw, reg, rw_flag); + + switch (reg) { + case 0: + PDEBUG("reg0 CFG1 ref_sel %d hybernate %d rf_vco_reg_en %d" + " if_vco_reg_en %d if_vga_en %d", + bits(rw, 14, 15), bit(rw, 3), bit(rw, 2), bit(rw, 1), + bit(rw, 0)); + break; + case 1: + PDEBUG("reg1 IFPLL1 pll_en1 %d kv_en1 %d vtc_en1 %d lpf1 %d" + " cpl1 %d pdp1 %d autocal_en1 %d ld_en1 %d ifloopr %d" + " ifloopc %d dac1 %d", + bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14), + bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10), + bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0, 3)); + break; + case 2: + PDEBUG("reg2 IFPLL2 n1 %d num1 %d", + bits(rw, 6, 17), bits(rw, 0, 5)); + break; + case 3: + PDEBUG("reg3 IFPLL3 num %d", bits(rw, 0, 17)); + break; + case 4: + PDEBUG("reg4 IFPLL4 dn1 %#04x ct_def1 %d kv_def1 %d", + bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3)); + break; + case 5: + PDEBUG("reg5 RFPLL1 pll_en %d kv_en %d vtc_en %d lpf %d cpl %d" + " pdp %d autocal_en %d ld_en %d rfloopr %d rfloopc %d" + " dac %d", + bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14), + bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10), + bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0,3)); + break; + case 6: + PDEBUG("reg6 RFPLL2 n %d num %d", + bits(rw, 6, 17), bits(rw, 0, 5)); + break; + case 7: + PDEBUG("reg7 RFPLL3 num2 %d", bits(rw, 0, 17)); + break; + case 8: + PDEBUG("reg8 RFPLL4 dn %#06x ct_def %d kv_def %d", + bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3)); + break; + case 9: + PDEBUG("reg9 CAL1 tvco %d tlock %d m_ct_value %d ld_window %d", + bits(rw, 13, 17), bits(rw, 8, 12), bits(rw, 3, 7), + bits(rw, 0, 2)); + break; + case 10: + PDEBUG("reg10 TXRX1 rxdcfbbyps %d pcontrol %d txvgc %d" + " rxlpfbw %d txlpfbw %d txdiffmode %d txenmode %d" + " intbiasen %d tybypass %d", + bit(rw, 17), bits(rw, 15, 16), bits(rw, 10, 14), + bits(rw, 7, 9), bits(rw, 4, 6), bit(rw, 3), bit(rw, 2), + bit(rw, 1), bit(rw, 0)); + break; + case 11: + PDEBUG("reg11 PCNT1 mid_bias %d p_desired %d pc_offset %d" + " tx_delay %d", + bits(rw, 15, 17), bits(rw, 9, 14), bits(rw, 3, 8), + bits(rw, 0, 2)); + break; + case 12: + PDEBUG("reg12 PCNT2 max_power %d mid_power %d min_power %d", + bits(rw, 12, 17), bits(rw, 6, 11), bits(rw, 0, 5)); + break; + case 13: + PDEBUG("reg13 VCOT1 rfpll vco comp %d ifpll vco comp %d" + " lobias %d if_biasbuf %d if_biasvco %d rf_biasbuf %d" + " rf_biasvco %d", + bit(rw, 17), bit(rw, 16), bit(rw, 15), + bits(rw, 8, 9), bits(rw, 5, 7), bits(rw, 3, 4), + bits(rw, 0, 2)); + break; + case 14: + PDEBUG("reg14 IQCAL rx_acal %d rx_pcal %d" + " tx_acal %d tx_pcal %d", + bits(rw, 13, 17), bits(rw, 9, 12), bits(rw, 4, 8), + bits(rw, 0, 3)); + break; + } +} +#endif /* 0 */ + +static int rf2959_init_hw(struct zd_rf *rf) +{ + int r; + struct zd_chip *chip = zd_rf_to_chip(rf); + + static const struct zd_ioreq16 ioreqs[] = { + { CR2, 0x1E }, { CR9, 0x20 }, { CR10, 0x89 }, + { CR11, 0x00 }, { CR15, 0xD0 }, { CR17, 0x68 }, + { CR19, 0x4a }, { CR20, 0x0c }, { CR21, 0x0E }, + { CR23, 0x48 }, + /* normal size for cca threshold */ + { CR24, 0x14 }, + /* { CR24, 0x20 }, */ + { CR26, 0x90 }, { CR27, 0x30 }, { CR29, 0x20 }, + { CR31, 0xb2 }, { CR32, 0x43 }, { CR33, 0x28 }, + { CR38, 0x30 }, { CR34, 0x0f }, { CR35, 0xF0 }, + { CR41, 0x2a }, { CR46, 0x7F }, { CR47, 0x1E }, + { CR51, 0xc5 }, { CR52, 0xc5 }, { CR53, 0xc5 }, + { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, + { CR82, 0x00 }, { CR83, 0x24 }, { CR84, 0x04 }, + { CR85, 0x00 }, { CR86, 0x10 }, { CR87, 0x2A }, + { CR88, 0x10 }, { CR89, 0x24 }, { CR90, 0x18 }, + /* { CR91, 0x18 }, */ + /* should solve continous CTS frame problems */ + { CR91, 0x00 }, + { CR92, 0x0a }, { CR93, 0x00 }, { CR94, 0x01 }, + { CR95, 0x00 }, { CR96, 0x40 }, { CR97, 0x37 }, + { CR98, 0x05 }, { CR99, 0x28 }, { CR100, 0x00 }, + { CR101, 0x13 }, { CR102, 0x27 }, { CR103, 0x27 }, + { CR104, 0x18 }, { CR105, 0x12 }, + /* normal size */ + { CR106, 0x1a }, + /* { CR106, 0x22 }, */ + { CR107, 0x24 }, { CR108, 0x0a }, { CR109, 0x13 }, + { CR110, 0x2F }, { CR111, 0x27 }, { CR112, 0x27 }, + { CR113, 0x27 }, { CR114, 0x27 }, { CR115, 0x40 }, + { CR116, 0x40 }, { CR117, 0xF0 }, { CR118, 0xF0 }, + { CR119, 0x16 }, + /* no TX continuation */ + { CR122, 0x00 }, + /* { CR122, 0xff }, */ + { CR127, 0x03 }, { CR131, 0x08 }, { CR138, 0x28 }, + { CR148, 0x44 }, { CR150, 0x10 }, { CR169, 0xBB }, + { CR170, 0xBB }, + }; + + static const u32 rv[] = { + 0x000007, /* REG0(CFG1) */ + 0x07dd43, /* REG1(IFPLL1) */ + 0x080959, /* REG2(IFPLL2) */ + 0x0e6666, + 0x116a57, /* REG4 */ + 0x17dd43, /* REG5 */ + 0x1819f9, /* REG6 */ + 0x1e6666, + 0x214554, + 0x25e7fa, + 0x27fffa, + /* The Zydas driver somehow forgets to set this value. It's + * only set for Japan. We are using internal power control + * for now. + */ + 0x294128, /* internal power */ + /* 0x28252c, */ /* External control TX power */ + /* CR31_CCK, CR51_6-36M, CR52_48M, CR53_54M */ + 0x2c0000, + 0x300000, + 0x340000, /* REG13(0xD) */ + 0x381e0f, /* REG14(0xE) */ + /* Bogus, RF2959's data sheet doesn't know register 27, which is + * actually referenced here. The commented 0x11 is 17. + */ + 0x6c180f, /* REG27(0x11) */ + }; + + r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); + if (r) + return r; + + return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS); +} + +static int rf2959_set_channel(struct zd_rf *rf, u8 channel) +{ + int i, r; + u32 *rv = rf2959_table[channel-1]; + struct zd_chip *chip = zd_rf_to_chip(rf); + + for (i = 0; i < 2; i++) { + r = zd_rfwrite_locked(chip, rv[i], RF_RV_BITS); + if (r) + return r; + } + return 0; +} + +static int rf2959_switch_radio_on(struct zd_rf *rf) +{ + static const struct zd_ioreq16 ioreqs[] = { + { CR10, 0x89 }, + { CR11, 0x00 }, + }; + struct zd_chip *chip = zd_rf_to_chip(rf); + + return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); +} + +static int rf2959_switch_radio_off(struct zd_rf *rf) +{ + static const struct zd_ioreq16 ioreqs[] = { + { CR10, 0x15 }, + { CR11, 0x81 }, + }; + struct zd_chip *chip = zd_rf_to_chip(rf); + + return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); +} + +int zd_rf_init_rf2959(struct zd_rf *rf) +{ + struct zd_chip *chip = zd_rf_to_chip(rf); + + if (chip->is_zd1211b) { + dev_err(zd_chip_dev(chip), + "RF2959 is currently not supported for ZD1211B" + " devices\n"); + return -ENODEV; + } + rf->init_hw = rf2959_init_hw; + rf->set_channel = rf2959_set_channel; + rf->switch_radio_on = rf2959_switch_radio_on; + rf->switch_radio_off = rf2959_switch_radio_off; + return 0; +} diff --git a/drivers/net/wireless/zd1211rw/zd_types.h b/drivers/net/wireless/zd1211rw/zd_types.h new file mode 100644 index 000000000..0155a1584 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_types.h @@ -0,0 +1,71 @@ +/* zd_types.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ZD_TYPES_H +#define _ZD_TYPES_H + +#include <linux/types.h> + +/* We have three register spaces mapped into the overall USB address space of + * 64K words (16-bit values). There is the control register space of + * double-word registers, the eeprom register space and the firmware register + * space. The control register space is byte mapped, the others are word + * mapped. + * + * For that reason, we are using byte offsets for control registers and word + * offsets for everything else. + */ + +typedef u32 __nocast zd_addr_t; + +enum { + ADDR_BASE_MASK = 0xff000000, + ADDR_OFFSET_MASK = 0x0000ffff, + ADDR_ZERO_MASK = 0x00ff0000, + NULL_BASE = 0x00000000, + USB_BASE = 0x01000000, + CR_BASE = 0x02000000, + CR_MAX_OFFSET = 0x0b30, + E2P_BASE = 0x03000000, + E2P_MAX_OFFSET = 0x007e, + FW_BASE = 0x04000000, + FW_MAX_OFFSET = 0x0005, +}; + +#define ZD_ADDR_BASE(addr) ((u32)(addr) & ADDR_BASE_MASK) +#define ZD_OFFSET(addr) ((u32)(addr) & ADDR_OFFSET_MASK) + +#define ZD_ADDR(base, offset) \ + ((zd_addr_t)(((base) & ADDR_BASE_MASK) | ((offset) & ADDR_OFFSET_MASK))) + +#define ZD_NULL_ADDR ((zd_addr_t)0) +#define USB_REG(offset) ZD_ADDR(USB_BASE, offset) /* word addressing */ +#define CTL_REG(offset) ZD_ADDR(CR_BASE, offset) /* byte addressing */ +#define E2P_REG(offset) ZD_ADDR(E2P_BASE, offset) /* word addressing */ +#define FW_REG(offset) ZD_ADDR(FW_BASE, offset) /* word addressing */ + +static inline zd_addr_t zd_inc_word(zd_addr_t addr) +{ + u32 base = ZD_ADDR_BASE(addr); + u32 offset = ZD_OFFSET(addr); + + offset += base == CR_BASE ? 2 : 1; + + return base | offset; +} + +#endif /* _ZD_TYPES_H */ diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c new file mode 100644 index 000000000..632098412 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -0,0 +1,1309 @@ +/* zd_usb.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <asm/unaligned.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/firmware.h> +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/skbuff.h> +#include <linux/usb.h> +#include <net/ieee80211.h> + +#include "zd_def.h" +#include "zd_netdev.h" +#include "zd_mac.h" +#include "zd_usb.h" +#include "zd_util.h" + +static struct usb_device_id usb_ids[] = { + /* ZD1211 */ + { USB_DEVICE(0x0ace, 0x1211), .driver_info = DEVICE_ZD1211 }, + { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211 }, + { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 }, + { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, + { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, + { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 }, + /* ZD1211B */ + { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, + {} +}; + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("USB driver for devices with the ZD1211 chip."); +MODULE_AUTHOR("Ulrich Kunitz"); +MODULE_AUTHOR("Daniel Drake"); +MODULE_VERSION("1.0"); +MODULE_DEVICE_TABLE(usb, usb_ids); + +#define FW_ZD1211_PREFIX "zd1211/zd1211_" +#define FW_ZD1211B_PREFIX "zd1211/zd1211b_" + +/* register address handling */ + +#ifdef DEBUG +static int check_addr(struct zd_usb *usb, zd_addr_t addr) +{ + u32 base = ZD_ADDR_BASE(addr); + u32 offset = ZD_OFFSET(addr); + + if ((u32)addr & ADDR_ZERO_MASK) + goto invalid_address; + switch (base) { + case USB_BASE: + break; + case CR_BASE: + if (offset > CR_MAX_OFFSET) { + dev_dbg(zd_usb_dev(usb), + "CR offset %#010x larger than" + " CR_MAX_OFFSET %#10x\n", + offset, CR_MAX_OFFSET); + goto invalid_address; + } + if (offset & 1) { + dev_dbg(zd_usb_dev(usb), + "CR offset %#010x is not a multiple of 2\n", + offset); + goto invalid_address; + } + break; + case E2P_BASE: + if (offset > E2P_MAX_OFFSET) { + dev_dbg(zd_usb_dev(usb), + "E2P offset %#010x larger than" + " E2P_MAX_OFFSET %#010x\n", + offset, E2P_MAX_OFFSET); + goto invalid_address; + } + break; + case FW_BASE: + if (!usb->fw_base_offset) { + dev_dbg(zd_usb_dev(usb), + "ERROR: fw base offset has not been set\n"); + return -EAGAIN; + } + if (offset > FW_MAX_OFFSET) { + dev_dbg(zd_usb_dev(usb), + "FW offset %#10x is larger than" + " FW_MAX_OFFSET %#010x\n", + offset, FW_MAX_OFFSET); + goto invalid_address; + } + break; + default: + dev_dbg(zd_usb_dev(usb), + "address has unsupported base %#010x\n", addr); + goto invalid_address; + } + + return 0; +invalid_address: + dev_dbg(zd_usb_dev(usb), + "ERROR: invalid address: %#010x\n", addr); + return -EINVAL; +} +#endif /* DEBUG */ + +static u16 usb_addr(struct zd_usb *usb, zd_addr_t addr) +{ + u32 base; + u16 offset; + + base = ZD_ADDR_BASE(addr); + offset = ZD_OFFSET(addr); + + ZD_ASSERT(check_addr(usb, addr) == 0); + + switch (base) { + case CR_BASE: + offset += CR_BASE_OFFSET; + break; + case E2P_BASE: + offset += E2P_BASE_OFFSET; + break; + case FW_BASE: + offset += usb->fw_base_offset; + break; + } + + return offset; +} + +/* USB device initialization */ + +static int request_fw_file( + const struct firmware **fw, const char *name, struct device *device) +{ + int r; + + dev_dbg_f(device, "fw name %s\n", name); + + r = request_firmware(fw, name, device); + if (r) + dev_err(device, + "Could not load firmware file %s. Error number %d\n", + name, r); + return r; +} + +static inline u16 get_bcdDevice(const struct usb_device *udev) +{ + return le16_to_cpu(udev->descriptor.bcdDevice); +} + +enum upload_code_flags { + REBOOT = 1, +}; + +/* Ensures that MAX_TRANSFER_SIZE is even. */ +#define MAX_TRANSFER_SIZE (USB_MAX_TRANSFER_SIZE & ~1) + +static int upload_code(struct usb_device *udev, + const u8 *data, size_t size, u16 code_offset, int flags) +{ + u8 *p; + int r; + + /* USB request blocks need "kmalloced" buffers. + */ + p = kmalloc(MAX_TRANSFER_SIZE, GFP_KERNEL); + if (!p) { + dev_err(&udev->dev, "out of memory\n"); + r = -ENOMEM; + goto error; + } + + size &= ~1; + while (size > 0) { + size_t transfer_size = size <= MAX_TRANSFER_SIZE ? + size : MAX_TRANSFER_SIZE; + + dev_dbg_f(&udev->dev, "transfer size %zu\n", transfer_size); + + memcpy(p, data, transfer_size); + r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_FIRMWARE_DOWNLOAD, + USB_DIR_OUT | USB_TYPE_VENDOR, + code_offset, 0, p, transfer_size, 1000 /* ms */); + if (r < 0) { + dev_err(&udev->dev, + "USB control request for firmware upload" + " failed. Error number %d\n", r); + goto error; + } + transfer_size = r & ~1; + + size -= transfer_size; + data += transfer_size; + code_offset += transfer_size/sizeof(u16); + } + + if (flags & REBOOT) { + u8 ret; + + r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + USB_REQ_FIRMWARE_CONFIRM, + USB_DIR_IN | USB_TYPE_VENDOR, + 0, 0, &ret, sizeof(ret), 5000 /* ms */); + if (r != sizeof(ret)) { + dev_err(&udev->dev, + "control request firmeware confirmation failed." + " Return value %d\n", r); + if (r >= 0) + r = -ENODEV; + goto error; + } + if (ret & 0x80) { + dev_err(&udev->dev, + "Internal error while downloading." + " Firmware confirm return value %#04x\n", + (unsigned int)ret); + r = -ENODEV; + goto error; + } + dev_dbg_f(&udev->dev, "firmware confirm return value %#04x\n", + (unsigned int)ret); + } + + r = 0; +error: + kfree(p); + return r; +} + +static u16 get_word(const void *data, u16 offset) +{ + const __le16 *p = data; + return le16_to_cpu(p[offset]); +} + +static char *get_fw_name(char *buffer, size_t size, u8 device_type, + const char* postfix) +{ + scnprintf(buffer, size, "%s%s", + device_type == DEVICE_ZD1211B ? + FW_ZD1211B_PREFIX : FW_ZD1211_PREFIX, + postfix); + return buffer; +} + +static int upload_firmware(struct usb_device *udev, u8 device_type) +{ + int r; + u16 fw_bcdDevice; + u16 bcdDevice; + const struct firmware *ub_fw = NULL; + const struct firmware *uph_fw = NULL; + char fw_name[128]; + + bcdDevice = get_bcdDevice(udev); + + r = request_fw_file(&ub_fw, + get_fw_name(fw_name, sizeof(fw_name), device_type, "ub"), + &udev->dev); + if (r) + goto error; + + fw_bcdDevice = get_word(ub_fw->data, EEPROM_REGS_OFFSET); + + /* FIXME: do we have any reason to perform the kludge that the vendor + * driver does when there is a version mismatch? (their driver uploads + * different firmwares and stuff) + */ + if (fw_bcdDevice != bcdDevice) { + dev_info(&udev->dev, + "firmware device id %#06x and actual device id " + "%#06x differ, continuing anyway\n", + fw_bcdDevice, bcdDevice); + } else { + dev_dbg_f(&udev->dev, + "firmware device id %#06x is equal to the " + "actual device id\n", fw_bcdDevice); + } + + + r = request_fw_file(&uph_fw, + get_fw_name(fw_name, sizeof(fw_name), device_type, "uphr"), + &udev->dev); + if (r) + goto error; + + r = upload_code(udev, uph_fw->data, uph_fw->size, FW_START_OFFSET, + REBOOT); + if (r) { + dev_err(&udev->dev, + "Could not upload firmware code uph. Error number %d\n", + r); + } + + /* FALL-THROUGH */ +error: + release_firmware(ub_fw); + release_firmware(uph_fw); + return r; +} + +static void disable_read_regs_int(struct zd_usb *usb) +{ + struct zd_usb_interrupt *intr = &usb->intr; + + spin_lock(&intr->lock); + intr->read_regs_enabled = 0; + spin_unlock(&intr->lock); +} + +#define urb_dev(urb) (&(urb)->dev->dev) + +static inline void handle_regs_int(struct urb *urb) +{ + struct zd_usb *usb = urb->context; + struct zd_usb_interrupt *intr = &usb->intr; + int len; + + ZD_ASSERT(in_interrupt()); + spin_lock(&intr->lock); + + if (intr->read_regs_enabled) { + intr->read_regs.length = len = urb->actual_length; + + if (len > sizeof(intr->read_regs.buffer)) + len = sizeof(intr->read_regs.buffer); + memcpy(intr->read_regs.buffer, urb->transfer_buffer, len); + intr->read_regs_enabled = 0; + complete(&intr->read_regs.completion); + goto out; + } + + dev_dbg_f(urb_dev(urb), "regs interrupt ignored\n"); +out: + spin_unlock(&intr->lock); +} + +static inline void handle_retry_failed_int(struct urb *urb) +{ + dev_dbg_f(urb_dev(urb), "retry failed interrupt\n"); +} + + +static void int_urb_complete(struct urb *urb, struct pt_regs *pt_regs) +{ + int r; + struct usb_int_header *hdr; + + switch (urb->status) { + case 0: + break; + case -ESHUTDOWN: + case -EINVAL: + case -ENODEV: + case -ENOENT: + case -ECONNRESET: + case -EPIPE: + goto kfree; + default: + goto resubmit; + } + + if (urb->actual_length < sizeof(hdr)) { + dev_dbg_f(urb_dev(urb), "error: urb %p to small\n", urb); + goto resubmit; + } + + hdr = urb->transfer_buffer; + if (hdr->type != USB_INT_TYPE) { + dev_dbg_f(urb_dev(urb), "error: urb %p wrong type\n", urb); + goto resubmit; + } + + switch (hdr->id) { + case USB_INT_ID_REGS: + handle_regs_int(urb); + break; + case USB_INT_ID_RETRY_FAILED: + handle_retry_failed_int(urb); + break; + default: + dev_dbg_f(urb_dev(urb), "error: urb %p unknown id %x\n", urb, + (unsigned int)hdr->id); + goto resubmit; + } + +resubmit: + r = usb_submit_urb(urb, GFP_ATOMIC); + if (r) { + dev_dbg_f(urb_dev(urb), "resubmit urb %p\n", urb); + goto kfree; + } + return; +kfree: + kfree(urb->transfer_buffer); +} + +static inline int int_urb_interval(struct usb_device *udev) +{ + switch (udev->speed) { + case USB_SPEED_HIGH: + return 4; + case USB_SPEED_LOW: + return 10; + case USB_SPEED_FULL: + default: + return 1; + } +} + +static inline int usb_int_enabled(struct zd_usb *usb) +{ + unsigned long flags; + struct zd_usb_interrupt *intr = &usb->intr; + struct urb *urb; + + spin_lock_irqsave(&intr->lock, flags); + urb = intr->urb; + spin_unlock_irqrestore(&intr->lock, flags); + return urb != NULL; +} + +int zd_usb_enable_int(struct zd_usb *usb) +{ + int r; + struct usb_device *udev; + struct zd_usb_interrupt *intr = &usb->intr; + void *transfer_buffer = NULL; + struct urb *urb; + + dev_dbg_f(zd_usb_dev(usb), "\n"); + + urb = usb_alloc_urb(0, GFP_NOFS); + if (!urb) { + r = -ENOMEM; + goto out; + } + + ZD_ASSERT(!irqs_disabled()); + spin_lock_irq(&intr->lock); + if (intr->urb) { + spin_unlock_irq(&intr->lock); + r = 0; + goto error_free_urb; + } + intr->urb = urb; + spin_unlock_irq(&intr->lock); + + /* TODO: make it a DMA buffer */ + r = -ENOMEM; + transfer_buffer = kmalloc(USB_MAX_EP_INT_BUFFER, GFP_NOFS); + if (!transfer_buffer) { + dev_dbg_f(zd_usb_dev(usb), + "couldn't allocate transfer_buffer\n"); + goto error_set_urb_null; + } + + udev = zd_usb_to_usbdev(usb); + usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, EP_INT_IN), + transfer_buffer, USB_MAX_EP_INT_BUFFER, + int_urb_complete, usb, + intr->interval); + + dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb); + r = usb_submit_urb(urb, GFP_NOFS); + if (r) { + dev_dbg_f(zd_usb_dev(usb), + "Couldn't submit urb. Error number %d\n", r); + goto error; + } + + return 0; +error: + kfree(transfer_buffer); +error_set_urb_null: + spin_lock_irq(&intr->lock); + intr->urb = NULL; + spin_unlock_irq(&intr->lock); +error_free_urb: + usb_free_urb(urb); +out: + return r; +} + +void zd_usb_disable_int(struct zd_usb *usb) +{ + unsigned long flags; + struct zd_usb_interrupt *intr = &usb->intr; + struct urb *urb; + + spin_lock_irqsave(&intr->lock, flags); + urb = intr->urb; + if (!urb) { + spin_unlock_irqrestore(&intr->lock, flags); + return; + } + intr->urb = NULL; + spin_unlock_irqrestore(&intr->lock, flags); + + usb_kill_urb(urb); + dev_dbg_f(zd_usb_dev(usb), "urb %p killed\n", urb); + usb_free_urb(urb); +} + +static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer, + unsigned int length) +{ + int i; + struct zd_mac *mac = zd_usb_to_mac(usb); + const struct rx_length_info *length_info; + + if (length < sizeof(struct rx_length_info)) { + /* It's not a complete packet anyhow. */ + return; + } + length_info = (struct rx_length_info *) + (buffer + length - sizeof(struct rx_length_info)); + + /* It might be that three frames are merged into a single URB + * transaction. We have to check for the length info tag. + * + * While testing we discovered that length_info might be unaligned, + * because if USB transactions are merged, the last packet will not + * be padded. Unaligned access might also happen if the length_info + * structure is not present. + */ + if (get_unaligned(&length_info->tag) == cpu_to_le16(RX_LENGTH_INFO_TAG)) + { + unsigned int l, k, n; + for (i = 0, l = 0;; i++) { + k = le16_to_cpu(get_unaligned(&length_info->length[i])); + n = l+k; + if (n > length) + return; + zd_mac_rx(mac, buffer+l, k); + if (i >= 2) + return; + l = (n+3) & ~3; + } + } else { + zd_mac_rx(mac, buffer, length); + } +} + +static void rx_urb_complete(struct urb *urb, struct pt_regs *pt_regs) +{ + struct zd_usb *usb; + struct zd_usb_rx *rx; + const u8 *buffer; + unsigned int length; + + switch (urb->status) { + case 0: + break; + case -ESHUTDOWN: + case -EINVAL: + case -ENODEV: + case -ENOENT: + case -ECONNRESET: + case -EPIPE: + return; + default: + dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); + goto resubmit; + } + + buffer = urb->transfer_buffer; + length = urb->actual_length; + usb = urb->context; + rx = &usb->rx; + + if (length%rx->usb_packet_size > rx->usb_packet_size-4) { + /* If there is an old first fragment, we don't care. */ + dev_dbg_f(urb_dev(urb), "*** first fragment ***\n"); + ZD_ASSERT(length <= ARRAY_SIZE(rx->fragment)); + spin_lock(&rx->lock); + memcpy(rx->fragment, buffer, length); + rx->fragment_length = length; + spin_unlock(&rx->lock); + goto resubmit; + } + + spin_lock(&rx->lock); + if (rx->fragment_length > 0) { + /* We are on a second fragment, we believe */ + ZD_ASSERT(length + rx->fragment_length <= + ARRAY_SIZE(rx->fragment)); + dev_dbg_f(urb_dev(urb), "*** second fragment ***\n"); + memcpy(rx->fragment+rx->fragment_length, buffer, length); + handle_rx_packet(usb, rx->fragment, + rx->fragment_length + length); + rx->fragment_length = 0; + spin_unlock(&rx->lock); + } else { + spin_unlock(&rx->lock); + handle_rx_packet(usb, buffer, length); + } + +resubmit: + usb_submit_urb(urb, GFP_ATOMIC); +} + +struct urb *alloc_urb(struct zd_usb *usb) +{ + struct usb_device *udev = zd_usb_to_usbdev(usb); + struct urb *urb; + void *buffer; + + urb = usb_alloc_urb(0, GFP_NOFS); + if (!urb) + return NULL; + buffer = usb_buffer_alloc(udev, USB_MAX_RX_SIZE, GFP_NOFS, + &urb->transfer_dma); + if (!buffer) { + usb_free_urb(urb); + return NULL; + } + + usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, EP_DATA_IN), + buffer, USB_MAX_RX_SIZE, + rx_urb_complete, usb); + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + return urb; +} + +void free_urb(struct urb *urb) +{ + if (!urb) + return; + usb_buffer_free(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); + usb_free_urb(urb); +} + +int zd_usb_enable_rx(struct zd_usb *usb) +{ + int i, r; + struct zd_usb_rx *rx = &usb->rx; + struct urb **urbs; + + dev_dbg_f(zd_usb_dev(usb), "\n"); + + r = -ENOMEM; + urbs = kcalloc(URBS_COUNT, sizeof(struct urb *), GFP_NOFS); + if (!urbs) + goto error; + for (i = 0; i < URBS_COUNT; i++) { + urbs[i] = alloc_urb(usb); + if (!urbs[i]) + goto error; + } + + ZD_ASSERT(!irqs_disabled()); + spin_lock_irq(&rx->lock); + if (rx->urbs) { + spin_unlock_irq(&rx->lock); + r = 0; + goto error; + } + rx->urbs = urbs; + rx->urbs_count = URBS_COUNT; + spin_unlock_irq(&rx->lock); + + for (i = 0; i < URBS_COUNT; i++) { + r = usb_submit_urb(urbs[i], GFP_NOFS); + if (r) + goto error_submit; + } + + return 0; +error_submit: + for (i = 0; i < URBS_COUNT; i++) { + usb_kill_urb(urbs[i]); + } + spin_lock_irq(&rx->lock); + rx->urbs = NULL; + rx->urbs_count = 0; + spin_unlock_irq(&rx->lock); +error: + if (urbs) { + for (i = 0; i < URBS_COUNT; i++) + free_urb(urbs[i]); + } + return r; +} + +void zd_usb_disable_rx(struct zd_usb *usb) +{ + int i; + unsigned long flags; + struct urb **urbs; + unsigned int count; + struct zd_usb_rx *rx = &usb->rx; + + spin_lock_irqsave(&rx->lock, flags); + urbs = rx->urbs; + count = rx->urbs_count; + spin_unlock_irqrestore(&rx->lock, flags); + if (!urbs) + return; + + for (i = 0; i < count; i++) { + usb_kill_urb(urbs[i]); + free_urb(urbs[i]); + } + kfree(urbs); + + spin_lock_irqsave(&rx->lock, flags); + rx->urbs = NULL; + rx->urbs_count = 0; + spin_unlock_irqrestore(&rx->lock, flags); +} + +static void tx_urb_complete(struct urb *urb, struct pt_regs *pt_regs) +{ + int r; + + switch (urb->status) { + case 0: + break; + case -ESHUTDOWN: + case -EINVAL: + case -ENODEV: + case -ENOENT: + case -ECONNRESET: + case -EPIPE: + dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); + break; + default: + dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); + goto resubmit; + } +free_urb: + usb_buffer_free(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); + usb_free_urb(urb); + return; +resubmit: + r = usb_submit_urb(urb, GFP_ATOMIC); + if (r) { + dev_dbg_f(urb_dev(urb), "error resubmit urb %p %d\n", urb, r); + goto free_urb; + } +} + +/* Puts the frame on the USB endpoint. It doesn't wait for + * completion. The frame must contain the control set. + */ +int zd_usb_tx(struct zd_usb *usb, const u8 *frame, unsigned int length) +{ + int r; + struct usb_device *udev = zd_usb_to_usbdev(usb); + struct urb *urb; + void *buffer; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + r = -ENOMEM; + goto out; + } + + buffer = usb_buffer_alloc(zd_usb_to_usbdev(usb), length, GFP_ATOMIC, + &urb->transfer_dma); + if (!buffer) { + r = -ENOMEM; + goto error_free_urb; + } + memcpy(buffer, frame, length); + + usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT), + buffer, length, tx_urb_complete, NULL); + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + r = usb_submit_urb(urb, GFP_ATOMIC); + if (r) + goto error; + return 0; +error: + usb_buffer_free(zd_usb_to_usbdev(usb), length, buffer, + urb->transfer_dma); +error_free_urb: + usb_free_urb(urb); +out: + return r; +} + +static inline void init_usb_interrupt(struct zd_usb *usb) +{ + struct zd_usb_interrupt *intr = &usb->intr; + + spin_lock_init(&intr->lock); + intr->interval = int_urb_interval(zd_usb_to_usbdev(usb)); + init_completion(&intr->read_regs.completion); + intr->read_regs.cr_int_addr = cpu_to_le16(usb_addr(usb, CR_INTERRUPT)); +} + +static inline void init_usb_rx(struct zd_usb *usb) +{ + struct zd_usb_rx *rx = &usb->rx; + spin_lock_init(&rx->lock); + if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH) { + rx->usb_packet_size = 512; + } else { + rx->usb_packet_size = 64; + } + ZD_ASSERT(rx->fragment_length == 0); +} + +static inline void init_usb_tx(struct zd_usb *usb) +{ + /* FIXME: at this point we will allocate a fixed number of urb's for + * use in a cyclic scheme */ +} + +void zd_usb_init(struct zd_usb *usb, struct net_device *netdev, + struct usb_interface *intf) +{ + memset(usb, 0, sizeof(*usb)); + usb->intf = usb_get_intf(intf); + usb_set_intfdata(usb->intf, netdev); + init_usb_interrupt(usb); + init_usb_tx(usb); + init_usb_rx(usb); +} + +int zd_usb_init_hw(struct zd_usb *usb) +{ + int r; + struct zd_chip *chip = zd_usb_to_chip(usb); + + ZD_ASSERT(mutex_is_locked(&chip->mutex)); + r = zd_ioread16_locked(chip, &usb->fw_base_offset, + USB_REG((u16)FW_BASE_ADDR_OFFSET)); + if (r) + return r; + dev_dbg_f(zd_usb_dev(usb), "fw_base_offset: %#06hx\n", + usb->fw_base_offset); + + return 0; +} + +void zd_usb_clear(struct zd_usb *usb) +{ + usb_set_intfdata(usb->intf, NULL); + usb_put_intf(usb->intf); + memset(usb, 0, sizeof(*usb)); + /* FIXME: usb_interrupt, usb_tx, usb_rx? */ +} + +static const char *speed(enum usb_device_speed speed) +{ + switch (speed) { + case USB_SPEED_LOW: + return "low"; + case USB_SPEED_FULL: + return "full"; + case USB_SPEED_HIGH: + return "high"; + default: + return "unknown speed"; + } +} + +static int scnprint_id(struct usb_device *udev, char *buffer, size_t size) +{ + return scnprintf(buffer, size, "%04hx:%04hx v%04hx %s", + le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct), + get_bcdDevice(udev), + speed(udev->speed)); +} + +int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size) +{ + struct usb_device *udev = interface_to_usbdev(usb->intf); + return scnprint_id(udev, buffer, size); +} + +#ifdef DEBUG +static void print_id(struct usb_device *udev) +{ + char buffer[40]; + + scnprint_id(udev, buffer, sizeof(buffer)); + buffer[sizeof(buffer)-1] = 0; + dev_dbg_f(&udev->dev, "%s\n", buffer); +} +#else +#define print_id(udev) do { } while (0) +#endif + +static int probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + int r; + struct usb_device *udev = interface_to_usbdev(intf); + struct net_device *netdev = NULL; + + print_id(udev); + + switch (udev->speed) { + case USB_SPEED_LOW: + case USB_SPEED_FULL: + case USB_SPEED_HIGH: + break; + default: + dev_dbg_f(&intf->dev, "Unknown USB speed\n"); + r = -ENODEV; + goto error; + } + + netdev = zd_netdev_alloc(intf); + if (netdev == NULL) { + r = -ENOMEM; + goto error; + } + + r = upload_firmware(udev, id->driver_info); + if (r) { + dev_err(&intf->dev, + "couldn't load firmware. Error number %d\n", r); + goto error; + } + + r = usb_reset_configuration(udev); + if (r) { + dev_dbg_f(&intf->dev, + "couldn't reset configuration. Error number %d\n", r); + goto error; + } + + /* At this point the interrupt endpoint is not generally enabled. We + * save the USB bandwidth until the network device is opened. But + * notify that the initialization of the MAC will require the + * interrupts to be temporary enabled. + */ + r = zd_mac_init_hw(zd_netdev_mac(netdev), id->driver_info); + if (r) { + dev_dbg_f(&intf->dev, + "couldn't initialize mac. Error number %d\n", r); + goto error; + } + + r = register_netdev(netdev); + if (r) { + dev_dbg_f(&intf->dev, + "couldn't register netdev. Error number %d\n", r); + goto error; + } + + dev_dbg_f(&intf->dev, "successful\n"); + dev_info(&intf->dev,"%s\n", netdev->name); + return 0; +error: + usb_reset_device(interface_to_usbdev(intf)); + zd_netdev_free(netdev); + return r; +} + +static void disconnect(struct usb_interface *intf) +{ + struct net_device *netdev = zd_intf_to_netdev(intf); + struct zd_mac *mac = zd_netdev_mac(netdev); + struct zd_usb *usb = &mac->chip.usb; + + dev_dbg_f(zd_usb_dev(usb), "\n"); + + zd_netdev_disconnect(netdev); + + /* Just in case something has gone wrong! */ + zd_usb_disable_rx(usb); + zd_usb_disable_int(usb); + + /* If the disconnect has been caused by a removal of the + * driver module, the reset allows reloading of the driver. If the + * reset will not be executed here, the upload of the firmware in the + * probe function caused by the reloading of the driver will fail. + */ + usb_reset_device(interface_to_usbdev(intf)); + + /* If somebody still waits on this lock now, this is an error. */ + zd_netdev_free(netdev); + dev_dbg(&intf->dev, "disconnected\n"); +} + +static struct usb_driver driver = { + .name = "zd1211rw", + .id_table = usb_ids, + .probe = probe, + .disconnect = disconnect, +}; + +static int __init usb_init(void) +{ + int r; + + pr_debug("usb_init()\n"); + + r = usb_register(&driver); + if (r) { + printk(KERN_ERR "usb_register() failed. Error number %d\n", r); + return r; + } + + pr_debug("zd1211rw initialized\n"); + return 0; +} + +static void __exit usb_exit(void) +{ + pr_debug("usb_exit()\n"); + usb_deregister(&driver); +} + +module_init(usb_init); +module_exit(usb_exit); + +static int usb_int_regs_length(unsigned int count) +{ + return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data); +} + +static void prepare_read_regs_int(struct zd_usb *usb) +{ + struct zd_usb_interrupt *intr = &usb->intr; + + spin_lock(&intr->lock); + intr->read_regs_enabled = 1; + INIT_COMPLETION(intr->read_regs.completion); + spin_unlock(&intr->lock); +} + +static int get_results(struct zd_usb *usb, u16 *values, + struct usb_req_read_regs *req, unsigned int count) +{ + int r; + int i; + struct zd_usb_interrupt *intr = &usb->intr; + struct read_regs_int *rr = &intr->read_regs; + struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer; + + spin_lock(&intr->lock); + + r = -EIO; + /* The created block size seems to be larger than expected. + * However results appear to be correct. + */ + if (rr->length < usb_int_regs_length(count)) { + dev_dbg_f(zd_usb_dev(usb), + "error: actual length %d less than expected %d\n", + rr->length, usb_int_regs_length(count)); + goto error_unlock; + } + if (rr->length > sizeof(rr->buffer)) { + dev_dbg_f(zd_usb_dev(usb), + "error: actual length %d exceeds buffer size %zu\n", + rr->length, sizeof(rr->buffer)); + goto error_unlock; + } + + for (i = 0; i < count; i++) { + struct reg_data *rd = ®s->regs[i]; + if (rd->addr != req->addr[i]) { + dev_dbg_f(zd_usb_dev(usb), + "rd[%d] addr %#06hx expected %#06hx\n", i, + le16_to_cpu(rd->addr), + le16_to_cpu(req->addr[i])); + goto error_unlock; + } + values[i] = le16_to_cpu(rd->value); + } + + r = 0; +error_unlock: + spin_unlock(&intr->lock); + return r; +} + +int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, + const zd_addr_t *addresses, unsigned int count) +{ + int r; + int i, req_len, actual_req_len; + struct usb_device *udev; + struct usb_req_read_regs *req = NULL; + unsigned long timeout; + + if (count < 1) { + dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n"); + return -EINVAL; + } + if (count > USB_MAX_IOREAD16_COUNT) { + dev_dbg_f(zd_usb_dev(usb), + "error: count %u exceeds possible max %u\n", + count, USB_MAX_IOREAD16_COUNT); + return -EINVAL; + } + if (in_atomic()) { + dev_dbg_f(zd_usb_dev(usb), + "error: io in atomic context not supported\n"); + return -EWOULDBLOCK; + } + if (!usb_int_enabled(usb)) { + dev_dbg_f(zd_usb_dev(usb), + "error: usb interrupt not enabled\n"); + return -EWOULDBLOCK; + } + + req_len = sizeof(struct usb_req_read_regs) + count * sizeof(__le16); + req = kmalloc(req_len, GFP_NOFS); + if (!req) + return -ENOMEM; + req->id = cpu_to_le16(USB_REQ_READ_REGS); + for (i = 0; i < count; i++) + req->addr[i] = cpu_to_le16(usb_addr(usb, addresses[i])); + + udev = zd_usb_to_usbdev(usb); + prepare_read_regs_int(usb); + r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), + req, req_len, &actual_req_len, 1000 /* ms */); + if (r) { + dev_dbg_f(zd_usb_dev(usb), + "error in usb_bulk_msg(). Error number %d\n", r); + goto error; + } + if (req_len != actual_req_len) { + dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()\n" + " req_len %d != actual_req_len %d\n", + req_len, actual_req_len); + r = -EIO; + goto error; + } + + timeout = wait_for_completion_timeout(&usb->intr.read_regs.completion, + msecs_to_jiffies(1000)); + if (!timeout) { + disable_read_regs_int(usb); + dev_dbg_f(zd_usb_dev(usb), "read timed out\n"); + r = -ETIMEDOUT; + goto error; + } + + r = get_results(usb, values, req, count); +error: + kfree(req); + return r; +} + +int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, + unsigned int count) +{ + int r; + struct usb_device *udev; + struct usb_req_write_regs *req = NULL; + int i, req_len, actual_req_len; + + if (count == 0) + return 0; + if (count > USB_MAX_IOWRITE16_COUNT) { + dev_dbg_f(zd_usb_dev(usb), + "error: count %u exceeds possible max %u\n", + count, USB_MAX_IOWRITE16_COUNT); + return -EINVAL; + } + if (in_atomic()) { + dev_dbg_f(zd_usb_dev(usb), + "error: io in atomic context not supported\n"); + return -EWOULDBLOCK; + } + + req_len = sizeof(struct usb_req_write_regs) + + count * sizeof(struct reg_data); + req = kmalloc(req_len, GFP_NOFS); + if (!req) + return -ENOMEM; + + req->id = cpu_to_le16(USB_REQ_WRITE_REGS); + for (i = 0; i < count; i++) { + struct reg_data *rw = &req->reg_writes[i]; + rw->addr = cpu_to_le16(usb_addr(usb, ioreqs[i].addr)); + rw->value = cpu_to_le16(ioreqs[i].value); + } + + udev = zd_usb_to_usbdev(usb); + r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), + req, req_len, &actual_req_len, 1000 /* ms */); + if (r) { + dev_dbg_f(zd_usb_dev(usb), + "error in usb_bulk_msg(). Error number %d\n", r); + goto error; + } + if (req_len != actual_req_len) { + dev_dbg_f(zd_usb_dev(usb), + "error in usb_bulk_msg()" + " req_len %d != actual_req_len %d\n", + req_len, actual_req_len); + r = -EIO; + goto error; + } + + /* FALL-THROUGH with r == 0 */ +error: + kfree(req); + return r; +} + +int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits) +{ + int r; + struct usb_device *udev; + struct usb_req_rfwrite *req = NULL; + int i, req_len, actual_req_len; + u16 bit_value_template; + + if (in_atomic()) { + dev_dbg_f(zd_usb_dev(usb), + "error: io in atomic context not supported\n"); + return -EWOULDBLOCK; + } + if (bits < USB_MIN_RFWRITE_BIT_COUNT) { + dev_dbg_f(zd_usb_dev(usb), + "error: bits %d are smaller than" + " USB_MIN_RFWRITE_BIT_COUNT %d\n", + bits, USB_MIN_RFWRITE_BIT_COUNT); + return -EINVAL; + } + if (bits > USB_MAX_RFWRITE_BIT_COUNT) { + dev_dbg_f(zd_usb_dev(usb), + "error: bits %d exceed USB_MAX_RFWRITE_BIT_COUNT %d\n", + bits, USB_MAX_RFWRITE_BIT_COUNT); + return -EINVAL; + } +#ifdef DEBUG + if (value & (~0UL << bits)) { + dev_dbg_f(zd_usb_dev(usb), + "error: value %#09x has bits >= %d set\n", + value, bits); + return -EINVAL; + } +#endif /* DEBUG */ + + dev_dbg_f(zd_usb_dev(usb), "value %#09x bits %d\n", value, bits); + + r = zd_usb_ioread16(usb, &bit_value_template, CR203); + if (r) { + dev_dbg_f(zd_usb_dev(usb), + "error %d: Couldn't read CR203\n", r); + goto out; + } + bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA); + + req_len = sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16); + req = kmalloc(req_len, GFP_NOFS); + if (!req) + return -ENOMEM; + + req->id = cpu_to_le16(USB_REQ_WRITE_RF); + /* 1: 3683a, but not used in ZYDAS driver */ + req->value = cpu_to_le16(2); + req->bits = cpu_to_le16(bits); + + for (i = 0; i < bits; i++) { + u16 bv = bit_value_template; + if (value & (1 << (bits-1-i))) + bv |= RF_DATA; + req->bit_values[i] = cpu_to_le16(bv); + } + + udev = zd_usb_to_usbdev(usb); + r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), + req, req_len, &actual_req_len, 1000 /* ms */); + if (r) { + dev_dbg_f(zd_usb_dev(usb), + "error in usb_bulk_msg(). Error number %d\n", r); + goto out; + } + if (req_len != actual_req_len) { + dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()" + " req_len %d != actual_req_len %d\n", + req_len, actual_req_len); + r = -EIO; + goto out; + } + + /* FALL-THROUGH with r == 0 */ +out: + kfree(req); + return r; +} diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h new file mode 100644 index 000000000..d6420283b --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_usb.h @@ -0,0 +1,240 @@ +/* zd_usb.h: Header for USB interface implemented by ZD1211 chip + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ZD_USB_H +#define _ZD_USB_H + +#include <linux/completion.h> +#include <linux/netdevice.h> +#include <linux/spinlock.h> +#include <linux/skbuff.h> +#include <linux/usb.h> + +#include "zd_def.h" +#include "zd_types.h" + +enum devicetype { + DEVICE_ZD1211 = 0, + DEVICE_ZD1211B = 1, +}; + +enum endpoints { + EP_CTRL = 0, + EP_DATA_OUT = 1, + EP_DATA_IN = 2, + EP_INT_IN = 3, + EP_REGS_OUT = 4, +}; + +enum { + USB_MAX_TRANSFER_SIZE = 4096, /* bytes */ + /* FIXME: The original driver uses this value. We have to check, + * whether the MAX_TRANSFER_SIZE is sufficient and this needs only be + * used if one combined frame is split over two USB transactions. + */ + USB_MAX_RX_SIZE = 4800, /* bytes */ + USB_MAX_IOWRITE16_COUNT = 15, + USB_MAX_IOWRITE32_COUNT = USB_MAX_IOWRITE16_COUNT/2, + USB_MAX_IOREAD16_COUNT = 15, + USB_MAX_IOREAD32_COUNT = USB_MAX_IOREAD16_COUNT/2, + USB_MIN_RFWRITE_BIT_COUNT = 16, + USB_MAX_RFWRITE_BIT_COUNT = 28, + USB_MAX_EP_INT_BUFFER = 64, + USB_ZD1211B_BCD_DEVICE = 0x4810, +}; + +enum control_requests { + USB_REQ_WRITE_REGS = 0x21, + USB_REQ_READ_REGS = 0x22, + USB_REQ_WRITE_RF = 0x23, + USB_REQ_PROG_FLASH = 0x24, + USB_REQ_EEPROM_START = 0x0128, /* ? request is a byte */ + USB_REQ_EEPROM_MID = 0x28, + USB_REQ_EEPROM_END = 0x0228, /* ? request is a byte */ + USB_REQ_FIRMWARE_DOWNLOAD = 0x30, + USB_REQ_FIRMWARE_CONFIRM = 0x31, + USB_REQ_FIRMWARE_READ_DATA = 0x32, +}; + +struct usb_req_read_regs { + __le16 id; + __le16 addr[0]; +} __attribute__((packed)); + +struct reg_data { + __le16 addr; + __le16 value; +} __attribute__((packed)); + +struct usb_req_write_regs { + __le16 id; + struct reg_data reg_writes[0]; +} __attribute__((packed)); + +enum { + RF_IF_LE = 0x02, + RF_CLK = 0x04, + RF_DATA = 0x08, +}; + +struct usb_req_rfwrite { + __le16 id; + __le16 value; + /* 1: 3683a */ + /* 2: other (default) */ + __le16 bits; + /* RF2595: 24 */ + __le16 bit_values[0]; + /* (CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */ +} __attribute__((packed)); + +/* USB interrupt */ + +enum usb_int_id { + USB_INT_TYPE = 0x01, + USB_INT_ID_REGS = 0x90, + USB_INT_ID_RETRY_FAILED = 0xa0, +}; + +enum usb_int_flags { + USB_INT_READ_REGS_EN = 0x01, +}; + +struct usb_int_header { + u8 type; /* must always be 1 */ + u8 id; +} __attribute__((packed)); + +struct usb_int_regs { + struct usb_int_header hdr; + struct reg_data regs[0]; +} __attribute__((packed)); + +struct usb_int_retry_fail { + struct usb_int_header hdr; + u8 new_rate; + u8 _dummy; + u8 addr[ETH_ALEN]; + u8 ibss_wakeup_dest; +} __attribute__((packed)); + +struct read_regs_int { + struct completion completion; + /* Stores the USB int structure and contains the USB address of the + * first requested register before request. + */ + u8 buffer[USB_MAX_EP_INT_BUFFER]; + int length; + __le16 cr_int_addr; +}; + +struct zd_ioreq16 { + zd_addr_t addr; + u16 value; +}; + +struct zd_ioreq32 { + zd_addr_t addr; + u32 value; +}; + +struct zd_usb_interrupt { + struct read_regs_int read_regs; + spinlock_t lock; + struct urb *urb; + int interval; + u8 read_regs_enabled:1; +}; + +static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr) +{ + return (struct usb_int_regs *)intr->read_regs.buffer; +} + +#define URBS_COUNT 5 + +struct zd_usb_rx { + spinlock_t lock; + u8 fragment[2*USB_MAX_RX_SIZE]; + unsigned int fragment_length; + unsigned int usb_packet_size; + struct urb **urbs; + int urbs_count; +}; + +struct zd_usb_tx { + spinlock_t lock; +}; + +/* Contains the usb parts. The structure doesn't require a lock, because intf + * and fw_base_offset, will not be changed after initialization. + */ +struct zd_usb { + struct zd_usb_interrupt intr; + struct zd_usb_rx rx; + struct zd_usb_tx tx; + struct usb_interface *intf; + u16 fw_base_offset; +}; + +#define zd_usb_dev(usb) (&usb->intf->dev) + +static inline struct usb_device *zd_usb_to_usbdev(struct zd_usb *usb) +{ + return interface_to_usbdev(usb->intf); +} + +static inline struct net_device *zd_intf_to_netdev(struct usb_interface *intf) +{ + return usb_get_intfdata(intf); +} + +static inline struct net_device *zd_usb_to_netdev(struct zd_usb *usb) +{ + return zd_intf_to_netdev(usb->intf); +} + +void zd_usb_init(struct zd_usb *usb, struct net_device *netdev, + struct usb_interface *intf); +int zd_usb_init_hw(struct zd_usb *usb); +void zd_usb_clear(struct zd_usb *usb); + +int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size); + +int zd_usb_enable_int(struct zd_usb *usb); +void zd_usb_disable_int(struct zd_usb *usb); + +int zd_usb_enable_rx(struct zd_usb *usb); +void zd_usb_disable_rx(struct zd_usb *usb); + +int zd_usb_tx(struct zd_usb *usb, const u8 *frame, unsigned int length); + +int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, + const zd_addr_t *addresses, unsigned int count); + +static inline int zd_usb_ioread16(struct zd_usb *usb, u16 *value, + const zd_addr_t addr) +{ + return zd_usb_ioread16v(usb, value, (const zd_addr_t *)&addr, 1); +} + +int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, + unsigned int count); + +int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits); + +#endif /* _ZD_USB_H */ diff --git a/drivers/net/wireless/zd1211rw/zd_util.c b/drivers/net/wireless/zd1211rw/zd_util.c new file mode 100644 index 000000000..d20036c15 --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_util.c @@ -0,0 +1,82 @@ +/* zd_util.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Utility program + */ + +#include "zd_def.h" +#include "zd_util.h" + +#ifdef DEBUG +static char hex(u8 v) +{ + v &= 0xf; + return (v < 10 ? '0' : 'a' - 10) + v; +} + +static char hex_print(u8 c) +{ + return (0x20 <= c && c < 0x7f) ? c : '.'; +} + +static void dump_line(const u8 *bytes, size_t size) +{ + char c; + size_t i; + + size = size <= 8 ? size : 8; + printk(KERN_DEBUG "zd1211 %p ", bytes); + for (i = 0; i < 8; i++) { + switch (i) { + case 1: + case 5: + c = '.'; + break; + case 3: + c = ':'; + break; + default: + c = ' '; + } + if (i < size) { + printk("%c%c%c", hex(bytes[i] >> 4), hex(bytes[i]), c); + } else { + printk(" %c", c); + } + } + + for (i = 0; i < size; i++) + printk("%c", hex_print(bytes[i])); + printk("\n"); +} + +void zd_hexdump(const void *bytes, size_t size) +{ + size_t i = 0; + + do { + dump_line((u8 *)bytes + i, size-i); + i += 8; + } while (i < size); +} +#endif /* DEBUG */ + +void *zd_tail(const void *buffer, size_t buffer_size, size_t tail_size) +{ + if (buffer_size < tail_size) + return NULL; + return (u8 *)buffer + (buffer_size - tail_size); +} diff --git a/drivers/net/wireless/zd1211rw/zd_util.h b/drivers/net/wireless/zd1211rw/zd_util.h new file mode 100644 index 000000000..ce26f7ade --- /dev/null +++ b/drivers/net/wireless/zd1211rw/zd_util.h @@ -0,0 +1,29 @@ +/* zd_util.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ZD_UTIL_H +#define _ZD_UTIL_H + +void *zd_tail(const void *buffer, size_t buffer_size, size_t tail_size); + +#ifdef DEBUG +void zd_hexdump(const void *bytes, size_t size); +#else +#define zd_hexdump(bytes, size) +#endif /* DEBUG */ + +#endif /* _ZD_UTIL_H */ diff --git a/drivers/parport/parport_ax88796.c b/drivers/parport/parport_ax88796.c new file mode 100644 index 000000000..185063259 --- /dev/null +++ b/drivers/parport/parport_ax88796.c @@ -0,0 +1,443 @@ +/* linux/drivers/parport/parport_ax88796.c + * + * (c) 2005,2006 Simtec Electronics + * Ben Dooks <ben@simtec.co.uk> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/parport.h> +#include <linux/interrupt.h> +#include <linux/errno.h> +#include <linux/platform_device.h> + +#include <asm/io.h> +#include <asm/irq.h> + +#define AX_SPR_BUSY (1<<7) +#define AX_SPR_ACK (1<<6) +#define AX_SPR_PE (1<<5) +#define AX_SPR_SLCT (1<<4) +#define AX_SPR_ERR (1<<3) + +#define AX_CPR_nDOE (1<<5) +#define AX_CPR_SLCTIN (1<<3) +#define AX_CPR_nINIT (1<<2) +#define AX_CPR_ATFD (1<<1) +#define AX_CPR_STRB (1<<0) + +struct ax_drvdata { + struct parport *parport; + struct parport_state suspend; + + struct device *dev; + struct resource *io; + + unsigned char irq_enabled; + + void __iomem *base; + void __iomem *spp_data; + void __iomem *spp_spr; + void __iomem *spp_cpr; +}; + +static inline struct ax_drvdata *pp_to_drv(struct parport *p) +{ + return p->private_data; +} + +static unsigned char +parport_ax88796_read_data(struct parport *p) +{ + struct ax_drvdata *dd = pp_to_drv(p); + + return readb(dd->spp_data); +} + +static void +parport_ax88796_write_data(struct parport *p, unsigned char data) +{ + struct ax_drvdata *dd = pp_to_drv(p); + + writeb(data, dd->spp_data); +} + +static unsigned char +parport_ax88796_read_control(struct parport *p) +{ + struct ax_drvdata *dd = pp_to_drv(p); + unsigned int cpr = readb(dd->spp_cpr); + unsigned int ret = 0; + + if (!(cpr & AX_CPR_STRB)) + ret |= PARPORT_CONTROL_STROBE; + + if (!(cpr & AX_CPR_ATFD)) + ret |= PARPORT_CONTROL_AUTOFD; + + if (cpr & AX_CPR_nINIT) + ret |= PARPORT_CONTROL_INIT; + + if (!(cpr & AX_CPR_SLCTIN)) + ret |= PARPORT_CONTROL_SELECT; + + return ret; +} + +static void +parport_ax88796_write_control(struct parport *p, unsigned char control) +{ + struct ax_drvdata *dd = pp_to_drv(p); + unsigned int cpr = readb(dd->spp_cpr); + + cpr &= AX_CPR_nDOE; + + if (!(control & PARPORT_CONTROL_STROBE)) + cpr |= AX_CPR_STRB; + + if (!(control & PARPORT_CONTROL_AUTOFD)) + cpr |= AX_CPR_ATFD; + + if (control & PARPORT_CONTROL_INIT) + cpr |= AX_CPR_nINIT; + + if (!(control & PARPORT_CONTROL_SELECT)) + cpr |= AX_CPR_SLCTIN; + + dev_dbg(dd->dev, "write_control: ctrl=%02x, cpr=%02x\n", control, cpr); + writeb(cpr, dd->spp_cpr); + + if (parport_ax88796_read_control(p) != control) { + dev_err(dd->dev, "write_control: read != set (%02x, %02x)\n", + parport_ax88796_read_control(p), control); + } +} + +static unsigned char +parport_ax88796_read_status(struct parport *p) +{ + struct ax_drvdata *dd = pp_to_drv(p); + unsigned int status = readb(dd->spp_spr); + unsigned int ret = 0; + + if (status & AX_SPR_BUSY) + ret |= PARPORT_STATUS_BUSY; + + if (status & AX_SPR_ACK) + ret |= PARPORT_STATUS_ACK; + + if (status & AX_SPR_ERR) + ret |= PARPORT_STATUS_ERROR; + + if (status & AX_SPR_SLCT) + ret |= PARPORT_STATUS_SELECT; + + if (status & AX_SPR_PE) + ret |= PARPORT_STATUS_PAPEROUT; + + return ret; +} + +static unsigned char +parport_ax88796_frob_control(struct parport *p, unsigned char mask, + unsigned char val) +{ + struct ax_drvdata *dd = pp_to_drv(p); + unsigned char old = parport_ax88796_read_control(p); + + dev_dbg(dd->dev, "frob: mask=%02x, val=%02x, old=%02x\n", + mask, val, old); + + parport_ax88796_write_control(p, (old & ~mask) | val); + return old; +} + +static void +parport_ax88796_enable_irq(struct parport *p) +{ + struct ax_drvdata *dd = pp_to_drv(p); + unsigned long flags; + + local_irq_save(flags); + if (!dd->irq_enabled) { + enable_irq(p->irq); + dd->irq_enabled = 1; + } + local_irq_restore(flags); +} + +static void +parport_ax88796_disable_irq(struct parport *p) +{ + struct ax_drvdata *dd = pp_to_drv(p); + unsigned long flags; + + local_irq_save(flags); + if (dd->irq_enabled) { + disable_irq(p->irq); + dd->irq_enabled = 0; + } + local_irq_restore(flags); +} + +static void +parport_ax88796_data_forward(struct parport *p) +{ + struct ax_drvdata *dd = pp_to_drv(p); + void __iomem *cpr = dd->spp_cpr; + + writeb((readb(cpr) & ~AX_CPR_nDOE), cpr); +} + +static void +parport_ax88796_data_reverse(struct parport *p) +{ + struct ax_drvdata *dd = pp_to_drv(p); + void __iomem *cpr = dd->spp_cpr; + + writeb(readb(cpr) | AX_CPR_nDOE, cpr); +} + +static void +parport_ax88796_init_state(struct pardevice *d, struct parport_state *s) +{ + struct ax_drvdata *dd = pp_to_drv(d->port); + + memset(s, 0, sizeof(struct parport_state)); + + dev_dbg(dd->dev, "init_state: %p: state=%p\n", d, s); + s->u.ax88796.cpr = readb(dd->spp_cpr); +} + +static void +parport_ax88796_save_state(struct parport *p, struct parport_state *s) +{ + struct ax_drvdata *dd = pp_to_drv(p); + + dev_dbg(dd->dev, "save_state: %p: state=%p\n", p, s); + s->u.ax88796.cpr = readb(dd->spp_cpr); +} + +static void +parport_ax88796_restore_state(struct parport *p, struct parport_state *s) +{ + struct ax_drvdata *dd = pp_to_drv(p); + + dev_dbg(dd->dev, "restore_state: %p: state=%p\n", p, s); + writeb(s->u.ax88796.cpr, dd->spp_cpr); +} + +static irqreturn_t +parport_ax88796_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + parport_generic_irq(irq, dev_id, regs); + return IRQ_HANDLED; +} + + +static struct parport_operations parport_ax88796_ops = { + .write_data = parport_ax88796_write_data, + .read_data = parport_ax88796_read_data, + + .write_control = parport_ax88796_write_control, + .read_control = parport_ax88796_read_control, + .frob_control = parport_ax88796_frob_control, + + .read_status = parport_ax88796_read_status, + + .enable_irq = parport_ax88796_enable_irq, + .disable_irq = parport_ax88796_disable_irq, + + .data_forward = parport_ax88796_data_forward, + .data_reverse = parport_ax88796_data_reverse, + + .init_state = parport_ax88796_init_state, + .save_state = parport_ax88796_save_state, + .restore_state = parport_ax88796_restore_state, + + .epp_write_data = parport_ieee1284_epp_write_data, + .epp_read_data = parport_ieee1284_epp_read_data, + .epp_write_addr = parport_ieee1284_epp_write_addr, + .epp_read_addr = parport_ieee1284_epp_read_addr, + + .ecp_write_data = parport_ieee1284_ecp_write_data, + .ecp_read_data = parport_ieee1284_ecp_read_data, + .ecp_write_addr = parport_ieee1284_ecp_write_addr, + + .compat_write_data = parport_ieee1284_write_compat, + .nibble_read_data = parport_ieee1284_read_nibble, + .byte_read_data = parport_ieee1284_read_byte, + + .owner = THIS_MODULE, +}; + +static int parport_ax88796_probe(struct platform_device *pdev) +{ + struct device *_dev = &pdev->dev; + struct ax_drvdata *dd; + struct parport *pp = NULL; + struct resource *res; + unsigned long size; + int spacing; + int irq; + int ret; + + dd = kzalloc(sizeof(struct ax_drvdata), GFP_KERNEL); + if (dd == NULL) { + dev_err(_dev, "no memory for private data\n"); + return -ENOMEM; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(_dev, "no MEM specified\n"); + ret = -ENXIO; + goto exit_mem; + } + + size = (res->end - res->start) + 1; + spacing = size / 3; + + dd->io = request_mem_region(res->start, size, pdev->name); + if (dd->io == NULL) { + dev_err(_dev, "cannot reserve memory\n"); + ret = -ENXIO; + goto exit_mem; + } + + dd->base = ioremap(res->start, size); + if (dd->base == NULL) { + dev_err(_dev, "cannot ioremap region\n"); + ret = -ENXIO; + goto exit_res; + } + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) + irq = PARPORT_IRQ_NONE; + + pp = parport_register_port((unsigned long)dd->base, irq, + PARPORT_DMA_NONE, + &parport_ax88796_ops); + + if (pp == NULL) { + dev_err(_dev, "failed to register parallel port\n"); + ret = -ENOMEM; + goto exit_unmap; + } + + pp->private_data = dd; + dd->parport = pp; + dd->dev = _dev; + + dd->spp_data = dd->base; + dd->spp_spr = dd->base + (spacing * 1); + dd->spp_cpr = dd->base + (spacing * 2); + + /* initialise the port controls */ + writeb(AX_CPR_STRB, dd->spp_cpr); + + if (irq >= 0) { + /* request irq */ + ret = request_irq(irq, parport_ax88796_interrupt, + IRQF_TRIGGER_FALLING, pdev->name, pp); + + if (ret < 0) + goto exit_port; + + dd->irq_enabled = 1; + } + + platform_set_drvdata(pdev, pp); + + dev_info(_dev, "attached parallel port driver\n"); + parport_announce_port(pp); + + return 0; + + exit_port: + parport_remove_port(pp); + exit_unmap: + iounmap(dd->base); + exit_res: + release_resource(dd->io); + kfree(dd->io); + exit_mem: + kfree(dd); + return ret; +} + +static int parport_ax88796_remove(struct platform_device *pdev) +{ + struct parport *p = platform_get_drvdata(pdev); + struct ax_drvdata *dd = pp_to_drv(p); + + free_irq(p->irq, p); + parport_remove_port(p); + iounmap(dd->base); + release_resource(dd->io); + kfree(dd->io); + kfree(dd); + + return 0; +} + +#ifdef CONFIG_PM + +static int parport_ax88796_suspend(struct platform_device *dev, + pm_message_t state) +{ + struct parport *p = platform_get_drvdata(dev); + struct ax_drvdata *dd = pp_to_drv(p); + + parport_ax88796_save_state(p, &dd->suspend); + writeb(AX_CPR_nDOE | AX_CPR_STRB, dd->spp_cpr); + return 0; +} + +static int parport_ax88796_resume(struct platform_device *dev) +{ + struct parport *p = platform_get_drvdata(dev); + struct ax_drvdata *dd = pp_to_drv(p); + + parport_ax88796_restore_state(p, &dd->suspend); + return 0; +} + +#else +#define parport_ax88796_suspend NULL +#define parport_ax88796_resume NULL +#endif + +static struct platform_driver axdrv = { + .driver = { + .name = "ax88796-pp", + .owner = THIS_MODULE, + }, + .probe = parport_ax88796_probe, + .remove = parport_ax88796_remove, + .suspend = parport_ax88796_suspend, + .resume = parport_ax88796_resume, +}; + +static int __init parport_ax88796_init(void) +{ + return platform_driver_register(&axdrv); +} + +static void __exit parport_ax88796_exit(void) +{ + platform_driver_unregister(&axdrv); +} + +module_init(parport_ax88796_init) +module_exit(parport_ax88796_exit) + +MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); +MODULE_DESCRIPTION("AX88796 Parport parallel port driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pci/msi-altix.c b/drivers/pci/msi-altix.c new file mode 100644 index 000000000..bed4183a5 --- /dev/null +++ b/drivers/pci/msi-altix.c @@ -0,0 +1,210 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2006 Silicon Graphics, Inc. All Rights Reserved. + */ + +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/cpumask.h> + +#include <asm/sn/addrs.h> +#include <asm/sn/intr.h> +#include <asm/sn/pcibus_provider_defs.h> +#include <asm/sn/pcidev.h> +#include <asm/sn/nodepda.h> + +#include "msi.h" + +struct sn_msi_info { + u64 pci_addr; + struct sn_irq_info *sn_irq_info; +}; + +static struct sn_msi_info *sn_msi_info; + +static void +sn_msi_teardown(unsigned int vector) +{ + nasid_t nasid; + int widget; + struct pci_dev *pdev; + struct pcidev_info *sn_pdev; + struct sn_irq_info *sn_irq_info; + struct pcibus_bussoft *bussoft; + struct sn_pcibus_provider *provider; + + sn_irq_info = sn_msi_info[vector].sn_irq_info; + if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0) + return; + + sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; + pdev = sn_pdev->pdi_linux_pcidev; + provider = SN_PCIDEV_BUSPROVIDER(pdev); + + (*provider->dma_unmap)(pdev, + sn_msi_info[vector].pci_addr, + PCI_DMA_FROMDEVICE); + sn_msi_info[vector].pci_addr = 0; + + bussoft = SN_PCIDEV_BUSSOFT(pdev); + nasid = NASID_GET(bussoft->bs_base); + widget = (nasid & 1) ? + TIO_SWIN_WIDGETNUM(bussoft->bs_base) : + SWIN_WIDGETNUM(bussoft->bs_base); + + sn_intr_free(nasid, widget, sn_irq_info); + sn_msi_info[vector].sn_irq_info = NULL; + + return; +} + +int +sn_msi_setup(struct pci_dev *pdev, unsigned int vector, + u32 *addr_hi, u32 *addr_lo, u32 *data) +{ + int widget; + int status; + nasid_t nasid; + u64 bus_addr; + struct sn_irq_info *sn_irq_info; + struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev); + struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); + + if (bussoft == NULL) + return -EINVAL; + + if (provider == NULL || provider->dma_map_consistent == NULL) + return -EINVAL; + + /* + * Set up the vector plumbing. Let the prom (via sn_intr_alloc) + * decide which cpu to direct this msi at by default. + */ + + nasid = NASID_GET(bussoft->bs_base); + widget = (nasid & 1) ? + TIO_SWIN_WIDGETNUM(bussoft->bs_base) : + SWIN_WIDGETNUM(bussoft->bs_base); + + sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL); + if (! sn_irq_info) + return -ENOMEM; + + status = sn_intr_alloc(nasid, widget, sn_irq_info, vector, -1, -1); + if (status) { + kfree(sn_irq_info); + return -ENOMEM; + } + + sn_irq_info->irq_int_bit = -1; /* mark this as an MSI irq */ + sn_irq_fixup(pdev, sn_irq_info); + + /* Prom probably should fill these in, but doesn't ... */ + sn_irq_info->irq_bridge_type = bussoft->bs_asic_type; + sn_irq_info->irq_bridge = (void *)bussoft->bs_base; + + /* + * Map the xio address into bus space + */ + bus_addr = (*provider->dma_map_consistent)(pdev, + sn_irq_info->irq_xtalkaddr, + sizeof(sn_irq_info->irq_xtalkaddr), + SN_DMA_MSI|SN_DMA_ADDR_XIO); + if (! bus_addr) { + sn_intr_free(nasid, widget, sn_irq_info); + kfree(sn_irq_info); + return -ENOMEM; + } + + sn_msi_info[vector].sn_irq_info = sn_irq_info; + sn_msi_info[vector].pci_addr = bus_addr; + + *addr_hi = (u32)(bus_addr >> 32); + *addr_lo = (u32)(bus_addr & 0x00000000ffffffff); + + /* + * In the SN platform, bit 16 is a "send vector" bit which + * must be present in order to move the vector through the system. + */ + *data = 0x100 + (unsigned int)vector; + +#ifdef CONFIG_SMP + set_irq_affinity_info((vector & 0xff), sn_irq_info->irq_cpuid, 0); +#endif + + return 0; +} + +static void +sn_msi_target(unsigned int vector, unsigned int cpu, + u32 *addr_hi, u32 *addr_lo) +{ + int slice; + nasid_t nasid; + u64 bus_addr; + struct pci_dev *pdev; + struct pcidev_info *sn_pdev; + struct sn_irq_info *sn_irq_info; + struct sn_irq_info *new_irq_info; + struct sn_pcibus_provider *provider; + + sn_irq_info = sn_msi_info[vector].sn_irq_info; + if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0) + return; + + /* + * Release XIO resources for the old MSI PCI address + */ + + sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; + pdev = sn_pdev->pdi_linux_pcidev; + provider = SN_PCIDEV_BUSPROVIDER(pdev); + + bus_addr = (u64)(*addr_hi) << 32 | (u64)(*addr_lo); + (*provider->dma_unmap)(pdev, bus_addr, PCI_DMA_FROMDEVICE); + sn_msi_info[vector].pci_addr = 0; + + nasid = cpuid_to_nasid(cpu); + slice = cpuid_to_slice(cpu); + + new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice); + sn_msi_info[vector].sn_irq_info = new_irq_info; + if (new_irq_info == NULL) + return; + + /* + * Map the xio address into bus space + */ + + bus_addr = (*provider->dma_map_consistent)(pdev, + new_irq_info->irq_xtalkaddr, + sizeof(new_irq_info->irq_xtalkaddr), + SN_DMA_MSI|SN_DMA_ADDR_XIO); + + sn_msi_info[vector].pci_addr = bus_addr; + *addr_hi = (u32)(bus_addr >> 32); + *addr_lo = (u32)(bus_addr & 0x00000000ffffffff); +} + +struct msi_ops sn_msi_ops = { + .setup = sn_msi_setup, + .teardown = sn_msi_teardown, +#ifdef CONFIG_SMP + .target = sn_msi_target, +#endif +}; + +int +sn_msi_init(void) +{ + sn_msi_info = + kzalloc(sizeof(struct sn_msi_info) * NR_VECTORS, GFP_KERNEL); + if (! sn_msi_info) + return -ENOMEM; + + msi_register(&sn_msi_ops); + return 0; +} diff --git a/drivers/pci/msi-apic.c b/drivers/pci/msi-apic.c new file mode 100644 index 000000000..5ed798b31 --- /dev/null +++ b/drivers/pci/msi-apic.c @@ -0,0 +1,101 @@ +/* + * MSI hooks for standard x86 apic + */ + +#include <linux/pci.h> +#include <linux/irq.h> +#include <asm/smp.h> + +#include "msi.h" + +/* + * Shifts for APIC-based data + */ + +#define MSI_DATA_VECTOR_SHIFT 0 +#define MSI_DATA_VECTOR(v) (((u8)v) << MSI_DATA_VECTOR_SHIFT) + +#define MSI_DATA_DELIVERY_SHIFT 8 +#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_SHIFT) +#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_SHIFT) + +#define MSI_DATA_LEVEL_SHIFT 14 +#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT) +#define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT) + +#define MSI_DATA_TRIGGER_SHIFT 15 +#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT) +#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT) + +/* + * Shift/mask fields for APIC-based bus address + */ + +#define MSI_ADDR_HEADER 0xfee00000 + +#define MSI_ADDR_DESTID_MASK 0xfff0000f +#define MSI_ADDR_DESTID_CPU(cpu) ((cpu) << MSI_TARGET_CPU_SHIFT) + +#define MSI_ADDR_DESTMODE_SHIFT 2 +#define MSI_ADDR_DESTMODE_PHYS (0 << MSI_ADDR_DESTMODE_SHIFT) +#define MSI_ADDR_DESTMODE_LOGIC (1 << MSI_ADDR_DESTMODE_SHIFT) + +#define MSI_ADDR_REDIRECTION_SHIFT 3 +#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) +#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) + + +static void +msi_target_apic(unsigned int vector, + unsigned int dest_cpu, + u32 *address_hi, /* in/out */ + u32 *address_lo) /* in/out */ +{ + u32 addr = *address_lo; + + addr &= MSI_ADDR_DESTID_MASK; + addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(dest_cpu)); + + *address_lo = addr; +} + +static int +msi_setup_apic(struct pci_dev *pdev, /* unused in generic */ + unsigned int vector, + u32 *address_hi, + u32 *address_lo, + u32 *data) +{ + unsigned long dest_phys_id; + + dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map)); + + *address_hi = 0; + *address_lo = MSI_ADDR_HEADER | + MSI_ADDR_DESTMODE_PHYS | + MSI_ADDR_REDIRECTION_CPU | + MSI_ADDR_DESTID_CPU(dest_phys_id); + + *data = MSI_DATA_TRIGGER_EDGE | + MSI_DATA_LEVEL_ASSERT | + MSI_DATA_DELIVERY_FIXED | + MSI_DATA_VECTOR(vector); + + return 0; +} + +static void +msi_teardown_apic(unsigned int vector) +{ + return; /* no-op */ +} + +/* + * Generic ops used on most IA archs/platforms. Set with msi_register() + */ + +struct msi_ops msi_apic_ops = { + .setup = msi_setup_apic, + .teardown = msi_teardown_apic, + .target = msi_target_apic, +}; diff --git a/drivers/rtc/rtc-at91.c b/drivers/rtc/rtc-at91.c new file mode 100644 index 000000000..dfd0ce86f --- /dev/null +++ b/drivers/rtc/rtc-at91.c @@ -0,0 +1,407 @@ +/* + * Real Time Clock interface for Linux on Atmel AT91RM9200 + * + * Copyright (C) 2002 Rick Bronson + * + * Converted to RTC class model by Andrew Victor + * + * Ported to Linux 2.6 by Steven Scholz + * Based on s3c2410-rtc.c Simtec Electronics + * + * Based on sa1100-rtc.c by Nils Faerber + * Based on rtc.c by Paul Gortmaker + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/time.h> +#include <linux/rtc.h> +#include <linux/bcd.h> +#include <linux/interrupt.h> +#include <linux/ioctl.h> +#include <linux/completion.h> + +#include <asm/uaccess.h> +#include <asm/rtc.h> + +#include <asm/mach/time.h> + + +#define AT91_RTC_FREQ 1 +#define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */ + +static DECLARE_COMPLETION(at91_rtc_updated); +static unsigned int at91_alarm_year = AT91_RTC_EPOCH; + +/* + * Decode time/date into rtc_time structure + */ +static void at91_rtc_decodetime(unsigned int timereg, unsigned int calreg, + struct rtc_time *tm) +{ + unsigned int time, date; + + /* must read twice in case it changes */ + do { + time = at91_sys_read(timereg); + date = at91_sys_read(calreg); + } while ((time != at91_sys_read(timereg)) || + (date != at91_sys_read(calreg))); + + tm->tm_sec = BCD2BIN((time & AT91_RTC_SEC) >> 0); + tm->tm_min = BCD2BIN((time & AT91_RTC_MIN) >> 8); + tm->tm_hour = BCD2BIN((time & AT91_RTC_HOUR) >> 16); + + /* + * The Calendar Alarm register does not have a field for + * the year - so these will return an invalid value. When an + * alarm is set, at91_alarm_year wille store the current year. + */ + tm->tm_year = BCD2BIN(date & AT91_RTC_CENT) * 100; /* century */ + tm->tm_year += BCD2BIN((date & AT91_RTC_YEAR) >> 8); /* year */ + + tm->tm_wday = BCD2BIN((date & AT91_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */ + tm->tm_mon = BCD2BIN((date & AT91_RTC_MONTH) >> 16) - 1; + tm->tm_mday = BCD2BIN((date & AT91_RTC_DATE) >> 24); +} + +/* + * Read current time and date in RTC + */ +static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm) +{ + at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, tm); + tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); + tm->tm_year = tm->tm_year - 1900; + + pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, + 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + return 0; +} + +/* + * Set current time and date in RTC + */ +static int at91_rtc_settime(struct device *dev, struct rtc_time *tm) +{ + unsigned long cr; + + pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, + 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + /* Stop Time/Calendar from counting */ + cr = at91_sys_read(AT91_RTC_CR); + at91_sys_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM); + + at91_sys_write(AT91_RTC_IER, AT91_RTC_ACKUPD); + wait_for_completion(&at91_rtc_updated); /* wait for ACKUPD interrupt */ + at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD); + + at91_sys_write(AT91_RTC_TIMR, + BIN2BCD(tm->tm_sec) << 0 + | BIN2BCD(tm->tm_min) << 8 + | BIN2BCD(tm->tm_hour) << 16); + + at91_sys_write(AT91_RTC_CALR, + BIN2BCD((tm->tm_year + 1900) / 100) /* century */ + | BIN2BCD(tm->tm_year % 100) << 8 /* year */ + | BIN2BCD(tm->tm_mon + 1) << 16 /* tm_mon starts at zero */ + | BIN2BCD(tm->tm_wday + 1) << 21 /* day of the week [0-6], Sunday=0 */ + | BIN2BCD(tm->tm_mday) << 24); + + /* Restart Time/Calendar */ + cr = at91_sys_read(AT91_RTC_CR); + at91_sys_write(AT91_RTC_CR, cr & ~(AT91_RTC_UPDCAL | AT91_RTC_UPDTIM)); + + return 0; +} + +/* + * Read alarm time and date in RTC + */ +static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct rtc_time *tm = &alrm->time; + + at91_rtc_decodetime(AT91_RTC_TIMALR, AT91_RTC_CALALR, tm); + tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); + tm->tm_year = at91_alarm_year - 1900; + + pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, + 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + return 0; +} + +/* + * Set alarm time and date in RTC + */ +static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct rtc_time tm; + + at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, &tm); + + at91_alarm_year = tm.tm_year; + + tm.tm_hour = alrm->time.tm_hour; + tm.tm_min = alrm->time.tm_min; + tm.tm_sec = alrm->time.tm_sec; + + at91_sys_write(AT91_RTC_TIMALR, + BIN2BCD(tm.tm_sec) << 0 + | BIN2BCD(tm.tm_min) << 8 + | BIN2BCD(tm.tm_hour) << 16 + | AT91_RTC_HOUREN | AT91_RTC_MINEN | AT91_RTC_SECEN); + at91_sys_write(AT91_RTC_CALALR, + BIN2BCD(tm.tm_mon + 1) << 16 /* tm_mon starts at zero */ + | BIN2BCD(tm.tm_mday) << 24 + | AT91_RTC_DATEEN | AT91_RTC_MTHEN); + + pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, + at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, + tm.tm_min, tm.tm_sec); + + return 0; +} + +/* + * Handle commands from user-space + */ +static int at91_rtc_ioctl(struct device *dev, unsigned int cmd, + unsigned long arg) +{ + int ret = 0; + + pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __FUNCTION__, cmd, arg); + + switch (cmd) { + case RTC_AIE_OFF: /* alarm off */ + at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM); + break; + case RTC_AIE_ON: /* alarm on */ + at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM); + break; + case RTC_UIE_OFF: /* update off */ + case RTC_PIE_OFF: /* periodic off */ + at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV); + break; + case RTC_UIE_ON: /* update on */ + case RTC_PIE_ON: /* periodic on */ + at91_sys_write(AT91_RTC_IER, AT91_RTC_SECEV); + break; + case RTC_IRQP_READ: /* read periodic alarm frequency */ + ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg); + break; + case RTC_IRQP_SET: /* set periodic alarm frequency */ + if (arg != AT91_RTC_FREQ) + ret = -EINVAL; + break; + default: + ret = -ENOIOCTLCMD; + break; + } + + return ret; +} + +/* + * Provide additional RTC information in /proc/driver/rtc + */ +static int at91_rtc_proc(struct device *dev, struct seq_file *seq) +{ + unsigned long imr = at91_sys_read(AT91_RTC_IMR); + + seq_printf(seq, "alarm_IRQ\t: %s\n", + (imr & AT91_RTC_ALARM) ? "yes" : "no"); + seq_printf(seq, "update_IRQ\t: %s\n", + (imr & AT91_RTC_ACKUPD) ? "yes" : "no"); + seq_printf(seq, "periodic_IRQ\t: %s\n", + (imr & AT91_RTC_SECEV) ? "yes" : "no"); + seq_printf(seq, "periodic_freq\t: %ld\n", + (unsigned long) AT91_RTC_FREQ); + + return 0; +} + +/* + * IRQ handler for the RTC + */ +static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + struct platform_device *pdev = dev_id; + struct rtc_device *rtc = platform_get_drvdata(pdev); + unsigned int rtsr; + unsigned long events = 0; + + rtsr = at91_sys_read(AT91_RTC_SR) & at91_sys_read(AT91_RTC_IMR); + if (rtsr) { /* this interrupt is shared! Is it ours? */ + if (rtsr & AT91_RTC_ALARM) + events |= (RTC_AF | RTC_IRQF); + if (rtsr & AT91_RTC_SECEV) + events |= (RTC_UF | RTC_IRQF); + if (rtsr & AT91_RTC_ACKUPD) + complete(&at91_rtc_updated); + + at91_sys_write(AT91_RTC_SCCR, rtsr); /* clear status reg */ + + rtc_update_irq(&rtc->class_dev, 1, events); + + pr_debug("%s(): num=%ld, events=0x%02lx\n", __FUNCTION__, + events >> 8, events & 0x000000FF); + + return IRQ_HANDLED; + } + return IRQ_NONE; /* not handled */ +} + +static struct rtc_class_ops at91_rtc_ops = { + .ioctl = at91_rtc_ioctl, + .read_time = at91_rtc_readtime, + .set_time = at91_rtc_settime, + .read_alarm = at91_rtc_readalarm, + .set_alarm = at91_rtc_setalarm, + .proc = at91_rtc_proc, +}; + +/* + * Initialize and install RTC driver + */ +static int __init at91_rtc_probe(struct platform_device *pdev) +{ + struct rtc_device *rtc; + int ret; + + at91_sys_write(AT91_RTC_CR, 0); + at91_sys_write(AT91_RTC_MR, 0); /* 24 hour mode */ + + /* Disable all interrupts */ + at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | + AT91_RTC_SECEV | AT91_RTC_TIMEV | + AT91_RTC_CALEV); + + ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, + IRQF_SHARED, "at91_rtc", pdev); + if (ret) { + printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n", + AT91_ID_SYS); + return ret; + } + + rtc = rtc_device_register(pdev->name, &pdev->dev, + &at91_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) { + free_irq(AT91_ID_SYS, pdev); + return PTR_ERR(rtc); + } + platform_set_drvdata(pdev, rtc); + + printk(KERN_INFO "AT91 Real Time Clock driver.\n"); + return 0; +} + +/* + * Disable and remove the RTC driver + */ +static int __devexit at91_rtc_remove(struct platform_device *pdev) +{ + struct rtc_device *rtc = platform_get_drvdata(pdev); + + /* Disable all interrupts */ + at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | + AT91_RTC_SECEV | AT91_RTC_TIMEV | + AT91_RTC_CALEV); + free_irq(AT91_ID_SYS, pdev); + + rtc_device_unregister(rtc); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +#ifdef CONFIG_PM + +/* AT91RM9200 RTC Power management control */ + +static struct timespec at91_rtc_delta; + +static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct rtc_time tm; + struct timespec time; + + time.tv_nsec = 0; + + /* calculate time delta for suspend */ + at91_rtc_readtime(&pdev->dev, &tm); + rtc_tm_to_time(&tm, &time.tv_sec); + save_time_delta(&at91_rtc_delta, &time); + + pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, + 1900 + tm.tm_year, tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + + return 0; +} + +static int at91_rtc_resume(struct platform_device *pdev) +{ + struct rtc_time tm; + struct timespec time; + + time.tv_nsec = 0; + + at91_rtc_readtime(&pdev->dev, &tm); + rtc_tm_to_time(&tm, &time.tv_sec); + restore_time_delta(&at91_rtc_delta, &time); + + pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__, + 1900 + tm.tm_year, tm.tm_mon, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + + return 0; +} +#else +#define at91_rtc_suspend NULL +#define at91_rtc_resume NULL +#endif + +static struct platform_driver at91_rtc_driver = { + .probe = at91_rtc_probe, + .remove = at91_rtc_remove, + .suspend = at91_rtc_suspend, + .resume = at91_rtc_resume, + .driver = { + .name = "at91_rtc", + .owner = THIS_MODULE, + }, +}; + +static int __init at91_rtc_init(void) +{ + return platform_driver_register(&at91_rtc_driver); +} + +static void __exit at91_rtc_exit(void) +{ + platform_driver_unregister(&at91_rtc_driver); +} + +module_init(at91_rtc_init); +module_exit(at91_rtc_exit); + +MODULE_AUTHOR("Rick Bronson"); +MODULE_DESCRIPTION("RTC driver for Atmel AT91RM9200"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c new file mode 100644 index 000000000..e8afb9384 --- /dev/null +++ b/drivers/rtc/rtc-ds1307.c @@ -0,0 +1,388 @@ +/* + * rtc-ds1307.c - RTC driver for some mostly-compatible I2C chips. + * + * Copyright (C) 2005 James Chapman (ds1337 core) + * Copyright (C) 2006 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/string.h> +#include <linux/rtc.h> +#include <linux/bcd.h> + + + +/* We can't determine type by probing, but if we expect pre-Linux code + * to have set the chip up as a clock (turning on the oscillator and + * setting the date and time), Linux can ignore the non-clock features. + * That's a natural job for a factory or repair bench. + * + * If the I2C "force" mechanism is used, we assume the chip is a ds1337. + * (Much better would be board-specific tables of I2C devices, along with + * the platform_data drivers would use to sort such issues out.) + */ +enum ds_type { + unknown = 0, + ds_1307, /* or ds1338, ... */ + ds_1337, /* or ds1339, ... */ + ds_1340, /* or st m41t00, ... */ + // rs5c372 too? different address... +}; + +static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END }; + +I2C_CLIENT_INSMOD; + + + +/* RTC registers don't differ much, except for the century flag */ +#define DS1307_REG_SECS 0x00 /* 00-59 */ +# define DS1307_BIT_CH 0x80 +#define DS1307_REG_MIN 0x01 /* 00-59 */ +#define DS1307_REG_HOUR 0x02 /* 00-23, or 1-12{am,pm} */ +# define DS1340_BIT_CENTURY_EN 0x80 /* in REG_HOUR */ +# define DS1340_BIT_CENTURY 0x40 /* in REG_HOUR */ +#define DS1307_REG_WDAY 0x03 /* 01-07 */ +#define DS1307_REG_MDAY 0x04 /* 01-31 */ +#define DS1307_REG_MONTH 0x05 /* 01-12 */ +# define DS1337_BIT_CENTURY 0x80 /* in REG_MONTH */ +#define DS1307_REG_YEAR 0x06 /* 00-99 */ + +/* Other registers (control, status, alarms, trickle charge, NVRAM, etc) + * start at 7, and they differ a lot. Only control and status matter for RTC; + * be careful using them. + */ +#define DS1307_REG_CONTROL 0x07 +# define DS1307_BIT_OUT 0x80 +# define DS1307_BIT_SQWE 0x10 +# define DS1307_BIT_RS1 0x02 +# define DS1307_BIT_RS0 0x01 +#define DS1337_REG_CONTROL 0x0e +# define DS1337_BIT_nEOSC 0x80 +# define DS1337_BIT_RS2 0x10 +# define DS1337_BIT_RS1 0x08 +# define DS1337_BIT_INTCN 0x04 +# define DS1337_BIT_A2IE 0x02 +# define DS1337_BIT_A1IE 0x01 +#define DS1337_REG_STATUS 0x0f +# define DS1337_BIT_OSF 0x80 +# define DS1337_BIT_A2I 0x02 +# define DS1337_BIT_A1I 0x01 +#define DS1339_REG_TRICKLE 0x10 + + + +struct ds1307 { + u8 reg_addr; + u8 regs[8]; + enum ds_type type; + struct i2c_msg msg[2]; + struct i2c_client client; + struct rtc_device *rtc; +}; + + +static int ds1307_get_time(struct device *dev, struct rtc_time *t) +{ + struct ds1307 *ds1307 = dev_get_drvdata(dev); + int tmp; + + /* read the RTC registers all at once */ + ds1307->msg[1].flags = I2C_M_RD; + ds1307->msg[1].len = 7; + + tmp = i2c_transfer(ds1307->client.adapter, ds1307->msg, 2); + if (tmp != 2) { + dev_err(dev, "%s error %d\n", "read", tmp); + return -EIO; + } + + dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n", + "read", + ds1307->regs[0], ds1307->regs[1], + ds1307->regs[2], ds1307->regs[3], + ds1307->regs[4], ds1307->regs[5], + ds1307->regs[6]); + + t->tm_sec = BCD2BIN(ds1307->regs[DS1307_REG_SECS] & 0x7f); + t->tm_min = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f); + tmp = ds1307->regs[DS1307_REG_HOUR] & 0x3f; + t->tm_hour = BCD2BIN(tmp); + t->tm_wday = BCD2BIN(ds1307->regs[DS1307_REG_WDAY] & 0x07) - 1; + t->tm_mday = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f); + tmp = ds1307->regs[DS1307_REG_MONTH] & 0x1f; + t->tm_mon = BCD2BIN(tmp) - 1; + + /* assume 20YY not 19YY, and ignore DS1337_BIT_CENTURY */ + t->tm_year = BCD2BIN(ds1307->regs[DS1307_REG_YEAR]) + 100; + + dev_dbg(dev, "%s secs=%d, mins=%d, " + "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", + "read", t->tm_sec, t->tm_min, + t->tm_hour, t->tm_mday, + t->tm_mon, t->tm_year, t->tm_wday); + + return 0; +} + +static int ds1307_set_time(struct device *dev, struct rtc_time *t) +{ + struct ds1307 *ds1307 = dev_get_drvdata(dev); + int result; + int tmp; + u8 *buf = ds1307->regs; + + dev_dbg(dev, "%s secs=%d, mins=%d, " + "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n", + "write", dt->tm_sec, dt->tm_min, + dt->tm_hour, dt->tm_mday, + dt->tm_mon, dt->tm_year, dt->tm_wday); + + *buf++ = 0; /* first register addr */ + buf[DS1307_REG_SECS] = BIN2BCD(t->tm_sec); + buf[DS1307_REG_MIN] = BIN2BCD(t->tm_min); + buf[DS1307_REG_HOUR] = BIN2BCD(t->tm_hour); + buf[DS1307_REG_WDAY] = BIN2BCD(t->tm_wday + 1); + buf[DS1307_REG_MDAY] = BIN2BCD(t->tm_mday); + buf[DS1307_REG_MONTH] = BIN2BCD(t->tm_mon + 1); + + /* assume 20YY not 19YY */ + tmp = t->tm_year - 100; + buf[DS1307_REG_YEAR] = BIN2BCD(tmp); + + if (ds1307->type == ds_1337) + buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY; + else if (ds1307->type == ds_1340) + buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN + | DS1340_BIT_CENTURY; + + ds1307->msg[1].flags = 0; + ds1307->msg[1].len = 8; + + dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n", + "write", buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6]); + + result = i2c_transfer(ds1307->client.adapter, &ds1307->msg[1], 1); + if (result != 1) { + dev_err(dev, "%s error %d\n", "write", tmp); + return -EIO; + } + return 0; +} + +static struct rtc_class_ops ds13xx_rtc_ops = { + .read_time = ds1307_get_time, + .set_time = ds1307_set_time, +}; + +static struct i2c_driver ds1307_driver; + +static int __devinit +ds1307_detect(struct i2c_adapter *adapter, int address, int kind) +{ + struct ds1307 *ds1307; + int err = -ENODEV; + struct i2c_client *client; + int tmp; + + if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL))) { + err = -ENOMEM; + goto exit; + } + + client = &ds1307->client; + client->addr = address; + client->adapter = adapter; + client->driver = &ds1307_driver; + client->flags = 0; + + i2c_set_clientdata(client, ds1307); + + ds1307->msg[0].addr = client->addr; + ds1307->msg[0].flags = 0; + ds1307->msg[0].len = 1; + ds1307->msg[0].buf = &ds1307->reg_addr; + + ds1307->msg[1].addr = client->addr; + ds1307->msg[1].flags = I2C_M_RD; + ds1307->msg[1].len = sizeof(ds1307->regs); + ds1307->msg[1].buf = ds1307->regs; + + /* HACK: "force" implies "needs ds1337-style-oscillator setup" */ + if (kind >= 0) { + ds1307->type = ds_1337; + + ds1307->reg_addr = DS1337_REG_CONTROL; + ds1307->msg[1].len = 2; + + tmp = i2c_transfer(client->adapter, ds1307->msg, 2); + if (tmp != 2) { + pr_debug("read error %d\n", tmp); + err = -EIO; + goto exit_free; + } + + ds1307->reg_addr = 0; + ds1307->msg[1].len = sizeof(ds1307->regs); + + /* oscillator is off; need to turn it on */ + if ((ds1307->regs[0] & DS1337_BIT_nEOSC) + || (ds1307->regs[1] & DS1337_BIT_OSF)) { + printk(KERN_ERR "no ds1337 oscillator code\n"); + goto exit_free; + } + } else + ds1307->type = ds_1307; + +read_rtc: + /* read RTC registers */ + + tmp = i2c_transfer(client->adapter, ds1307->msg, 2); + if (tmp != 2) { + pr_debug("read error %d\n", tmp); + err = -EIO; + goto exit_free; + } + + /* minimal sanity checking; some chips (like DS1340) don't + * specify the extra bits as must-be-zero, but there are + * still a few values that are clearly out-of-range. + */ + tmp = ds1307->regs[DS1307_REG_SECS]; + if (tmp & DS1307_BIT_CH) { + if (ds1307->type && ds1307->type != ds_1307) { + pr_debug("not a ds1307?\n"); + goto exit_free; + } + ds1307->type = ds_1307; + + /* this partial initialization should work for ds1307, + * ds1338, ds1340, st m41t00, and more. + */ + dev_warn(&client->dev, "oscillator started; SET TIME!\n"); + i2c_smbus_write_byte_data(client, 0, 0); + goto read_rtc; + } + tmp = BCD2BIN(tmp & 0x7f); + if (tmp > 60) + goto exit_free; + tmp = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f); + if (tmp > 60) + goto exit_free; + + tmp = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f); + if (tmp == 0 || tmp > 31) + goto exit_free; + + tmp = BCD2BIN(ds1307->regs[DS1307_REG_MONTH] & 0x1f); + if (tmp == 0 || tmp > 12) + goto exit_free; + + /* force into in 24 hour mode (most chips) or + * disable century bit (ds1340) + */ + tmp = ds1307->regs[DS1307_REG_HOUR]; + if (tmp & (1 << 6)) { + if (tmp & (1 << 5)) + tmp = BCD2BIN(tmp & 0x1f) + 12; + else + tmp = BCD2BIN(tmp); + i2c_smbus_write_byte_data(client, + DS1307_REG_HOUR, + BIN2BCD(tmp)); + } + + /* FIXME chips like 1337 can generate alarm irqs too; those are + * worth exposing through the API (especially when the irq is + * wakeup-capable). + */ + + switch (ds1307->type) { + case unknown: + strlcpy(client->name, "unknown", I2C_NAME_SIZE); + break; + case ds_1307: + strlcpy(client->name, "ds1307", I2C_NAME_SIZE); + break; + case ds_1337: + strlcpy(client->name, "ds1337", I2C_NAME_SIZE); + break; + case ds_1340: + strlcpy(client->name, "ds1340", I2C_NAME_SIZE); + break; + } + + /* Tell the I2C layer a new client has arrived */ + if ((err = i2c_attach_client(client))) + goto exit_free; + + ds1307->rtc = rtc_device_register(client->name, &client->dev, + &ds13xx_rtc_ops, THIS_MODULE); + if (IS_ERR(ds1307->rtc)) { + err = PTR_ERR(ds1307->rtc); + dev_err(&client->dev, + "unable to register the class device\n"); + goto exit_detach; + } + + return 0; + +exit_detach: + i2c_detach_client(client); +exit_free: + kfree(ds1307); +exit: + return err; +} + +static int __devinit +ds1307_attach_adapter(struct i2c_adapter *adapter) +{ + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) + return 0; + return i2c_probe(adapter, &addr_data, ds1307_detect); +} + +static int __devexit ds1307_detach_client(struct i2c_client *client) +{ + int err; + struct ds1307 *ds1307 = i2c_get_clientdata(client); + + rtc_device_unregister(ds1307->rtc); + if ((err = i2c_detach_client(client))) + return err; + kfree(ds1307); + return 0; +} + +static struct i2c_driver ds1307_driver = { + .driver = { + .name = "ds1307", + .owner = THIS_MODULE, + }, + .attach_adapter = ds1307_attach_adapter, + .detach_client = __devexit_p(ds1307_detach_client), +}; + +static int __init ds1307_init(void) +{ + return i2c_add_driver(&ds1307_driver); +} +module_init(ds1307_init); + +static void __exit ds1307_exit(void) +{ + i2c_del_driver(&ds1307_driver); +} +module_exit(ds1307_exit); + +MODULE_DESCRIPTION("RTC driver for DS1307 and similar chips"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c new file mode 100644 index 000000000..209001495 --- /dev/null +++ b/drivers/rtc/rtc-ds1553.c @@ -0,0 +1,414 @@ +/* + * An rtc driver for the Dallas DS1553 + * + * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/bcd.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/jiffies.h> +#include <linux/interrupt.h> +#include <linux/rtc.h> +#include <linux/platform_device.h> +#include <linux/io.h> + +#define DRV_VERSION "0.1" + +#define RTC_REG_SIZE 0x2000 +#define RTC_OFFSET 0x1ff0 + +#define RTC_FLAGS (RTC_OFFSET + 0) +#define RTC_SECONDS_ALARM (RTC_OFFSET + 2) +#define RTC_MINUTES_ALARM (RTC_OFFSET + 3) +#define RTC_HOURS_ALARM (RTC_OFFSET + 4) +#define RTC_DATE_ALARM (RTC_OFFSET + 5) +#define RTC_INTERRUPTS (RTC_OFFSET + 6) +#define RTC_WATCHDOG (RTC_OFFSET + 7) +#define RTC_CONTROL (RTC_OFFSET + 8) +#define RTC_CENTURY (RTC_OFFSET + 8) +#define RTC_SECONDS (RTC_OFFSET + 9) +#define RTC_MINUTES (RTC_OFFSET + 10) +#define RTC_HOURS (RTC_OFFSET + 11) +#define RTC_DAY (RTC_OFFSET + 12) +#define RTC_DATE (RTC_OFFSET + 13) +#define RTC_MONTH (RTC_OFFSET + 14) +#define RTC_YEAR (RTC_OFFSET + 15) + +#define RTC_CENTURY_MASK 0x3f +#define RTC_SECONDS_MASK 0x7f +#define RTC_DAY_MASK 0x07 + +/* Bits in the Control/Century register */ +#define RTC_WRITE 0x80 +#define RTC_READ 0x40 + +/* Bits in the Seconds register */ +#define RTC_STOP 0x80 + +/* Bits in the Flags register */ +#define RTC_FLAGS_AF 0x40 +#define RTC_FLAGS_BLF 0x10 + +/* Bits in the Interrupts register */ +#define RTC_INTS_AE 0x80 + +struct rtc_plat_data { + struct rtc_device *rtc; + void __iomem *ioaddr; + unsigned long baseaddr; + unsigned long last_jiffies; + int irq; + unsigned int irqen; + int alrm_sec; + int alrm_min; + int alrm_hour; + int alrm_mday; +}; + +static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + u8 century; + + century = BIN2BCD((tm->tm_year + 1900) / 100); + + writeb(RTC_WRITE, pdata->ioaddr + RTC_CONTROL); + + writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR); + writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH); + writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY); + writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE); + writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS); + writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES); + writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS); + + /* RTC_CENTURY and RTC_CONTROL share same register */ + writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY); + writeb(century & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL); + return 0; +} + +static int ds1553_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + unsigned int year, month, day, hour, minute, second, week; + unsigned int century; + + /* give enough time to update RTC in case of continuous read */ + if (pdata->last_jiffies == jiffies) + msleep(1); + pdata->last_jiffies = jiffies; + writeb(RTC_READ, ioaddr + RTC_CONTROL); + second = readb(ioaddr + RTC_SECONDS) & RTC_SECONDS_MASK; + minute = readb(ioaddr + RTC_MINUTES); + hour = readb(ioaddr + RTC_HOURS); + day = readb(ioaddr + RTC_DATE); + week = readb(ioaddr + RTC_DAY) & RTC_DAY_MASK; + month = readb(ioaddr + RTC_MONTH); + year = readb(ioaddr + RTC_YEAR); + century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK; + writeb(0, ioaddr + RTC_CONTROL); + tm->tm_sec = BCD2BIN(second); + tm->tm_min = BCD2BIN(minute); + tm->tm_hour = BCD2BIN(hour); + tm->tm_mday = BCD2BIN(day); + tm->tm_wday = BCD2BIN(week); + tm->tm_mon = BCD2BIN(month) - 1; + /* year is 1900 + tm->tm_year */ + tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900; + + if (rtc_valid_tm(tm) < 0) { + dev_err(dev, "retrieved date/time is not valid.\n"); + rtc_time_to_tm(0, tm); + } + return 0; +} + +static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata) +{ + void __iomem *ioaddr = pdata->ioaddr; + unsigned long flags; + + spin_lock_irqsave(&pdata->rtc->irq_lock, flags); + writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? + 0x80 : BIN2BCD(pdata->alrm_mday), + ioaddr + RTC_DATE_ALARM); + writeb(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ? + 0x80 : BIN2BCD(pdata->alrm_hour), + ioaddr + RTC_HOURS_ALARM); + writeb(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ? + 0x80 : BIN2BCD(pdata->alrm_min), + ioaddr + RTC_MINUTES_ALARM); + writeb(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ? + 0x80 : BIN2BCD(pdata->alrm_sec), + ioaddr + RTC_SECONDS_ALARM); + writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS); + readb(ioaddr + RTC_FLAGS); /* clear interrupts */ + spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags); +} + +static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + + if (pdata->irq < 0) + return -EINVAL; + pdata->alrm_mday = alrm->time.tm_mday; + pdata->alrm_hour = alrm->time.tm_hour; + pdata->alrm_min = alrm->time.tm_min; + pdata->alrm_sec = alrm->time.tm_sec; + if (alrm->enabled) + pdata->irqen |= RTC_AF; + ds1553_rtc_update_alarm(pdata); + return 0; +} + +static int ds1553_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + + if (pdata->irq < 0) + return -EINVAL; + alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday; + alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour; + alrm->time.tm_min = pdata->alrm_min < 0 ? 0 : pdata->alrm_min; + alrm->time.tm_sec = pdata->alrm_sec < 0 ? 0 : pdata->alrm_sec; + alrm->enabled = (pdata->irqen & RTC_AF) ? 1 : 0; + return 0; +} + +static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + struct platform_device *pdev = dev_id; + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + unsigned long events = RTC_IRQF; + + /* read and clear interrupt */ + if (!(readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF)) + return IRQ_NONE; + if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80) + events |= RTC_UF; + else + events |= RTC_AF; + rtc_update_irq(&pdata->rtc->class_dev, 1, events); + return IRQ_HANDLED; +} + +static void ds1553_rtc_release(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + + if (pdata->irq >= 0) { + pdata->irqen = 0; + ds1553_rtc_update_alarm(pdata); + } +} + +static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd, + unsigned long arg) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + + if (pdata->irq < 0) + return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ + switch (cmd) { + case RTC_AIE_OFF: + pdata->irqen &= ~RTC_AF; + ds1553_rtc_update_alarm(pdata); + break; + case RTC_AIE_ON: + pdata->irqen |= RTC_AF; + ds1553_rtc_update_alarm(pdata); + break; + case RTC_UIE_OFF: + pdata->irqen &= ~RTC_UF; + ds1553_rtc_update_alarm(pdata); + break; + case RTC_UIE_ON: + pdata->irqen |= RTC_UF; + ds1553_rtc_update_alarm(pdata); + break; + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static struct rtc_class_ops ds1553_rtc_ops = { + .read_time = ds1553_rtc_read_time, + .set_time = ds1553_rtc_set_time, + .read_alarm = ds1553_rtc_read_alarm, + .set_alarm = ds1553_rtc_set_alarm, + .release = ds1553_rtc_release, + .ioctl = ds1553_rtc_ioctl, +}; + +static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf, + loff_t pos, size_t size) +{ + struct platform_device *pdev = + to_platform_device(container_of(kobj, struct device, kobj)); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + ssize_t count; + + for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) + *buf++ = readb(ioaddr + pos++); + return count; +} + +static ssize_t ds1553_nvram_write(struct kobject *kobj, char *buf, + loff_t pos, size_t size) +{ + struct platform_device *pdev = + to_platform_device(container_of(kobj, struct device, kobj)); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + ssize_t count; + + for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) + writeb(*buf++, ioaddr + pos++); + return count; +} + +static struct bin_attribute ds1553_nvram_attr = { + .attr = { + .name = "nvram", + .mode = S_IRUGO | S_IWUGO, + .owner = THIS_MODULE, + }, + .size = RTC_OFFSET, + .read = ds1553_nvram_read, + .write = ds1553_nvram_write, +}; + +static int __init ds1553_rtc_probe(struct platform_device *pdev) +{ + struct rtc_device *rtc; + struct resource *res; + unsigned int cen, sec; + struct rtc_plat_data *pdata = NULL; + void __iomem *ioaddr = NULL; + int ret = 0; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + pdata->irq = -1; + if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) { + ret = -EBUSY; + goto out; + } + pdata->baseaddr = res->start; + ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE); + if (!ioaddr) { + ret = -ENOMEM; + goto out; + } + pdata->ioaddr = ioaddr; + pdata->irq = platform_get_irq(pdev, 0); + + /* turn RTC on if it was not on */ + sec = readb(ioaddr + RTC_SECONDS); + if (sec & RTC_STOP) { + sec &= RTC_SECONDS_MASK; + cen = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK; + writeb(RTC_WRITE, ioaddr + RTC_CONTROL); + writeb(sec, ioaddr + RTC_SECONDS); + writeb(cen & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL); + } + if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_BLF) + dev_warn(&pdev->dev, "voltage-low detected.\n"); + + if (pdata->irq >= 0) { + writeb(0, ioaddr + RTC_INTERRUPTS); + if (request_irq(pdata->irq, ds1553_rtc_interrupt, IRQF_SHARED, + pdev->name, pdev) < 0) { + dev_warn(&pdev->dev, "interrupt not available.\n"); + pdata->irq = -1; + } + } + + rtc = rtc_device_register(pdev->name, &pdev->dev, + &ds1553_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) { + ret = PTR_ERR(rtc); + goto out; + } + pdata->rtc = rtc; + pdata->last_jiffies = jiffies; + platform_set_drvdata(pdev, pdata); + sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); + return 0; + out: + if (pdata->irq >= 0) + free_irq(pdata->irq, pdev); + if (ioaddr) + iounmap(ioaddr); + if (pdata->baseaddr) + release_mem_region(pdata->baseaddr, RTC_REG_SIZE); + kfree(pdata); + return ret; +} + +static int __devexit ds1553_rtc_remove(struct platform_device *pdev) +{ + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + + sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr); + rtc_device_unregister(pdata->rtc); + if (pdata->irq >= 0) { + writeb(0, pdata->ioaddr + RTC_INTERRUPTS); + free_irq(pdata->irq, pdev); + } + iounmap(pdata->ioaddr); + release_mem_region(pdata->baseaddr, RTC_REG_SIZE); + kfree(pdata); + return 0; +} + +static struct platform_driver ds1553_rtc_driver = { + .probe = ds1553_rtc_probe, + .remove = __devexit_p(ds1553_rtc_remove), + .driver = { + .name = "ds1553", + .owner = THIS_MODULE, + }, +}; + +static __init int ds1553_init(void) +{ + return platform_driver_register(&ds1553_rtc_driver); +} + +static __exit void ds1553_exit(void) +{ + return platform_driver_unregister(&ds1553_rtc_driver); +} + +module_init(ds1553_init); +module_exit(ds1553_exit); + +MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); +MODULE_DESCRIPTION("Dallas DS1553 RTC driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c new file mode 100644 index 000000000..8e47e5a06 --- /dev/null +++ b/drivers/rtc/rtc-ds1742.c @@ -0,0 +1,259 @@ +/* + * An rtc driver for the Dallas DS1742 + * + * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/bcd.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/delay.h> +#include <linux/jiffies.h> +#include <linux/rtc.h> +#include <linux/platform_device.h> +#include <linux/io.h> + +#define DRV_VERSION "0.1" + +#define RTC_REG_SIZE 0x800 +#define RTC_OFFSET 0x7f8 + +#define RTC_CONTROL (RTC_OFFSET + 0) +#define RTC_CENTURY (RTC_OFFSET + 0) +#define RTC_SECONDS (RTC_OFFSET + 1) +#define RTC_MINUTES (RTC_OFFSET + 2) +#define RTC_HOURS (RTC_OFFSET + 3) +#define RTC_DAY (RTC_OFFSET + 4) +#define RTC_DATE (RTC_OFFSET + 5) +#define RTC_MONTH (RTC_OFFSET + 6) +#define RTC_YEAR (RTC_OFFSET + 7) + +#define RTC_CENTURY_MASK 0x3f +#define RTC_SECONDS_MASK 0x7f +#define RTC_DAY_MASK 0x07 + +/* Bits in the Control/Century register */ +#define RTC_WRITE 0x80 +#define RTC_READ 0x40 + +/* Bits in the Seconds register */ +#define RTC_STOP 0x80 + +/* Bits in the Day register */ +#define RTC_BATT_FLAG 0x80 + +struct rtc_plat_data { + struct rtc_device *rtc; + void __iomem *ioaddr; + unsigned long baseaddr; + unsigned long last_jiffies; +}; + +static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + u8 century; + + century = BIN2BCD((tm->tm_year + 1900) / 100); + + writeb(RTC_WRITE, ioaddr + RTC_CONTROL); + + writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR); + writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH); + writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY); + writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE); + writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS); + writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES); + writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS); + + /* RTC_CENTURY and RTC_CONTROL share same register */ + writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY); + writeb(century & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL); + return 0; +} + +static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + unsigned int year, month, day, hour, minute, second, week; + unsigned int century; + + /* give enough time to update RTC in case of continuous read */ + if (pdata->last_jiffies == jiffies) + msleep(1); + pdata->last_jiffies = jiffies; + writeb(RTC_READ, ioaddr + RTC_CONTROL); + second = readb(ioaddr + RTC_SECONDS) & RTC_SECONDS_MASK; + minute = readb(ioaddr + RTC_MINUTES); + hour = readb(ioaddr + RTC_HOURS); + day = readb(ioaddr + RTC_DATE); + week = readb(ioaddr + RTC_DAY) & RTC_DAY_MASK; + month = readb(ioaddr + RTC_MONTH); + year = readb(ioaddr + RTC_YEAR); + century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK; + writeb(0, ioaddr + RTC_CONTROL); + tm->tm_sec = BCD2BIN(second); + tm->tm_min = BCD2BIN(minute); + tm->tm_hour = BCD2BIN(hour); + tm->tm_mday = BCD2BIN(day); + tm->tm_wday = BCD2BIN(week); + tm->tm_mon = BCD2BIN(month) - 1; + /* year is 1900 + tm->tm_year */ + tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900; + + if (rtc_valid_tm(tm) < 0) { + dev_err(dev, "retrieved date/time is not valid.\n"); + rtc_time_to_tm(0, tm); + } + return 0; +} + +static struct rtc_class_ops ds1742_rtc_ops = { + .read_time = ds1742_rtc_read_time, + .set_time = ds1742_rtc_set_time, +}; + +static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf, + loff_t pos, size_t size) +{ + struct platform_device *pdev = + to_platform_device(container_of(kobj, struct device, kobj)); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + ssize_t count; + + for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) + *buf++ = readb(ioaddr + pos++); + return count; +} + +static ssize_t ds1742_nvram_write(struct kobject *kobj, char *buf, + loff_t pos, size_t size) +{ + struct platform_device *pdev = + to_platform_device(container_of(kobj, struct device, kobj)); + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + void __iomem *ioaddr = pdata->ioaddr; + ssize_t count; + + for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--) + writeb(*buf++, ioaddr + pos++); + return count; +} + +static struct bin_attribute ds1742_nvram_attr = { + .attr = { + .name = "nvram", + .mode = S_IRUGO | S_IWUGO, + .owner = THIS_MODULE, + }, + .size = RTC_OFFSET, + .read = ds1742_nvram_read, + .write = ds1742_nvram_write, +}; + +static int __init ds1742_rtc_probe(struct platform_device *pdev) +{ + struct rtc_device *rtc; + struct resource *res; + unsigned int cen, sec; + struct rtc_plat_data *pdata = NULL; + void __iomem *ioaddr = NULL; + int ret = 0; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) { + ret = -EBUSY; + goto out; + } + pdata->baseaddr = res->start; + ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE); + if (!ioaddr) { + ret = -ENOMEM; + goto out; + } + pdata->ioaddr = ioaddr; + + /* turn RTC on if it was not on */ + sec = readb(ioaddr + RTC_SECONDS); + if (sec & RTC_STOP) { + sec &= RTC_SECONDS_MASK; + cen = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK; + writeb(RTC_WRITE, ioaddr + RTC_CONTROL); + writeb(sec, ioaddr + RTC_SECONDS); + writeb(cen & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL); + } + if (readb(ioaddr + RTC_DAY) & RTC_BATT_FLAG) + dev_warn(&pdev->dev, "voltage-low detected.\n"); + + rtc = rtc_device_register(pdev->name, &pdev->dev, + &ds1742_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) { + ret = PTR_ERR(rtc); + goto out; + } + pdata->rtc = rtc; + pdata->last_jiffies = jiffies; + platform_set_drvdata(pdev, pdata); + sysfs_create_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr); + return 0; + out: + if (ioaddr) + iounmap(ioaddr); + if (pdata->baseaddr) + release_mem_region(pdata->baseaddr, RTC_REG_SIZE); + kfree(pdata); + return ret; +} + +static int __devexit ds1742_rtc_remove(struct platform_device *pdev) +{ + struct rtc_plat_data *pdata = platform_get_drvdata(pdev); + + sysfs_remove_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr); + rtc_device_unregister(pdata->rtc); + iounmap(pdata->ioaddr); + release_mem_region(pdata->baseaddr, RTC_REG_SIZE); + kfree(pdata); + return 0; +} + +static struct platform_driver ds1742_rtc_driver = { + .probe = ds1742_rtc_probe, + .remove = __devexit_p(ds1742_rtc_remove), + .driver = { + .name = "ds1742", + .owner = THIS_MODULE, + }, +}; + +static __init int ds1742_init(void) +{ + return platform_driver_register(&ds1742_rtc_driver); +} + +static __exit void ds1742_exit(void) +{ + return platform_driver_unregister(&ds1742_rtc_driver); +} + +module_init(ds1742_init); +module_exit(ds1742_exit); + +MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); +MODULE_DESCRIPTION("Dallas DS1742 RTC driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c new file mode 100644 index 000000000..f324d0a63 --- /dev/null +++ b/drivers/rtc/rtc-isl1208.c @@ -0,0 +1,591 @@ +/* + * Intersil ISL1208 rtc class driver + * + * Copyright 2005,2006 Hebert Valerio Riedel <hvr@gnu.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/bcd.h> +#include <linux/rtc.h> + +#define DRV_NAME "isl1208" +#define DRV_VERSION "0.2" + +/* Register map */ +/* rtc section */ +#define ISL1208_REG_SC 0x00 +#define ISL1208_REG_MN 0x01 +#define ISL1208_REG_HR 0x02 +#define ISL1208_REG_HR_MIL (1<<7) /* 24h/12h mode */ +#define ISL1208_REG_HR_PM (1<<5) /* PM/AM bit in 12h mode */ +#define ISL1208_REG_DT 0x03 +#define ISL1208_REG_MO 0x04 +#define ISL1208_REG_YR 0x05 +#define ISL1208_REG_DW 0x06 +#define ISL1208_RTC_SECTION_LEN 7 + +/* control/status section */ +#define ISL1208_REG_SR 0x07 +#define ISL1208_REG_SR_ARST (1<<7) /* auto reset */ +#define ISL1208_REG_SR_XTOSCB (1<<6) /* crystal oscillator */ +#define ISL1208_REG_SR_WRTC (1<<4) /* write rtc */ +#define ISL1208_REG_SR_ALM (1<<2) /* alarm */ +#define ISL1208_REG_SR_BAT (1<<1) /* battery */ +#define ISL1208_REG_SR_RTCF (1<<0) /* rtc fail */ +#define ISL1208_REG_INT 0x08 +#define ISL1208_REG_09 0x09 /* reserved */ +#define ISL1208_REG_ATR 0x0a +#define ISL1208_REG_DTR 0x0b + +/* alarm section */ +#define ISL1208_REG_SCA 0x0c +#define ISL1208_REG_MNA 0x0d +#define ISL1208_REG_HRA 0x0e +#define ISL1208_REG_DTA 0x0f +#define ISL1208_REG_MOA 0x10 +#define ISL1208_REG_DWA 0x11 +#define ISL1208_ALARM_SECTION_LEN 6 + +/* user section */ +#define ISL1208_REG_USR1 0x12 +#define ISL1208_REG_USR2 0x13 +#define ISL1208_USR_SECTION_LEN 2 + +/* i2c configuration */ +#define ISL1208_I2C_ADDR 0xde + +static unsigned short normal_i2c[] = { + ISL1208_I2C_ADDR>>1, I2C_CLIENT_END +}; +I2C_CLIENT_INSMOD; /* defines addr_data */ + +static int isl1208_attach_adapter(struct i2c_adapter *adapter); +static int isl1208_detach_client(struct i2c_client *client); + +static struct i2c_driver isl1208_driver = { + .driver = { + .name = DRV_NAME, + }, + .id = I2C_DRIVERID_ISL1208, + .attach_adapter = &isl1208_attach_adapter, + .detach_client = &isl1208_detach_client, +}; + +/* block read */ +static int +isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[], + unsigned len) +{ + u8 reg_addr[1] = { reg }; + struct i2c_msg msgs[2] = { + { client->addr, client->flags, sizeof(reg_addr), reg_addr }, + { client->addr, client->flags | I2C_M_RD, len, buf } + }; + int ret; + + BUG_ON(len == 0); + BUG_ON(reg > ISL1208_REG_USR2); + BUG_ON(reg + len > ISL1208_REG_USR2 + 1); + + ret = i2c_transfer(client->adapter, msgs, 2); + if (ret > 0) + ret = 0; + return ret; +} + +/* block write */ +static int +isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[], + unsigned len) +{ + u8 i2c_buf[ISL1208_REG_USR2 + 2]; + struct i2c_msg msgs[1] = { + { client->addr, client->flags, len + 1, i2c_buf } + }; + int ret; + + BUG_ON(len == 0); + BUG_ON(reg > ISL1208_REG_USR2); + BUG_ON(reg + len > ISL1208_REG_USR2 + 1); + + i2c_buf[0] = reg; + memcpy(&i2c_buf[1], &buf[0], len); + + ret = i2c_transfer(client->adapter, msgs, 1); + if (ret > 0) + ret = 0; + return ret; +} + +/* simple check to see wether we have a isl1208 */ +static int isl1208_i2c_validate_client(struct i2c_client *client) +{ + u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, }; + u8 zero_mask[ISL1208_RTC_SECTION_LEN] = { + 0x80, 0x80, 0x40, 0xc0, 0xe0, 0x00, 0xf8 + }; + int i; + int ret; + + ret = isl1208_i2c_read_regs(client, 0, regs, ISL1208_RTC_SECTION_LEN); + if (ret < 0) + return ret; + + for (i = 0; i < ISL1208_RTC_SECTION_LEN; ++i) { + if (regs[i] & zero_mask[i]) /* check if bits are cleared */ + return -ENODEV; + } + + return 0; +} + +static int isl1208_i2c_get_sr(struct i2c_client *client) +{ + return i2c_smbus_read_byte_data(client, ISL1208_REG_SR) == -1 ? -EIO:0; +} + +static int isl1208_i2c_get_atr(struct i2c_client *client) +{ + int atr = i2c_smbus_read_byte_data(client, ISL1208_REG_ATR); + + if (atr < 0) + return -EIO; + + /* The 6bit value in the ATR register controls the load + * capacitance C_load * in steps of 0.25pF + * + * bit (1<<5) of the ATR register is inverted + * + * C_load(ATR=0x20) = 4.50pF + * C_load(ATR=0x00) = 12.50pF + * C_load(ATR=0x1f) = 20.25pF + * + */ + + atr &= 0x3f; /* mask out lsb */ + atr ^= 1<<5; /* invert 6th bit */ + atr += 2*9; /* add offset of 4.5pF; unit[atr] = 0.25pF */ + + return atr; +} + +static int isl1208_i2c_get_dtr(struct i2c_client *client) +{ + int dtr = i2c_smbus_read_byte_data(client, ISL1208_REG_DTR); + + if (dtr < 0) + return -EIO; + + /* dtr encodes adjustments of {-60,-40,-20,0,20,40,60} ppm */ + dtr = ((dtr & 0x3) * 20) * (dtr & (1<<2) ? -1 : 1); + + return dtr; +} + +static int isl1208_i2c_get_usr(struct i2c_client *client) +{ + u8 buf[ISL1208_USR_SECTION_LEN] = { 0, }; + int ret; + + ret = isl1208_i2c_read_regs (client, ISL1208_REG_USR1, buf, + ISL1208_USR_SECTION_LEN); + if (ret < 0) + return ret; + + return (buf[1] << 8) | buf[0]; +} + +static int isl1208_i2c_set_usr(struct i2c_client *client, u16 usr) +{ + u8 buf[ISL1208_USR_SECTION_LEN]; + + buf[0] = usr & 0xff; + buf[1] = (usr >> 8) & 0xff; + + return isl1208_i2c_set_regs (client, ISL1208_REG_USR1, buf, + ISL1208_USR_SECTION_LEN); +} + +static int isl1208_rtc_proc(struct device *dev, struct seq_file *seq) +{ + struct i2c_client *const client = to_i2c_client(dev); + int sr, dtr, atr, usr; + + sr = isl1208_i2c_get_sr(client); + if (sr < 0) { + dev_err(&client->dev, "%s: reading SR failed\n", __func__); + return sr; + } + + seq_printf(seq, "status_reg\t:%s%s%s%s%s%s (0x%.2x)\n", + (sr & ISL1208_REG_SR_RTCF) ? " RTCF" : "", + (sr & ISL1208_REG_SR_BAT) ? " BAT" : "", + (sr & ISL1208_REG_SR_ALM) ? " ALM" : "", + (sr & ISL1208_REG_SR_WRTC) ? " WRTC" : "", + (sr & ISL1208_REG_SR_XTOSCB) ? " XTOSCB" : "", + (sr & ISL1208_REG_SR_ARST) ? " ARST" : "", + sr); + + seq_printf(seq, "batt_status\t: %s\n", + (sr & ISL1208_REG_SR_RTCF) ? "bad" : "okay"); + + dtr = isl1208_i2c_get_dtr(client); + if (dtr >= 0 -1) + seq_printf(seq, "digital_trim\t: %d ppm\n", dtr); + + atr = isl1208_i2c_get_atr(client); + if (atr >= 0) + seq_printf(seq, "analog_trim\t: %d.%.2d pF\n", + atr>>2, (atr&0x3)*25); + + usr = isl1208_i2c_get_usr(client); + if (usr >= 0) + seq_printf(seq, "user_data\t: 0x%.4x\n", usr); + + return 0; +} + + +static int isl1208_i2c_read_time(struct i2c_client *client, + struct rtc_time *tm) +{ + int sr; + u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, }; + + sr = isl1208_i2c_get_sr(client); + if (sr < 0) { + dev_err(&client->dev, "%s: reading SR failed\n", __func__); + return -EIO; + } + + sr = isl1208_i2c_read_regs(client, 0, regs, ISL1208_RTC_SECTION_LEN); + if (sr < 0) { + dev_err(&client->dev, "%s: reading RTC section failed\n", + __func__); + return sr; + } + + tm->tm_sec = BCD2BIN(regs[ISL1208_REG_SC]); + tm->tm_min = BCD2BIN(regs[ISL1208_REG_MN]); + { /* HR field has a more complex interpretation */ + const u8 _hr = regs[ISL1208_REG_HR]; + if (_hr & ISL1208_REG_HR_MIL) /* 24h format */ + tm->tm_hour = BCD2BIN(_hr & 0x3f); + else { // 12h format + tm->tm_hour = BCD2BIN(_hr & 0x1f); + if (_hr & ISL1208_REG_HR_PM) /* PM flag set */ + tm->tm_hour += 12; + } + } + + tm->tm_mday = BCD2BIN(regs[ISL1208_REG_DT]); + tm->tm_mon = BCD2BIN(regs[ISL1208_REG_MO]) - 1; /* rtc starts at 1 */ + tm->tm_year = BCD2BIN(regs[ISL1208_REG_YR]) + 100; + tm->tm_wday = BCD2BIN(regs[ISL1208_REG_DW]); + + return 0; +} + +static int isl1208_i2c_read_alarm(struct i2c_client *client, + struct rtc_wkalrm *alarm) +{ + struct rtc_time *const tm = &alarm->time; + u8 regs[ISL1208_ALARM_SECTION_LEN] = { 0, }; + int sr; + + sr = isl1208_i2c_get_sr(client); + if (sr < 0) { + dev_err(&client->dev, "%s: reading SR failed\n", __func__); + return sr; + } + + sr = isl1208_i2c_read_regs(client, ISL1208_REG_SCA, regs, + ISL1208_ALARM_SECTION_LEN); + if (sr < 0) { + dev_err(&client->dev, "%s: reading alarm section failed\n", + __func__); + return sr; + } + + /* MSB of each alarm register is an enable bit */ + tm->tm_sec = BCD2BIN(regs[ISL1208_REG_SCA-ISL1208_REG_SCA] & 0x7f); + tm->tm_min = BCD2BIN(regs[ISL1208_REG_MNA-ISL1208_REG_SCA] & 0x7f); + tm->tm_hour = BCD2BIN(regs[ISL1208_REG_HRA-ISL1208_REG_SCA] & 0x3f); + tm->tm_mday = BCD2BIN(regs[ISL1208_REG_DTA-ISL1208_REG_SCA] & 0x3f); + tm->tm_mon = BCD2BIN(regs[ISL1208_REG_MOA-ISL1208_REG_SCA] & 0x1f)-1; + tm->tm_wday = BCD2BIN(regs[ISL1208_REG_DWA-ISL1208_REG_SCA] & 0x03); + + return 0; +} + +static int isl1208_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + return isl1208_i2c_read_time(to_i2c_client(dev), tm); +} + +static int isl1208_i2c_set_time(struct i2c_client *client, + struct rtc_time const *tm) +{ + int sr; + u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, }; + + regs[ISL1208_REG_SC] = BIN2BCD(tm->tm_sec); + regs[ISL1208_REG_MN] = BIN2BCD(tm->tm_min); + regs[ISL1208_REG_HR] = BIN2BCD(tm->tm_hour) | ISL1208_REG_HR_MIL; + + regs[ISL1208_REG_DT] = BIN2BCD(tm->tm_mday); + regs[ISL1208_REG_MO] = BIN2BCD(tm->tm_mon + 1); + regs[ISL1208_REG_YR] = BIN2BCD(tm->tm_year - 100); + + regs[ISL1208_REG_DW] = BIN2BCD(tm->tm_wday & 7); + + sr = isl1208_i2c_get_sr(client); + if (sr < 0) { + dev_err(&client->dev, "%s: reading SR failed\n", __func__); + return sr; + } + + /* set WRTC */ + sr = i2c_smbus_write_byte_data (client, ISL1208_REG_SR, + sr | ISL1208_REG_SR_WRTC); + if (sr < 0) { + dev_err(&client->dev, "%s: writing SR failed\n", __func__); + return sr; + } + + /* write RTC registers */ + sr = isl1208_i2c_set_regs(client, 0, regs, ISL1208_RTC_SECTION_LEN); + if (sr < 0) { + dev_err(&client->dev, "%s: writing RTC section failed\n", + __func__); + return sr; + } + + /* clear WRTC again */ + sr = i2c_smbus_write_byte_data (client, ISL1208_REG_SR, + sr & ~ISL1208_REG_SR_WRTC); + if (sr < 0) { + dev_err(&client->dev, "%s: writing SR failed\n", __func__); + return sr; + } + + return 0; +} + + +static int isl1208_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + return isl1208_i2c_set_time(to_i2c_client(dev), tm); +} + +static int isl1208_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + return isl1208_i2c_read_alarm(to_i2c_client(dev), alarm); +} + +static struct rtc_class_ops isl1208_rtc_ops = { + .proc = isl1208_rtc_proc, + .read_time = isl1208_rtc_read_time, + .set_time = isl1208_rtc_set_time, + .read_alarm = isl1208_rtc_read_alarm, + //.set_alarm = isl1208_rtc_set_alarm, +}; + +/* sysfs interface */ + +static ssize_t isl1208_sysfs_show_atrim(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int atr; + + atr = isl1208_i2c_get_atr(to_i2c_client(dev)); + if (atr < 0) + return atr; + + return sprintf(buf, "%d.%.2d pF\n", atr>>2, (atr&0x3)*25); +} +static DEVICE_ATTR(atrim, S_IRUGO, isl1208_sysfs_show_atrim, NULL); + +static ssize_t isl1208_sysfs_show_dtrim(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int dtr; + + dtr = isl1208_i2c_get_dtr(to_i2c_client(dev)); + if (dtr < 0) + return dtr; + + return sprintf(buf, "%d ppm\n", dtr); +} +static DEVICE_ATTR(dtrim, S_IRUGO, isl1208_sysfs_show_dtrim, NULL); + +static ssize_t isl1208_sysfs_show_usr(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int usr; + + usr = isl1208_i2c_get_usr(to_i2c_client(dev)); + if (usr < 0) + return usr; + + return sprintf(buf, "0x%.4x\n", usr); +} + +static ssize_t isl1208_sysfs_store_usr(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int usr = -1; + + if (buf[0] == '0' && (buf[1] == 'x' || buf[1] == 'X')) { + if (sscanf(buf, "%x", &usr) != 1) + return -EINVAL; + } else { + if (sscanf(buf, "%d", &usr) != 1) + return -EINVAL; + } + + if (usr < 0 || usr > 0xffff) + return -EINVAL; + + return isl1208_i2c_set_usr(to_i2c_client(dev), usr) ? -EIO : count; +} +static DEVICE_ATTR(usr, S_IRUGO | S_IWUSR, isl1208_sysfs_show_usr, + isl1208_sysfs_store_usr); + +static int +isl1208_probe(struct i2c_adapter *adapter, int addr, int kind) +{ + int rc = 0; + struct i2c_client *new_client = NULL; + struct rtc_device *rtc = NULL; + + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { + rc = -ENODEV; + goto failout; + } + + new_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (new_client == NULL) { + rc = -ENOMEM; + goto failout; + } + + new_client->addr = addr; + new_client->adapter = adapter; + new_client->driver = &isl1208_driver; + new_client->flags = 0; + strcpy(new_client->name, DRV_NAME); + + if (kind < 0) { + rc = isl1208_i2c_validate_client(new_client); + if (rc < 0) + goto failout; + } + + rc = i2c_attach_client(new_client); + if (rc < 0) + goto failout; + + dev_info(&new_client->dev, + "chip found, driver version " DRV_VERSION "\n"); + + rtc = rtc_device_register(isl1208_driver.driver.name, + &new_client->dev, + &isl1208_rtc_ops, THIS_MODULE); + + if (IS_ERR(rtc)) { + rc = PTR_ERR(rtc); + goto failout_detach; + } + + i2c_set_clientdata(new_client, rtc); + + rc = isl1208_i2c_get_sr(new_client); + if (rc < 0) { + dev_err(&new_client->dev, "reading status failed\n"); + goto failout_unregister; + } + + if (rc & ISL1208_REG_SR_RTCF) + dev_warn(&new_client->dev, "rtc power failure detected, " + "please set clock.\n"); + + rc = device_create_file(&new_client->dev, &dev_attr_atrim); + if (rc < 0) + goto failout_unregister; + rc = device_create_file(&new_client->dev, &dev_attr_dtrim); + if (rc < 0) + goto failout_atrim; + rc = device_create_file(&new_client->dev, &dev_attr_usr); + if (rc < 0) + goto failout_dtrim; + + return 0; + + failout_dtrim: + device_remove_file(&new_client->dev, &dev_attr_dtrim); + failout_atrim: + device_remove_file(&new_client->dev, &dev_attr_atrim); + failout_unregister: + rtc_device_unregister(rtc); + failout_detach: + i2c_detach_client(new_client); + failout: + kfree(new_client); + return rc; +} + +static int +isl1208_attach_adapter (struct i2c_adapter *adapter) +{ + return i2c_probe(adapter, &addr_data, isl1208_probe); +} + +static int +isl1208_detach_client(struct i2c_client *client) +{ + int rc; + struct rtc_device *const rtc = i2c_get_clientdata(client); + + if (rtc) + rtc_device_unregister(rtc); /* do we need to kfree? */ + + rc = i2c_detach_client(client); + if (rc) + return rc; + + kfree(client); + + return 0; +} + +/* module management */ + +static int __init isl1208_init(void) +{ + return i2c_add_driver(&isl1208_driver); +} + +static void __exit isl1208_exit(void) +{ + i2c_del_driver(&isl1208_driver); +} + +MODULE_AUTHOR("Herbert Valerio Riedel <hvr@gnu.org>"); +MODULE_DESCRIPTION("Intersil ISL1208 RTC driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); + +module_init(isl1208_init); +module_exit(isl1208_exit); diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c new file mode 100644 index 000000000..480ce6cdc --- /dev/null +++ b/drivers/rtc/rtc-max6902.c @@ -0,0 +1,285 @@ +/* drivers/char/max6902.c + * + * Copyright (C) 2006 8D Technologies inc. + * Copyright (C) 2004 Compulab Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Driver for MAX6902 spi RTC + * + * Changelog: + * + * 24-May-2006: Raphael Assenat <raph@8d.com> + * - Major rework + * Converted to rtc_device and uses the SPI layer. + * + * ??-???-2005: Someone at Compulab + * - Initial driver creation. + */ + +#include <linux/module.h> +#include <linux/version.h> + +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/init.h> +#include <linux/rtc.h> +#include <linux/spi/spi.h> +#include <linux/bcd.h> +#include <linux/delay.h> + +#define MAX6902_REG_SECONDS 0x01 +#define MAX6902_REG_MINUTES 0x03 +#define MAX6902_REG_HOURS 0x05 +#define MAX6902_REG_DATE 0x07 +#define MAX6902_REG_MONTH 0x09 +#define MAX6902_REG_DAY 0x0B +#define MAX6902_REG_YEAR 0x0D +#define MAX6902_REG_CONTROL 0x0F +#define MAX6902_REG_CENTURY 0x13 + +#undef MAX6902_DEBUG + +struct max6902 { + struct rtc_device *rtc; + u8 buf[9]; /* Burst read cmd + 8 registers */ + u8 tx_buf[2]; + u8 rx_buf[2]; +}; + +static void max6902_set_reg(struct device *dev, unsigned char address, + unsigned char data) +{ + struct spi_device *spi = to_spi_device(dev); + unsigned char buf[2]; + + /* MSB must be '0' to write */ + buf[0] = address & 0x7f; + buf[1] = data; + + spi_write(spi, buf, 2); +} + +static int max6902_get_reg(struct device *dev, unsigned char address, + unsigned char *data) +{ + struct spi_device *spi = to_spi_device(dev); + struct max6902 *chip = dev_get_drvdata(dev); + struct spi_message message; + struct spi_transfer xfer; + int status; + + if (!data) + return -EINVAL; + + /* Build our spi message */ + spi_message_init(&message); + memset(&xfer, 0, sizeof(xfer)); + xfer.len = 2; + /* Can tx_buf and rx_buf be equal? The doc in spi.h is not sure... */ + xfer.tx_buf = chip->tx_buf; + xfer.rx_buf = chip->rx_buf; + + /* Set MSB to indicate read */ + chip->tx_buf[0] = address | 0x80; + + spi_message_add_tail(&xfer, &message); + + /* do the i/o */ + status = spi_sync(spi, &message); + if (status == 0) + status = message.status; + else + return status; + + *data = chip->rx_buf[1]; + + return status; +} + +static int max6902_get_datetime(struct device *dev, struct rtc_time *dt) +{ + unsigned char tmp; + int century; + int err; + struct spi_device *spi = to_spi_device(dev); + struct max6902 *chip = dev_get_drvdata(dev); + struct spi_message message; + struct spi_transfer xfer; + int status; + + err = max6902_get_reg(dev, MAX6902_REG_CENTURY, &tmp); + if (err) + return err; + + /* build the message */ + spi_message_init(&message); + memset(&xfer, 0, sizeof(xfer)); + xfer.len = 1 + 7; /* Burst read command + 7 registers */ + xfer.tx_buf = chip->buf; + xfer.rx_buf = chip->buf; + chip->buf[0] = 0xbf; /* Burst read */ + spi_message_add_tail(&xfer, &message); + + /* do the i/o */ + status = spi_sync(spi, &message); + if (status == 0) + status = message.status; + else + return status; + + /* The chip sends data in this order: + * Seconds, Minutes, Hours, Date, Month, Day, Year */ + dt->tm_sec = BCD2BIN(chip->buf[1]); + dt->tm_min = BCD2BIN(chip->buf[2]); + dt->tm_hour = BCD2BIN(chip->buf[3]); + dt->tm_mday = BCD2BIN(chip->buf[4]); + dt->tm_mon = BCD2BIN(chip->buf[5]) - 1; + dt->tm_wday = BCD2BIN(chip->buf[6]); + dt->tm_year = BCD2BIN(chip->buf[7]); + + century = BCD2BIN(tmp) * 100; + + dt->tm_year += century; + dt->tm_year -= 1900; + +#ifdef MAX6902_DEBUG + printk("\n%s : Read RTC values\n",__FUNCTION__); + printk("tm_hour: %i\n",dt->tm_hour); + printk("tm_min : %i\n",dt->tm_min); + printk("tm_sec : %i\n",dt->tm_sec); + printk("tm_year: %i\n",dt->tm_year); + printk("tm_mon : %i\n",dt->tm_mon); + printk("tm_mday: %i\n",dt->tm_mday); + printk("tm_wday: %i\n",dt->tm_wday); +#endif + + return 0; +} + +static int max6902_set_datetime(struct device *dev, struct rtc_time *dt) +{ + dt->tm_year = dt->tm_year+1900; + +#ifdef MAX6902_DEBUG + printk("\n%s : Setting RTC values\n",__FUNCTION__); + printk("tm_sec : %i\n",dt->tm_sec); + printk("tm_min : %i\n",dt->tm_min); + printk("tm_hour: %i\n",dt->tm_hour); + printk("tm_mday: %i\n",dt->tm_mday); + printk("tm_wday: %i\n",dt->tm_wday); + printk("tm_year: %i\n",dt->tm_year); +#endif + + /* Remove write protection */ + max6902_set_reg(dev, 0xF, 0); + + max6902_set_reg(dev, 0x01, BIN2BCD(dt->tm_sec)); + max6902_set_reg(dev, 0x03, BIN2BCD(dt->tm_min)); + max6902_set_reg(dev, 0x05, BIN2BCD(dt->tm_hour)); + + max6902_set_reg(dev, 0x07, BIN2BCD(dt->tm_mday)); + max6902_set_reg(dev, 0x09, BIN2BCD(dt->tm_mon+1)); + max6902_set_reg(dev, 0x0B, BIN2BCD(dt->tm_wday)); + max6902_set_reg(dev, 0x0D, BIN2BCD(dt->tm_year%100)); + max6902_set_reg(dev, 0x13, BIN2BCD(dt->tm_year/100)); + + /* Compulab used a delay here. However, the datasheet + * does not mention a delay being required anywhere... */ + /* delay(2000); */ + + /* Write protect */ + max6902_set_reg(dev, 0xF, 0x80); + + return 0; +} + +static int max6902_read_time(struct device *dev, struct rtc_time *tm) +{ + return max6902_get_datetime(dev, tm); +} + +static int max6902_set_time(struct device *dev, struct rtc_time *tm) +{ + return max6902_set_datetime(dev, tm); +} + +static struct rtc_class_ops max6902_rtc_ops = { + .read_time = max6902_read_time, + .set_time = max6902_set_time, +}; + +static int __devinit max6902_probe(struct spi_device *spi) +{ + struct rtc_device *rtc; + unsigned char tmp; + struct max6902 *chip; + int res; + + rtc = rtc_device_register("max6902", + &spi->dev, &max6902_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + + spi->mode = SPI_MODE_3; + spi->bits_per_word = 8; + spi_setup(spi); + + chip = kzalloc(sizeof *chip, GFP_KERNEL); + if (!chip) { + rtc_device_unregister(rtc); + return -ENOMEM; + } + chip->rtc = rtc; + dev_set_drvdata(&spi->dev, chip); + + res = max6902_get_reg(&spi->dev, MAX6902_REG_SECONDS, &tmp); + if (res) { + rtc_device_unregister(rtc); + return res; + } + + return 0; +} + +static int __devexit max6902_remove(struct spi_device *spi) +{ + struct max6902 *chip = platform_get_drvdata(spi); + struct rtc_device *rtc = chip->rtc; + + if (rtc) + rtc_device_unregister(rtc); + + kfree(chip); + + return 0; +} + +static struct spi_driver max6902_driver = { + .driver = { + .name = "max6902", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = max6902_probe, + .remove = __devexit_p(max6902_remove), +}; + +static __init int max6902_init(void) +{ + printk("max6902 spi driver\n"); + return spi_register_driver(&max6902_driver); +} +module_init(max6902_init); + +static __exit void max6902_exit(void) +{ + spi_unregister_driver(&max6902_driver); +} +module_exit(max6902_exit); + +MODULE_DESCRIPTION ("max6902 spi RTC driver"); +MODULE_AUTHOR ("Raphael Assenat"); +MODULE_LICENSE ("GPL"); diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c new file mode 100644 index 000000000..b235a30cb --- /dev/null +++ b/drivers/rtc/rtc-pcf8583.c @@ -0,0 +1,394 @@ +/* + * drivers/rtc/rtc-pcf8583.c + * + * Copyright (C) 2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Driver for PCF8583 RTC & RAM chip + * + * Converted to the generic RTC susbsystem by G. Liakhovetski (2006) + */ +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/mc146818rtc.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/bcd.h> + +struct rtc_mem { + unsigned int loc; + unsigned int nr; + unsigned char *data; +}; + +struct pcf8583 { + struct i2c_client client; + struct rtc_device *rtc; + unsigned char ctrl; +}; + +#define CTRL_STOP 0x80 +#define CTRL_HOLD 0x40 +#define CTRL_32KHZ 0x00 +#define CTRL_MASK 0x08 +#define CTRL_ALARMEN 0x04 +#define CTRL_ALARM 0x02 +#define CTRL_TIMER 0x01 + +static unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Module parameters */ +I2C_CLIENT_INSMOD; + +static struct i2c_driver pcf8583_driver; + +#define get_ctrl(x) ((struct pcf8583 *)i2c_get_clientdata(x))->ctrl +#define set_ctrl(x, v) get_ctrl(x) = v + +#define CMOS_YEAR (64 + 128) +#define CMOS_CHECKSUM (63) + +static int pcf8583_get_datetime(struct i2c_client *client, struct rtc_time *dt) +{ + unsigned char buf[8], addr[1] = { 1 }; + struct i2c_msg msgs[2] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = addr, + }, { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 6, + .buf = buf, + } + }; + int ret; + + memset(buf, 0, sizeof(buf)); + + ret = i2c_transfer(client->adapter, msgs, 2); + if (ret == 2) { + dt->tm_year = buf[4] >> 6; + dt->tm_wday = buf[5] >> 5; + + buf[4] &= 0x3f; + buf[5] &= 0x1f; + + dt->tm_sec = BCD_TO_BIN(buf[1]); + dt->tm_min = BCD_TO_BIN(buf[2]); + dt->tm_hour = BCD_TO_BIN(buf[3]); + dt->tm_mday = BCD_TO_BIN(buf[4]); + dt->tm_mon = BCD_TO_BIN(buf[5]); + } + + return ret == 2 ? 0 : -EIO; +} + +static int pcf8583_set_datetime(struct i2c_client *client, struct rtc_time *dt, int datetoo) +{ + unsigned char buf[8]; + int ret, len = 6; + + buf[0] = 0; + buf[1] = get_ctrl(client) | 0x80; + buf[2] = 0; + buf[3] = BIN_TO_BCD(dt->tm_sec); + buf[4] = BIN_TO_BCD(dt->tm_min); + buf[5] = BIN_TO_BCD(dt->tm_hour); + + if (datetoo) { + len = 8; + buf[6] = BIN_TO_BCD(dt->tm_mday) | (dt->tm_year << 6); + buf[7] = BIN_TO_BCD(dt->tm_mon) | (dt->tm_wday << 5); + } + + ret = i2c_master_send(client, (char *)buf, len); + if (ret != len) + return -EIO; + + buf[1] = get_ctrl(client); + ret = i2c_master_send(client, (char *)buf, 2); + + return ret == 2 ? 0 : -EIO; +} + +static int pcf8583_get_ctrl(struct i2c_client *client, unsigned char *ctrl) +{ + *ctrl = get_ctrl(client); + return 0; +} + +static int pcf8583_set_ctrl(struct i2c_client *client, unsigned char *ctrl) +{ + unsigned char buf[2]; + + buf[0] = 0; + buf[1] = *ctrl; + set_ctrl(client, *ctrl); + + return i2c_master_send(client, (char *)buf, 2); +} + +static int pcf8583_read_mem(struct i2c_client *client, struct rtc_mem *mem) +{ + unsigned char addr[1]; + struct i2c_msg msgs[2] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = addr, + }, { + .addr = client->addr, + .flags = I2C_M_RD, + .len = mem->nr, + .buf = mem->data, + } + }; + + if (mem->loc < 8) + return -EINVAL; + + addr[0] = mem->loc; + + return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO; +} + +static int pcf8583_write_mem(struct i2c_client *client, struct rtc_mem *mem) +{ + unsigned char addr[1]; + struct i2c_msg msgs[2] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = addr, + }, { + .addr = client->addr, + .flags = I2C_M_NOSTART, + .len = mem->nr, + .buf = mem->data, + } + }; + + if (mem->loc < 8) + return -EINVAL; + + addr[0] = mem->loc; + + return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO; +} + +static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct i2c_client *client = to_i2c_client(dev); + unsigned char ctrl, year[2]; + struct rtc_mem mem = { CMOS_YEAR, sizeof(year), year }; + int real_year, year_offset, err; + + /* + * Ensure that the RTC is running. + */ + pcf8583_get_ctrl(client, &ctrl); + if (ctrl & (CTRL_STOP | CTRL_HOLD)) { + unsigned char new_ctrl = ctrl & ~(CTRL_STOP | CTRL_HOLD); + + printk(KERN_WARNING "RTC: resetting control %02x -> %02x\n", + ctrl, new_ctrl); + + if ((err = pcf8583_set_ctrl(client, &new_ctrl)) < 0) + return err; + } + + if (pcf8583_get_datetime(client, tm) || + pcf8583_read_mem(client, &mem)) + return -EIO; + + real_year = year[0]; + + /* + * The RTC year holds the LSB two bits of the current + * year, which should reflect the LSB two bits of the + * CMOS copy of the year. Any difference indicates + * that we have to correct the CMOS version. + */ + year_offset = tm->tm_year - (real_year & 3); + if (year_offset < 0) + /* + * RTC year wrapped. Adjust it appropriately. + */ + year_offset += 4; + + tm->tm_year = real_year + year_offset + year[1] * 100; + + return 0; +} + +static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct i2c_client *client = to_i2c_client(dev); + unsigned char year[2], chk; + struct rtc_mem cmos_year = { CMOS_YEAR, sizeof(year), year }; + struct rtc_mem cmos_check = { CMOS_CHECKSUM, 1, &chk }; + int ret; + + /* + * The RTC's own 2-bit year must reflect the least + * significant two bits of the CMOS year. + */ + + ret = pcf8583_set_datetime(client, tm, 1); + if (ret) + return ret; + + ret = pcf8583_read_mem(client, &cmos_check); + if (ret) + return ret; + + ret = pcf8583_read_mem(client, &cmos_year); + if (ret) + return ret; + + chk -= year[1] + year[0]; + + year[1] = tm->tm_year / 100; + year[0] = tm->tm_year % 100; + + chk += year[1] + year[0]; + + ret = pcf8583_write_mem(client, &cmos_year); + + if (ret) + return ret; + + ret = pcf8583_write_mem(client, &cmos_check); + + return ret; +} + +static struct rtc_class_ops pcf8583_rtc_ops = { + .read_time = pcf8583_rtc_read_time, + .set_time = pcf8583_rtc_set_time, +}; + +static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind); + +static int pcf8583_attach(struct i2c_adapter *adap) +{ + return i2c_probe(adap, &addr_data, pcf8583_probe); +} + +static int pcf8583_detach(struct i2c_client *client) +{ + int err; + struct pcf8583 *pcf = i2c_get_clientdata(client); + struct rtc_device *rtc = pcf->rtc; + + if (rtc) + rtc_device_unregister(rtc); + + if ((err = i2c_detach_client(client))) + return err; + + kfree(pcf); + return 0; +} + +static struct i2c_driver pcf8583_driver = { + .driver = { + .name = "pcf8583", + }, + .id = I2C_DRIVERID_PCF8583, + .attach_adapter = pcf8583_attach, + .detach_client = pcf8583_detach, +}; + +static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind) +{ + struct pcf8583 *pcf; + struct i2c_client *client; + struct rtc_device *rtc; + unsigned char buf[1], ad[1] = { 0 }; + int err; + struct i2c_msg msgs[2] = { + { + .addr = addr, + .flags = 0, + .len = 1, + .buf = ad, + }, { + .addr = addr, + .flags = I2C_M_RD, + .len = 1, + .buf = buf, + } + }; + + pcf = kzalloc(sizeof(*pcf), GFP_KERNEL); + if (!pcf) + return -ENOMEM; + + client = &pcf->client; + + client->addr = addr; + client->adapter = adap; + client->driver = &pcf8583_driver; + + strlcpy(client->name, pcf8583_driver.driver.name, I2C_NAME_SIZE); + + if (i2c_transfer(client->adapter, msgs, 2) != 2) { + err = -EIO; + goto exit_kfree; + } + + err = i2c_attach_client(client); + + if (err) + goto exit_kfree; + + rtc = rtc_device_register(pcf8583_driver.driver.name, &client->dev, + &pcf8583_rtc_ops, THIS_MODULE); + + if (IS_ERR(rtc)) { + err = PTR_ERR(rtc); + goto exit_detach; + } + + pcf->rtc = rtc; + i2c_set_clientdata(client, pcf); + set_ctrl(client, buf[0]); + + return 0; + +exit_detach: + i2c_detach_client(client); + +exit_kfree: + kfree(pcf); + + return err; +} + +static __init int pcf8583_init(void) +{ + return i2c_add_driver(&pcf8583_driver); +} + +static __exit void pcf8583_exit(void) +{ + i2c_del_driver(&pcf8583_driver); +} + +module_init(pcf8583_init); +module_exit(pcf8583_exit); + +MODULE_AUTHOR("Russell King"); +MODULE_DESCRIPTION("PCF8583 I2C RTC driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c new file mode 100644 index 000000000..d6d1c5726 --- /dev/null +++ b/drivers/rtc/rtc-pl031.c @@ -0,0 +1,233 @@ +/* + * drivers/rtc/rtc-pl031.c + * + * Real Time Clock interface for ARM AMBA PrimeCell 031 RTC + * + * Author: Deepak Saxena <dsaxena@plexity.net> + * + * Copyright 2006 (c) MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/rtc.h> +#include <linux/init.h> +#include <linux/fs.h> +#include <linux/interrupt.h> +#include <linux/string.h> +#include <linux/pm.h> + +#include <linux/amba/bus.h> + +#include <asm/io.h> +#include <asm/bitops.h> +#include <asm/hardware.h> +#include <asm/irq.h> +#include <asm/rtc.h> + +/* + * Register definitions + */ +#define RTC_DR 0x00 /* Data read register */ +#define RTC_MR 0x04 /* Match register */ +#define RTC_LR 0x08 /* Data load register */ +#define RTC_CR 0x0c /* Control register */ +#define RTC_IMSC 0x10 /* Interrupt mask and set register */ +#define RTC_RIS 0x14 /* Raw interrupt status register */ +#define RTC_MIS 0x18 /* Masked interrupt status register */ +#define RTC_ICR 0x1c /* Interrupt clear register */ + +struct pl031_local { + struct rtc_device *rtc; + void __iomem *base; +}; + +static irqreturn_t pl031_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct rtc_device *rtc = dev_id; + + rtc_update_irq(&rtc->class_dev, 1, RTC_AF); + + return IRQ_HANDLED; +} + +static int pl031_open(struct device *dev) +{ + /* + * We request IRQ in pl031_probe, so nothing to do here... + */ + return 0; +} + +static void pl031_release(struct device *dev) +{ +} + +static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) +{ + struct pl031_local *ldata = dev_get_drvdata(dev); + + switch (cmd) { + case RTC_AIE_OFF: + __raw_writel(1, ldata->base + RTC_MIS); + return 0; + case RTC_AIE_ON: + __raw_writel(0, ldata->base + RTC_MIS); + return 0; + } + + return -ENOIOCTLCMD; +} + +static int pl031_read_time(struct device *dev, struct rtc_time *tm) +{ + struct pl031_local *ldata = dev_get_drvdata(dev); + + rtc_time_to_tm(__raw_readl(ldata->base + RTC_DR), tm); + + return 0; +} + +static int pl031_set_time(struct device *dev, struct rtc_time *tm) +{ + unsigned long time; + struct pl031_local *ldata = dev_get_drvdata(dev); + + rtc_tm_to_time(tm, &time); + __raw_writel(time, ldata->base + RTC_LR); + + return 0; +} + +static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct pl031_local *ldata = dev_get_drvdata(dev); + + rtc_time_to_tm(__raw_readl(ldata->base + RTC_MR), &alarm->time); + alarm->pending = __raw_readl(ldata->base + RTC_RIS); + alarm->enabled = __raw_readl(ldata->base + RTC_IMSC); + + return 0; +} + +static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct pl031_local *ldata = dev_get_drvdata(dev); + unsigned long time; + + rtc_tm_to_time(&alarm->time, &time); + + __raw_writel(time, ldata->base + RTC_MR); + __raw_writel(!alarm->enabled, ldata->base + RTC_MIS); + + return 0; +} + +static struct rtc_class_ops pl031_ops = { + .open = pl031_open, + .release = pl031_release, + .ioctl = pl031_ioctl, + .read_time = pl031_read_time, + .set_time = pl031_set_time, + .read_alarm = pl031_read_alarm, + .set_alarm = pl031_set_alarm, +}; + +static int pl031_remove(struct amba_device *adev) +{ + struct pl031_local *ldata = dev_get_drvdata(&adev->dev); + + if (ldata) { + dev_set_drvdata(&adev->dev, NULL); + free_irq(adev->irq[0], ldata->rtc); + rtc_device_unregister(ldata->rtc); + iounmap(ldata->base); + kfree(ldata); + } + + return 0; +} + +static int pl031_probe(struct amba_device *adev, void *id) +{ + int ret; + struct pl031_local *ldata; + + + ldata = kmalloc(sizeof(struct pl031_local), GFP_KERNEL); + if (!ldata) { + ret = -ENOMEM; + goto out; + } + dev_set_drvdata(&adev->dev, ldata); + + ldata->base = ioremap(adev->res.start, + adev->res.end - adev->res.start + 1); + if (!ldata->base) { + ret = -ENOMEM; + goto out_no_remap; + } + + if (request_irq(adev->irq[0], pl031_interrupt, IRQF_DISABLED, + "rtc-pl031", ldata->rtc)) { + ret = -EIO; + goto out_no_irq; + } + + ldata->rtc = rtc_device_register("pl031", &adev->dev, &pl031_ops, + THIS_MODULE); + if (IS_ERR(ldata->rtc)) { + ret = PTR_ERR(ldata->rtc); + goto out_no_rtc; + } + + return 0; + +out_no_rtc: + free_irq(adev->irq[0], ldata->rtc); +out_no_irq: + iounmap(ldata->base); +out_no_remap: + dev_set_drvdata(&adev->dev, NULL); + kfree(ldata); +out: + return ret; +} + +static struct amba_id pl031_ids[] __initdata = { + { + .id = 0x00041031, + .mask = 0x000fffff, }, + {0, 0}, +}; + +static struct amba_driver pl031_driver = { + .drv = { + .name = "rtc-pl031", + }, + .id_table = pl031_ids, + .probe = pl031_probe, + .remove = pl031_remove, +}; + +static int __init pl031_init(void) +{ + return amba_driver_register(&pl031_driver); +} + +static void __exit pl031_exit(void) +{ + amba_driver_unregister(&pl031_driver); +} + +module_init(pl031_init); +module_exit(pl031_exit); + +MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net"); +MODULE_DESCRIPTION("ARM AMBA PL031 RTC Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c new file mode 100644 index 000000000..0964d1dba --- /dev/null +++ b/drivers/rtc/rtc-rs5c348.c @@ -0,0 +1,246 @@ +/* + * A SPI driver for the Ricoh RS5C348 RTC + * + * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * The board specific init code should provide characteristics of this + * device: + * Mode 1 (High-Active, Shift-Then-Sample), High Avtive CS + */ + +#include <linux/bcd.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/rtc.h> +#include <linux/workqueue.h> +#include <linux/spi/spi.h> + +#define DRV_VERSION "0.1" + +#define RS5C348_REG_SECS 0 +#define RS5C348_REG_MINS 1 +#define RS5C348_REG_HOURS 2 +#define RS5C348_REG_WDAY 3 +#define RS5C348_REG_DAY 4 +#define RS5C348_REG_MONTH 5 +#define RS5C348_REG_YEAR 6 +#define RS5C348_REG_CTL1 14 +#define RS5C348_REG_CTL2 15 + +#define RS5C348_SECS_MASK 0x7f +#define RS5C348_MINS_MASK 0x7f +#define RS5C348_HOURS_MASK 0x3f +#define RS5C348_WDAY_MASK 0x03 +#define RS5C348_DAY_MASK 0x3f +#define RS5C348_MONTH_MASK 0x1f + +#define RS5C348_BIT_PM 0x20 /* REG_HOURS */ +#define RS5C348_BIT_Y2K 0x80 /* REG_MONTH */ +#define RS5C348_BIT_24H 0x20 /* REG_CTL1 */ +#define RS5C348_BIT_XSTP 0x10 /* REG_CTL2 */ +#define RS5C348_BIT_VDET 0x40 /* REG_CTL2 */ + +#define RS5C348_CMD_W(addr) (((addr) << 4) | 0x08) /* single write */ +#define RS5C348_CMD_R(addr) (((addr) << 4) | 0x0c) /* single read */ +#define RS5C348_CMD_MW(addr) (((addr) << 4) | 0x00) /* burst write */ +#define RS5C348_CMD_MR(addr) (((addr) << 4) | 0x04) /* burst read */ + +struct rs5c348_plat_data { + struct rtc_device *rtc; + int rtc_24h; +}; + +static int +rs5c348_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ + struct spi_device *spi = to_spi_device(dev); + struct rs5c348_plat_data *pdata = spi->dev.platform_data; + u8 txbuf[5+7], *txp; + int ret; + + /* Transfer 5 bytes before writing SEC. This gives 31us for carry. */ + txp = txbuf; + txbuf[0] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */ + txbuf[1] = 0; /* dummy */ + txbuf[2] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */ + txbuf[3] = 0; /* dummy */ + txbuf[4] = RS5C348_CMD_MW(RS5C348_REG_SECS); /* cmd, sec, ... */ + txp = &txbuf[5]; + txp[RS5C348_REG_SECS] = BIN2BCD(tm->tm_sec); + txp[RS5C348_REG_MINS] = BIN2BCD(tm->tm_min); + if (pdata->rtc_24h) { + txp[RS5C348_REG_HOURS] = BIN2BCD(tm->tm_hour); + } else { + /* hour 0 is AM12, noon is PM12 */ + txp[RS5C348_REG_HOURS] = BIN2BCD((tm->tm_hour + 11) % 12 + 1) | + (tm->tm_hour >= 12 ? RS5C348_BIT_PM : 0); + } + txp[RS5C348_REG_WDAY] = BIN2BCD(tm->tm_wday); + txp[RS5C348_REG_DAY] = BIN2BCD(tm->tm_mday); + txp[RS5C348_REG_MONTH] = BIN2BCD(tm->tm_mon + 1) | + (tm->tm_year >= 100 ? RS5C348_BIT_Y2K : 0); + txp[RS5C348_REG_YEAR] = BIN2BCD(tm->tm_year % 100); + /* write in one transfer to avoid data inconsistency */ + ret = spi_write_then_read(spi, txbuf, sizeof(txbuf), NULL, 0); + udelay(62); /* Tcsr 62us */ + return ret; +} + +static int +rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct spi_device *spi = to_spi_device(dev); + struct rs5c348_plat_data *pdata = spi->dev.platform_data; + u8 txbuf[5], rxbuf[7]; + int ret; + + /* Transfer 5 byte befores reading SEC. This gives 31us for carry. */ + txbuf[0] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */ + txbuf[1] = 0; /* dummy */ + txbuf[2] = RS5C348_CMD_R(RS5C348_REG_CTL2); /* cmd, ctl2 */ + txbuf[3] = 0; /* dummy */ + txbuf[4] = RS5C348_CMD_MR(RS5C348_REG_SECS); /* cmd, sec, ... */ + + /* read in one transfer to avoid data inconsistency */ + ret = spi_write_then_read(spi, txbuf, sizeof(txbuf), + rxbuf, sizeof(rxbuf)); + udelay(62); /* Tcsr 62us */ + if (ret < 0) + return ret; + + tm->tm_sec = BCD2BIN(rxbuf[RS5C348_REG_SECS] & RS5C348_SECS_MASK); + tm->tm_min = BCD2BIN(rxbuf[RS5C348_REG_MINS] & RS5C348_MINS_MASK); + tm->tm_hour = BCD2BIN(rxbuf[RS5C348_REG_HOURS] & RS5C348_HOURS_MASK); + if (!pdata->rtc_24h) { + tm->tm_hour %= 12; + if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM) + tm->tm_hour += 12; + } + tm->tm_wday = BCD2BIN(rxbuf[RS5C348_REG_WDAY] & RS5C348_WDAY_MASK); + tm->tm_mday = BCD2BIN(rxbuf[RS5C348_REG_DAY] & RS5C348_DAY_MASK); + tm->tm_mon = + BCD2BIN(rxbuf[RS5C348_REG_MONTH] & RS5C348_MONTH_MASK) - 1; + /* year is 1900 + tm->tm_year */ + tm->tm_year = BCD2BIN(rxbuf[RS5C348_REG_YEAR]) + + ((rxbuf[RS5C348_REG_MONTH] & RS5C348_BIT_Y2K) ? 100 : 0); + + if (rtc_valid_tm(tm) < 0) { + dev_err(&spi->dev, "retrieved date/time is not valid.\n"); + rtc_time_to_tm(0, tm); + } + + return 0; +} + +static struct rtc_class_ops rs5c348_rtc_ops = { + .read_time = rs5c348_rtc_read_time, + .set_time = rs5c348_rtc_set_time, +}; + +static struct spi_driver rs5c348_driver; + +static int __devinit rs5c348_probe(struct spi_device *spi) +{ + int ret; + struct rtc_device *rtc; + struct rs5c348_plat_data *pdata; + + pdata = kzalloc(sizeof(struct rs5c348_plat_data), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + spi->dev.platform_data = pdata; + + /* Check D7 of SECOND register */ + ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_SECS)); + if (ret < 0 || (ret & 0x80)) { + dev_err(&spi->dev, "not found.\n"); + goto kfree_exit; + } + + dev_info(&spi->dev, "chip found, driver version " DRV_VERSION "\n"); + dev_info(&spi->dev, "spiclk %u KHz.\n", + (spi->max_speed_hz + 500) / 1000); + + /* turn RTC on if it was not on */ + ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_CTL2)); + if (ret < 0) + goto kfree_exit; + if (ret & (RS5C348_BIT_XSTP | RS5C348_BIT_VDET)) { + u8 buf[2]; + if (ret & RS5C348_BIT_VDET) + dev_warn(&spi->dev, "voltage-low detected.\n"); + buf[0] = RS5C348_CMD_W(RS5C348_REG_CTL2); + buf[1] = 0; + ret = spi_write_then_read(spi, buf, sizeof(buf), NULL, 0); + if (ret < 0) + goto kfree_exit; + } + + ret = spi_w8r8(spi, RS5C348_CMD_R(RS5C348_REG_CTL1)); + if (ret < 0) + goto kfree_exit; + if (ret & RS5C348_BIT_24H) + pdata->rtc_24h = 1; + + rtc = rtc_device_register(rs5c348_driver.driver.name, &spi->dev, + &rs5c348_rtc_ops, THIS_MODULE); + + if (IS_ERR(rtc)) { + ret = PTR_ERR(rtc); + goto kfree_exit; + } + + pdata->rtc = rtc; + + return 0; + kfree_exit: + kfree(pdata); + return ret; +} + +static int __devexit rs5c348_remove(struct spi_device *spi) +{ + struct rs5c348_plat_data *pdata = spi->dev.platform_data; + struct rtc_device *rtc = pdata->rtc; + + if (rtc) + rtc_device_unregister(rtc); + kfree(pdata); + return 0; +} + +static struct spi_driver rs5c348_driver = { + .driver = { + .name = "rs5c348", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + .probe = rs5c348_probe, + .remove = __devexit_p(rs5c348_remove), +}; + +static __init int rs5c348_init(void) +{ + return spi_register_driver(&rs5c348_driver); +} + +static __exit void rs5c348_exit(void) +{ + spi_unregister_driver(&rs5c348_driver); +} + +module_init(rs5c348_init); +module_exit(rs5c348_exit); + +MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); +MODULE_DESCRIPTION("Ricoh RS5C348 RTC driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(DRV_VERSION); diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c new file mode 100644 index 000000000..2c7de79c8 --- /dev/null +++ b/drivers/rtc/rtc-s3c.c @@ -0,0 +1,621 @@ +/* drivers/rtc/rtc-s3c.c + * + * Copyright (c) 2004,2006 Simtec Electronics + * Ben Dooks, <ben@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * S3C2410/S3C2440/S3C24XX Internal RTC Driver +*/ + +#include <linux/module.h> +#include <linux/fs.h> +#include <linux/string.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/rtc.h> +#include <linux/bcd.h> +#include <linux/clk.h> + +#include <asm/hardware.h> +#include <asm/uaccess.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/rtc.h> + +#include <asm/mach/time.h> + +#include <asm/arch/regs-rtc.h> + +/* I have yet to find an S3C implementation with more than one + * of these rtc blocks in */ + +static struct resource *s3c_rtc_mem; + +static void __iomem *s3c_rtc_base; +static int s3c_rtc_alarmno = NO_IRQ; +static int s3c_rtc_tickno = NO_IRQ; +static int s3c_rtc_freq = 1; + +static DEFINE_SPINLOCK(s3c_rtc_pie_lock); +static unsigned int tick_count; + +/* IRQ Handlers */ + +static irqreturn_t s3c_rtc_alarmirq(int irq, void *id, struct pt_regs *r) +{ + struct rtc_device *rdev = id; + + rtc_update_irq(&rdev->class_dev, 1, RTC_AF | RTC_IRQF); + return IRQ_HANDLED; +} + +static irqreturn_t s3c_rtc_tickirq(int irq, void *id, struct pt_regs *r) +{ + struct rtc_device *rdev = id; + + rtc_update_irq(&rdev->class_dev, tick_count++, RTC_PF | RTC_IRQF); + return IRQ_HANDLED; +} + +/* Update control registers */ +static void s3c_rtc_setaie(int to) +{ + unsigned int tmp; + + pr_debug("%s: aie=%d\n", __FUNCTION__, to); + + tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN; + + if (to) + tmp |= S3C2410_RTCALM_ALMEN; + + writeb(tmp, s3c_rtc_base + S3C2410_RTCALM); +} + +static void s3c_rtc_setpie(int to) +{ + unsigned int tmp; + + pr_debug("%s: pie=%d\n", __FUNCTION__, to); + + spin_lock_irq(&s3c_rtc_pie_lock); + tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE; + + if (to) + tmp |= S3C2410_TICNT_ENABLE; + + writeb(tmp, s3c_rtc_base + S3C2410_TICNT); + spin_unlock_irq(&s3c_rtc_pie_lock); +} + +static void s3c_rtc_setfreq(int freq) +{ + unsigned int tmp; + + spin_lock_irq(&s3c_rtc_pie_lock); + tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE; + + s3c_rtc_freq = freq; + + tmp |= (128 / freq)-1; + + writeb(tmp, s3c_rtc_base + S3C2410_TICNT); + spin_unlock_irq(&s3c_rtc_pie_lock); +} + +/* Time read/write */ + +static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) +{ + unsigned int have_retried = 0; + void __iomem *base = s3c_rtc_base; + + retry_get_time: + rtc_tm->tm_min = readb(base + S3C2410_RTCMIN); + rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR); + rtc_tm->tm_mday = readb(base + S3C2410_RTCDATE); + rtc_tm->tm_mon = readb(base + S3C2410_RTCMON); + rtc_tm->tm_year = readb(base + S3C2410_RTCYEAR); + rtc_tm->tm_sec = readb(base + S3C2410_RTCSEC); + + /* the only way to work out wether the system was mid-update + * when we read it is to check the second counter, and if it + * is zero, then we re-try the entire read + */ + + if (rtc_tm->tm_sec == 0 && !have_retried) { + have_retried = 1; + goto retry_get_time; + } + + pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n", + rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday, + rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec); + + BCD_TO_BIN(rtc_tm->tm_sec); + BCD_TO_BIN(rtc_tm->tm_min); + BCD_TO_BIN(rtc_tm->tm_hour); + BCD_TO_BIN(rtc_tm->tm_mday); + BCD_TO_BIN(rtc_tm->tm_mon); + BCD_TO_BIN(rtc_tm->tm_year); + + rtc_tm->tm_year += 100; + rtc_tm->tm_mon -= 1; + + return 0; +} + +static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm) +{ + void __iomem *base = s3c_rtc_base; + int year = tm->tm_year - 100; + + pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n", + tm->tm_year, tm->tm_mon, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + /* we get around y2k by simply not supporting it */ + + if (year < 0 || year >= 100) { + dev_err(dev, "rtc only supports 100 years\n"); + return -EINVAL; + } + + writeb(BIN2BCD(tm->tm_sec), base + S3C2410_RTCSEC); + writeb(BIN2BCD(tm->tm_min), base + S3C2410_RTCMIN); + writeb(BIN2BCD(tm->tm_hour), base + S3C2410_RTCHOUR); + writeb(BIN2BCD(tm->tm_mday), base + S3C2410_RTCDATE); + writeb(BIN2BCD(tm->tm_mon + 1), base + S3C2410_RTCMON); + writeb(BIN2BCD(year), base + S3C2410_RTCYEAR); + + return 0; +} + +static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct rtc_time *alm_tm = &alrm->time; + void __iomem *base = s3c_rtc_base; + unsigned int alm_en; + + alm_tm->tm_sec = readb(base + S3C2410_ALMSEC); + alm_tm->tm_min = readb(base + S3C2410_ALMMIN); + alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR); + alm_tm->tm_mon = readb(base + S3C2410_ALMMON); + alm_tm->tm_mday = readb(base + S3C2410_ALMDATE); + alm_tm->tm_year = readb(base + S3C2410_ALMYEAR); + + alm_en = readb(base + S3C2410_RTCALM); + + pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n", + alm_en, + alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday, + alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec); + + + /* decode the alarm enable field */ + + if (alm_en & S3C2410_RTCALM_SECEN) + BCD_TO_BIN(alm_tm->tm_sec); + else + alm_tm->tm_sec = 0xff; + + if (alm_en & S3C2410_RTCALM_MINEN) + BCD_TO_BIN(alm_tm->tm_min); + else + alm_tm->tm_min = 0xff; + + if (alm_en & S3C2410_RTCALM_HOUREN) + BCD_TO_BIN(alm_tm->tm_hour); + else + alm_tm->tm_hour = 0xff; + + if (alm_en & S3C2410_RTCALM_DAYEN) + BCD_TO_BIN(alm_tm->tm_mday); + else + alm_tm->tm_mday = 0xff; + + if (alm_en & S3C2410_RTCALM_MONEN) { + BCD_TO_BIN(alm_tm->tm_mon); + alm_tm->tm_mon -= 1; + } else { + alm_tm->tm_mon = 0xff; + } + + if (alm_en & S3C2410_RTCALM_YEAREN) + BCD_TO_BIN(alm_tm->tm_year); + else + alm_tm->tm_year = 0xffff; + + return 0; +} + +static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct rtc_time *tm = &alrm->time; + void __iomem *base = s3c_rtc_base; + unsigned int alrm_en; + + pr_debug("s3c_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n", + alrm->enabled, + tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff, + tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec); + + + alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN; + writeb(0x00, base + S3C2410_RTCALM); + + if (tm->tm_sec < 60 && tm->tm_sec >= 0) { + alrm_en |= S3C2410_RTCALM_SECEN; + writeb(BIN2BCD(tm->tm_sec), base + S3C2410_ALMSEC); + } + + if (tm->tm_min < 60 && tm->tm_min >= 0) { + alrm_en |= S3C2410_RTCALM_MINEN; + writeb(BIN2BCD(tm->tm_min), base + S3C2410_ALMMIN); + } + + if (tm->tm_hour < 24 && tm->tm_hour >= 0) { + alrm_en |= S3C2410_RTCALM_HOUREN; + writeb(BIN2BCD(tm->tm_hour), base + S3C2410_ALMHOUR); + } + + pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en); + + writeb(alrm_en, base + S3C2410_RTCALM); + + if (0) { + alrm_en = readb(base + S3C2410_RTCALM); + alrm_en &= ~S3C2410_RTCALM_ALMEN; + writeb(alrm_en, base + S3C2410_RTCALM); + disable_irq_wake(s3c_rtc_alarmno); + } + + if (alrm->enabled) + enable_irq_wake(s3c_rtc_alarmno); + else + disable_irq_wake(s3c_rtc_alarmno); + + return 0; +} + +static int s3c_rtc_ioctl(struct device *dev, + unsigned int cmd, unsigned long arg) +{ + unsigned int ret = -ENOIOCTLCMD; + + switch (cmd) { + case RTC_AIE_OFF: + case RTC_AIE_ON: + s3c_rtc_setaie((cmd == RTC_AIE_ON) ? 1 : 0); + ret = 0; + break; + + case RTC_PIE_OFF: + case RTC_PIE_ON: + tick_count = 0; + s3c_rtc_setpie((cmd == RTC_PIE_ON) ? 1 : 0); + ret = 0; + break; + + case RTC_IRQP_READ: + ret = put_user(s3c_rtc_freq, (unsigned long __user *)arg); + break; + + case RTC_IRQP_SET: + /* check for power of 2 */ + + if ((arg & (arg-1)) != 0 || arg < 1) { + ret = -EINVAL; + goto exit; + } + + pr_debug("s3c2410_rtc: setting frequency %ld\n", arg); + + s3c_rtc_setfreq(arg); + ret = 0; + break; + + case RTC_UIE_ON: + case RTC_UIE_OFF: + ret = -EINVAL; + } + + exit: + return ret; +} + +static int s3c_rtc_proc(struct device *dev, struct seq_file *seq) +{ + unsigned int rtcalm = readb(s3c_rtc_base + S3C2410_RTCALM); + unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT); + + seq_printf(seq, "alarm_IRQ\t: %s\n", + (rtcalm & S3C2410_RTCALM_ALMEN) ? "yes" : "no" ); + + seq_printf(seq, "periodic_IRQ\t: %s\n", + (ticnt & S3C2410_TICNT_ENABLE) ? "yes" : "no" ); + + seq_printf(seq, "periodic_freq\t: %d\n", s3c_rtc_freq); + + return 0; +} + +static int s3c_rtc_open(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_device *rtc_dev = platform_get_drvdata(pdev); + int ret; + + ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq, + SA_INTERRUPT, "s3c2410-rtc alarm", rtc_dev); + + if (ret) { + dev_err(dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret); + return ret; + } + + ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq, + SA_INTERRUPT, "s3c2410-rtc tick", rtc_dev); + + if (ret) { + dev_err(dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret); + goto tick_err; + } + + return ret; + + tick_err: + free_irq(s3c_rtc_alarmno, rtc_dev); + return ret; +} + +static void s3c_rtc_release(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct rtc_device *rtc_dev = platform_get_drvdata(pdev); + + /* do not clear AIE here, it may be needed for wake */ + + s3c_rtc_setpie(0); + free_irq(s3c_rtc_alarmno, rtc_dev); + free_irq(s3c_rtc_tickno, rtc_dev); +} + +static struct rtc_class_ops s3c_rtcops = { + .open = s3c_rtc_open, + .release = s3c_rtc_release, + .ioctl = s3c_rtc_ioctl, + .read_time = s3c_rtc_gettime, + .set_time = s3c_rtc_settime, + .read_alarm = s3c_rtc_getalarm, + .set_alarm = s3c_rtc_setalarm, + .proc = s3c_rtc_proc, +}; + +static void s3c_rtc_enable(struct platform_device *pdev, int en) +{ + void __iomem *base = s3c_rtc_base; + unsigned int tmp; + + if (s3c_rtc_base == NULL) + return; + + if (!en) { + tmp = readb(base + S3C2410_RTCCON); + writeb(tmp & ~S3C2410_RTCCON_RTCEN, base + S3C2410_RTCCON); + + tmp = readb(base + S3C2410_TICNT); + writeb(tmp & ~S3C2410_TICNT_ENABLE, base + S3C2410_TICNT); + } else { + /* re-enable the device, and check it is ok */ + + if ((readb(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){ + dev_info(&pdev->dev, "rtc disabled, re-enabling\n"); + + tmp = readb(base + S3C2410_RTCCON); + writeb(tmp|S3C2410_RTCCON_RTCEN, base+S3C2410_RTCCON); + } + + if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){ + dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n"); + + tmp = readb(base + S3C2410_RTCCON); + writeb(tmp& ~S3C2410_RTCCON_CNTSEL, base+S3C2410_RTCCON); + } + + if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){ + dev_info(&pdev->dev, "removing RTCCON_CLKRST\n"); + + tmp = readb(base + S3C2410_RTCCON); + writeb(tmp & ~S3C2410_RTCCON_CLKRST, base+S3C2410_RTCCON); + } + } +} + +static int s3c_rtc_remove(struct platform_device *dev) +{ + struct rtc_device *rtc = platform_get_drvdata(dev); + + platform_set_drvdata(dev, NULL); + rtc_device_unregister(rtc); + + s3c_rtc_setpie(0); + s3c_rtc_setaie(0); + + iounmap(s3c_rtc_base); + release_resource(s3c_rtc_mem); + kfree(s3c_rtc_mem); + + return 0; +} + +static int s3c_rtc_probe(struct platform_device *pdev) +{ + struct rtc_device *rtc; + struct resource *res; + int ret; + + pr_debug("%s: probe=%p\n", __FUNCTION__, pdev); + + /* find the IRQs */ + + s3c_rtc_tickno = platform_get_irq(pdev, 1); + if (s3c_rtc_tickno < 0) { + dev_err(&pdev->dev, "no irq for rtc tick\n"); + return -ENOENT; + } + + s3c_rtc_alarmno = platform_get_irq(pdev, 0); + if (s3c_rtc_alarmno < 0) { + dev_err(&pdev->dev, "no irq for alarm\n"); + return -ENOENT; + } + + pr_debug("s3c2410_rtc: tick irq %d, alarm irq %d\n", + s3c_rtc_tickno, s3c_rtc_alarmno); + + /* get the memory region */ + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "failed to get memory region resource\n"); + return -ENOENT; + } + + s3c_rtc_mem = request_mem_region(res->start, + res->end-res->start+1, + pdev->name); + + if (s3c_rtc_mem == NULL) { + dev_err(&pdev->dev, "failed to reserve memory region\n"); + ret = -ENOENT; + goto err_nores; + } + + s3c_rtc_base = ioremap(res->start, res->end - res->start + 1); + if (s3c_rtc_base == NULL) { + dev_err(&pdev->dev, "failed ioremap()\n"); + ret = -EINVAL; + goto err_nomap; + } + + /* check to see if everything is setup correctly */ + + s3c_rtc_enable(pdev, 1); + + pr_debug("s3c2410_rtc: RTCCON=%02x\n", + readb(s3c_rtc_base + S3C2410_RTCCON)); + + s3c_rtc_setfreq(s3c_rtc_freq); + + /* register RTC and exit */ + + rtc = rtc_device_register("s3c", &pdev->dev, &s3c_rtcops, + THIS_MODULE); + + if (IS_ERR(rtc)) { + dev_err(&pdev->dev, "cannot attach rtc\n"); + ret = PTR_ERR(rtc); + goto err_nortc; + } + + rtc->max_user_freq = 128; + + platform_set_drvdata(pdev, rtc); + return 0; + + err_nortc: + s3c_rtc_enable(pdev, 0); + iounmap(s3c_rtc_base); + + err_nomap: + release_resource(s3c_rtc_mem); + + err_nores: + return ret; +} + +#ifdef CONFIG_PM + +/* RTC Power management control */ + +static struct timespec s3c_rtc_delta; + +static int ticnt_save; + +static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct rtc_time tm; + struct timespec time; + + time.tv_nsec = 0; + + /* save TICNT for anyone using periodic interrupts */ + + ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT); + + /* calculate time delta for suspend */ + + s3c_rtc_gettime(&pdev->dev, &tm); + rtc_tm_to_time(&tm, &time.tv_sec); + save_time_delta(&s3c_rtc_delta, &time); + s3c_rtc_enable(pdev, 0); + + return 0; +} + +static int s3c_rtc_resume(struct platform_device *pdev) +{ + struct rtc_time tm; + struct timespec time; + + time.tv_nsec = 0; + + s3c_rtc_enable(pdev, 1); + s3c_rtc_gettime(&pdev->dev, &tm); + rtc_tm_to_time(&tm, &time.tv_sec); + restore_time_delta(&s3c_rtc_delta, &time); + + writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT); + return 0; +} +#else +#define s3c_rtc_suspend NULL +#define s3c_rtc_resume NULL +#endif + +static struct platform_driver s3c2410_rtcdrv = { + .probe = s3c_rtc_probe, + .remove = s3c_rtc_remove, + .suspend = s3c_rtc_suspend, + .resume = s3c_rtc_resume, + .driver = { + .name = "s3c2410-rtc", + .owner = THIS_MODULE, + }, +}; + +static char __initdata banner[] = "S3C24XX RTC, (c) 2004,2006 Simtec Electronics\n"; + +static int __init s3c_rtc_init(void) +{ + printk(banner); + return platform_driver_register(&s3c2410_rtcdrv); +} + +static void __exit s3c_rtc_exit(void) +{ + platform_driver_unregister(&s3c2410_rtcdrv); +} + +module_init(s3c_rtc_init); +module_exit(s3c_rtc_exit); + +MODULE_DESCRIPTION("Samsung S3C RTC Driver"); +MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c new file mode 100644 index 000000000..a40f400ac --- /dev/null +++ b/drivers/rtc/rtc-v3020.c @@ -0,0 +1,264 @@ +/* drivers/rtc/rtc-v3020.c + * + * Copyright (C) 2006 8D Technologies inc. + * Copyright (C) 2004 Compulab Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Driver for the V3020 RTC + * + * Changelog: + * + * 10-May-2006: Raphael Assenat <raph@8d.com> + * - Converted to platform driver + * - Use the generic rtc class + * + * ??-???-2004: Someone at Compulab + * - Initial driver creation. + * + */ +#include <linux/platform_device.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/rtc.h> +#include <linux/types.h> +#include <linux/bcd.h> +#include <linux/rtc-v3020.h> + +#include <asm/io.h> + +#undef DEBUG + +struct v3020 { + void __iomem *ioaddress; + int leftshift; + struct rtc_device *rtc; +}; + +static void v3020_set_reg(struct v3020 *chip, unsigned char address, + unsigned char data) +{ + int i; + unsigned char tmp; + + tmp = address; + for (i = 0; i < 4; i++) { + writel((tmp & 1) << chip->leftshift, chip->ioaddress); + tmp >>= 1; + } + + /* Commands dont have data */ + if (!V3020_IS_COMMAND(address)) { + for (i = 0; i < 8; i++) { + writel((data & 1) << chip->leftshift, chip->ioaddress); + data >>= 1; + } + } +} + +static unsigned char v3020_get_reg(struct v3020 *chip, unsigned char address) +{ + unsigned int data=0; + int i; + + for (i = 0; i < 4; i++) { + writel((address & 1) << chip->leftshift, chip->ioaddress); + address >>= 1; + } + + for (i = 0; i < 8; i++) { + data >>= 1; + if (readl(chip->ioaddress) & (1 << chip->leftshift)) + data |= 0x80; + } + + return data; +} + +static int v3020_read_time(struct device *dev, struct rtc_time *dt) +{ + struct v3020 *chip = dev_get_drvdata(dev); + int tmp; + + /* Copy the current time to ram... */ + v3020_set_reg(chip, V3020_CMD_CLOCK2RAM, 0); + + /* ...and then read constant values. */ + tmp = v3020_get_reg(chip, V3020_SECONDS); + dt->tm_sec = BCD2BIN(tmp); + tmp = v3020_get_reg(chip, V3020_MINUTES); + dt->tm_min = BCD2BIN(tmp); + tmp = v3020_get_reg(chip, V3020_HOURS); + dt->tm_hour = BCD2BIN(tmp); + tmp = v3020_get_reg(chip, V3020_MONTH_DAY); + dt->tm_mday = BCD2BIN(tmp); + tmp = v3020_get_reg(chip, V3020_MONTH); + dt->tm_mon = BCD2BIN(tmp); + tmp = v3020_get_reg(chip, V3020_WEEK_DAY); + dt->tm_wday = BCD2BIN(tmp); + tmp = v3020_get_reg(chip, V3020_YEAR); + dt->tm_year = BCD2BIN(tmp)+100; + +#ifdef DEBUG + printk("\n%s : Read RTC values\n",__FUNCTION__); + printk("tm_hour: %i\n",dt->tm_hour); + printk("tm_min : %i\n",dt->tm_min); + printk("tm_sec : %i\n",dt->tm_sec); + printk("tm_year: %i\n",dt->tm_year); + printk("tm_mon : %i\n",dt->tm_mon); + printk("tm_mday: %i\n",dt->tm_mday); + printk("tm_wday: %i\n",dt->tm_wday); +#endif + + return 0; +} + + +static int v3020_set_time(struct device *dev, struct rtc_time *dt) +{ + struct v3020 *chip = dev_get_drvdata(dev); + +#ifdef DEBUG + printk("\n%s : Setting RTC values\n",__FUNCTION__); + printk("tm_sec : %i\n",dt->tm_sec); + printk("tm_min : %i\n",dt->tm_min); + printk("tm_hour: %i\n",dt->tm_hour); + printk("tm_mday: %i\n",dt->tm_mday); + printk("tm_wday: %i\n",dt->tm_wday); + printk("tm_year: %i\n",dt->tm_year); +#endif + + /* Write all the values to ram... */ + v3020_set_reg(chip, V3020_SECONDS, BIN2BCD(dt->tm_sec)); + v3020_set_reg(chip, V3020_MINUTES, BIN2BCD(dt->tm_min)); + v3020_set_reg(chip, V3020_HOURS, BIN2BCD(dt->tm_hour)); + v3020_set_reg(chip, V3020_MONTH_DAY, BIN2BCD(dt->tm_mday)); + v3020_set_reg(chip, V3020_MONTH, BIN2BCD(dt->tm_mon)); + v3020_set_reg(chip, V3020_WEEK_DAY, BIN2BCD(dt->tm_wday)); + v3020_set_reg(chip, V3020_YEAR, BIN2BCD(dt->tm_year % 100)); + + /* ...and set the clock. */ + v3020_set_reg(chip, V3020_CMD_RAM2CLOCK, 0); + + /* Compulab used this delay here. I dont know why, + * the datasheet does not specify a delay. */ + /*mdelay(5);*/ + + return 0; +} + +static struct rtc_class_ops v3020_rtc_ops = { + .read_time = v3020_read_time, + .set_time = v3020_set_time, +}; + +static int rtc_probe(struct platform_device *pdev) +{ + struct v3020_platform_data *pdata = pdev->dev.platform_data; + struct v3020 *chip; + struct rtc_device *rtc; + int retval = -EBUSY; + int i; + int temp; + + if (pdev->num_resources != 1) + return -EBUSY; + + if (pdev->resource[0].flags != IORESOURCE_MEM) + return -EBUSY; + + if (pdev == NULL) + return -EBUSY; + + chip = kzalloc(sizeof *chip, GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->leftshift = pdata->leftshift; + chip->ioaddress = ioremap(pdev->resource[0].start, 1); + if (chip->ioaddress == NULL) + goto err_chip; + + /* Make sure the v3020 expects a communication cycle + * by reading 8 times */ + for (i = 0; i < 8; i++) + temp = readl(chip->ioaddress); + + /* Test chip by doing a write/read sequence + * to the chip ram */ + v3020_set_reg(chip, V3020_SECONDS, 0x33); + if(v3020_get_reg(chip, V3020_SECONDS) != 0x33) { + retval = -ENODEV; + goto err_io; + } + + /* Make sure frequency measurment mode, test modes, and lock + * are all disabled */ + v3020_set_reg(chip, V3020_STATUS_0, 0x0); + + dev_info(&pdev->dev, "Chip available at physical address 0x%p," + "data connected to D%d\n", + (void*)pdev->resource[0].start, + chip->leftshift); + + platform_set_drvdata(pdev, chip); + + rtc = rtc_device_register("v3020", + &pdev->dev, &v3020_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) { + retval = PTR_ERR(rtc); + goto err_io; + } + chip->rtc = rtc; + + return 0; + +err_io: + iounmap(chip->ioaddress); +err_chip: + kfree(chip); + + return retval; +} + +static int rtc_remove(struct platform_device *dev) +{ + struct v3020 *chip = platform_get_drvdata(dev); + struct rtc_device *rtc = chip->rtc; + + if (rtc) + rtc_device_unregister(rtc); + + iounmap(chip->ioaddress); + kfree(chip); + + return 0; +} + +static struct platform_driver rtc_device_driver = { + .probe = rtc_probe, + .remove = rtc_remove, + .driver = { + .name = "v3020", + .owner = THIS_MODULE, + }, +}; + +static __init int v3020_init(void) +{ + return platform_driver_register(&rtc_device_driver); +} + +static __exit void v3020_exit(void) +{ + platform_driver_unregister(&rtc_device_driver); +} + +module_init(v3020_init); +module_exit(v3020_exit); + +MODULE_DESCRIPTION("V3020 RTC"); +MODULE_AUTHOR("Raphael Assenat"); +MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c new file mode 100644 index 000000000..28bfb8f9f --- /dev/null +++ b/drivers/scsi/hptiop.c @@ -0,0 +1,942 @@ +/* + * HighPoint RR3xxx controller driver for Linux + * Copyright (C) 2006 HighPoint Technologies, Inc. All Rights Reserved. + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Please report bugs/comments/suggestions to linux@highpoint-tech.com + * + * For more information, visit http://www.highpoint-tech.com + */ +#include <linux/module.h> +#include <linux/types.h> +#include <linux/string.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/interrupt.h> +#include <linux/errno.h> +#include <linux/delay.h> +#include <linux/timer.h> +#include <linux/spinlock.h> +#include <linux/hdreg.h> +#include <asm/uaccess.h> +#include <asm/io.h> +#include <asm/div64.h> +#include <scsi/scsi_cmnd.h> +#include <scsi/scsi_device.h> +#include <scsi/scsi.h> +#include <scsi/scsi_tcq.h> +#include <scsi/scsi_host.h> + +#include "hptiop.h" + +MODULE_AUTHOR("HighPoint Technologies, Inc."); +MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx SATA Controller Driver"); + +static char driver_name[] = "hptiop"; +static const char driver_name_long[] = "RocketRAID 3xxx SATA Controller driver"; +static const char driver_ver[] = "v1.0 (060426)"; + +static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag); +static void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag); +static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg); + +static inline void hptiop_pci_posting_flush(struct hpt_iopmu __iomem *iop) +{ + readl(&iop->outbound_intstatus); +} + +static int iop_wait_ready(struct hpt_iopmu __iomem *iop, u32 millisec) +{ + u32 req = 0; + int i; + + for (i = 0; i < millisec; i++) { + req = readl(&iop->inbound_queue); + if (req != IOPMU_QUEUE_EMPTY) + break; + msleep(1); + } + + if (req != IOPMU_QUEUE_EMPTY) { + writel(req, &iop->outbound_queue); + hptiop_pci_posting_flush(iop); + return 0; + } + + return -1; +} + +static void hptiop_request_callback(struct hptiop_hba *hba, u32 tag) +{ + if ((tag & IOPMU_QUEUE_MASK_HOST_BITS) == IOPMU_QUEUE_ADDR_HOST_BIT) + return hptiop_host_request_callback(hba, + tag & ~IOPMU_QUEUE_ADDR_HOST_BIT); + else + return hptiop_iop_request_callback(hba, tag); +} + +static inline void hptiop_drain_outbound_queue(struct hptiop_hba *hba) +{ + u32 req; + + while ((req = readl(&hba->iop->outbound_queue)) != IOPMU_QUEUE_EMPTY) { + + if (req & IOPMU_QUEUE_MASK_HOST_BITS) + hptiop_request_callback(hba, req); + else { + struct hpt_iop_request_header __iomem * p; + + p = (struct hpt_iop_request_header __iomem *) + ((char __iomem *)hba->iop + req); + + if (readl(&p->flags) & IOP_REQUEST_FLAG_SYNC_REQUEST) { + if (readl(&p->context)) + hptiop_request_callback(hba, req); + else + writel(1, &p->context); + } + else + hptiop_request_callback(hba, req); + } + } +} + +static int __iop_intr(struct hptiop_hba *hba) +{ + struct hpt_iopmu __iomem *iop = hba->iop; + u32 status; + int ret = 0; + + status = readl(&iop->outbound_intstatus); + + if (status & IOPMU_OUTBOUND_INT_MSG0) { + u32 msg = readl(&iop->outbound_msgaddr0); + dprintk("received outbound msg %x\n", msg); + writel(IOPMU_OUTBOUND_INT_MSG0, &iop->outbound_intstatus); + hptiop_message_callback(hba, msg); + ret = 1; + } + + if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) { + hptiop_drain_outbound_queue(hba); + ret = 1; + } + + return ret; +} + +static int iop_send_sync_request(struct hptiop_hba *hba, + void __iomem *_req, u32 millisec) +{ + struct hpt_iop_request_header __iomem *req = _req; + u32 i; + + writel(readl(&req->flags) | IOP_REQUEST_FLAG_SYNC_REQUEST, + &req->flags); + + writel(0, &req->context); + + writel((unsigned long)req - (unsigned long)hba->iop, + &hba->iop->inbound_queue); + + hptiop_pci_posting_flush(hba->iop); + + for (i = 0; i < millisec; i++) { + __iop_intr(hba); + if (readl(&req->context)) + return 0; + msleep(1); + } + + return -1; +} + +static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec) +{ + u32 i; + + hba->msg_done = 0; + + writel(msg, &hba->iop->inbound_msgaddr0); + + hptiop_pci_posting_flush(hba->iop); + + for (i = 0; i < millisec; i++) { + spin_lock_irq(hba->host->host_lock); + __iop_intr(hba); + spin_unlock_irq(hba->host->host_lock); + if (hba->msg_done) + break; + msleep(1); + } + + return hba->msg_done? 0 : -1; +} + +static int iop_get_config(struct hptiop_hba *hba, + struct hpt_iop_request_get_config *config) +{ + u32 req32; + struct hpt_iop_request_get_config __iomem *req; + + req32 = readl(&hba->iop->inbound_queue); + if (req32 == IOPMU_QUEUE_EMPTY) + return -1; + + req = (struct hpt_iop_request_get_config __iomem *) + ((unsigned long)hba->iop + req32); + + writel(0, &req->header.flags); + writel(IOP_REQUEST_TYPE_GET_CONFIG, &req->header.type); + writel(sizeof(struct hpt_iop_request_get_config), &req->header.size); + writel(IOP_RESULT_PENDING, &req->header.result); + + if (iop_send_sync_request(hba, req, 20000)) { + dprintk("Get config send cmd failed\n"); + return -1; + } + + memcpy_fromio(config, req, sizeof(*config)); + writel(req32, &hba->iop->outbound_queue); + return 0; +} + +static int iop_set_config(struct hptiop_hba *hba, + struct hpt_iop_request_set_config *config) +{ + u32 req32; + struct hpt_iop_request_set_config __iomem *req; + + req32 = readl(&hba->iop->inbound_queue); + if (req32 == IOPMU_QUEUE_EMPTY) + return -1; + + req = (struct hpt_iop_request_set_config __iomem *) + ((unsigned long)hba->iop + req32); + + memcpy_toio((u8 __iomem *)req + sizeof(struct hpt_iop_request_header), + (u8 *)config + sizeof(struct hpt_iop_request_header), + sizeof(struct hpt_iop_request_set_config) - + sizeof(struct hpt_iop_request_header)); + + writel(0, &req->header.flags); + writel(IOP_REQUEST_TYPE_SET_CONFIG, &req->header.type); + writel(sizeof(struct hpt_iop_request_set_config), &req->header.size); + writel(IOP_RESULT_PENDING, &req->header.result); + + if (iop_send_sync_request(hba, req, 20000)) { + dprintk("Set config send cmd failed\n"); + return -1; + } + + writel(req32, &hba->iop->outbound_queue); + return 0; +} + +static int hptiop_initialize_iop(struct hptiop_hba *hba) +{ + struct hpt_iopmu __iomem *iop = hba->iop; + + /* enable interrupts */ + writel(~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0), + &iop->outbound_intmask); + + hba->initialized = 1; + + /* start background tasks */ + if (iop_send_sync_msg(hba, + IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) { + printk(KERN_ERR "scsi%d: fail to start background task\n", + hba->host->host_no); + return -1; + } + return 0; +} + +static int hptiop_map_pci_bar(struct hptiop_hba *hba) +{ + u32 mem_base_phy, length; + void __iomem *mem_base_virt; + struct pci_dev *pcidev = hba->pcidev; + + if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) { + printk(KERN_ERR "scsi%d: pci resource invalid\n", + hba->host->host_no); + return -1; + } + + mem_base_phy = pci_resource_start(pcidev, 0); + length = pci_resource_len(pcidev, 0); + mem_base_virt = ioremap(mem_base_phy, length); + + if (!mem_base_virt) { + printk(KERN_ERR "scsi%d: Fail to ioremap memory space\n", + hba->host->host_no); + return -1; + } + + hba->iop = mem_base_virt; + dprintk("hptiop_map_pci_bar: iop=%p\n", hba->iop); + return 0; +} + +static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg) +{ + dprintk("iop message 0x%x\n", msg); + + if (!hba->initialized) + return; + + if (msg == IOPMU_INBOUND_MSG0_RESET) { + atomic_set(&hba->resetting, 0); + wake_up(&hba->reset_wq); + } + else if (msg <= IOPMU_INBOUND_MSG0_MAX) + hba->msg_done = 1; +} + +static inline struct hptiop_request *get_req(struct hptiop_hba *hba) +{ + struct hptiop_request *ret; + + dprintk("get_req : req=%p\n", hba->req_list); + + ret = hba->req_list; + if (ret) + hba->req_list = ret->next; + + return ret; +} + +static inline void free_req(struct hptiop_hba *hba, struct hptiop_request *req) +{ + dprintk("free_req(%d, %p)\n", req->index, req); + req->next = hba->req_list; + hba->req_list = req; +} + +static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag) +{ + struct hpt_iop_request_scsi_command *req; + struct scsi_cmnd *scp; + + req = (struct hpt_iop_request_scsi_command *)hba->reqs[tag].req_virt; + dprintk("hptiop_host_request_callback: req=%p, type=%d, " + "result=%d, context=0x%x tag=%d\n", + req, req->header.type, req->header.result, + req->header.context, tag); + + BUG_ON(!req->header.result); + BUG_ON(req->header.type != cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND)); + + scp = hba->reqs[tag].scp; + + if (HPT_SCP(scp)->mapped) { + if (scp->use_sg) + pci_unmap_sg(hba->pcidev, + (struct scatterlist *)scp->request_buffer, + scp->use_sg, + scp->sc_data_direction + ); + else + pci_unmap_single(hba->pcidev, + HPT_SCP(scp)->dma_handle, + scp->request_bufflen, + scp->sc_data_direction + ); + } + + switch (le32_to_cpu(req->header.result)) { + case IOP_RESULT_SUCCESS: + scp->result = (DID_OK<<16); + break; + case IOP_RESULT_BAD_TARGET: + scp->result = (DID_BAD_TARGET<<16); + break; + case IOP_RESULT_BUSY: + scp->result = (DID_BUS_BUSY<<16); + break; + case IOP_RESULT_RESET: + scp->result = (DID_RESET<<16); + break; + case IOP_RESULT_FAIL: + scp->result = (DID_ERROR<<16); + break; + case IOP_RESULT_INVALID_REQUEST: + scp->result = (DID_ABORT<<16); + break; + case IOP_RESULT_MODE_SENSE_CHECK_CONDITION: + scp->result = SAM_STAT_CHECK_CONDITION; + memset(&scp->sense_buffer, + 0, sizeof(scp->sense_buffer)); + memcpy(&scp->sense_buffer, + &req->sg_list, le32_to_cpu(req->dataxfer_length)); + break; + + default: + scp->result = ((DRIVER_INVALID|SUGGEST_ABORT)<<24) | + (DID_ABORT<<16); + break; + } + + dprintk("scsi_done(%p)\n", scp); + scp->scsi_done(scp); + free_req(hba, &hba->reqs[tag]); +} + +void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag) +{ + struct hpt_iop_request_header __iomem *req; + struct hpt_iop_request_ioctl_command __iomem *p; + struct hpt_ioctl_k *arg; + + req = (struct hpt_iop_request_header __iomem *) + ((unsigned long)hba->iop + tag); + dprintk("hptiop_iop_request_callback: req=%p, type=%d, " + "result=%d, context=0x%x tag=%d\n", + req, readl(&req->type), readl(&req->result), + readl(&req->context), tag); + + BUG_ON(!readl(&req->result)); + BUG_ON(readl(&req->type) != IOP_REQUEST_TYPE_IOCTL_COMMAND); + + p = (struct hpt_iop_request_ioctl_command __iomem *)req; + arg = (struct hpt_ioctl_k *)(unsigned long) + (readl(&req->context) | + ((u64)readl(&req->context_hi32)<<32)); + + if (readl(&req->result) == IOP_RESULT_SUCCESS) { + arg->result = HPT_IOCTL_RESULT_OK; + + if (arg->outbuf_size) + memcpy_fromio(arg->outbuf, + &p->buf[(readl(&p->inbuf_size) + 3)& ~3], + arg->outbuf_size); + + if (arg->bytes_returned) + *arg->bytes_returned = arg->outbuf_size; + } + else + arg->result = HPT_IOCTL_RESULT_FAILED; + + arg->done(arg); + writel(tag, &hba->iop->outbound_queue); +} + +static irqreturn_t hptiop_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct hptiop_hba *hba = dev_id; + int handled; + unsigned long flags; + + spin_lock_irqsave(hba->host->host_lock, flags); + handled = __iop_intr(hba); + spin_unlock_irqrestore(hba->host->host_lock, flags); + + return handled; +} + +static int hptiop_buildsgl(struct scsi_cmnd *scp, struct hpt_iopsg *psg) +{ + struct Scsi_Host *host = scp->device->host; + struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; + struct scatterlist *sglist = (struct scatterlist *)scp->request_buffer; + + /* + * though we'll not get non-use_sg fields anymore, + * keep use_sg checking anyway + */ + if (scp->use_sg) { + int idx; + + HPT_SCP(scp)->sgcnt = pci_map_sg(hba->pcidev, + sglist, scp->use_sg, + scp->sc_data_direction); + HPT_SCP(scp)->mapped = 1; + BUG_ON(HPT_SCP(scp)->sgcnt > hba->max_sg_descriptors); + + for (idx = 0; idx < HPT_SCP(scp)->sgcnt; idx++) { + psg[idx].pci_address = + cpu_to_le64(sg_dma_address(&sglist[idx])); + psg[idx].size = cpu_to_le32(sg_dma_len(&sglist[idx])); + psg[idx].eot = (idx == HPT_SCP(scp)->sgcnt - 1) ? + cpu_to_le32(1) : 0; + } + + return HPT_SCP(scp)->sgcnt; + } else { + HPT_SCP(scp)->dma_handle = pci_map_single( + hba->pcidev, + scp->request_buffer, + scp->request_bufflen, + scp->sc_data_direction + ); + HPT_SCP(scp)->mapped = 1; + psg->pci_address = cpu_to_le64(HPT_SCP(scp)->dma_handle); + psg->size = cpu_to_le32(scp->request_bufflen); + psg->eot = cpu_to_le32(1); + return 1; + } +} + +static int hptiop_queuecommand(struct scsi_cmnd *scp, + void (*done)(struct scsi_cmnd *)) +{ + struct Scsi_Host *host = scp->device->host; + struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; + struct hpt_iop_request_scsi_command *req; + int sg_count = 0; + struct hptiop_request *_req; + + BUG_ON(!done); + scp->scsi_done = done; + + _req = get_req(hba); + if (_req == NULL) { + dprintk("hptiop_queuecmd : no free req\n"); + return SCSI_MLQUEUE_HOST_BUSY; + } + + _req->scp = scp; + + dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%d cdb=(%x-%x-%x) " + "req_index=%d, req=%p\n", + scp, + host->host_no, scp->device->channel, + scp->device->id, scp->device->lun, + *((u32 *)&scp->cmnd), + *((u32 *)&scp->cmnd + 1), + *((u32 *)&scp->cmnd + 2), + _req->index, _req->req_virt); + + scp->result = 0; + + if (scp->device->channel || scp->device->lun || + scp->device->id > hba->max_devices) { + scp->result = DID_BAD_TARGET << 16; + free_req(hba, _req); + goto cmd_done; + } + + req = (struct hpt_iop_request_scsi_command *)_req->req_virt; + + /* build S/G table */ + if (scp->request_bufflen) + sg_count = hptiop_buildsgl(scp, req->sg_list); + else + HPT_SCP(scp)->mapped = 0; + + req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT); + req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND); + req->header.result = cpu_to_le32(IOP_RESULT_PENDING); + req->header.context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT | + (u32)_req->index); + req->header.context_hi32 = 0; + req->dataxfer_length = cpu_to_le32(scp->request_bufflen); + req->channel = scp->device->channel; + req->target = scp->device->id; + req->lun = scp->device->lun; + req->header.size = cpu_to_le32( + sizeof(struct hpt_iop_request_scsi_command) + - sizeof(struct hpt_iopsg) + + sg_count * sizeof(struct hpt_iopsg)); + + memcpy(req->cdb, scp->cmnd, sizeof(req->cdb)); + + writel(IOPMU_QUEUE_ADDR_HOST_BIT | _req->req_shifted_phy, + &hba->iop->inbound_queue); + + return 0; + +cmd_done: + dprintk("scsi_done(scp=%p)\n", scp); + scp->scsi_done(scp); + return 0; +} + +static const char *hptiop_info(struct Scsi_Host *host) +{ + return driver_name_long; +} + +static int hptiop_reset_hba(struct hptiop_hba *hba) +{ + if (atomic_xchg(&hba->resetting, 1) == 0) { + atomic_inc(&hba->reset_count); + writel(IOPMU_INBOUND_MSG0_RESET, + &hba->iop->inbound_msgaddr0); + hptiop_pci_posting_flush(hba->iop); + } + + wait_event_timeout(hba->reset_wq, + atomic_read(&hba->resetting) == 0, 60 * HZ); + + if (atomic_read(&hba->resetting)) { + /* IOP is in unkown state, abort reset */ + printk(KERN_ERR "scsi%d: reset failed\n", hba->host->host_no); + return -1; + } + + if (iop_send_sync_msg(hba, + IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) { + dprintk("scsi%d: fail to start background task\n", + hba->host->host_no); + } + + return 0; +} + +static int hptiop_reset(struct scsi_cmnd *scp) +{ + struct Scsi_Host * host = scp->device->host; + struct hptiop_hba * hba = (struct hptiop_hba *)host->hostdata; + + printk(KERN_WARNING "hptiop_reset(%d/%d/%d) scp=%p\n", + scp->device->host->host_no, scp->device->channel, + scp->device->id, scp); + + return hptiop_reset_hba(hba)? FAILED : SUCCESS; +} + +static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev, + int queue_depth) +{ + if(queue_depth > 256) + queue_depth = 256; + scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth); + return queue_depth; +} + +static ssize_t hptiop_show_version(struct class_device *class_dev, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s\n", driver_ver); +} + +static ssize_t hptiop_show_fw_version(struct class_device *class_dev, char *buf) +{ + struct Scsi_Host *host = class_to_shost(class_dev); + struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; + + return snprintf(buf, PAGE_SIZE, "%d.%d.%d.%d\n", + hba->firmware_version >> 24, + (hba->firmware_version >> 16) & 0xff, + (hba->firmware_version >> 8) & 0xff, + hba->firmware_version & 0xff); +} + +static struct class_device_attribute hptiop_attr_version = { + .attr = { + .name = "driver-version", + .mode = S_IRUGO, + }, + .show = hptiop_show_version, +}; + +static struct class_device_attribute hptiop_attr_fw_version = { + .attr = { + .name = "firmware-version", + .mode = S_IRUGO, + }, + .show = hptiop_show_fw_version, +}; + +static struct class_device_attribute *hptiop_attrs[] = { + &hptiop_attr_version, + &hptiop_attr_fw_version, + NULL +}; + +static struct scsi_host_template driver_template = { + .module = THIS_MODULE, + .name = driver_name, + .queuecommand = hptiop_queuecommand, + .eh_device_reset_handler = hptiop_reset, + .eh_bus_reset_handler = hptiop_reset, + .info = hptiop_info, + .unchecked_isa_dma = 0, + .emulated = 0, + .use_clustering = ENABLE_CLUSTERING, + .proc_name = driver_name, + .shost_attrs = hptiop_attrs, + .this_id = -1, + .change_queue_depth = hptiop_adjust_disk_queue_depth, +}; + +static int __devinit hptiop_probe(struct pci_dev *pcidev, + const struct pci_device_id *id) +{ + struct Scsi_Host *host = NULL; + struct hptiop_hba *hba; + struct hpt_iop_request_get_config iop_config; + struct hpt_iop_request_set_config set_config; + dma_addr_t start_phy; + void *start_virt; + u32 offset, i, req_size; + + dprintk("hptiop_probe(%p)\n", pcidev); + + if (pci_enable_device(pcidev)) { + printk(KERN_ERR "hptiop: fail to enable pci device\n"); + return -ENODEV; + } + + printk(KERN_INFO "adapter at PCI %d:%d:%d, IRQ %d\n", + pcidev->bus->number, pcidev->devfn >> 3, pcidev->devfn & 7, + pcidev->irq); + + pci_set_master(pcidev); + + /* Enable 64bit DMA if possible */ + if (pci_set_dma_mask(pcidev, DMA_64BIT_MASK)) { + if (pci_set_dma_mask(pcidev, DMA_32BIT_MASK)) { + printk(KERN_ERR "hptiop: fail to set dma_mask\n"); + goto disable_pci_device; + } + } + + if (pci_request_regions(pcidev, driver_name)) { + printk(KERN_ERR "hptiop: pci_request_regions failed\n"); + goto disable_pci_device; + } + + host = scsi_host_alloc(&driver_template, sizeof(struct hptiop_hba)); + if (!host) { + printk(KERN_ERR "hptiop: fail to alloc scsi host\n"); + goto free_pci_regions; + } + + hba = (struct hptiop_hba *)host->hostdata; + + hba->pcidev = pcidev; + hba->host = host; + hba->initialized = 0; + + atomic_set(&hba->resetting, 0); + atomic_set(&hba->reset_count, 0); + + init_waitqueue_head(&hba->reset_wq); + init_waitqueue_head(&hba->ioctl_wq); + + host->max_lun = 1; + host->max_channel = 0; + host->io_port = 0; + host->n_io_port = 0; + host->irq = pcidev->irq; + + if (hptiop_map_pci_bar(hba)) + goto free_scsi_host; + + if (iop_wait_ready(hba->iop, 20000)) { + printk(KERN_ERR "scsi%d: firmware not ready\n", + hba->host->host_no); + goto unmap_pci_bar; + } + + if (iop_get_config(hba, &iop_config)) { + printk(KERN_ERR "scsi%d: get config failed\n", + hba->host->host_no); + goto unmap_pci_bar; + } + + hba->max_requests = min(le32_to_cpu(iop_config.max_requests), + HPTIOP_MAX_REQUESTS); + hba->max_devices = le32_to_cpu(iop_config.max_devices); + hba->max_request_size = le32_to_cpu(iop_config.request_size); + hba->max_sg_descriptors = le32_to_cpu(iop_config.max_sg_count); + hba->firmware_version = le32_to_cpu(iop_config.firmware_version); + hba->sdram_size = le32_to_cpu(iop_config.sdram_size); + + host->max_sectors = le32_to_cpu(iop_config.data_transfer_length) >> 9; + host->max_id = le32_to_cpu(iop_config.max_devices); + host->sg_tablesize = le32_to_cpu(iop_config.max_sg_count); + host->can_queue = le32_to_cpu(iop_config.max_requests); + host->cmd_per_lun = le32_to_cpu(iop_config.max_requests); + host->max_cmd_len = 16; + + set_config.vbus_id = cpu_to_le32(host->host_no); + set_config.iop_id = cpu_to_le32(host->host_no); + + if (iop_set_config(hba, &set_config)) { + printk(KERN_ERR "scsi%d: set config failed\n", + hba->host->host_no); + goto unmap_pci_bar; + } + + pci_set_drvdata(pcidev, host); + + if (request_irq(pcidev->irq, hptiop_intr, IRQF_SHARED, + driver_name, hba)) { + printk(KERN_ERR "scsi%d: request irq %d failed\n", + hba->host->host_no, pcidev->irq); + goto unmap_pci_bar; + } + + /* Allocate request mem */ + req_size = sizeof(struct hpt_iop_request_scsi_command) + + sizeof(struct hpt_iopsg) * (hba->max_sg_descriptors - 1); + if ((req_size& 0x1f) != 0) + req_size = (req_size + 0x1f) & ~0x1f; + + dprintk("req_size=%d, max_requests=%d\n", req_size, hba->max_requests); + + hba->req_size = req_size; + start_virt = dma_alloc_coherent(&pcidev->dev, + hba->req_size*hba->max_requests + 0x20, + &start_phy, GFP_KERNEL); + + if (!start_virt) { + printk(KERN_ERR "scsi%d: fail to alloc request mem\n", + hba->host->host_no); + goto free_request_irq; + } + + hba->dma_coherent = start_virt; + hba->dma_coherent_handle = start_phy; + + if ((start_phy & 0x1f) != 0) + { + offset = ((start_phy + 0x1f) & ~0x1f) - start_phy; + start_phy += offset; + start_virt += offset; + } + + hba->req_list = start_virt; + for (i = 0; i < hba->max_requests; i++) { + hba->reqs[i].next = NULL; + hba->reqs[i].req_virt = start_virt; + hba->reqs[i].req_shifted_phy = start_phy >> 5; + hba->reqs[i].index = i; + free_req(hba, &hba->reqs[i]); + start_virt = (char *)start_virt + hba->req_size; + start_phy = start_phy + hba->req_size; + } + + /* Enable Interrupt and start background task */ + if (hptiop_initialize_iop(hba)) + goto free_request_mem; + + if (scsi_add_host(host, &pcidev->dev)) { + printk(KERN_ERR "scsi%d: scsi_add_host failed\n", + hba->host->host_no); + goto free_request_mem; + } + + + scsi_scan_host(host); + + dprintk("scsi%d: hptiop_probe successfully\n", hba->host->host_no); + return 0; + +free_request_mem: + dma_free_coherent(&hba->pcidev->dev, + hba->req_size*hba->max_requests + 0x20, + hba->dma_coherent, hba->dma_coherent_handle); + +free_request_irq: + free_irq(hba->pcidev->irq, hba); + +unmap_pci_bar: + iounmap(hba->iop); + +free_pci_regions: + pci_release_regions(pcidev) ; + +free_scsi_host: + scsi_host_put(host); + +disable_pci_device: + pci_disable_device(pcidev); + + dprintk("scsi%d: hptiop_probe fail\n", host->host_no); + return -ENODEV; +} + +static void hptiop_shutdown(struct pci_dev *pcidev) +{ + struct Scsi_Host *host = pci_get_drvdata(pcidev); + struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; + struct hpt_iopmu __iomem *iop = hba->iop; + u32 int_mask; + + dprintk("hptiop_shutdown(%p)\n", hba); + + /* stop the iop */ + if (iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_SHUTDOWN, 60000)) + printk(KERN_ERR "scsi%d: shutdown the iop timeout\n", + hba->host->host_no); + + /* disable all outbound interrupts */ + int_mask = readl(&iop->outbound_intmask); + writel(int_mask | + IOPMU_OUTBOUND_INT_MSG0 | IOPMU_OUTBOUND_INT_POSTQUEUE, + &iop->outbound_intmask); + hptiop_pci_posting_flush(iop); +} + +static void hptiop_remove(struct pci_dev *pcidev) +{ + struct Scsi_Host *host = pci_get_drvdata(pcidev); + struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; + + dprintk("scsi%d: hptiop_remove\n", hba->host->host_no); + + scsi_remove_host(host); + + hptiop_shutdown(pcidev); + + free_irq(hba->pcidev->irq, hba); + + dma_free_coherent(&hba->pcidev->dev, + hba->req_size * hba->max_requests + 0x20, + hba->dma_coherent, + hba->dma_coherent_handle); + + iounmap(hba->iop); + + pci_release_regions(hba->pcidev); + pci_set_drvdata(hba->pcidev, NULL); + pci_disable_device(hba->pcidev); + + scsi_host_put(host); +} + +static struct pci_device_id hptiop_id_table[] = { + { PCI_DEVICE(0x1103, 0x3220) }, + { PCI_DEVICE(0x1103, 0x3320) }, + {}, +}; + +MODULE_DEVICE_TABLE(pci, hptiop_id_table); + +static struct pci_driver hptiop_pci_driver = { + .name = driver_name, + .id_table = hptiop_id_table, + .probe = hptiop_probe, + .remove = hptiop_remove, + .shutdown = hptiop_shutdown, +}; + +static int __init hptiop_module_init(void) +{ + printk(KERN_INFO "%s %s\n", driver_name_long, driver_ver); + return pci_register_driver(&hptiop_pci_driver); +} + +static void __exit hptiop_module_exit(void) +{ + pci_unregister_driver(&hptiop_pci_driver); +} + + +module_init(hptiop_module_init); +module_exit(hptiop_module_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/hptiop.h b/drivers/scsi/hptiop.h new file mode 100644 index 000000000..f04f7e81d --- /dev/null +++ b/drivers/scsi/hptiop.h @@ -0,0 +1,465 @@ +/* + * HighPoint RR3xxx controller driver for Linux + * Copyright (C) 2006 HighPoint Technologies, Inc. All Rights Reserved. + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Please report bugs/comments/suggestions to linux@highpoint-tech.com + * + * For more information, visit http://www.highpoint-tech.com + */ +#ifndef _HPTIOP_H_ +#define _HPTIOP_H_ + +/* + * logical device type. + * Identify array (logical device) and physical device. + */ +#define LDT_ARRAY 1 +#define LDT_DEVICE 2 + +/* + * Array types + */ +#define AT_UNKNOWN 0 +#define AT_RAID0 1 +#define AT_RAID1 2 +#define AT_RAID5 3 +#define AT_RAID6 4 +#define AT_JBOD 7 + +#define MAX_NAME_LENGTH 36 +#define MAX_ARRAYNAME_LEN 16 + +#define MAX_ARRAY_MEMBERS_V1 8 +#define MAX_ARRAY_MEMBERS_V2 16 + +/* keep definition for source code compatiblity */ +#define MAX_ARRAY_MEMBERS MAX_ARRAY_MEMBERS_V1 + +/* + * array flags + */ +#define ARRAY_FLAG_DISABLED 0x00000001 /* The array is disabled */ +#define ARRAY_FLAG_NEEDBUILDING 0x00000002 /* need to be rebuilt */ +#define ARRAY_FLAG_REBUILDING 0x00000004 /* in rebuilding process */ +#define ARRAY_FLAG_BROKEN 0x00000008 /* broken but still working */ +#define ARRAY_FLAG_BOOTDISK 0x00000010 /* has a active partition */ +#define ARRAY_FLAG_BOOTMARK 0x00000040 /* array has boot mark set */ +#define ARRAY_FLAG_NEED_AUTOREBUILD 0x00000080 /* auto-rebuild should start */ +#define ARRAY_FLAG_VERIFYING 0x00000100 /* is being verified */ +#define ARRAY_FLAG_INITIALIZING 0x00000200 /* is being initialized */ +#define ARRAY_FLAG_TRANSFORMING 0x00000400 /* tranform in progress */ +#define ARRAY_FLAG_NEEDTRANSFORM 0x00000800 /* array need tranform */ +#define ARRAY_FLAG_NEEDINITIALIZING 0x00001000 /* initialization not done */ +#define ARRAY_FLAG_BROKEN_REDUNDANT 0x00002000 /* broken but redundant */ + +/* + * device flags + */ +#define DEVICE_FLAG_DISABLED 0x00000001 /* device is disabled */ +#define DEVICE_FLAG_UNINITIALIZED 0x00010000 /* device is not initialized */ +#define DEVICE_FLAG_LEGACY 0x00020000 /* lagacy drive */ +#define DEVICE_FLAG_IS_SPARE 0x80000000 /* is a spare disk */ + +/* + * ioctl codes + */ +#define HPT_CTL_CODE(x) (x+0xFF00) +#define HPT_CTL_CODE_LINUX_TO_IOP(x) ((x)-0xff00) + +#define HPT_IOCTL_GET_CONTROLLER_INFO HPT_CTL_CODE(2) +#define HPT_IOCTL_GET_CHANNEL_INFO HPT_CTL_CODE(3) +#define HPT_IOCTL_GET_LOGICAL_DEVICES HPT_CTL_CODE(4) +#define HPT_IOCTL_GET_DRIVER_CAPABILITIES HPT_CTL_CODE(19) +#define HPT_IOCTL_GET_DEVICE_INFO_V3 HPT_CTL_CODE(46) +#define HPT_IOCTL_GET_CONTROLLER_INFO_V2 HPT_CTL_CODE(47) + +/* + * Controller information. + */ +struct hpt_controller_info { + u8 chip_type; /* chip type */ + u8 interrupt_level; /* IRQ level */ + u8 num_buses; /* bus count */ + u8 chip_flags; + + u8 product_id[MAX_NAME_LENGTH];/* product name */ + u8 vendor_id[MAX_NAME_LENGTH]; /* vendor name */ +} +__attribute__((packed)); + +/* + * Channel information. + */ +struct hpt_channel_info { + __le32 io_port; /* IDE Base Port Address */ + __le32 control_port; /* IDE Control Port Address */ + __le32 devices[2]; /* device connected to this channel */ +} +__attribute__((packed)); + +/* + * Array information. + */ +struct hpt_array_info_v3 { + u8 name[MAX_ARRAYNAME_LEN]; /* array name */ + u8 description[64]; /* array description */ + u8 create_manager[16]; /* who created it */ + __le32 create_time; /* when created it */ + + u8 array_type; /* array type */ + u8 block_size_shift; /* stripe size */ + u8 ndisk; /* Number of ID in Members[] */ + u8 reserved; + + __le32 flags; /* working flags, see ARRAY_FLAG_XXX */ + __le32 members[MAX_ARRAY_MEMBERS_V2]; /* member array/disks */ + + __le32 rebuilding_progress; + __le64 rebuilt_sectors; /* rebuilding point (LBA) for single member */ + + __le32 transform_source; + __le32 transform_target; /* destination device ID */ + __le32 transforming_progress; + __le32 signature; /* persistent identification*/ + __le16 critical_members; /* bit mask of critical members */ + __le16 reserve2; + __le32 reserve; +} +__attribute__((packed)); + +/* + * physical device information. + */ +#define MAX_PARENTS_PER_DISK 8 + +struct hpt_device_info_v2 { + u8 ctlr_id; /* controller id */ + u8 path_id; /* bus */ + u8 target_id; /* id */ + u8 device_mode_setting; /* Current Data Transfer mode: 0-4 PIO0-4 */ + /* 5-7 MW DMA0-2, 8-13 UDMA0-5 */ + u8 device_type; /* device type */ + u8 usable_mode; /* highest usable mode */ + +#ifdef __BIG_ENDIAN_BITFIELD + u8 NCQ_enabled: 1; + u8 NCQ_supported: 1; + u8 TCQ_enabled: 1; + u8 TCQ_supported: 1; + u8 write_cache_enabled: 1; + u8 write_cache_supported: 1; + u8 read_ahead_enabled: 1; + u8 read_ahead_supported: 1; + u8 reserved6: 6; + u8 spin_up_mode: 2; +#else + u8 read_ahead_supported: 1; + u8 read_ahead_enabled: 1; + u8 write_cache_supported: 1; + u8 write_cache_enabled: 1; + u8 TCQ_supported: 1; + u8 TCQ_enabled: 1; + u8 NCQ_supported: 1; + u8 NCQ_enabled: 1; + u8 spin_up_mode: 2; + u8 reserved6: 6; +#endif + + __le32 flags; /* working flags, see DEVICE_FLAG_XXX */ + u8 ident[150]; /* (partitial) Identify Data of this device */ + + __le64 total_free; + __le64 max_free; + __le64 bad_sectors; + __le32 parent_arrays[MAX_PARENTS_PER_DISK]; +} +__attribute__((packed)); + +/* + * Logical device information. + */ +#define INVALID_TARGET_ID 0xFF +#define INVALID_BUS_ID 0xFF + +struct hpt_logical_device_info_v3 { + u8 type; /* LDT_ARRAY or LDT_DEVICE */ + u8 cache_policy; /* refer to CACHE_POLICY_xxx */ + u8 vbus_id; /* vbus sequence in vbus_list */ + u8 target_id; /* OS target id. 0xFF is invalid */ + /* OS name: DISK $VBusId_$TargetId */ + __le64 capacity; /* array capacity */ + __le32 parent_array; /* don't use this field for physical + device. use ParentArrays field in + hpt_device_info_v2 */ + /* reserved statistic fields */ + __le32 stat1; + __le32 stat2; + __le32 stat3; + __le32 stat4; + + union { + struct hpt_array_info_v3 array; + struct hpt_device_info_v2 device; + } __attribute__((packed)) u; + +} +__attribute__((packed)); + +/* + * ioctl structure + */ +#define HPT_IOCTL_MAGIC 0xA1B2C3D4 + +struct hpt_ioctl_u { + u32 magic; /* used to check if it's a valid ioctl packet */ + u32 ioctl_code; /* operation control code */ + void __user *inbuf; /* input data buffer */ + u32 inbuf_size; /* size of input data buffer */ + void __user *outbuf; /* output data buffer */ + u32 outbuf_size; /* size of output data buffer */ + void __user *bytes_returned; /* count of bytes returned */ +} +__attribute__((packed)); + + +struct hpt_iopmu +{ + __le32 resrved0[4]; + __le32 inbound_msgaddr0; + __le32 inbound_msgaddr1; + __le32 outbound_msgaddr0; + __le32 outbound_msgaddr1; + __le32 inbound_doorbell; + __le32 inbound_intstatus; + __le32 inbound_intmask; + __le32 outbound_doorbell; + __le32 outbound_intstatus; + __le32 outbound_intmask; + __le32 reserved1[2]; + __le32 inbound_queue; + __le32 outbound_queue; +}; + +#define IOPMU_QUEUE_EMPTY 0xffffffff +#define IOPMU_QUEUE_MASK_HOST_BITS 0xf0000000 +#define IOPMU_QUEUE_ADDR_HOST_BIT 0x80000000 + +#define IOPMU_OUTBOUND_INT_MSG0 1 +#define IOPMU_OUTBOUND_INT_MSG1 2 +#define IOPMU_OUTBOUND_INT_DOORBELL 4 +#define IOPMU_OUTBOUND_INT_POSTQUEUE 8 +#define IOPMU_OUTBOUND_INT_PCI 0x10 + +#define IOPMU_INBOUND_INT_MSG0 1 +#define IOPMU_INBOUND_INT_MSG1 2 +#define IOPMU_INBOUND_INT_DOORBELL 4 +#define IOPMU_INBOUND_INT_ERROR 8 +#define IOPMU_INBOUND_INT_POSTQUEUE 0x10 + +enum hpt_iopmu_message { + /* host-to-iop messages */ + IOPMU_INBOUND_MSG0_NOP = 0, + IOPMU_INBOUND_MSG0_RESET, + IOPMU_INBOUND_MSG0_FLUSH, + IOPMU_INBOUND_MSG0_SHUTDOWN, + IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK, + IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, + IOPMU_INBOUND_MSG0_MAX = 0xff, + /* iop-to-host messages */ + IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_0 = 0x100, + IOPMU_OUTBOUND_MSG0_REGISTER_DEVICE_MAX = 0x1ff, + IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_0 = 0x200, + IOPMU_OUTBOUND_MSG0_UNREGISTER_DEVICE_MAX = 0x2ff, + IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_0 = 0x300, + IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_MAX = 0x3ff, +}; + +struct hpt_iop_request_header +{ + __le32 size; + __le32 type; + __le32 flags; + __le32 result; + __le32 context; /* host context */ + __le32 context_hi32; +}; + +#define IOP_REQUEST_FLAG_SYNC_REQUEST 1 +#define IOP_REQUEST_FLAG_BIST_REQUEST 2 +#define IOP_REQUEST_FLAG_REMAPPED 4 +#define IOP_REQUEST_FLAG_OUTPUT_CONTEXT 8 + +enum hpt_iop_request_type { + IOP_REQUEST_TYPE_GET_CONFIG = 0, + IOP_REQUEST_TYPE_SET_CONFIG, + IOP_REQUEST_TYPE_BLOCK_COMMAND, + IOP_REQUEST_TYPE_SCSI_COMMAND, + IOP_REQUEST_TYPE_IOCTL_COMMAND, + IOP_REQUEST_TYPE_MAX +}; + +enum hpt_iop_result_type { + IOP_RESULT_PENDING = 0, + IOP_RESULT_SUCCESS, + IOP_RESULT_FAIL, + IOP_RESULT_BUSY, + IOP_RESULT_RESET, + IOP_RESULT_INVALID_REQUEST, + IOP_RESULT_BAD_TARGET, + IOP_RESULT_MODE_SENSE_CHECK_CONDITION, +}; + +struct hpt_iop_request_get_config +{ + struct hpt_iop_request_header header; + __le32 interface_version; + __le32 firmware_version; + __le32 max_requests; + __le32 request_size; + __le32 max_sg_count; + __le32 data_transfer_length; + __le32 alignment_mask; + __le32 max_devices; + __le32 sdram_size; +}; + +struct hpt_iop_request_set_config +{ + struct hpt_iop_request_header header; + __le32 iop_id; + __le32 vbus_id; + __le32 reserve[6]; +}; + +struct hpt_iopsg +{ + __le32 size; + __le32 eot; /* non-zero: end of table */ + __le64 pci_address; +}; + +struct hpt_iop_request_block_command +{ + struct hpt_iop_request_header header; + u8 channel; + u8 target; + u8 lun; + u8 pad1; + __le16 command; /* IOP_BLOCK_COMMAND_{READ,WRITE} */ + __le16 sectors; + __le64 lba; + struct hpt_iopsg sg_list[1]; +}; + +#define IOP_BLOCK_COMMAND_READ 1 +#define IOP_BLOCK_COMMAND_WRITE 2 +#define IOP_BLOCK_COMMAND_VERIFY 3 +#define IOP_BLOCK_COMMAND_FLUSH 4 +#define IOP_BLOCK_COMMAND_SHUTDOWN 5 + +struct hpt_iop_request_scsi_command +{ + struct hpt_iop_request_header header; + u8 channel; + u8 target; + u8 lun; + u8 pad1; + u8 cdb[16]; + __le32 dataxfer_length; + struct hpt_iopsg sg_list[1]; +}; + +struct hpt_iop_request_ioctl_command +{ + struct hpt_iop_request_header header; + __le32 ioctl_code; + __le32 inbuf_size; + __le32 outbuf_size; + __le32 bytes_returned; + u8 buf[1]; + /* out data should be put at buf[(inbuf_size+3)&~3] */ +}; + +#define HPTIOP_MAX_REQUESTS 256u + +struct hptiop_request { + struct hptiop_request * next; + void * req_virt; + u32 req_shifted_phy; + struct scsi_cmnd * scp; + int index; +}; + +struct hpt_scsi_pointer { + int mapped; + int sgcnt; + dma_addr_t dma_handle; +}; + +#define HPT_SCP(scp) ((struct hpt_scsi_pointer *)&(scp)->SCp) + +struct hptiop_hba { + struct hpt_iopmu __iomem * iop; + struct Scsi_Host * host; + struct pci_dev * pcidev; + + struct list_head link; + + /* IOP config info */ + u32 firmware_version; + u32 sdram_size; + u32 max_devices; + u32 max_requests; + u32 max_request_size; + u32 max_sg_descriptors; + + u32 req_size; /* host-allocated request buffer size */ + int initialized; + int msg_done; + + struct hptiop_request * req_list; + struct hptiop_request reqs[HPTIOP_MAX_REQUESTS]; + + /* used to free allocated dma area */ + void * dma_coherent; + dma_addr_t dma_coherent_handle; + + atomic_t reset_count; + atomic_t resetting; + + wait_queue_head_t reset_wq; + wait_queue_head_t ioctl_wq; +}; + +struct hpt_ioctl_k +{ + struct hptiop_hba * hba; + u32 ioctl_code; + u32 inbuf_size; + u32 outbuf_size; + void * inbuf; + void * outbuf; + u32 * bytes_returned; + void (*done)(struct hpt_ioctl_k *); + int result; /* HPT_IOCTL_RESULT_ */ +}; + +#define HPT_IOCTL_RESULT_OK 0 +#define HPT_IOCTL_RESULT_FAILED (-1) + +#if 0 +#define dprintk(fmt, args...) do { printk(fmt, ##args); } while(0) +#else +#define dprintk(fmt, args...) +#endif + +#endif diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c new file mode 100644 index 000000000..2c34af996 --- /dev/null +++ b/drivers/scsi/libata-eh.c @@ -0,0 +1,2245 @@ +/* + * libata-eh.c - libata error handling + * + * Maintained by: Jeff Garzik <jgarzik@pobox.com> + * Please ALWAYS copy linux-ide@vger.kernel.org + * on emails. + * + * Copyright 2006 Tejun Heo <htejun@gmail.com> + * + * + * 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, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, + * USA. + * + * + * libata documentation is available via 'make {ps|pdf}docs', + * as Documentation/DocBook/libata.* + * + * Hardware documentation available from http://www.t13.org/ and + * http://www.sata-io.org/ + * + */ + +#include <linux/kernel.h> +#include <scsi/scsi.h> +#include <scsi/scsi_host.h> +#include <scsi/scsi_eh.h> +#include <scsi/scsi_device.h> +#include <scsi/scsi_cmnd.h> +#include "scsi_transport_api.h" + +#include <linux/libata.h> + +#include "libata.h" + +static void __ata_port_freeze(struct ata_port *ap); +static void ata_eh_finish(struct ata_port *ap); +static void ata_eh_handle_port_suspend(struct ata_port *ap); +static void ata_eh_handle_port_resume(struct ata_port *ap); + +static void ata_ering_record(struct ata_ering *ering, int is_io, + unsigned int err_mask) +{ + struct ata_ering_entry *ent; + + WARN_ON(!err_mask); + + ering->cursor++; + ering->cursor %= ATA_ERING_SIZE; + + ent = &ering->ring[ering->cursor]; + ent->is_io = is_io; + ent->err_mask = err_mask; + ent->timestamp = get_jiffies_64(); +} + +static struct ata_ering_entry * ata_ering_top(struct ata_ering *ering) +{ + struct ata_ering_entry *ent = &ering->ring[ering->cursor]; + if (!ent->err_mask) + return NULL; + return ent; +} + +static int ata_ering_map(struct ata_ering *ering, + int (*map_fn)(struct ata_ering_entry *, void *), + void *arg) +{ + int idx, rc = 0; + struct ata_ering_entry *ent; + + idx = ering->cursor; + do { + ent = &ering->ring[idx]; + if (!ent->err_mask) + break; + rc = map_fn(ent, arg); + if (rc) + break; + idx = (idx - 1 + ATA_ERING_SIZE) % ATA_ERING_SIZE; + } while (idx != ering->cursor); + + return rc; +} + +static unsigned int ata_eh_dev_action(struct ata_device *dev) +{ + struct ata_eh_context *ehc = &dev->ap->eh_context; + + return ehc->i.action | ehc->i.dev_action[dev->devno]; +} + +static void ata_eh_clear_action(struct ata_device *dev, + struct ata_eh_info *ehi, unsigned int action) +{ + int i; + + if (!dev) { + ehi->action &= ~action; + for (i = 0; i < ATA_MAX_DEVICES; i++) + ehi->dev_action[i] &= ~action; + } else { + /* doesn't make sense for port-wide EH actions */ + WARN_ON(!(action & ATA_EH_PERDEV_MASK)); + + /* break ehi->action into ehi->dev_action */ + if (ehi->action & action) { + for (i = 0; i < ATA_MAX_DEVICES; i++) + ehi->dev_action[i] |= ehi->action & action; + ehi->action &= ~action; + } + + /* turn off the specified per-dev action */ + ehi->dev_action[dev->devno] &= ~action; + } +} + +/** + * ata_scsi_timed_out - SCSI layer time out callback + * @cmd: timed out SCSI command + * + * Handles SCSI layer timeout. We race with normal completion of + * the qc for @cmd. If the qc is already gone, we lose and let + * the scsi command finish (EH_HANDLED). Otherwise, the qc has + * timed out and EH should be invoked. Prevent ata_qc_complete() + * from finishing it by setting EH_SCHEDULED and return + * EH_NOT_HANDLED. + * + * TODO: kill this function once old EH is gone. + * + * LOCKING: + * Called from timer context + * + * RETURNS: + * EH_HANDLED or EH_NOT_HANDLED + */ +enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) +{ + struct Scsi_Host *host = cmd->device->host; + struct ata_port *ap = ata_shost_to_port(host); + unsigned long flags; + struct ata_queued_cmd *qc; + enum scsi_eh_timer_return ret; + + DPRINTK("ENTER\n"); + + if (ap->ops->error_handler) { + ret = EH_NOT_HANDLED; + goto out; + } + + ret = EH_HANDLED; + spin_lock_irqsave(ap->lock, flags); + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc) { + WARN_ON(qc->scsicmd != cmd); + qc->flags |= ATA_QCFLAG_EH_SCHEDULED; + qc->err_mask |= AC_ERR_TIMEOUT; + ret = EH_NOT_HANDLED; + } + spin_unlock_irqrestore(ap->lock, flags); + + out: + DPRINTK("EXIT, ret=%d\n", ret); + return ret; +} + +/** + * ata_scsi_error - SCSI layer error handler callback + * @host: SCSI host on which error occurred + * + * Handles SCSI-layer-thrown error events. + * + * LOCKING: + * Inherited from SCSI layer (none, can sleep) + * + * RETURNS: + * Zero. + */ +void ata_scsi_error(struct Scsi_Host *host) +{ + struct ata_port *ap = ata_shost_to_port(host); + int i, repeat_cnt = ATA_EH_MAX_REPEAT; + unsigned long flags; + + DPRINTK("ENTER\n"); + + /* synchronize with port task */ + ata_port_flush_task(ap); + + /* synchronize with host_set lock and sort out timeouts */ + + /* For new EH, all qcs are finished in one of three ways - + * normal completion, error completion, and SCSI timeout. + * Both cmpletions can race against SCSI timeout. When normal + * completion wins, the qc never reaches EH. When error + * completion wins, the qc has ATA_QCFLAG_FAILED set. + * + * When SCSI timeout wins, things are a bit more complex. + * Normal or error completion can occur after the timeout but + * before this point. In such cases, both types of + * completions are honored. A scmd is determined to have + * timed out iff its associated qc is active and not failed. + */ + if (ap->ops->error_handler) { + struct scsi_cmnd *scmd, *tmp; + int nr_timedout = 0; + + spin_lock_irqsave(ap->lock, flags); + + list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) { + struct ata_queued_cmd *qc; + + for (i = 0; i < ATA_MAX_QUEUE; i++) { + qc = __ata_qc_from_tag(ap, i); + if (qc->flags & ATA_QCFLAG_ACTIVE && + qc->scsicmd == scmd) + break; + } + + if (i < ATA_MAX_QUEUE) { + /* the scmd has an associated qc */ + if (!(qc->flags & ATA_QCFLAG_FAILED)) { + /* which hasn't failed yet, timeout */ + qc->err_mask |= AC_ERR_TIMEOUT; + qc->flags |= ATA_QCFLAG_FAILED; + nr_timedout++; + } + } else { + /* Normal completion occurred after + * SCSI timeout but before this point. + * Successfully complete it. + */ + scmd->retries = scmd->allowed; + scsi_eh_finish_cmd(scmd, &ap->eh_done_q); + } + } + + /* If we have timed out qcs. They belong to EH from + * this point but the state of the controller is + * unknown. Freeze the port to make sure the IRQ + * handler doesn't diddle with those qcs. This must + * be done atomically w.r.t. setting QCFLAG_FAILED. + */ + if (nr_timedout) + __ata_port_freeze(ap); + + spin_unlock_irqrestore(ap->lock, flags); + } else + spin_unlock_wait(ap->lock); + + repeat: + /* invoke error handler */ + if (ap->ops->error_handler) { + /* process port resume request */ + ata_eh_handle_port_resume(ap); + + /* fetch & clear EH info */ + spin_lock_irqsave(ap->lock, flags); + + memset(&ap->eh_context, 0, sizeof(ap->eh_context)); + ap->eh_context.i = ap->eh_info; + memset(&ap->eh_info, 0, sizeof(ap->eh_info)); + + ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS; + ap->pflags &= ~ATA_PFLAG_EH_PENDING; + + spin_unlock_irqrestore(ap->lock, flags); + + /* invoke EH, skip if unloading or suspended */ + if (!(ap->pflags & (ATA_PFLAG_UNLOADING | ATA_PFLAG_SUSPENDED))) + ap->ops->error_handler(ap); + else + ata_eh_finish(ap); + + /* process port suspend request */ + ata_eh_handle_port_suspend(ap); + + /* Exception might have happend after ->error_handler + * recovered the port but before this point. Repeat + * EH in such case. + */ + spin_lock_irqsave(ap->lock, flags); + + if (ap->pflags & ATA_PFLAG_EH_PENDING) { + if (--repeat_cnt) { + ata_port_printk(ap, KERN_INFO, + "EH pending after completion, " + "repeating EH (cnt=%d)\n", repeat_cnt); + spin_unlock_irqrestore(ap->lock, flags); + goto repeat; + } + ata_port_printk(ap, KERN_ERR, "EH pending after %d " + "tries, giving up\n", ATA_EH_MAX_REPEAT); + } + + /* this run is complete, make sure EH info is clear */ + memset(&ap->eh_info, 0, sizeof(ap->eh_info)); + + /* Clear host_eh_scheduled while holding ap->lock such + * that if exception occurs after this point but + * before EH completion, SCSI midlayer will + * re-initiate EH. + */ + host->host_eh_scheduled = 0; + + spin_unlock_irqrestore(ap->lock, flags); + } else { + WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL); + ap->ops->eng_timeout(ap); + } + + /* finish or retry handled scmd's and clean up */ + WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q)); + + scsi_eh_flush_done_q(&ap->eh_done_q); + + /* clean up */ + spin_lock_irqsave(ap->lock, flags); + + if (ap->pflags & ATA_PFLAG_LOADING) + ap->pflags &= ~ATA_PFLAG_LOADING; + else if (ap->pflags & ATA_PFLAG_SCSI_HOTPLUG) + queue_work(ata_aux_wq, &ap->hotplug_task); + + if (ap->pflags & ATA_PFLAG_RECOVERED) + ata_port_printk(ap, KERN_INFO, "EH complete\n"); + + ap->pflags &= ~(ATA_PFLAG_SCSI_HOTPLUG | ATA_PFLAG_RECOVERED); + + /* tell wait_eh that we're done */ + ap->pflags &= ~ATA_PFLAG_EH_IN_PROGRESS; + wake_up_all(&ap->eh_wait_q); + + spin_unlock_irqrestore(ap->lock, flags); + + DPRINTK("EXIT\n"); +} + +/** + * ata_port_wait_eh - Wait for the currently pending EH to complete + * @ap: Port to wait EH for + * + * Wait until the currently pending EH is complete. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +void ata_port_wait_eh(struct ata_port *ap) +{ + unsigned long flags; + DEFINE_WAIT(wait); + + retry: + spin_lock_irqsave(ap->lock, flags); + + while (ap->pflags & (ATA_PFLAG_EH_PENDING | ATA_PFLAG_EH_IN_PROGRESS)) { + prepare_to_wait(&ap->eh_wait_q, &wait, TASK_UNINTERRUPTIBLE); + spin_unlock_irqrestore(ap->lock, flags); + schedule(); + spin_lock_irqsave(ap->lock, flags); + } + finish_wait(&ap->eh_wait_q, &wait); + + spin_unlock_irqrestore(ap->lock, flags); + + /* make sure SCSI EH is complete */ + if (scsi_host_in_recovery(ap->host)) { + msleep(10); + goto retry; + } +} + +/** + * ata_qc_timeout - Handle timeout of queued command + * @qc: Command that timed out + * + * Some part of the kernel (currently, only the SCSI layer) + * has noticed that the active command on port @ap has not + * completed after a specified length of time. Handle this + * condition by disabling DMA (if necessary) and completing + * transactions, with error if necessary. + * + * This also handles the case of the "lost interrupt", where + * for some reason (possibly hardware bug, possibly driver bug) + * an interrupt was not delivered to the driver, even though the + * transaction completed successfully. + * + * TODO: kill this function once old EH is gone. + * + * LOCKING: + * Inherited from SCSI layer (none, can sleep) + */ +static void ata_qc_timeout(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + u8 host_stat = 0, drv_stat; + unsigned long flags; + + DPRINTK("ENTER\n"); + + ap->hsm_task_state = HSM_ST_IDLE; + + spin_lock_irqsave(ap->lock, flags); + + switch (qc->tf.protocol) { + + case ATA_PROT_DMA: + case ATA_PROT_ATAPI_DMA: + host_stat = ap->ops->bmdma_status(ap); + + /* before we do anything else, clear DMA-Start bit */ + ap->ops->bmdma_stop(qc); + + /* fall through */ + + default: + ata_altstatus(ap); + drv_stat = ata_chk_status(ap); + + /* ack bmdma irq events */ + ap->ops->irq_clear(ap); + + ata_dev_printk(qc->dev, KERN_ERR, "command 0x%x timeout, " + "stat 0x%x host_stat 0x%x\n", + qc->tf.command, drv_stat, host_stat); + + /* complete taskfile transaction */ + qc->err_mask |= AC_ERR_TIMEOUT; + break; + } + + spin_unlock_irqrestore(ap->lock, flags); + + ata_eh_qc_complete(qc); + + DPRINTK("EXIT\n"); +} + +/** + * ata_eng_timeout - Handle timeout of queued command + * @ap: Port on which timed-out command is active + * + * Some part of the kernel (currently, only the SCSI layer) + * has noticed that the active command on port @ap has not + * completed after a specified length of time. Handle this + * condition by disabling DMA (if necessary) and completing + * transactions, with error if necessary. + * + * This also handles the case of the "lost interrupt", where + * for some reason (possibly hardware bug, possibly driver bug) + * an interrupt was not delivered to the driver, even though the + * transaction completed successfully. + * + * TODO: kill this function once old EH is gone. + * + * LOCKING: + * Inherited from SCSI layer (none, can sleep) + */ +void ata_eng_timeout(struct ata_port *ap) +{ + DPRINTK("ENTER\n"); + + ata_qc_timeout(ata_qc_from_tag(ap, ap->active_tag)); + + DPRINTK("EXIT\n"); +} + +/** + * ata_qc_schedule_eh - schedule qc for error handling + * @qc: command to schedule error handling for + * + * Schedule error handling for @qc. EH will kick in as soon as + * other commands are drained. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +void ata_qc_schedule_eh(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + + WARN_ON(!ap->ops->error_handler); + + qc->flags |= ATA_QCFLAG_FAILED; + qc->ap->pflags |= ATA_PFLAG_EH_PENDING; + + /* The following will fail if timeout has already expired. + * ata_scsi_error() takes care of such scmds on EH entry. + * Note that ATA_QCFLAG_FAILED is unconditionally set after + * this function completes. + */ + scsi_req_abort_cmd(qc->scsicmd); +} + +/** + * ata_port_schedule_eh - schedule error handling without a qc + * @ap: ATA port to schedule EH for + * + * Schedule error handling for @ap. EH will kick in as soon as + * all commands are drained. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +void ata_port_schedule_eh(struct ata_port *ap) +{ + WARN_ON(!ap->ops->error_handler); + + ap->pflags |= ATA_PFLAG_EH_PENDING; + scsi_schedule_eh(ap->host); + + DPRINTK("port EH scheduled\n"); +} + +/** + * ata_port_abort - abort all qc's on the port + * @ap: ATA port to abort qc's for + * + * Abort all active qc's of @ap and schedule EH. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * Number of aborted qc's. + */ +int ata_port_abort(struct ata_port *ap) +{ + int tag, nr_aborted = 0; + + WARN_ON(!ap->ops->error_handler); + + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag); + + if (qc) { + qc->flags |= ATA_QCFLAG_FAILED; + ata_qc_complete(qc); + nr_aborted++; + } + } + + if (!nr_aborted) + ata_port_schedule_eh(ap); + + return nr_aborted; +} + +/** + * __ata_port_freeze - freeze port + * @ap: ATA port to freeze + * + * This function is called when HSM violation or some other + * condition disrupts normal operation of the port. Frozen port + * is not allowed to perform any operation until the port is + * thawed, which usually follows a successful reset. + * + * ap->ops->freeze() callback can be used for freezing the port + * hardware-wise (e.g. mask interrupt and stop DMA engine). If a + * port cannot be frozen hardware-wise, the interrupt handler + * must ack and clear interrupts unconditionally while the port + * is frozen. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +static void __ata_port_freeze(struct ata_port *ap) +{ + WARN_ON(!ap->ops->error_handler); + + if (ap->ops->freeze) + ap->ops->freeze(ap); + + ap->pflags |= ATA_PFLAG_FROZEN; + + DPRINTK("ata%u port frozen\n", ap->id); +} + +/** + * ata_port_freeze - abort & freeze port + * @ap: ATA port to freeze + * + * Abort and freeze @ap. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * Number of aborted commands. + */ +int ata_port_freeze(struct ata_port *ap) +{ + int nr_aborted; + + WARN_ON(!ap->ops->error_handler); + + nr_aborted = ata_port_abort(ap); + __ata_port_freeze(ap); + + return nr_aborted; +} + +/** + * ata_eh_freeze_port - EH helper to freeze port + * @ap: ATA port to freeze + * + * Freeze @ap. + * + * LOCKING: + * None. + */ +void ata_eh_freeze_port(struct ata_port *ap) +{ + unsigned long flags; + + if (!ap->ops->error_handler) + return; + + spin_lock_irqsave(ap->lock, flags); + __ata_port_freeze(ap); + spin_unlock_irqrestore(ap->lock, flags); +} + +/** + * ata_port_thaw_port - EH helper to thaw port + * @ap: ATA port to thaw + * + * Thaw frozen port @ap. + * + * LOCKING: + * None. + */ +void ata_eh_thaw_port(struct ata_port *ap) +{ + unsigned long flags; + + if (!ap->ops->error_handler) + return; + + spin_lock_irqsave(ap->lock, flags); + + ap->pflags &= ~ATA_PFLAG_FROZEN; + + if (ap->ops->thaw) + ap->ops->thaw(ap); + + spin_unlock_irqrestore(ap->lock, flags); + + DPRINTK("ata%u port thawed\n", ap->id); +} + +static void ata_eh_scsidone(struct scsi_cmnd *scmd) +{ + /* nada */ +} + +static void __ata_eh_qc_complete(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct scsi_cmnd *scmd = qc->scsicmd; + unsigned long flags; + + spin_lock_irqsave(ap->lock, flags); + qc->scsidone = ata_eh_scsidone; + __ata_qc_complete(qc); + WARN_ON(ata_tag_valid(qc->tag)); + spin_unlock_irqrestore(ap->lock, flags); + + scsi_eh_finish_cmd(scmd, &ap->eh_done_q); +} + +/** + * ata_eh_qc_complete - Complete an active ATA command from EH + * @qc: Command to complete + * + * Indicate to the mid and upper layers that an ATA command has + * completed. To be used from EH. + */ +void ata_eh_qc_complete(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + scmd->retries = scmd->allowed; + __ata_eh_qc_complete(qc); +} + +/** + * ata_eh_qc_retry - Tell midlayer to retry an ATA command after EH + * @qc: Command to retry + * + * Indicate to the mid and upper layers that an ATA command + * should be retried. To be used from EH. + * + * SCSI midlayer limits the number of retries to scmd->allowed. + * scmd->retries is decremented for commands which get retried + * due to unrelated failures (qc->err_mask is zero). + */ +void ata_eh_qc_retry(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + if (!qc->err_mask && scmd->retries) + scmd->retries--; + __ata_eh_qc_complete(qc); +} + +/** + * ata_eh_detach_dev - detach ATA device + * @dev: ATA device to detach + * + * Detach @dev. + * + * LOCKING: + * None. + */ +static void ata_eh_detach_dev(struct ata_device *dev) +{ + struct ata_port *ap = dev->ap; + unsigned long flags; + + ata_dev_disable(dev); + + spin_lock_irqsave(ap->lock, flags); + + dev->flags &= ~ATA_DFLAG_DETACH; + + if (ata_scsi_offline_dev(dev)) { + dev->flags |= ATA_DFLAG_DETACHED; + ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; + } + + /* clear per-dev EH actions */ + ata_eh_clear_action(dev, &ap->eh_info, ATA_EH_PERDEV_MASK); + ata_eh_clear_action(dev, &ap->eh_context.i, ATA_EH_PERDEV_MASK); + + spin_unlock_irqrestore(ap->lock, flags); +} + +/** + * ata_eh_about_to_do - about to perform eh_action + * @ap: target ATA port + * @dev: target ATA dev for per-dev action (can be NULL) + * @action: action about to be performed + * + * Called just before performing EH actions to clear related bits + * in @ap->eh_info such that eh actions are not unnecessarily + * repeated. + * + * LOCKING: + * None. + */ +static void ata_eh_about_to_do(struct ata_port *ap, struct ata_device *dev, + unsigned int action) +{ + unsigned long flags; + struct ata_eh_info *ehi = &ap->eh_info; + struct ata_eh_context *ehc = &ap->eh_context; + + spin_lock_irqsave(ap->lock, flags); + + /* Reset is represented by combination of actions and EHI + * flags. Suck in all related bits before clearing eh_info to + * avoid losing requested action. + */ + if (action & ATA_EH_RESET_MASK) { + ehc->i.action |= ehi->action & ATA_EH_RESET_MASK; + ehc->i.flags |= ehi->flags & ATA_EHI_RESET_MODIFIER_MASK; + + /* make sure all reset actions are cleared & clear EHI flags */ + action |= ATA_EH_RESET_MASK; + ehi->flags &= ~ATA_EHI_RESET_MODIFIER_MASK; + } + + ata_eh_clear_action(dev, ehi, action); + + if (!(ehc->i.flags & ATA_EHI_QUIET)) + ap->pflags |= ATA_PFLAG_RECOVERED; + + spin_unlock_irqrestore(ap->lock, flags); +} + +/** + * ata_eh_done - EH action complete + * @ap: target ATA port + * @dev: target ATA dev for per-dev action (can be NULL) + * @action: action just completed + * + * Called right after performing EH actions to clear related bits + * in @ap->eh_context. + * + * LOCKING: + * None. + */ +static void ata_eh_done(struct ata_port *ap, struct ata_device *dev, + unsigned int action) +{ + /* if reset is complete, clear all reset actions & reset modifier */ + if (action & ATA_EH_RESET_MASK) { + action |= ATA_EH_RESET_MASK; + ap->eh_context.i.flags &= ~ATA_EHI_RESET_MODIFIER_MASK; + } + + ata_eh_clear_action(dev, &ap->eh_context.i, action); +} + +/** + * ata_err_string - convert err_mask to descriptive string + * @err_mask: error mask to convert to string + * + * Convert @err_mask to descriptive string. Errors are + * prioritized according to severity and only the most severe + * error is reported. + * + * LOCKING: + * None. + * + * RETURNS: + * Descriptive string for @err_mask + */ +static const char * ata_err_string(unsigned int err_mask) +{ + if (err_mask & AC_ERR_HOST_BUS) + return "host bus error"; + if (err_mask & AC_ERR_ATA_BUS) + return "ATA bus error"; + if (err_mask & AC_ERR_TIMEOUT) + return "timeout"; + if (err_mask & AC_ERR_HSM) + return "HSM violation"; + if (err_mask & AC_ERR_SYSTEM) + return "internal error"; + if (err_mask & AC_ERR_MEDIA) + return "media error"; + if (err_mask & AC_ERR_INVALID) + return "invalid argument"; + if (err_mask & AC_ERR_DEV) + return "device error"; + return "unknown error"; +} + +/** + * ata_read_log_page - read a specific log page + * @dev: target device + * @page: page to read + * @buf: buffer to store read page + * @sectors: number of sectors to read + * + * Read log page using READ_LOG_EXT command. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, AC_ERR_* mask otherwise. + */ +static unsigned int ata_read_log_page(struct ata_device *dev, + u8 page, void *buf, unsigned int sectors) +{ + struct ata_taskfile tf; + unsigned int err_mask; + + DPRINTK("read log page - page %d\n", page); + + ata_tf_init(dev, &tf); + tf.command = ATA_CMD_READ_LOG_EXT; + tf.lbal = page; + tf.nsect = sectors; + tf.hob_nsect = sectors >> 8; + tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_LBA48 | ATA_TFLAG_DEVICE; + tf.protocol = ATA_PROT_PIO; + + err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE, + buf, sectors * ATA_SECT_SIZE); + + DPRINTK("EXIT, err_mask=%x\n", err_mask); + return err_mask; +} + +/** + * ata_eh_read_log_10h - Read log page 10h for NCQ error details + * @dev: Device to read log page 10h from + * @tag: Resulting tag of the failed command + * @tf: Resulting taskfile registers of the failed command + * + * Read log page 10h to obtain NCQ error details and clear error + * condition. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, -errno otherwise. + */ +static int ata_eh_read_log_10h(struct ata_device *dev, + int *tag, struct ata_taskfile *tf) +{ + u8 *buf = dev->ap->sector_buf; + unsigned int err_mask; + u8 csum; + int i; + + err_mask = ata_read_log_page(dev, ATA_LOG_SATA_NCQ, buf, 1); + if (err_mask) + return -EIO; + + csum = 0; + for (i = 0; i < ATA_SECT_SIZE; i++) + csum += buf[i]; + if (csum) + ata_dev_printk(dev, KERN_WARNING, + "invalid checksum 0x%x on log page 10h\n", csum); + + if (buf[0] & 0x80) + return -ENOENT; + + *tag = buf[0] & 0x1f; + + tf->command = buf[2]; + tf->feature = buf[3]; + tf->lbal = buf[4]; + tf->lbam = buf[5]; + tf->lbah = buf[6]; + tf->device = buf[7]; + tf->hob_lbal = buf[8]; + tf->hob_lbam = buf[9]; + tf->hob_lbah = buf[10]; + tf->nsect = buf[12]; + tf->hob_nsect = buf[13]; + + return 0; +} + +/** + * atapi_eh_request_sense - perform ATAPI REQUEST_SENSE + * @dev: device to perform REQUEST_SENSE to + * @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long) + * + * Perform ATAPI REQUEST_SENSE after the device reported CHECK + * SENSE. This function is EH helper. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, AC_ERR_* mask on failure + */ +static unsigned int atapi_eh_request_sense(struct ata_device *dev, + unsigned char *sense_buf) +{ + struct ata_port *ap = dev->ap; + struct ata_taskfile tf; + u8 cdb[ATAPI_CDB_LEN]; + + DPRINTK("ATAPI request sense\n"); + + ata_tf_init(dev, &tf); + + /* FIXME: is this needed? */ + memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE); + + /* XXX: why tf_read here? */ + ap->ops->tf_read(ap, &tf); + + /* fill these in, for the case where they are -not- overwritten */ + sense_buf[0] = 0x70; + sense_buf[2] = tf.feature >> 4; + + memset(cdb, 0, ATAPI_CDB_LEN); + cdb[0] = REQUEST_SENSE; + cdb[4] = SCSI_SENSE_BUFFERSIZE; + + tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + tf.command = ATA_CMD_PACKET; + + /* is it pointless to prefer PIO for "safety reasons"? */ + if (ap->flags & ATA_FLAG_PIO_DMA) { + tf.protocol = ATA_PROT_ATAPI_DMA; + tf.feature |= ATAPI_PKT_DMA; + } else { + tf.protocol = ATA_PROT_ATAPI; + tf.lbam = (8 * 1024) & 0xff; + tf.lbah = (8 * 1024) >> 8; + } + + return ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE, + sense_buf, SCSI_SENSE_BUFFERSIZE); +} + +/** + * ata_eh_analyze_serror - analyze SError for a failed port + * @ap: ATA port to analyze SError for + * + * Analyze SError if available and further determine cause of + * failure. + * + * LOCKING: + * None. + */ +static void ata_eh_analyze_serror(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + u32 serror = ehc->i.serror; + unsigned int err_mask = 0, action = 0; + + if (serror & SERR_PERSISTENT) { + err_mask |= AC_ERR_ATA_BUS; + action |= ATA_EH_HARDRESET; + } + if (serror & + (SERR_DATA_RECOVERED | SERR_COMM_RECOVERED | SERR_DATA)) { + err_mask |= AC_ERR_ATA_BUS; + action |= ATA_EH_SOFTRESET; + } + if (serror & SERR_PROTOCOL) { + err_mask |= AC_ERR_HSM; + action |= ATA_EH_SOFTRESET; + } + if (serror & SERR_INTERNAL) { + err_mask |= AC_ERR_SYSTEM; + action |= ATA_EH_SOFTRESET; + } + if (serror & (SERR_PHYRDY_CHG | SERR_DEV_XCHG)) + ata_ehi_hotplugged(&ehc->i); + + ehc->i.err_mask |= err_mask; + ehc->i.action |= action; +} + +/** + * ata_eh_analyze_ncq_error - analyze NCQ error + * @ap: ATA port to analyze NCQ error for + * + * Read log page 10h, determine the offending qc and acquire + * error status TF. For NCQ device errors, all LLDDs have to do + * is setting AC_ERR_DEV in ehi->err_mask. This function takes + * care of the rest. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +static void ata_eh_analyze_ncq_error(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + struct ata_device *dev = ap->device; + struct ata_queued_cmd *qc; + struct ata_taskfile tf; + int tag, rc; + + /* if frozen, we can't do much */ + if (ap->pflags & ATA_PFLAG_FROZEN) + return; + + /* is it NCQ device error? */ + if (!ap->sactive || !(ehc->i.err_mask & AC_ERR_DEV)) + return; + + /* has LLDD analyzed already? */ + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + qc = __ata_qc_from_tag(ap, tag); + + if (!(qc->flags & ATA_QCFLAG_FAILED)) + continue; + + if (qc->err_mask) + return; + } + + /* okay, this error is ours */ + rc = ata_eh_read_log_10h(dev, &tag, &tf); + if (rc) { + ata_port_printk(ap, KERN_ERR, "failed to read log page 10h " + "(errno=%d)\n", rc); + return; + } + + if (!(ap->sactive & (1 << tag))) { + ata_port_printk(ap, KERN_ERR, "log page 10h reported " + "inactive tag %d\n", tag); + return; + } + + /* we've got the perpetrator, condemn it */ + qc = __ata_qc_from_tag(ap, tag); + memcpy(&qc->result_tf, &tf, sizeof(tf)); + qc->err_mask |= AC_ERR_DEV; + ehc->i.err_mask &= ~AC_ERR_DEV; +} + +/** + * ata_eh_analyze_tf - analyze taskfile of a failed qc + * @qc: qc to analyze + * @tf: Taskfile registers to analyze + * + * Analyze taskfile of @qc and further determine cause of + * failure. This function also requests ATAPI sense data if + * avaliable. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * Determined recovery action + */ +static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, + const struct ata_taskfile *tf) +{ + unsigned int tmp, action = 0; + u8 stat = tf->command, err = tf->feature; + + if ((stat & (ATA_BUSY | ATA_DRQ | ATA_DRDY)) != ATA_DRDY) { + qc->err_mask |= AC_ERR_HSM; + return ATA_EH_SOFTRESET; + } + + if (!(qc->err_mask & AC_ERR_DEV)) + return 0; + + switch (qc->dev->class) { + case ATA_DEV_ATA: + if (err & ATA_ICRC) + qc->err_mask |= AC_ERR_ATA_BUS; + if (err & ATA_UNC) + qc->err_mask |= AC_ERR_MEDIA; + if (err & ATA_IDNF) + qc->err_mask |= AC_ERR_INVALID; + break; + + case ATA_DEV_ATAPI: + tmp = atapi_eh_request_sense(qc->dev, + qc->scsicmd->sense_buffer); + if (!tmp) { + /* ATA_QCFLAG_SENSE_VALID is used to tell + * atapi_qc_complete() that sense data is + * already valid. + * + * TODO: interpret sense data and set + * appropriate err_mask. + */ + qc->flags |= ATA_QCFLAG_SENSE_VALID; + } else + qc->err_mask |= tmp; + } + + if (qc->err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT | AC_ERR_ATA_BUS)) + action |= ATA_EH_SOFTRESET; + + return action; +} + +static int ata_eh_categorize_ering_entry(struct ata_ering_entry *ent) +{ + if (ent->err_mask & (AC_ERR_ATA_BUS | AC_ERR_TIMEOUT)) + return 1; + + if (ent->is_io) { + if (ent->err_mask & AC_ERR_HSM) + return 1; + if ((ent->err_mask & + (AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV) + return 2; + } + + return 0; +} + +struct speed_down_needed_arg { + u64 since; + int nr_errors[3]; +}; + +static int speed_down_needed_cb(struct ata_ering_entry *ent, void *void_arg) +{ + struct speed_down_needed_arg *arg = void_arg; + + if (ent->timestamp < arg->since) + return -1; + + arg->nr_errors[ata_eh_categorize_ering_entry(ent)]++; + return 0; +} + +/** + * ata_eh_speed_down_needed - Determine wheter speed down is necessary + * @dev: Device of interest + * + * This function examines error ring of @dev and determines + * whether speed down is necessary. Speed down is necessary if + * there have been more than 3 of Cat-1 errors or 10 of Cat-2 + * errors during last 15 minutes. + * + * Cat-1 errors are ATA_BUS, TIMEOUT for any command and HSM + * violation for known supported commands. + * + * Cat-2 errors are unclassified DEV error for known supported + * command. + * + * LOCKING: + * Inherited from caller. + * + * RETURNS: + * 1 if speed down is necessary, 0 otherwise + */ +static int ata_eh_speed_down_needed(struct ata_device *dev) +{ + const u64 interval = 15LLU * 60 * HZ; + static const int err_limits[3] = { -1, 3, 10 }; + struct speed_down_needed_arg arg; + struct ata_ering_entry *ent; + int err_cat; + u64 j64; + + ent = ata_ering_top(&dev->ering); + if (!ent) + return 0; + + err_cat = ata_eh_categorize_ering_entry(ent); + if (err_cat == 0) + return 0; + + memset(&arg, 0, sizeof(arg)); + + j64 = get_jiffies_64(); + if (j64 >= interval) + arg.since = j64 - interval; + else + arg.since = 0; + + ata_ering_map(&dev->ering, speed_down_needed_cb, &arg); + + return arg.nr_errors[err_cat] > err_limits[err_cat]; +} + +/** + * ata_eh_speed_down - record error and speed down if necessary + * @dev: Failed device + * @is_io: Did the device fail during normal IO? + * @err_mask: err_mask of the error + * + * Record error and examine error history to determine whether + * adjusting transmission speed is necessary. It also sets + * transmission limits appropriately if such adjustment is + * necessary. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, -errno otherwise + */ +static int ata_eh_speed_down(struct ata_device *dev, int is_io, + unsigned int err_mask) +{ + if (!err_mask) + return 0; + + /* record error and determine whether speed down is necessary */ + ata_ering_record(&dev->ering, is_io, err_mask); + + if (!ata_eh_speed_down_needed(dev)) + return 0; + + /* speed down SATA link speed if possible */ + if (sata_down_spd_limit(dev->ap) == 0) + return ATA_EH_HARDRESET; + + /* lower transfer mode */ + if (ata_down_xfermask_limit(dev, 0) == 0) + return ATA_EH_SOFTRESET; + + ata_dev_printk(dev, KERN_ERR, + "speed down requested but no transfer mode left\n"); + return 0; +} + +/** + * ata_eh_autopsy - analyze error and determine recovery action + * @ap: ATA port to perform autopsy on + * + * Analyze why @ap failed and determine which recovery action is + * needed. This function also sets more detailed AC_ERR_* values + * and fills sense data for ATAPI CHECK SENSE. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +static void ata_eh_autopsy(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + unsigned int all_err_mask = 0; + int tag, is_io = 0; + u32 serror; + int rc; + + DPRINTK("ENTER\n"); + + if (ehc->i.flags & ATA_EHI_NO_AUTOPSY) + return; + + /* obtain and analyze SError */ + rc = sata_scr_read(ap, SCR_ERROR, &serror); + if (rc == 0) { + ehc->i.serror |= serror; + ata_eh_analyze_serror(ap); + } else if (rc != -EOPNOTSUPP) + ehc->i.action |= ATA_EH_HARDRESET; + + /* analyze NCQ failure */ + ata_eh_analyze_ncq_error(ap); + + /* any real error trumps AC_ERR_OTHER */ + if (ehc->i.err_mask & ~AC_ERR_OTHER) + ehc->i.err_mask &= ~AC_ERR_OTHER; + + all_err_mask |= ehc->i.err_mask; + + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); + + if (!(qc->flags & ATA_QCFLAG_FAILED)) + continue; + + /* inherit upper level err_mask */ + qc->err_mask |= ehc->i.err_mask; + + /* analyze TF */ + ehc->i.action |= ata_eh_analyze_tf(qc, &qc->result_tf); + + /* DEV errors are probably spurious in case of ATA_BUS error */ + if (qc->err_mask & AC_ERR_ATA_BUS) + qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_MEDIA | + AC_ERR_INVALID); + + /* any real error trumps unknown error */ + if (qc->err_mask & ~AC_ERR_OTHER) + qc->err_mask &= ~AC_ERR_OTHER; + + /* SENSE_VALID trumps dev/unknown error and revalidation */ + if (qc->flags & ATA_QCFLAG_SENSE_VALID) { + qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER); + ehc->i.action &= ~ATA_EH_REVALIDATE; + } + + /* accumulate error info */ + ehc->i.dev = qc->dev; + all_err_mask |= qc->err_mask; + if (qc->flags & ATA_QCFLAG_IO) + is_io = 1; + } + + /* enforce default EH actions */ + if (ap->pflags & ATA_PFLAG_FROZEN || + all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT)) + ehc->i.action |= ATA_EH_SOFTRESET; + else if (all_err_mask) + ehc->i.action |= ATA_EH_REVALIDATE; + + /* if we have offending qcs and the associated failed device */ + if (ehc->i.dev) { + /* speed down */ + ehc->i.action |= ata_eh_speed_down(ehc->i.dev, is_io, + all_err_mask); + + /* perform per-dev EH action only on the offending device */ + ehc->i.dev_action[ehc->i.dev->devno] |= + ehc->i.action & ATA_EH_PERDEV_MASK; + ehc->i.action &= ~ATA_EH_PERDEV_MASK; + } + + DPRINTK("EXIT\n"); +} + +/** + * ata_eh_report - report error handling to user + * @ap: ATA port EH is going on + * + * Report EH to user. + * + * LOCKING: + * None. + */ +static void ata_eh_report(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + const char *frozen, *desc; + int tag, nr_failed = 0; + + desc = NULL; + if (ehc->i.desc[0] != '\0') + desc = ehc->i.desc; + + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); + + if (!(qc->flags & ATA_QCFLAG_FAILED)) + continue; + if (qc->flags & ATA_QCFLAG_SENSE_VALID && !qc->err_mask) + continue; + + nr_failed++; + } + + if (!nr_failed && !ehc->i.err_mask) + return; + + frozen = ""; + if (ap->pflags & ATA_PFLAG_FROZEN) + frozen = " frozen"; + + if (ehc->i.dev) { + ata_dev_printk(ehc->i.dev, KERN_ERR, "exception Emask 0x%x " + "SAct 0x%x SErr 0x%x action 0x%x%s\n", + ehc->i.err_mask, ap->sactive, ehc->i.serror, + ehc->i.action, frozen); + if (desc) + ata_dev_printk(ehc->i.dev, KERN_ERR, "(%s)\n", desc); + } else { + ata_port_printk(ap, KERN_ERR, "exception Emask 0x%x " + "SAct 0x%x SErr 0x%x action 0x%x%s\n", + ehc->i.err_mask, ap->sactive, ehc->i.serror, + ehc->i.action, frozen); + if (desc) + ata_port_printk(ap, KERN_ERR, "(%s)\n", desc); + } + + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); + + if (!(qc->flags & ATA_QCFLAG_FAILED) || !qc->err_mask) + continue; + + ata_dev_printk(qc->dev, KERN_ERR, "tag %d cmd 0x%x " + "Emask 0x%x stat 0x%x err 0x%x (%s)\n", + qc->tag, qc->tf.command, qc->err_mask, + qc->result_tf.command, qc->result_tf.feature, + ata_err_string(qc->err_mask)); + } +} + +static int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, + unsigned int *classes) +{ + int i, rc; + + for (i = 0; i < ATA_MAX_DEVICES; i++) + classes[i] = ATA_DEV_UNKNOWN; + + rc = reset(ap, classes); + if (rc) + return rc; + + /* If any class isn't ATA_DEV_UNKNOWN, consider classification + * is complete and convert all ATA_DEV_UNKNOWN to + * ATA_DEV_NONE. + */ + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (classes[i] != ATA_DEV_UNKNOWN) + break; + + if (i < ATA_MAX_DEVICES) + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (classes[i] == ATA_DEV_UNKNOWN) + classes[i] = ATA_DEV_NONE; + + return 0; +} + +static int ata_eh_followup_srst_needed(int rc, int classify, + const unsigned int *classes) +{ + if (rc == -EAGAIN) + return 1; + if (rc != 0) + return 0; + if (classify && classes[0] == ATA_DEV_UNKNOWN) + return 1; + return 0; +} + +static int ata_eh_reset(struct ata_port *ap, int classify, + ata_prereset_fn_t prereset, ata_reset_fn_t softreset, + ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) +{ + struct ata_eh_context *ehc = &ap->eh_context; + unsigned int *classes = ehc->classes; + int tries = ATA_EH_RESET_TRIES; + int verbose = !(ehc->i.flags & ATA_EHI_QUIET); + unsigned int action; + ata_reset_fn_t reset; + int i, did_followup_srst, rc; + + /* about to reset */ + ata_eh_about_to_do(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK); + + /* Determine which reset to use and record in ehc->i.action. + * prereset() may examine and modify it. + */ + action = ehc->i.action; + ehc->i.action &= ~ATA_EH_RESET_MASK; + if (softreset && (!hardreset || (!sata_set_spd_needed(ap) && + !(action & ATA_EH_HARDRESET)))) + ehc->i.action |= ATA_EH_SOFTRESET; + else + ehc->i.action |= ATA_EH_HARDRESET; + + if (prereset) { + rc = prereset(ap); + if (rc) { + ata_port_printk(ap, KERN_ERR, + "prereset failed (errno=%d)\n", rc); + return rc; + } + } + + /* prereset() might have modified ehc->i.action */ + if (ehc->i.action & ATA_EH_HARDRESET) + reset = hardreset; + else if (ehc->i.action & ATA_EH_SOFTRESET) + reset = softreset; + else { + /* prereset told us not to reset, bang classes and return */ + for (i = 0; i < ATA_MAX_DEVICES; i++) + classes[i] = ATA_DEV_NONE; + return 0; + } + + /* did prereset() screw up? if so, fix up to avoid oopsing */ + if (!reset) { + ata_port_printk(ap, KERN_ERR, "BUG: prereset() requested " + "invalid reset type\n"); + if (softreset) + reset = softreset; + else + reset = hardreset; + } + + retry: + /* shut up during boot probing */ + if (verbose) + ata_port_printk(ap, KERN_INFO, "%s resetting port\n", + reset == softreset ? "soft" : "hard"); + + /* mark that this EH session started with reset */ + ehc->i.flags |= ATA_EHI_DID_RESET; + + rc = ata_do_reset(ap, reset, classes); + + did_followup_srst = 0; + if (reset == hardreset && + ata_eh_followup_srst_needed(rc, classify, classes)) { + /* okay, let's do follow-up softreset */ + did_followup_srst = 1; + reset = softreset; + + if (!reset) { + ata_port_printk(ap, KERN_ERR, + "follow-up softreset required " + "but no softreset avaliable\n"); + return -EINVAL; + } + + ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK); + rc = ata_do_reset(ap, reset, classes); + + if (rc == 0 && classify && + classes[0] == ATA_DEV_UNKNOWN) { + ata_port_printk(ap, KERN_ERR, + "classification failed\n"); + return -EINVAL; + } + } + + if (rc && --tries) { + const char *type; + + if (reset == softreset) { + if (did_followup_srst) + type = "follow-up soft"; + else + type = "soft"; + } else + type = "hard"; + + ata_port_printk(ap, KERN_WARNING, + "%sreset failed, retrying in 5 secs\n", type); + ssleep(5); + + if (reset == hardreset) + sata_down_spd_limit(ap); + if (hardreset) + reset = hardreset; + goto retry; + } + + if (rc == 0) { + /* After the reset, the device state is PIO 0 and the + * controller state is undefined. Record the mode. + */ + for (i = 0; i < ATA_MAX_DEVICES; i++) + ap->device[i].pio_mode = XFER_PIO_0; + + if (postreset) + postreset(ap, classes); + + /* reset successful, schedule revalidation */ + ata_eh_done(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK); + ehc->i.action |= ATA_EH_REVALIDATE; + } + + return rc; +} + +static int ata_eh_revalidate_and_attach(struct ata_port *ap, + struct ata_device **r_failed_dev) +{ + struct ata_eh_context *ehc = &ap->eh_context; + struct ata_device *dev; + unsigned long flags; + int i, rc = 0; + + DPRINTK("ENTER\n"); + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + unsigned int action; + + dev = &ap->device[i]; + action = ata_eh_dev_action(dev); + + if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) { + if (ata_port_offline(ap)) { + rc = -EIO; + break; + } + + ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE); + rc = ata_dev_revalidate(dev, + ehc->i.flags & ATA_EHI_DID_RESET); + if (rc) + break; + + ata_eh_done(ap, dev, ATA_EH_REVALIDATE); + + /* schedule the scsi_rescan_device() here */ + queue_work(ata_aux_wq, &(ap->scsi_rescan_task)); + } else if (dev->class == ATA_DEV_UNKNOWN && + ehc->tries[dev->devno] && + ata_class_enabled(ehc->classes[dev->devno])) { + dev->class = ehc->classes[dev->devno]; + + rc = ata_dev_read_id(dev, &dev->class, 1, dev->id); + if (rc == 0) + rc = ata_dev_configure(dev, 1); + + if (rc) { + dev->class = ATA_DEV_UNKNOWN; + break; + } + + spin_lock_irqsave(ap->lock, flags); + ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; + spin_unlock_irqrestore(ap->lock, flags); + } + } + + if (rc) + *r_failed_dev = dev; + + DPRINTK("EXIT\n"); + return rc; +} + +/** + * ata_eh_suspend - handle suspend EH action + * @ap: target host port + * @r_failed_dev: result parameter to indicate failing device + * + * Handle suspend EH action. Disk devices are spinned down and + * other types of devices are just marked suspended. Once + * suspended, no EH action to the device is allowed until it is + * resumed. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, -errno otherwise + */ +static int ata_eh_suspend(struct ata_port *ap, struct ata_device **r_failed_dev) +{ + struct ata_device *dev; + int i, rc = 0; + + DPRINTK("ENTER\n"); + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + unsigned long flags; + unsigned int action, err_mask; + + dev = &ap->device[i]; + action = ata_eh_dev_action(dev); + + if (!ata_dev_enabled(dev) || !(action & ATA_EH_SUSPEND)) + continue; + + WARN_ON(dev->flags & ATA_DFLAG_SUSPENDED); + + ata_eh_about_to_do(ap, dev, ATA_EH_SUSPEND); + + if (dev->class == ATA_DEV_ATA && !(action & ATA_EH_PM_FREEZE)) { + /* flush cache */ + rc = ata_flush_cache(dev); + if (rc) + break; + + /* spin down */ + err_mask = ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1); + if (err_mask) { + ata_dev_printk(dev, KERN_ERR, "failed to " + "spin down (err_mask=0x%x)\n", + err_mask); + rc = -EIO; + break; + } + } + + spin_lock_irqsave(ap->lock, flags); + dev->flags |= ATA_DFLAG_SUSPENDED; + spin_unlock_irqrestore(ap->lock, flags); + + ata_eh_done(ap, dev, ATA_EH_SUSPEND); + } + + if (rc) + *r_failed_dev = dev; + + DPRINTK("EXIT\n"); + return 0; +} + +/** + * ata_eh_prep_resume - prep for resume EH action + * @ap: target host port + * + * Clear SUSPENDED in preparation for scheduled resume actions. + * This allows other parts of EH to access the devices being + * resumed. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +static void ata_eh_prep_resume(struct ata_port *ap) +{ + struct ata_device *dev; + unsigned long flags; + int i; + + DPRINTK("ENTER\n"); + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + unsigned int action; + + dev = &ap->device[i]; + action = ata_eh_dev_action(dev); + + if (!ata_dev_enabled(dev) || !(action & ATA_EH_RESUME)) + continue; + + spin_lock_irqsave(ap->lock, flags); + dev->flags &= ~ATA_DFLAG_SUSPENDED; + spin_unlock_irqrestore(ap->lock, flags); + } + + DPRINTK("EXIT\n"); +} + +/** + * ata_eh_resume - handle resume EH action + * @ap: target host port + * @r_failed_dev: result parameter to indicate failing device + * + * Handle resume EH action. Target devices are already reset and + * revalidated. Spinning up is the only operation left. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, -errno otherwise + */ +static int ata_eh_resume(struct ata_port *ap, struct ata_device **r_failed_dev) +{ + struct ata_device *dev; + int i, rc = 0; + + DPRINTK("ENTER\n"); + + for (i = 0; i < ATA_MAX_DEVICES; i++) { + unsigned int action, err_mask; + + dev = &ap->device[i]; + action = ata_eh_dev_action(dev); + + if (!ata_dev_enabled(dev) || !(action & ATA_EH_RESUME)) + continue; + + ata_eh_about_to_do(ap, dev, ATA_EH_RESUME); + + if (dev->class == ATA_DEV_ATA && !(action & ATA_EH_PM_FREEZE)) { + err_mask = ata_do_simple_cmd(dev, + ATA_CMD_IDLEIMMEDIATE); + if (err_mask) { + ata_dev_printk(dev, KERN_ERR, "failed to " + "spin up (err_mask=0x%x)\n", + err_mask); + rc = -EIO; + break; + } + } + + ata_eh_done(ap, dev, ATA_EH_RESUME); + } + + if (rc) + *r_failed_dev = dev; + + DPRINTK("EXIT\n"); + return 0; +} + +static int ata_port_nr_enabled(struct ata_port *ap) +{ + int i, cnt = 0; + + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (ata_dev_enabled(&ap->device[i])) + cnt++; + return cnt; +} + +static int ata_port_nr_vacant(struct ata_port *ap) +{ + int i, cnt = 0; + + for (i = 0; i < ATA_MAX_DEVICES; i++) + if (ap->device[i].class == ATA_DEV_UNKNOWN) + cnt++; + return cnt; +} + +static int ata_eh_skip_recovery(struct ata_port *ap) +{ + struct ata_eh_context *ehc = &ap->eh_context; + int i; + + /* skip if all possible devices are suspended */ + for (i = 0; i < ata_port_max_devices(ap); i++) { + struct ata_device *dev = &ap->device[i]; + + if (!(dev->flags & ATA_DFLAG_SUSPENDED)) + break; + } + + if (i == ata_port_max_devices(ap)) + return 1; + + /* thaw frozen port, resume link and recover failed devices */ + if ((ap->pflags & ATA_PFLAG_FROZEN) || + (ehc->i.flags & ATA_EHI_RESUME_LINK) || ata_port_nr_enabled(ap)) + return 0; + + /* skip if class codes for all vacant slots are ATA_DEV_NONE */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + + if (dev->class == ATA_DEV_UNKNOWN && + ehc->classes[dev->devno] != ATA_DEV_NONE) + return 0; + } + + return 1; +} + +/** + * ata_eh_recover - recover host port after error + * @ap: host port to recover + * @prereset: prereset method (can be NULL) + * @softreset: softreset method (can be NULL) + * @hardreset: hardreset method (can be NULL) + * @postreset: postreset method (can be NULL) + * + * This is the alpha and omega, eum and yang, heart and soul of + * libata exception handling. On entry, actions required to + * recover the port and hotplug requests are recorded in + * eh_context. This function executes all the operations with + * appropriate retrials and fallbacks to resurrect failed + * devices, detach goners and greet newcomers. + * + * LOCKING: + * Kernel thread context (may sleep). + * + * RETURNS: + * 0 on success, -errno on failure. + */ +static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, + ata_reset_fn_t softreset, ata_reset_fn_t hardreset, + ata_postreset_fn_t postreset) +{ + struct ata_eh_context *ehc = &ap->eh_context; + struct ata_device *dev; + int down_xfermask, i, rc; + + DPRINTK("ENTER\n"); + + /* prep for recovery */ + for (i = 0; i < ATA_MAX_DEVICES; i++) { + dev = &ap->device[i]; + + ehc->tries[dev->devno] = ATA_EH_DEV_TRIES; + + /* process hotplug request */ + if (dev->flags & ATA_DFLAG_DETACH) + ata_eh_detach_dev(dev); + + if (!ata_dev_enabled(dev) && + ((ehc->i.probe_mask & (1 << dev->devno)) && + !(ehc->did_probe_mask & (1 << dev->devno)))) { + ata_eh_detach_dev(dev); + ata_dev_init(dev); + ehc->did_probe_mask |= (1 << dev->devno); + ehc->i.action |= ATA_EH_SOFTRESET; + } + } + + retry: + down_xfermask = 0; + rc = 0; + + /* if UNLOADING, finish immediately */ + if (ap->pflags & ATA_PFLAG_UNLOADING) + goto out; + + /* prep for resume */ + ata_eh_prep_resume(ap); + + /* skip EH if possible. */ + if (ata_eh_skip_recovery(ap)) + ehc->i.action = 0; + + for (i = 0; i < ATA_MAX_DEVICES; i++) + ehc->classes[i] = ATA_DEV_UNKNOWN; + + /* reset */ + if (ehc->i.action & ATA_EH_RESET_MASK) { + ata_eh_freeze_port(ap); + + rc = ata_eh_reset(ap, ata_port_nr_vacant(ap), prereset, + softreset, hardreset, postreset); + if (rc) { + ata_port_printk(ap, KERN_ERR, + "reset failed, giving up\n"); + goto out; + } + + ata_eh_thaw_port(ap); + } + + /* revalidate existing devices and attach new ones */ + rc = ata_eh_revalidate_and_attach(ap, &dev); + if (rc) + goto dev_fail; + + /* resume devices */ + rc = ata_eh_resume(ap, &dev); + if (rc) + goto dev_fail; + + /* configure transfer mode if the port has been reset */ + if (ehc->i.flags & ATA_EHI_DID_RESET) { + rc = ata_set_mode(ap, &dev); + if (rc) { + down_xfermask = 1; + goto dev_fail; + } + } + + /* suspend devices */ + rc = ata_eh_suspend(ap, &dev); + if (rc) + goto dev_fail; + + goto out; + + dev_fail: + switch (rc) { + case -ENODEV: + /* device missing, schedule probing */ + ehc->i.probe_mask |= (1 << dev->devno); + case -EINVAL: + ehc->tries[dev->devno] = 0; + break; + case -EIO: + sata_down_spd_limit(ap); + default: + ehc->tries[dev->devno]--; + if (down_xfermask && + ata_down_xfermask_limit(dev, ehc->tries[dev->devno] == 1)) + ehc->tries[dev->devno] = 0; + } + + if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) { + /* disable device if it has used up all its chances */ + ata_dev_disable(dev); + + /* detach if offline */ + if (ata_port_offline(ap)) + ata_eh_detach_dev(dev); + + /* probe if requested */ + if ((ehc->i.probe_mask & (1 << dev->devno)) && + !(ehc->did_probe_mask & (1 << dev->devno))) { + ata_eh_detach_dev(dev); + ata_dev_init(dev); + + ehc->tries[dev->devno] = ATA_EH_DEV_TRIES; + ehc->did_probe_mask |= (1 << dev->devno); + ehc->i.action |= ATA_EH_SOFTRESET; + } + } else { + /* soft didn't work? be haaaaard */ + if (ehc->i.flags & ATA_EHI_DID_RESET) + ehc->i.action |= ATA_EH_HARDRESET; + else + ehc->i.action |= ATA_EH_SOFTRESET; + } + + if (ata_port_nr_enabled(ap)) { + ata_port_printk(ap, KERN_WARNING, "failed to recover some " + "devices, retrying in 5 secs\n"); + ssleep(5); + } else { + /* no device left, repeat fast */ + msleep(500); + } + + goto retry; + + out: + if (rc) { + for (i = 0; i < ATA_MAX_DEVICES; i++) + ata_dev_disable(&ap->device[i]); + } + + DPRINTK("EXIT, rc=%d\n", rc); + return rc; +} + +/** + * ata_eh_finish - finish up EH + * @ap: host port to finish EH for + * + * Recovery is complete. Clean up EH states and retry or finish + * failed qcs. + * + * LOCKING: + * None. + */ +static void ata_eh_finish(struct ata_port *ap) +{ + int tag; + + /* retry or finish qcs */ + for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { + struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag); + + if (!(qc->flags & ATA_QCFLAG_FAILED)) + continue; + + if (qc->err_mask) { + /* FIXME: Once EH migration is complete, + * generate sense data in this function, + * considering both err_mask and tf. + */ + if (qc->err_mask & AC_ERR_INVALID) + ata_eh_qc_complete(qc); + else + ata_eh_qc_retry(qc); + } else { + if (qc->flags & ATA_QCFLAG_SENSE_VALID) { + ata_eh_qc_complete(qc); + } else { + /* feed zero TF to sense generation */ + memset(&qc->result_tf, 0, sizeof(qc->result_tf)); + ata_eh_qc_retry(qc); + } + } + } +} + +/** + * ata_do_eh - do standard error handling + * @ap: host port to handle error for + * @prereset: prereset method (can be NULL) + * @softreset: softreset method (can be NULL) + * @hardreset: hardreset method (can be NULL) + * @postreset: postreset method (can be NULL) + * + * Perform standard error handling sequence. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset, + ata_reset_fn_t softreset, ata_reset_fn_t hardreset, + ata_postreset_fn_t postreset) +{ + ata_eh_autopsy(ap); + ata_eh_report(ap); + ata_eh_recover(ap, prereset, softreset, hardreset, postreset); + ata_eh_finish(ap); +} + +/** + * ata_eh_handle_port_suspend - perform port suspend operation + * @ap: port to suspend + * + * Suspend @ap. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +static void ata_eh_handle_port_suspend(struct ata_port *ap) +{ + unsigned long flags; + int rc = 0; + + /* are we suspending? */ + spin_lock_irqsave(ap->lock, flags); + if (!(ap->pflags & ATA_PFLAG_PM_PENDING) || + ap->pm_mesg.event == PM_EVENT_ON) { + spin_unlock_irqrestore(ap->lock, flags); + return; + } + spin_unlock_irqrestore(ap->lock, flags); + + WARN_ON(ap->pflags & ATA_PFLAG_SUSPENDED); + + /* suspend */ + ata_eh_freeze_port(ap); + + if (ap->ops->port_suspend) + rc = ap->ops->port_suspend(ap, ap->pm_mesg); + + /* report result */ + spin_lock_irqsave(ap->lock, flags); + + ap->pflags &= ~ATA_PFLAG_PM_PENDING; + if (rc == 0) + ap->pflags |= ATA_PFLAG_SUSPENDED; + else + ata_port_schedule_eh(ap); + + if (ap->pm_result) { + *ap->pm_result = rc; + ap->pm_result = NULL; + } + + spin_unlock_irqrestore(ap->lock, flags); + + return; +} + +/** + * ata_eh_handle_port_resume - perform port resume operation + * @ap: port to resume + * + * Resume @ap. + * + * This function also waits upto one second until all devices + * hanging off this port requests resume EH action. This is to + * prevent invoking EH and thus reset multiple times on resume. + * + * On DPM resume, where some of devices might not be resumed + * together, this may delay port resume upto one second, but such + * DPM resumes are rare and 1 sec delay isn't too bad. + * + * LOCKING: + * Kernel thread context (may sleep). + */ +static void ata_eh_handle_port_resume(struct ata_port *ap) +{ + unsigned long timeout; + unsigned long flags; + int i, rc = 0; + + /* are we resuming? */ + spin_lock_irqsave(ap->lock, flags); + if (!(ap->pflags & ATA_PFLAG_PM_PENDING) || + ap->pm_mesg.event != PM_EVENT_ON) { + spin_unlock_irqrestore(ap->lock, flags); + return; + } + spin_unlock_irqrestore(ap->lock, flags); + + /* spurious? */ + if (!(ap->pflags & ATA_PFLAG_SUSPENDED)) + goto done; + + if (ap->ops->port_resume) + rc = ap->ops->port_resume(ap); + + /* give devices time to request EH */ + timeout = jiffies + HZ; /* 1s max */ + while (1) { + for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *dev = &ap->device[i]; + unsigned int action = ata_eh_dev_action(dev); + + if ((dev->flags & ATA_DFLAG_SUSPENDED) && + !(action & ATA_EH_RESUME)) + break; + } + + if (i == ATA_MAX_DEVICES || time_after(jiffies, timeout)) + break; + msleep(10); + } + + done: + spin_lock_irqsave(ap->lock, flags); + ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED); + if (ap->pm_result) { + *ap->pm_result = rc; + ap->pm_result = NULL; + } + spin_unlock_irqrestore(ap->lock, flags); +} diff --git a/drivers/scsi/scsi_transport_api.h b/drivers/scsi/scsi_transport_api.h new file mode 100644 index 000000000..934f0e62b --- /dev/null +++ b/drivers/scsi/scsi_transport_api.h @@ -0,0 +1,6 @@ +#ifndef _SCSI_TRANSPORT_API_H +#define _SCSI_TRANSPORT_API_H + +void scsi_schedule_eh(struct Scsi_Host *shost); + +#endif /* _SCSI_TRANSPORT_API_H */ diff --git a/drivers/serial/netx-serial.c b/drivers/serial/netx-serial.c new file mode 100644 index 000000000..7502109d3 --- /dev/null +++ b/drivers/serial/netx-serial.c @@ -0,0 +1,747 @@ +/* + * drivers/serial/netx-serial.c + * + * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if defined(CONFIG_SERIAL_NETX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#include <linux/device.h> +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/init.h> +#include <linux/console.h> +#include <linux/sysrq.h> +#include <linux/platform_device.h> +#include <linux/tty.h> +#include <linux/tty_flip.h> +#include <linux/serial_core.h> +#include <linux/serial.h> + +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/hardware.h> +#include <asm/arch/netx-regs.h> + +/* We've been assigned a range on the "Low-density serial ports" major */ +#define SERIAL_NX_MAJOR 204 +#define MINOR_START 170 + +#ifdef CONFIG_SERIAL_NETX_CONSOLE + +enum uart_regs { + UART_DR = 0x00, + UART_SR = 0x04, + UART_LINE_CR = 0x08, + UART_BAUDDIV_MSB = 0x0c, + UART_BAUDDIV_LSB = 0x10, + UART_CR = 0x14, + UART_FR = 0x18, + UART_IIR = 0x1c, + UART_ILPR = 0x20, + UART_RTS_CR = 0x24, + UART_RTS_LEAD = 0x28, + UART_RTS_TRAIL = 0x2c, + UART_DRV_ENABLE = 0x30, + UART_BRM_CR = 0x34, + UART_RXFIFO_IRQLEVEL = 0x38, + UART_TXFIFO_IRQLEVEL = 0x3c, +}; + +#define SR_FE (1<<0) +#define SR_PE (1<<1) +#define SR_BE (1<<2) +#define SR_OE (1<<3) + +#define LINE_CR_BRK (1<<0) +#define LINE_CR_PEN (1<<1) +#define LINE_CR_EPS (1<<2) +#define LINE_CR_STP2 (1<<3) +#define LINE_CR_FEN (1<<4) +#define LINE_CR_5BIT (0<<5) +#define LINE_CR_6BIT (1<<5) +#define LINE_CR_7BIT (2<<5) +#define LINE_CR_8BIT (3<<5) +#define LINE_CR_BITS_MASK (3<<5) + +#define CR_UART_EN (1<<0) +#define CR_SIREN (1<<1) +#define CR_SIRLP (1<<2) +#define CR_MSIE (1<<3) +#define CR_RIE (1<<4) +#define CR_TIE (1<<5) +#define CR_RTIE (1<<6) +#define CR_LBE (1<<7) + +#define FR_CTS (1<<0) +#define FR_DSR (1<<1) +#define FR_DCD (1<<2) +#define FR_BUSY (1<<3) +#define FR_RXFE (1<<4) +#define FR_TXFF (1<<5) +#define FR_RXFF (1<<6) +#define FR_TXFE (1<<7) + +#define IIR_MIS (1<<0) +#define IIR_RIS (1<<1) +#define IIR_TIS (1<<2) +#define IIR_RTIS (1<<3) +#define IIR_MASK 0xf + +#define RTS_CR_AUTO (1<<0) +#define RTS_CR_RTS (1<<1) +#define RTS_CR_COUNT (1<<2) +#define RTS_CR_MOD2 (1<<3) +#define RTS_CR_RTS_POL (1<<4) +#define RTS_CR_CTS_CTR (1<<5) +#define RTS_CR_CTS_POL (1<<6) +#define RTS_CR_STICK (1<<7) + +#define UART_PORT_SIZE 0x40 +#define DRIVER_NAME "netx-uart" + +struct netx_port { + struct uart_port port; +}; + +static void netx_stop_tx(struct uart_port *port) +{ + unsigned int val; + val = readl(port->membase + UART_CR); + writel(val & ~CR_TIE, port->membase + UART_CR); +} + +static void netx_stop_rx(struct uart_port *port) +{ + unsigned int val; + val = readl(port->membase + UART_CR); + writel(val & ~CR_RIE, port->membase + UART_CR); +} + +static void netx_enable_ms(struct uart_port *port) +{ + unsigned int val; + val = readl(port->membase + UART_CR); + writel(val | CR_MSIE, port->membase + UART_CR); +} + +static inline void netx_transmit_buffer(struct uart_port *port) +{ + struct circ_buf *xmit = &port->info->xmit; + + if (port->x_char) { + writel(port->x_char, port->membase + UART_DR); + port->icount.tx++; + port->x_char = 0; + return; + } + + if (uart_tx_stopped(port) || uart_circ_empty(xmit)) { + netx_stop_tx(port); + return; + } + + do { + /* send xmit->buf[xmit->tail] + * out the port here */ + writel(xmit->buf[xmit->tail], port->membase + UART_DR); + xmit->tail = (xmit->tail + 1) & + (UART_XMIT_SIZE - 1); + port->icount.tx++; + if (uart_circ_empty(xmit)) + break; + } while (!(readl(port->membase + UART_FR) & FR_TXFF)); + + if (uart_circ_empty(xmit)) + netx_stop_tx(port); +} + +static void netx_start_tx(struct uart_port *port) +{ + writel( + readl(port->membase + UART_CR) | CR_TIE, port->membase + UART_CR); + + if (!(readl(port->membase + UART_FR) & FR_TXFF)) + netx_transmit_buffer(port); +} + +static unsigned int netx_tx_empty(struct uart_port *port) +{ + return readl(port->membase + UART_FR) & FR_BUSY ? 0 : TIOCSER_TEMT; +} + +static void netx_txint(struct uart_port *port) +{ + struct circ_buf *xmit = &port->info->xmit; + + if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { + netx_stop_tx(port); + return; + } + + netx_transmit_buffer(port); + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); +} + +static void netx_rxint(struct uart_port *port, struct pt_regs *regs) +{ + unsigned char rx, flg, status; + struct tty_struct *tty = port->info->tty; + + while (!(readl(port->membase + UART_FR) & FR_RXFE)) { + rx = readl(port->membase + UART_DR); + flg = TTY_NORMAL; + port->icount.rx++; + status = readl(port->membase + UART_SR); + if (status & SR_BE) { + writel(0, port->membase + UART_SR); + if (uart_handle_break(port)) + continue; + } + + if (unlikely(status & (SR_FE | SR_PE | SR_OE))) { + + if (status & SR_PE) + port->icount.parity++; + else if (status & SR_FE) + port->icount.frame++; + if (status & SR_OE) + port->icount.overrun++; + + status &= port->read_status_mask; + + if (status & SR_BE) + flg = TTY_BREAK; + else if (status & SR_PE) + flg = TTY_PARITY; + else if (status & SR_FE) + flg = TTY_FRAME; + } + + if (uart_handle_sysrq_char(port, rx, regs)) + continue; + + uart_insert_char(port, status, SR_OE, rx, flg); + } + + tty_flip_buffer_push(tty); + return; +} + +static irqreturn_t netx_int(int irq, void *dev_id, struct pt_regs *regs) +{ + struct uart_port *port = (struct uart_port *)dev_id; + unsigned long flags; + unsigned char status; + + spin_lock_irqsave(&port->lock,flags); + + status = readl(port->membase + UART_IIR) & IIR_MASK; + while (status) { + if (status & IIR_RIS) + netx_rxint(port, regs); + if (status & IIR_TIS) + netx_txint(port); + if (status & IIR_MIS) { + if (readl(port->membase + UART_FR) & FR_CTS) + uart_handle_cts_change(port, 1); + else + uart_handle_cts_change(port, 0); + } + writel(0, port->membase + UART_IIR); + status = readl(port->membase + UART_IIR) & IIR_MASK; + } + + spin_unlock_irqrestore(&port->lock,flags); + return IRQ_HANDLED; +} + +static unsigned int netx_get_mctrl(struct uart_port *port) +{ + unsigned int ret = TIOCM_DSR | TIOCM_CAR; + + if (readl(port->membase + UART_FR) & FR_CTS) + ret |= TIOCM_CTS; + + return ret; +} + +static void netx_set_mctrl(struct uart_port *port, unsigned int mctrl) +{ + unsigned int val; + + if (mctrl & TIOCM_RTS) { + val = readl(port->membase + UART_RTS_CR); + writel(val | RTS_CR_RTS, port->membase + UART_RTS_CR); + } +} + +static void netx_break_ctl(struct uart_port *port, int break_state) +{ + unsigned int line_cr; + spin_lock_irq(&port->lock); + + line_cr = readl(port->membase + UART_LINE_CR); + if (break_state != 0) + line_cr |= LINE_CR_BRK; + else + line_cr &= ~LINE_CR_BRK; + writel(line_cr, port->membase + UART_LINE_CR); + + spin_unlock_irq(&port->lock); +} + +static int netx_startup(struct uart_port *port) +{ + int ret; + + ret = request_irq(port->irq, netx_int, 0, + DRIVER_NAME, port); + if (ret) { + dev_err(port->dev, "unable to grab irq%d\n",port->irq); + goto exit; + } + + writel(readl(port->membase + UART_LINE_CR) | LINE_CR_FEN, + port->membase + UART_LINE_CR); + + writel(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE | CR_UART_EN, + port->membase + UART_CR); + +exit: + return ret; +} + +static void netx_shutdown(struct uart_port *port) +{ + writel(0, port->membase + UART_CR) ; + + free_irq(port->irq, port); +} + +static void +netx_set_termios(struct uart_port *port, struct termios *termios, + struct termios *old) +{ + unsigned int baud, quot; + unsigned char old_cr; + unsigned char line_cr = LINE_CR_FEN; + unsigned char rts_cr = 0; + + switch (termios->c_cflag & CSIZE) { + case CS5: + line_cr |= LINE_CR_5BIT; + break; + case CS6: + line_cr |= LINE_CR_6BIT; + break; + case CS7: + line_cr |= LINE_CR_7BIT; + break; + case CS8: + line_cr |= LINE_CR_8BIT; + break; + } + + if (termios->c_cflag & CSTOPB) + line_cr |= LINE_CR_STP2; + + if (termios->c_cflag & PARENB) { + line_cr |= LINE_CR_PEN; + if (!(termios->c_cflag & PARODD)) + line_cr |= LINE_CR_EPS; + } + + if (termios->c_cflag & CRTSCTS) + rts_cr = RTS_CR_AUTO | RTS_CR_CTS_CTR | RTS_CR_RTS_POL; + + baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); + quot = baud * 4096; + quot /= 1000; + quot *= 256; + quot /= 100000; + + spin_lock_irq(&port->lock); + + uart_update_timeout(port, termios->c_cflag, baud); + + old_cr = readl(port->membase + UART_CR); + + /* disable interrupts */ + writel(old_cr & ~(CR_MSIE | CR_RIE | CR_TIE | CR_RTIE), + port->membase + UART_CR); + + /* drain transmitter */ + while (readl(port->membase + UART_FR) & FR_BUSY); + + /* disable UART */ + writel(old_cr & ~CR_UART_EN, port->membase + UART_CR); + + /* modem status interrupts */ + old_cr &= ~CR_MSIE; + if (UART_ENABLE_MS(port, termios->c_cflag)) + old_cr |= CR_MSIE; + + writel((quot>>8) & 0xff, port->membase + UART_BAUDDIV_MSB); + writel(quot & 0xff, port->membase + UART_BAUDDIV_LSB); + writel(line_cr, port->membase + UART_LINE_CR); + + writel(rts_cr, port->membase + UART_RTS_CR); + + /* + * Characters to ignore + */ + port->ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= SR_PE; + if (termios->c_iflag & IGNBRK) { + port->ignore_status_mask |= SR_BE; + /* + * If we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= SR_PE; + } + + port->read_status_mask = 0; + if (termios->c_iflag & (BRKINT | PARMRK)) + port->read_status_mask |= SR_BE; + if (termios->c_iflag & INPCK) + port->read_status_mask |= SR_PE | SR_FE; + + writel(old_cr, port->membase + UART_CR); + + spin_unlock_irq(&port->lock); +} + +static const char *netx_type(struct uart_port *port) +{ + return port->type == PORT_NETX ? "NETX" : NULL; +} + +static void netx_release_port(struct uart_port *port) +{ + release_mem_region(port->mapbase, UART_PORT_SIZE); +} + +static int netx_request_port(struct uart_port *port) +{ + return request_mem_region(port->mapbase, UART_PORT_SIZE, + DRIVER_NAME) != NULL ? 0 : -EBUSY; +} + +static void netx_config_port(struct uart_port *port, int flags) +{ + if (flags & UART_CONFIG_TYPE && netx_request_port(port) == 0) + port->type = PORT_NETX; +} + +static int +netx_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + int ret = 0; + + if (ser->type != PORT_UNKNOWN && ser->type != PORT_NETX) + ret = -EINVAL; + + return ret; +} + +static struct uart_ops netx_pops = { + .tx_empty = netx_tx_empty, + .set_mctrl = netx_set_mctrl, + .get_mctrl = netx_get_mctrl, + .stop_tx = netx_stop_tx, + .start_tx = netx_start_tx, + .stop_rx = netx_stop_rx, + .enable_ms = netx_enable_ms, + .break_ctl = netx_break_ctl, + .startup = netx_startup, + .shutdown = netx_shutdown, + .set_termios = netx_set_termios, + .type = netx_type, + .release_port = netx_release_port, + .request_port = netx_request_port, + .config_port = netx_config_port, + .verify_port = netx_verify_port, +}; + +static struct netx_port netx_ports[] = { + { + .port = { + .type = PORT_NETX, + .iotype = UPIO_MEM, + .membase = (char __iomem *)io_p2v(NETX_PA_UART0), + .mapbase = NETX_PA_UART0, + .irq = NETX_IRQ_UART0, + .uartclk = 100000000, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .ops = &netx_pops, + .line = 0, + }, + }, { + .port = { + .type = PORT_NETX, + .iotype = UPIO_MEM, + .membase = (char __iomem *)io_p2v(NETX_PA_UART1), + .mapbase = NETX_PA_UART1, + .irq = NETX_IRQ_UART1, + .uartclk = 100000000, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .ops = &netx_pops, + .line = 1, + }, + }, { + .port = { + .type = PORT_NETX, + .iotype = UPIO_MEM, + .membase = (char __iomem *)io_p2v(NETX_PA_UART2), + .mapbase = NETX_PA_UART2, + .irq = NETX_IRQ_UART2, + .uartclk = 100000000, + .fifosize = 16, + .flags = UPF_BOOT_AUTOCONF, + .ops = &netx_pops, + .line = 2, + }, + } +}; + +static void netx_console_putchar(struct uart_port *port, int ch) +{ + while (readl(port->membase + UART_FR) & FR_BUSY); + writel(ch, port->membase + UART_DR); +} + +static void +netx_console_write(struct console *co, const char *s, unsigned int count) +{ + struct uart_port *port = &netx_ports[co->index].port; + unsigned char cr_save; + + cr_save = readl(port->membase + UART_CR); + writel(cr_save | CR_UART_EN, port->membase + UART_CR); + + uart_console_write(port, s, count, netx_console_putchar); + + while (readl(port->membase + UART_FR) & FR_BUSY); + writel(cr_save, port->membase + UART_CR); +} + +static void __init +netx_console_get_options(struct uart_port *port, int *baud, + int *parity, int *bits, int *flow) +{ + unsigned char line_cr; + + *baud = (readl(port->membase + UART_BAUDDIV_MSB) << 8) | + readl(port->membase + UART_BAUDDIV_LSB); + *baud *= 1000; + *baud /= 4096; + *baud *= 1000; + *baud /= 256; + *baud *= 100; + + line_cr = readl(port->membase + UART_LINE_CR); + *parity = 'n'; + if (line_cr & LINE_CR_PEN) { + if (line_cr & LINE_CR_EPS) + *parity = 'e'; + else + *parity = 'o'; + } + + switch (line_cr & LINE_CR_BITS_MASK) { + case LINE_CR_8BIT: + *bits = 8; + break; + case LINE_CR_7BIT: + *bits = 7; + break; + case LINE_CR_6BIT: + *bits = 6; + break; + case LINE_CR_5BIT: + *bits = 5; + break; + } + + if (readl(port->membase + UART_RTS_CR) & RTS_CR_AUTO) + *flow = 'r'; +} + +static int __init +netx_console_setup(struct console *co, char *options) +{ + struct netx_port *sport; + int baud = 9600; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + /* + * Check whether an invalid uart number has been specified, and + * if so, search for the first available port that does have + * console support. + */ + if (co->index == -1 || co->index >= ARRAY_SIZE(netx_ports)) + co->index = 0; + sport = &netx_ports[co->index]; + + if (options) { + uart_parse_options(options, &baud, &parity, &bits, &flow); + } else { + /* if the UART is enabled, assume it has been correctly setup + * by the bootloader and get the options + */ + if (readl(sport->port.membase + UART_CR) & CR_UART_EN) { + netx_console_get_options(&sport->port, &baud, + &parity, &bits, &flow); + } + + } + + return uart_set_options(&sport->port, co, baud, parity, bits, flow); +} + +static struct uart_driver netx_reg; +static struct console netx_console = { + .name = "ttyNX", + .write = netx_console_write, + .device = uart_console_device, + .setup = netx_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &netx_reg, +}; + +static int __init netx_console_init(void) +{ + register_console(&netx_console); + return 0; +} +console_initcall(netx_console_init); + +#define NETX_CONSOLE &netx_console +#else +#define NETX_CONSOLE NULL +#endif + +static struct uart_driver netx_reg = { + .owner = THIS_MODULE, + .driver_name = DRIVER_NAME, + .dev_name = "ttyNX", + .major = SERIAL_NX_MAJOR, + .minor = MINOR_START, + .nr = ARRAY_SIZE(netx_ports), + .cons = NETX_CONSOLE, +}; + +static int serial_netx_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct netx_port *sport = platform_get_drvdata(pdev); + + if (sport) + uart_suspend_port(&netx_reg, &sport->port); + + return 0; +} + +static int serial_netx_resume(struct platform_device *pdev) +{ + struct netx_port *sport = platform_get_drvdata(pdev); + + if (sport) + uart_resume_port(&netx_reg, &sport->port); + + return 0; +} + +static int serial_netx_probe(struct platform_device *pdev) +{ + struct uart_port *port = &netx_ports[pdev->id].port; + + dev_info(&pdev->dev, "initialising\n"); + + port->dev = &pdev->dev; + + writel(1, port->membase + UART_RXFIFO_IRQLEVEL); + uart_add_one_port(&netx_reg, &netx_ports[pdev->id].port); + platform_set_drvdata(pdev, &netx_ports[pdev->id]); + + return 0; +} + +static int serial_netx_remove(struct platform_device *pdev) +{ + struct netx_port *sport = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + + if (sport) + uart_remove_one_port(&netx_reg, &sport->port); + + return 0; +} + +static struct platform_driver serial_netx_driver = { + .probe = serial_netx_probe, + .remove = serial_netx_remove, + + .suspend = serial_netx_suspend, + .resume = serial_netx_resume, + + .driver = { + .name = DRIVER_NAME, + }, +}; + +static int __init netx_serial_init(void) +{ + int ret; + + printk(KERN_INFO "Serial: NetX driver\n"); + + ret = uart_register_driver(&netx_reg); + if (ret) + return ret; + + ret = platform_driver_register(&serial_netx_driver); + if (ret != 0) + uart_unregister_driver(&netx_reg); + + return 0; +} + +static void __exit netx_serial_exit(void) +{ + platform_driver_unregister(&serial_netx_driver); + uart_unregister_driver(&netx_reg); +} + +module_init(netx_serial_init); +module_exit(netx_serial_exit); + +MODULE_AUTHOR("Sascha Hauer"); +MODULE_DESCRIPTION("NetX serial port driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c new file mode 100644 index 000000000..247b5a491 --- /dev/null +++ b/drivers/usb/core/endpoint.c @@ -0,0 +1,275 @@ +/* + * drivers/usb/core/endpoint.c + * + * (C) Copyright 2002,2004,2006 Greg Kroah-Hartman + * (C) Copyright 2002,2004 IBM Corp. + * (C) Copyright 2006 Novell Inc. + * + * Endpoint sysfs stuff + * + */ + +#include <linux/kernel.h> +#include <linux/usb.h> +#include "usb.h" + +/* endpoint stuff */ + +struct ep_device { + struct usb_endpoint_descriptor *desc; + struct usb_device *udev; + struct device dev; +}; +#define to_ep_device(_dev) \ + container_of(_dev, struct ep_device, dev) + +struct ep_attribute { + struct attribute attr; + ssize_t (*show)(struct usb_device *, + struct usb_endpoint_descriptor *, char *); +}; +#define to_ep_attribute(_attr) \ + container_of(_attr, struct ep_attribute, attr) + +#define usb_ep_attr(field, format_string) \ +static ssize_t show_ep_##field(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + struct ep_device *ep = to_ep_device(dev); \ + return sprintf(buf, format_string, ep->desc->field); \ +} \ +static DEVICE_ATTR(field, S_IRUGO, show_ep_##field, NULL); + +usb_ep_attr(bLength, "%02x\n") +usb_ep_attr(bEndpointAddress, "%02x\n") +usb_ep_attr(bmAttributes, "%02x\n") +usb_ep_attr(bInterval, "%02x\n") + +static ssize_t show_ep_wMaxPacketSize(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ep_device *ep = to_ep_device(dev); + return sprintf(buf, "%04x\n", + le16_to_cpu(ep->desc->wMaxPacketSize) & 0x07ff); +} +static DEVICE_ATTR(wMaxPacketSize, S_IRUGO, show_ep_wMaxPacketSize, NULL); + +static ssize_t show_ep_type(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct ep_device *ep = to_ep_device(dev); + char *type = "unknown"; + + switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_CONTROL: + type = "Control"; + break; + case USB_ENDPOINT_XFER_ISOC: + type = "Isoc"; + break; + case USB_ENDPOINT_XFER_BULK: + type = "Bulk"; + break; + case USB_ENDPOINT_XFER_INT: + type = "Interrupt"; + break; + } + return sprintf(buf, "%s\n", type); +} +static DEVICE_ATTR(type, S_IRUGO, show_ep_type, NULL); + +static ssize_t show_ep_interval(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ep_device *ep = to_ep_device(dev); + char unit; + unsigned interval = 0; + unsigned in; + + in = (ep->desc->bEndpointAddress & USB_DIR_IN); + + switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + case USB_ENDPOINT_XFER_CONTROL: + if (ep->udev->speed == USB_SPEED_HIGH) /* uframes per NAK */ + interval = ep->desc->bInterval; + break; + case USB_ENDPOINT_XFER_ISOC: + interval = 1 << (ep->desc->bInterval - 1); + break; + case USB_ENDPOINT_XFER_BULK: + if (ep->udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */ + interval = ep->desc->bInterval; + break; + case USB_ENDPOINT_XFER_INT: + if (ep->udev->speed == USB_SPEED_HIGH) + interval = 1 << (ep->desc->bInterval - 1); + else + interval = ep->desc->bInterval; + break; + } + interval *= (ep->udev->speed == USB_SPEED_HIGH) ? 125 : 1000; + if (interval % 1000) + unit = 'u'; + else { + unit = 'm'; + interval /= 1000; + } + + return sprintf(buf, "%d%cs\n", interval, unit); +} +static DEVICE_ATTR(interval, S_IRUGO, show_ep_interval, NULL); + +static ssize_t show_ep_direction(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ep_device *ep = to_ep_device(dev); + char *direction; + + if ((ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL) + direction = "both"; + else if (ep->desc->bEndpointAddress & USB_DIR_IN) + direction = "in"; + else + direction = "out"; + return sprintf(buf, "%s\n", direction); +} +static DEVICE_ATTR(direction, S_IRUGO, show_ep_direction, NULL); + +static struct attribute *ep_dev_attrs[] = { + &dev_attr_bLength.attr, + &dev_attr_bEndpointAddress.attr, + &dev_attr_bmAttributes.attr, + &dev_attr_bInterval.attr, + &dev_attr_wMaxPacketSize.attr, + &dev_attr_interval.attr, + &dev_attr_type.attr, + &dev_attr_direction.attr, + NULL, +}; +static struct attribute_group ep_dev_attr_grp = { + .attrs = ep_dev_attrs, +}; + +static struct endpoint_class { + struct kref kref; + struct class *class; +} *ep_class; + +static int init_endpoint_class(void) +{ + int result = 0; + + if (ep_class != NULL) { + kref_get(&ep_class->kref); + goto exit; + } + + ep_class = kmalloc(sizeof(*ep_class), GFP_KERNEL); + if (!ep_class) { + result = -ENOMEM; + goto exit; + } + + kref_init(&ep_class->kref); + ep_class->class = class_create(THIS_MODULE, "usb_endpoint"); + if (IS_ERR(ep_class->class)) { + result = IS_ERR(ep_class->class); + kfree(ep_class); + ep_class = NULL; + goto exit; + } + +exit: + return result; +} + +static void release_endpoint_class(struct kref *kref) +{ + /* Ok, we cheat as we know we only have one ep_class */ + class_destroy(ep_class->class); + kfree(ep_class); + ep_class = NULL; +} + +static void destroy_endpoint_class(void) +{ + if (ep_class) + kref_put(&ep_class->kref, release_endpoint_class); +} + +static void ep_device_release(struct device *dev) +{ + struct ep_device *ep_dev = to_ep_device(dev); + + dev_dbg(dev, "%s called for %s\n", __FUNCTION__, dev->bus_id); + kfree(ep_dev); +} + +void usb_create_ep_files(struct device *parent, + struct usb_host_endpoint *endpoint, + struct usb_device *udev) +{ + char name[8]; + struct ep_device *ep_dev; + int minor; + int retval; + + retval = init_endpoint_class(); + if (retval) + goto exit; + + ep_dev = kzalloc(sizeof(*ep_dev), GFP_KERNEL); + if (!ep_dev) { + retval = -ENOMEM; + goto exit; + } + + /* fun calculation to determine the minor of this endpoint */ + minor = (((udev->bus->busnum - 1) * 128) * 16) + (udev->devnum - 1); + + ep_dev->desc = &endpoint->desc; + ep_dev->udev = udev; + ep_dev->dev.devt = MKDEV(442, minor); // FIXME fake number... + ep_dev->dev.class = ep_class->class; + ep_dev->dev.parent = parent; + ep_dev->dev.release = ep_device_release; + snprintf(ep_dev->dev.bus_id, BUS_ID_SIZE, "usbdev%d.%d_ep%02x", + udev->bus->busnum, udev->devnum, + endpoint->desc.bEndpointAddress); + + retval = device_register(&ep_dev->dev); + if (retval) + goto error; + sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp); + + endpoint->ep_dev = ep_dev; + + /* create the symlink to the old-style "ep_XX" directory */ + sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); + sysfs_create_link(&parent->kobj, &endpoint->ep_dev->dev.kobj, name); + +exit: + return; +error: + kfree(ep_dev); + return; +} + +void usb_remove_ep_files(struct usb_host_endpoint *endpoint) +{ + + if (endpoint->ep_dev) { + char name[8]; + + sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); + sysfs_remove_link(&endpoint->ep_dev->dev.parent->kobj, name); + sysfs_remove_group(&endpoint->ep_dev->dev.kobj, &ep_dev_attr_grp); + device_unregister(&endpoint->ep_dev->dev); + endpoint->ep_dev = NULL; + } + destroy_endpoint_class(); +} + + diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c new file mode 100644 index 000000000..6531c4d26 --- /dev/null +++ b/drivers/usb/host/ohci-ep93xx.c @@ -0,0 +1,225 @@ +/* + * OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> + * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> + * (C) Copyright 2002 Hewlett-Packard Company + * + * Bus Glue for ep93xx. + * + * Written by Christopher Hoover <ch@hpl.hp.com> + * Based on fragments of previous driver by Russell King et al. + * + * Modified for LH7A404 from ohci-sa1111.c + * by Durgesh Pattamatta <pattamattad@sharpsec.com> + * + * Modified for pxa27x from ohci-lh7a404.c + * by Nick Bane <nick@cecomputing.co.uk> 26-8-2004 + * + * Modified for ep93xx from ohci-pxa27x.c + * by Lennert Buytenhek <buytenh@wantstofly.org> 28-2-2006 + * Based on an earlier driver by Ray Lehtiniemi + * + * This file is licenced under the GPL. + */ + +#include <linux/clk.h> +#include <linux/device.h> +#include <linux/signal.h> +#include <linux/platform_device.h> + +#include <asm/mach-types.h> +#include <asm/hardware.h> + +static struct clk *usb_host_clock; + +static void ep93xx_start_hc(struct device *dev) +{ + clk_enable(usb_host_clock); +} + +static void ep93xx_stop_hc(struct device *dev) +{ + clk_disable(usb_host_clock); +} + +static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, + struct platform_device *pdev) +{ + int retval; + struct usb_hcd *hcd; + + if (pdev->resource[1].flags != IORESOURCE_IRQ) { + pr_debug("resource[1] is not IORESOURCE_IRQ"); + return -ENOMEM; + } + + hcd = usb_create_hcd(driver, &pdev->dev, "ep93xx"); + if (hcd == NULL) + return -ENOMEM; + + hcd->rsrc_start = pdev->resource[0].start; + hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { + usb_put_hcd(hcd); + retval = -EBUSY; + goto err1; + } + + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + if (hcd->regs == NULL) { + pr_debug("ioremap failed"); + retval = -ENOMEM; + goto err2; + } + + usb_host_clock = clk_get(&pdev->dev, "usb_host"); + ep93xx_start_hc(&pdev->dev); + + ohci_hcd_init(hcd_to_ohci(hcd)); + + retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT); + if (retval == 0) + return retval; + + ep93xx_stop_hc(&pdev->dev); + iounmap(hcd->regs); +err2: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); +err1: + usb_put_hcd(hcd); + + return retval; +} + +static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd, + struct platform_device *pdev) +{ + usb_remove_hcd(hcd); + ep93xx_stop_hc(&pdev->dev); + clk_put(usb_host_clock); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); +} + +static int __devinit ohci_ep93xx_start(struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + int ret; + + if ((ret = ohci_init(ohci)) < 0) + return ret; + + if ((ret = ohci_run(ohci)) < 0) { + err("can't start %s", hcd->self.bus_name); + ohci_stop(hcd); + return ret; + } + + return 0; +} + +static struct hc_driver ohci_ep93xx_hc_driver = { + .description = hcd_name, + .product_desc = "EP93xx OHCI", + .hcd_priv_size = sizeof(struct ohci_hcd), + .irq = ohci_irq, + .flags = HCD_USB11 | HCD_MEMORY, + .start = ohci_ep93xx_start, + .stop = ohci_stop, + .urb_enqueue = ohci_urb_enqueue, + .urb_dequeue = ohci_urb_dequeue, + .endpoint_disable = ohci_endpoint_disable, + .get_frame_number = ohci_get_frame, + .hub_status_data = ohci_hub_status_data, + .hub_control = ohci_hub_control, +#ifdef CONFIG_PM + .bus_suspend = ohci_bus_suspend, + .bus_resume = ohci_bus_resume, +#endif + .start_port_reset = ohci_start_port_reset, +}; + +extern int usb_disabled(void); + +static int ohci_hcd_ep93xx_drv_probe(struct platform_device *pdev) +{ + int ret; + + ret = -ENODEV; + if (!usb_disabled()) + ret = usb_hcd_ep93xx_probe(&ohci_ep93xx_hc_driver, pdev); + + return ret; +} + +static int ohci_hcd_ep93xx_drv_remove(struct platform_device *pdev) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + + usb_hcd_ep93xx_remove(hcd, pdev); + + return 0; +} + +#ifdef CONFIG_PM +static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct ochi_hcd *ohci = hcd_to_ohci(hcd); + + if (time_before(jiffies, ohci->next_statechange)) + msleep(5); + ohci->next_statechange = jiffies; + + ep93xx_stop_hc(&pdev->dev); + hcd->state = HC_STATE_SUSPENDED; + pdev->dev.power.power_state = PMSG_SUSPEND; + + return 0; +} + +static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + int status; + + if (time_before(jiffies, ohci->next_statechange)) + msleep(5); + ohci->next_statechange = jiffies; + + ep93xx_start_hc(&pdev->dev); + pdev->dev.power.power_state = PMSG_ON; + usb_hcd_resume_root_hub(hcd); + + return 0; +} +#endif + + +static struct platform_driver ohci_hcd_ep93xx_driver = { + .probe = ohci_hcd_ep93xx_drv_probe, + .remove = ohci_hcd_ep93xx_drv_remove, +#ifdef CONFIG_PM + .suspend = ohci_hcd_ep93xx_drv_suspend, + .resume = ohci_hcd_ep93xx_drv_resume, +#endif + .driver = { + .name = "ep93xx-ohci", + }, +}; + +static int __init ohci_hcd_ep93xx_init(void) +{ + return platform_driver_register(&ohci_hcd_ep93xx_driver); +} + +static void __exit ohci_hcd_ep93xx_cleanup(void) +{ + platform_driver_unregister(&ohci_hcd_ep93xx_driver); +} + +module_init(ohci_hcd_ep93xx_init); +module_exit(ohci_hcd_ep93xx_cleanup); diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c new file mode 100644 index 000000000..fc6cc1479 --- /dev/null +++ b/drivers/usb/misc/appledisplay.c @@ -0,0 +1,382 @@ +/* + * Apple Cinema Display driver + * + * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.ch) + * + * Thanks to Caskey L. Dickson for his work with acdctl. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/usb.h> +#include <linux/backlight.h> +#include <linux/timer.h> +#include <linux/workqueue.h> +#include <asm/atomic.h> +#include <asm/semaphore.h> + +#define APPLE_VENDOR_ID 0x05AC + +#define USB_REQ_GET_REPORT 0x01 +#define USB_REQ_SET_REPORT 0x09 + +#define ACD_USB_TIMEOUT 250 + +#define ACD_USB_EDID 0x0302 +#define ACD_USB_BRIGHTNESS 0x0310 + +#define ACD_BTN_NONE 0 +#define ACD_BTN_BRIGHT_UP 3 +#define ACD_BTN_BRIGHT_DOWN 4 + +#define ACD_URB_BUFFER_LEN 2 +#define ACD_MSG_BUFFER_LEN 2 + +#define APPLEDISPLAY_DEVICE(prod) \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ + USB_DEVICE_ID_MATCH_INT_CLASS | \ + USB_DEVICE_ID_MATCH_INT_PROTOCOL, \ + .idVendor = APPLE_VENDOR_ID, \ + .idProduct = (prod), \ + .bInterfaceClass = USB_CLASS_HID, \ + .bInterfaceProtocol = 0x00 + +/* table of devices that work with this driver */ +static struct usb_device_id appledisplay_table [] = { + { APPLEDISPLAY_DEVICE(0x9218) }, + { APPLEDISPLAY_DEVICE(0x9219) }, + { APPLEDISPLAY_DEVICE(0x921d) }, + + /* Terminating entry */ + { } +}; +MODULE_DEVICE_TABLE(usb, appledisplay_table); + +/* Structure to hold all of our device specific stuff */ +struct appledisplay { + struct usb_device *udev; /* usb device */ + struct urb *urb; /* usb request block */ + struct backlight_device *bd; /* backlight device */ + char *urbdata; /* interrupt URB data buffer */ + char *msgdata; /* control message data buffer */ + + struct work_struct work; + int button_pressed; + spinlock_t lock; +}; + +static atomic_t count_displays = ATOMIC_INIT(0); +static struct workqueue_struct *wq; + +static void appledisplay_complete(struct urb *urb, struct pt_regs *regs) +{ + struct appledisplay *pdata = urb->context; + unsigned long flags; + int retval; + + switch (urb->status) { + case 0: + /* success */ + break; + case -EOVERFLOW: + printk(KERN_ERR "appletouch: OVERFLOW with data " + "length %d, actual length is %d\n", + ACD_URB_BUFFER_LEN, pdata->urb->actual_length); + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* This urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", + __FUNCTION__, urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", + __FUNCTION__, urb->status); + goto exit; + } + + spin_lock_irqsave(&pdata->lock, flags); + + switch(pdata->urbdata[1]) { + case ACD_BTN_BRIGHT_UP: + case ACD_BTN_BRIGHT_DOWN: + pdata->button_pressed = 1; + queue_work(wq, &pdata->work); + break; + case ACD_BTN_NONE: + default: + pdata->button_pressed = 0; + break; + } + + spin_unlock_irqrestore(&pdata->lock, flags); + +exit: + retval = usb_submit_urb(pdata->urb, GFP_ATOMIC); + if (retval) { + err("%s - usb_submit_urb failed with result %d", + __FUNCTION__, retval); + } +} + +static int appledisplay_bl_update_status(struct backlight_device *bd) +{ + struct appledisplay *pdata = class_get_devdata(&bd->class_dev); + int retval; + + pdata->msgdata[0] = 0x10; + pdata->msgdata[1] = bd->props->brightness; + + retval = usb_control_msg( + pdata->udev, + usb_sndctrlpipe(pdata->udev, 0), + USB_REQ_SET_REPORT, + USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + ACD_USB_BRIGHTNESS, + 0, + pdata->msgdata, 2, + ACD_USB_TIMEOUT); + + return retval; +} + +static int appledisplay_bl_get_brightness(struct backlight_device *bd) +{ + struct appledisplay *pdata = class_get_devdata(&bd->class_dev); + int retval; + + retval = usb_control_msg( + pdata->udev, + usb_rcvctrlpipe(pdata->udev, 0), + USB_REQ_GET_REPORT, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + ACD_USB_BRIGHTNESS, + 0, + pdata->msgdata, 2, + ACD_USB_TIMEOUT); + + if (retval < 0) + return retval; + else + return pdata->msgdata[1]; +} + +static struct backlight_properties appledisplay_bl_data = { + .owner = THIS_MODULE, + .get_brightness = appledisplay_bl_get_brightness, + .update_status = appledisplay_bl_update_status, + .max_brightness = 0xFF +}; + +static void appledisplay_work(void *private) +{ + struct appledisplay *pdata = private; + int retval; + + up(&pdata->bd->sem); + retval = appledisplay_bl_get_brightness(pdata->bd); + if (retval >= 0) + pdata->bd->props->brightness = retval; + down(&pdata->bd->sem); + + /* Poll again in about 125ms if there's still a button pressed */ + if (pdata->button_pressed) + schedule_delayed_work(&pdata->work, HZ / 8); +} + +static int appledisplay_probe(struct usb_interface *iface, + const struct usb_device_id *id) +{ + struct appledisplay *pdata; + struct usb_device *udev = interface_to_usbdev(iface); + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + int int_in_endpointAddr = 0; + int i, retval = -ENOMEM, brightness; + char bl_name[20]; + + /* set up the endpoint information */ + /* use only the first interrupt-in endpoint */ + iface_desc = iface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { + endpoint = &iface_desc->endpoint[i].desc; + if (!int_in_endpointAddr && + (endpoint->bEndpointAddress & USB_DIR_IN) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_INT)) { + /* we found an interrupt in endpoint */ + int_in_endpointAddr = endpoint->bEndpointAddress; + break; + } + } + if (!int_in_endpointAddr) { + err("Could not find int-in endpoint"); + return -EIO; + } + + /* allocate memory for our device state and initialize it */ + pdata = kzalloc(sizeof(struct appledisplay), GFP_KERNEL); + if (!pdata) { + retval = -ENOMEM; + err("Out of memory"); + goto error; + } + + pdata->udev = udev; + + spin_lock_init(&pdata->lock); + INIT_WORK(&pdata->work, appledisplay_work, pdata); + + /* Allocate buffer for control messages */ + pdata->msgdata = kmalloc(ACD_MSG_BUFFER_LEN, GFP_KERNEL); + if (!pdata->msgdata) { + retval = -ENOMEM; + err("appledisplay: Allocating buffer for control messages " + "failed"); + goto error; + } + + /* Allocate interrupt URB */ + pdata->urb = usb_alloc_urb(0, GFP_KERNEL); + if (!pdata->urb) { + retval = -ENOMEM; + err("appledisplay: Allocating URB failed"); + goto error; + } + + /* Allocate buffer for interrupt data */ + pdata->urbdata = usb_buffer_alloc(pdata->udev, ACD_URB_BUFFER_LEN, + GFP_KERNEL, &pdata->urb->transfer_dma); + if (!pdata->urbdata) { + retval = -ENOMEM; + err("appledisplay: Allocating URB buffer failed"); + goto error; + } + + /* Configure interrupt URB */ + usb_fill_int_urb(pdata->urb, udev, + usb_rcvintpipe(udev, int_in_endpointAddr), + pdata->urbdata, ACD_URB_BUFFER_LEN, appledisplay_complete, + pdata, 1); + if (usb_submit_urb(pdata->urb, GFP_KERNEL)) { + retval = -EIO; + err("appledisplay: Submitting URB failed"); + goto error; + } + + /* Register backlight device */ + snprintf(bl_name, sizeof(bl_name), "appledisplay%d", + atomic_inc_return(&count_displays) - 1); + pdata->bd = backlight_device_register(bl_name, pdata, + &appledisplay_bl_data); + if (IS_ERR(pdata->bd)) { + err("appledisplay: Backlight registration failed"); + goto error; + } + + /* Try to get brightness */ + up(&pdata->bd->sem); + brightness = appledisplay_bl_get_brightness(pdata->bd); + down(&pdata->bd->sem); + + if (brightness < 0) { + retval = brightness; + err("appledisplay: Error while getting initial brightness: %d", retval); + goto error; + } + + /* Set brightness in backlight device */ + up(&pdata->bd->sem); + pdata->bd->props->brightness = brightness; + down(&pdata->bd->sem); + + /* save our data pointer in the interface device */ + usb_set_intfdata(iface, pdata); + + printk(KERN_INFO "appledisplay: Apple Cinema Display connected\n"); + + return 0; + +error: + if (pdata) { + if (pdata->urb) { + usb_kill_urb(pdata->urb); + if (pdata->urbdata) + usb_buffer_free(pdata->udev, ACD_URB_BUFFER_LEN, + pdata->urbdata, pdata->urb->transfer_dma); + usb_free_urb(pdata->urb); + } + if (pdata->bd) + backlight_device_unregister(pdata->bd); + kfree(pdata->msgdata); + } + usb_set_intfdata(iface, NULL); + kfree(pdata); + return retval; +} + +static void appledisplay_disconnect(struct usb_interface *iface) +{ + struct appledisplay *pdata = usb_get_intfdata(iface); + + if (pdata) { + usb_kill_urb(pdata->urb); + cancel_delayed_work(&pdata->work); + backlight_device_unregister(pdata->bd); + usb_buffer_free(pdata->udev, ACD_URB_BUFFER_LEN, + pdata->urbdata, pdata->urb->transfer_dma); + usb_free_urb(pdata->urb); + kfree(pdata->msgdata); + kfree(pdata); + } + + printk(KERN_INFO "appledisplay: Apple Cinema Display disconnected\n"); +} + +static struct usb_driver appledisplay_driver = { + .name = "appledisplay", + .probe = appledisplay_probe, + .disconnect = appledisplay_disconnect, + .id_table = appledisplay_table, +}; + +static int __init appledisplay_init(void) +{ + wq = create_singlethread_workqueue("appledisplay"); + if (!wq) { + err("Could not create work queue\n"); + return -ENOMEM; + } + + return usb_register(&appledisplay_driver); +} + +static void __exit appledisplay_exit(void) +{ + flush_workqueue(wq); + destroy_workqueue(wq); + usb_deregister(&appledisplay_driver); +} + +MODULE_AUTHOR("Michael Hanselmann"); +MODULE_DESCRIPTION("Apple Cinema Display driver"); +MODULE_LICENSE("GPL"); + +module_init(appledisplay_init); +module_exit(appledisplay_exit); diff --git a/drivers/usb/misc/cypress_cy7c63.c b/drivers/usb/misc/cypress_cy7c63.c new file mode 100644 index 000000000..9c46746d5 --- /dev/null +++ b/drivers/usb/misc/cypress_cy7c63.c @@ -0,0 +1,284 @@ +/* +* cypress_cy7c63.c +* +* Copyright (c) 2006 Oliver Bock (o.bock@fh-wolfenbuettel.de) +* +* This driver is based on the Cypress USB Driver by Marcus Maul +* (cyport) and the 2.0 version of Greg Kroah-Hartman's +* USB Skeleton driver. +* +* This is a generic driver for the Cypress CY7C63xxx family. +* For the time being it enables you to read from and write to +* the single I/O ports of the device. +* +* Supported vendors: AK Modul-Bus Computer GmbH +* (Firmware "Port-Chip") +* +* Supported devices: CY7C63001A-PC +* CY7C63001C-PXC +* CY7C63001C-SXC +* +* Supported functions: Read/Write Ports +* +* +* 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, version 2. +*/ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/usb.h> + +#define DRIVER_AUTHOR "Oliver Bock (o.bock@fh-wolfenbuettel.de)" +#define DRIVER_DESC "Cypress CY7C63xxx USB driver" + +#define CYPRESS_VENDOR_ID 0xa2c +#define CYPRESS_PRODUCT_ID 0x8 + +#define CYPRESS_READ_PORT 0x4 +#define CYPRESS_WRITE_PORT 0x5 + +#define CYPRESS_READ_RAM 0x2 +#define CYPRESS_WRITE_RAM 0x3 +#define CYPRESS_READ_ROM 0x1 + +#define CYPRESS_READ_PORT_ID0 0 +#define CYPRESS_WRITE_PORT_ID0 0 +#define CYPRESS_READ_PORT_ID1 0x2 +#define CYPRESS_WRITE_PORT_ID1 1 + +#define CYPRESS_MAX_REQSIZE 8 + + +/* table of devices that work with this driver */ +static struct usb_device_id cypress_table [] = { + { USB_DEVICE(CYPRESS_VENDOR_ID, CYPRESS_PRODUCT_ID) }, + { } +}; +MODULE_DEVICE_TABLE(usb, cypress_table); + +/* structure to hold all of our device specific stuff */ +struct cypress { + struct usb_device * udev; + unsigned char port[2]; +}; + +/* used to send usb control messages to device */ +static int vendor_command(struct cypress *dev, unsigned char request, + unsigned char address, unsigned char data) +{ + int retval = 0; + unsigned int pipe; + unsigned char *iobuf; + + /* allocate some memory for the i/o buffer*/ + iobuf = kzalloc(CYPRESS_MAX_REQSIZE, GFP_KERNEL); + if (!iobuf) { + dev_err(&dev->udev->dev, "Out of memory!\n"); + retval = -ENOMEM; + goto error; + } + + dev_dbg(&dev->udev->dev, "Sending usb_control_msg (data: %d)\n", data); + + /* prepare usb control message and send it upstream */ + pipe = usb_rcvctrlpipe(dev->udev, 0); + retval = usb_control_msg(dev->udev, pipe, request, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, + address, data, iobuf, CYPRESS_MAX_REQSIZE, + USB_CTRL_GET_TIMEOUT); + + /* store returned data (more READs to be added) */ + switch (request) { + case CYPRESS_READ_PORT: + if (address == CYPRESS_READ_PORT_ID0) { + dev->port[0] = iobuf[1]; + dev_dbg(&dev->udev->dev, + "READ_PORT0 returned: %d\n", + dev->port[0]); + } + else if (address == CYPRESS_READ_PORT_ID1) { + dev->port[1] = iobuf[1]; + dev_dbg(&dev->udev->dev, + "READ_PORT1 returned: %d\n", + dev->port[1]); + } + break; + } + + kfree(iobuf); +error: + return retval; +} + +/* write port value */ +static ssize_t write_port(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count, + int port_num, int write_id) +{ + int value = -1; + int result = 0; + + struct usb_interface *intf = to_usb_interface(dev); + struct cypress *cyp = usb_get_intfdata(intf); + + dev_dbg(&cyp->udev->dev, "WRITE_PORT%d called\n", port_num); + + /* validate input data */ + if (sscanf(buf, "%d", &value) < 1) { + result = -EINVAL; + goto error; + } + if (value < 0 || value > 255) { + result = -EINVAL; + goto error; + } + + result = vendor_command(cyp, CYPRESS_WRITE_PORT, write_id, + (unsigned char)value); + + dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n", result); +error: + return result < 0 ? result : count; +} + +/* attribute callback handler (write) */ +static ssize_t set_port0_handler(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return write_port(dev, attr, buf, count, 0, CYPRESS_WRITE_PORT_ID0); +} + +/* attribute callback handler (write) */ +static ssize_t set_port1_handler(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return write_port(dev, attr, buf, count, 1, CYPRESS_WRITE_PORT_ID1); +} + +/* read port value */ +static ssize_t read_port(struct device *dev, struct device_attribute *attr, + char *buf, int port_num, int read_id) +{ + int result = 0; + + struct usb_interface *intf = to_usb_interface(dev); + struct cypress *cyp = usb_get_intfdata(intf); + + dev_dbg(&cyp->udev->dev, "READ_PORT%d called\n", port_num); + + result = vendor_command(cyp, CYPRESS_READ_PORT, read_id, 0); + + dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n", result); + + return sprintf(buf, "%d", cyp->port[port_num]); +} + +/* attribute callback handler (read) */ +static ssize_t get_port0_handler(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return read_port(dev, attr, buf, 0, CYPRESS_READ_PORT_ID0); +} + +/* attribute callback handler (read) */ +static ssize_t get_port1_handler(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return read_port(dev, attr, buf, 1, CYPRESS_READ_PORT_ID1); +} + +static DEVICE_ATTR(port0, S_IWUGO | S_IRUGO, + get_port0_handler, set_port0_handler); + +static DEVICE_ATTR(port1, S_IWUGO | S_IRUGO, + get_port1_handler, set_port1_handler); + + +static int cypress_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct cypress *dev = NULL; + int retval = -ENOMEM; + + /* allocate memory for our device state and initialize it */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev == NULL) { + dev_err(&interface->dev, "Out of memory!\n"); + goto error; + } + + dev->udev = usb_get_dev(interface_to_usbdev(interface)); + + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, dev); + + /* create device attribute files */ + device_create_file(&interface->dev, &dev_attr_port0); + device_create_file(&interface->dev, &dev_attr_port1); + + /* let the user know that the device is now attached */ + dev_info(&interface->dev, + "Cypress CY7C63xxx device now attached\n"); + + retval = 0; +error: + return retval; +} + +static void cypress_disconnect(struct usb_interface *interface) +{ + struct cypress *dev; + + dev = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + + /* remove device attribute files */ + device_remove_file(&interface->dev, &dev_attr_port0); + device_remove_file(&interface->dev, &dev_attr_port1); + + usb_put_dev(dev->udev); + + dev_info(&interface->dev, + "Cypress CY7C63xxx device now disconnected\n"); + + kfree(dev); +} + +static struct usb_driver cypress_driver = { + .name = "cypress_cy7c63", + .probe = cypress_probe, + .disconnect = cypress_disconnect, + .id_table = cypress_table, +}; + +static int __init cypress_init(void) +{ + int result; + + /* register this driver with the USB subsystem */ + result = usb_register(&cypress_driver); + if (result) { + err("Function usb_register failed! Error number: %d\n", result); + } + + return result; +} + +static void __exit cypress_exit(void) +{ + /* deregister this driver with the USB subsystem */ + usb_deregister(&cypress_driver); +} + +module_init(cypress_init); +module_exit(cypress_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); + +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c new file mode 100644 index 000000000..d29638daa --- /dev/null +++ b/drivers/usb/serial/sierra.c @@ -0,0 +1,75 @@ +/* + * Sierra Wireless CDMA Wireless Serial USB driver + * + * Current Copy modified by: Kevin Lloyd <linux@sierrawireless.com> + * Original Copyright (C) 2005-2006 Greg Kroah-Hartman <gregkh@suse.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/tty.h> +#include <linux/module.h> +#include <linux/usb.h> +#include <linux/usb/serial.h> + +static struct usb_device_id id_table [] = { + { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ + { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ + { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ + { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ + { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ + { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ + { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */ + { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ + /* Following devices are supported in the airprime.c driver */ + /* { USB_DEVICE(0x1199, 0x0112) }, */ /* Sierra Wireless AirCard 580 */ + /* { USB_DEVICE(0x0F3D, 0x0112) }, */ /* AirPrime/Sierra PC 5220 */ + { } +}; +MODULE_DEVICE_TABLE(usb, id_table); + +static struct usb_driver sierra_driver = { + .name = "sierra_wireless", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, +}; + +static struct usb_serial_driver sierra_device = { + .driver = { + .owner = THIS_MODULE, + .name = "Sierra_Wireless", + }, + .id_table = id_table, + .num_interrupt_in = NUM_DONT_CARE, + .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = NUM_DONT_CARE, + .num_ports = 3, +}; + +static int __init sierra_init(void) +{ + int retval; + + retval = usb_serial_register(&sierra_device); + if (retval) + return retval; + retval = usb_register(&sierra_driver); + if (retval) + usb_serial_deregister(&sierra_device); + return retval; +} + +static void __exit sierra_exit(void) +{ + usb_deregister(&sierra_driver); + usb_serial_deregister(&sierra_device); +} + +module_init(sierra_init); +module_exit(sierra_exit); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c new file mode 100644 index 000000000..585eb7b9e --- /dev/null +++ b/drivers/video/aty/radeon_backlight.c @@ -0,0 +1,247 @@ +/* + * Backlight code for ATI Radeon based graphic cards + * + * Copyright (c) 2000 Ani Joshi <ajoshi@kernel.crashing.org> + * Copyright (c) 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org> + * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "radeonfb.h" +#include <linux/backlight.h> + +#ifdef CONFIG_PMAC_BACKLIGHT +#include <asm/backlight.h> +#endif + +#define MAX_RADEON_LEVEL 0xFF + +static struct backlight_properties radeon_bl_data; + +struct radeon_bl_privdata { + struct radeonfb_info *rinfo; + uint8_t negative; +}; + +static int radeon_bl_get_level_brightness(struct radeon_bl_privdata *pdata, + int level) +{ + struct fb_info *info = pdata->rinfo->info; + int rlevel; + + mutex_lock(&info->bl_mutex); + + /* Get and convert the value */ + rlevel = pdata->rinfo->info->bl_curve[level] * + FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL; + + mutex_unlock(&info->bl_mutex); + + if (rlevel < 0) + rlevel = 0; + else if (rlevel > MAX_RADEON_LEVEL) + rlevel = MAX_RADEON_LEVEL; + + if (pdata->negative) + rlevel = MAX_RADEON_LEVEL - rlevel; + + return rlevel; +} + +static int radeon_bl_update_status(struct backlight_device *bd) +{ + struct radeon_bl_privdata *pdata = class_get_devdata(&bd->class_dev); + struct radeonfb_info *rinfo = pdata->rinfo; + u32 lvds_gen_cntl, tmpPixclksCntl; + int level; + + if (rinfo->mon1_type != MT_LCD) + return 0; + + /* We turn off the LCD completely instead of just dimming the + * backlight. This provides some greater power saving and the display + * is useless without backlight anyway. + */ + if (bd->props->power != FB_BLANK_UNBLANK || + bd->props->fb_blank != FB_BLANK_UNBLANK) + level = 0; + else + level = bd->props->brightness; + + del_timer_sync(&rinfo->lvds_timer); + radeon_engine_idle(); + + lvds_gen_cntl = INREG(LVDS_GEN_CNTL); + if (level > 0) { + lvds_gen_cntl &= ~LVDS_DISPLAY_DIS; + if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) { + lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON); + lvds_gen_cntl |= LVDS_BLON | LVDS_EN; + OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); + lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; + lvds_gen_cntl |= + (radeon_bl_get_level_brightness(pdata, level) << + LVDS_BL_MOD_LEVEL_SHIFT); + lvds_gen_cntl |= LVDS_ON; + lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN); + rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; + mod_timer(&rinfo->lvds_timer, + jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); + } else { + lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK; + lvds_gen_cntl |= + (radeon_bl_get_level_brightness(pdata, level) << + LVDS_BL_MOD_LEVEL_SHIFT); + OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); + } + rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; + rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl + & LVDS_STATE_MASK; + } else { + /* Asic bug, when turning off LVDS_ON, we have to make sure + RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off + */ + tmpPixclksCntl = INPLL(PIXCLKS_CNTL); + if (rinfo->is_mobility || rinfo->is_IGP) + OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb); + lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN); + lvds_gen_cntl |= (radeon_bl_get_level_brightness(pdata, 0) << + LVDS_BL_MOD_LEVEL_SHIFT); + lvds_gen_cntl |= LVDS_DISPLAY_DIS; + OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); + udelay(100); + lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN); + OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl); + lvds_gen_cntl &= ~(LVDS_DIGON); + rinfo->pending_lvds_gen_cntl = lvds_gen_cntl; + mod_timer(&rinfo->lvds_timer, + jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay)); + if (rinfo->is_mobility || rinfo->is_IGP) + OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl); + } + rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; + rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK); + + return 0; +} + +static int radeon_bl_get_brightness(struct backlight_device *bd) +{ + return bd->props->brightness; +} + +static struct backlight_properties radeon_bl_data = { + .owner = THIS_MODULE, + .get_brightness = radeon_bl_get_brightness, + .update_status = radeon_bl_update_status, + .max_brightness = (FB_BACKLIGHT_LEVELS - 1), +}; + +void radeonfb_bl_init(struct radeonfb_info *rinfo) +{ + struct backlight_device *bd; + struct radeon_bl_privdata *pdata; + char name[12]; + + if (rinfo->mon1_type != MT_LCD) + return; + +#ifdef CONFIG_PMAC_BACKLIGHT + if (!pmac_has_backlight_type("ati") && + !pmac_has_backlight_type("mnca")) + return; +#endif + + pdata = kmalloc(sizeof(struct radeon_bl_privdata), GFP_KERNEL); + if (!pdata) { + printk("radeonfb: Memory allocation failed\n"); + goto error; + } + + snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node); + + bd = backlight_device_register(name, pdata, &radeon_bl_data); + if (IS_ERR(bd)) { + rinfo->info->bl_dev = NULL; + printk("radeonfb: Backlight registration failed\n"); + goto error; + } + + pdata->rinfo = rinfo; + + /* Pardon me for that hack... maybe some day we can figure out in what + * direction backlight should work on a given panel? + */ + pdata->negative = + (rinfo->family != CHIP_FAMILY_RV200 && + rinfo->family != CHIP_FAMILY_RV250 && + rinfo->family != CHIP_FAMILY_RV280 && + rinfo->family != CHIP_FAMILY_RV350); + +#ifdef CONFIG_PMAC_BACKLIGHT + pdata->negative = pdata->negative || + machine_is_compatible("PowerBook4,3") || + machine_is_compatible("PowerBook6,3") || + machine_is_compatible("PowerBook6,5"); +#endif + + mutex_lock(&rinfo->info->bl_mutex); + rinfo->info->bl_dev = bd; + fb_bl_default_curve(rinfo->info, 0, + 63 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL, + 217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL); + mutex_unlock(&rinfo->info->bl_mutex); + + down(&bd->sem); + bd->props->brightness = radeon_bl_data.max_brightness; + bd->props->power = FB_BLANK_UNBLANK; + bd->props->update_status(bd); + up(&bd->sem); + +#ifdef CONFIG_PMAC_BACKLIGHT + mutex_lock(&pmac_backlight_mutex); + if (!pmac_backlight) + pmac_backlight = bd; + mutex_unlock(&pmac_backlight_mutex); +#endif + + printk("radeonfb: Backlight initialized (%s)\n", name); + + return; + +error: + kfree(pdata); + return; +} + +void radeonfb_bl_exit(struct radeonfb_info *rinfo) +{ +#ifdef CONFIG_PMAC_BACKLIGHT + mutex_lock(&pmac_backlight_mutex); +#endif + + mutex_lock(&rinfo->info->bl_mutex); + if (rinfo->info->bl_dev) { + struct radeon_bl_privdata *pdata; + +#ifdef CONFIG_PMAC_BACKLIGHT + if (pmac_backlight == rinfo->info->bl_dev) + pmac_backlight = NULL; +#endif + + pdata = class_get_devdata(&rinfo->info->bl_dev->class_dev); + backlight_device_unregister(rinfo->info->bl_dev); + kfree(pdata); + rinfo->info->bl_dev = NULL; + + printk("radeonfb: Backlight unloaded\n"); + } + mutex_unlock(&rinfo->info->bl_mutex); + +#ifdef CONFIG_PMAC_BACKLIGHT + mutex_unlock(&pmac_backlight_mutex); +#endif +} diff --git a/drivers/video/fb_notify.c b/drivers/video/fb_notify.c new file mode 100644 index 000000000..8c020389e --- /dev/null +++ b/drivers/video/fb_notify.c @@ -0,0 +1,46 @@ +/* + * linux/drivers/video/fb_notify.c + * + * Copyright (C) 2006 Antonino Daplas <adaplas@pol.net> + * + * 2001 - Documented with DocBook + * - Brad Douglas <brad@neruo.com> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ +#include <linux/fb.h> +#include <linux/notifier.h> + +static BLOCKING_NOTIFIER_HEAD(fb_notifier_list); + +/** + * fb_register_client - register a client notifier + * @nb: notifier block to callback on events + */ +int fb_register_client(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&fb_notifier_list, nb); +} +EXPORT_SYMBOL(fb_register_client); + +/** + * fb_unregister_client - unregister a client notifier + * @nb: notifier block to callback on events + */ +int fb_unregister_client(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&fb_notifier_list, nb); +} +EXPORT_SYMBOL(fb_unregister_client); + +/** + * fb_notifier_call_chain - notify clients of fb_events + * + */ +int fb_notifier_call_chain(unsigned long val, void *v) +{ + return blocking_notifier_call_chain(&fb_notifier_list, val, v); +} +EXPORT_SYMBOL_GPL(fb_notifier_call_chain); diff --git a/drivers/video/imacfb.c b/drivers/video/imacfb.c new file mode 100644 index 000000000..18ea4a549 --- /dev/null +++ b/drivers/video/imacfb.c @@ -0,0 +1,380 @@ +/* + * framebuffer driver for Intel Based Mac's + * + * (c) 2006 Edgar Hucek <gimli@dark-green.com> + * Original imac driver written by Gerd Knorr <kraxel@goldbach.in-berlin.de> + * + */ + +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/fb.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/screen_info.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/dmi.h> +#include <linux/efi.h> + +#include <asm/io.h> + +#include <video/vga.h> + +typedef enum _MAC_TYPE { + M_I17, + M_I20, + M_MINI, + M_MACBOOK, + M_UNKNOWN +} MAC_TYPE; + +/* --------------------------------------------------------------------- */ + +static struct fb_var_screeninfo imacfb_defined __initdata = { + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .right_margin = 32, + .upper_margin = 16, + .lower_margin = 4, + .vsync_len = 4, + .vmode = FB_VMODE_NONINTERLACED, +}; + +static struct fb_fix_screeninfo imacfb_fix __initdata = { + .id = "IMAC VGA", + .type = FB_TYPE_PACKED_PIXELS, + .accel = FB_ACCEL_NONE, + .visual = FB_VISUAL_TRUECOLOR, +}; + +static int inverse; +static int model = M_UNKNOWN; +static int manual_height; +static int manual_width; + +static int set_system(struct dmi_system_id *id) +{ + printk(KERN_INFO "imacfb: %s detected - set system to %ld\n", + id->ident, (long)id->driver_data); + + model = (long)id->driver_data; + + return 0; +} + +static struct dmi_system_id __initdata dmi_system_table[] = { + { set_system, "iMac4,1", { + DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME,"iMac4,1") }, (void*)M_I17}, + { set_system, "MacBookPro1,1", { + DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro1,1") }, (void*)M_I17}, + { set_system, "MacBook1,1", { + DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME,"MacBook1,1")}, (void *)M_MACBOOK}, + { set_system, "Macmini1,1", { + DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME,"Macmini1,1")}, (void *)M_MINI}, + {}, +}; + +#define DEFAULT_FB_MEM 1024*1024*16 + +/* --------------------------------------------------------------------- */ + +static int imacfb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + /* + * Set a single color register. The values supplied are + * already rounded down to the hardware's capabilities + * (according to the entries in the `var' structure). Return + * != 0 for invalid regno. + */ + + if (regno >= info->cmap.len) + return 1; + + if (regno < 16) { + red >>= 8; + green >>= 8; + blue >>= 8; + ((u32 *)(info->pseudo_palette))[regno] = + (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset); + } + return 0; +} + +static struct fb_ops imacfb_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = imacfb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +static int __init imacfb_setup(char *options) +{ + char *this_opt; + + if (!options || !*options) + return 0; + + while ((this_opt = strsep(&options, ",")) != NULL) { + if (!*this_opt) continue; + + if (!strcmp(this_opt, "inverse")) + inverse = 1; + else if (!strcmp(this_opt, "i17")) + model = M_I17; + else if (!strcmp(this_opt, "i20")) + model = M_I20; + else if (!strcmp(this_opt, "mini")) + model = M_MINI; + else if (!strcmp(this_opt, "macbook")) + model = M_MACBOOK; + else if (!strncmp(this_opt, "height:", 7)) + manual_height = simple_strtoul(this_opt+7, NULL, 0); + else if (!strncmp(this_opt, "width:", 6)) + manual_width = simple_strtoul(this_opt+6, NULL, 0); + } + return 0; +} + +static int __init imacfb_probe(struct platform_device *dev) +{ + struct fb_info *info; + int err; + unsigned int size_vmode; + unsigned int size_remap; + unsigned int size_total; + + screen_info.lfb_depth = 32; + screen_info.lfb_size = DEFAULT_FB_MEM / 0x10000; + screen_info.pages=1; + screen_info.blue_size = 8; + screen_info.blue_pos = 0; + screen_info.green_size = 8; + screen_info.green_pos = 8; + screen_info.red_size = 8; + screen_info.red_pos = 16; + screen_info.rsvd_size = 8; + screen_info.rsvd_pos = 24; + + switch (model) { + case M_I17: + screen_info.lfb_width = 1440; + screen_info.lfb_height = 900; + screen_info.lfb_linelength = 1472 * 4; + screen_info.lfb_base = 0x80010000; + break; + case M_I20: + screen_info.lfb_width = 1680; + screen_info.lfb_height = 1050; + screen_info.lfb_linelength = 1728 * 4; + screen_info.lfb_base = 0x80010000; + break; + case M_MINI: + screen_info.lfb_width = 1024; + screen_info.lfb_height = 768; + screen_info.lfb_linelength = 2048 * 4; + screen_info.lfb_base = 0x80000000; + break; + case M_MACBOOK: + screen_info.lfb_width = 1280; + screen_info.lfb_height = 800; + screen_info.lfb_linelength = 2048 * 4; + screen_info.lfb_base = 0x80000000; + break; + } + + /* if the user wants to manually specify height/width, + we will override the defaults */ + /* TODO: eventually get auto-detection working */ + if (manual_height > 0) + screen_info.lfb_height = manual_height; + if (manual_width > 0) + screen_info.lfb_width = manual_width; + + imacfb_fix.smem_start = screen_info.lfb_base; + imacfb_defined.bits_per_pixel = screen_info.lfb_depth; + imacfb_defined.xres = screen_info.lfb_width; + imacfb_defined.yres = screen_info.lfb_height; + imacfb_fix.line_length = screen_info.lfb_linelength; + + /* size_vmode -- that is the amount of memory needed for the + * used video mode, i.e. the minimum amount of + * memory we need. */ + size_vmode = imacfb_defined.yres * imacfb_fix.line_length; + + /* size_total -- all video memory we have. Used for + * entries, ressource allocation and bounds + * checking. */ + size_total = screen_info.lfb_size * 65536; + if (size_total < size_vmode) + size_total = size_vmode; + + /* size_remap -- the amount of video memory we are going to + * use for imacfb. With modern cards it is no + * option to simply use size_total as that + * wastes plenty of kernel address space. */ + size_remap = size_vmode * 2; + if (size_remap < size_vmode) + size_remap = size_vmode; + if (size_remap > size_total) + size_remap = size_total; + imacfb_fix.smem_len = size_remap; + +#ifndef __i386__ + screen_info.imacpm_seg = 0; +#endif + + if (!request_mem_region(imacfb_fix.smem_start, size_total, "imacfb")) { + printk(KERN_WARNING + "imacfb: cannot reserve video memory at 0x%lx\n", + imacfb_fix.smem_start); + /* We cannot make this fatal. Sometimes this comes from magic + spaces our resource handlers simply don't know about */ + } + + info = framebuffer_alloc(sizeof(u32) * 16, &dev->dev); + if (!info) { + err = -ENOMEM; + goto err_release_mem; + } + info->pseudo_palette = info->par; + info->par = NULL; + + info->screen_base = ioremap(imacfb_fix.smem_start, imacfb_fix.smem_len); + if (!info->screen_base) { + printk(KERN_ERR "imacfb: abort, cannot ioremap video memory " + "0x%x @ 0x%lx\n", + imacfb_fix.smem_len, imacfb_fix.smem_start); + err = -EIO; + goto err_unmap; + } + + printk(KERN_INFO "imacfb: framebuffer at 0x%lx, mapped to 0x%p, " + "using %dk, total %dk\n", + imacfb_fix.smem_start, info->screen_base, + size_remap/1024, size_total/1024); + printk(KERN_INFO "imacfb: mode is %dx%dx%d, linelength=%d, pages=%d\n", + imacfb_defined.xres, imacfb_defined.yres, + imacfb_defined.bits_per_pixel, imacfb_fix.line_length, + screen_info.pages); + + imacfb_defined.xres_virtual = imacfb_defined.xres; + imacfb_defined.yres_virtual = imacfb_fix.smem_len / + imacfb_fix.line_length; + printk(KERN_INFO "imacfb: scrolling: redraw\n"); + imacfb_defined.yres_virtual = imacfb_defined.yres; + + /* some dummy values for timing to make fbset happy */ + imacfb_defined.pixclock = 10000000 / imacfb_defined.xres * + 1000 / imacfb_defined.yres; + imacfb_defined.left_margin = (imacfb_defined.xres / 8) & 0xf8; + imacfb_defined.hsync_len = (imacfb_defined.xres / 8) & 0xf8; + + imacfb_defined.red.offset = screen_info.red_pos; + imacfb_defined.red.length = screen_info.red_size; + imacfb_defined.green.offset = screen_info.green_pos; + imacfb_defined.green.length = screen_info.green_size; + imacfb_defined.blue.offset = screen_info.blue_pos; + imacfb_defined.blue.length = screen_info.blue_size; + imacfb_defined.transp.offset = screen_info.rsvd_pos; + imacfb_defined.transp.length = screen_info.rsvd_size; + + printk(KERN_INFO "imacfb: %s: " + "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n", + "Truecolor", + screen_info.rsvd_size, + screen_info.red_size, + screen_info.green_size, + screen_info.blue_size, + screen_info.rsvd_pos, + screen_info.red_pos, + screen_info.green_pos, + screen_info.blue_pos); + + imacfb_fix.ypanstep = 0; + imacfb_fix.ywrapstep = 0; + + /* request failure does not faze us, as vgacon probably has this + * region already (FIXME) */ + request_region(0x3c0, 32, "imacfb"); + + info->fbops = &imacfb_ops; + info->var = imacfb_defined; + info->fix = imacfb_fix; + info->flags = FBINFO_FLAG_DEFAULT; + + if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { + err = -ENOMEM; + goto err_unmap; + } + if (register_framebuffer(info)<0) { + err = -EINVAL; + goto err_fb_dealoc; + } + printk(KERN_INFO "fb%d: %s frame buffer device\n", + info->node, info->fix.id); + return 0; + +err_fb_dealoc: + fb_dealloc_cmap(&info->cmap); +err_unmap: + iounmap(info->screen_base); + framebuffer_release(info); +err_release_mem: + release_mem_region(imacfb_fix.smem_start, size_total); + return err; +} + +static struct platform_driver imacfb_driver = { + .probe = imacfb_probe, + .driver = { + .name = "imacfb", + }, +}; + +static struct platform_device imacfb_device = { + .name = "imacfb", +}; + +static int __init imacfb_init(void) +{ + int ret; + char *option = NULL; + + if (!efi_enabled) + return -ENODEV; + if (!dmi_check_system(dmi_system_table)) + return -ENODEV; + if (model == M_UNKNOWN) + return -ENODEV; + + if (fb_get_options("imacfb", &option)) + return -ENODEV; + + imacfb_setup(option); + ret = platform_driver_register(&imacfb_driver); + + if (!ret) { + ret = platform_device_register(&imacfb_device); + if (ret) + platform_driver_unregister(&imacfb_driver); + } + return ret; +} +module_init(imacfb_init); + +MODULE_LICENSE("GPL"); diff --git a/drivers/video/mbx/Makefile b/drivers/video/mbx/Makefile new file mode 100644 index 000000000..16c1165cf --- /dev/null +++ b/drivers/video/mbx/Makefile @@ -0,0 +1,4 @@ +# Makefile for the 2700G controller driver. + +obj-$(CONFIG_FB_MBX) += mbxfb.o +obj-$(CONFIG_FB_MBX_DEBUG) += mbxfbdebugfs.o diff --git a/drivers/video/mbx/mbxdebugfs.c b/drivers/video/mbx/mbxdebugfs.c new file mode 100644 index 000000000..84aab3ad0 --- /dev/null +++ b/drivers/video/mbx/mbxdebugfs.c @@ -0,0 +1,188 @@ +#include <linux/debugfs.h> + +#define BIG_BUFFER_SIZE (1024) + +static char big_buffer[BIG_BUFFER_SIZE]; + +struct mbxfb_debugfs_data { + struct dentry *dir; + struct dentry *sysconf; + struct dentry *clock; + struct dentry *display; + struct dentry *gsctl; +}; + +static int open_file_generic(struct inode *inode, struct file *file) +{ + file->private_data = inode->u.generic_ip; + return 0; +} + +static ssize_t write_file_dummy(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + return count; +} + +static ssize_t sysconf_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char * s = big_buffer; + + s += sprintf(s, "SYSCFG = %08lx\n", SYSCFG); + s += sprintf(s, "PFBASE = %08lx\n", PFBASE); + s += sprintf(s, "PFCEIL = %08lx\n", PFCEIL); + s += sprintf(s, "POLLFLAG = %08lx\n", POLLFLAG); + s += sprintf(s, "SYSRST = %08lx\n", SYSRST); + + return simple_read_from_buffer(userbuf, count, ppos, + big_buffer, s-big_buffer); +} + + +static ssize_t gsctl_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char * s = big_buffer; + + s += sprintf(s, "GSCTRL = %08lx\n", GSCTRL); + s += sprintf(s, "VSCTRL = %08lx\n", VSCTRL); + s += sprintf(s, "GBBASE = %08lx\n", GBBASE); + s += sprintf(s, "VBBASE = %08lx\n", VBBASE); + s += sprintf(s, "GDRCTRL = %08lx\n", GDRCTRL); + s += sprintf(s, "VCMSK = %08lx\n", VCMSK); + s += sprintf(s, "GSCADR = %08lx\n", GSCADR); + s += sprintf(s, "VSCADR = %08lx\n", VSCADR); + s += sprintf(s, "VUBASE = %08lx\n", VUBASE); + s += sprintf(s, "VVBASE = %08lx\n", VVBASE); + s += sprintf(s, "GSADR = %08lx\n", GSADR); + s += sprintf(s, "VSADR = %08lx\n", VSADR); + s += sprintf(s, "HCCTRL = %08lx\n", HCCTRL); + s += sprintf(s, "HCSIZE = %08lx\n", HCSIZE); + s += sprintf(s, "HCPOS = %08lx\n", HCPOS); + s += sprintf(s, "HCBADR = %08lx\n", HCBADR); + s += sprintf(s, "HCCKMSK = %08lx\n", HCCKMSK); + s += sprintf(s, "GPLUT = %08lx\n", GPLUT); + + return simple_read_from_buffer(userbuf, count, ppos, + big_buffer, s-big_buffer); +} + +static ssize_t display_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char * s = big_buffer; + + s += sprintf(s, "DSCTRL = %08lx\n", DSCTRL); + s += sprintf(s, "DHT01 = %08lx\n", DHT01); + s += sprintf(s, "DHT02 = %08lx\n", DHT02); + s += sprintf(s, "DHT03 = %08lx\n", DHT03); + s += sprintf(s, "DVT01 = %08lx\n", DVT01); + s += sprintf(s, "DVT02 = %08lx\n", DVT02); + s += sprintf(s, "DVT03 = %08lx\n", DVT03); + s += sprintf(s, "DBCOL = %08lx\n", DBCOL); + s += sprintf(s, "BGCOLOR = %08lx\n", BGCOLOR); + s += sprintf(s, "DINTRS = %08lx\n", DINTRS); + s += sprintf(s, "DINTRE = %08lx\n", DINTRE); + s += sprintf(s, "DINTRCNT = %08lx\n", DINTRCNT); + s += sprintf(s, "DSIG = %08lx\n", DSIG); + s += sprintf(s, "DMCTRL = %08lx\n", DMCTRL); + s += sprintf(s, "CLIPCTRL = %08lx\n", CLIPCTRL); + s += sprintf(s, "SPOCTRL = %08lx\n", SPOCTRL); + s += sprintf(s, "SVCTRL = %08lx\n", SVCTRL); + s += sprintf(s, "DLSTS = %08lx\n", DLSTS); + s += sprintf(s, "DLLCTRL = %08lx\n", DLLCTRL); + s += sprintf(s, "DVLNUM = %08lx\n", DVLNUM); + s += sprintf(s, "DUCTRL = %08lx\n", DUCTRL); + s += sprintf(s, "DVECTRL = %08lx\n", DVECTRL); + s += sprintf(s, "DHDET = %08lx\n", DHDET); + s += sprintf(s, "DVDET = %08lx\n", DVDET); + s += sprintf(s, "DODMSK = %08lx\n", DODMSK); + s += sprintf(s, "CSC01 = %08lx\n", CSC01); + s += sprintf(s, "CSC02 = %08lx\n", CSC02); + s += sprintf(s, "CSC03 = %08lx\n", CSC03); + s += sprintf(s, "CSC04 = %08lx\n", CSC04); + s += sprintf(s, "CSC05 = %08lx\n", CSC05); + + return simple_read_from_buffer(userbuf, count, ppos, + big_buffer, s-big_buffer); +} + +static ssize_t clock_read_file(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + char * s = big_buffer; + + s += sprintf(s, "SYSCLKSRC = %08lx\n", SYSCLKSRC); + s += sprintf(s, "PIXCLKSRC = %08lx\n", PIXCLKSRC); + s += sprintf(s, "CLKSLEEP = %08lx\n", CLKSLEEP); + s += sprintf(s, "COREPLL = %08lx\n", COREPLL); + s += sprintf(s, "DISPPLL = %08lx\n", DISPPLL); + s += sprintf(s, "PLLSTAT = %08lx\n", PLLSTAT); + s += sprintf(s, "VOVRCLK = %08lx\n", VOVRCLK); + s += sprintf(s, "PIXCLK = %08lx\n", PIXCLK); + s += sprintf(s, "MEMCLK = %08lx\n", MEMCLK); + s += sprintf(s, "M24CLK = %08lx\n", M24CLK); + s += sprintf(s, "MBXCLK = %08lx\n", MBXCLK); + s += sprintf(s, "SDCLK = %08lx\n", SDCLK); + s += sprintf(s, "PIXCLKDIV = %08lx\n", PIXCLKDIV); + + return simple_read_from_buffer(userbuf, count, ppos, + big_buffer, s-big_buffer); +} + +static struct file_operations sysconf_fops = { + .read = sysconf_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; + +static struct file_operations clock_fops = { + .read = clock_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; + +static struct file_operations display_fops = { + .read = display_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; + +static struct file_operations gsctl_fops = { + .read = gsctl_read_file, + .write = write_file_dummy, + .open = open_file_generic, +}; + + +static void __devinit mbxfb_debugfs_init(struct fb_info *fbi) +{ + struct mbxfb_info *mfbi = fbi->par; + struct mbxfb_debugfs_data *dbg; + + dbg = kzalloc(sizeof(struct mbxfb_debugfs_data), GFP_KERNEL); + mfbi->debugfs_data = dbg; + + dbg->dir = debugfs_create_dir("mbxfb", NULL); + dbg->sysconf = debugfs_create_file("sysconf", 0444, dbg->dir, + fbi, &sysconf_fops); + dbg->clock = debugfs_create_file("clock", 0444, dbg->dir, + fbi, &clock_fops); + dbg->display = debugfs_create_file("display", 0444, dbg->dir, + fbi, &display_fops); + dbg->gsctl = debugfs_create_file("gsctl", 0444, dbg->dir, + fbi, &gsctl_fops); +} + +static void __devexit mbxfb_debugfs_remove(struct fb_info *fbi) +{ + struct mbxfb_info *mfbi = fbi->par; + struct mbxfb_debugfs_data *dbg = mfbi->debugfs_data; + + debugfs_remove(dbg->gsctl); + debugfs_remove(dbg->display); + debugfs_remove(dbg->clock); + debugfs_remove(dbg->sysconf); + debugfs_remove(dbg->dir); +} diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c new file mode 100644 index 000000000..6849ab75d --- /dev/null +++ b/drivers/video/mbx/mbxfb.c @@ -0,0 +1,683 @@ +/* + * linux/drivers/video/mbx/mbxfb.c + * + * Copyright (C) 2006 Compulab, Ltd. + * Mike Rapoport <mike@compulab.co.il> + * + * Based on pxafb.c + * + * 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. + * + * Intel 2700G (Marathon) Graphics Accelerator Frame Buffer Driver + * + */ + +#include <linux/delay.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include <asm/io.h> + +#include <video/mbxfb.h> + +#include "regs.h" +#include "reg_bits.h" + +static unsigned long virt_base_2700; + +#define MIN_XRES 16 +#define MIN_YRES 16 +#define MAX_XRES 2048 +#define MAX_YRES 2048 + +#define MAX_PALETTES 16 + +/* FIXME: take care of different chip revisions with different sizes + of ODFB */ +#define MEMORY_OFFSET 0x60000 + +struct mbxfb_info { + struct device *dev; + + struct resource *fb_res; + struct resource *fb_req; + + struct resource *reg_res; + struct resource *reg_req; + + void __iomem *fb_virt_addr; + unsigned long fb_phys_addr; + + void __iomem *reg_virt_addr; + unsigned long reg_phys_addr; + + int (*platform_probe) (struct fb_info * fb); + int (*platform_remove) (struct fb_info * fb); + + u32 pseudo_palette[MAX_PALETTES]; +#ifdef CONFIG_FB_MBX_DEBUG + void *debugfs_data; +#endif + +}; + +static struct fb_var_screeninfo mbxfb_default __devinitdata = { + .xres = 640, + .yres = 480, + .xres_virtual = 640, + .yres_virtual = 480, + .bits_per_pixel = 16, + .red = {11, 5, 0}, + .green = {5, 6, 0}, + .blue = {0, 5, 0}, + .activate = FB_ACTIVATE_TEST, + .height = -1, + .width = -1, + .pixclock = 40000, + .left_margin = 48, + .right_margin = 16, + .upper_margin = 33, + .lower_margin = 10, + .hsync_len = 96, + .vsync_len = 2, + .vmode = FB_VMODE_NONINTERLACED, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, +}; + +static struct fb_fix_screeninfo mbxfb_fix __devinitdata = { + .id = "MBX", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .xpanstep = 0, + .ypanstep = 0, + .ywrapstep = 0, + .accel = FB_ACCEL_NONE, +}; + +struct pixclock_div { + u8 m; + u8 n; + u8 p; +}; + +static unsigned int mbxfb_get_pixclock(unsigned int pixclock_ps, + struct pixclock_div *div) +{ + u8 m, n, p; + unsigned int err = 0; + unsigned int min_err = ~0x0; + unsigned int clk; + unsigned int best_clk = 0; + unsigned int ref_clk = 13000; /* FIXME: take from platform data */ + unsigned int pixclock; + + /* convert pixclock to KHz */ + pixclock = PICOS2KHZ(pixclock_ps); + + for (m = 1; m < 64; m++) { + for (n = 1; n < 8; n++) { + for (p = 0; p < 8; p++) { + clk = (ref_clk * m) / (n * (1 << p)); + err = (clk > pixclock) ? (clk - pixclock) : + (pixclock - clk); + if (err < min_err) { + min_err = err; + best_clk = clk; + div->m = m; + div->n = n; + div->p = p; + } + } + } + } + return KHZ2PICOS(best_clk); +} + +static int mbxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int trans, struct fb_info *info) +{ + u32 val, ret = 1; + + if (regno < MAX_PALETTES) { + u32 *pal = info->pseudo_palette; + + val = (red & 0xf800) | ((green & 0xfc00) >> 5) | + ((blue & 0xf800) >> 11); + pal[regno] = val; + ret = 0; + } + + return ret; +} + +static int mbxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + struct pixclock_div div; + + var->pixclock = mbxfb_get_pixclock(var->pixclock, &div); + + if (var->xres < MIN_XRES) + var->xres = MIN_XRES; + if (var->yres < MIN_YRES) + var->yres = MIN_YRES; + if (var->xres > MAX_XRES) + return -EINVAL; + if (var->yres > MAX_YRES) + return -EINVAL; + var->xres_virtual = max(var->xres_virtual, var->xres); + var->yres_virtual = max(var->yres_virtual, var->yres); + + switch (var->bits_per_pixel) { + /* 8 bits-per-pixel is not supported yet */ + case 8: + return -EINVAL; + case 16: + var->green.length = (var->green.length == 5) ? 5 : 6; + var->red.length = 5; + var->blue.length = 5; + var->transp.length = 6 - var->green.length; + var->blue.offset = 0; + var->green.offset = 5; + var->red.offset = 5 + var->green.length; + var->transp.offset = (5 + var->red.offset) & 15; + break; + case 24: /* RGB 888 */ + case 32: /* RGBA 8888 */ + var->red.offset = 16; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->transp.length = var->bits_per_pixel - 24; + var->transp.offset = (var->transp.length) ? 24 : 0; + break; + } + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; + var->transp.msb_right = 0; + + return 0; +} + +static int mbxfb_set_par(struct fb_info *info) +{ + struct fb_var_screeninfo *var = &info->var; + struct pixclock_div div; + ushort hbps, ht, hfps, has; + ushort vbps, vt, vfps, vas; + u32 gsctrl = readl(GSCTRL); + u32 gsadr = readl(GSADR); + + info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8; + + /* setup color mode */ + gsctrl &= ~(FMsk(GSCTRL_GPIXFMT)); + /* FIXME: add *WORKING* support for 8-bits per color */ + if (info->var.bits_per_pixel == 8) { + return -EINVAL; + } else { + fb_dealloc_cmap(&info->cmap); + gsctrl &= ~GSCTRL_LUT_EN; + + info->fix.visual = FB_VISUAL_TRUECOLOR; + switch (info->var.bits_per_pixel) { + case 16: + if (info->var.green.length == 5) + gsctrl |= GSCTRL_GPIXFMT_ARGB1555; + else + gsctrl |= GSCTRL_GPIXFMT_RGB565; + break; + case 24: + gsctrl |= GSCTRL_GPIXFMT_RGB888; + break; + case 32: + gsctrl |= GSCTRL_GPIXFMT_ARGB8888; + break; + } + } + + /* setup resolution */ + gsctrl &= ~(FMsk(GSCTRL_GSWIDTH) | FMsk(GSCTRL_GSHEIGHT)); + gsctrl |= Gsctrl_Width(info->var.xres - 1) | + Gsctrl_Height(info->var.yres - 1); + writel(gsctrl, GSCTRL); + udelay(1000); + + gsadr &= ~(FMsk(GSADR_SRCSTRIDE)); + gsadr |= Gsadr_Srcstride(info->var.xres * info->var.bits_per_pixel / + (8 * 16) - 1); + writel(gsadr, GSADR); + udelay(1000); + + /* setup timings */ + var->pixclock = mbxfb_get_pixclock(info->var.pixclock, &div); + + writel((Disp_Pll_M(div.m) | Disp_Pll_N(div.n) | + Disp_Pll_P(div.p) | DISP_PLL_EN), DISPPLL); + + hbps = var->hsync_len; + has = hbps + var->left_margin; + hfps = has + var->xres; + ht = hfps + var->right_margin; + + vbps = var->vsync_len; + vas = vbps + var->upper_margin; + vfps = vas + var->yres; + vt = vfps + var->lower_margin; + + writel((Dht01_Hbps(hbps) | Dht01_Ht(ht)), DHT01); + writel((Dht02_Hlbs(has) | Dht02_Has(has)), DHT02); + writel((Dht03_Hfps(hfps) | Dht03_Hrbs(hfps)), DHT03); + writel((Dhdet_Hdes(has) | Dhdet_Hdef(hfps)), DHDET); + + writel((Dvt01_Vbps(vbps) | Dvt01_Vt(vt)), DVT01); + writel((Dvt02_Vtbs(vas) | Dvt02_Vas(vas)), DVT02); + writel((Dvt03_Vfps(vfps) | Dvt03_Vbbs(vfps)), DVT03); + writel((Dvdet_Vdes(vas) | Dvdet_Vdef(vfps)), DVDET); + writel((Dvectrl_Vevent(vfps) | Dvectrl_Vfetch(vbps)), DVECTRL); + + writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + + return 0; +} + +static int mbxfb_blank(int blank, struct fb_info *info) +{ + switch (blank) { + case FB_BLANK_POWERDOWN: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_NORMAL: + writel((readl(DSCTRL) & ~DSCTRL_SYNCGEN_EN), DSCTRL); + udelay(1000); + writel((readl(PIXCLK) & ~PIXCLK_EN), PIXCLK); + udelay(1000); + writel((readl(VOVRCLK) & ~VOVRCLK_EN), VOVRCLK); + udelay(1000); + break; + case FB_BLANK_UNBLANK: + writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + udelay(1000); + writel((readl(PIXCLK) | PIXCLK_EN), PIXCLK); + udelay(1000); + break; + } + return 0; +} + +static struct fb_ops mbxfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = mbxfb_check_var, + .fb_set_par = mbxfb_set_par, + .fb_setcolreg = mbxfb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_blank = mbxfb_blank, +}; + +/* + Enable external SDRAM controller. Assume that all clocks are active + by now. +*/ +static void __devinit setup_memc(struct fb_info *fbi) +{ + struct mbxfb_info *mfbi = fbi->par; + unsigned long tmp; + int i; + + /* FIXME: use platfrom specific parameters */ + /* setup SDRAM controller */ + writel((LMCFG_LMC_DS | LMCFG_LMC_TS | LMCFG_LMD_TS | + LMCFG_LMA_TS), + LMCFG); + udelay(1000); + + writel(LMPWR_MC_PWR_ACT, LMPWR); + udelay(1000); + + /* setup SDRAM timings */ + writel((Lmtim_Tras(7) | Lmtim_Trp(3) | Lmtim_Trcd(3) | + Lmtim_Trc(9) | Lmtim_Tdpl(2)), + LMTIM); + udelay(1000); + /* setup SDRAM refresh rate */ + writel(0xc2b, LMREFRESH); + udelay(1000); + /* setup SDRAM type parameters */ + writel((LMTYPE_CASLAT_3 | LMTYPE_BKSZ_2 | LMTYPE_ROWSZ_11 | + LMTYPE_COLSZ_8), + LMTYPE); + udelay(1000); + /* enable memory controller */ + writel(LMPWR_MC_PWR_ACT, LMPWR); + udelay(1000); + + /* perform dummy reads */ + for ( i = 0; i < 16; i++ ) { + tmp = readl(fbi->screen_base); + } +} + +static void enable_clocks(struct fb_info *fbi) +{ + /* enable clocks */ + writel(SYSCLKSRC_PLL_2, SYSCLKSRC); + udelay(1000); + writel(PIXCLKSRC_PLL_1, PIXCLKSRC); + udelay(1000); + writel(0x00000000, CLKSLEEP); + udelay(1000); + writel((Core_Pll_M(0x17) | Core_Pll_N(0x3) | Core_Pll_P(0x0) | + CORE_PLL_EN), + COREPLL); + udelay(1000); + writel((Disp_Pll_M(0x1b) | Disp_Pll_N(0x7) | Disp_Pll_P(0x1) | + DISP_PLL_EN), + DISPPLL); + + writel(0x00000000, VOVRCLK); + udelay(1000); + writel(PIXCLK_EN, PIXCLK); + udelay(1000); + writel(MEMCLK_EN, MEMCLK); + udelay(1000); + writel(0x00000006, M24CLK); + udelay(1000); + writel(0x00000006, MBXCLK); + udelay(1000); + writel(SDCLK_EN, SDCLK); + udelay(1000); + writel(0x00000001, PIXCLKDIV); + udelay(1000); +} + +static void __devinit setup_graphics(struct fb_info *fbi) +{ + unsigned long gsctrl; + + gsctrl = GSCTRL_GAMMA_EN | Gsctrl_Width(fbi->var.xres - 1) | + Gsctrl_Height(fbi->var.yres - 1); + switch (fbi->var.bits_per_pixel) { + case 16: + if (fbi->var.green.length == 5) + gsctrl |= GSCTRL_GPIXFMT_ARGB1555; + else + gsctrl |= GSCTRL_GPIXFMT_RGB565; + break; + case 24: + gsctrl |= GSCTRL_GPIXFMT_RGB888; + break; + case 32: + gsctrl |= GSCTRL_GPIXFMT_ARGB8888; + break; + } + + writel(gsctrl, GSCTRL); + udelay(1000); + writel(0x00000000, GBBASE); + udelay(1000); + writel(0x00ffffff, GDRCTRL); + udelay(1000); + writel((GSCADR_STR_EN | Gscadr_Gbase_Adr(0x6000)), GSCADR); + udelay(1000); + writel(0x00000000, GPLUT); + udelay(1000); +} + +static void __devinit setup_display(struct fb_info *fbi) +{ + unsigned long dsctrl = 0; + + dsctrl = DSCTRL_BLNK_POL; + if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT) + dsctrl |= DSCTRL_HS_POL; + if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) + dsctrl |= DSCTRL_VS_POL; + writel(dsctrl, DSCTRL); + udelay(1000); + writel(0xd0303010, DMCTRL); + udelay(1000); + writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); +} + +static void __devinit enable_controller(struct fb_info *fbi) +{ + writel(SYSRST_RST, SYSRST); + udelay(1000); + + + enable_clocks(fbi); + setup_memc(fbi); + setup_graphics(fbi); + setup_display(fbi); +} + +#ifdef CONFIG_PM +/* + * Power management hooks. Note that we won't be called from IRQ context, + * unlike the blank functions above, so we may sleep. + */ +static int mbxfb_suspend(struct platform_device *dev, pm_message_t state) +{ + /* make frame buffer memory enter self-refresh mode */ + writel(LMPWR_MC_PWR_SRM, LMPWR); + while (LMPWRSTAT != LMPWRSTAT_MC_PWR_SRM) + ; /* empty statement */ + + /* reset the device, since it's initial state is 'mostly sleeping' */ + writel(SYSRST_RST, SYSRST); + return 0; +} + +static int mbxfb_resume(struct platform_device *dev) +{ + struct fb_info *fbi = platform_get_drvdata(dev); + + enable_clocks(fbi); +/* setup_graphics(fbi); */ +/* setup_display(fbi); */ + + writel((readl(DSCTRL) | DSCTRL_SYNCGEN_EN), DSCTRL); + return 0; +} +#else +#define mbxfb_suspend NULL +#define mbxfb_resume NULL +#endif + +/* debugfs entries */ +#ifndef CONFIG_FB_MBX_DEBUG +#define mbxfb_debugfs_init(x) do {} while(0) +#define mbxfb_debugfs_remove(x) do {} while(0) +#endif + +#define res_size(_r) (((_r)->end - (_r)->start) + 1) + +static int __devinit mbxfb_probe(struct platform_device *dev) +{ + int ret; + struct fb_info *fbi; + struct mbxfb_info *mfbi; + struct mbxfb_platform_data *pdata; + + dev_dbg(dev, "mbxfb_probe\n"); + + fbi = framebuffer_alloc(sizeof(struct mbxfb_info), &dev->dev); + if (fbi == NULL) { + dev_err(&dev->dev, "framebuffer_alloc failed\n"); + return -ENOMEM; + } + + mfbi = fbi->par; + fbi->pseudo_palette = mfbi->pseudo_palette; + pdata = dev->dev.platform_data; + if (pdata->probe) + mfbi->platform_probe = pdata->probe; + if (pdata->remove) + mfbi->platform_remove = pdata->remove; + + mfbi->fb_res = platform_get_resource(dev, IORESOURCE_MEM, 0); + mfbi->reg_res = platform_get_resource(dev, IORESOURCE_MEM, 1); + + if (!mfbi->fb_res || !mfbi->reg_res) { + dev_err(&dev->dev, "no resources found\n"); + ret = -ENODEV; + goto err1; + } + + mfbi->fb_req = request_mem_region(mfbi->fb_res->start, + res_size(mfbi->fb_res), dev->name); + if (mfbi->fb_req == NULL) { + dev_err(&dev->dev, "failed to claim framebuffer memory\n"); + ret = -EINVAL; + goto err1; + } + mfbi->fb_phys_addr = mfbi->fb_res->start; + + mfbi->reg_req = request_mem_region(mfbi->reg_res->start, + res_size(mfbi->reg_res), dev->name); + if (mfbi->reg_req == NULL) { + dev_err(&dev->dev, "failed to claim Marathon registers\n"); + ret = -EINVAL; + goto err2; + } + mfbi->reg_phys_addr = mfbi->reg_res->start; + + mfbi->reg_virt_addr = ioremap_nocache(mfbi->reg_phys_addr, + res_size(mfbi->reg_req)); + if (!mfbi->reg_virt_addr) { + dev_err(&dev->dev, "failed to ioremap Marathon registers\n"); + ret = -EINVAL; + goto err3; + } + virt_base_2700 = (unsigned long)mfbi->reg_virt_addr; + + mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr, + res_size(mfbi->fb_req)); + if (!mfbi->reg_virt_addr) { + dev_err(&dev->dev, "failed to ioremap frame buffer\n"); + ret = -EINVAL; + goto err4; + } + + /* FIXME: get from platform */ + fbi->screen_base = (char __iomem *)(mfbi->fb_virt_addr + 0x60000); + fbi->screen_size = 8 * 1024 * 1024; /* 8 Megs */ + fbi->fbops = &mbxfb_ops; + + fbi->var = mbxfb_default; + fbi->fix = mbxfb_fix; + fbi->fix.smem_start = mfbi->fb_phys_addr + 0x60000; + fbi->fix.smem_len = 8 * 1024 * 1024; + fbi->fix.line_length = 640 * 2; + + ret = fb_alloc_cmap(&fbi->cmap, 256, 0); + if (ret < 0) { + dev_err(&dev->dev, "fb_alloc_cmap failed\n"); + ret = -EINVAL; + goto err5; + } + + platform_set_drvdata(dev, fbi); + + printk(KERN_INFO "fb%d: mbx frame buffer device\n", fbi->node); + + if (mfbi->platform_probe) + mfbi->platform_probe(fbi); + + enable_controller(fbi); + + mbxfb_debugfs_init(fbi); + + ret = register_framebuffer(fbi); + if (ret < 0) { + dev_err(&dev->dev, "register_framebuffer failed\n"); + ret = -EINVAL; + goto err6; + } + + return 0; + +err6: + fb_dealloc_cmap(&fbi->cmap); +err5: + iounmap(mfbi->fb_virt_addr); +err4: + iounmap(mfbi->reg_virt_addr); +err3: + release_mem_region(mfbi->reg_res->start, res_size(mfbi->reg_res)); +err2: + release_mem_region(mfbi->fb_res->start, res_size(mfbi->fb_res)); +err1: + framebuffer_release(fbi); + + return ret; +} + +static int __devexit mbxfb_remove(struct platform_device *dev) +{ + struct fb_info *fbi = platform_get_drvdata(dev); + + writel(SYSRST_RST, SYSRST); + udelay(1000); + + mbxfb_debugfs_remove(fbi); + + if (fbi) { + struct mbxfb_info *mfbi = fbi->par; + + unregister_framebuffer(fbi); + if (mfbi) { + if (mfbi->platform_remove) + mfbi->platform_remove(fbi); + + if (mfbi->fb_virt_addr) + iounmap(mfbi->fb_virt_addr); + if (mfbi->reg_virt_addr) + iounmap(mfbi->reg_virt_addr); + if (mfbi->reg_req) + release_mem_region(mfbi->reg_req->start, + res_size(mfbi->reg_req)); + if (mfbi->fb_req) + release_mem_region(mfbi->fb_req->start, + res_size(mfbi->fb_req)); + } + framebuffer_release(fbi); + } + + return 0; +} + +static struct platform_driver mbxfb_driver = { + .probe = mbxfb_probe, + .remove = mbxfb_remove, + .suspend = mbxfb_suspend, + .resume = mbxfb_resume, + .driver = { + .name = "mbx-fb", + }, +}; + +int __devinit mbxfb_init(void) +{ + return platform_driver_register(&mbxfb_driver); +} + +static void __devexit mbxfb_exit(void) +{ + platform_driver_unregister(&mbxfb_driver); +} + +module_init(mbxfb_init); +module_exit(mbxfb_exit); + +MODULE_DESCRIPTION("loadable framebuffer driver for Marathon device"); +MODULE_AUTHOR("Mike Rapoport, Compulab"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/mbx/reg_bits.h b/drivers/video/mbx/reg_bits.h new file mode 100644 index 000000000..c226a8e45 --- /dev/null +++ b/drivers/video/mbx/reg_bits.h @@ -0,0 +1,418 @@ +#ifndef __REG_BITS_2700G_ +#define __REG_BITS_2700G_ + +/* use defines from asm-arm/arch-pxa/bitfields.h for bit fields access */ +#define UData(Data) ((unsigned long) (Data)) +#define Fld(Size, Shft) (((Size) << 16) + (Shft)) +#define FSize(Field) ((Field) >> 16) +#define FShft(Field) ((Field) & 0x0000FFFF) +#define FMsk(Field) (((UData (1) << FSize (Field)) - 1) << FShft (Field)) +#define FAlnMsk(Field) ((UData (1) << FSize (Field)) - 1) +#define F1stBit(Field) (UData (1) << FShft (Field)) + +#define SYSRST_RST (1 << 0) + +/* SYSCLKSRC - SYSCLK Source Control Register */ +#define SYSCLKSRC_SEL Fld(2,0) +#define SYSCLKSRC_REF ((0x0) << FShft(SYSCLKSRC_SEL)) +#define SYSCLKSRC_PLL_1 ((0x1) << FShft(SYSCLKSRC_SEL)) +#define SYSCLKSRC_PLL_2 ((0x2) << FShft(SYSCLKSRC_SEL)) + +/* PIXCLKSRC - PIXCLK Source Control Register */ +#define PIXCLKSRC_SEL Fld(2,0) +#define PIXCLKSRC_REF ((0x0) << FShft(PIXCLKSRC_SEL)) +#define PIXCLKSRC_PLL_1 ((0x1) << FShft(PIXCLKSRC_SEL)) +#define PIXCLKSRC_PLL_2 ((0x2) << FShft(PIXCLKSRC_SEL)) + +/* Clock Disable Register */ +#define CLKSLEEP_SLP (1 << 0) + +/* Core PLL Control Register */ +#define CORE_PLL_M Fld(6,7) +#define Core_Pll_M(x) ((x) << FShft(CORE_PLL_M)) +#define CORE_PLL_N Fld(3,4) +#define Core_Pll_N(x) ((x) << FShft(CORE_PLL_N)) +#define CORE_PLL_P Fld(3,1) +#define Core_Pll_P(x) ((x) << FShft(CORE_PLL_P)) +#define CORE_PLL_EN (1 << 0) + +/* Display PLL Control Register */ +#define DISP_PLL_M Fld(6,7) +#define Disp_Pll_M(x) ((x) << FShft(DISP_PLL_M)) +#define DISP_PLL_N Fld(3,4) +#define Disp_Pll_N(x) ((x) << FShft(DISP_PLL_N)) +#define DISP_PLL_P Fld(3,1) +#define Disp_Pll_P(x) ((x) << FShft(DISP_PLL_P)) +#define DISP_PLL_EN (1 << 0) + +/* PLL status register */ +#define PLLSTAT_CORE_PLL_LOST_L (1 << 3) +#define PLLSTAT_CORE_PLL_LSTS (1 << 2) +#define PLLSTAT_DISP_PLL_LOST_L (1 << 1) +#define PLLSTAT_DISP_PLL_LSTS (1 << 0) + +/* Video and scale clock control register */ +#define VOVRCLK_EN (1 << 0) + +/* Pixel clock control register */ +#define PIXCLK_EN (1 << 0) + +/* Memory clock control register */ +#define MEMCLK_EN (1 << 0) + +/* MBX clock control register */ +#define MBXCLK_DIV Fld(2,2) +#define MBXCLK_DIV_1 ((0x0) << FShft(MBXCLK_DIV)) +#define MBXCLK_DIV_2 ((0x1) << FShft(MBXCLK_DIV)) +#define MBXCLK_DIV_3 ((0x2) << FShft(MBXCLK_DIV)) +#define MBXCLK_DIV_4 ((0x3) << FShft(MBXCLK_DIV)) +#define MBXCLK_EN Fld(2,0) +#define MBXCLK_EN_NONE ((0x0) << FShft(MBXCLK_EN)) +#define MBXCLK_EN_2D ((0x1) << FShft(MBXCLK_EN)) +#define MBXCLK_EN_BOTH ((0x2) << FShft(MBXCLK_EN)) + +/* M24 clock control register */ +#define M24CLK_DIV Fld(2,1) +#define M24CLK_DIV_1 ((0x0) << FShft(M24CLK_DIV)) +#define M24CLK_DIV_2 ((0x1) << FShft(M24CLK_DIV)) +#define M24CLK_DIV_3 ((0x2) << FShft(M24CLK_DIV)) +#define M24CLK_DIV_4 ((0x3) << FShft(M24CLK_DIV)) +#define M24CLK_EN (1 << 0) + +/* SDRAM clock control register */ +#define SDCLK_EN (1 << 0) + +/* PixClk Divisor Register */ +#define PIXCLKDIV_PD Fld(9,0) +#define Pixclkdiv_Pd(x) ((x) << FShft(PIXCLKDIV_PD)) + +/* LCD Config control register */ +#define LCDCFG_IN_FMT Fld(3,28) +#define Lcdcfg_In_Fmt(x) ((x) << FShft(LCDCFG_IN_FMT)) +#define LCDCFG_LCD1DEN_POL (1 << 27) +#define LCDCFG_LCD1FCLK_POL (1 << 26) +#define LCDCFG_LCD1LCLK_POL (1 << 25) +#define LCDCFG_LCD1D_POL (1 << 24) +#define LCDCFG_LCD2DEN_POL (1 << 23) +#define LCDCFG_LCD2FCLK_POL (1 << 22) +#define LCDCFG_LCD2LCLK_POL (1 << 21) +#define LCDCFG_LCD2D_POL (1 << 20) +#define LCDCFG_LCD1_TS (1 << 19) +#define LCDCFG_LCD1D_DS (1 << 18) +#define LCDCFG_LCD1C_DS (1 << 17) +#define LCDCFG_LCD1_IS_IN (1 << 16) +#define LCDCFG_LCD2_TS (1 << 3) +#define LCDCFG_LCD2D_DS (1 << 2) +#define LCDCFG_LCD2C_DS (1 << 1) +#define LCDCFG_LCD2_IS_IN (1 << 0) + +/* On-Die Frame Buffer Power Control Register */ +#define ODFBPWR_SLOW (1 << 2) +#define ODFBPWR_MODE Fld(2,0) +#define ODFBPWR_MODE_ACT ((0x0) << FShft(ODFBPWR_MODE)) +#define ODFBPWR_MODE_ACT_LP ((0x1) << FShft(ODFBPWR_MODE)) +#define ODFBPWR_MODE_SLEEP ((0x2) << FShft(ODFBPWR_MODE)) +#define ODFBPWR_MODE_SHUTD ((0x3) << FShft(ODFBPWR_MODE)) + +/* On-Die Frame Buffer Power State Status Register */ +#define ODFBSTAT_ACT (1 << 2) +#define ODFBSTAT_SLP (1 << 1) +#define ODFBSTAT_SDN (1 << 0) + +/* LMRST - Local Memory (SDRAM) Reset */ +#define LMRST_MC_RST (1 << 0) + +/* LMCFG - Local Memory (SDRAM) Configuration Register */ +#define LMCFG_LMC_DS (1 << 5) +#define LMCFG_LMD_DS (1 << 4) +#define LMCFG_LMA_DS (1 << 3) +#define LMCFG_LMC_TS (1 << 2) +#define LMCFG_LMD_TS (1 << 1) +#define LMCFG_LMA_TS (1 << 0) + +/* LMPWR - Local Memory (SDRAM) Power Control Register */ +#define LMPWR_MC_PWR_CNT Fld(2,0) +#define LMPWR_MC_PWR_ACT ((0x0) << FShft(LMPWR_MC_PWR_CNT)) /* Active */ +#define LMPWR_MC_PWR_SRM ((0x1) << FShft(LMPWR_MC_PWR_CNT)) /* Self-refresh */ +#define LMPWR_MC_PWR_DPD ((0x3) << FShft(LMPWR_MC_PWR_CNT)) /* deep power down */ + +/* LMPWRSTAT - Local Memory (SDRAM) Power Status Register */ +#define LMPWRSTAT_MC_PWR_CNT Fld(2,0) +#define LMPWRSTAT_MC_PWR_ACT ((0x0) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* Active */ +#define LMPWRSTAT_MC_PWR_SRM ((0x1) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* Self-refresh */ +#define LMPWRSTAT_MC_PWR_DPD ((0x3) << FShft(LMPWRSTAT_MC_PWR_CNT)) /* deep power down */ + +/* LMTYPE - Local Memory (SDRAM) Type Register */ +#define LMTYPE_CASLAT Fld(3,10) +#define LMTYPE_CASLAT_1 ((0x1) << FShft(LMTYPE_CASLAT)) +#define LMTYPE_CASLAT_2 ((0x2) << FShft(LMTYPE_CASLAT)) +#define LMTYPE_CASLAT_3 ((0x3) << FShft(LMTYPE_CASLAT)) +#define LMTYPE_BKSZ Fld(2,8) +#define LMTYPE_BKSZ_1 ((0x1) << FShft(LMTYPE_BKSZ)) +#define LMTYPE_BKSZ_2 ((0x2) << FShft(LMTYPE_BKSZ)) +#define LMTYPE_ROWSZ Fld(4,4) +#define LMTYPE_ROWSZ_11 ((0xb) << FShft(LMTYPE_ROWSZ)) +#define LMTYPE_ROWSZ_12 ((0xc) << FShft(LMTYPE_ROWSZ)) +#define LMTYPE_ROWSZ_13 ((0xd) << FShft(LMTYPE_ROWSZ)) +#define LMTYPE_COLSZ Fld(4,0) +#define LMTYPE_COLSZ_7 ((0x7) << FShft(LMTYPE_COLSZ)) +#define LMTYPE_COLSZ_8 ((0x8) << FShft(LMTYPE_COLSZ)) +#define LMTYPE_COLSZ_9 ((0x9) << FShft(LMTYPE_COLSZ)) +#define LMTYPE_COLSZ_10 ((0xa) << FShft(LMTYPE_COLSZ)) +#define LMTYPE_COLSZ_11 ((0xb) << FShft(LMTYPE_COLSZ)) +#define LMTYPE_COLSZ_12 ((0xc) << FShft(LMTYPE_COLSZ)) + +/* LMTIM - Local Memory (SDRAM) Timing Register */ +#define LMTIM_TRAS Fld(4,16) +#define Lmtim_Tras(x) ((x) << FShft(LMTIM_TRAS)) +#define LMTIM_TRP Fld(4,12) +#define Lmtim_Trp(x) ((x) << FShft(LMTIM_TRP)) +#define LMTIM_TRCD Fld(4,8) +#define Lmtim_Trcd(x) ((x) << FShft(LMTIM_TRCD)) +#define LMTIM_TRC Fld(4,4) +#define Lmtim_Trc(x) ((x) << FShft(LMTIM_TRC)) +#define LMTIM_TDPL Fld(4,0) +#define Lmtim_Tdpl(x) ((x) << FShft(LMTIM_TDPL)) + +/* LMREFRESH - Local Memory (SDRAM) tREF Control Register */ +#define LMREFRESH_TREF Fld(2,0) +#define Lmrefresh_Tref(x) ((x) << FShft(LMREFRESH_TREF)) + +/* GSCTRL - Graphics surface control register */ +#define GSCTRL_LUT_EN (1 << 31) +#define GSCTRL_GPIXFMT Fld(4,27) +#define GSCTRL_GPIXFMT_INDEXED ((0x0) << FShft(GSCTRL_GPIXFMT)) +#define GSCTRL_GPIXFMT_ARGB4444 ((0x4) << FShft(GSCTRL_GPIXFMT)) +#define GSCTRL_GPIXFMT_ARGB1555 ((0x5) << FShft(GSCTRL_GPIXFMT)) +#define GSCTRL_GPIXFMT_RGB888 ((0x6) << FShft(GSCTRL_GPIXFMT)) +#define GSCTRL_GPIXFMT_RGB565 ((0x7) << FShft(GSCTRL_GPIXFMT)) +#define GSCTRL_GPIXFMT_ARGB8888 ((0x8) << FShft(GSCTRL_GPIXFMT)) +#define GSCTRL_GAMMA_EN (1 << 26) + +#define GSCTRL_GSWIDTH Fld(11,11) +#define Gsctrl_Width(Pixel) /* Display Width [1..2048 pix.] */ \ + (((Pixel) - 1) << FShft(GSCTRL_GSWIDTH)) + +#define GSCTRL_GSHEIGHT Fld(11,0) +#define Gsctrl_Height(Pixel) /* Display Height [1..2048 pix.] */ \ + (((Pixel) - 1) << FShft(GSCTRL_GSHEIGHT)) + +/* GBBASE fileds */ +#define GBBASE_GLALPHA Fld(8,24) +#define Gbbase_Glalpha(x) ((x) << FShft(GBBASE_GLALPHA)) + +#define GBBASE_COLKEY Fld(24,0) +#define Gbbase_Colkey(x) ((x) << FShft(GBBASE_COLKEY)) + +/* GDRCTRL fields */ +#define GDRCTRL_PIXDBL (1 << 31) +#define GDRCTRL_PIXHLV (1 << 30) +#define GDRCTRL_LNDBL (1 << 29) +#define GDRCTRL_LNHLV (1 << 28) +#define GDRCTRL_COLKEYM Fld(24,0) +#define Gdrctrl_Colkeym(x) ((x) << FShft(GDRCTRL_COLKEYM)) + +/* GSCADR graphics stream control address register fields */ +#define GSCADR_STR_EN (1 << 31) +#define GSCADR_COLKEY_EN (1 << 30) +#define GSCADR_COLKEYSCR (1 << 29) +#define GSCADR_BLEND_M Fld(2,27) +#define GSCADR_BLEND_NONE ((0x0) << FShft(GSCADR_BLEND_M)) +#define GSCADR_BLEND_INV ((0x1) << FShft(GSCADR_BLEND_M)) +#define GSCADR_BLEND_GLOB ((0x2) << FShft(GSCADR_BLEND_M)) +#define GSCADR_BLEND_PIX ((0x3) << FShft(GSCADR_BLEND_M)) +#define GSCADR_BLEND_POS Fld(2,24) +#define GSCADR_BLEND_GFX ((0x0) << FShft(GSCADR_BLEND_POS)) +#define GSCADR_BLEND_VID ((0x1) << FShft(GSCADR_BLEND_POS)) +#define GSCADR_BLEND_CUR ((0x2) << FShft(GSCADR_BLEND_POS)) +#define GSCADR_GBASE_ADR Fld(23,0) +#define Gscadr_Gbase_Adr(x) ((x) << FShft(GSCADR_GBASE_ADR)) + +/* GSADR graphics stride address register fields */ +#define GSADR_SRCSTRIDE Fld(10,22) +#define Gsadr_Srcstride(x) ((x) << FShft(GSADR_SRCSTRIDE)) +#define GSADR_XSTART Fld(11,11) +#define Gsadr_Xstart(x) ((x) << FShft(GSADR_XSTART)) +#define GSADR_YSTART Fld(11,0) +#define Gsadr_Ystart(y) ((y) << FShft(GSADR_YSTART)) + +/* GPLUT graphics palette register fields */ +#define GPLUT_LUTADR Fld(8,24) +#define Gplut_Lutadr(x) ((x) << FShft(GPLUT_LUTADR)) +#define GPLUT_LUTDATA Fld(24,0) +#define Gplut_Lutdata(x) ((x) << FShft(GPLUT_LUTDATA)) + +/* HCCTRL - Hardware Cursor Register fields */ +#define HCCTRL_CUR_EN (1 << 31) +#define HCCTRL_COLKEY_EN (1 << 29) +#define HCCTRL_COLKEYSRC (1 << 28) +#define HCCTRL_BLEND_M Fld(2,26) +#define HCCTRL_BLEND_NONE ((0x0) << FShft(HCCTRL_BLEND_M)) +#define HCCTRL_BLEND_INV ((0x1) << FShft(HCCTRL_BLEND_M)) +#define HCCTRL_BLEND_GLOB ((0x2) << FShft(HCCTRL_BLEND_M)) +#define HCCTRL_BLEND_PIX ((0x3) << FShft(HCCTRL_BLEND_M)) +#define HCCTRL_CPIXFMT Fld(3,23) +#define HCCTRL_CPIXFMT_RGB332 ((0x3) << FShft(HCCTRL_CPIXFMT)) +#define HCCTRL_CPIXFMT_ARGB4444 ((0x4) << FShft(HCCTRL_CPIXFMT)) +#define HCCTRL_CPIXFMT_ARGB1555 ((0x5) << FShft(HCCTRL_CPIXFMT)) +#define HCCTRL_CBASE_ADR Fld(23,0) +#define Hcctrl_Cbase_Adr(x) ((x) << FShft(HCCTRL_CBASE_ADR)) + +/* HCSIZE Hardware Cursor Size Register fields */ +#define HCSIZE_BLEND_POS Fld(2,29) +#define HCSIZE_BLEND_GFX ((0x0) << FShft(HCSIZE_BLEND_POS)) +#define HCSIZE_BLEND_VID ((0x1) << FShft(HCSIZE_BLEND_POS)) +#define HCSIZE_BLEND_CUR ((0x2) << FShft(HCSIZE_BLEND_POS)) +#define HCSIZE_CWIDTH Fld(3,16) +#define Hcsize_Cwidth(x) ((x) << FShft(HCSIZE_CWIDTH)) +#define HCSIZE_CHEIGHT Fld(3,0) +#define Hcsize_Cheight(x) ((x) << FShft(HCSIZE_CHEIGHT)) + +/* HCPOS Hardware Cursor Position Register fields */ +#define HCPOS_SWITCHSRC (1 << 30) +#define HCPOS_CURBLINK Fld(6,24) +#define Hcpos_Curblink(x) ((x) << FShft(HCPOS_CURBLINK)) +#define HCPOS_XSTART Fld(12,12) +#define Hcpos_Xstart(x) ((x) << FShft(HCPOS_XSTART)) +#define HCPOS_YSTART Fld(12,0) +#define Hcpos_Ystart(y) ((y) << FShft(HCPOS_YSTART)) + +/* HCBADR Hardware Cursor Blend Address Register */ +#define HCBADR_GLALPHA Fld(8,24) +#define Hcbadr_Glalpha(x) ((x) << FShft(HCBADR_GLALPHA)) +#define HCBADR_COLKEY Fld(24,0) +#define Hcbadr_Colkey(x) ((x) << FShft(HCBADR_COLKEY)) + +/* HCCKMSK - Hardware Cursor Color Key Mask Register */ +#define HCCKMSK_COLKEY_M Fld(24,0) +#define Hcckmsk_Colkey_M(x) ((x) << FShft(HCCKMSK_COLKEY_M)) + +/* DSCTRL - Display sync control register */ +#define DSCTRL_SYNCGEN_EN (1 << 31) +#define DSCTRL_DPL_RST (1 << 29) +#define DSCTRL_PWRDN_M (1 << 28) +#define DSCTRL_UPDSYNCCNT (1 << 26) +#define DSCTRL_UPDINTCNT (1 << 25) +#define DSCTRL_UPDCNT (1 << 24) +#define DSCTRL_UPDWAIT Fld(4,16) +#define Dsctrl_Updwait(x) ((x) << FShft(DSCTRL_UPDWAIT)) +#define DSCTRL_CLKPOL (1 << 11) +#define DSCTRL_CSYNC_EN (1 << 10) +#define DSCTRL_VS_SLAVE (1 << 7) +#define DSCTRL_HS_SLAVE (1 << 6) +#define DSCTRL_BLNK_POL (1 << 5) +#define DSCTRL_BLNK_DIS (1 << 4) +#define DSCTRL_VS_POL (1 << 3) +#define DSCTRL_VS_DIS (1 << 2) +#define DSCTRL_HS_POL (1 << 1) +#define DSCTRL_HS_DIS (1 << 0) + +/* DHT01 - Display horizontal timing register 01 */ +#define DHT01_HBPS Fld(12,16) +#define Dht01_Hbps(x) ((x) << FShft(DHT01_HBPS)) +#define DHT01_HT Fld(12,0) +#define Dht01_Ht(x) ((x) << FShft(DHT01_HT)) + +/* DHT02 - Display horizontal timing register 02 */ +#define DHT02_HAS Fld(12,16) +#define Dht02_Has(x) ((x) << FShft(DHT02_HAS)) +#define DHT02_HLBS Fld(12,0) +#define Dht02_Hlbs(x) ((x) << FShft(DHT02_HLBS)) + +/* DHT03 - Display horizontal timing register 03 */ +#define DHT03_HFPS Fld(12,16) +#define Dht03_Hfps(x) ((x) << FShft(DHT03_HFPS)) +#define DHT03_HRBS Fld(12,0) +#define Dht03_Hrbs(x) ((x) << FShft(DHT03_HRBS)) + +/* DVT01 - Display vertical timing register 01 */ +#define DVT01_VBPS Fld(12,16) +#define Dvt01_Vbps(x) ((x) << FShft(DVT01_VBPS)) +#define DVT01_VT Fld(12,0) +#define Dvt01_Vt(x) ((x) << FShft(DVT01_VT)) + +/* DVT02 - Display vertical timing register 02 */ +#define DVT02_VAS Fld(12,16) +#define Dvt02_Vas(x) ((x) << FShft(DVT02_VAS)) +#define DVT02_VTBS Fld(12,0) +#define Dvt02_Vtbs(x) ((x) << FShft(DVT02_VTBS)) + +/* DVT03 - Display vertical timing register 03 */ +#define DVT03_VFPS Fld(12,16) +#define Dvt03_Vfps(x) ((x) << FShft(DVT03_VFPS)) +#define DVT03_VBBS Fld(12,0) +#define Dvt03_Vbbs(x) ((x) << FShft(DVT03_VBBS)) + +/* DVECTRL - display vertical event control register */ +#define DVECTRL_VEVENT Fld(12,16) +#define Dvectrl_Vevent(x) ((x) << FShft(DVECTRL_VEVENT)) +#define DVECTRL_VFETCH Fld(12,0) +#define Dvectrl_Vfetch(x) ((x) << FShft(DVECTRL_VFETCH)) + +/* DHDET - display horizontal DE timing register */ +#define DHDET_HDES Fld(12,16) +#define Dhdet_Hdes(x) ((x) << FShft(DHDET_HDES)) +#define DHDET_HDEF Fld(12,0) +#define Dhdet_Hdef(x) ((x) << FShft(DHDET_HDEF)) + +/* DVDET - display vertical DE timing register */ +#define DVDET_VDES Fld(12,16) +#define Dvdet_Vdes(x) ((x) << FShft(DVDET_VDES)) +#define DVDET_VDEF Fld(12,0) +#define Dvdet_Vdef(x) ((x) << FShft(DVDET_VDEF)) + +/* DODMSK - display output data mask register */ +#define DODMSK_MASK_LVL (1 << 31) +#define DODMSK_BLNK_LVL (1 << 30) +#define DODMSK_MASK_B Fld(8,16) +#define Dodmsk_Mask_B(x) ((x) << FShft(DODMSK_MASK_B)) +#define DODMSK_MASK_G Fld(8,8) +#define Dodmsk_Mask_G(x) ((x) << FShft(DODMSK_MASK_G)) +#define DODMSK_MASK_R Fld(8,0) +#define Dodmsk_Mask_R(x) ((x) << FShft(DODMSK_MASK_R)) + +/* DBCOL - display border color control register */ +#define DBCOL_BORDCOL Fld(24,0) +#define Dbcol_Bordcol(x) ((x) << FShft(DBCOL_BORDCOL)) + +/* DVLNUM - display vertical line number register */ +#define DVLNUM_VLINE Fld(12,0) +#define Dvlnum_Vline(x) ((x) << FShft(DVLNUM_VLINE)) + +/* DMCTRL - Display Memory Control Register */ +#define DMCTRL_MEM_REF Fld(2,30) +#define DMCTRL_MEM_REF_ACT ((0x0) << FShft(DMCTRL_MEM_REF)) +#define DMCTRL_MEM_REF_HB ((0x1) << FShft(DMCTRL_MEM_REF)) +#define DMCTRL_MEM_REF_VB ((0x2) << FShft(DMCTRL_MEM_REF)) +#define DMCTRL_MEM_REF_BOTH ((0x3) << FShft(DMCTRL_MEM_REF)) +#define DMCTRL_UV_THRHLD Fld(6,24) +#define Dmctrl_Uv_Thrhld(x) ((x) << FShft(DMCTRL_UV_THRHLD)) +#define DMCTRL_V_THRHLD Fld(7,16) +#define Dmctrl_V_Thrhld(x) ((x) << FShft(DMCTRL_V_THRHLD)) +#define DMCTRL_D_THRHLD Fld(7,8) +#define Dmctrl_D_Thrhld(x) ((x) << FShft(DMCTRL_D_THRHLD)) +#define DMCTRL_BURSTLEN Fld(6,0) +#define Dmctrl_Burstlen(x) ((x) << FShft(DMCTRL_BURSTLEN)) + + +/* DLSTS - display load status register */ +#define DLSTS_RLD_ADONE (1 << 23) +/* #define DLSTS_RLD_ADOUT Fld(23,0) */ + +/* DLLCTRL - display list load control register */ +#define DLLCTRL_RLD_ADRLN Fld(8,24) +#define Dllctrl_Rld_Adrln(x) ((x) << FShft(DLLCTRL_RLD_ADRLN)) + +/* SPOCTRL - Scale Pitch/Order Control Register */ +#define SPOCTRL_H_SC_BP (1 << 31) +#define SPOCTRL_V_SC_BP (1 << 30) +#define SPOCTRL_HV_SC_OR (1 << 29) +#define SPOCTRL_VS_UR_C (1 << 27) +#define SPOCTRL_VORDER Fld(2,16) +#define SPOCTRL_VORDER_1TAP ((0x0) << FShft(SPOCTRL_VORDER)) +#define SPOCTRL_VORDER_2TAP ((0x1) << FShft(SPOCTRL_VORDER)) +#define SPOCTRL_VORDER_4TAP ((0x3) << FShft(SPOCTRL_VORDER)) +#define SPOCTRL_VPITCH Fld(16,0) +#define Spoctrl_Vpitch(x) ((x) << FShft(SPOCTRL_VPITCH)) + +#endif /* __REG_BITS_2700G_ */ diff --git a/drivers/video/mbx/regs.h b/drivers/video/mbx/regs.h new file mode 100644 index 000000000..ad20be076 --- /dev/null +++ b/drivers/video/mbx/regs.h @@ -0,0 +1,195 @@ +#ifndef __REGS_2700G_ +#define __REGS_2700G_ + +/* extern unsigned long virt_base_2700; */ +/* #define __REG_2700G(x) (*(volatile unsigned long*)((x)+virt_base_2700)) */ +#define __REG_2700G(x) ((x)+virt_base_2700) + +/* System Configuration Registers (0x0000_0000 0x0000_0010) */ +#define SYSCFG __REG_2700G(0x00000000) +#define PFBASE __REG_2700G(0x00000004) +#define PFCEIL __REG_2700G(0x00000008) +#define POLLFLAG __REG_2700G(0x0000000c) +#define SYSRST __REG_2700G(0x00000010) + +/* Interrupt Control Registers (0x0000_0014 0x0000_002F) */ +#define NINTPW __REG_2700G(0x00000014) +#define MINTENABLE __REG_2700G(0x00000018) +#define MINTSTAT __REG_2700G(0x0000001c) +#define SINTENABLE __REG_2700G(0x00000020) +#define SINTSTAT __REG_2700G(0x00000024) +#define SINTCLR __REG_2700G(0x00000028) + +/* Clock Control Registers (0x0000_002C 0x0000_005F) */ +#define SYSCLKSRC __REG_2700G(0x0000002c) +#define PIXCLKSRC __REG_2700G(0x00000030) +#define CLKSLEEP __REG_2700G(0x00000034) +#define COREPLL __REG_2700G(0x00000038) +#define DISPPLL __REG_2700G(0x0000003c) +#define PLLSTAT __REG_2700G(0x00000040) +#define VOVRCLK __REG_2700G(0x00000044) +#define PIXCLK __REG_2700G(0x00000048) +#define MEMCLK __REG_2700G(0x0000004c) +#define M24CLK __REG_2700G(0x00000054) +#define MBXCLK __REG_2700G(0x00000054) +#define SDCLK __REG_2700G(0x00000058) +#define PIXCLKDIV __REG_2700G(0x0000005c) + +/* LCD Port Control Register (0x0000_0060 0x0000_006F) */ +#define LCD_CONFIG __REG_2700G(0x00000060) + +/* On-Die Frame Buffer Registers (0x0000_0064 0x0000_006B) */ +#define ODFBPWR __REG_2700G(0x00000064) +#define ODFBSTAT __REG_2700G(0x00000068) + +/* GPIO Registers (0x0000_006C 0x0000_007F) */ +#define GPIOCGF __REG_2700G(0x0000006c) +#define GPIOHI __REG_2700G(0x00000070) +#define GPIOLO __REG_2700G(0x00000074) +#define GPIOSTAT __REG_2700G(0x00000078) + +/* Pulse Width Modulator (PWM) Registers (0x0000_0200 0x0000_02FF) */ +#define PWMRST __REG_2700G(0x00000200) +#define PWMCFG __REG_2700G(0x00000204) +#define PWM0DIV __REG_2700G(0x00000210) +#define PWM0DUTY __REG_2700G(0x00000214) +#define PWM0PER __REG_2700G(0x00000218) +#define PWM1DIV __REG_2700G(0x00000220) +#define PWM1DUTY __REG_2700G(0x00000224) +#define PWM1PER __REG_2700G(0x00000228) + +/* Identification (ID) Registers (0x0000_0300 0x0000_0FFF) */ +#define ID __REG_2700G(0x00000FF0) + +/* Local Memory (SDRAM) Interface Registers (0x0000_1000 0x0000_1FFF) */ +#define LMRST __REG_2700G(0x00001000) +#define LMCFG __REG_2700G(0x00001004) +#define LMPWR __REG_2700G(0x00001008) +#define LMPWRSTAT __REG_2700G(0x0000100c) +#define LMCEMR __REG_2700G(0x00001010) +#define LMTYPE __REG_2700G(0x00001014) +#define LMTIM __REG_2700G(0x00001018) +#define LMREFRESH __REG_2700G(0x0000101c) +#define LMPROTMIN __REG_2700G(0x00001020) +#define LMPROTMAX __REG_2700G(0x00001024) +#define LMPROTCFG __REG_2700G(0x00001028) +#define LMPROTERR __REG_2700G(0x0000102c) + +/* Plane Controller Registers (0x0000_2000 0x0000_2FFF) */ +#define GSCTRL __REG_2700G(0x00002000) +#define VSCTRL __REG_2700G(0x00002004) +#define GBBASE __REG_2700G(0x00002020) +#define VBBASE __REG_2700G(0x00002024) +#define GDRCTRL __REG_2700G(0x00002040) +#define VCMSK __REG_2700G(0x00002044) +#define GSCADR __REG_2700G(0x00002060) +#define VSCADR __REG_2700G(0x00002064) +#define VUBASE __REG_2700G(0x00002084) +#define VVBASE __REG_2700G(0x000020a4) +#define GSADR __REG_2700G(0x000020c0) +#define VSADR __REG_2700G(0x000020c4) +#define HCCTRL __REG_2700G(0x00002100) +#define HCSIZE __REG_2700G(0x00002110) +#define HCPOS __REG_2700G(0x00002120) +#define HCBADR __REG_2700G(0x00002130) +#define HCCKMSK __REG_2700G(0x00002140) +#define GPLUT __REG_2700G(0x00002150) +#define DSCTRL __REG_2700G(0x00002154) +#define DHT01 __REG_2700G(0x00002158) +#define DHT02 __REG_2700G(0x0000215c) +#define DHT03 __REG_2700G(0x00002160) +#define DVT01 __REG_2700G(0x00002164) +#define DVT02 __REG_2700G(0x00002168) +#define DVT03 __REG_2700G(0x0000216c) +#define DBCOL __REG_2700G(0x00002170) +#define BGCOLOR __REG_2700G(0x00002174) +#define DINTRS __REG_2700G(0x00002178) +#define DINTRE __REG_2700G(0x0000217c) +#define DINTRCNT __REG_2700G(0x00002180) +#define DSIG __REG_2700G(0x00002184) +#define DMCTRL __REG_2700G(0x00002188) +#define CLIPCTRL __REG_2700G(0x0000218c) +#define SPOCTRL __REG_2700G(0x00002190) +#define SVCTRL __REG_2700G(0x00002194) + +/* 0x0000_2198 */ +/* 0x0000_21A8 VSCOEFF[0:4] Video Scalar Vertical Coefficient [0:4] 4.14.5 */ +#define VSCOEFF0 __REG_2700G(0x00002198) +#define VSCOEFF1 __REG_2700G(0x0000219c) +#define VSCOEFF2 __REG_2700G(0x000021a0) +#define VSCOEFF3 __REG_2700G(0x000021a4) +#define VSCOEFF4 __REG_2700G(0x000021a8) + +#define SHCTRL __REG_2700G(0x000021b0) + +/* 0x0000_21B4 */ +/* 0x0000_21D4 HSCOEFF[0:8] Video Scalar Horizontal Coefficient [0:8] 4.14.7 */ +#define HSCOEFF0 __REG_2700G(0x000021b4) +#define HSCOEFF1 __REG_2700G(0x000021b8) +#define HSCOEFF2 __REG_2700G(0x000021bc) +#define HSCOEFF3 __REG_2700G(0x000021b0) +#define HSCOEFF4 __REG_2700G(0x000021c4) +#define HSCOEFF5 __REG_2700G(0x000021c8) +#define HSCOEFF6 __REG_2700G(0x000021cc) +#define HSCOEFF7 __REG_2700G(0x000021d0) +#define HSCOEFF8 __REG_2700G(0x000021d4) + +#define SSSIZE __REG_2700G(0x000021D8) + +/* 0x0000_2200 */ +/* 0x0000_2240 VIDGAM[0:16] Video Gamma LUT Index [0:16] 4.15.2 */ +#define VIDGAM0 __REG_2700G(0x00002200) +#define VIDGAM1 __REG_2700G(0x00002204) +#define VIDGAM2 __REG_2700G(0x00002208) +#define VIDGAM3 __REG_2700G(0x0000220c) +#define VIDGAM4 __REG_2700G(0x00002210) +#define VIDGAM5 __REG_2700G(0x00002214) +#define VIDGAM6 __REG_2700G(0x00002218) +#define VIDGAM7 __REG_2700G(0x0000221c) +#define VIDGAM8 __REG_2700G(0x00002220) +#define VIDGAM9 __REG_2700G(0x00002224) +#define VIDGAM10 __REG_2700G(0x00002228) +#define VIDGAM11 __REG_2700G(0x0000222c) +#define VIDGAM12 __REG_2700G(0x00002230) +#define VIDGAM13 __REG_2700G(0x00002234) +#define VIDGAM14 __REG_2700G(0x00002238) +#define VIDGAM15 __REG_2700G(0x0000223c) +#define VIDGAM16 __REG_2700G(0x00002240) + +/* 0x0000_2250 */ +/* 0x0000_2290 GFXGAM[0:16] Graphics Gamma LUT Index [0:16] 4.15.3 */ +#define GFXGAM0 __REG_2700G(0x00002250) +#define GFXGAM1 __REG_2700G(0x00002254) +#define GFXGAM2 __REG_2700G(0x00002258) +#define GFXGAM3 __REG_2700G(0x0000225c) +#define GFXGAM4 __REG_2700G(0x00002260) +#define GFXGAM5 __REG_2700G(0x00002264) +#define GFXGAM6 __REG_2700G(0x00002268) +#define GFXGAM7 __REG_2700G(0x0000226c) +#define GFXGAM8 __REG_2700G(0x00002270) +#define GFXGAM9 __REG_2700G(0x00002274) +#define GFXGAM10 __REG_2700G(0x00002278) +#define GFXGAM11 __REG_2700G(0x0000227c) +#define GFXGAM12 __REG_2700G(0x00002280) +#define GFXGAM13 __REG_2700G(0x00002284) +#define GFXGAM14 __REG_2700G(0x00002288) +#define GFXGAM15 __REG_2700G(0x0000228c) +#define GFXGAM16 __REG_2700G(0x00002290) + +#define DLSTS __REG_2700G(0x00002300) +#define DLLCTRL __REG_2700G(0x00002304) +#define DVLNUM __REG_2700G(0x00002308) +#define DUCTRL __REG_2700G(0x0000230c) +#define DVECTRL __REG_2700G(0x00002310) +#define DHDET __REG_2700G(0x00002314) +#define DVDET __REG_2700G(0x00002318) +#define DODMSK __REG_2700G(0x0000231c) +#define CSC01 __REG_2700G(0x00002330) +#define CSC02 __REG_2700G(0x00002334) +#define CSC03 __REG_2700G(0x00002338) +#define CSC04 __REG_2700G(0x0000233c) +#define CSC05 __REG_2700G(0x00002340) + +#define FB_MEMORY_START __REG_2700G(0x00060000) + +#endif /* __REGS_2700G_ */ diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c new file mode 100644 index 000000000..5b75ae4e9 --- /dev/null +++ b/drivers/video/nvidia/nv_backlight.c @@ -0,0 +1,203 @@ +/* + * Backlight code for nVidia based graphic cards + * + * Copyright 2004 Antonino Daplas <adaplas@pol.net> + * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/backlight.h> +#include <linux/fb.h> +#include <linux/pci.h> +#include "nv_local.h" +#include "nv_type.h" +#include "nv_proto.h" + +#ifdef CONFIG_PMAC_BACKLIGHT +#include <asm/backlight.h> +#include <asm/machdep.h> +#endif + +/* We do not have any information about which values are allowed, thus + * we used safe values. + */ +#define MIN_LEVEL 0x158 +#define MAX_LEVEL 0x534 +#define LEVEL_STEP ((MAX_LEVEL - MIN_LEVEL) / FB_BACKLIGHT_MAX) + +static struct backlight_properties nvidia_bl_data; + +/* Call with fb_info->bl_mutex held */ +static int nvidia_bl_get_level_brightness(struct nvidia_par *par, + int level) +{ + struct fb_info *info = pci_get_drvdata(par->pci_dev); + int nlevel; + + /* Get and convert the value */ + nlevel = MIN_LEVEL + info->bl_curve[level] * LEVEL_STEP; + + if (nlevel < 0) + nlevel = 0; + else if (nlevel < MIN_LEVEL) + nlevel = MIN_LEVEL; + else if (nlevel > MAX_LEVEL) + nlevel = MAX_LEVEL; + + return nlevel; +} + +/* Call with fb_info->bl_mutex held */ +static int __nvidia_bl_update_status(struct backlight_device *bd) +{ + struct nvidia_par *par = class_get_devdata(&bd->class_dev); + u32 tmp_pcrt, tmp_pmc, fpcontrol; + int level; + + if (!par->FlatPanel) + return 0; + + if (bd->props->power != FB_BLANK_UNBLANK || + bd->props->fb_blank != FB_BLANK_UNBLANK) + level = 0; + else + level = bd->props->brightness; + + tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF; + tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC; + fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC; + + if (level > 0) { + tmp_pcrt |= 0x1; + tmp_pmc |= (1 << 31); /* backlight bit */ + tmp_pmc |= nvidia_bl_get_level_brightness(par, level) << 16; + fpcontrol |= par->fpSyncs; + } else + fpcontrol |= 0x20000022; + + NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt); + NV_WR32(par->PMC, 0x10F0, tmp_pmc); + NV_WR32(par->PRAMDAC, 0x848, fpcontrol); + + return 0; +} + +static int nvidia_bl_update_status(struct backlight_device *bd) +{ + struct nvidia_par *par = class_get_devdata(&bd->class_dev); + struct fb_info *info = pci_get_drvdata(par->pci_dev); + int ret; + + mutex_lock(&info->bl_mutex); + ret = __nvidia_bl_update_status(bd); + mutex_unlock(&info->bl_mutex); + + return ret; +} + +static int nvidia_bl_get_brightness(struct backlight_device *bd) +{ + return bd->props->brightness; +} + +static struct backlight_properties nvidia_bl_data = { + .owner = THIS_MODULE, + .get_brightness = nvidia_bl_get_brightness, + .update_status = nvidia_bl_update_status, + .max_brightness = (FB_BACKLIGHT_LEVELS - 1), +}; + +void nvidia_bl_set_power(struct fb_info *info, int power) +{ + mutex_lock(&info->bl_mutex); + + if (info->bl_dev) { + down(&info->bl_dev->sem); + info->bl_dev->props->power = power; + __nvidia_bl_update_status(info->bl_dev); + up(&info->bl_dev->sem); + } + + mutex_unlock(&info->bl_mutex); +} + +void nvidia_bl_init(struct nvidia_par *par) +{ + struct fb_info *info = pci_get_drvdata(par->pci_dev); + struct backlight_device *bd; + char name[12]; + + if (!par->FlatPanel) + return; + +#ifdef CONFIG_PMAC_BACKLIGHT + if (!machine_is(powermac) || + !pmac_has_backlight_type("mnca")) + return; +#endif + + snprintf(name, sizeof(name), "nvidiabl%d", info->node); + + bd = backlight_device_register(name, par, &nvidia_bl_data); + if (IS_ERR(bd)) { + info->bl_dev = NULL; + printk(KERN_WARNING "nvidia: Backlight registration failed\n"); + goto error; + } + + mutex_lock(&info->bl_mutex); + info->bl_dev = bd; + fb_bl_default_curve(info, 0, + 0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL, + 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); + mutex_unlock(&info->bl_mutex); + + down(&bd->sem); + bd->props->brightness = nvidia_bl_data.max_brightness; + bd->props->power = FB_BLANK_UNBLANK; + bd->props->update_status(bd); + up(&bd->sem); + +#ifdef CONFIG_PMAC_BACKLIGHT + mutex_lock(&pmac_backlight_mutex); + if (!pmac_backlight) + pmac_backlight = bd; + mutex_unlock(&pmac_backlight_mutex); +#endif + + printk("nvidia: Backlight initialized (%s)\n", name); + + return; + +error: + return; +} + +void nvidia_bl_exit(struct nvidia_par *par) +{ + struct fb_info *info = pci_get_drvdata(par->pci_dev); + +#ifdef CONFIG_PMAC_BACKLIGHT + mutex_lock(&pmac_backlight_mutex); +#endif + + mutex_lock(&info->bl_mutex); + if (info->bl_dev) { +#ifdef CONFIG_PMAC_BACKLIGHT + if (pmac_backlight == info->bl_dev) + pmac_backlight = NULL; +#endif + + backlight_device_unregister(info->bl_dev); + + printk("nvidia: Backlight unloaded\n"); + } + mutex_unlock(&info->bl_mutex); + +#ifdef CONFIG_PMAC_BACKLIGHT + mutex_unlock(&pmac_backlight_mutex); +#endif +} diff --git a/drivers/video/pnx4008/Makefile b/drivers/video/pnx4008/Makefile new file mode 100644 index 000000000..636aaccf0 --- /dev/null +++ b/drivers/video/pnx4008/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the new PNX4008 framebuffer device driver +# + +obj-$(CONFIG_FB_PNX4008_DUM) += sdum.o +obj-$(CONFIG_FB_PNX4008_DUM_RGB) += pnxrgbfb.o + diff --git a/drivers/video/pnx4008/dum.h b/drivers/video/pnx4008/dum.h new file mode 100644 index 000000000..d80a614d8 --- /dev/null +++ b/drivers/video/pnx4008/dum.h @@ -0,0 +1,211 @@ +/* + * linux/drivers/video/pnx4008/dum.h + * + * Internal header for SDUM + * + * 2005 (c) Koninklijke Philips N.V. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#ifndef __PNX008_DUM_H__ +#define __PNX008_DUM_H__ + +#include <asm/arch/platform.h> + +#define PNX4008_DUMCONF_VA_BASE IO_ADDRESS(PNX4008_DUMCONF_BASE) +#define PNX4008_DUM_MAIN_VA_BASE IO_ADDRESS(PNX4008_DUM_MAINCFG_BASE) + +/* DUM CFG ADDRESSES */ +#define DUM_CH_BASE_ADR (PNX4008_DUMCONF_VA_BASE + 0x00) +#define DUM_CH_MIN_ADR (PNX4008_DUMCONF_VA_BASE + 0x00) +#define DUM_CH_MAX_ADR (PNX4008_DUMCONF_VA_BASE + 0x04) +#define DUM_CH_CONF_ADR (PNX4008_DUMCONF_VA_BASE + 0x08) +#define DUM_CH_STAT_ADR (PNX4008_DUMCONF_VA_BASE + 0x0C) +#define DUM_CH_CTRL_ADR (PNX4008_DUMCONF_VA_BASE + 0x10) + +#define CH_MARG (0x100 / sizeof(u32)) +#define DUM_CH_MIN(i) (*((volatile u32 *)DUM_CH_MIN_ADR + (i) * CH_MARG)) +#define DUM_CH_MAX(i) (*((volatile u32 *)DUM_CH_MAX_ADR + (i) * CH_MARG)) +#define DUM_CH_CONF(i) (*((volatile u32 *)DUM_CH_CONF_ADR + (i) * CH_MARG)) +#define DUM_CH_STAT(i) (*((volatile u32 *)DUM_CH_STAT_ADR + (i) * CH_MARG)) +#define DUM_CH_CTRL(i) (*((volatile u32 *)DUM_CH_CTRL_ADR + (i) * CH_MARG)) + +#define DUM_CONF_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x00) +#define DUM_CTRL_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x04) +#define DUM_STAT_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x08) +#define DUM_DECODE_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x0C) +#define DUM_COM_BASE_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x10) +#define DUM_SYNC_C_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x14) +#define DUM_CLK_DIV_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x18) +#define DUM_DIRTY_LOW_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x20) +#define DUM_DIRTY_HIGH_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x24) +#define DUM_FORMAT_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x28) +#define DUM_WTCFG1_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x30) +#define DUM_RTCFG1_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x34) +#define DUM_WTCFG2_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x38) +#define DUM_RTCFG2_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x3C) +#define DUM_TCFG_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x40) +#define DUM_OUTP_FORMAT1_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x44) +#define DUM_OUTP_FORMAT2_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x48) +#define DUM_SYNC_MODE_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x4C) +#define DUM_SYNC_OUT_C_ADR (PNX4008_DUM_MAIN_VA_BASE + 0x50) + +#define DUM_CONF (*(volatile u32 *)(DUM_CONF_ADR)) +#define DUM_CTRL (*(volatile u32 *)(DUM_CTRL_ADR)) +#define DUM_STAT (*(volatile u32 *)(DUM_STAT_ADR)) +#define DUM_DECODE (*(volatile u32 *)(DUM_DECODE_ADR)) +#define DUM_COM_BASE (*(volatile u32 *)(DUM_COM_BASE_ADR)) +#define DUM_SYNC_C (*(volatile u32 *)(DUM_SYNC_C_ADR)) +#define DUM_CLK_DIV (*(volatile u32 *)(DUM_CLK_DIV_ADR)) +#define DUM_DIRTY_LOW (*(volatile u32 *)(DUM_DIRTY_LOW_ADR)) +#define DUM_DIRTY_HIGH (*(volatile u32 *)(DUM_DIRTY_HIGH_ADR)) +#define DUM_FORMAT (*(volatile u32 *)(DUM_FORMAT_ADR)) +#define DUM_WTCFG1 (*(volatile u32 *)(DUM_WTCFG1_ADR)) +#define DUM_RTCFG1 (*(volatile u32 *)(DUM_RTCFG1_ADR)) +#define DUM_WTCFG2 (*(volatile u32 *)(DUM_WTCFG2_ADR)) +#define DUM_RTCFG2 (*(volatile u32 *)(DUM_RTCFG2_ADR)) +#define DUM_TCFG (*(volatile u32 *)(DUM_TCFG_ADR)) +#define DUM_OUTP_FORMAT1 (*(volatile u32 *)(DUM_OUTP_FORMAT1_ADR)) +#define DUM_OUTP_FORMAT2 (*(volatile u32 *)(DUM_OUTP_FORMAT2_ADR)) +#define DUM_SYNC_MODE (*(volatile u32 *)(DUM_SYNC_MODE_ADR)) +#define DUM_SYNC_OUT_C (*(volatile u32 *)(DUM_SYNC_OUT_C_ADR)) + +/* DUM SLAVE ADDRESSES */ +#define DUM_SLAVE_WRITE_ADR (PNX4008_DUM_MAINCFG_BASE + 0x0000000) +#define DUM_SLAVE_READ1_I_ADR (PNX4008_DUM_MAINCFG_BASE + 0x1000000) +#define DUM_SLAVE_READ1_R_ADR (PNX4008_DUM_MAINCFG_BASE + 0x1000004) +#define DUM_SLAVE_READ2_I_ADR (PNX4008_DUM_MAINCFG_BASE + 0x1000008) +#define DUM_SLAVE_READ2_R_ADR (PNX4008_DUM_MAINCFG_BASE + 0x100000C) + +#define DUM_SLAVE_WRITE_W ((volatile u32 *)(DUM_SLAVE_WRITE_ADR)) +#define DUM_SLAVE_WRITE_HW ((volatile u16 *)(DUM_SLAVE_WRITE_ADR)) +#define DUM_SLAVE_READ1_I ((volatile u8 *)(DUM_SLAVE_READ1_I_ADR)) +#define DUM_SLAVE_READ1_R ((volatile u16 *)(DUM_SLAVE_READ1_R_ADR)) +#define DUM_SLAVE_READ2_I ((volatile u8 *)(DUM_SLAVE_READ2_I_ADR)) +#define DUM_SLAVE_READ2_R ((volatile u16 *)(DUM_SLAVE_READ2_R_ADR)) + +/* Sony display register addresses */ +#define DISP_0_REG (0x00) +#define DISP_1_REG (0x01) +#define DISP_CAL_REG (0x20) +#define DISP_ID_REG (0x2A) +#define DISP_XMIN_L_REG (0x30) +#define DISP_XMIN_H_REG (0x31) +#define DISP_YMIN_REG (0x32) +#define DISP_XMAX_L_REG (0x34) +#define DISP_XMAX_H_REG (0x35) +#define DISP_YMAX_REG (0x36) +#define DISP_SYNC_EN_REG (0x38) +#define DISP_SYNC_RISE_L_REG (0x3C) +#define DISP_SYNC_RISE_H_REG (0x3D) +#define DISP_SYNC_FALL_L_REG (0x3E) +#define DISP_SYNC_FALL_H_REG (0x3F) +#define DISP_PIXEL_REG (0x0B) +#define DISP_DUMMY1_REG (0x28) +#define DISP_DUMMY2_REG (0x29) +#define DISP_TIMING_REG (0x98) +#define DISP_DUMP_REG (0x99) + +/* Sony display constants */ +#define SONY_ID1 (0x22) +#define SONY_ID2 (0x23) + +/* Philips display register addresses */ +#define PH_DISP_ORIENT_REG (0x003) +#define PH_DISP_YPOINT_REG (0x200) +#define PH_DISP_XPOINT_REG (0x201) +#define PH_DISP_PIXEL_REG (0x202) +#define PH_DISP_YMIN_REG (0x406) +#define PH_DISP_YMAX_REG (0x407) +#define PH_DISP_XMIN_REG (0x408) +#define PH_DISP_XMAX_REG (0x409) + +/* Misc constants */ +#define NO_VALID_DISPLAY_FOUND (0) +#define DISPLAY2_IS_NOT_CONNECTED (0) + +/* register values */ +#define V_BAC_ENABLE (BIT(0)) +#define V_BAC_DISABLE_IDLE (BIT(1)) +#define V_BAC_DISABLE_TRIG (BIT(2)) +#define V_DUM_RESET (BIT(3)) +#define V_MUX_RESET (BIT(4)) +#define BAC_ENABLED (BIT(0)) +#define BAC_DISABLED 0 + +/* Sony LCD commands */ +#define V_LCD_STANDBY_OFF ((BIT(25)) | (0 << 16) | DISP_0_REG) +#define V_LCD_USE_9BIT_BUS ((BIT(25)) | (2 << 16) | DISP_1_REG) +#define V_LCD_SYNC_RISE_L ((BIT(25)) | (0 << 16) | DISP_SYNC_RISE_L_REG) +#define V_LCD_SYNC_RISE_H ((BIT(25)) | (0 << 16) | DISP_SYNC_RISE_H_REG) +#define V_LCD_SYNC_FALL_L ((BIT(25)) | (160 << 16) | DISP_SYNC_FALL_L_REG) +#define V_LCD_SYNC_FALL_H ((BIT(25)) | (0 << 16) | DISP_SYNC_FALL_H_REG) +#define V_LCD_SYNC_ENABLE ((BIT(25)) | (128 << 16) | DISP_SYNC_EN_REG) +#define V_LCD_DISPLAY_ON ((BIT(25)) | (64 << 16) | DISP_0_REG) + +enum { + PAD_NONE, + PAD_512, + PAD_1024 +}; + +enum { + RGB888, + RGB666, + RGB565, + BGR565, + ARGB1555, + ABGR1555, + ARGB4444, + ABGR4444 +}; + +struct dum_setup { + int sync_neg_edge; + int round_robin; + int mux_int; + int synced_dirty_flag_int; + int dirty_flag_int; + int error_int; + int pf_empty_int; + int sf_empty_int; + int bac_dis_int; + u32 dirty_base_adr; + u32 command_base_adr; + u32 sync_clk_div; + int sync_output; + u32 sync_restart_val; + u32 set_sync_high; + u32 set_sync_low; +}; + +struct dum_ch_setup { + int disp_no; + u32 xmin; + u32 ymin; + u32 xmax; + u32 ymax; + int xmirror; + int ymirror; + int rotate; + u32 minadr; + u32 maxadr; + u32 dirtybuffer; + int pad; + int format; + int hwdirty; + int slave_trans; +}; + +struct disp_window { + u32 xmin_l; + u32 xmin_h; + u32 ymin; + u32 xmax_l; + u32 xmax_h; + u32 ymax; +}; + +#endif /* #ifndef __PNX008_DUM_H__ */ diff --git a/drivers/video/pnx4008/fbcommon.h b/drivers/video/pnx4008/fbcommon.h new file mode 100644 index 000000000..4ebc87daf --- /dev/null +++ b/drivers/video/pnx4008/fbcommon.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2005 Philips Semiconductors + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA, or http://www.gnu.org/licenses/gpl.html +*/ + +#define QCIF_W (176) +#define QCIF_H (144) + +#define CIF_W (352) +#define CIF_H (288) + +#define LCD_X_RES 208 +#define LCD_Y_RES 320 +#define LCD_X_PAD 256 +#define LCD_BBP 4 /* Bytes Per Pixel */ + +#define DISP_MAX_X_SIZE (320) +#define DISP_MAX_Y_SIZE (208) + +#define RETURNVAL_BASE (0x400) + +enum fb_ioctl_returntype { + ENORESOURCESLEFT = RETURNVAL_BASE, + ERESOURCESNOTFREED, + EPROCNOTOWNER, + EFBNOTOWNER, + ECOPYFAILED, + EIOREMAPFAILED, +}; diff --git a/drivers/video/pnx4008/pnxrgbfb.c b/drivers/video/pnx4008/pnxrgbfb.c new file mode 100644 index 000000000..7d9453c91 --- /dev/null +++ b/drivers/video/pnx4008/pnxrgbfb.c @@ -0,0 +1,213 @@ +/* + * drivers/video/pnx4008/pnxrgbfb.c + * + * PNX4008's framebuffer support + * + * Author: Grigory Tolstolytkin <gtolstolytkin@ru.mvista.com> + * Based on Philips Semiconductors's code + * + * Copyrght (c) 2005 MontaVista Software, Inc. + * Copyright (c) 2005 Philips Semiconductors + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/platform_device.h> + +#include <asm/uaccess.h> +#include "sdum.h" +#include "fbcommon.h" + +static u32 colreg[16]; + +static struct fb_var_screeninfo rgbfb_var __initdata = { + .xres = LCD_X_RES, + .yres = LCD_Y_RES, + .xres_virtual = LCD_X_RES, + .yres_virtual = LCD_Y_RES, + .bits_per_pixel = 32, + .red.offset = 16, + .red.length = 8, + .green.offset = 8, + .green.length = 8, + .blue.offset = 0, + .blue.length = 8, + .left_margin = 0, + .right_margin = 0, + .upper_margin = 0, + .lower_margin = 0, + .vmode = FB_VMODE_NONINTERLACED, +}; +static struct fb_fix_screeninfo rgbfb_fix __initdata = { + .id = "RGBFB", + .line_length = LCD_X_RES * LCD_BBP, + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .xpanstep = 0, + .ypanstep = 0, + .ywrapstep = 0, + .accel = FB_ACCEL_NONE, +}; + +static int channel_owned; + +static int no_cursor(struct fb_info *info, struct fb_cursor *cursor) +{ + return 0; +} + +static int rgbfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + if (regno > 15) + return 1; + + colreg[regno] = ((red & 0xff00) << 8) | (green & 0xff00) | + ((blue & 0xff00) >> 8); + return 0; +} + +static int rgbfb_mmap(struct fb_info *info, struct vm_area_struct *vma) +{ + return pnx4008_sdum_mmap(info, vma, NULL); +} + +static struct fb_ops rgbfb_ops = { + .fb_mmap = rgbfb_mmap, + .fb_setcolreg = rgbfb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +static int rgbfb_remove(struct platform_device *pdev) +{ + struct fb_info *info = platform_get_drvdata(pdev); + + if (info) { + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); + platform_set_drvdata(pdev, NULL); + kfree(info); + } + + pnx4008_free_dum_channel(channel_owned, pdev->id); + pnx4008_set_dum_exit_notification(pdev->id); + + return 0; +} + +static int __devinit rgbfb_probe(struct platform_device *pdev) +{ + struct fb_info *info; + struct dumchannel_uf chan_uf; + int ret; + char *option; + + info = framebuffer_alloc(sizeof(u32) * 16, &pdev->dev); + if (!info) { + ret = -ENOMEM; + goto err; + } + + pnx4008_get_fb_addresses(FB_TYPE_RGB, (void **)&info->screen_base, + (dma_addr_t *) &rgbfb_fix.smem_start, + &rgbfb_fix.smem_len); + + if ((ret = pnx4008_alloc_dum_channel(pdev->id)) < 0) + goto err0; + else { + channel_owned = ret; + chan_uf.channelnr = channel_owned; + chan_uf.dirty = (u32 *) NULL; + chan_uf.source = (u32 *) rgbfb_fix.smem_start; + chan_uf.x_offset = 0; + chan_uf.y_offset = 0; + chan_uf.width = LCD_X_RES; + chan_uf.height = LCD_Y_RES; + + if ((ret = pnx4008_put_dum_channel_uf(chan_uf, pdev->id))< 0) + goto err1; + + if ((ret = + pnx4008_set_dum_channel_sync(channel_owned, CONF_SYNC_ON, + pdev->id)) < 0) + goto err1; + + if ((ret = + pnx4008_set_dum_channel_dirty_detect(channel_owned, + CONF_DIRTYDETECTION_ON, + pdev->id)) < 0) + goto err1; + } + + if (!fb_get_options("pnxrgbfb", &option) && !strcmp(option, "nocursor")) + rgbfb_ops.fb_cursor = no_cursor; + + info->node = -1; + info->flags = FBINFO_FLAG_DEFAULT; + info->fbops = &rgbfb_ops; + info->fix = rgbfb_fix; + info->var = rgbfb_var; + info->screen_size = rgbfb_fix.smem_len; + info->pseudo_palette = info->par; + info->par = NULL; + + ret = fb_alloc_cmap(&info->cmap, 256, 0); + if (ret < 0) + goto err2; + + ret = register_framebuffer(info); + if (ret < 0) + goto err3; + platform_set_drvdata(pdev, info); + + return 0; + +err3: + fb_dealloc_cmap(&info->cmap); +err2: + framebuffer_release(info); +err1: + pnx4008_free_dum_channel(channel_owned, pdev->id); +err0: + kfree(info); +err: + return ret; +} + +static struct platform_driver rgbfb_driver = { + .driver = { + .name = "rgbfb", + }, + .probe = rgbfb_probe, + .remove = rgbfb_remove, +}; + +static int __init rgbfb_init(void) +{ + return platform_driver_register(&rgbfb_driver); +} + +static void __exit rgbfb_exit(void) +{ + platform_driver_unregister(&rgbfb_driver); +} + +module_init(rgbfb_init); +module_exit(rgbfb_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/video/pnx4008/sdum.c b/drivers/video/pnx4008/sdum.c new file mode 100644 index 000000000..51f0ecc2a --- /dev/null +++ b/drivers/video/pnx4008/sdum.c @@ -0,0 +1,872 @@ +/* + * drivers/video/pnx4008/sdum.c + * + * Display Update Master support + * + * Authors: Grigory Tolstolytkin <gtolstolytkin@ru.mvista.com> + * Vitaly Wool <vitalywool@gmail.com> + * Based on Philips Semiconductors's code + * + * Copyrght (c) 2005-2006 MontaVista Software, Inc. + * Copyright (c) 2005 Philips Semiconductors + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/tty.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/dma-mapping.h> +#include <linux/clk.h> +#include <asm/uaccess.h> +#include <asm/arch/gpio.h> + +#include "sdum.h" +#include "fbcommon.h" +#include "dum.h" + +/* Framebuffers we have */ + +static struct pnx4008_fb_addr { + int fb_type; + long addr_offset; + long fb_length; +} fb_addr[] = { + [0] = { + FB_TYPE_YUV, 0, 0xB0000 + }, + [1] = { + FB_TYPE_RGB, 0xB0000, 0x50000 + }, +}; + +static struct dum_data { + u32 lcd_phys_start; + u32 lcd_virt_start; + u32 slave_phys_base; + u32 *slave_virt_base; + int fb_owning_channel[MAX_DUM_CHANNELS]; + struct dumchannel_uf chan_uf_store[MAX_DUM_CHANNELS]; +} dum_data; + +/* Different local helper functions */ + +static u32 nof_pixels_dx(struct dum_ch_setup *ch_setup) +{ + return (ch_setup->xmax - ch_setup->xmin + 1); +} + +static u32 nof_pixels_dy(struct dum_ch_setup *ch_setup) +{ + return (ch_setup->ymax - ch_setup->ymin + 1); +} + +static u32 nof_pixels_dxy(struct dum_ch_setup *ch_setup) +{ + return (nof_pixels_dx(ch_setup) * nof_pixels_dy(ch_setup)); +} + +static u32 nof_bytes(struct dum_ch_setup *ch_setup) +{ + u32 r = nof_pixels_dxy(ch_setup); + switch (ch_setup->format) { + case RGB888: + case RGB666: + r *= 4; + break; + + default: + r *= 2; + break; + } + return r; +} + +static u32 build_command(int disp_no, u32 reg, u32 val) +{ + return ((disp_no << 26) | BIT(25) | (val << 16) | (disp_no << 10) | + (reg << 0)); +} + +static u32 build_double_index(int disp_no, u32 val) +{ + return ((disp_no << 26) | (val << 16) | (disp_no << 10) | (val << 0)); +} + +static void build_disp_window(struct dum_ch_setup * ch_setup, struct disp_window * dw) +{ + dw->ymin = ch_setup->ymin; + dw->ymax = ch_setup->ymax; + dw->xmin_l = ch_setup->xmin & 0xFF; + dw->xmin_h = (ch_setup->xmin & BIT(8)) >> 8; + dw->xmax_l = ch_setup->xmax & 0xFF; + dw->xmax_h = (ch_setup->xmax & BIT(8)) >> 8; +} + +static int put_channel(struct dumchannel chan) +{ + int i = chan.channelnr; + + if (i < 0 || i > MAX_DUM_CHANNELS) + return -EINVAL; + else { + DUM_CH_MIN(i) = chan.dum_ch_min; + DUM_CH_MAX(i) = chan.dum_ch_max; + DUM_CH_CONF(i) = chan.dum_ch_conf; + DUM_CH_CTRL(i) = chan.dum_ch_ctrl; + } + + return 0; +} + +static void clear_channel(int channr) +{ + struct dumchannel chan; + + chan.channelnr = channr; + chan.dum_ch_min = 0; + chan.dum_ch_max = 0; + chan.dum_ch_conf = 0; + chan.dum_ch_ctrl = 0; + + put_channel(chan); +} + +static int put_cmd_string(struct cmdstring cmds) +{ + u16 *cmd_str_virtaddr; + u32 *cmd_ptr0_virtaddr; + u32 cmd_str_physaddr; + + int i = cmds.channelnr; + + if (i < 0 || i > MAX_DUM_CHANNELS) + return -EINVAL; + else if ((cmd_ptr0_virtaddr = + (int *)ioremap_nocache(DUM_COM_BASE, + sizeof(int) * MAX_DUM_CHANNELS)) == + NULL) + return -EIOREMAPFAILED; + else { + cmd_str_physaddr = ioread32(&cmd_ptr0_virtaddr[cmds.channelnr]); + if ((cmd_str_virtaddr = + (u16 *) ioremap_nocache(cmd_str_physaddr, + sizeof(cmds))) == NULL) { + iounmap(cmd_ptr0_virtaddr); + return -EIOREMAPFAILED; + } else { + int t; + for (t = 0; t < 8; t++) + iowrite16(*((u16 *)&cmds.prestringlen + t), + cmd_str_virtaddr + t); + + for (t = 0; t < cmds.prestringlen / 2; t++) + iowrite16(*((u16 *)&cmds.precmd + t), + cmd_str_virtaddr + t + 8); + + for (t = 0; t < cmds.poststringlen / 2; t++) + iowrite16(*((u16 *)&cmds.postcmd + t), + cmd_str_virtaddr + t + 8 + + cmds.prestringlen / 2); + + iounmap(cmd_ptr0_virtaddr); + iounmap(cmd_str_virtaddr); + } + } + + return 0; +} + +static u32 dum_ch_setup(int ch_no, struct dum_ch_setup * ch_setup) +{ + struct cmdstring cmds_c; + struct cmdstring *cmds = &cmds_c; + struct disp_window dw; + int standard; + u32 orientation = 0; + struct dumchannel chan = { 0 }; + int ret; + + if ((ch_setup->xmirror) || (ch_setup->ymirror) || (ch_setup->rotate)) { + standard = 0; + + orientation = BIT(1); /* always set 9-bit-bus */ + if (ch_setup->xmirror) + orientation |= BIT(4); + if (ch_setup->ymirror) + orientation |= BIT(3); + if (ch_setup->rotate) + orientation |= BIT(0); + } else + standard = 1; + + cmds->channelnr = ch_no; + + /* build command string header */ + if (standard) { + cmds->prestringlen = 32; + cmds->poststringlen = 0; + } else { + cmds->prestringlen = 48; + cmds->poststringlen = 16; + } + + cmds->format = + (u16) ((ch_setup->disp_no << 4) | (BIT(3)) | (ch_setup->format)); + cmds->reserved = 0x0; + cmds->startaddr_low = (ch_setup->minadr & 0xFFFF); + cmds->startaddr_high = (ch_setup->minadr >> 16); + + if ((ch_setup->minadr == 0) && (ch_setup->maxadr == 0) + && (ch_setup->xmin == 0) + && (ch_setup->ymin == 0) && (ch_setup->xmax == 0) + && (ch_setup->ymax == 0)) { + cmds->pixdatlen_low = 0; + cmds->pixdatlen_high = 0; + } else { + u32 nbytes = nof_bytes(ch_setup); + cmds->pixdatlen_low = (nbytes & 0xFFFF); + cmds->pixdatlen_high = (nbytes >> 16); + } + + if (ch_setup->slave_trans) + cmds->pixdatlen_high |= BIT(15); + + /* build pre-string */ + build_disp_window(ch_setup, &dw); + + if (standard) { + cmds->precmd[0] = + build_command(ch_setup->disp_no, DISP_XMIN_L_REG, 0x99); + cmds->precmd[1] = + build_command(ch_setup->disp_no, DISP_XMIN_L_REG, + dw.xmin_l); + cmds->precmd[2] = + build_command(ch_setup->disp_no, DISP_XMIN_H_REG, + dw.xmin_h); + cmds->precmd[3] = + build_command(ch_setup->disp_no, DISP_YMIN_REG, dw.ymin); + cmds->precmd[4] = + build_command(ch_setup->disp_no, DISP_XMAX_L_REG, + dw.xmax_l); + cmds->precmd[5] = + build_command(ch_setup->disp_no, DISP_XMAX_H_REG, + dw.xmax_h); + cmds->precmd[6] = + build_command(ch_setup->disp_no, DISP_YMAX_REG, dw.ymax); + cmds->precmd[7] = + build_double_index(ch_setup->disp_no, DISP_PIXEL_REG); + } else { + if (dw.xmin_l == ch_no) + cmds->precmd[0] = + build_command(ch_setup->disp_no, DISP_XMIN_L_REG, + 0x99); + else + cmds->precmd[0] = + build_command(ch_setup->disp_no, DISP_XMIN_L_REG, + ch_no); + + cmds->precmd[1] = + build_command(ch_setup->disp_no, DISP_XMIN_L_REG, + dw.xmin_l); + cmds->precmd[2] = + build_command(ch_setup->disp_no, DISP_XMIN_H_REG, + dw.xmin_h); + cmds->precmd[3] = + build_command(ch_setup->disp_no, DISP_YMIN_REG, dw.ymin); + cmds->precmd[4] = + build_command(ch_setup->disp_no, DISP_XMAX_L_REG, + dw.xmax_l); + cmds->precmd[5] = + build_command(ch_setup->disp_no, DISP_XMAX_H_REG, + dw.xmax_h); + cmds->precmd[6] = + build_command(ch_setup->disp_no, DISP_YMAX_REG, dw.ymax); + cmds->precmd[7] = + build_command(ch_setup->disp_no, DISP_1_REG, orientation); + cmds->precmd[8] = + build_double_index(ch_setup->disp_no, DISP_PIXEL_REG); + cmds->precmd[9] = + build_double_index(ch_setup->disp_no, DISP_PIXEL_REG); + cmds->precmd[0xA] = + build_double_index(ch_setup->disp_no, DISP_PIXEL_REG); + cmds->precmd[0xB] = + build_double_index(ch_setup->disp_no, DISP_PIXEL_REG); + cmds->postcmd[0] = + build_command(ch_setup->disp_no, DISP_1_REG, BIT(1)); + cmds->postcmd[1] = + build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 1); + cmds->postcmd[2] = + build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 2); + cmds->postcmd[3] = + build_command(ch_setup->disp_no, DISP_DUMMY1_REG, 3); + } + + if ((ret = put_cmd_string(cmds_c)) != 0) { + return ret; + } + + chan.channelnr = cmds->channelnr; + chan.dum_ch_min = ch_setup->dirtybuffer + ch_setup->minadr; + chan.dum_ch_max = ch_setup->dirtybuffer + ch_setup->maxadr; + chan.dum_ch_conf = 0x002; + chan.dum_ch_ctrl = 0x04; + + put_channel(chan); + + return 0; +} + +static u32 display_open(int ch_no, int auto_update, u32 * dirty_buffer, + u32 * frame_buffer, u32 xpos, u32 ypos, u32 w, u32 h) +{ + + struct dum_ch_setup k; + int ret; + + /* keep width & height within display area */ + if ((xpos + w) > DISP_MAX_X_SIZE) + w = DISP_MAX_X_SIZE - xpos; + + if ((ypos + h) > DISP_MAX_Y_SIZE) + h = DISP_MAX_Y_SIZE - ypos; + + /* assume 1 display only */ + k.disp_no = 0; + k.xmin = xpos; + k.ymin = ypos; + k.xmax = xpos + (w - 1); + k.ymax = ypos + (h - 1); + + /* adjust min and max values if necessary */ + if (k.xmin > DISP_MAX_X_SIZE - 1) + k.xmin = DISP_MAX_X_SIZE - 1; + if (k.ymin > DISP_MAX_Y_SIZE - 1) + k.ymin = DISP_MAX_Y_SIZE - 1; + + if (k.xmax > DISP_MAX_X_SIZE - 1) + k.xmax = DISP_MAX_X_SIZE - 1; + if (k.ymax > DISP_MAX_Y_SIZE - 1) + k.ymax = DISP_MAX_Y_SIZE - 1; + + k.xmirror = 0; + k.ymirror = 0; + k.rotate = 0; + k.minadr = (u32) frame_buffer; + k.maxadr = (u32) frame_buffer + (((w - 1) << 10) | ((h << 2) - 2)); + k.pad = PAD_1024; + k.dirtybuffer = (u32) dirty_buffer; + k.format = RGB888; + k.hwdirty = 0; + k.slave_trans = 0; + + ret = dum_ch_setup(ch_no, &k); + + return ret; +} + +static void lcd_reset(void) +{ + u32 *dum_pio_base = (u32 *)IO_ADDRESS(PNX4008_PIO_BASE); + + udelay(1); + iowrite32(BIT(19), &dum_pio_base[2]); + udelay(1); + iowrite32(BIT(19), &dum_pio_base[1]); + udelay(1); +} + +static int dum_init(struct platform_device *pdev) +{ + struct clk *clk; + + /* enable DUM clock */ + clk = clk_get(&pdev->dev, "dum_ck"); + if (IS_ERR(clk)) { + printk(KERN_ERR "pnx4008_dum: Unable to access DUM clock\n"); + return PTR_ERR(clk); + } + + clk_set_rate(clk, 1); + clk_put(clk); + + DUM_CTRL = V_DUM_RESET; + + /* set priority to "round-robin". All other params to "false" */ + DUM_CONF = BIT(9); + + /* Display 1 */ + DUM_WTCFG1 = PNX4008_DUM_WT_CFG; + DUM_RTCFG1 = PNX4008_DUM_RT_CFG; + DUM_TCFG = PNX4008_DUM_T_CFG; + + return 0; +} + +static void dum_chan_init(void) +{ + int i = 0, ch = 0; + u32 *cmdptrs; + u32 *cmdstrings; + + DUM_COM_BASE = + CMDSTRING_BASEADDR + BYTES_PER_CMDSTRING * NR_OF_CMDSTRINGS; + + if ((cmdptrs = + (u32 *) ioremap_nocache(DUM_COM_BASE, + sizeof(u32) * NR_OF_CMDSTRINGS)) == NULL) + return; + + for (ch = 0; ch < NR_OF_CMDSTRINGS; ch++) + iowrite32(CMDSTRING_BASEADDR + BYTES_PER_CMDSTRING * ch, + cmdptrs + ch); + + for (ch = 0; ch < MAX_DUM_CHANNELS; ch++) + clear_channel(ch); + + /* Clear the cmdstrings */ + cmdstrings = + (u32 *)ioremap_nocache(*cmdptrs, + BYTES_PER_CMDSTRING * NR_OF_CMDSTRINGS); + + if (!cmdstrings) + goto out; + + for (i = 0; i < NR_OF_CMDSTRINGS * BYTES_PER_CMDSTRING / sizeof(u32); + i++) + iowrite32(0, cmdstrings + i); + + iounmap((u32 *)cmdstrings); + +out: + iounmap((u32 *)cmdptrs); +} + +static void lcd_init(void) +{ + lcd_reset(); + + DUM_OUTP_FORMAT1 = 0; /* RGB666 */ + + udelay(1); + iowrite32(V_LCD_STANDBY_OFF, dum_data.slave_virt_base); + udelay(1); + iowrite32(V_LCD_USE_9BIT_BUS, dum_data.slave_virt_base); + udelay(1); + iowrite32(V_LCD_SYNC_RISE_L, dum_data.slave_virt_base); + udelay(1); + iowrite32(V_LCD_SYNC_RISE_H, dum_data.slave_virt_base); + udelay(1); + iowrite32(V_LCD_SYNC_FALL_L, dum_data.slave_virt_base); + udelay(1); + iowrite32(V_LCD_SYNC_FALL_H, dum_data.slave_virt_base); + udelay(1); + iowrite32(V_LCD_SYNC_ENABLE, dum_data.slave_virt_base); + udelay(1); + iowrite32(V_LCD_DISPLAY_ON, dum_data.slave_virt_base); + udelay(1); +} + +/* Interface exported to framebuffer drivers */ + +int pnx4008_get_fb_addresses(int fb_type, void **virt_addr, + dma_addr_t *phys_addr, int *fb_length) +{ + int i; + int ret = -1; + for (i = 0; i < ARRAY_SIZE(fb_addr); i++) + if (fb_addr[i].fb_type == fb_type) { + *virt_addr = (void *)(dum_data.lcd_virt_start + + fb_addr[i].addr_offset); + *phys_addr = + dum_data.lcd_phys_start + fb_addr[i].addr_offset; + *fb_length = fb_addr[i].fb_length; + ret = 0; + break; + } + + return ret; +} + +EXPORT_SYMBOL(pnx4008_get_fb_addresses); + +int pnx4008_alloc_dum_channel(int dev_id) +{ + int i = 0; + + while ((i < MAX_DUM_CHANNELS) && (dum_data.fb_owning_channel[i] != -1)) + i++; + + if (i == MAX_DUM_CHANNELS) + return -ENORESOURCESLEFT; + else { + dum_data.fb_owning_channel[i] = dev_id; + return i; + } +} + +EXPORT_SYMBOL(pnx4008_alloc_dum_channel); + +int pnx4008_free_dum_channel(int channr, int dev_id) +{ + if (channr < 0 || channr > MAX_DUM_CHANNELS) + return -EINVAL; + else if (dum_data.fb_owning_channel[channr] != dev_id) + return -EFBNOTOWNER; + else { + clear_channel(channr); + dum_data.fb_owning_channel[channr] = -1; + } + + return 0; +} + +EXPORT_SYMBOL(pnx4008_free_dum_channel); + +int pnx4008_put_dum_channel_uf(struct dumchannel_uf chan_uf, int dev_id) +{ + int i = chan_uf.channelnr; + int ret; + + if (i < 0 || i > MAX_DUM_CHANNELS) + return -EINVAL; + else if (dum_data.fb_owning_channel[i] != dev_id) + return -EFBNOTOWNER; + else if ((ret = + display_open(chan_uf.channelnr, 0, chan_uf.dirty, + chan_uf.source, chan_uf.y_offset, + chan_uf.x_offset, chan_uf.height, + chan_uf.width)) != 0) + return ret; + else { + dum_data.chan_uf_store[i].dirty = chan_uf.dirty; + dum_data.chan_uf_store[i].source = chan_uf.source; + dum_data.chan_uf_store[i].x_offset = chan_uf.x_offset; + dum_data.chan_uf_store[i].y_offset = chan_uf.y_offset; + dum_data.chan_uf_store[i].width = chan_uf.width; + dum_data.chan_uf_store[i].height = chan_uf.height; + } + + return 0; +} + +EXPORT_SYMBOL(pnx4008_put_dum_channel_uf); + +int pnx4008_set_dum_channel_sync(int channr, int val, int dev_id) +{ + if (channr < 0 || channr > MAX_DUM_CHANNELS) + return -EINVAL; + else if (dum_data.fb_owning_channel[channr] != dev_id) + return -EFBNOTOWNER; + else { + if (val == CONF_SYNC_ON) { + DUM_CH_CONF(channr) |= CONF_SYNCENABLE; + DUM_CH_CONF(channr) |= DUM_CHANNEL_CFG_SYNC_MASK | + DUM_CHANNEL_CFG_SYNC_MASK_SET; + } else if (val == CONF_SYNC_OFF) + DUM_CH_CONF(channr) &= ~CONF_SYNCENABLE; + else + return -EINVAL; + } + + return 0; +} + +EXPORT_SYMBOL(pnx4008_set_dum_channel_sync); + +int pnx4008_set_dum_channel_dirty_detect(int channr, int val, int dev_id) +{ + if (channr < 0 || channr > MAX_DUM_CHANNELS) + return -EINVAL; + else if (dum_data.fb_owning_channel[channr] != dev_id) + return -EFBNOTOWNER; + else { + if (val == CONF_DIRTYDETECTION_ON) + DUM_CH_CONF(channr) |= CONF_DIRTYENABLE; + else if (val == CONF_DIRTYDETECTION_OFF) + DUM_CH_CONF(channr) &= ~CONF_DIRTYENABLE; + else + return -EINVAL; + } + + return 0; +} + +EXPORT_SYMBOL(pnx4008_set_dum_channel_dirty_detect); + +#if 0 /* Functions not used currently, but likely to be used in future */ + +static int get_channel(struct dumchannel *p_chan) +{ + int i = p_chan->channelnr; + + if (i < 0 || i > MAX_DUM_CHANNELS) + return -EINVAL; + else { + p_chan->dum_ch_min = DUM_CH_MIN(i); + p_chan->dum_ch_max = DUM_CH_MAX(i); + p_chan->dum_ch_conf = DUM_CH_CONF(i); + p_chan->dum_ch_stat = DUM_CH_STAT(i); + p_chan->dum_ch_ctrl = 0; /* WriteOnly control register */ + } + + return 0; +} + +int pnx4008_get_dum_channel_uf(struct dumchannel_uf *p_chan_uf, int dev_id) +{ + int i = p_chan_uf->channelnr; + + if (i < 0 || i > MAX_DUM_CHANNELS) + return -EINVAL; + else if (dum_data.fb_owning_channel[i] != dev_id) + return -EFBNOTOWNER; + else { + p_chan_uf->dirty = dum_data.chan_uf_store[i].dirty; + p_chan_uf->source = dum_data.chan_uf_store[i].source; + p_chan_uf->x_offset = dum_data.chan_uf_store[i].x_offset; + p_chan_uf->y_offset = dum_data.chan_uf_store[i].y_offset; + p_chan_uf->width = dum_data.chan_uf_store[i].width; + p_chan_uf->height = dum_data.chan_uf_store[i].height; + } + + return 0; +} + +EXPORT_SYMBOL(pnx4008_get_dum_channel_uf); + +int pnx4008_get_dum_channel_config(int channr, int dev_id) +{ + int ret; + struct dumchannel chan; + + if (channr < 0 || channr > MAX_DUM_CHANNELS) + return -EINVAL; + else if (dum_data.fb_owning_channel[channr] != dev_id) + return -EFBNOTOWNER; + else { + chan.channelnr = channr; + if ((ret = get_channel(&chan)) != 0) + return ret; + } + + return (chan.dum_ch_conf & DUM_CHANNEL_CFG_MASK); +} + +EXPORT_SYMBOL(pnx4008_get_dum_channel_config); + +int pnx4008_force_update_dum_channel(int channr, int dev_id) +{ + if (channr < 0 || channr > MAX_DUM_CHANNELS) + return -EINVAL; + + else if (dum_data.fb_owning_channel[channr] != dev_id) + return -EFBNOTOWNER; + else + DUM_CH_CTRL(channr) = CTRL_SETDIRTY; + + return 0; +} + +EXPORT_SYMBOL(pnx4008_force_update_dum_channel); + +#endif + +int pnx4008_sdum_mmap(struct fb_info *info, struct vm_area_struct *vma, + struct device *dev) +{ + unsigned long off = vma->vm_pgoff << PAGE_SHIFT; + + if (off < info->fix.smem_len) { + vma->vm_pgoff += 1; + return dma_mmap_writecombine(dev, vma, + (void *)dum_data.lcd_virt_start, + dum_data.lcd_phys_start, + FB_DMA_SIZE); + } + return -EINVAL; +} + +EXPORT_SYMBOL(pnx4008_sdum_mmap); + +int pnx4008_set_dum_exit_notification(int dev_id) +{ + int i; + + for (i = 0; i < MAX_DUM_CHANNELS; i++) + if (dum_data.fb_owning_channel[i] == dev_id) + return -ERESOURCESNOTFREED; + + return 0; +} + +EXPORT_SYMBOL(pnx4008_set_dum_exit_notification); + +/* Platform device driver for DUM */ + +static int sdum_suspend(struct platform_device *pdev, pm_message_t state) +{ + int retval = 0; + struct clk *clk; + + clk = clk_get(0, "dum_ck"); + if (!IS_ERR(clk)) { + clk_set_rate(clk, 0); + clk_put(clk); + } else + retval = PTR_ERR(clk); + + /* disable BAC */ + DUM_CTRL = V_BAC_DISABLE_IDLE; + + /* LCD standby & turn off display */ + lcd_reset(); + + return retval; +} + +static int sdum_resume(struct platform_device *pdev) +{ + int retval = 0; + struct clk *clk; + + clk = clk_get(0, "dum_ck"); + if (!IS_ERR(clk)) { + clk_set_rate(clk, 1); + clk_put(clk); + } else + retval = PTR_ERR(clk); + + /* wait for BAC disable */ + DUM_CTRL = V_BAC_DISABLE_TRIG; + + while (DUM_CTRL & BAC_ENABLED) + udelay(10); + + /* re-init LCD */ + lcd_init(); + + /* enable BAC and reset MUX */ + DUM_CTRL = V_BAC_ENABLE; + udelay(1); + DUM_CTRL = V_MUX_RESET; + return 0; +} + +static int __devinit sdum_probe(struct platform_device *pdev) +{ + int ret = 0, i = 0; + + /* map frame buffer */ + dum_data.lcd_virt_start = (u32) dma_alloc_writecombine(&pdev->dev, + FB_DMA_SIZE, + &dum_data.lcd_phys_start, + GFP_KERNEL); + + if (!dum_data.lcd_virt_start) { + ret = -ENOMEM; + goto out_3; + } + + /* map slave registers */ + dum_data.slave_phys_base = PNX4008_DUM_SLAVE_BASE; + dum_data.slave_virt_base = + (u32 *) ioremap_nocache(dum_data.slave_phys_base, sizeof(u32)); + + if (dum_data.slave_virt_base == NULL) { + ret = -ENOMEM; + goto out_2; + } + + /* initialize DUM and LCD display */ + ret = dum_init(pdev); + if (ret) + goto out_1; + + dum_chan_init(); + lcd_init(); + + DUM_CTRL = V_BAC_ENABLE; + udelay(1); + DUM_CTRL = V_MUX_RESET; + + /* set decode address and sync clock divider */ + DUM_DECODE = dum_data.lcd_phys_start & DUM_DECODE_MASK; + DUM_CLK_DIV = PNX4008_DUM_CLK_DIV; + + for (i = 0; i < MAX_DUM_CHANNELS; i++) + dum_data.fb_owning_channel[i] = -1; + + /*setup wakeup interrupt */ + start_int_set_rising_edge(SE_DISP_SYNC_INT); + start_int_ack(SE_DISP_SYNC_INT); + start_int_umask(SE_DISP_SYNC_INT); + + return 0; + +out_1: + iounmap((void *)dum_data.slave_virt_base); +out_2: + dma_free_writecombine(&pdev->dev, FB_DMA_SIZE, + (void *)dum_data.lcd_virt_start, + dum_data.lcd_phys_start); +out_3: + return ret; +} + +static int sdum_remove(struct platform_device *pdev) +{ + struct clk *clk; + + start_int_mask(SE_DISP_SYNC_INT); + + clk = clk_get(0, "dum_ck"); + if (!IS_ERR(clk)) { + clk_set_rate(clk, 0); + clk_put(clk); + } + + iounmap((void *)dum_data.slave_virt_base); + + dma_free_writecombine(&pdev->dev, FB_DMA_SIZE, + (void *)dum_data.lcd_virt_start, + dum_data.lcd_phys_start); + + return 0; +} + +static struct platform_driver sdum_driver = { + .driver = { + .name = "sdum", + }, + .probe = sdum_probe, + .remove = sdum_remove, + .suspend = sdum_suspend, + .resume = sdum_resume, +}; + +int __init sdum_init(void) +{ + return platform_driver_register(&sdum_driver); +} + +static void __exit sdum_exit(void) +{ + platform_driver_unregister(&sdum_driver); +}; + +module_init(sdum_init); +module_exit(sdum_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/video/pnx4008/sdum.h b/drivers/video/pnx4008/sdum.h new file mode 100644 index 000000000..e8c5dcdd8 --- /dev/null +++ b/drivers/video/pnx4008/sdum.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2005 Philips Semiconductors + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA, or http://www.gnu.org/licenses/gpl.html +*/ + +#define MAX_DUM_CHANNELS 64 + +#define RGB_MEM_WINDOW(x) (0x10000000 + (x)*0x00100000) + +#define QCIF_OFFSET(x) (((x) == 0) ? 0x00000: ((x) == 1) ? 0x30000: -1) +#define CIF_OFFSET(x) (((x) == 0) ? 0x00000: ((x) == 1) ? 0x60000: -1) + +#define CTRL_SETDIRTY (0x00000001) +#define CONF_DIRTYENABLE (0x00000020) +#define CONF_SYNCENABLE (0x00000004) + +#define DIRTY_ENABLED(conf) ((conf) & 0x0020) +#define SYNC_ENABLED(conf) ((conf) & 0x0004) + +/* Display 1 & 2 Write Timing Configuration */ +#define PNX4008_DUM_WT_CFG 0x00372000 + +/* Display 1 & 2 Read Timing Configuration */ +#define PNX4008_DUM_RT_CFG 0x00003A47 + +/* DUM Transit State Timing Configuration */ +#define PNX4008_DUM_T_CFG 0x1D /* 29 HCLK cycles */ + +/* DUM Sync count clock divider */ +#define PNX4008_DUM_CLK_DIV 0x02DD + +/* Memory size for framebuffer, allocated through dma_alloc_writecombine(). + * Must be PAGE aligned + */ +#define FB_DMA_SIZE (PAGE_ALIGN(SZ_1M + PAGE_SIZE)) + +#define OFFSET_RGBBUFFER (0xB0000) +#define OFFSET_YUVBUFFER (0x00000) + +#define YUVBUFFER (lcd_video_start + OFFSET_YUVBUFFER) +#define RGBBUFFER (lcd_video_start + OFFSET_RGBBUFFER) + +#define CMDSTRING_BASEADDR (0x00C000) /* iram */ +#define BYTES_PER_CMDSTRING (0x80) +#define NR_OF_CMDSTRINGS (64) + +#define MAX_NR_PRESTRINGS (0x40) +#define MAX_NR_POSTSTRINGS (0x40) + +/* various mask definitions */ +#define DUM_CLK_ENABLE 0x01 +#define DUM_CLK_DISABLE 0 +#define DUM_DECODE_MASK 0x1FFFFFFF +#define DUM_CHANNEL_CFG_MASK 0x01FF +#define DUM_CHANNEL_CFG_SYNC_MASK 0xFFFE00FF +#define DUM_CHANNEL_CFG_SYNC_MASK_SET 0x0CA00 + +#define SDUM_RETURNVAL_BASE (0x500) + +#define CONF_SYNC_OFF (0x602) +#define CONF_SYNC_ON (0x603) + +#define CONF_DIRTYDETECTION_OFF (0x600) +#define CONF_DIRTYDETECTION_ON (0x601) + +/* Set the corresponding bit. */ +#define BIT(n) (0x1U << (n)) + +struct dumchannel_uf { + int channelnr; + u32 *dirty; + u32 *source; + u32 x_offset; + u32 y_offset; + u32 width; + u32 height; +}; + +enum { + FB_TYPE_YUV, + FB_TYPE_RGB +}; + +struct cmdstring { + int channelnr; + uint16_t prestringlen; + uint16_t poststringlen; + uint16_t format; + uint16_t reserved; + uint16_t startaddr_low; + uint16_t startaddr_high; + uint16_t pixdatlen_low; + uint16_t pixdatlen_high; + u32 precmd[MAX_NR_PRESTRINGS]; + u32 postcmd[MAX_NR_POSTSTRINGS]; + +}; + +struct dumchannel { + int channelnr; + int dum_ch_min; + int dum_ch_max; + int dum_ch_conf; + int dum_ch_stat; + int dum_ch_ctrl; +}; + +int pnx4008_alloc_dum_channel(int dev_id); +int pnx4008_free_dum_channel(int channr, int dev_id); + +int pnx4008_get_dum_channel_uf(struct dumchannel_uf *pChan_uf, int dev_id); +int pnx4008_put_dum_channel_uf(struct dumchannel_uf chan_uf, int dev_id); + +int pnx4008_set_dum_channel_sync(int channr, int val, int dev_id); +int pnx4008_set_dum_channel_dirty_detect(int channr, int val, int dev_id); + +int pnx4008_force_dum_update_channel(int channr, int dev_id); + +int pnx4008_get_dum_channel_config(int channr, int dev_id); + +int pnx4008_sdum_mmap(struct fb_info *info, struct vm_area_struct *vma, struct device *dev); +int pnx4008_set_dum_exit_notification(int dev_id); + +int pnx4008_get_fb_addresses(int fb_type, void **virt_addr, + dma_addr_t * phys_addr, int *fb_length); diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c new file mode 100644 index 000000000..299e274d2 --- /dev/null +++ b/drivers/w1/masters/ds2490.c @@ -0,0 +1,947 @@ +/* + * dscore.c + * + * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru> + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/mod_devicetable.h> +#include <linux/usb.h> + +#include "../w1_int.h" +#include "../w1.h" + +/* COMMAND TYPE CODES */ +#define CONTROL_CMD 0x00 +#define COMM_CMD 0x01 +#define MODE_CMD 0x02 + +/* CONTROL COMMAND CODES */ +#define CTL_RESET_DEVICE 0x0000 +#define CTL_START_EXE 0x0001 +#define CTL_RESUME_EXE 0x0002 +#define CTL_HALT_EXE_IDLE 0x0003 +#define CTL_HALT_EXE_DONE 0x0004 +#define CTL_FLUSH_COMM_CMDS 0x0007 +#define CTL_FLUSH_RCV_BUFFER 0x0008 +#define CTL_FLUSH_XMT_BUFFER 0x0009 +#define CTL_GET_COMM_CMDS 0x000A + +/* MODE COMMAND CODES */ +#define MOD_PULSE_EN 0x0000 +#define MOD_SPEED_CHANGE_EN 0x0001 +#define MOD_1WIRE_SPEED 0x0002 +#define MOD_STRONG_PU_DURATION 0x0003 +#define MOD_PULLDOWN_SLEWRATE 0x0004 +#define MOD_PROG_PULSE_DURATION 0x0005 +#define MOD_WRITE1_LOWTIME 0x0006 +#define MOD_DSOW0_TREC 0x0007 + +/* COMMUNICATION COMMAND CODES */ +#define COMM_ERROR_ESCAPE 0x0601 +#define COMM_SET_DURATION 0x0012 +#define COMM_BIT_IO 0x0020 +#define COMM_PULSE 0x0030 +#define COMM_1_WIRE_RESET 0x0042 +#define COMM_BYTE_IO 0x0052 +#define COMM_MATCH_ACCESS 0x0064 +#define COMM_BLOCK_IO 0x0074 +#define COMM_READ_STRAIGHT 0x0080 +#define COMM_DO_RELEASE 0x6092 +#define COMM_SET_PATH 0x00A2 +#define COMM_WRITE_SRAM_PAGE 0x00B2 +#define COMM_WRITE_EPROM 0x00C4 +#define COMM_READ_CRC_PROT_PAGE 0x00D4 +#define COMM_READ_REDIRECT_PAGE_CRC 0x21E4 +#define COMM_SEARCH_ACCESS 0x00F4 + +/* Communication command bits */ +#define COMM_TYPE 0x0008 +#define COMM_SE 0x0008 +#define COMM_D 0x0008 +#define COMM_Z 0x0008 +#define COMM_CH 0x0008 +#define COMM_SM 0x0008 +#define COMM_R 0x0008 +#define COMM_IM 0x0001 + +#define COMM_PS 0x4000 +#define COMM_PST 0x4000 +#define COMM_CIB 0x4000 +#define COMM_RTS 0x4000 +#define COMM_DT 0x2000 +#define COMM_SPU 0x1000 +#define COMM_F 0x0800 +#define COMM_NTP 0x0400 +#define COMM_ICP 0x0200 +#define COMM_RST 0x0100 + +#define PULSE_PROG 0x01 +#define PULSE_SPUE 0x02 + +#define BRANCH_MAIN 0xCC +#define BRANCH_AUX 0x33 + +/* + * Duration of the strong pull-up pulse in milliseconds. + */ +#define PULLUP_PULSE_DURATION 750 + +/* Status flags */ +#define ST_SPUA 0x01 /* Strong Pull-up is active */ +#define ST_PRGA 0x02 /* 12V programming pulse is being generated */ +#define ST_12VP 0x04 /* external 12V programming voltage is present */ +#define ST_PMOD 0x08 /* DS2490 powered from USB and external sources */ +#define ST_HALT 0x10 /* DS2490 is currently halted */ +#define ST_IDLE 0x20 /* DS2490 is currently idle */ +#define ST_EPOF 0x80 + +#define SPEED_NORMAL 0x00 +#define SPEED_FLEXIBLE 0x01 +#define SPEED_OVERDRIVE 0x02 + +#define NUM_EP 4 +#define EP_CONTROL 0 +#define EP_STATUS 1 +#define EP_DATA_OUT 2 +#define EP_DATA_IN 3 + +struct ds_device +{ + struct list_head ds_entry; + + struct usb_device *udev; + struct usb_interface *intf; + + int ep[NUM_EP]; + + struct w1_bus_master master; +}; + +struct ds_status +{ + u8 enable; + u8 speed; + u8 pullup_dur; + u8 ppuls_dur; + u8 pulldown_slew; + u8 write1_time; + u8 write0_time; + u8 reserved0; + u8 status; + u8 command0; + u8 command1; + u8 command_buffer_status; + u8 data_out_buffer_status; + u8 data_in_buffer_status; + u8 reserved1; + u8 reserved2; + +}; + +static struct usb_device_id ds_id_table [] = { + { USB_DEVICE(0x04fa, 0x2490) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, ds_id_table); + +static int ds_probe(struct usb_interface *, const struct usb_device_id *); +static void ds_disconnect(struct usb_interface *); + +static inline void ds_dump_status(unsigned char *, unsigned char *, int); +static int ds_send_control(struct ds_device *, u16, u16); +static int ds_send_control_cmd(struct ds_device *, u16, u16); + +static LIST_HEAD(ds_devices); +static DEFINE_MUTEX(ds_mutex); + +static struct usb_driver ds_driver = { + .name = "DS9490R", + .probe = ds_probe, + .disconnect = ds_disconnect, + .id_table = ds_id_table, +}; + +static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index) +{ + int err; + + err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), + CONTROL_CMD, 0x40, value, index, NULL, 0, 1000); + if (err < 0) { + printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n", + value, index, err); + return err; + } + + return err; +} +#if 0 +static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index) +{ + int err; + + err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), + MODE_CMD, 0x40, value, index, NULL, 0, 1000); + if (err < 0) { + printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n", + value, index, err); + return err; + } + + return err; +} +#endif +static int ds_send_control(struct ds_device *dev, u16 value, u16 index) +{ + int err; + + err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), + COMM_CMD, 0x40, value, index, NULL, 0, 1000); + if (err < 0) { + printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n", + value, index, err); + return err; + } + + return err; +} + +static inline void ds_dump_status(unsigned char *buf, unsigned char *str, int off) +{ + printk("%45s: %8x\n", str, buf[off]); +} + +static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, + unsigned char *buf, int size) +{ + int count, err; + + memset(st, 0, sizeof(st)); + + count = 0; + err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100); + if (err < 0) { + printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err); + return err; + } + + if (count >= sizeof(*st)) + memcpy(st, buf, sizeof(*st)); + + return count; +} + +static int ds_recv_status(struct ds_device *dev, struct ds_status *st) +{ + unsigned char buf[64]; + int count, err = 0, i; + + memcpy(st, buf, sizeof(*st)); + + count = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); + if (count < 0) + return err; + + printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], count); + for (i=0; i<count; ++i) + printk("%02x ", buf[i]); + printk("\n"); + + if (count >= 16) { + ds_dump_status(buf, "enable flag", 0); + ds_dump_status(buf, "1-wire speed", 1); + ds_dump_status(buf, "strong pullup duration", 2); + ds_dump_status(buf, "programming pulse duration", 3); + ds_dump_status(buf, "pulldown slew rate control", 4); + ds_dump_status(buf, "write-1 low time", 5); + ds_dump_status(buf, "data sample offset/write-0 recovery time", 6); + ds_dump_status(buf, "reserved (test register)", 7); + ds_dump_status(buf, "device status flags", 8); + ds_dump_status(buf, "communication command byte 1", 9); + ds_dump_status(buf, "communication command byte 2", 10); + ds_dump_status(buf, "communication command buffer status", 11); + ds_dump_status(buf, "1-wire data output buffer status", 12); + ds_dump_status(buf, "1-wire data input buffer status", 13); + ds_dump_status(buf, "reserved", 14); + ds_dump_status(buf, "reserved", 15); + } + + memcpy(st, buf, sizeof(*st)); + + if (st->status & ST_EPOF) { + printk(KERN_INFO "Resetting device after ST_EPOF.\n"); + err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); + if (err) + return err; + count = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); + if (count < 0) + return err; + } +#if 0 + if (st->status & ST_IDLE) { + printk(KERN_INFO "Resetting pulse after ST_IDLE.\n"); + err = ds_start_pulse(dev, PULLUP_PULSE_DURATION); + if (err) + return err; + } +#endif + + return err; +} + +static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) +{ + int count, err; + struct ds_status st; + + count = 0; + err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), + buf, size, &count, 1000); + if (err < 0) { + printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); + usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN])); + ds_recv_status(dev, &st); + return err; + } + +#if 0 + { + int i; + + printk("%s: count=%d: ", __func__, count); + for (i=0; i<count; ++i) + printk("%02x ", buf[i]); + printk("\n"); + } +#endif + return count; +} + +static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len) +{ + int count, err; + + count = 0; + err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000); + if (err < 0) { + printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err); + return err; + } + + return err; +} + +#if 0 + +int ds_stop_pulse(struct ds_device *dev, int limit) +{ + struct ds_status st; + int count = 0, err = 0; + u8 buf[0x20]; + + do { + err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0); + if (err) + break; + err = ds_send_control(dev, CTL_RESUME_EXE, 0); + if (err) + break; + err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); + if (err) + break; + + if ((st.status & ST_SPUA) == 0) { + err = ds_send_control_mode(dev, MOD_PULSE_EN, 0); + if (err) + break; + } + } while(++count < limit); + + return err; +} + +int ds_detect(struct ds_device *dev, struct ds_status *st) +{ + int err; + + err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); + if (err) + return err; + + err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0); + if (err) + return err; + + err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40); + if (err) + return err; + + err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG); + if (err) + return err; + + err = ds_recv_status(dev, st); + + return err; +} + +#endif /* 0 */ + +static int ds_wait_status(struct ds_device *dev, struct ds_status *st) +{ + u8 buf[0x20]; + int err, count = 0; + + do { + err = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); +#if 0 + if (err >= 0) { + int i; + printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err); + for (i=0; i<err; ++i) + printk("%02x ", buf[i]); + printk("\n"); + } +#endif + } while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100); + + + if (((err > 16) && (buf[0x10] & 0x01)) || count >= 100 || err < 0) { + ds_recv_status(dev, st); + return -1; + } else + return 0; +} + +static int ds_reset(struct ds_device *dev, struct ds_status *st) +{ + int err; + + //err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE); + err = ds_send_control(dev, 0x43, SPEED_NORMAL); + if (err) + return err; + + ds_wait_status(dev, st); +#if 0 + if (st->command_buffer_status) { + printk(KERN_INFO "Short circuit.\n"); + return -EIO; + } +#endif + + return 0; +} + +#if 0 +static int ds_set_speed(struct ds_device *dev, int speed) +{ + int err; + + if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE) + return -EINVAL; + + if (speed != SPEED_OVERDRIVE) + speed = SPEED_FLEXIBLE; + + speed &= 0xff; + + err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed); + if (err) + return err; + + return err; +} +#endif /* 0 */ + +static int ds_start_pulse(struct ds_device *dev, int delay) +{ + int err; + u8 del = 1 + (u8)(delay >> 4); + struct ds_status st; + +#if 0 + err = ds_stop_pulse(dev, 10); + if (err) + return err; + + err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE); + if (err) + return err; +#endif + err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del); + if (err) + return err; + + err = ds_send_control(dev, COMM_PULSE | COMM_IM | COMM_F, 0); + if (err) + return err; + + mdelay(delay); + + ds_wait_status(dev, &st); + + return err; +} + +static int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit) +{ + int err, count; + struct ds_status st; + u16 value = (COMM_BIT_IO | COMM_IM) | ((bit) ? COMM_D : 0); + u16 cmd; + + err = ds_send_control(dev, value, 0); + if (err) + return err; + + count = 0; + do { + err = ds_wait_status(dev, &st); + if (err) + return err; + + cmd = st.command0 | (st.command1 << 8); + } while (cmd != value && ++count < 10); + + if (err < 0 || count >= 10) { + printk(KERN_ERR "Failed to obtain status.\n"); + return -EINVAL; + } + + err = ds_recv_data(dev, tbit, sizeof(*tbit)); + if (err < 0) + return err; + + return 0; +} + +static int ds_write_bit(struct ds_device *dev, u8 bit) +{ + int err; + struct ds_status st; + + err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit) ? COMM_D : 0, 0); + if (err) + return err; + + ds_wait_status(dev, &st); + + return 0; +} + +static int ds_write_byte(struct ds_device *dev, u8 byte) +{ + int err; + struct ds_status st; + u8 rbyte; + + err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte); + if (err) + return err; + + err = ds_wait_status(dev, &st); + if (err) + return err; + + err = ds_recv_data(dev, &rbyte, sizeof(rbyte)); + if (err < 0) + return err; + + ds_start_pulse(dev, PULLUP_PULSE_DURATION); + + return !(byte == rbyte); +} + +static int ds_read_byte(struct ds_device *dev, u8 *byte) +{ + int err; + struct ds_status st; + + err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM , 0xff); + if (err) + return err; + + ds_wait_status(dev, &st); + + err = ds_recv_data(dev, byte, sizeof(*byte)); + if (err < 0) + return err; + + return 0; +} + +static int ds_read_block(struct ds_device *dev, u8 *buf, int len) +{ + struct ds_status st; + int err; + + if (len > 64*1024) + return -E2BIG; + + memset(buf, 0xFF, len); + + err = ds_send_data(dev, buf, len); + if (err < 0) + return err; + + err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len); + if (err) + return err; + + ds_wait_status(dev, &st); + + memset(buf, 0x00, len); + err = ds_recv_data(dev, buf, len); + + return err; +} + +static int ds_write_block(struct ds_device *dev, u8 *buf, int len) +{ + int err; + struct ds_status st; + + err = ds_send_data(dev, buf, len); + if (err < 0) + return err; + + ds_wait_status(dev, &st); + + err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len); + if (err) + return err; + + ds_wait_status(dev, &st); + + err = ds_recv_data(dev, buf, len); + if (err < 0) + return err; + + ds_start_pulse(dev, PULLUP_PULSE_DURATION); + + return !(err == len); +} + +#if 0 + +static int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search) +{ + int err; + u16 value, index; + struct ds_status st; + + memset(buf, 0, sizeof(buf)); + + err = ds_send_data(ds_dev, (unsigned char *)&init, 8); + if (err) + return err; + + ds_wait_status(ds_dev, &st); + + value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS; + index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8); + err = ds_send_control(ds_dev, value, index); + if (err) + return err; + + ds_wait_status(ds_dev, &st); + + err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number); + if (err < 0) + return err; + + return err/8; +} + +static int ds_match_access(struct ds_device *dev, u64 init) +{ + int err; + struct ds_status st; + + err = ds_send_data(dev, (unsigned char *)&init, sizeof(init)); + if (err) + return err; + + ds_wait_status(dev, &st); + + err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055); + if (err) + return err; + + ds_wait_status(dev, &st); + + return 0; +} + +static int ds_set_path(struct ds_device *dev, u64 init) +{ + int err; + struct ds_status st; + u8 buf[9]; + + memcpy(buf, &init, 8); + buf[8] = BRANCH_MAIN; + + err = ds_send_data(dev, buf, sizeof(buf)); + if (err) + return err; + + ds_wait_status(dev, &st); + + err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0); + if (err) + return err; + + ds_wait_status(dev, &st); + + return 0; +} + +#endif /* 0 */ + +static u8 ds9490r_touch_bit(void *data, u8 bit) +{ + u8 ret; + struct ds_device *dev = data; + + if (ds_touch_bit(dev, bit, &ret)) + return 0; + + return ret; +} + +static void ds9490r_write_bit(void *data, u8 bit) +{ + struct ds_device *dev = data; + + ds_write_bit(dev, bit); +} + +static void ds9490r_write_byte(void *data, u8 byte) +{ + struct ds_device *dev = data; + + ds_write_byte(dev, byte); +} + +static u8 ds9490r_read_bit(void *data) +{ + struct ds_device *dev = data; + int err; + u8 bit = 0; + + err = ds_touch_bit(dev, 1, &bit); + if (err) + return 0; + + return bit & 1; +} + +static u8 ds9490r_read_byte(void *data) +{ + struct ds_device *dev = data; + int err; + u8 byte = 0; + + err = ds_read_byte(dev, &byte); + if (err) + return 0; + + return byte; +} + +static void ds9490r_write_block(void *data, const u8 *buf, int len) +{ + struct ds_device *dev = data; + + ds_write_block(dev, (u8 *)buf, len); +} + +static u8 ds9490r_read_block(void *data, u8 *buf, int len) +{ + struct ds_device *dev = data; + int err; + + err = ds_read_block(dev, buf, len); + if (err < 0) + return 0; + + return len; +} + +static u8 ds9490r_reset(void *data) +{ + struct ds_device *dev = data; + struct ds_status st; + int err; + + memset(&st, 0, sizeof(st)); + + err = ds_reset(dev, &st); + if (err) + return 1; + + return 0; +} + +static int ds_w1_init(struct ds_device *dev) +{ + memset(&dev->master, 0, sizeof(struct w1_bus_master)); + + dev->master.data = dev; + dev->master.touch_bit = &ds9490r_touch_bit; + dev->master.read_bit = &ds9490r_read_bit; + dev->master.write_bit = &ds9490r_write_bit; + dev->master.read_byte = &ds9490r_read_byte; + dev->master.write_byte = &ds9490r_write_byte; + dev->master.read_block = &ds9490r_read_block; + dev->master.write_block = &ds9490r_write_block; + dev->master.reset_bus = &ds9490r_reset; + + return w1_add_master_device(&dev->master); +} + +static void ds_w1_fini(struct ds_device *dev) +{ + w1_remove_master_device(&dev->master); +} + +static int ds_probe(struct usb_interface *intf, + const struct usb_device_id *udev_id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct usb_endpoint_descriptor *endpoint; + struct usb_host_interface *iface_desc; + struct ds_device *dev; + int i, err; + + dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL); + if (!dev) { + printk(KERN_INFO "Failed to allocate new DS9490R structure.\n"); + return -ENOMEM; + } + dev->udev = usb_get_dev(udev); + if (!dev->udev) { + err = -ENOMEM; + goto err_out_free; + } + memset(dev->ep, 0, sizeof(dev->ep)); + + usb_set_intfdata(intf, dev); + + err = usb_set_interface(dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3); + if (err) { + printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n", + intf->altsetting[0].desc.bInterfaceNumber, err); + goto err_out_clear; + } + + err = usb_reset_configuration(dev->udev); + if (err) { + printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err); + goto err_out_clear; + } + + iface_desc = &intf->altsetting[0]; + if (iface_desc->desc.bNumEndpoints != NUM_EP-1) { + printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints); + err = -EINVAL; + goto err_out_clear; + } + + /* + * This loop doesn'd show control 0 endpoint, + * so we will fill only 1-3 endpoints entry. + */ + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + dev->ep[i+1] = endpoint->bEndpointAddress; +#if 0 + printk("%d: addr=%x, size=%d, dir=%s, type=%x\n", + i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize), + (endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT", + endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); +#endif + } + + err = ds_w1_init(dev); + if (err) + goto err_out_clear; + + mutex_lock(&ds_mutex); + list_add_tail(&dev->ds_entry, &ds_devices); + mutex_unlock(&ds_mutex); + + return 0; + +err_out_clear: + usb_set_intfdata(intf, NULL); + usb_put_dev(dev->udev); +err_out_free: + kfree(dev); + return err; +} + +static void ds_disconnect(struct usb_interface *intf) +{ + struct ds_device *dev; + + dev = usb_get_intfdata(intf); + if (!dev) + return; + + mutex_lock(&ds_mutex); + list_del(&dev->ds_entry); + mutex_unlock(&ds_mutex); + + ds_w1_fini(dev); + + usb_set_intfdata(intf, NULL); + + usb_put_dev(dev->udev); + kfree(dev); +} + +static int ds_init(void) +{ + int err; + + err = usb_register(&ds_driver); + if (err) { + printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err); + return err; + } + + return 0; +} + +static void ds_fini(void) +{ + usb_deregister(&ds_driver); +} + +module_init(ds_init); +module_exit(ds_fini); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); +MODULE_DESCRIPTION("DS2490 USB <-> W1 bus master driver (DS9490*)"); diff --git a/drivers/xen/blktap/blktapmain.c b/drivers/xen/blktap/blktapmain.c new file mode 100644 index 000000000..15b368b9e --- /dev/null +++ b/drivers/xen/blktap/blktapmain.c @@ -0,0 +1,1393 @@ +/****************************************************************************** + * drivers/xen/blktap/blktap.c + * + * Back-end driver for user level virtual block devices. This portion of the + * driver exports a 'unified' block-device interface that can be accessed + * by any operating system that implements a compatible front end. Requests + * are remapped to a user-space memory region. + * + * Based on the blkback driver code. + * + * Copyright (c) 2004-2005, Andrew Warfield and Julian Chesterfield + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <linux/spinlock.h> +#include <linux/kthread.h> +#include <linux/list.h> +#include <asm/hypervisor.h> +#include "common.h" +#include <xen/balloon.h> +#include <linux/kernel.h> +#include <linux/fs.h> +#include <linux/mm.h> +#include <linux/errno.h> +#include <linux/major.h> +#include <linux/gfp.h> +#include <linux/poll.h> +#include <asm/tlbflush.h> + +#define MAX_TAP_DEV 100 /*the maximum number of tapdisk ring devices */ +#define MAX_DEV_NAME 100 /*the max tapdisk ring device name e.g. blktap0 */ + + +struct class *xen_class; +EXPORT_SYMBOL_GPL(xen_class); + +/* + * Setup the xen class. This should probably go in another file, but + * since blktap is the only user of it so far, it gets to keep it. + */ +int setup_xen_class(void) +{ + int ret; + + if (xen_class) + return 0; + + xen_class = class_create(THIS_MODULE, "xen"); + if ((ret = IS_ERR(xen_class))) { + xen_class = NULL; + return ret; + } + + return 0; +} + +/* + * The maximum number of requests that can be outstanding at any time + * is determined by + * + * [mmap_alloc * MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST] + * + * where mmap_alloc < MAX_DYNAMIC_MEM. + * + * TODO: + * mmap_alloc is initialised to 2 and should be adjustable on the fly via + * sysfs. + */ +#define MAX_DYNAMIC_MEM 64 +#define MAX_PENDING_REQS 64 +#define MMAP_PAGES (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST) +#define MMAP_VADDR(_start, _req,_seg) \ + (_start + \ + ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) + \ + ((_seg) * PAGE_SIZE)) +static int blkif_reqs = MAX_PENDING_REQS; +static int mmap_pages = MMAP_PAGES; + +#define RING_PAGES 1 /* BLKTAP - immediately before the mmap area, we + * have a bunch of pages reserved for shared + * memory rings. + */ + +/*Data struct associated with each of the tapdisk devices*/ +typedef struct tap_blkif { + struct vm_area_struct *vma; /*Shared memory area */ + unsigned long rings_vstart; /*Kernel memory mapping */ + unsigned long user_vstart; /*User memory mapping */ + unsigned long dev_inuse; /*One process opens device at a time. */ + unsigned long dev_pending; /*In process of being opened */ + unsigned long ring_ok; /*make this ring->state */ + blkif_front_ring_t ufe_ring; /*Rings up to user space. */ + wait_queue_head_t wait; /*for poll */ + unsigned long mode; /*current switching mode */ + int minor; /*Minor number for tapdisk device */ + pid_t pid; /*tapdisk process id */ + enum { RUNNING, CLEANSHUTDOWN } status; /*Detect a clean userspace + shutdown */ + unsigned long *idx_map; /*Record the user ring id to kern + [req id, idx] tuple */ + blkif_t *blkif; /*Associate blkif with tapdev */ + int sysfs_set; /*Set if it has a class device. */ +} tap_blkif_t; + +/*Data struct handed back to userspace for tapdisk device to VBD mapping*/ +typedef struct domid_translate { + unsigned short domid; + unsigned short busid; +} domid_translate_t ; + +static domid_translate_t translate_domid[MAX_TAP_DEV]; +static tap_blkif_t *tapfds[MAX_TAP_DEV]; + +static int __init set_blkif_reqs(char *str) +{ + get_option(&str, &blkif_reqs); + return 1; +} +__setup("blkif_reqs=", set_blkif_reqs); + +/* Run-time switchable: /sys/module/blktap/parameters/ */ +static unsigned int log_stats = 0; +static unsigned int debug_lvl = 0; +module_param(log_stats, int, 0644); +module_param(debug_lvl, int, 0644); + +/* + * Each outstanding request that we've passed to the lower device layers has a + * 'pending_req' allocated to it. Each buffer_head that completes decrements + * the pendcnt towards zero. When it hits zero, the specified domain has a + * response queued for it, with the saved 'id' passed back. + */ +typedef struct { + blkif_t *blkif; + unsigned long id; + unsigned short mem_idx; + int nr_pages; + atomic_t pendcnt; + unsigned short operation; + int status; + struct list_head free_list; + int inuse; +} pending_req_t; + +static pending_req_t *pending_reqs[MAX_PENDING_REQS]; +static struct list_head pending_free; +static DEFINE_SPINLOCK(pending_free_lock); +static DECLARE_WAIT_QUEUE_HEAD (pending_free_wq); +static int alloc_pending_reqs; + +typedef unsigned int PEND_RING_IDX; + +static inline int MASK_PEND_IDX(int i) { + return (i & (MAX_PENDING_REQS-1)); +} + +static inline unsigned int RTN_PEND_IDX(pending_req_t *req, int idx) { + return (req - pending_reqs[idx]); +} + +#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons) + +#define BLKBACK_INVALID_HANDLE (~0) + +static struct page **foreign_pages[MAX_DYNAMIC_MEM]; +static inline unsigned long idx_to_kaddr( + unsigned int mmap_idx, unsigned int req_idx, unsigned int sg_idx) +{ + unsigned int arr_idx = req_idx*BLKIF_MAX_SEGMENTS_PER_REQUEST + sg_idx; + unsigned long pfn = page_to_pfn(foreign_pages[mmap_idx][arr_idx]); + return (unsigned long)pfn_to_kaddr(pfn); +} + +static unsigned short mmap_alloc = 0; +static unsigned short mmap_lock = 0; +static unsigned short mmap_inuse = 0; + +/****************************************************************** + * GRANT HANDLES + */ + +/* When using grant tables to map a frame for device access then the + * handle returned must be used to unmap the frame. This is needed to + * drop the ref count on the frame. + */ +struct grant_handle_pair +{ + grant_handle_t kernel; + grant_handle_t user; +}; + +static struct grant_handle_pair + pending_grant_handles[MAX_DYNAMIC_MEM][MMAP_PAGES]; +#define pending_handle(_id, _idx, _i) \ + (pending_grant_handles[_id][((_idx) * BLKIF_MAX_SEGMENTS_PER_REQUEST) \ + + (_i)]) + + +static int blktap_read_ufe_ring(tap_blkif_t *info); /*local prototypes*/ + +#define BLKTAP_MINOR 0 /*/dev/xen/blktap has a dynamic major */ +#define BLKTAP_DEV_DIR "/dev/xen" + +static int blktap_major; + +/* blktap IOCTLs: */ +#define BLKTAP_IOCTL_KICK_FE 1 +#define BLKTAP_IOCTL_KICK_BE 2 /* currently unused */ +#define BLKTAP_IOCTL_SETMODE 3 +#define BLKTAP_IOCTL_SENDPID 4 +#define BLKTAP_IOCTL_NEWINTF 5 +#define BLKTAP_IOCTL_MINOR 6 +#define BLKTAP_IOCTL_MAJOR 7 +#define BLKTAP_QUERY_ALLOC_REQS 8 +#define BLKTAP_IOCTL_FREEINTF 9 +#define BLKTAP_IOCTL_PRINT_IDXS 100 + +/* blktap switching modes: (Set with BLKTAP_IOCTL_SETMODE) */ +#define BLKTAP_MODE_PASSTHROUGH 0x00000000 /* default */ +#define BLKTAP_MODE_INTERCEPT_FE 0x00000001 +#define BLKTAP_MODE_INTERCEPT_BE 0x00000002 /* unimp. */ + +#define BLKTAP_MODE_INTERPOSE \ + (BLKTAP_MODE_INTERCEPT_FE | BLKTAP_MODE_INTERCEPT_BE) + + +static inline int BLKTAP_MODE_VALID(unsigned long arg) +{ + return ((arg == BLKTAP_MODE_PASSTHROUGH ) || + (arg == BLKTAP_MODE_INTERCEPT_FE) || + (arg == BLKTAP_MODE_INTERPOSE )); +} + +/* Requests passing through the tap to userspace are re-assigned an ID. + * We must record a mapping between the BE [IDX,ID] tuple and the userspace + * ring ID. + */ + +static inline unsigned long MAKE_ID(domid_t fe_dom, PEND_RING_IDX idx) +{ + return ((fe_dom << 16) | MASK_PEND_IDX(idx)); +} + +extern inline PEND_RING_IDX ID_TO_IDX(unsigned long id) +{ + return (PEND_RING_IDX)(id & 0x0000ffff); +} + +extern inline int ID_TO_MIDX(unsigned long id) +{ + return (int)(id >> 16); +} + +#define INVALID_REQ 0xdead0000 + +/*TODO: Convert to a free list*/ +static inline int GET_NEXT_REQ(unsigned long *idx_map) +{ + int i; + for (i = 0; i < MAX_PENDING_REQS; i++) + if (idx_map[i] == INVALID_REQ) + return i; + + return INVALID_REQ; +} + + +#define BLKTAP_INVALID_HANDLE(_g) \ + (((_g->kernel) == 0xFFFF) && ((_g->user) == 0xFFFF)) + +#define BLKTAP_INVALIDATE_HANDLE(_g) do { \ + (_g)->kernel = 0xFFFF; (_g)->user = 0xFFFF; \ + } while(0) + + +/****************************************************************** + * BLKTAP VM OPS + */ + +static struct page *blktap_nopage(struct vm_area_struct *vma, + unsigned long address, + int *type) +{ + /* + * if the page has not been mapped in by the driver then return + * NOPAGE_SIGBUS to the domain. + */ + + return NOPAGE_SIGBUS; +} + +struct vm_operations_struct blktap_vm_ops = { + nopage: blktap_nopage, +}; + +/****************************************************************** + * BLKTAP FILE OPS + */ + +/*Function Declarations*/ +static int get_next_free_dev(void); +static int blktap_open(struct inode *inode, struct file *filp); +static int blktap_release(struct inode *inode, struct file *filp); +static int blktap_mmap(struct file *filp, struct vm_area_struct *vma); +static int blktap_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); +static unsigned int blktap_poll(struct file *file, poll_table *wait); + +static struct file_operations blktap_fops = { + .owner = THIS_MODULE, + .poll = blktap_poll, + .ioctl = blktap_ioctl, + .open = blktap_open, + .release = blktap_release, + .mmap = blktap_mmap, +}; + + +static int get_next_free_dev(void) +{ + tap_blkif_t *info; + int i = 0, ret = -1; + unsigned long flags; + + spin_lock_irqsave(&pending_free_lock, flags); + + while (i < MAX_TAP_DEV) { + info = tapfds[i]; + if ( (tapfds[i] != NULL) && (info->dev_inuse == 0) + && (info->dev_pending == 0) ) { + info->dev_pending = 1; + ret = i; + goto done; + } + i++; + } + +done: + spin_unlock_irqrestore(&pending_free_lock, flags); + + /* + * We are protected by having the dev_pending set. + */ + if (!tapfds[i]->sysfs_set && xen_class) { + class_device_create(xen_class, NULL, + MKDEV(blktap_major, ret), NULL, + "blktap%d", ret); + tapfds[i]->sysfs_set = 1; + } + return ret; +} + +int dom_to_devid(domid_t domid, int xenbus_id, blkif_t *blkif) +{ + int i; + + for (i = 0; i < MAX_TAP_DEV; i++) + if ( (translate_domid[i].domid == domid) + && (translate_domid[i].busid == xenbus_id) ) { + tapfds[i]->blkif = blkif; + tapfds[i]->status = RUNNING; + return i; + } + return -1; +} + +void signal_tapdisk(int idx) +{ + tap_blkif_t *info; + struct task_struct *ptask; + + info = tapfds[idx]; + if ( (idx > 0) && (idx < MAX_TAP_DEV) && (info->pid > 0) ) { + ptask = find_task_by_pid(info->pid); + if (ptask) + info->status = CLEANSHUTDOWN; + } + info->blkif = NULL; + return; +} + +static int blktap_open(struct inode *inode, struct file *filp) +{ + blkif_sring_t *sring; + int idx = iminor(inode) - BLKTAP_MINOR; + tap_blkif_t *info; + int i; + + if (tapfds[idx] == NULL) { + WPRINTK("Unable to open device /dev/xen/blktap%d\n", + idx); + return -ENOMEM; + } + DPRINTK("Opening device /dev/xen/blktap%d\n",idx); + + info = tapfds[idx]; + + /*Only one process can access device at a time*/ + if (test_and_set_bit(0, &info->dev_inuse)) + return -EBUSY; + + info->dev_pending = 0; + + /* Allocate the fe ring. */ + sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL); + if (sring == NULL) + goto fail_nomem; + + SetPageReserved(virt_to_page(sring)); + + SHARED_RING_INIT(sring); + FRONT_RING_INIT(&info->ufe_ring, sring, PAGE_SIZE); + + filp->private_data = info; + info->vma = NULL; + + info->idx_map = kmalloc(sizeof(unsigned long) * MAX_PENDING_REQS, + GFP_KERNEL); + + if (idx > 0) { + init_waitqueue_head(&info->wait); + for (i = 0; i < MAX_PENDING_REQS; i++) + info->idx_map[i] = INVALID_REQ; + } + + DPRINTK("Tap open: device /dev/xen/blktap%d\n",idx); + return 0; + + fail_nomem: + return -ENOMEM; +} + +static int blktap_release(struct inode *inode, struct file *filp) +{ + tap_blkif_t *info = filp->private_data; + + /* can this ever happen? - sdr */ + if (!info) { + WPRINTK("Trying to free device that doesn't exist " + "[/dev/xen/blktap%d]\n",iminor(inode) - BLKTAP_MINOR); + return -EBADF; + } + info->dev_inuse = 0; + DPRINTK("Freeing device [/dev/xen/blktap%d]\n",info->minor); + + /* Free the ring page. */ + ClearPageReserved(virt_to_page(info->ufe_ring.sring)); + free_page((unsigned long) info->ufe_ring.sring); + + /* Clear any active mappings and free foreign map table */ + if (info->vma) { + zap_page_range( + info->vma, info->vma->vm_start, + info->vma->vm_end - info->vma->vm_start, NULL); + info->vma = NULL; + } + + if ( (info->status != CLEANSHUTDOWN) && (info->blkif != NULL) ) { + kthread_stop(info->blkif->xenblkd); + info->blkif->xenblkd = NULL; + info->status = CLEANSHUTDOWN; + } + return 0; +} + + +/* Note on mmap: + * We need to map pages to user space in a way that will allow the block + * subsystem set up direct IO to them. This couldn't be done before, because + * there isn't really a sane way to translate a user virtual address down to a + * physical address when the page belongs to another domain. + * + * My first approach was to map the page in to kernel memory, add an entry + * for it in the physical frame list (using alloc_lomem_region as in blkback) + * and then attempt to map that page up to user space. This is disallowed + * by xen though, which realizes that we don't really own the machine frame + * underlying the physical page. + * + * The new approach is to provide explicit support for this in xen linux. + * The VMA now has a flag, VM_FOREIGN, to indicate that it contains pages + * mapped from other vms. vma->vm_private_data is set up as a mapping + * from pages to actual page structs. There is a new clause in get_user_pages + * that does the right thing for this sort of mapping. + */ +static int blktap_mmap(struct file *filp, struct vm_area_struct *vma) +{ + int size; + struct page **map; + int i; + tap_blkif_t *info = filp->private_data; + + if (info == NULL) { + WPRINTK("blktap: mmap, retrieving idx failed\n"); + return -ENOMEM; + } + + vma->vm_flags |= VM_RESERVED; + vma->vm_ops = &blktap_vm_ops; + + size = vma->vm_end - vma->vm_start; + if (size != ((mmap_pages + RING_PAGES) << PAGE_SHIFT)) { + WPRINTK("you _must_ map exactly %d pages!\n", + mmap_pages + RING_PAGES); + return -EAGAIN; + } + + size >>= PAGE_SHIFT; + info->rings_vstart = vma->vm_start; + info->user_vstart = info->rings_vstart + (RING_PAGES << PAGE_SHIFT); + + /* Map the ring pages to the start of the region and reserve it. */ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + if (remap_pfn_range(vma, vma->vm_start, + __pa(info->ufe_ring.sring) >> PAGE_SHIFT, + PAGE_SIZE, vma->vm_page_prot)) { + WPRINTK("Mapping user ring failed!\n"); + goto fail; + } + + /* Mark this VM as containing foreign pages, and set up mappings. */ + map = kzalloc(((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) + * sizeof(struct page_struct*), + GFP_KERNEL); + if (map == NULL) { + WPRINTK("Couldn't alloc VM_FOREIGN map.\n"); + goto fail; + } + + for (i = 0; i < ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT); i++) + map[i] = NULL; + + vma->vm_private_data = map; + vma->vm_flags |= VM_FOREIGN; + + info->vma = vma; + info->ring_ok = 1; + return 0; + fail: + /* Clear any active mappings. */ + zap_page_range(vma, vma->vm_start, + vma->vm_end - vma->vm_start, NULL); + + return -ENOMEM; +} + + +static int blktap_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + tap_blkif_t *info = filp->private_data; + + switch(cmd) { + case BLKTAP_IOCTL_KICK_FE: + { + /* There are fe messages to process. */ + return blktap_read_ufe_ring(info); + } + case BLKTAP_IOCTL_SETMODE: + { + if (info) { + if (BLKTAP_MODE_VALID(arg)) { + info->mode = arg; + /* XXX: may need to flush rings here. */ + DPRINTK("blktap: set mode to %lx\n", + arg); + return 0; + } + } + return 0; + } + case BLKTAP_IOCTL_PRINT_IDXS: + { + if (info) { + printk("User Rings: \n-----------\n"); + printk("UF: rsp_cons: %2d, req_prod_prv: %2d " + "| req_prod: %2d, rsp_prod: %2d\n", + info->ufe_ring.rsp_cons, + info->ufe_ring.req_prod_pvt, + info->ufe_ring.sring->req_prod, + info->ufe_ring.sring->rsp_prod); + } + return 0; + } + case BLKTAP_IOCTL_SENDPID: + { + if (info) { + info->pid = (pid_t)arg; + DPRINTK("blktap: pid received %d\n", + info->pid); + } + return 0; + } + case BLKTAP_IOCTL_NEWINTF: + { + uint64_t val = (uint64_t)arg; + domid_translate_t *tr = (domid_translate_t *)&val; + int newdev; + + DPRINTK("NEWINTF Req for domid %d and bus id %d\n", + tr->domid, tr->busid); + newdev = get_next_free_dev(); + if (newdev < 1) { + WPRINTK("Error initialising /dev/xen/blktap - " + "No more devices\n"); + return -1; + } + translate_domid[newdev].domid = tr->domid; + translate_domid[newdev].busid = tr->busid; + return newdev; + } + case BLKTAP_IOCTL_FREEINTF: + { + unsigned long dev = arg; + unsigned long flags; + + /* Looking at another device */ + info = NULL; + + if ( (dev > 0) && (dev < MAX_TAP_DEV) ) + info = tapfds[dev]; + + spin_lock_irqsave(&pending_free_lock, flags); + if ( (info != NULL) && (info->dev_pending) ) + info->dev_pending = 0; + spin_unlock_irqrestore(&pending_free_lock, flags); + + return 0; + } + case BLKTAP_IOCTL_MINOR: + { + unsigned long dev = arg; + + /* Looking at another device */ + info = NULL; + + if ( (dev > 0) && (dev < MAX_TAP_DEV) ) + info = tapfds[dev]; + + if (info != NULL) + return info->minor; + else + return -1; + } + case BLKTAP_IOCTL_MAJOR: + return blktap_major; + + case BLKTAP_QUERY_ALLOC_REQS: + { + WPRINTK("BLKTAP_QUERY_ALLOC_REQS ioctl: %d/%d\n", + alloc_pending_reqs, blkif_reqs); + return (alloc_pending_reqs/blkif_reqs) * 100; + } + } + return -ENOIOCTLCMD; +} + +static unsigned int blktap_poll(struct file *filp, poll_table *wait) +{ + tap_blkif_t *info = filp->private_data; + + if (!info) { + WPRINTK(" poll, retrieving idx failed\n"); + return 0; + } + + /* do not work on the control device */ + if (!info->minor) + return 0; + + poll_wait(filp, &info->wait, wait); + if (info->ufe_ring.req_prod_pvt != info->ufe_ring.sring->req_prod) { + RING_PUSH_REQUESTS(&info->ufe_ring); + return POLLIN | POLLRDNORM; + } + return 0; +} + +void blktap_kick_user(int idx) +{ + tap_blkif_t *info; + + if (idx == 0) + return; + + info = tapfds[idx]; + + if (info != NULL) + wake_up_interruptible(&info->wait); + + return; +} + +static int do_block_io_op(blkif_t *blkif); +static void dispatch_rw_block_io(blkif_t *blkif, + blkif_request_t *req, + pending_req_t *pending_req); +static void make_response(blkif_t *blkif, unsigned long id, + unsigned short op, int st); + +/****************************************************************** + * misc small helpers + */ +static int req_increase(void) +{ + int i, j; + + if (mmap_alloc >= MAX_PENDING_REQS || mmap_lock) + return -EINVAL; + + pending_reqs[mmap_alloc] = kzalloc(sizeof(pending_req_t) + * blkif_reqs, GFP_KERNEL); + foreign_pages[mmap_alloc] = alloc_empty_pages_and_pagevec(mmap_pages); + + if (!pending_reqs[mmap_alloc] || !foreign_pages[mmap_alloc]) + goto out_of_memory; + + DPRINTK("%s: reqs=%d, pages=%d\n", + __FUNCTION__, blkif_reqs, mmap_pages); + + for (i = 0; i < MAX_PENDING_REQS; i++) { + list_add_tail(&pending_reqs[mmap_alloc][i].free_list, + &pending_free); + pending_reqs[mmap_alloc][i].mem_idx = mmap_alloc; + for (j = 0; j < BLKIF_MAX_SEGMENTS_PER_REQUEST; j++) + BLKTAP_INVALIDATE_HANDLE(&pending_handle(mmap_alloc, + i, j)); + } + + mmap_alloc++; + DPRINTK("# MMAPs increased to %d\n",mmap_alloc); + return 0; + + out_of_memory: + free_empty_pages_and_pagevec(foreign_pages[mmap_alloc], mmap_pages); + kfree(pending_reqs[mmap_alloc]); + WPRINTK("%s: out of memory\n", __FUNCTION__); + return -ENOMEM; +} + +static void mmap_req_del(int mmap) +{ + BUG_ON(!spin_is_locked(&pending_free_lock)); + + kfree(pending_reqs[mmap]); + pending_reqs[mmap] = NULL; + + free_empty_pages_and_pagevec(foreign_pages[mmap_alloc], mmap_pages); + foreign_pages[mmap] = NULL; + + mmap_lock = 0; + DPRINTK("# MMAPs decreased to %d\n",mmap_alloc); + mmap_alloc--; +} + +static pending_req_t* alloc_req(void) +{ + pending_req_t *req = NULL; + unsigned long flags; + + spin_lock_irqsave(&pending_free_lock, flags); + + if (!list_empty(&pending_free)) { + req = list_entry(pending_free.next, pending_req_t, free_list); + list_del(&req->free_list); + } + + if (req) { + req->inuse = 1; + alloc_pending_reqs++; + } + spin_unlock_irqrestore(&pending_free_lock, flags); + + return req; +} + +static void free_req(pending_req_t *req) +{ + unsigned long flags; + int was_empty; + + spin_lock_irqsave(&pending_free_lock, flags); + + alloc_pending_reqs--; + req->inuse = 0; + if (mmap_lock && (req->mem_idx == mmap_alloc-1)) { + mmap_inuse--; + if (mmap_inuse == 0) mmap_req_del(mmap_alloc-1); + spin_unlock_irqrestore(&pending_free_lock, flags); + return; + } + was_empty = list_empty(&pending_free); + list_add(&req->free_list, &pending_free); + + spin_unlock_irqrestore(&pending_free_lock, flags); + + if (was_empty) + wake_up(&pending_free_wq); +} + +static void fast_flush_area(pending_req_t *req, int k_idx, int u_idx, int + tapidx) +{ + struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST*2]; + unsigned int i, invcount = 0; + struct grant_handle_pair *khandle; + uint64_t ptep; + int ret, mmap_idx; + unsigned long kvaddr, uvaddr; + + tap_blkif_t *info = tapfds[tapidx]; + + if (info == NULL) { + WPRINTK("fast_flush: Couldn't get info!\n"); + return; + } + mmap_idx = req->mem_idx; + + for (i = 0; i < req->nr_pages; i++) { + kvaddr = idx_to_kaddr(mmap_idx, k_idx, i); + uvaddr = MMAP_VADDR(info->user_vstart, u_idx, i); + + khandle = &pending_handle(mmap_idx, k_idx, i); + if (BLKTAP_INVALID_HANDLE(khandle)) { + WPRINTK("BLKTAP_INVALID_HANDLE\n"); + continue; + } + gnttab_set_unmap_op(&unmap[invcount], + idx_to_kaddr(mmap_idx, k_idx, i), + GNTMAP_host_map, khandle->kernel); + invcount++; + + if (create_lookup_pte_addr( + info->vma->vm_mm, + MMAP_VADDR(info->user_vstart, u_idx, i), + &ptep) !=0) { + WPRINTK("Couldn't get a pte addr!\n"); + return; + } + + gnttab_set_unmap_op(&unmap[invcount], + ptep, GNTMAP_host_map, + khandle->user); + invcount++; + + BLKTAP_INVALIDATE_HANDLE(khandle); + } + ret = HYPERVISOR_grant_table_op( + GNTTABOP_unmap_grant_ref, unmap, invcount); + BUG_ON(ret); + + if (info->vma != NULL) + zap_page_range(info->vma, + MMAP_VADDR(info->user_vstart, u_idx, 0), + req->nr_pages << PAGE_SHIFT, NULL); +} + +/****************************************************************** + * SCHEDULER FUNCTIONS + */ + +static void print_stats(blkif_t *blkif) +{ + printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d\n", + current->comm, blkif->st_oo_req, + blkif->st_rd_req, blkif->st_wr_req); + blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000); + blkif->st_rd_req = 0; + blkif->st_wr_req = 0; + blkif->st_oo_req = 0; +} + +int tap_blkif_schedule(void *arg) +{ + blkif_t *blkif = arg; + + blkif_get(blkif); + + if (debug_lvl) + printk(KERN_DEBUG "%s: started\n", current->comm); + + while (!kthread_should_stop()) { + wait_event_interruptible( + blkif->wq, + blkif->waiting_reqs || kthread_should_stop()); + wait_event_interruptible( + pending_free_wq, + !list_empty(&pending_free) || kthread_should_stop()); + + blkif->waiting_reqs = 0; + smp_mb(); /* clear flag *before* checking for work */ + + if (do_block_io_op(blkif)) + blkif->waiting_reqs = 1; + + if (log_stats && time_after(jiffies, blkif->st_print)) + print_stats(blkif); + } + + if (log_stats) + print_stats(blkif); + if (debug_lvl) + printk(KERN_DEBUG "%s: exiting\n", current->comm); + + blkif->xenblkd = NULL; + blkif_put(blkif); + + return 0; +} + +/****************************************************************** + * COMPLETION CALLBACK -- Called by user level ioctl() + */ + +static int blktap_read_ufe_ring(tap_blkif_t *info) +{ + /* This is called to read responses from the UFE ring. */ + RING_IDX i, j, rp; + blkif_response_t *resp; + blkif_t *blkif=NULL; + int pending_idx, usr_idx, mmap_idx; + pending_req_t *pending_req; + + if (!info) + return 0; + + /* We currently only forward packets in INTERCEPT_FE mode. */ + if (!(info->mode & BLKTAP_MODE_INTERCEPT_FE)) + return 0; + + /* for each outstanding message on the UFEring */ + rp = info->ufe_ring.sring->rsp_prod; + rmb(); + + for (i = info->ufe_ring.rsp_cons; i != rp; i++) { + resp = RING_GET_RESPONSE(&info->ufe_ring, i); + ++info->ufe_ring.rsp_cons; + + /*retrieve [usr_idx] to [mmap_idx,pending_idx] mapping*/ + usr_idx = (int)resp->id; + pending_idx = MASK_PEND_IDX(ID_TO_IDX(info->idx_map[usr_idx])); + mmap_idx = ID_TO_MIDX(info->idx_map[usr_idx]); + + if ( (mmap_idx >= mmap_alloc) || + (ID_TO_IDX(info->idx_map[usr_idx]) >= MAX_PENDING_REQS) ) + WPRINTK("Incorrect req map" + "[%d], internal map [%d,%d (%d)]\n", + usr_idx, mmap_idx, + ID_TO_IDX(info->idx_map[usr_idx]), + MASK_PEND_IDX( + ID_TO_IDX(info->idx_map[usr_idx]))); + + pending_req = &pending_reqs[mmap_idx][pending_idx]; + blkif = pending_req->blkif; + + for (j = 0; j < pending_req->nr_pages; j++) { + + unsigned long kvaddr, uvaddr; + struct page **map = info->vma->vm_private_data; + struct page *pg; + int offset; + + uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, j); + kvaddr = idx_to_kaddr(mmap_idx, pending_idx, j); + + pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT); + ClearPageReserved(pg); + offset = (uvaddr - info->vma->vm_start) + >> PAGE_SHIFT; + map[offset] = NULL; + } + fast_flush_area(pending_req, pending_idx, usr_idx, info->minor); + make_response(blkif, pending_req->id, resp->operation, + resp->status); + info->idx_map[usr_idx] = INVALID_REQ; + blkif_put(pending_req->blkif); + free_req(pending_req); + } + + return 0; +} + + +/****************************************************************************** + * NOTIFICATION FROM GUEST OS. + */ + +static void blkif_notify_work(blkif_t *blkif) +{ + blkif->waiting_reqs = 1; + wake_up(&blkif->wq); +} + +irqreturn_t tap_blkif_be_int(int irq, void *dev_id, struct pt_regs *regs) +{ + blkif_notify_work(dev_id); + return IRQ_HANDLED; +} + + + +/****************************************************************** + * DOWNWARD CALLS -- These interface with the block-device layer proper. + */ +static int print_dbug = 1; +static int do_block_io_op(blkif_t *blkif) +{ + blkif_back_ring_t *blk_ring = &blkif->blk_ring; + blkif_request_t *req; + pending_req_t *pending_req; + RING_IDX rc, rp; + int more_to_do = 0; + tap_blkif_t *info; + + rc = blk_ring->req_cons; + rp = blk_ring->sring->req_prod; + rmb(); /* Ensure we see queued requests up to 'rp'. */ + + /*Check blkif has corresponding UE ring*/ + if (blkif->dev_num == -1) { + /*oops*/ + if (print_dbug) { + WPRINTK("Corresponding UE " + "ring does not exist!\n"); + print_dbug = 0; /*We only print this message once*/ + } + return 0; + } + + info = tapfds[blkif->dev_num]; + if (info == NULL || !info->dev_inuse) { + if (print_dbug) { + WPRINTK("Can't get UE info!\n"); + print_dbug = 0; + } + return 0; + } + + while (rc != rp) { + + if (RING_FULL(&info->ufe_ring)) { + WPRINTK("RING_FULL! More to do\n"); + more_to_do = 1; + break; + } + + if (RING_REQUEST_CONS_OVERFLOW(blk_ring, rc)) { + WPRINTK("RING_REQUEST_CONS_OVERFLOW!" + " More to do\n"); + more_to_do = 1; + break; + } + + pending_req = alloc_req(); + if (NULL == pending_req) { + blkif->st_oo_req++; + more_to_do = 1; + break; + } + + req = RING_GET_REQUEST(blk_ring, rc); + blk_ring->req_cons = ++rc; /* before make_response() */ + + switch (req->operation) { + case BLKIF_OP_READ: + blkif->st_rd_req++; + dispatch_rw_block_io(blkif, req, pending_req); + break; + + case BLKIF_OP_WRITE: + blkif->st_wr_req++; + dispatch_rw_block_io(blkif, req, pending_req); + break; + + default: + WPRINTK("unknown operation [%d]\n", + req->operation); + make_response(blkif, req->id, req->operation, + BLKIF_RSP_ERROR); + free_req(pending_req); + break; + } + } + + blktap_kick_user(blkif->dev_num); + + return more_to_do; +} + +static void dispatch_rw_block_io(blkif_t *blkif, + blkif_request_t *req, + pending_req_t *pending_req) +{ + extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]); + int op, operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ; + struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST*2]; + unsigned int nseg; + int ret, i; + tap_blkif_t *info = tapfds[blkif->dev_num]; + uint64_t sector; + + blkif_request_t *target; + int pending_idx = RTN_PEND_IDX(pending_req,pending_req->mem_idx); + int usr_idx = GET_NEXT_REQ(info->idx_map); + uint16_t mmap_idx = pending_req->mem_idx; + + /*Check we have space on user ring - should never fail*/ + if(usr_idx == INVALID_REQ) goto fail_flush; + + /* Check that number of segments is sane. */ + nseg = req->nr_segments; + if ( unlikely(nseg == 0) || + unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST) ) { + WPRINTK("Bad number of segments in request (%d)\n", nseg); + goto fail_response; + } + + /* Make sure userspace is ready. */ + if (!info->ring_ok) { + WPRINTK("blktap: ring not ready for requests!\n"); + goto fail_response; + } + + if (RING_FULL(&info->ufe_ring)) { + WPRINTK("blktap: fe_ring is full, can't add " + "IO Request will be dropped. %d %d\n", + RING_SIZE(&info->ufe_ring), + RING_SIZE(&blkif->blk_ring)); + goto fail_response; + } + + pending_req->blkif = blkif; + pending_req->id = req->id; + pending_req->operation = operation; + pending_req->status = BLKIF_RSP_OKAY; + pending_req->nr_pages = nseg; + op = 0; + for (i = 0; i < nseg; i++) { + unsigned long uvaddr; + unsigned long kvaddr; + uint64_t ptep; + struct page *page; + uint32_t flags; + + uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i); + kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i); + page = virt_to_page(kvaddr); + + sector = req->sector_number + (8*i); + if( (blkif->sectors > 0) && (sector >= blkif->sectors) ) { + WPRINTK("BLKTAP: Sector request greater" + "than size\n"); + WPRINTK("BLKTAP: %s request sector" + "[%llu,%llu], Total [%llu]\n", + (req->operation == + BLKIF_OP_WRITE ? "WRITE" : "READ"), + (long long unsigned) sector, + (long long unsigned) sector>>9, + blkif->sectors); + } + + flags = GNTMAP_host_map; + if (operation == WRITE) + flags |= GNTMAP_readonly; + gnttab_set_map_op(&map[op], kvaddr, flags, + req->seg[i].gref, blkif->domid); + op++; + + /* Now map it to user. */ + ret = create_lookup_pte_addr(info->vma->vm_mm, + uvaddr, &ptep); + if (ret) { + WPRINTK("Couldn't get a pte addr!\n"); + fast_flush_area(pending_req, pending_idx, usr_idx, + blkif->dev_num); + goto fail_flush; + } + + flags = GNTMAP_host_map | GNTMAP_application_map + | GNTMAP_contains_pte; + if (operation == WRITE) + flags |= GNTMAP_readonly; + gnttab_set_map_op(&map[op], ptep, flags, + req->seg[i].gref, blkif->domid); + op++; + } + + ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, op); + BUG_ON(ret); + + for (i = 0; i < (nseg*2); i+=2) { + unsigned long uvaddr; + unsigned long kvaddr; + unsigned long offset; + struct page *pg; + + uvaddr = MMAP_VADDR(info->user_vstart, usr_idx, i/2); + kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i/2); + + if (unlikely(map[i].status != 0)) { + WPRINTK("invalid kernel buffer -- " + "could not remap it\n"); + goto fail_flush; + } + + if (unlikely(map[i+1].status != 0)) { + WPRINTK("invalid user buffer -- " + "could not remap it\n"); + goto fail_flush; + } + + pending_handle(mmap_idx, pending_idx, i/2).kernel + = map[i].handle; + pending_handle(mmap_idx, pending_idx, i/2).user + = map[i+1].handle; + set_phys_to_machine(__pa(kvaddr) >> PAGE_SHIFT, + FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT)); + offset = (uvaddr - info->vma->vm_start) >> PAGE_SHIFT; + pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT); + ((struct page **)info->vma->vm_private_data)[offset] = + pg; + } + /* Mark mapped pages as reserved: */ + for (i = 0; i < req->nr_segments; i++) { + unsigned long kvaddr; + struct page *pg; + + kvaddr = idx_to_kaddr(mmap_idx, pending_idx, i); + pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT); + SetPageReserved(pg); + } + + /*record [mmap_idx,pending_idx] to [usr_idx] mapping*/ + info->idx_map[usr_idx] = MAKE_ID(mmap_idx, pending_idx); + + blkif_get(blkif); + /* Finally, write the request message to the user ring. */ + target = RING_GET_REQUEST(&info->ufe_ring, + info->ufe_ring.req_prod_pvt); + memcpy(target, req, sizeof(*req)); + target->id = usr_idx; + info->ufe_ring.req_prod_pvt++; + return; + + fail_flush: + WPRINTK("Reached Fail_flush\n"); + fast_flush_area(pending_req, pending_idx, usr_idx, blkif->dev_num); + fail_response: + make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR); + free_req(pending_req); +} + + + +/****************************************************************** + * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING + */ + + +static void make_response(blkif_t *blkif, unsigned long id, + unsigned short op, int st) +{ + blkif_response_t *resp; + unsigned long flags; + blkif_back_ring_t *blk_ring = &blkif->blk_ring; + int more_to_do = 0; + int notify; + + spin_lock_irqsave(&blkif->blk_ring_lock, flags); + /* Place on the response ring for the relevant domain. */ + resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt); + resp->id = id; + resp->operation = op; + resp->status = st; + blk_ring->rsp_prod_pvt++; + RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(blk_ring, notify); + + if (blk_ring->rsp_prod_pvt == blk_ring->req_cons) { + /* + * Tail check for pending requests. Allows frontend to avoid + * notifications if requests are already in flight (lower + * overheads and promotes batching). + */ + RING_FINAL_CHECK_FOR_REQUESTS(blk_ring, more_to_do); + } else if (RING_HAS_UNCONSUMED_REQUESTS(blk_ring)) { + more_to_do = 1; + + } + spin_unlock_irqrestore(&blkif->blk_ring_lock, flags); + if (more_to_do) + blkif_notify_work(blkif); + if (notify) + notify_remote_via_irq(blkif->irq); +} + +static int __init blkif_init(void) +{ + int i, ret; + tap_blkif_t *info; + + if (!is_running_on_xen()) + return -ENODEV; + + INIT_LIST_HEAD(&pending_free); + for(i = 0; i < 2; i++) { + ret = req_increase(); + if (ret) + break; + } + if (i == 0) + return ret; + + tap_blkif_interface_init(); + + alloc_pending_reqs = 0; + + tap_blkif_xenbus_init(); + + /*Create the blktap devices, but do not map memory or waitqueue*/ + for(i = 0; i < MAX_TAP_DEV; i++) translate_domid[i].domid = 0xFFFF; + + /* Dynamically allocate a major for this device */ + ret = register_chrdev(0, "blktap", &blktap_fops); + + if ( (ret < 0) ) { + WPRINTK("Couldn't register /dev/xen/blktap\n"); + return -ENOMEM; + } + + blktap_major = ret; + + for(i = 0; i < MAX_TAP_DEV; i++ ) { + info = tapfds[i] = kzalloc(sizeof(tap_blkif_t),GFP_KERNEL); + if(tapfds[i] == NULL) + return -ENOMEM; + info->minor = i; + info->pid = 0; + info->blkif = NULL; + + info->dev_pending = info->dev_inuse = 0; + + DPRINTK("Created misc_dev [/dev/xen/blktap%d]\n",i); + } + + /* Make sure the xen class exists */ + if (!setup_xen_class()) { + /* + * This will allow udev to create the blktap ctrl device. + * We only want to create blktap0 first. We don't want + * to flood the sysfs system with needless blktap devices. + * We only create the device when a request of a new device is + * made. + */ + class_device_create(xen_class, NULL, + MKDEV(blktap_major, 0), NULL, + "blktap0"); + tapfds[0]->sysfs_set = 1; + } else { + /* this is bad, but not fatal */ + WPRINTK("blktap: sysfs xen_class not created\n"); + } + + DPRINTK("Blktap device successfully created\n"); + + return 0; +} + +module_init(blkif_init); + +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/xen/xenfb/Makefile b/drivers/xen/xenfb/Makefile new file mode 100644 index 000000000..de96da7a9 --- /dev/null +++ b/drivers/xen/xenfb/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_XEN_FRAMEBUFFER) := xenfb.o diff --git a/drivers/xen/xenfb/xenfb.c b/drivers/xen/xenfb/xenfb.c new file mode 100644 index 000000000..481aef672 --- /dev/null +++ b/drivers/xen/xenfb/xenfb.c @@ -0,0 +1,571 @@ +/* + * linux/drivers/video/xenfb.c -- Xen para-virtual frame buffer device + * + * Copyright (C) 2005-2006 + * + * Anthony Liguori <aliguori@us.ibm.com> + * + * Based on linux/drivers/video/q40fb.c + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/fb.h> +#include <linux/module.h> +#include <linux/vmalloc.h> +#include <linux/mm.h> +#include <asm/hypervisor.h> +#include <xen/evtchn.h> +#include <xen/xenbus.h> +#include <linux/xenfb.h> +#include <linux/kthread.h> + +#define XENFB_WIDTH 800 +#define XENFB_HEIGHT 600 +#define XENFB_DEPTH 32 + +static int xenfb_fps = 20; +static unsigned long xenfb_mem_len = XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8; + +struct xenfb_mapping +{ + struct list_head next; + struct vm_area_struct *vma; + atomic_t map_refs; + int faults; + struct xenfb_info *info; +}; + +struct xenfb_info +{ + struct task_struct *kthread; + wait_queue_head_t wq; + + unsigned char *fb; + struct fb_fix_screeninfo *fix; + struct fb_var_screeninfo *var; + struct fb_info *fb_info; + struct timer_list refresh; + int dirty; + int y1, y2; + int x1, x2; + + struct semaphore mm_lock; + int nr_pages; + struct page **pages; + struct list_head mappings; + + unsigned evtchn; + int irq; + struct xenfb_page *page; + unsigned long *mfns; + u32 flags; +}; + +static void xenfb_do_update(struct xenfb_info *info, + int x, int y, int w, int h) +{ + union xenfb_out_event event; + __u32 prod; + + event.type = XENFB_TYPE_UPDATE; + event.update.x = x; + event.update.y = y; + event.update.width = w; + event.update.height = h; + + prod = info->page->out_prod; + if (prod - info->page->out_cons == XENFB_OUT_RING_LEN) + return; /* ring buffer full, event lost */ + mb(); /* ensure ring space available */ + XENFB_OUT_RING_REF(info->page, prod) = event; + wmb(); /* ensure ring contents visible */ + info->page->out_prod = prod + 1; + + notify_remote_via_evtchn(info->evtchn); +} + +static int xenfb_queue_full(struct xenfb_info *info) +{ + __u32 cons, prod; + + prod = info->page->out_prod; + cons = info->page->out_cons; + return prod - cons == XENFB_OUT_RING_LEN; +} + +static void xenfb_update_screen(struct xenfb_info *info) +{ + int y1, y2, x1, x2; + struct list_head *item; + struct xenfb_mapping *map; + + if (!(info->flags & XENFB_FLAG_UPDATE)) + return; + if (xenfb_queue_full(info)) + return; + + y1 = info->y1; + y2 = info->y2; + x1 = info->x1; + x2 = info->x2; + info->y1 = info->y2 = info->x1 = info->x2 = 0; + down(&info->mm_lock); + list_for_each(item, &info->mappings) { + map = list_entry(item, struct xenfb_mapping, next); + if (!map->faults) + continue; + zap_page_range(map->vma, map->vma->vm_start, + map->vma->vm_end - map->vma->vm_start, NULL); + map->faults = 0; + } + up(&info->mm_lock); + + xenfb_do_update(info, x1, y1, x2 - x1, y2 - y1); +} + +static int xenfb_thread(void *data) +{ + struct xenfb_info *info = data; + + for (;;) { + if (kthread_should_stop()) + break; + if (info->dirty) { + info->dirty = 0; + xenfb_update_screen(info); + } + wait_event_interruptible(info->wq, + kthread_should_stop() || info->dirty); + } + return 0; +} + +static int xenfb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + u32 v; + + if (regno > info->cmap.len) + return 1; + + red >>= (16 - info->var.red.length); + green >>= (16 - info->var.green.length); + blue >>= (16 - info->var.blue.length); + + v = (red << info->var.red.offset) | + (green << info->var.green.offset) | + (blue << info->var.blue.offset); + + switch (info->var.bits_per_pixel) { + case 16: + case 24: + case 32: + ((u32 *)info->pseudo_palette)[regno] = v; + break; + } + + return 0; +} + +static void xenfb_timer(unsigned long data) +{ + struct xenfb_info *info = (struct xenfb_info *)data; + info->dirty = 1; + wake_up(&info->wq); +} + +static void xenfb_refresh(struct xenfb_info *info, + int x1, int y1, int w, int h) +{ + int y2, x2; + + y2 = y1 + h; + x2 = x1 + w; + if (info->y2 == 0) { + info->y1 = y1; + info->y2 = y2; + } + if (info->x2 == 0) { + info->x1 = x1; + info->x2 = x2; + } + + if (info->y1 > y1) + info->y1 = y1; + if (info->y2 < y2) + info->y2 = y2; + if (info->x1 > x1) + info->x1 = x1; + if (info->x2 < x2) + info->x2 = x2; + + if (timer_pending(&info->refresh)) + return; + + mod_timer(&info->refresh, jiffies + HZ/xenfb_fps); +} + +static void xenfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) +{ + struct xenfb_info *info = p->par; + + cfb_fillrect(p, rect); + xenfb_refresh(info, rect->dx, rect->dy, rect->width, rect->height); +} + +static void xenfb_imageblit(struct fb_info *p, const struct fb_image *image) +{ + struct xenfb_info *info = p->par; + + cfb_imageblit(p, image); + xenfb_refresh(info, image->dx, image->dy, image->width, image->height); +} + +static void xenfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) +{ + struct xenfb_info *info = p->par; + + cfb_copyarea(p, area); + xenfb_refresh(info, area->dx, area->dy, area->width, area->height); +} + +static void xenfb_vm_open(struct vm_area_struct *vma) +{ + struct xenfb_mapping *map = vma->vm_private_data; + atomic_inc(&map->map_refs); +} + +static void xenfb_vm_close(struct vm_area_struct *vma) +{ + struct xenfb_mapping *map = vma->vm_private_data; + struct xenfb_info *info = map->info; + + down(&info->mm_lock); + if (atomic_dec_and_test(&map->map_refs)) { + list_del(&map->next); + kfree(map); + } + up(&info->mm_lock); +} + +static struct page *xenfb_vm_nopage(struct vm_area_struct *vma, + unsigned long vaddr, int *type) +{ + struct xenfb_mapping *map = vma->vm_private_data; + struct xenfb_info *info = map->info; + int pgnr = (vaddr - vma->vm_start) >> PAGE_SHIFT; + struct page *page; + int y1, y2; + + if (pgnr >= info->nr_pages) + return NOPAGE_SIGBUS; + + down(&info->mm_lock); + page = info->pages[pgnr]; + get_page(page); + map->faults++; + + y1 = pgnr * PAGE_SIZE / info->fix->line_length; + y2 = (pgnr * PAGE_SIZE + PAGE_SIZE - 1) / info->fix->line_length; + if (y2 > info->var->yres) + y2 = info->var->yres; + xenfb_refresh(info, 0, y1, info->var->xres, y2 - y1); + up(&info->mm_lock); + + if (type) + *type = VM_FAULT_MINOR; + + return page; +} + +static struct vm_operations_struct xenfb_vm_ops = { + .open = xenfb_vm_open, + .close = xenfb_vm_close, + .nopage = xenfb_vm_nopage, +}; + +static int xenfb_mmap(struct fb_info *fb_info, struct vm_area_struct *vma) +{ + struct xenfb_info *info = fb_info->par; + struct xenfb_mapping *map; + int ret; + int map_pages; + + down(&info->mm_lock); + + ret = -EINVAL; + if (!(vma->vm_flags & VM_WRITE)) + goto out; + if (!(vma->vm_flags & VM_SHARED)) + goto out; + if (vma->vm_pgoff != 0) + goto out; + + map_pages = (vma->vm_end - vma->vm_start + PAGE_SIZE-1) >> PAGE_SHIFT; + if (map_pages > info->nr_pages) + goto out; + + ret = -ENOMEM; + map = kmalloc(sizeof(*map), GFP_KERNEL); + if (map == NULL) + goto out; + memset(map, 0, sizeof(*map)); + + map->vma = vma; + map->faults = 0; + map->info = info; + atomic_set(&map->map_refs, 1); + list_add(&map->next, &info->mappings); + vma->vm_ops = &xenfb_vm_ops; + vma->vm_flags |= (VM_DONTEXPAND | VM_RESERVED); + vma->vm_private_data = map; + ret = 0; + + out: + up(&info->mm_lock); + return ret; +} + +static struct fb_ops xenfb_fb_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = xenfb_setcolreg, + .fb_fillrect = xenfb_fillrect, + .fb_copyarea = xenfb_copyarea, + .fb_imageblit = xenfb_imageblit, + .fb_mmap = xenfb_mmap, +}; + +static irqreturn_t xenfb_event_handler(int rq, void *dev_id, + struct pt_regs *regs) +{ + struct xenfb_info *info = dev_id; + __u32 cons, prod; + + prod = info->page->in_prod; + rmb(); /* ensure we see ring contents up to prod */ + for (cons = info->page->in_cons; cons != prod; cons++) { + union xenfb_in_event *event; + event = &XENFB_IN_RING_REF(info->page, cons); + + switch (event->type) { + case XENFB_TYPE_SET_EVENTS: + info->flags = event->set_events.flags; + break; + } + } + mb(); /* ensure we're done with ring contents */ + info->page->in_cons = cons; + notify_remote_via_evtchn(info->evtchn); + + return IRQ_HANDLED; +} + +static unsigned long vmalloc_to_mfn(void *address) +{ + return pfn_to_mfn(vmalloc_to_pfn(address)); + //return arbitrary_virt_to_machine(address) >> PAGE_SHIFT; +} + +static struct xenfb_info *xenfb_info; + +static int __init xenfb_probe(void) +{ + struct xenfb_info *info; + int i, ret; + struct fb_info *fb_info; + struct evtchn_alloc_unbound alloc_unbound; + struct evtchn_close close; + struct xenbus_transaction xbt; + + /* Nothing to do if running in dom0. */ + if (is_initial_xendomain()) + return -ENODEV; +#if 1 + /* if we're not set up to use graphics mode, then don't initialize */ + if (xenbus_scanf(XBT_NIL, "console", "use_graphics", "%d", &ret) < 0) + return -ENODEV; + if (ret == 0) + return -ENODEV; +#endif + + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (info == NULL) + return -ENOMEM; + memset(info, 0, sizeof(*info)); + + INIT_LIST_HEAD(&info->mappings); + + info->fb = vmalloc(xenfb_mem_len); + if (info->fb == NULL) + goto error; + memset(info->fb, 0, xenfb_mem_len); + info->nr_pages = (xenfb_mem_len + PAGE_SIZE - 1) >> PAGE_SHIFT; + info->pages = kmalloc(sizeof(struct page*)*info->nr_pages, GFP_KERNEL); + if (info->pages == NULL) + goto error_vfree; + for (i = 0; i < info->nr_pages; i++) + info->pages[i] = vmalloc_to_page(info->fb + i * PAGE_SIZE); + + fb_info = framebuffer_alloc(sizeof(u32) * 256, NULL); + // FIXME sizeof(struct xenfb_info) + if (fb_info == NULL) + goto error_kfree; + + info->mfns = vmalloc(sizeof(unsigned long) * info->nr_pages); + /* set up shared page */ + info->page = (void *)__get_free_page(GFP_KERNEL); + if (!info->page) + goto error_kfree; + /* set up event channel */ + alloc_unbound.dom = DOMID_SELF; + alloc_unbound.remote_dom = 0; + ret = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, + &alloc_unbound); + if (ret) + goto error_freep; + info->evtchn = alloc_unbound.port; + + for (i = 0; i < info->nr_pages; i++) + info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE); + info->page->pd[0] = vmalloc_to_mfn(info->mfns); + info->page->pd[1] = 0; + info->page->width = XENFB_WIDTH; + info->page->height = XENFB_HEIGHT; + info->page->depth = XENFB_DEPTH; + info->page->line_length = (info->page->depth / 8) * info->page->width; + info->page->mem_length = xenfb_mem_len; + info->page->in_cons = info->page->in_prod = 0; + info->page->out_cons = info->page->out_prod = 0; + + ret = bind_evtchn_to_irqhandler(info->evtchn, xenfb_event_handler, + 0, "xenfb", info); + if (ret < 0) { + close.port = info->evtchn; + HYPERVISOR_event_channel_op(EVTCHNOP_close, &close); + goto error_freep; + } + + info->irq = ret; + xenfb_info = info; + + fb_info->pseudo_palette = fb_info->par; + fb_info->par = info; + fb_info->screen_base = info->fb; + + memset(&fb_info->var, 0, sizeof(fb_info->var)); + memset(&fb_info->fix, 0, sizeof(fb_info->fix)); + + fb_info->fbops = &xenfb_fb_ops; + fb_info->var.xres_virtual = fb_info->var.xres = info->page->width; + fb_info->var.yres_virtual = fb_info->var.yres = info->page->height; + fb_info->var.bits_per_pixel = info->page->depth; + + fb_info->var.red = (struct fb_bitfield){16, 8, 0}; + fb_info->var.green = (struct fb_bitfield){8, 8, 0}; + fb_info->var.blue = (struct fb_bitfield){0, 8, 0}; + + fb_info->var.activate = FB_ACTIVATE_NOW; + fb_info->var.height = -1; + fb_info->var.width = -1; + fb_info->var.vmode = FB_VMODE_NONINTERLACED; + + fb_info->fix.visual = FB_VISUAL_TRUECOLOR; + fb_info->fix.line_length = info->page->line_length; + fb_info->fix.smem_start = 0; + fb_info->fix.smem_len = xenfb_mem_len; + strcpy(fb_info->fix.id, "xen"); + fb_info->fix.type = FB_TYPE_PACKED_PIXELS; + fb_info->fix.accel = FB_ACCEL_NONE; + + fb_info->flags = FBINFO_FLAG_DEFAULT; + + fb_alloc_cmap(&fb_info->cmap, 256, 0); + + info->fb_info = fb_info; + info->fix = &fb_info->fix; + info->var = &fb_info->var; + + init_MUTEX(&info->mm_lock); + init_waitqueue_head(&info->wq); + init_timer(&info->refresh); + info->refresh.function = xenfb_timer; + info->refresh.data = (unsigned long)info; + + info->kthread = kthread_run(xenfb_thread, info, "xenfb thread"); + if (IS_ERR(info->kthread)) + goto error_unbind; + + ret = register_framebuffer(fb_info); + if (ret) + goto error_unbind; + + again: + ret = xenbus_transaction_start(&xbt); + if (ret) + goto error_unreg; + ret = xenbus_printf(xbt, "vfb", "page-ref", "%lu", + virt_to_mfn(info->page)); + // FIXME grant tables? + if (ret) + goto error_xenbus; + ret = xenbus_printf(xbt, "vfb", "event-channel", "%u", + info->evtchn); + if (ret) + goto error_xenbus; + ret = xenbus_transaction_end(xbt, 0); + if (ret) { + if (ret == -EAGAIN) + goto again; + goto error_unreg; + } + + return 0; + + error_xenbus: + xenbus_transaction_end(xbt, 1); + error_unreg: + unregister_framebuffer(fb_info); + error_unbind: + unbind_from_irqhandler(info->irq, info); + // FIXME do we have to stop info->kthread? + error_freep: + free_page((unsigned long)info->page); + error_kfree: + kfree(info->pages); + error_vfree: + vfree(info->fb); + error: + kfree(info); + xenfb_info = NULL; + + return -ENODEV; +} + +static int __init xenfb_init(void) +{ + return xenfb_probe(); +} + +static void __exit xenfb_cleanup(void) +{ + struct xenfb_info *info = xenfb_info; + + unregister_framebuffer(info->fb_info); + unbind_from_irqhandler(info->irq, info); + free_page((unsigned long)info->page); + kfree(info->pages); + vfree(info->fb); + kfree(info); + xenfb_info = NULL; +} + +module_init(xenfb_init); +module_exit(xenfb_cleanup); + +MODULE_LICENSE("GPL"); diff --git a/drivers/xen/xenkbd/Makefile b/drivers/xen/xenkbd/Makefile new file mode 100644 index 000000000..724efe2bf --- /dev/null +++ b/drivers/xen/xenkbd/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_XEN_KEYBOARD) += xenkbd.o diff --git a/drivers/xen/xenkbd/xenkbd.c b/drivers/xen/xenkbd/xenkbd.c new file mode 100644 index 000000000..26749ff2b --- /dev/null +++ b/drivers/xen/xenkbd/xenkbd.c @@ -0,0 +1,178 @@ +/* + * linux/drivers/input/keyboard/xenkbd.c -- Xen para-virtual input device + * + * Copyright (C) 2005 + * + * Anthony Liguori <aliguori@us.ibm.com> + * + * Based on linux/drivers/input/mouse/sermouse.c + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/module.h> +#include <linux/input.h> +#include <asm/hypervisor.h> +#include <xen/evtchn.h> +#include <xen/xenbus.h> +#include <linux/xenkbd.h> + +struct xenkbd_device +{ + struct input_dev *dev; + struct xenkbd_info *info; + unsigned evtchn; + int irq; +}; + +static irqreturn_t input_handler(int rq, void *dev_id, struct pt_regs *regs) +{ + struct xenkbd_device *dev = dev_id; + struct xenkbd_info *info = dev ? dev->info : 0; + static int button_map[3] = { BTN_RIGHT, BTN_MIDDLE, BTN_LEFT }; + __u32 cons, prod; + + prod = info->in_prod; + rmb(); /* ensure we see ring contents up to prod */ + for (cons = info->in_cons; cons != prod; cons++) { + union xenkbd_in_event *event; + event = &XENKBD_IN_RING_REF(info, cons); + + switch (event->type) { + case XENKBD_TYPE_MOTION: + input_report_rel(dev->dev, REL_X, event->motion.rel_x); + input_report_rel(dev->dev, REL_Y, event->motion.rel_y); + break; + case XENKBD_TYPE_BUTTON: + if (event->button.button < 3) + input_report_key(dev->dev, + button_map[event->button.button], + event->button.pressed); + break; + case XENKBD_TYPE_KEY: + input_report_key(dev->dev, event->key.keycode, event->key.pressed); + break; + } + } + input_sync(dev->dev); + mb(); /* ensure we got ring contents */ + info->in_cons = cons; + notify_remote_via_evtchn(dev->evtchn); + + return IRQ_HANDLED; +} + +static struct xenkbd_device *xenkbd_dev; + +int __init xenkbd_init(void) +{ + int ret = 0; + int i; + struct xenkbd_device *dev; + struct input_dev *input_dev; + struct evtchn_alloc_unbound alloc_unbound; + struct xenbus_transaction xbt; + + /* Nothing to do if running in dom0. */ + if (is_initial_xendomain()) + return -ENODEV; +#if 1 + /* if we're not set up to use graphics mode, then don't initialize */ + if (xenbus_scanf(XBT_NIL, "console", "use_graphics", "%d", &ret) < 0) + return -ENODEV; + if (ret == 0) + return -ENODEV; +#endif + + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + input_dev = input_allocate_device(); + if (!dev || !input_dev) + return -ENOMEM; + + dev->dev = input_dev; + dev->info = (void *)__get_free_page(GFP_KERNEL); + if (!dev->info) { + ret = -ENOMEM; + goto error; + } + + alloc_unbound.dom = DOMID_SELF; + alloc_unbound.remote_dom = 0; + ret = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, + &alloc_unbound); + if (ret) + goto error_freep; + dev->evtchn = alloc_unbound.port; + ret = bind_evtchn_to_irqhandler(dev->evtchn, input_handler, 0, + "xenkbd", dev); + if (ret < 0) + goto error_freep; + dev->irq = ret; + + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); + input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT); + input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); + + /* FIXME not sure this is quite right */ + for (i = 0; i < 256; i++) + set_bit(i, input_dev->keybit); + + input_dev->name = "Xen Virtual Keyboard/Mouse"; + + input_register_device(input_dev); + + again: + ret = xenbus_transaction_start(&xbt); + if (ret) + goto error_unreg; + ret = xenbus_printf(xbt, "vkbd", "page-ref", "%lu", + virt_to_mfn(dev->info)); + if (ret) + goto error_xenbus; + ret = xenbus_printf(xbt, "vkbd", "event-channel", "%u", + dev->evtchn); + if (ret) + goto error_xenbus; + ret = xenbus_transaction_end(xbt, 0); + if (ret) { + if (ret == -EAGAIN) + goto again; + goto error_unreg; + } + + dev->info->in_cons = dev->info->in_prod = 0; + dev->info->out_cons = dev->info->out_prod = 0; + xenkbd_dev = dev; + + return ret; + + + error_xenbus: + xenbus_transaction_end(xbt, 1); + error_unreg: + input_unregister_device(input_dev); + unbind_from_irqhandler(dev->irq, dev); + error_freep: + free_page((unsigned long)dev->info); + error: + kfree(dev); + return ret; +} + +static void __exit xenkbd_cleanup(void) +{ + input_unregister_device(xenkbd_dev->dev); + unbind_from_irqhandler(xenkbd_dev->irq, xenkbd_dev); + free_page((unsigned long)xenkbd_dev->info); + kfree(xenkbd_dev); + xenkbd_dev = NULL; +} + +module_init(xenkbd_init); +module_exit(xenkbd_cleanup); + +MODULE_LICENSE("GPL"); diff --git a/fs/cachefiles/Makefile b/fs/cachefiles/Makefile new file mode 100644 index 000000000..c1522d98b --- /dev/null +++ b/fs/cachefiles/Makefile @@ -0,0 +1,18 @@ +# +# Makefile for caching in a mounted filesystem +# + +cachefiles-objs := \ + cf-bind.o \ + cf-interface.o \ + cf-key.o \ + cf-main.o \ + cf-namei.o \ + cf-proc.o \ + cf-xattr.o + +ifeq ($(CONFIG_SYSCTL),y) +cachefiles-objs += cf-sysctl.o +endif + +obj-$(CONFIG_CACHEFILES) := cachefiles.o diff --git a/fs/cachefiles/cf-bind.c b/fs/cachefiles/cf-bind.c new file mode 100644 index 000000000..d8cb4c394 --- /dev/null +++ b/fs/cachefiles/cf-bind.c @@ -0,0 +1,279 @@ +/* cf-bind.c: bind and unbind a cache from the filesystem backing it + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/completion.h> +#include <linux/slab.h> +#include <linux/fs.h> +#include <linux/file.h> +#include <linux/namei.h> +#include <linux/mount.h> +#include <linux/namespace.h> +#include <linux/statfs.h> +#include <linux/proc_fs.h> +#include <linux/ctype.h> +#include "internal.h" + +static int cachefiles_proc_add_cache(struct cachefiles_cache *cache, + struct vfsmount *mnt); + +/*****************************************************************************/ +/* + * bind a directory as a cache + */ +int cachefiles_proc_bind(struct cachefiles_cache *cache, char *args) +{ + _enter("{%u,%u,%u},%s", + cache->brun_percent, + cache->bcull_percent, + cache->bstop_percent, + args); + + /* start by checking things over */ + ASSERT(cache->bstop_percent >= 0 && + cache->bstop_percent < cache->bcull_percent && + cache->bcull_percent < cache->brun_percent && + cache->brun_percent < 100); + + if (*args) { + kerror("'bind' command doesn't take an argument"); + return -EINVAL; + } + + if (!cache->rootdirname) { + kerror("No cache directory specified"); + return -EINVAL; + } + + /* don't permit already bound caches to be re-bound */ + if (test_bit(CACHEFILES_READY, &cache->flags)) { + kerror("Cache already bound"); + return -EBUSY; + } + + /* make sure we have copies of the tag and dirname strings */ + if (!cache->tag) { + /* the tag string is released by the fops->release() + * function, so we don't release it on error here */ + cache->tag = kstrdup("CacheFiles", GFP_KERNEL); + if (!cache->tag) + return -ENOMEM; + } + + /* add the cache */ + return cachefiles_proc_add_cache(cache, NULL); +} + +/*****************************************************************************/ +/* + * add a cache + */ +static int cachefiles_proc_add_cache(struct cachefiles_cache *cache, + struct vfsmount *mnt) +{ + struct cachefiles_object *fsdef; + struct nameidata nd; + struct kstatfs stats; + struct dentry *graveyard, *cachedir, *root; + int ret; + + _enter(""); + + /* allocate the root index object */ + ret = -ENOMEM; + + fsdef = kmem_cache_alloc(cachefiles_object_jar, SLAB_KERNEL); + if (!fsdef) + goto error_root_object; + + atomic_set(&fsdef->usage, 1); + atomic_set(&fsdef->fscache_usage, 1); + fsdef->type = FSCACHE_COOKIE_TYPE_INDEX; + + _debug("- fsdef %p", fsdef); + + /* look up the directory at the root of the cache */ + memset(&nd, 0, sizeof(nd)); + + ret = path_lookup(cache->rootdirname, LOOKUP_DIRECTORY, &nd); + if (ret < 0) + goto error_open_root; + + /* bind to the special mountpoint we've prepared */ + if (mnt) { + atomic_inc(&nd.mnt->mnt_sb->s_active); + mnt->mnt_sb = nd.mnt->mnt_sb; + mnt->mnt_flags = nd.mnt->mnt_flags; + mnt->mnt_flags |= MNT_NOSUID | MNT_NOEXEC | MNT_NODEV; + mnt->mnt_root = dget(nd.dentry); + mnt->mnt_mountpoint = mnt->mnt_root; + + /* copy the name, but ignore kstrdup() failing ENOMEM - we'll + * just end up with an devicenameless mountpoint */ + mnt->mnt_devname = kstrdup(nd.mnt->mnt_devname, GFP_KERNEL); + path_release(&nd); + + cache->mnt = mntget(mnt); + root = dget(mnt->mnt_root); + } else { + cache->mnt = nd.mnt; + root = nd.dentry; + + nd.mnt = NULL; + nd.dentry = NULL; + path_release(&nd); + } + + /* check parameters */ + ret = -EOPNOTSUPP; + if (!root->d_inode || + !root->d_inode->i_op || + !root->d_inode->i_op->lookup || + !root->d_inode->i_op->mkdir || + !root->d_inode->i_op->setxattr || + !root->d_inode->i_op->getxattr || + !root->d_sb || + !root->d_sb->s_op || + !root->d_sb->s_op->statfs || + !root->d_sb->s_op->sync_fs) + goto error_unsupported; + + ret = -EROFS; + if (root->d_sb->s_flags & MS_RDONLY) + goto error_unsupported; + + /* get the cache size and blocksize */ + ret = root->d_sb->s_op->statfs(root, &stats); + if (ret < 0) + goto error_unsupported; + + ret = -ERANGE; + if (stats.f_bsize <= 0) + goto error_unsupported; + + ret = -EOPNOTSUPP; + if (stats.f_bsize > PAGE_SIZE) + goto error_unsupported; + + cache->bsize = stats.f_bsize; + cache->bshift = 0; + if (stats.f_bsize < PAGE_SIZE) + cache->bshift = PAGE_SHIFT - long_log2(stats.f_bsize); + + _debug("blksize %u (shift %u)", + cache->bsize, cache->bshift); + + _debug("size %llu, avail %llu", stats.f_blocks, stats.f_bavail); + + /* set up caching limits */ + stats.f_blocks >>= cache->bshift; + do_div(stats.f_blocks, 100); + cache->bstop = stats.f_blocks * cache->bstop_percent; + cache->bcull = stats.f_blocks * cache->bcull_percent; + cache->brun = stats.f_blocks * cache->brun_percent; + + _debug("limits {%llu,%llu,%llu}", + cache->brun, + cache->bcull, + cache->bstop); + + /* get the cache directory and check its type */ + cachedir = cachefiles_get_directory(cache, root, "cache"); + if (IS_ERR(cachedir)) { + ret = PTR_ERR(cachedir); + goto error_unsupported; + } + + fsdef->dentry = cachedir; + + ret = cachefiles_check_object_type(fsdef); + if (ret < 0) + goto error_unsupported; + + /* get the graveyard directory */ + graveyard = cachefiles_get_directory(cache, root, "graveyard"); + if (IS_ERR(graveyard)) { + ret = PTR_ERR(graveyard); + goto error_unsupported; + } + + cache->graveyard = graveyard; + + /* publish the cache */ + fscache_init_cache(&cache->cache, + &cachefiles_cache_ops, + "%02x:%02x", + MAJOR(fsdef->dentry->d_sb->s_dev), + MINOR(fsdef->dentry->d_sb->s_dev) + ); + + ret = fscache_add_cache(&cache->cache, &fsdef->fscache, cache->tag); + if (ret < 0) + goto error_add_cache; + + /* done */ + set_bit(CACHEFILES_READY, &cache->flags); + dput(root); + + printk(KERN_INFO "CacheFiles:" + " File cache on %s registered\n", + cache->cache.identifier); + + /* check how much space the cache has */ + cachefiles_has_space(cache, 0); + + return 0; + +error_add_cache: + dput(cache->graveyard); + cache->graveyard = NULL; +error_unsupported: + mntput(cache->mnt); + cache->mnt = NULL; + dput(fsdef->dentry); + fsdef->dentry = NULL; + dput(root); +error_open_root: + kmem_cache_free(cachefiles_object_jar, fsdef); +error_root_object: + kerror("Failed to register: %d", ret); + return ret; +} + +/*****************************************************************************/ +/* + * unbind a cache on fd release + */ +void cachefiles_proc_unbind(struct cachefiles_cache *cache) +{ + _enter(""); + + if (test_bit(CACHEFILES_READY, &cache->flags)) { + printk(KERN_INFO "CacheFiles:" + " File cache on %s unregistering\n", + cache->cache.identifier); + + fscache_withdraw_cache(&cache->cache); + } + + if (cache->cache.fsdef) + cache->cache.ops->put_object(cache->cache.fsdef); + + dput(cache->graveyard); + mntput(cache->mnt); + + kfree(cache->rootdirname); + kfree(cache->tag); + + _leave(""); +} diff --git a/fs/cachefiles/cf-interface.c b/fs/cachefiles/cf-interface.c new file mode 100644 index 000000000..b5ca30f76 --- /dev/null +++ b/fs/cachefiles/cf-interface.c @@ -0,0 +1,1299 @@ +/* cf-interface.c: CacheFiles to FS-Cache interface + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/file.h> +#include <linux/mount.h> +#include <linux/statfs.h> +#include <linux/buffer_head.h> +#include "internal.h" + +#define list_to_page(head) (list_entry((head)->prev, struct page, lru)) +#define log2(n) ffz(~(n)) + +/*****************************************************************************/ +/* + * look up the nominated node in this cache, creating it if necessary + */ +static struct fscache_object *cachefiles_lookup_object( + struct fscache_cache *_cache, + struct fscache_object *_parent, + struct fscache_cookie *cookie) +{ + struct cachefiles_object *parent, *object; + struct cachefiles_cache *cache; + struct cachefiles_xattr *auxdata; + unsigned keylen, auxlen; + void *buffer; + char *key; + int ret; + + ASSERT(_parent); + + cache = container_of(_cache, struct cachefiles_cache, cache); + parent = container_of(_parent, struct cachefiles_object, fscache); + + _enter("{%s},%p,%p", cache->cache.identifier, parent, cookie); + + /* create a new object record and a temporary leaf image */ + object = kmem_cache_alloc(cachefiles_object_jar, SLAB_KERNEL); + if (!object) + goto nomem_object; + + atomic_set(&object->usage, 1); + atomic_set(&object->fscache_usage, 1); + + fscache_object_init(&object->fscache); + object->fscache.cookie = cookie; + object->fscache.cache = parent->fscache.cache; + + object->type = cookie->def->type; + + /* get hold of the raw key + * - stick the length on the front and leave space on the back for the + * encoder + */ + buffer = kmalloc((2 + 512) + 3, GFP_KERNEL); + if (!buffer) + goto nomem_buffer; + + keylen = cookie->def->get_key(cookie->netfs_data, buffer + 2, 512); + ASSERTCMP(keylen, <, 512); + + *(uint16_t *)buffer = keylen; + ((char *)buffer)[keylen + 2] = 0; + ((char *)buffer)[keylen + 3] = 0; + ((char *)buffer)[keylen + 4] = 0; + + /* turn the raw key into something that can work with as a filename */ + key = cachefiles_cook_key(buffer, keylen + 2, object->type); + if (!key) + goto nomem_key; + + /* get hold of the auxiliary data and prepend the object type */ + auxdata = buffer; + auxlen = 0; + if (cookie->def->get_aux) { + auxlen = cookie->def->get_aux(cookie->netfs_data, + auxdata->data, 511); + ASSERTCMP(auxlen, <, 511); + } + + auxdata->len = auxlen + 1; + auxdata->type = cookie->def->type; + + /* look up the key, creating any missing bits */ + ret = cachefiles_walk_to_object(parent, object, key, auxdata); + if (ret < 0) + goto lookup_failed; + + kfree(buffer); + kfree(key); + _leave(" = %p", &object->fscache); + return &object->fscache; + +lookup_failed: + kmem_cache_free(cachefiles_object_jar, object); + kfree(buffer); + kfree(key); + _leave(" = %d", ret); + return ERR_PTR(ret); + +nomem_key: + kfree(buffer); +nomem_buffer: + kmem_cache_free(cachefiles_object_jar, object); +nomem_object: + _leave(" = -ENOMEM"); + return ERR_PTR(-ENOMEM); + +} + +/*****************************************************************************/ +/* + * increment the usage count on an inode object (may fail if unmounting) + */ +static struct fscache_object *cachefiles_grab_object(struct fscache_object *_object) +{ + struct cachefiles_object *object; + + _enter("%p", _object); + + object = container_of(_object, struct cachefiles_object, fscache); + +#ifdef CACHEFILES_DEBUG_SLAB + ASSERT((atomic_read(&object->fscache_usage) & 0xffff0000) != 0x6b6b0000); +#endif + + atomic_inc(&object->fscache_usage); + return &object->fscache; + +} + +/*****************************************************************************/ +/* + * lock the semaphore on an object object + */ +static void cachefiles_lock_object(struct fscache_object *_object) +{ + struct cachefiles_object *object; + + _enter("%p", _object); + + object = container_of(_object, struct cachefiles_object, fscache); + +#ifdef CACHEFILES_DEBUG_SLAB + ASSERT((atomic_read(&object->fscache_usage) & 0xffff0000) != 0x6b6b0000); +#endif + + down_write(&object->sem); + +} + +/*****************************************************************************/ +/* + * unlock the semaphore on an object object + */ +static void cachefiles_unlock_object(struct fscache_object *_object) +{ + struct cachefiles_object *object; + + _enter("%p", _object); + + object = container_of(_object, struct cachefiles_object, fscache); + up_write(&object->sem); + +} + +/*****************************************************************************/ +/* + * update the auxilliary data for an object object on disk + */ +static void cachefiles_update_object(struct fscache_object *_object) +{ + struct cachefiles_object *object; + struct cachefiles_cache *cache; + + _enter("%p", _object); + + object = container_of(_object, struct cachefiles_object, fscache); + cache = container_of(object->fscache.cache, struct cachefiles_cache, cache); + + //cachefiles_tree_update_object(super, object); + +} + +/*****************************************************************************/ +/* + * dispose of a reference to an object object + */ +static void cachefiles_put_object(struct fscache_object *_object) +{ + struct cachefiles_object *object; + struct cachefiles_cache *cache; + + ASSERT(_object); + + object = container_of(_object, struct cachefiles_object, fscache); + _enter("%p{%d}", object, atomic_read(&object->usage)); + + ASSERT(object); + + cache = container_of(object->fscache.cache, + struct cachefiles_cache, cache); + +#ifdef CACHEFILES_DEBUG_SLAB + ASSERT((atomic_read(&object->fscache_usage) & 0xffff0000) != 0x6b6b0000); +#endif + + if (!atomic_dec_and_test(&object->fscache_usage)) + return; + + _debug("- kill object %p", object); + + /* delete retired objects */ + if (test_bit(FSCACHE_OBJECT_RECYCLING, &object->fscache.flags) && + _object != cache->cache.fsdef + ) { + _debug("- retire object %p", object); + cachefiles_delete_object(cache, object); + } + + /* close the filesystem stuff attached to the object */ + if (object->backer != object->dentry) { + dput(object->backer); + object->backer = NULL; + } + + /* note that an object is now inactive */ + write_lock(&cache->active_lock); + rb_erase(&object->active_node, &cache->active_nodes); + write_unlock(&cache->active_lock); + + dput(object->dentry); + object->dentry = NULL; + + /* then dispose of the object */ + kmem_cache_free(cachefiles_object_jar, object); + + _leave(""); + +} + +/*****************************************************************************/ +/* + * sync a cache + */ +static void cachefiles_sync_cache(struct fscache_cache *_cache) +{ + struct cachefiles_cache *cache; + int ret; + + _enter("%p", _cache); + + cache = container_of(_cache, struct cachefiles_cache, cache); + + /* make sure all pages pinned by operations on behalf of the netfs are + * written to disc */ + ret = fsync_super(cache->mnt->mnt_sb); + if (ret == -EIO) + cachefiles_io_error(cache, + "Attempt to sync backing fs superblock" + " returned error %d", + ret); + +} + +/*****************************************************************************/ +/* + * set the data size on an object + */ +static int cachefiles_set_i_size(struct fscache_object *_object, loff_t i_size) +{ + struct cachefiles_object *object; + struct iattr newattrs; + int ret; + + _enter("%p,%llu", _object, i_size); + + object = container_of(_object, struct cachefiles_object, fscache); + + if (i_size == object->i_size) + return 0; + + if (!object->backer) + return -ENOBUFS; + + ASSERT(S_ISREG(object->backer->d_inode->i_mode)); + + newattrs.ia_size = i_size; + newattrs.ia_valid = ATTR_SIZE; + + mutex_lock(&object->backer->d_inode->i_mutex); + ret = notify_change(object->backer, &newattrs); + mutex_unlock(&object->backer->d_inode->i_mutex); + + if (ret == -EIO) { + cachefiles_io_error_obj(object, "Size set failed"); + ret = -ENOBUFS; + } + + _leave(" = %d", ret); + return ret; + +} + +/*****************************************************************************/ +/* + * see if we have space for a number of pages in the cache + */ +int cachefiles_has_space(struct cachefiles_cache *cache, unsigned nr) +{ + struct kstatfs stats; + int ret; + + _enter("{%llu,%llu,%llu},%d", + cache->brun, cache->bcull, cache->bstop, nr); + + /* find out how many pages of blockdev are available */ + memset(&stats, 0, sizeof(stats)); + + ret = cache->mnt->mnt_sb->s_op->statfs(cache->mnt->mnt_root, &stats); + if (ret < 0) { + if (ret == -EIO) + cachefiles_io_error(cache, "statfs failed"); + return ret; + } + + stats.f_bavail >>= cache->bshift; + + _debug("avail %llu", stats.f_bavail); + + /* see if there is sufficient space */ + stats.f_bavail -= nr; + + ret = -ENOBUFS; + if (stats.f_bavail < cache->bstop) + goto begin_cull; + + ret = 0; + if (stats.f_bavail < cache->bcull) + goto begin_cull; + + if (test_bit(CACHEFILES_CULLING, &cache->flags) && + stats.f_bavail >= cache->brun + ) { + if (test_and_clear_bit(CACHEFILES_CULLING, &cache->flags)) { + _debug("cease culling"); + send_sigurg(&cache->cachefilesd->f_owner); + } + } + + _leave(" = 0"); + return 0; + +begin_cull: + if (!test_and_set_bit(CACHEFILES_CULLING, &cache->flags)) { + _debug("### CULL CACHE ###"); + send_sigurg(&cache->cachefilesd->f_owner); + } + + _leave(" = %d", ret); + return ret; + +} + +/*****************************************************************************/ +/* + * waiting reading backing files + */ +static int cachefiles_read_waiter(wait_queue_t *wait, unsigned mode, + int sync, void *_key) +{ + struct cachefiles_one_read *monitor = + container_of(wait, struct cachefiles_one_read, monitor); + struct wait_bit_key *key = _key; + struct page *page = wait->private; + + ASSERT(key); + + _enter("{%lu},%u,%d,{%p,%u}", + monitor->netfs_page->index, mode, sync, + key->flags, key->bit_nr); + + if (key->flags != &page->flags || + key->bit_nr != PG_locked) + return 0; + + _debug("--- monitor %p %lx ---", page, page->flags); + + if (!PageUptodate(page) && !PageError(page)) + dump_stack(); + + /* remove from the waitqueue */ + list_del(&wait->task_list); + + /* move onto the action list and queue for keventd */ + ASSERT(monitor->object); + + spin_lock(&monitor->object->work_lock); + list_move(&monitor->obj_link, &monitor->object->read_list); + spin_unlock(&monitor->object->work_lock); + + schedule_work(&monitor->object->read_work); + + return 0; + +} + +/*****************************************************************************/ +/* + * let keventd drive the copying of pages + */ +void cachefiles_read_copier_work(void *_object) +{ + struct cachefiles_one_read *monitor; + struct cachefiles_object *object = _object; + struct fscache_cookie *cookie = object->fscache.cookie; + struct pagevec pagevec; + int error, max; + + _enter("{ino=%lu}", object->backer->d_inode->i_ino); + + pagevec_init(&pagevec, 0); + + max = 8; + spin_lock_irq(&object->work_lock); + + while (!list_empty(&object->read_list)) { + monitor = list_entry(object->read_list.next, + struct cachefiles_one_read, obj_link); + list_del(&monitor->obj_link); + + spin_unlock_irq(&object->work_lock); + + _debug("- copy {%lu}", monitor->back_page->index); + + error = -EIO; + if (PageUptodate(monitor->back_page)) { + copy_highpage(monitor->netfs_page, monitor->back_page); + + pagevec_add(&pagevec, monitor->netfs_page); + cookie->def->mark_pages_cached( + cookie->netfs_data, + monitor->netfs_page->mapping, + &pagevec); + pagevec_reinit(&pagevec); + + error = 0; + } + + if (error) + cachefiles_io_error_obj( + object, + "readpage failed on backing file %lx", + (unsigned long) monitor->back_page->flags); + + page_cache_release(monitor->back_page); + + monitor->end_io_func(monitor->netfs_page, + monitor->context, + error); + + page_cache_release(monitor->netfs_page); + fscache_put_context(cookie, monitor->context); + kfree(monitor); + + /* let keventd have some air occasionally */ + max--; + if (max < 0 || need_resched()) { + if (!list_empty(&object->read_list)) + schedule_work(&object->read_work); + _leave(" [maxed out]"); + return; + } + + spin_lock_irq(&object->work_lock); + } + + spin_unlock_irq(&object->work_lock); + + _leave(""); + +} + +/*****************************************************************************/ +/* + * read the corresponding page to the given set from the backing file + * - an uncertain page is simply discarded, to be tried again another time + */ +static int cachefiles_read_backing_file_one(struct cachefiles_object *object, + fscache_rw_complete_t end_io_func, + void *context, + struct page *netpage, + struct pagevec *lru_pvec) +{ + struct cachefiles_one_read *monitor; + struct address_space *bmapping; + struct page *newpage, *backpage; + int ret; + + _enter(""); + + ASSERTCMP(pagevec_count(lru_pvec), ==, 0); + pagevec_reinit(lru_pvec); + + _debug("read back %p{%lu,%d}", + netpage, netpage->index, page_count(netpage)); + + monitor = kzalloc(sizeof(*monitor), GFP_KERNEL); + if (!monitor) + goto nomem; + + monitor->netfs_page = netpage; + monitor->object = object; + monitor->end_io_func = end_io_func; + monitor->context = fscache_get_context(object->fscache.cookie, + context); + + init_waitqueue_func_entry(&monitor->monitor, cachefiles_read_waiter); + + /* attempt to get hold of the backing page */ + bmapping = object->backer->d_inode->i_mapping; + newpage = NULL; + + for (;;) { + backpage = find_get_page(bmapping, netpage->index); + if (backpage) + goto backing_page_already_present; + + if (!newpage) { + newpage = page_cache_alloc_cold(bmapping); + if (!newpage) + goto nomem_monitor; + } + + ret = add_to_page_cache(newpage, bmapping, + netpage->index, GFP_KERNEL); + if (ret == 0) + goto installed_new_backing_page; + if (ret != -EEXIST) + goto nomem_page; + } + + /* we've installed a new backing page, so now we need to add it + * to the LRU list and start it reading */ +installed_new_backing_page: + _debug("- new %p", newpage); + + backpage = newpage; + newpage = NULL; + + page_cache_get(backpage); + pagevec_add(lru_pvec, backpage); + __pagevec_lru_add(lru_pvec); + + ret = bmapping->a_ops->readpage(NULL, backpage); + if (ret < 0) + goto read_error; + + /* set the monitor to transfer the data across */ +monitor_backing_page: + _debug("- monitor add"); + + /* install the monitor */ + page_cache_get(monitor->netfs_page); + page_cache_get(backpage); + monitor->back_page = backpage; + + spin_lock_irq(&object->work_lock); + list_add_tail(&monitor->obj_link, &object->read_pend_list); + spin_unlock_irq(&object->work_lock); + + monitor->monitor.private = backpage; + install_page_waitqueue_monitor(backpage, &monitor->monitor); + monitor = NULL; + + /* but the page may have been read before the monitor was + * installed, so the monitor may miss the event - so we have to + * ensure that we do get one in such a case */ + if (!TestSetPageLocked(backpage)) + unlock_page(backpage); + goto success; + + /* if the backing page is already present, it can be in one of + * three states: read in progress, read failed or read okay */ +backing_page_already_present: + _debug("- present"); + + if (newpage) { + page_cache_release(newpage); + newpage = NULL; + } + + if (PageError(backpage)) + goto io_error; + + if (PageUptodate(backpage)) + goto backing_page_already_uptodate; + + goto monitor_backing_page; + + /* the backing page is already up to date, attach the netfs + * page to the pagecache and LRU and copy the data across */ +backing_page_already_uptodate: + _debug("- uptodate"); + + copy_highpage(netpage, backpage); + end_io_func(netpage, context, 0); + +success: + _debug("success"); + ret = 0; + +out: + if (backpage) + page_cache_release(backpage); + if (monitor) { + fscache_put_context(object->fscache.cookie, monitor->context); + kfree(monitor); + } + + _leave(" = %d", ret); + return ret; + +read_error: + _debug("read error %d", ret); + if (ret == -ENOMEM) + goto out; +io_error: + cachefiles_io_error_obj(object, "page read error on backing file"); + ret = -EIO; + goto out; + +nomem_page: + page_cache_release(newpage); +nomem_monitor: + fscache_put_context(object->fscache.cookie, monitor->context); + kfree(monitor); +nomem: + _leave(" = -ENOMEM"); + return -ENOMEM; + +} + +/*****************************************************************************/ +/* + * read a page from the cache or allocate a block in which to store it + * - cache withdrawal is prevented by the caller + * - returns -EINTR if interrupted + * - returns -ENOMEM if ran out of memory + * - returns -ENOBUFS if no buffers can be made available + * - returns -ENOBUFS if page is beyond EOF + * - if the page is backed by a block in the cache: + * - a read will be started which will call the callback on completion + * - 0 will be returned + * - else if the page is unbacked: + * - the metadata will be retained + * - -ENODATA will be returned + */ +static int cachefiles_read_or_alloc_page(struct fscache_object *_object, + struct page *page, + fscache_rw_complete_t end_io_func, + void *context, + unsigned long gfp) +{ + struct cachefiles_object *object; + struct cachefiles_cache *cache; + struct fscache_cookie *cookie; + struct pagevec pagevec; + struct inode *inode; + sector_t block0, block; + unsigned shift; + int ret; + + object = container_of(_object, struct cachefiles_object, fscache); + cache = container_of(object->fscache.cache, struct cachefiles_cache, cache); + + _enter("{%p},{%lx},,,", object, page->index); + + if (!object->backer) + return -ENOBUFS; + + inode = object->backer->d_inode; + ASSERT(S_ISREG(inode->i_mode)); + ASSERT(inode->i_mapping->a_ops->bmap); + ASSERT(inode->i_mapping->a_ops->readpages); + + /* calculate the shift required to use bmap */ + if (inode->i_sb->s_blocksize > PAGE_SIZE) + return -ENOBUFS; + + shift = PAGE_SHIFT - inode->i_sb->s_blocksize_bits; + + cookie = object->fscache.cookie; + + pagevec_init(&pagevec, 0); + + /* we assume the absence or presence of the first block is a good + * enough indication for the page as a whole + * - TODO: don't use bmap() for this as it is _not_ actually good + * enough for this as it doesn't indicate errors, but it's all we've + * got for the moment + */ + block0 = page->index; + block0 <<= shift; + + block = inode->i_mapping->a_ops->bmap(inode->i_mapping, block0); + _debug("%llx -> %llx", block0, block); + + if (block) { + /* submit the apparently valid page to the backing fs to be + * read from disk */ + ret = cachefiles_read_backing_file_one(object, + end_io_func, + context, + page, + &pagevec); + ret = 0; + } else if (cachefiles_has_space(cache, 1) == 0) { + /* there's space in the cache we can use */ + pagevec_add(&pagevec, page); + cookie->def->mark_pages_cached(cookie->netfs_data, + page->mapping, &pagevec); + ret = -ENODATA; + } else { + ret = -ENOBUFS; + } + + _leave(" = %d", ret); + return ret; + +} + +/*****************************************************************************/ +/* + * read the corresponding pages to the given set from the backing file + * - any uncertain pages are simply discarded, to be tried again another time + */ +static int cachefiles_read_backing_file(struct cachefiles_object *object, + fscache_rw_complete_t end_io_func, + void *context, + struct address_space *mapping, + struct list_head *list, + struct pagevec *lru_pvec) +{ + struct cachefiles_one_read *monitor = NULL; + struct address_space *bmapping = object->backer->d_inode->i_mapping; + struct page *newpage = NULL, *netpage, *_n, *backpage = NULL; + int ret = 0; + + _enter(""); + + ASSERTCMP(pagevec_count(lru_pvec), ==, 0); + pagevec_reinit(lru_pvec); + + list_for_each_entry_safe(netpage, _n, list, lru) { + list_del(&netpage->lru); + + _debug("read back %p{%lu,%d}", + netpage, netpage->index, page_count(netpage)); + + if (!monitor) { + monitor = kzalloc(sizeof(*monitor), GFP_KERNEL); + if (!monitor) + goto nomem; + + monitor->object = object; + monitor->end_io_func = end_io_func; + monitor->context = fscache_get_context( + object->fscache.cookie, context); + + init_waitqueue_func_entry(&monitor->monitor, + cachefiles_read_waiter); + } + + for (;;) { + backpage = find_get_page(bmapping, netpage->index); + if (backpage) + goto backing_page_already_present; + + if (!newpage) { + newpage = page_cache_alloc_cold(bmapping); + if (!newpage) + goto nomem; + } + + ret = add_to_page_cache(newpage, bmapping, + netpage->index, GFP_KERNEL); + if (ret == 0) + goto installed_new_backing_page; + if (ret != -EEXIST) + goto nomem; + } + + /* we've installed a new backing page, so now we need to add it + * to the LRU list and start it reading */ + installed_new_backing_page: + _debug("- new %p", newpage); + + backpage = newpage; + newpage = NULL; + + page_cache_get(backpage); + if (!pagevec_add(lru_pvec, backpage)) + __pagevec_lru_add(lru_pvec); + + reread_backing_page: + ret = bmapping->a_ops->readpage(NULL, backpage); + if (ret < 0) + goto read_error; + + /* add the netfs page to the pagecache and LRU, and set the + * monitor to transfer the data across */ + monitor_backing_page: + _debug("- monitor add"); + + ret = add_to_page_cache(netpage, mapping, netpage->index, + GFP_KERNEL); + if (ret < 0) { + if (ret == -EEXIST) { + page_cache_release(netpage); + continue; + } + goto nomem; + } + + page_cache_get(netpage); + if (!pagevec_add(lru_pvec, netpage)) + __pagevec_lru_add(lru_pvec); + + /* install a monitor */ + page_cache_get(netpage); + monitor->netfs_page = netpage; + + page_cache_get(backpage); + monitor->back_page = backpage; + + spin_lock_irq(&object->work_lock); + list_add_tail(&monitor->obj_link, &object->read_pend_list); + spin_unlock_irq(&object->work_lock); + + monitor->monitor.private = backpage; + install_page_waitqueue_monitor(backpage, &monitor->monitor); + monitor = NULL; + + /* but the page may have been read before the monitor was + * installed, so the monitor may miss the event - so we have to + * ensure that we do get one in such a case */ + if (!TestSetPageLocked(backpage)) { + _debug("2unlock %p", backpage); + unlock_page(backpage); + } + + page_cache_release(backpage); + backpage = NULL; + + page_cache_release(netpage); + netpage = NULL; + continue; + + /* if the backing page is already present, it can be in one of + * three states: read in progress, read failed or read okay */ + backing_page_already_present: + _debug("- present %p", backpage); + + if (PageError(backpage)) + goto io_error; + + if (PageUptodate(backpage)) + goto backing_page_already_uptodate; + + _debug("- not ready %p{%lx}", backpage, backpage->flags); + + if (TestSetPageLocked(backpage)) + goto monitor_backing_page; + + if (PageError(backpage)) { + unlock_page(backpage); + goto io_error; + } + + if (PageUptodate(backpage)) + goto backing_page_already_uptodate_unlock; + + /* we've locked a page that's neither up to date nor erroneous, + * so we need to attempt to read it again */ + goto reread_backing_page; + + /* the backing page is already up to date, attach the netfs + * page to the pagecache and LRU and copy the data across */ + backing_page_already_uptodate_unlock: + unlock_page(backpage); + backing_page_already_uptodate: + _debug("- uptodate"); + + ret = add_to_page_cache(netpage, mapping, netpage->index, + GFP_KERNEL); + if (ret < 0) { + if (ret == -EEXIST) { + page_cache_release(netpage); + continue; + } + goto nomem; + } + + copy_highpage(netpage, backpage); + + page_cache_release(backpage); + backpage = NULL; + + page_cache_get(netpage); + if (!pagevec_add(lru_pvec, netpage)) + __pagevec_lru_add(lru_pvec); + + end_io_func(netpage, context, 0); + + page_cache_release(netpage); + netpage = NULL; + continue; + } + + netpage = NULL; + + _debug("out"); + +out: + /* tidy up */ + pagevec_lru_add(lru_pvec); + + if (newpage) + page_cache_release(newpage); + if (netpage) + page_cache_release(netpage); + if (backpage) + page_cache_release(backpage); + if (monitor) { + fscache_put_context(object->fscache.cookie, monitor->context); + kfree(monitor); + } + + list_for_each_entry_safe(netpage, _n, list, lru) { + list_del(&netpage->lru); + page_cache_release(netpage); + } + + _leave(" = %d", ret); + return ret; + +nomem: + _debug("nomem"); + ret = -ENOMEM; + goto out; + +read_error: + _debug("read error %d", ret); + if (ret == -ENOMEM) + goto out; +io_error: + cachefiles_io_error_obj(object, "page read error on backing file"); + ret = -EIO; + goto out; + +} + +/*****************************************************************************/ +/* + * read a list of pages from the cache or allocate blocks in which to store + * them + */ +static int cachefiles_read_or_alloc_pages(struct fscache_object *_object, + struct address_space *mapping, + struct list_head *pages, + unsigned *nr_pages, + fscache_rw_complete_t end_io_func, + void *context, + unsigned long gfp) +{ + struct cachefiles_object *object; + struct cachefiles_cache *cache; + struct fscache_cookie *cookie; + struct list_head backpages; + struct pagevec pagevec; + struct inode *inode; + struct page *page, *_n; + unsigned shift, nrbackpages; + int ret, ret2, space; + + object = container_of(_object, struct cachefiles_object, fscache); + cache = container_of(object->fscache.cache, struct cachefiles_cache, cache); + + _enter("{%p},,%d,,", object, *nr_pages); + + if (!object->backer) + return -ENOBUFS; + + space = 1; + if (cachefiles_has_space(cache, *nr_pages) < 0) + space = 0; + + inode = object->backer->d_inode; + ASSERT(S_ISREG(inode->i_mode)); + ASSERT(inode->i_mapping->a_ops->bmap); + ASSERT(inode->i_mapping->a_ops->readpages); + + /* calculate the shift required to use bmap */ + if (inode->i_sb->s_blocksize > PAGE_SIZE) + return -ENOBUFS; + + shift = PAGE_SHIFT - inode->i_sb->s_blocksize_bits; + + pagevec_init(&pagevec, 0); + + cookie = object->fscache.cookie; + + INIT_LIST_HEAD(&backpages); + nrbackpages = 0; + + ret = space ? -ENODATA : -ENOBUFS; + list_for_each_entry_safe(page, _n, pages, lru) { + sector_t block0, block; + + /* we assume the absence or presence of the first block is a + * good enough indication for the page as a whole + * - TODO: don't use bmap() for this as it is _not_ actually + * good enough for this as it doesn't indicate errors, but + * it's all we've got for the moment + */ + block0 = page->index; + block0 <<= shift; + + block = inode->i_mapping->a_ops->bmap(inode->i_mapping, + block0); + _debug("%llx -> %llx", block0, block); + + if (block) { + /* we have data - add it to the list to give to the + * backing fs */ + list_move(&page->lru, &backpages); + (*nr_pages)--; + nrbackpages++; + } else if (space && pagevec_add(&pagevec, page) == 0) { + cookie->def->mark_pages_cached(cookie->netfs_data, + mapping, &pagevec); + pagevec_reinit(&pagevec); + ret = -ENODATA; + } + } + + if (pagevec_count(&pagevec) > 0) { + cookie->def->mark_pages_cached(cookie->netfs_data, + mapping, &pagevec); + pagevec_reinit(&pagevec); + } + + if (list_empty(pages)) + ret = 0; + + /* submit the apparently valid pages to the backing fs to be read from disk */ + if (nrbackpages > 0) { + ret2 = cachefiles_read_backing_file(object, + end_io_func, + context, + mapping, + &backpages, + &pagevec); + + ASSERTCMP(pagevec_count(&pagevec), ==, 0); + + if (ret2 == -ENOMEM || ret2 == -EINTR) + ret = ret2; + } + + _leave(" = %d [nr=%u%s]", + ret, *nr_pages, list_empty(pages) ? " empty" : ""); + return ret; + +} + +/*****************************************************************************/ +/* + * read a page from the cache or allocate a block in which to store it + * - cache withdrawal is prevented by the caller + * - returns -EINTR if interrupted + * - returns -ENOMEM if ran out of memory + * - returns -ENOBUFS if no buffers can be made available + * - returns -ENOBUFS if page is beyond EOF + * - otherwise: + * - the metadata will be retained + * - 0 will be returned + */ +static int cachefiles_allocate_page(struct fscache_object *_object, + struct page *page, + unsigned long gfp) +{ + struct cachefiles_object *object; + struct cachefiles_cache *cache; + + object = container_of(_object, struct cachefiles_object, fscache); + cache = container_of(object->fscache.cache, + struct cachefiles_cache, cache); + + _enter("%p,{%lx},,,", object, page->index); + + return cachefiles_has_space(cache, 1); + +} + +/*****************************************************************************/ +/* + * page storer + */ +void cachefiles_write_work(void *_object) +{ + struct cachefiles_one_write *writer; + struct cachefiles_object *object = _object; + int ret, max; + + _enter("%p", object); + + ASSERT(!irqs_disabled()); + + spin_lock_irq(&object->work_lock); + max = 8; + + while (!list_empty(&object->write_list)) { + writer = list_entry(object->write_list.next, + struct cachefiles_one_write, obj_link); + list_del(&writer->obj_link); + + spin_unlock_irq(&object->work_lock); + + _debug("- store {%lu}", writer->netfs_page->index); + + ret = generic_file_buffered_write_one_kernel_page( + object->backer->d_inode->i_mapping, + writer->netfs_page->index, + writer->netfs_page); + + if (ret == -ENOSPC) { + ret = -ENOBUFS; + } else if (ret == -EIO) { + cachefiles_io_error_obj(object, + "write page to backing file" + " failed"); + ret = -ENOBUFS; + } + + _debug("- callback"); + writer->end_io_func(writer->netfs_page, + writer->context, + ret); + + _debug("- put net"); + page_cache_release(writer->netfs_page); + fscache_put_context(object->fscache.cookie, writer->context); + kfree(writer); + + /* let keventd have some air occasionally */ + max--; + if (max < 0 || need_resched()) { + if (!list_empty(&object->write_list)) + schedule_work(&object->write_work); + _leave(" [maxed out]"); + return; + } + + _debug("- next"); + spin_lock_irq(&object->work_lock); + } + + spin_unlock_irq(&object->work_lock); + _leave(""); + +} + +/*****************************************************************************/ +/* + * request a page be stored in the cache + * - cache withdrawal is prevented by the caller + * - this request may be ignored if there's no cache block available, in which + * case -ENOBUFS will be returned + * - if the op is in progress, 0 will be returned + */ +static int cachefiles_write_page(struct fscache_object *_object, + struct page *page, + fscache_rw_complete_t end_io_func, + void *context, + unsigned long gfp) +{ +// struct cachefiles_one_write *writer; + struct cachefiles_object *object; + int ret; + + object = container_of(_object, struct cachefiles_object, fscache); + + _enter("%p,%p{%lx},,,", object, page, page->index); + + if (!object->backer) + return -ENOBUFS; + + ASSERT(S_ISREG(object->backer->d_inode->i_mode)); + +#if 0 // set to 1 for deferred writing + /* queue the operation for deferred processing by keventd */ + writer = kzalloc(sizeof(*writer), GFP_KERNEL); + if (!writer) + return -ENOMEM; + + page_cache_get(page); + writer->netfs_page = page; + writer->object = object; + writer->end_io_func = end_io_func; + writer->context = facache_get_context(object->fscache.cookie, context); + + spin_lock_irq(&object->work_lock); + list_add_tail(&writer->obj_link, &object->write_list); + spin_unlock_irq(&object->work_lock); + + schedule_work(&object->write_work); + ret = 0; + +#else + /* copy the page to ext3 and let it store it in its own time */ + ret = generic_file_buffered_write_one_kernel_page( + object->backer->d_inode->i_mapping, page->index, page); + + if (ret != 0) { + if (ret == -EIO) + cachefiles_io_error_obj(object, + "write page to backing file" + " failed"); + ret = -ENOBUFS; + } + + end_io_func(page, context, ret); +#endif + + _leave(" = %d", ret); + return ret; + +} + +/*****************************************************************************/ +/* + * detach a backing block from a page + * - cache withdrawal is prevented by the caller + */ +static void cachefiles_uncache_pages(struct fscache_object *_object, + struct pagevec *pagevec) +{ + struct cachefiles_object *object; + struct cachefiles_cache *cache; + + object = container_of(_object, struct cachefiles_object, fscache); + cache = container_of(object->fscache.cache, + struct cachefiles_cache, cache); + + _enter("%p,{%lu,%lx},,,", + object, pagevec->nr, pagevec->pages[0]->index); + +} + +/*****************************************************************************/ +/* + * dissociate a cache from all the pages it was backing + */ +static void cachefiles_dissociate_pages(struct fscache_cache *cache) +{ + _enter(""); + +} + +struct fscache_cache_ops cachefiles_cache_ops = { + .name = "cachefiles", + .lookup_object = cachefiles_lookup_object, + .grab_object = cachefiles_grab_object, + .lock_object = cachefiles_lock_object, + .unlock_object = cachefiles_unlock_object, + .update_object = cachefiles_update_object, + .put_object = cachefiles_put_object, + .sync_cache = cachefiles_sync_cache, + .set_i_size = cachefiles_set_i_size, + .read_or_alloc_page = cachefiles_read_or_alloc_page, + .read_or_alloc_pages = cachefiles_read_or_alloc_pages, + .allocate_page = cachefiles_allocate_page, + .write_page = cachefiles_write_page, + .uncache_pages = cachefiles_uncache_pages, + .dissociate_pages = cachefiles_dissociate_pages, +}; diff --git a/fs/cachefiles/cf-key.c b/fs/cachefiles/cf-key.c new file mode 100644 index 000000000..cfae5a715 --- /dev/null +++ b/fs/cachefiles/cf-key.c @@ -0,0 +1,157 @@ +/* cf-key.c: Key to pathname encoder + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/slab.h> +#include "internal.h" + +static const char cachefiles_charmap[64] = + "0123456789" /* 0 - 9 */ + "abcdefghijklmnopqrstuvwxyz" /* 10 - 35 */ + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /* 36 - 61 */ + "_-" /* 62 - 63 */ + ; + +static const char cachefiles_filecharmap[256] = { + /* we skip space and tab and control chars */ + [ 33 ... 46 ] = 1, /* '!' -> '.' */ + /* we skip '/' as it's significant to pathwalk */ + [ 48 ... 127 ] = 1, /* '0' -> '~' */ +}; + +/*****************************************************************************/ +/* + * turn the raw key into something cooked + * - the raw key should include the length in the two bytes at the front + * - the key may be up to 514 bytes in length (including the length word) + * - "base64" encode the strange keys, mapping 3 bytes of raw to four of + * cooked + * - need to cut the cooked key into 252 char lengths (189 raw bytes) + */ +char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type) +{ + unsigned char csum, ch; + unsigned int acc; + char *key; + int loop, len, max, seg, mark, print; + + _enter(",%d", keylen); + + BUG_ON(keylen < 2 || keylen > 514); + + csum = raw[0] + raw[1]; + print = 1; + for (loop = 2; loop < keylen; loop++) { + ch = raw[loop]; + csum += ch; + print &= cachefiles_filecharmap[ch]; + } + + if (print) { + /* if the path is usable ASCII, then we render it directly */ + max = keylen - 2; + max += 2; /* two base64'd length chars on the front */ + max += 5; /* @checksum/M */ + max += 3 * 2; /* maximum number of segment dividers (".../M") + * is ((514 + 251) / 252) = 3 + */ + max += 1; /* NUL on end */ + } else { + /* calculate the maximum length of the cooked key */ + keylen = (keylen + 2) / 3; + + max = keylen * 4; + max += 5; /* @checksum/M */ + max += 3 * 2; /* maximum number of segment dividers (".../M") + * is ((514 + 188) / 189) = 3 + */ + max += 1; /* NUL on end */ + } + + _debug("max: %d", max); + + key = kmalloc(max, GFP_KERNEL); + if (!key) + return NULL; + + len = 0; + + /* build the cooked key */ + sprintf(key, "@%02x/+", (unsigned) csum); + len = 5; + mark = len - 1; + + if (print) { + acc = *(uint16_t *) raw; + raw += 2; + + key[len + 1] = cachefiles_charmap[acc & 63]; + acc >>= 6; + key[len] = cachefiles_charmap[acc & 63]; + len += 2; + + seg = 250; + for (loop = keylen; loop > 0; loop--) { + if (seg <= 0) { + key[len++] = '/'; + mark = len; + key[len++] = '+'; + seg = 252; + } + + key[len++] = *raw++; + ASSERT(len < max); + } + + switch (type) { + case FSCACHE_COOKIE_TYPE_INDEX: type = 'I'; break; + case FSCACHE_COOKIE_TYPE_DATAFILE: type = 'D'; break; + default: type = 'S'; break; + } + } else { + seg = 252; + for (loop = keylen; loop > 0; loop--) { + if (seg <= 0) { + key[len++] = '/'; + mark = len; + key[len++] = '+'; + seg = 252; + } + + acc = *raw++; + acc |= *raw++ << 8; + acc |= *raw++ << 16; + + _debug("acc: %06x", acc); + + key[len++] = cachefiles_charmap[acc & 63]; + acc >>= 6; + key[len++] = cachefiles_charmap[acc & 63]; + acc >>= 6; + key[len++] = cachefiles_charmap[acc & 63]; + acc >>= 6; + key[len++] = cachefiles_charmap[acc & 63]; + + ASSERT(len < max); + } + + switch (type) { + case FSCACHE_COOKIE_TYPE_INDEX: type = 'J'; break; + case FSCACHE_COOKIE_TYPE_DATAFILE: type = 'E'; break; + default: type = 'T'; break; + } + } + + key[mark] = type; + key[len] = 0; + + _leave(" = %p %d:[%s]", key, len, key); + return key; +} diff --git a/fs/cachefiles/cf-main.c b/fs/cachefiles/cf-main.c new file mode 100644 index 000000000..da8d02010 --- /dev/null +++ b/fs/cachefiles/cf-main.c @@ -0,0 +1,129 @@ +/* cf-main.c: network filesystem caching backend to use cache files on a + * premounted filesystem + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/completion.h> +#include <linux/slab.h> +#include <linux/fs.h> +#include <linux/file.h> +#include <linux/namei.h> +#include <linux/mount.h> +#include <linux/statfs.h> +#include <linux/proc_fs.h> +#include <linux/sysctl.h> +#include "internal.h" + +unsigned long cachefiles_debug; + +static int cachefiles_init(void); +static void cachefiles_exit(void); + +fs_initcall(cachefiles_init); +module_exit(cachefiles_exit); + +MODULE_DESCRIPTION("Mounted-filesystem based cache"); +MODULE_AUTHOR("Red Hat, Inc."); +MODULE_LICENSE("GPL"); + +kmem_cache_t *cachefiles_object_jar; + +static void cachefiles_object_init_once(void *_object, kmem_cache_t *cachep, + unsigned long flags) +{ + struct cachefiles_object *object = _object; + + switch (flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) { + case SLAB_CTOR_CONSTRUCTOR: + memset(object, 0, sizeof(*object)); + fscache_object_init(&object->fscache); + init_rwsem(&object->sem); + spin_lock_init(&object->work_lock); + INIT_LIST_HEAD(&object->read_list); + INIT_LIST_HEAD(&object->read_pend_list); + INIT_WORK(&object->read_work, &cachefiles_read_copier_work, + object); + INIT_LIST_HEAD(&object->write_list); + INIT_WORK(&object->write_work, &cachefiles_write_work, object); + break; + + default: + break; + } +} + +/*****************************************************************************/ +/* + * initialise the fs caching module + */ +static int __init cachefiles_init(void) +{ + struct proc_dir_entry *pde; + int ret; + + /* create a proc entry to use as a handle for the userspace daemon */ + ret = -ENOMEM; + + pde = create_proc_entry("cachefiles", 0600, proc_root_fs); + if (!pde) { + kerror("Unable to create /proc/fs/cachefiles"); + goto error_proc; + } + + if (cachefiles_sysctl_init() < 0) { + kerror("Unable to create sysctl parameters"); + goto error_object_jar; + } + + pde->owner = THIS_MODULE; + pde->proc_fops = &cachefiles_proc_fops; + cachefiles_proc = pde; + + /* create an object jar */ + cachefiles_object_jar = + kmem_cache_create("cachefiles_object_jar", + sizeof(struct cachefiles_object), + 0, + SLAB_HWCACHE_ALIGN, + cachefiles_object_init_once, + NULL); + if (!cachefiles_object_jar) { + printk(KERN_NOTICE + "CacheFiles: Failed to allocate an object jar\n"); + goto error_sysctl; + } + + printk(KERN_INFO "CacheFiles: Loaded\n"); + return 0; + +error_sysctl: + cachefiles_sysctl_cleanup(); +error_object_jar: + remove_proc_entry("cachefiles", proc_root_fs); +error_proc: + kerror("failed to register: %d", ret); + return ret; +} + +/*****************************************************************************/ +/* + * clean up on module removal + */ +static void __exit cachefiles_exit(void) +{ + printk(KERN_INFO "CacheFiles: Unloading\n"); + + kmem_cache_destroy(cachefiles_object_jar); + remove_proc_entry("cachefiles", proc_root_fs); + cachefiles_sysctl_cleanup(); +} diff --git a/fs/cachefiles/cf-namei.c b/fs/cachefiles/cf-namei.c new file mode 100644 index 000000000..20db88ada --- /dev/null +++ b/fs/cachefiles/cf-namei.c @@ -0,0 +1,825 @@ +/* cf-namei.c: CacheFiles path walking and related routines + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/file.h> +#include <linux/fs.h> +#include <linux/fsnotify.h> +#include <linux/quotaops.h> +#include <linux/xattr.h> +#include <linux/mount.h> +#include <linux/namei.h> +#include "internal.h" + +/*****************************************************************************/ +/* + * record the fact that an object is now active + */ +static void cachefiles_mark_object_active(struct cachefiles_cache *cache, + struct cachefiles_object *object) +{ + struct cachefiles_object *xobject; + struct rb_node **_p, *_parent = NULL; + struct dentry *dentry; + + write_lock(&cache->active_lock); + + dentry = object->dentry; + _p = &cache->active_nodes.rb_node; + while (*_p) { + _parent = *_p; + xobject = rb_entry(_parent, + struct cachefiles_object, active_node); + + if (xobject->dentry > dentry) + _p = &(*_p)->rb_left; + else if (xobject->dentry < dentry) + _p = &(*_p)->rb_right; + else + BUG(); /* uh oh... this dentry shouldn't be here */ + } + + rb_link_node(&object->active_node, _parent, _p); + rb_insert_color(&object->active_node, &cache->active_nodes); + + write_unlock(&cache->active_lock); +} + +/*****************************************************************************/ +/* + * delete an object representation from the cache + * - file backed objects are unlinked + * - directory backed objects are stuffed into the graveyard for userspace to + * delete + * - unlocks the directory mutex + */ +static int cachefiles_bury_object(struct cachefiles_cache *cache, + struct dentry *dir, + struct dentry *rep) +{ + struct dentry *grave, *alt, *trap; + struct qstr name; + const char *old_name; + char nbuffer[8 + 8 + 1]; + int ret; + + _enter(",'%*.*s','%*.*s'", + dir->d_name.len, dir->d_name.len, dir->d_name.name, + rep->d_name.len, rep->d_name.len, rep->d_name.name); + + /* non-directories can just be unlinked */ + if (!S_ISDIR(rep->d_inode->i_mode)) { + _debug("unlink stale object"); + ret = dir->d_inode->i_op->unlink(dir->d_inode, rep); + + mutex_unlock(&dir->d_inode->i_mutex); + + if (ret == 0) { + _debug("d_delete"); + d_delete(rep); + } else if (ret == -EIO) { + cachefiles_io_error(cache, "Unlink failed"); + } + + _leave(" = %d", ret); + return ret; + } + + /* directories have to be moved to the graveyard */ + _debug("move stale object to graveyard"); + mutex_unlock(&dir->d_inode->i_mutex); + +try_again: + /* first step is to make up a grave dentry in the graveyard */ + sprintf(nbuffer, "%08x%08x", + (uint32_t) xtime.tv_sec, + (uint32_t) atomic_inc_return(&cache->gravecounter)); + + name.name = nbuffer; + name.len = strlen(name.name); + + /* hash the name */ + name.hash = full_name_hash(name.name, name.len); + + if (dir->d_op && dir->d_op->d_hash) { + ret = dir->d_op->d_hash(dir, &name); + if (ret < 0) { + if (ret == -EIO) + cachefiles_io_error(cache, "Hash failed"); + + _leave(" = %d", ret); + return ret; + } + } + + /* do the multiway lock magic */ + trap = lock_rename(cache->graveyard, dir); + + /* do some checks before getting the grave dentry */ + if (rep->d_parent != dir) { + /* the entry was probably culled when we dropped the parent dir + * lock */ + unlock_rename(cache->graveyard, dir); + _leave(" = 0 [culled?]"); + return 0; + } + + if (!S_ISDIR(cache->graveyard->d_inode->i_mode)) { + unlock_rename(cache->graveyard, dir); + cachefiles_io_error(cache, "Graveyard no longer a directory"); + return -EIO; + } + + if (trap == rep) { + unlock_rename(cache->graveyard, dir); + cachefiles_io_error(cache, "May not make directory loop"); + return -EIO; + } + + if (d_mountpoint(rep)) { + unlock_rename(cache->graveyard, dir); + cachefiles_io_error(cache, "Mountpoint in cache"); + return -EIO; + } + + /* see if there's a dentry already there for this name */ + grave = d_lookup(cache->graveyard, &name); + if (!grave) { + _debug("not found"); + + grave = d_alloc(cache->graveyard, &name); + if (!grave) { + unlock_rename(cache->graveyard, dir); + _leave(" = -ENOMEM"); + return -ENOMEM; + } + + alt = cache->graveyard->d_inode->i_op->lookup( + cache->graveyard->d_inode, grave, NULL); + if (IS_ERR(alt)) { + unlock_rename(cache->graveyard, dir); + dput(grave); + + if (PTR_ERR(alt) == -ENOMEM) { + _leave(" = -ENOMEM"); + return -ENOMEM; + } + + cachefiles_io_error(cache, "Lookup error %ld", + PTR_ERR(alt)); + return -EIO; + } + + if (alt) { + dput(grave); + grave = alt; + } + } + + if (grave->d_inode) { + unlock_rename(cache->graveyard, dir); + dput(grave); + grave = NULL; + cond_resched(); + goto try_again; + } + + if (d_mountpoint(grave)) { + unlock_rename(cache->graveyard, dir); + dput(grave); + cachefiles_io_error(cache, "Mountpoint in graveyard"); + return -EIO; + } + + /* target should not be an ancestor of source */ + if (trap == grave) { + unlock_rename(cache->graveyard, dir); + dput(grave); + cachefiles_io_error(cache, "May not make directory loop"); + return -EIO; + } + + /* attempt the rename */ + DQUOT_INIT(dir->d_inode); + DQUOT_INIT(cache->graveyard->d_inode); + + old_name = fsnotify_oldname_init(rep->d_name.name); + + ret = dir->d_inode->i_op->rename(dir->d_inode, rep, + cache->graveyard->d_inode, grave); + + if (ret == 0) { + d_move(rep, grave); + fsnotify_move(dir->d_inode, cache->graveyard->d_inode, + old_name, rep->d_name.name, 1, + grave->d_inode, rep->d_inode); + } else if (ret != -ENOMEM) { + cachefiles_io_error(cache, "Rename failed with error %d", ret); + } + + fsnotify_oldname_free(old_name); + + unlock_rename(cache->graveyard, dir); + dput(grave); + _leave(" = 0"); + return 0; +} + +/*****************************************************************************/ +/* + * delete an object representation from the cache + */ +int cachefiles_delete_object(struct cachefiles_cache *cache, + struct cachefiles_object *object) +{ + struct dentry *dir; + int ret; + + _enter(",{%p}", object->dentry); + + ASSERT(object->dentry); + ASSERT(object->dentry->d_inode); + ASSERT(object->dentry->d_parent); + + dir = dget_parent(object->dentry); + + mutex_lock(&dir->d_inode->i_mutex); + ret = cachefiles_bury_object(cache, dir, object->dentry); + + dput(dir); + _leave(" = %d", ret); + return ret; +} + +/*****************************************************************************/ +/* + * walk from the parent object to the child object through the backing + * filesystem, creating directories as we go + */ +int cachefiles_walk_to_object(struct cachefiles_object *parent, + struct cachefiles_object *object, + char *key, + struct cachefiles_xattr *auxdata) +{ + struct cachefiles_cache *cache; + struct dentry *dir, *next = NULL, *new; + struct qstr name; + uid_t fsuid; + gid_t fsgid; + int ret; + + _enter("{%p}", parent->dentry); + + cache = container_of(parent->fscache.cache, + struct cachefiles_cache, cache); + + ASSERT(parent->dentry); + ASSERT(parent->dentry->d_inode); + + if (!(S_ISDIR(parent->dentry->d_inode->i_mode))) { + // TODO: convert file to dir + _leave("looking up in none directory"); + return -ENOBUFS; + } + + fsuid = current->fsuid; + fsgid = current->fsgid; + current->fsuid = 0; + current->fsgid = 0; + + dir = dget(parent->dentry); + +advance: + /* attempt to transit the first directory component */ + name.name = key; + key = strchr(key, '/'); + if (key) { + name.len = key - (char *) name.name; + *key++ = 0; + } else { + name.len = strlen(name.name); + } + + /* hash the name */ + name.hash = full_name_hash(name.name, name.len); + + if (dir->d_op && dir->d_op->d_hash) { + ret = dir->d_op->d_hash(dir, &name); + if (ret < 0) { + cachefiles_io_error(cache, "Hash failed"); + goto error_out2; + } + } + +lookup_again: + /* search the current directory for the element name */ + _debug("lookup '%s' %x", name.name, name.hash); + + mutex_lock(&dir->d_inode->i_mutex); + + next = d_lookup(dir, &name); + if (!next) { + _debug("not found"); + + new = d_alloc(dir, &name); + if (!new) + goto nomem_d_alloc; + + ASSERT(dir->d_inode->i_op); + ASSERT(dir->d_inode->i_op->lookup); + + next = dir->d_inode->i_op->lookup(dir->d_inode, new, NULL); + if (IS_ERR(next)) + goto lookup_error; + + if (!next) + next = new; + else + dput(new); + + if (next->d_inode) { + ret = -EPERM; + if (!next->d_inode->i_op || + !next->d_inode->i_op->setxattr || + !next->d_inode->i_op->getxattr || + !next->d_inode->i_op->removexattr) + goto error; + + if (key && (!next->d_inode->i_op->lookup || + !next->d_inode->i_op->mkdir || + !next->d_inode->i_op->create || + !next->d_inode->i_op->rename || + !next->d_inode->i_op->rmdir || + !next->d_inode->i_op->unlink)) + goto error; + } + } + + _debug("next -> %p %s", next, next->d_inode ? "positive" : "negative"); + + if (!key) + object->new = !next->d_inode; + + /* we need to create the object if it's negative */ + if (key || object->type == FSCACHE_COOKIE_TYPE_INDEX) { + /* index objects and intervening tree levels must be subdirs */ + if (!next->d_inode) { + DQUOT_INIT(dir->d_inode); + ret = dir->d_inode->i_op->mkdir(dir->d_inode, next, 0); + if (ret < 0) + goto create_error; + + ASSERT(next->d_inode); + + fsnotify_mkdir(dir->d_inode, next); + + _debug("mkdir -> %p{%p{ino=%lu}}", + next, next->d_inode, next->d_inode->i_ino); + + } else if (!S_ISDIR(next->d_inode->i_mode)) { + kerror("inode %lu is not a directory", + next->d_inode->i_ino); + ret = -ENOBUFS; + goto error; + } + + } else { + /* non-index objects start out life as files */ + if (!next->d_inode) { + DQUOT_INIT(dir->d_inode); + ret = dir->d_inode->i_op->create(dir->d_inode, next, + S_IFREG, NULL); + if (ret < 0) + goto create_error; + + ASSERT(next->d_inode); + + fsnotify_create(dir->d_inode, next); + + _debug("create -> %p{%p{ino=%lu}}", + next, next->d_inode, next->d_inode->i_ino); + + } else if (!S_ISDIR(next->d_inode->i_mode) && + !S_ISREG(next->d_inode->i_mode) + ) { + kerror("inode %lu is not a file or directory", + next->d_inode->i_ino); + ret = -ENOBUFS; + goto error; + } + } + + /* process the next component */ + if (key) { + _debug("advance"); + mutex_unlock(&dir->d_inode->i_mutex); + dput(dir); + dir = next; + next = NULL; + goto advance; + } + + /* we've found the object we were looking for */ + object->dentry = next; + + /* if we've found that the terminal object exists, then we need to + * check its attributes and delete it if it's out of date */ + if (!object->new) { + _debug("validate '%*.*s'", + next->d_name.len, next->d_name.len, next->d_name.name); + + ret = cachefiles_check_object_xattr(object, auxdata); + if (ret == -ESTALE) { + /* delete the object (the deleter drops the directory + * mutex) */ + object->dentry = NULL; + + ret = cachefiles_bury_object(cache, dir, next); + dput(next); + next = NULL; + + if (ret < 0) + goto delete_error; + + _debug("redo lookup"); + goto lookup_again; + } + } + + /* note that we're now using this object */ + cachefiles_mark_object_active(cache, object); + + mutex_unlock(&dir->d_inode->i_mutex); + dput(dir); + dir = NULL; + + if (object->new) { + /* attach data to a newly constructed terminal object */ + ret = cachefiles_set_object_xattr(object, auxdata); + if (ret < 0) + goto check_error; + } else { + /* always update the atime on an object we've just looked up + * (this is used to keep track of culling, and atimes are only + * updated by read, write and readdir but not lookup or + * open) */ + touch_atime(cache->mnt, next); + } + + /* open a file interface onto a data file */ + if (object->type != FSCACHE_COOKIE_TYPE_INDEX) { + if (S_ISREG(object->dentry->d_inode->i_mode)) { + const struct address_space_operations *aops; + + ret = -EPERM; + aops = object->dentry->d_inode->i_mapping->a_ops; + if (!aops->bmap || + !aops->prepare_write || + !aops->commit_write) + goto check_error; + + object->backer = object->dentry; + } else { + BUG(); // TODO: open file in data-class subdir + } + } + + current->fsuid = fsuid; + current->fsgid = fsgid; + object->new = 0; + + _leave(" = 0 [%lu]", object->dentry->d_inode->i_ino); + return 0; + +create_error: + if (ret == -EIO) + cachefiles_io_error(cache, "create/mkdir failed"); + goto error; + +check_error: + write_lock(&cache->active_lock); + rb_erase(&object->active_node, &cache->active_nodes); + write_unlock(&cache->active_lock); + + dput(object->dentry); + object->dentry = NULL; + goto error_out; + +delete_error: + _debug("delete error %d", ret); + goto error_out2; + +lookup_error: + _debug("lookup error %ld", PTR_ERR(next)); + dput(new); + ret = PTR_ERR(next); + if (ret == -EIO) + cachefiles_io_error(cache, "Lookup failed"); + next = NULL; + goto error; + +nomem_d_alloc: + ret = -ENOMEM; +error: + mutex_unlock(&dir->d_inode->i_mutex); + dput(next); +error_out2: + dput(dir); +error_out: + current->fsuid = fsuid; + current->fsgid = fsgid; + + _leave(" = ret"); + return ret; +} + +/*****************************************************************************/ +/* + * get a subdirectory + */ +struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, + struct dentry *dir, + const char *dirname) +{ + struct dentry *subdir, *new; + struct qstr name; + uid_t fsuid; + gid_t fsgid; + int ret; + + _enter(""); + + /* set up the name */ + name.name = dirname; + name.len = strlen(dirname); + name.hash = full_name_hash(name.name, name.len); + + if (dir->d_op && dir->d_op->d_hash) { + ret = dir->d_op->d_hash(dir, &name); + if (ret < 0) { + if (ret == -EIO) + kerror("Hash failed"); + _leave(" = %d", ret); + return ERR_PTR(ret); + } + } + + /* search the current directory for the element name */ + _debug("lookup '%s' %x", name.name, name.hash); + + fsuid = current->fsuid; + fsgid = current->fsgid; + current->fsuid = 0; + current->fsgid = 0; + + mutex_lock(&dir->d_inode->i_mutex); + + subdir = d_lookup(dir, &name); + if (!subdir) { + _debug("not found"); + + new = d_alloc(dir, &name); + if (!new) + goto nomem_d_alloc; + + subdir = dir->d_inode->i_op->lookup(dir->d_inode, new, NULL); + if (IS_ERR(subdir)) + goto lookup_error; + + if (!subdir) + subdir = new; + else + dput(new); + } + + _debug("subdir -> %p %s", + subdir, subdir->d_inode ? "positive" : "negative"); + + /* we need to create the subdir if it doesn't exist yet */ + if (!subdir->d_inode) { + DQUOT_INIT(dir->d_inode); + ret = dir->d_inode->i_op->mkdir(dir->d_inode, subdir, 0700); + if (ret < 0) + goto mkdir_error; + + ASSERT(subdir->d_inode); + + fsnotify_mkdir(dir->d_inode, subdir); + + _debug("mkdir -> %p{%p{ino=%lu}}", + subdir, + subdir->d_inode, + subdir->d_inode->i_ino); + } + + mutex_unlock(&dir->d_inode->i_mutex); + + current->fsuid = fsuid; + current->fsgid = fsgid; + + /* we need to make sure the subdir is a directory */ + ASSERT(subdir->d_inode); + + if (!S_ISDIR(subdir->d_inode->i_mode)) { + kerror("%s is not a directory", dirname); + ret = -EIO; + goto check_error; + } + + ret = -EPERM; + if (!subdir->d_inode->i_op || + !subdir->d_inode->i_op->setxattr || + !subdir->d_inode->i_op->getxattr || + !subdir->d_inode->i_op->lookup || + !subdir->d_inode->i_op->mkdir || + !subdir->d_inode->i_op->create || + !subdir->d_inode->i_op->rename || + !subdir->d_inode->i_op->rmdir || + !subdir->d_inode->i_op->unlink) + goto check_error; + + _leave(" = [%lu]", subdir->d_inode->i_ino); + return subdir; + +check_error: + dput(subdir); + _leave(" = %d [check]", ret); + return ERR_PTR(ret); + +mkdir_error: + mutex_unlock(&dir->d_inode->i_mutex); + kerror("mkdir %s failed with error %d", dirname, ret); + goto error_out; + +lookup_error: + mutex_unlock(&dir->d_inode->i_mutex); + dput(new); + ret = PTR_ERR(subdir); + kerror("Lookup %s failed with error %d", dirname, ret); + goto error_out; + +nomem_d_alloc: + mutex_unlock(&dir->d_inode->i_mutex); + ret = -ENOMEM; + goto error_out; + +error_out: + current->fsuid = fsuid; + current->fsgid = fsgid; + _leave(" = %d", ret); + return ERR_PTR(ret); +} + +/*****************************************************************************/ +/* + * cull an object if it's not in use + * - called only by cache manager daemon + */ +int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir, + char *filename) +{ + struct cachefiles_object *object; + struct rb_node *_n; + struct dentry *victim, *new; + struct qstr name; + int ret; + + _enter(",%*.*s/,%s", + dir->d_name.len, dir->d_name.len, dir->d_name.name, filename); + + /* set up the name */ + name.name = filename; + name.len = strlen(filename); + name.hash = full_name_hash(name.name, name.len); + + if (dir->d_op && dir->d_op->d_hash) { + ret = dir->d_op->d_hash(dir, &name); + if (ret < 0) { + if (ret == -EIO) + cachefiles_io_error(cache, "Hash failed"); + _leave(" = %d", ret); + return ret; + } + } + + /* look up the victim */ + mutex_lock(&dir->d_inode->i_mutex); + + victim = d_lookup(dir, &name); + if (!victim) { + _debug("not found"); + + new = d_alloc(dir, &name); + if (!new) + goto nomem_d_alloc; + + victim = dir->d_inode->i_op->lookup(dir->d_inode, new, NULL); + if (IS_ERR(victim)) + goto lookup_error; + + if (!victim) + victim = new; + else + dput(new); + } + + _debug("victim -> %p %s", + victim, victim->d_inode ? "positive" : "negative"); + + /* if the object is no longer there then we probably retired the object + * at the netfs's request whilst the cull was in progress + */ + if (!victim->d_inode) { + mutex_unlock(&dir->d_inode->i_mutex); + dput(victim); + _leave(" = -ENOENT [absent]"); + return -ENOENT; + } + + /* check to see if we're using this object */ + read_lock(&cache->active_lock); + + _n = cache->active_nodes.rb_node; + + while (_n) { + object = rb_entry(_n, struct cachefiles_object, active_node); + + if (object->dentry > victim) + _n = _n->rb_left; + else if (object->dentry < victim) + _n = _n->rb_right; + else + goto object_in_use; + } + + read_unlock(&cache->active_lock); + + /* okay... the victim is not being used so we can cull it + * - start by marking it as stale + */ + _debug("victim is cullable"); + + ret = cachefiles_remove_object_xattr(cache, victim); + if (ret < 0) + goto error_unlock; + + /* actually remove the victim (drops the dir mutex) */ + _debug("bury"); + + ret = cachefiles_bury_object(cache, dir, victim); + if (ret < 0) + goto error; + + dput(victim); + _leave(" = 0"); + return 0; + + +object_in_use: + read_unlock(&cache->active_lock); + mutex_unlock(&dir->d_inode->i_mutex); + dput(victim); + _leave(" = -EBUSY [in use]"); + return -EBUSY; + +nomem_d_alloc: + mutex_unlock(&dir->d_inode->i_mutex); + _leave(" = -ENOMEM"); + return -ENOMEM; + +lookup_error: + mutex_unlock(&dir->d_inode->i_mutex); + dput(new); + ret = PTR_ERR(victim); + if (ret == -EIO) + cachefiles_io_error(cache, "Lookup failed"); + goto choose_error; + +error_unlock: + mutex_unlock(&dir->d_inode->i_mutex); +error: + dput(victim); +choose_error: + if (ret == -ENOENT) { + /* file or dir now absent - probably retired by netfs */ + _leave(" = -ESTALE [absent]"); + return -ESTALE; + } + + if (ret != -ENOMEM) { + kerror("Internal error: %d", ret); + ret = -EIO; + } + + _leave(" = %d", ret); + return ret; +} diff --git a/fs/cachefiles/cf-proc.c b/fs/cachefiles/cf-proc.c new file mode 100644 index 000000000..c14320e0a --- /dev/null +++ b/fs/cachefiles/cf-proc.c @@ -0,0 +1,498 @@ +/* cf-proc.c: /proc/fs/cachefiles interface + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/completion.h> +#include <linux/slab.h> +#include <linux/fs.h> +#include <linux/file.h> +#include <linux/namei.h> +#include <linux/mount.h> +#include <linux/namespace.h> +#include <linux/statfs.h> +#include <linux/proc_fs.h> +#include <linux/ctype.h> +#include "internal.h" + +static int cachefiles_proc_open(struct inode *, struct file *); +static int cachefiles_proc_release(struct inode *, struct file *); +static ssize_t cachefiles_proc_read(struct file *, char __user *, size_t, loff_t *); +static ssize_t cachefiles_proc_write(struct file *, const char __user *, size_t, loff_t *); +static int cachefiles_proc_brun(struct cachefiles_cache *cache, char *args); +static int cachefiles_proc_bcull(struct cachefiles_cache *cache, char *args); +static int cachefiles_proc_bstop(struct cachefiles_cache *cache, char *args); +static int cachefiles_proc_cull(struct cachefiles_cache *cache, char *args); +static int cachefiles_proc_debug(struct cachefiles_cache *cache, char *args); +static int cachefiles_proc_dir(struct cachefiles_cache *cache, char *args); +static int cachefiles_proc_tag(struct cachefiles_cache *cache, char *args); + +struct proc_dir_entry *cachefiles_proc; + +static unsigned long cachefiles_open; + +struct file_operations cachefiles_proc_fops = { + .open = cachefiles_proc_open, + .release = cachefiles_proc_release, + .read = cachefiles_proc_read, + .write = cachefiles_proc_write, +}; + +struct cachefiles_proc_cmd { + char name[8]; + int (*handler)(struct cachefiles_cache *cache, char *args); +}; + +static const struct cachefiles_proc_cmd cachefiles_proc_cmds[] = { + { "bind", cachefiles_proc_bind }, + { "brun", cachefiles_proc_brun }, + { "bcull", cachefiles_proc_bcull }, + { "bstop", cachefiles_proc_bstop }, + { "cull", cachefiles_proc_cull }, + { "debug", cachefiles_proc_debug }, + { "dir", cachefiles_proc_dir }, + { "tag", cachefiles_proc_tag }, + { "", NULL } +}; + + +/*****************************************************************************/ +/* + * do various checks + */ +static int cachefiles_proc_open(struct inode *inode, struct file *file) +{ + struct cachefiles_cache *cache; + + _enter(""); + + /* only the superuser may do this */ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + /* /proc/fs/cachefiles may only be open once at a time */ + if (xchg(&cachefiles_open, 1) == 1) + return -EBUSY; + + /* allocate a cache record */ + cache = kzalloc(sizeof(struct cachefiles_cache), GFP_KERNEL); + if (!cache) { + cachefiles_open = 0; + return -ENOMEM; + } + + cache->active_nodes = RB_ROOT; + rwlock_init(&cache->active_lock); + + /* set default caching limits + * - limit at 1% free space + * - cull below 5% free space + * - cease culling above 7% free space + */ + cache->brun_percent = 7; + cache->bcull_percent = 5; + cache->bstop_percent = 1; + + file->private_data = cache; + cache->cachefilesd = file; + return 0; +} + +/*****************************************************************************/ +/* + * release a cache + */ +static int cachefiles_proc_release(struct inode *inode, struct file *file) +{ + struct cachefiles_cache *cache = file->private_data; + + _enter(""); + + ASSERT(cache); + + set_bit(CACHEFILES_DEAD, &cache->flags); + + cachefiles_proc_unbind(cache); + + ASSERT(!cache->active_nodes.rb_node); + + /* clean up the control file interface */ + cache->cachefilesd = NULL; + file->private_data = NULL; + cachefiles_open = 0; + + kfree(cache); + + _leave(""); + return 0; +} + +/*****************************************************************************/ +/* + * read the cache state + */ +static ssize_t cachefiles_proc_read(struct file *file, char __user *_buffer, + size_t buflen, loff_t *pos) +{ + struct cachefiles_cache *cache = file->private_data; + char buffer[256]; + int n; + + _enter(",,%zu,", buflen); + + if (!test_bit(CACHEFILES_READY, &cache->flags)) + return 0; + + /* check how much space the cache has */ + cachefiles_has_space(cache, 0); + + /* summarise */ + n = snprintf(buffer, sizeof(buffer), + "cull=%c" + " brun=%llx" + " bcull=%llx" + " bstop=%llx", + test_bit(CACHEFILES_CULLING, &cache->flags) ? '1' : '0', + cache->brun, + cache->bcull, + cache->bstop + ); + + if (n > buflen) + return -EMSGSIZE; + + if (copy_to_user(_buffer, buffer, n) != 0) + return -EFAULT; + + return n; +} + +/*****************************************************************************/ +/* + * command the cache + */ +static ssize_t cachefiles_proc_write(struct file *file, + const char __user *_data, size_t datalen, + loff_t *pos) +{ + const struct cachefiles_proc_cmd *cmd; + struct cachefiles_cache *cache = file->private_data; + ssize_t ret; + char *data, *args, *cp; + + _enter(",,%zu,", datalen); + + ASSERT(cache); + + if (test_bit(CACHEFILES_DEAD, &cache->flags)) + return -EIO; + + if (datalen < 0 || datalen > PAGE_SIZE - 1) + return -EOPNOTSUPP; + + /* drag the command string into the kernel so we can parse it */ + data = kmalloc(datalen + 1, GFP_KERNEL); + if (!data) + return -ENOMEM; + + ret = -EFAULT; + if (copy_from_user(data, _data, datalen) != 0) + goto error; + + data[datalen] = '\0'; + + ret = -EINVAL; + if (memchr(data, '\0', datalen)) + goto error; + + /* strip any newline */ + cp = memchr(data, '\n', datalen); + if (cp) { + if (cp == data) + goto error; + + *cp = '\0'; + } + + /* parse the command */ + ret = -EOPNOTSUPP; + + for (args = data; *args; args++) + if (isspace(*args)) + break; + if (*args) { + if (args == data) + goto error; + *args = '\0'; + for (args++; isspace(*args); args++) + continue; + } + + /* run the appropriate command handler */ + for (cmd = cachefiles_proc_cmds; cmd->name[0]; cmd++) + if (strcmp(cmd->name, data) == 0) + goto found_command; + +error: + kfree(data); + _leave(" = %d", ret); + return ret; + +found_command: + mutex_lock(&file->f_dentry->d_inode->i_mutex); + + ret = -EIO; + if (!test_bit(CACHEFILES_DEAD, &cache->flags)) + ret = cmd->handler(cache, args); + + mutex_unlock(&file->f_dentry->d_inode->i_mutex); + + if (ret == 0) + ret = datalen; + goto error; +} + +/*****************************************************************************/ +/* + * give a range error for cache space constraints + * - can be tail-called + */ +static int cachefiles_proc_range_error(struct cachefiles_cache *cache, char *args) +{ + kerror("Free space limits must be in range" + " 0%%<=bstop<bcull<brun<100%%"); + + return -EINVAL; +} + +/*****************************************************************************/ +/* + * set the percentage of blocks at which to stop culling + * - command: "brun <N>%" + */ +static int cachefiles_proc_brun(struct cachefiles_cache *cache, char *args) +{ + unsigned long brun; + + _enter(",%s", args); + + if (!*args) + return -EINVAL; + + brun = simple_strtoul(args, &args, 10); + if (args[0] != '%' || args[1] != '\0') + return -EINVAL; + + if (brun <= cache->bcull_percent || brun >= 100) + return cachefiles_proc_range_error(cache, args); + + cache->brun_percent = brun; + return 0; +} + +/*****************************************************************************/ +/* + * set the percentage of blocks at which to start culling + * - command: "bcull <N>%" + */ +static int cachefiles_proc_bcull(struct cachefiles_cache *cache, char *args) +{ + unsigned long bcull; + + _enter(",%s", args); + + if (!*args) + return -EINVAL; + + bcull = simple_strtoul(args, &args, 10); + if (args[0] != '%' || args[1] != '\0') + return -EINVAL; + + if (bcull <= cache->bstop_percent || bcull >= cache->brun_percent) + return cachefiles_proc_range_error(cache, args); + + cache->bcull_percent = bcull; + return 0; +} + +/*****************************************************************************/ +/* + * set the percentage of blocks at which to stop allocating + * - command: "bstop <N>%" + */ +static int cachefiles_proc_bstop(struct cachefiles_cache *cache, char *args) +{ + unsigned long bstop; + + _enter(",%s", args); + + if (!*args) + return -EINVAL; + + bstop = simple_strtoul(args, &args, 10); + if (args[0] != '%' || args[1] != '\0') + return -EINVAL; + + if (bstop < 0 || bstop >= cache->bcull_percent) + return cachefiles_proc_range_error(cache, args); + + cache->bstop_percent = bstop; + return 0; +} + +/*****************************************************************************/ +/* + * set the cache directory + * - command: "dir <name>" + */ +static int cachefiles_proc_dir(struct cachefiles_cache *cache, char *args) +{ + char *dir; + + _enter(",%s", args); + + if (!*args) { + kerror("Empty directory specified"); + return -EINVAL; + } + + if (cache->rootdirname) { + kerror("Second cache directory specified"); + return -EEXIST; + } + + dir = kstrdup(args, GFP_KERNEL); + if (!dir) + return -ENOMEM; + + cache->rootdirname = dir; + return 0; +} + +/*****************************************************************************/ +/* + * set the cache tag + * - command: "tag <name>" + */ +static int cachefiles_proc_tag(struct cachefiles_cache *cache, char *args) +{ + char *tag; + + _enter(",%s", args); + + if (!*args) { + kerror("Empty tag specified"); + return -EINVAL; + } + + if (cache->tag) + return -EEXIST; + + tag = kstrdup(args, GFP_KERNEL); + if (!tag) + return -ENOMEM; + + cache->tag = tag; + return 0; +} + +/*****************************************************************************/ +/* + * request a node in the cache be culled + * - command: "cull <dirfd> <name>" + */ +static int cachefiles_proc_cull(struct cachefiles_cache *cache, char *args) +{ + struct dentry *dir; + struct file *dirfile; + int dirfd, fput_needed, ret; + + _enter(",%s", args); + + dirfd = simple_strtoul(args, &args, 0); + + if (!args || !isspace(*args)) + goto inval; + + while (isspace(*args)) + args++; + + if (!*args) + goto inval; + + if (strchr(args, '/')) + goto inval; + + if (!test_bit(CACHEFILES_READY, &cache->flags)) { + kerror("cull applied to unready cache"); + return -EIO; + } + + if (test_bit(CACHEFILES_DEAD, &cache->flags)) { + kerror("cull applied to dead cache"); + return -EIO; + } + + /* extract the directory dentry from the fd */ + dirfile = fget_light(dirfd, &fput_needed); + if (!dirfile) { + kerror("cull dirfd not open"); + return -EBADF; + } + + dir = dget(dirfile->f_dentry); + fput_light(dirfile, fput_needed); + dirfile = NULL; + + if (!S_ISDIR(dir->d_inode->i_mode)) + goto notdir; + + ret = cachefiles_cull(cache, dir, args); + + dput(dir); + _leave(" = %d", ret); + return ret; + +notdir: + dput(dir); + kerror("cull command requires dirfd to be a directory"); + return -ENOTDIR; + +inval: + kerror("cull command requires dirfd and filename"); + return -EINVAL; +} + +/*****************************************************************************/ +/* + * set debugging mode + * - command: "debug <mask>" + */ +static int cachefiles_proc_debug(struct cachefiles_cache *cache, char *args) +{ + unsigned long mask; + + _enter(",%s", args); + + mask = simple_strtoul(args, &args, 0); + + if (!args || !isspace(*args)) + goto inval; + + cachefiles_debug = mask; + _leave(" = 0"); + return 0; + +inval: + kerror("debug command requires mask"); + return -EINVAL; +} diff --git a/fs/cachefiles/cf-sysctl.c b/fs/cachefiles/cf-sysctl.c new file mode 100644 index 000000000..4d6fc04ca --- /dev/null +++ b/fs/cachefiles/cf-sysctl.c @@ -0,0 +1,69 @@ +/* cf-sysctl.c: Control parameters + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/sysctl.h> +#include "internal.h" + +static struct ctl_table_header *cachefiles_sysctl; + +/* + * Something that isn't CTL_ANY, CTL_NONE or a value that may clash. + * Use the same values as fs/nfs/sysctl.c + */ +#define CTL_UNNUMBERED -2 + +static ctl_table cachefiles_sysctl_table[] = { + { + .ctl_name = CTL_UNNUMBERED, + .procname = "debug", + .data = &cachefiles_debug, + .maxlen = sizeof(unsigned long), + .mode = 0644, + .proc_handler = &proc_doulongvec_minmax + }, + { .ctl_name = 0 } +}; + +static ctl_table cachefiles_sysctl_dir[] = { + { + .ctl_name = CTL_UNNUMBERED, + .procname = "cachefiles", + .maxlen = 0, + .mode = 0555, + .child = cachefiles_sysctl_table + }, + { .ctl_name = 0 } +}; + +static ctl_table cachefiles_sysctl_root[] = { + { + .ctl_name = CTL_FS, + .procname = "fs", + .mode = 0555, + .child = cachefiles_sysctl_dir, + }, + { .ctl_name = 0 } +}; + +int __init cachefiles_sysctl_init(void) +{ + cachefiles_sysctl = register_sysctl_table(cachefiles_sysctl_root, 0); + if (!cachefiles_sysctl) + return -ENOMEM; + return 0; +} + +void __exit cachefiles_sysctl_cleanup(void) +{ + unregister_sysctl_table(cachefiles_sysctl); +} diff --git a/fs/cachefiles/cf-xattr.c b/fs/cachefiles/cf-xattr.c new file mode 100644 index 000000000..8952bf0fe --- /dev/null +++ b/fs/cachefiles/cf-xattr.c @@ -0,0 +1,295 @@ +/* cf-xattr.c: CacheFiles extended attribute management + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/file.h> +#include <linux/fs.h> +#include <linux/fsnotify.h> +#include <linux/quotaops.h> +#include <linux/xattr.h> +#include "internal.h" + +static const char cachefiles_xattr_cache[] = XATTR_USER_PREFIX "CacheFiles.cache"; + +/*****************************************************************************/ +/* + * check the type label on an object + * - done using xattrs + */ +int cachefiles_check_object_type(struct cachefiles_object *object) +{ + struct dentry *dentry = object->dentry; + char type[3], xtype[3]; + int ret; + + ASSERT(dentry); + ASSERT(dentry->d_inode); + ASSERT(dentry->d_inode->i_op); + ASSERT(dentry->d_inode->i_op->setxattr); + ASSERT(dentry->d_inode->i_op->getxattr); + + if (!object->fscache.cookie) + strcpy(type, "C3"); + else + snprintf(type, 3, "%02x", object->fscache.cookie->def->type); + + _enter("%p{%s}", object, type); + + mutex_lock(&dentry->d_inode->i_mutex); + + /* attempt to install a type label directly */ + ret = dentry->d_inode->i_op->setxattr(dentry, cachefiles_xattr_cache, + type, 2, XATTR_CREATE); + if (ret == 0) { + _debug("SET"); + fsnotify_xattr(dentry); + mutex_unlock(&dentry->d_inode->i_mutex); + goto error; + } + + if (ret != -EEXIST) { + kerror("Can't set xattr on %*.*s [%lu] (err %d)", + dentry->d_name.len, dentry->d_name.len, + dentry->d_name.name, dentry->d_inode->i_ino, + -ret); + goto error; + } + + /* read the current type label */ + ret = dentry->d_inode->i_op->getxattr(dentry, cachefiles_xattr_cache, + xtype, 3); + if (ret < 0) { + if (ret == -ERANGE) + goto bad_type_length; + + kerror("Can't read xattr on %*.*s [%lu] (err %d)", + dentry->d_name.len, dentry->d_name.len, + dentry->d_name.name, dentry->d_inode->i_ino, + -ret); + goto error; + } + + /* check the type is what we're expecting */ + if (ret != 2) + goto bad_type_length; + + if (xtype[0] != type[0] || xtype[1] != type[1]) + goto bad_type; + + ret = 0; + +error: + mutex_unlock(&dentry->d_inode->i_mutex); + _leave(" = %d", ret); + return ret; + +bad_type_length: + kerror("Cache object %lu type xattr length incorrect", + dentry->d_inode->i_ino); + ret = -EIO; + goto error; + +bad_type: + xtype[2] = 0; + kerror("Cache object %*.*s [%lu] type %s not %s", + dentry->d_name.len, dentry->d_name.len, + dentry->d_name.name, dentry->d_inode->i_ino, + xtype, type); + ret = -EIO; + goto error; +} + +/*****************************************************************************/ +/* + * set the state xattr on a cache file + */ +int cachefiles_set_object_xattr(struct cachefiles_object *object, + struct cachefiles_xattr *auxdata) +{ + struct dentry *dentry = object->dentry; + int ret; + + ASSERT(object->fscache.cookie); + ASSERT(dentry); + ASSERT(dentry->d_inode->i_op->setxattr); + + _enter("%p,#%d", object, auxdata->len); + + /* attempt to install the cache metadata directly */ + mutex_lock(&dentry->d_inode->i_mutex); + + _debug("SET %s #%u", + object->fscache.cookie->def->name, auxdata->len); + + ret = dentry->d_inode->i_op->setxattr(dentry, cachefiles_xattr_cache, + &auxdata->type, auxdata->len, + XATTR_CREATE); + if (ret == 0) + fsnotify_xattr(dentry); + else if (ret != -ENOMEM) + cachefiles_io_error_obj(object, + "Failed to set xattr with error %d", + ret); + + mutex_unlock(&dentry->d_inode->i_mutex); + _leave(" = %d", ret); + return ret; +} + +/*****************************************************************************/ +/* + * check the state xattr on a cache file + * - return -ESTALE if the object should be deleted + */ +int cachefiles_check_object_xattr(struct cachefiles_object *object, + struct cachefiles_xattr *auxdata) +{ + struct cachefiles_xattr *auxbuf; + struct dentry *dentry = object->dentry; + int ret; + + _enter("%p,#%d", object, auxdata->len); + + ASSERT(dentry); + ASSERT(dentry->d_inode); + ASSERT(dentry->d_inode->i_op->setxattr); + ASSERT(dentry->d_inode->i_op->getxattr); + + auxbuf = kmalloc(sizeof(struct cachefiles_xattr) + 512, GFP_KERNEL); + if (!auxbuf) { + _leave(" = -ENOMEM"); + return -ENOMEM; + } + + mutex_lock(&dentry->d_inode->i_mutex); + + /* read the current type label */ + ret = dentry->d_inode->i_op->getxattr(dentry, cachefiles_xattr_cache, + &auxbuf->type, 512 + 1); + if (ret < 0) { + if (ret == -ENODATA) + goto stale; /* no attribute - power went off + * mid-cull? */ + + if (ret == -ERANGE) + goto bad_type_length; + + cachefiles_io_error_obj(object, + "can't read xattr on %lu (err %d)", + dentry->d_inode->i_ino, -ret); + goto error; + } + + /* check the on-disk object */ + if (ret < 1) + goto bad_type_length; + + if (auxbuf->type != auxdata->type) + goto stale; + + auxbuf->len = ret; + + /* consult the netfs */ + if (object->fscache.cookie->def->check_aux) { + fscache_checkaux_t result; + unsigned int dlen; + + dlen = auxbuf->len - 1; + + _debug("checkaux %s #%u", + object->fscache.cookie->def->name, dlen); + + result = object->fscache.cookie->def->check_aux( + object->fscache.cookie->netfs_data, + &auxbuf->data, dlen); + + switch (result) { + /* entry okay as is */ + case FSCACHE_CHECKAUX_OKAY: + goto okay; + + /* entry requires update */ + case FSCACHE_CHECKAUX_NEEDS_UPDATE: + break; + + /* entry requires deletion */ + case FSCACHE_CHECKAUX_OBSOLETE: + goto stale; + + default: + BUG(); + } + + /* update the current label */ + ret = dentry->d_inode->i_op->setxattr(dentry, + cachefiles_xattr_cache, + &auxdata->type, + auxdata->len, + XATTR_REPLACE); + if (ret < 0) { + cachefiles_io_error_obj(object, + "Can't update xattr on %lu" + " (error %d)", + dentry->d_inode->i_ino, -ret); + goto error; + } + } + +okay: + ret = 0; + +error: + mutex_unlock(&dentry->d_inode->i_mutex); + kfree(auxbuf); + _leave(" = %d", ret); + return ret; + +bad_type_length: + kerror("Cache object %lu xattr length incorrect", + dentry->d_inode->i_ino); + ret = -EIO; + goto error; + +stale: + ret = -ESTALE; + goto error; +} + +/*****************************************************************************/ +/* + * remove the object's xattr to mark it stale + */ +int cachefiles_remove_object_xattr(struct cachefiles_cache *cache, + struct dentry *dentry) +{ + int ret; + + mutex_lock(&dentry->d_inode->i_mutex); + + ret = dentry->d_inode->i_op->removexattr(dentry, + cachefiles_xattr_cache); + + mutex_unlock(&dentry->d_inode->i_mutex); + + if (ret < 0) { + if (ret == -ENOENT || ret == -ENODATA) + ret = 0; + else if (ret != -ENOMEM) + cachefiles_io_error(cache, + "Can't remove xattr from %lu" + " (error %d)", + dentry->d_inode->i_ino, -ret); + } + + _leave(" = %d", ret); + return ret; +} diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h new file mode 100644 index 000000000..edda6e776 --- /dev/null +++ b/fs/cachefiles/internal.h @@ -0,0 +1,308 @@ +/* internal.h: general netfs cache on cache files internal defs + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * + * CacheFiles layout: + * + * /..../CacheDir/ + * index + * 0/ + * 1/ + * 2/ + * index + * 0/ + * 1/ + * 2/ + * index + * 0 + * 1 + * 2 + */ + +#include <linux/fscache-cache.h> +#include <linux/timer.h> +#include <linux/wait.h> +#include <linux/workqueue.h> + +struct cachefiles_cache; +struct cachefiles_object; + +extern unsigned long cachefiles_debug; +#define CACHEFILES_DEBUG_KENTER 1 +#define CACHEFILES_DEBUG_KLEAVE 2 +#define CACHEFILES_DEBUG_KDEBUG 4 + +extern struct fscache_cache_ops cachefiles_cache_ops; +extern struct proc_dir_entry *cachefiles_proc; +extern struct file_operations cachefiles_proc_fops; + +/*****************************************************************************/ +/* + * node records + */ +struct cachefiles_object { + struct fscache_object fscache; /* fscache handle */ + struct dentry *dentry; /* the file/dir representing this object */ + struct dentry *backer; /* backing file */ + loff_t i_size; /* object size */ + atomic_t usage; /* basic object usage count */ + atomic_t fscache_usage; /* FSDEF object usage count */ + uint8_t type; /* object type */ + uint8_t new; /* T if object new */ + spinlock_t work_lock; + struct rw_semaphore sem; + struct work_struct read_work; /* read page copier */ + struct list_head read_list; /* pages to copy */ + struct list_head read_pend_list; /* pages to pending read from backer */ + struct work_struct write_work; /* page writer */ + struct list_head write_list; /* pages to store */ + struct rb_node active_node; /* link in active tree (dentry is key) */ +}; + +extern kmem_cache_t *cachefiles_object_jar; + +/*****************************************************************************/ +/* + * Cache files cache definition + */ +struct cachefiles_cache { + struct fscache_cache cache; /* FS-Cache record */ + struct vfsmount *mnt; /* mountpoint holding the cache */ + struct dentry *graveyard; /* directory into which dead objects go */ + struct file *cachefilesd; /* manager daemon handle */ + struct rb_root active_nodes; /* active nodes (can't be culled) */ + rwlock_t active_lock; /* lock for active_nodes */ + atomic_t gravecounter; /* graveyard uniquifier */ + unsigned brun_percent; /* when to stop culling (%) */ + unsigned bcull_percent; /* when to start culling (%) */ + unsigned bstop_percent; /* when to stop allocating (%) */ + unsigned bsize; /* cache's block size */ + unsigned bshift; /* min(log2 (PAGE_SIZE / bsize), 0) */ + sector_t brun; /* when to stop culling */ + sector_t bcull; /* when to start culling */ + sector_t bstop; /* when to stop allocating */ + unsigned long flags; +#define CACHEFILES_READY 0 /* T if cache prepared */ +#define CACHEFILES_DEAD 1 /* T if cache dead */ +#define CACHEFILES_CULLING 2 /* T if cull engaged */ + char *rootdirname; /* name of cache root directory */ + char *tag; /* cache binding tag */ +}; + +/*****************************************************************************/ +/* + * backing file read tracking + */ +struct cachefiles_one_read { + wait_queue_t monitor; /* link into monitored waitqueue */ + struct page *back_page; /* backing file page we're waiting for */ + struct page *netfs_page; /* netfs page we're going to fill */ + struct cachefiles_object *object; + struct list_head obj_link; /* link in object's lists */ + fscache_rw_complete_t end_io_func; + void *context; +}; + +/*****************************************************************************/ +/* + * backing file write tracking + */ +struct cachefiles_one_write { + struct page *netfs_page; /* netfs page to copy */ + struct cachefiles_object *object; + struct list_head obj_link; /* link in object's lists */ + fscache_rw_complete_t end_io_func; + void *context; +}; + +/*****************************************************************************/ +/* + * auxiliary data xattr buffer + */ +struct cachefiles_xattr { + uint16_t len; + uint8_t type; + uint8_t data[]; +}; + + +/* cf-bind.c */ +extern int cachefiles_proc_bind(struct cachefiles_cache *cache, char *args); +extern void cachefiles_proc_unbind(struct cachefiles_cache *cache); + +/* cf-interface.c */ +extern void cachefiles_read_copier_work(void *_object); +extern void cachefiles_write_work(void *_object); +extern int cachefiles_has_space(struct cachefiles_cache *cache, unsigned nr); + +/* cf-key.c */ +extern char *cachefiles_cook_key(const u8 *raw, int keylen, uint8_t type); + +/* cf-namei.c */ +extern int cachefiles_delete_object(struct cachefiles_cache *cache, + struct cachefiles_object *object); +extern int cachefiles_walk_to_object(struct cachefiles_object *parent, + struct cachefiles_object *object, + char *key, + struct cachefiles_xattr *auxdata); +extern struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, + struct dentry *dir, + const char *name); + +extern int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir, + char *filename); + +/* cf-sysctl.c */ +extern int __init cachefiles_sysctl_init(void); +extern void __exit cachefiles_sysctl_cleanup(void); + +/* cf-xattr.c */ +extern int cachefiles_check_object_type(struct cachefiles_object *object); +extern int cachefiles_set_object_xattr(struct cachefiles_object *object, + struct cachefiles_xattr *auxdata); +extern int cachefiles_check_object_xattr(struct cachefiles_object *object, + struct cachefiles_xattr *auxdata); +extern int cachefiles_remove_object_xattr(struct cachefiles_cache *cache, + struct dentry *dentry); + + +/*****************************************************************************/ +/* + * error handling + */ +#define kerror(FMT,...) printk(KERN_ERR "CacheFiles: "FMT"\n" ,##__VA_ARGS__); + +#define cachefiles_io_error(___cache, FMT, ...) \ +do { \ + kerror("I/O Error: " FMT ,##__VA_ARGS__); \ + fscache_io_error(&(___cache)->cache); \ + set_bit(CACHEFILES_DEAD, &(___cache)->flags); \ +} while(0) + +#define cachefiles_io_error_obj(object, FMT, ...) \ +do { \ + struct cachefiles_cache *___cache; \ + \ + ___cache = container_of((object)->fscache.cache, \ + struct cachefiles_cache, cache); \ + cachefiles_io_error(___cache, FMT ,##__VA_ARGS__); \ +} while(0) + + +/*****************************************************************************/ +/* + * debug tracing + */ +#define dbgprintk(FMT,...) \ + printk("[%-6.6s] "FMT"\n",current->comm ,##__VA_ARGS__) + +/* make sure we maintain the format strings, even when debugging is disabled */ +static inline void _dbprintk(const char *fmt, ...) + __attribute__((format(printf,1,2))); +static inline void _dbprintk(const char *fmt, ...) +{ +} + +#define kenter(FMT,...) dbgprintk("==> %s("FMT")",__FUNCTION__ ,##__VA_ARGS__) +#define kleave(FMT,...) dbgprintk("<== %s()"FMT"",__FUNCTION__ ,##__VA_ARGS__) +#define kdebug(FMT,...) dbgprintk(FMT ,##__VA_ARGS__) + + +#if defined(__KDEBUG) +#define _enter(FMT,...) kenter(FMT,##__VA_ARGS__) +#define _leave(FMT,...) kleave(FMT,##__VA_ARGS__) +#define _debug(FMT,...) kdebug(FMT,##__VA_ARGS__) + +#elif defined(CONFIG_CACHEFILES_DEBUG) +#define _enter(FMT,...) \ +do { \ + if (cachefiles_debug & CACHEFILES_DEBUG_KENTER) \ + kenter(FMT,##__VA_ARGS__); \ +} while (0) + +#define _leave(FMT,...) \ +do { \ + if (cachefiles_debug & CACHEFILES_DEBUG_KLEAVE) \ + kleave(FMT,##__VA_ARGS__); \ +} while (0) + +#define _debug(FMT,...) \ +do { \ + if (cachefiles_debug & CACHEFILES_DEBUG_KDEBUG) \ + kdebug(FMT,##__VA_ARGS__); \ +} while (0) + +#else +#define _enter(FMT,...) _dbprintk("==> %s("FMT")",__FUNCTION__ ,##__VA_ARGS__) +#define _leave(FMT,...) _dbprintk("<== %s()"FMT"",__FUNCTION__ ,##__VA_ARGS__) +#define _debug(FMT,...) _dbprintk(FMT ,##__VA_ARGS__) +#endif + +#if 1 // defined(__KDEBUGALL) + +#define ASSERT(X) \ +do { \ + if (unlikely(!(X))) { \ + printk(KERN_ERR "\n"); \ + printk(KERN_ERR "CacheFiles: Assertion failed\n"); \ + BUG(); \ + } \ +} while(0) + +#define ASSERTCMP(X, OP, Y) \ +do { \ + if (unlikely(!((X) OP (Y)))) { \ + printk(KERN_ERR "\n"); \ + printk(KERN_ERR "CacheFiles: Assertion failed\n"); \ + printk(KERN_ERR "%lx " #OP " %lx is false\n", \ + (unsigned long)(X), (unsigned long)(Y)); \ + BUG(); \ + } \ +} while(0) + +#define ASSERTIF(C, X) \ +do { \ + if (unlikely((C) && !(X))) { \ + printk(KERN_ERR "\n"); \ + printk(KERN_ERR "CacheFiles: Assertion failed\n"); \ + BUG(); \ + } \ +} while(0) + +#define ASSERTIFCMP(C, X, OP, Y) \ +do { \ + if (unlikely((C) && !((X) OP (Y)))) { \ + printk(KERN_ERR "\n"); \ + printk(KERN_ERR "CacheFiles: Assertion failed\n"); \ + printk(KERN_ERR "%lx " #OP " %lx is false\n", \ + (unsigned long)(X), (unsigned long)(Y)); \ + BUG(); \ + } \ +} while(0) + +#else + +#define ASSERT(X) \ +do { \ +} while(0) + +#define ASSERTCMP(X, OP, Y) \ +do { \ +} while(0) + +#define ASSERTIF(C, X) \ +do { \ +} while(0) + +#define ASSERTIFCMP(C, X, OP, Y) \ +do { \ +} while(0) + +#endif diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c new file mode 100644 index 000000000..d1705ab81 --- /dev/null +++ b/fs/cifs/sess.c @@ -0,0 +1,538 @@ +/* + * fs/cifs/sess.c + * + * SMB/CIFS session setup handling routines + * + * Copyright (c) International Business Machines Corp., 2006 + * Author(s): Steve French (sfrench@us.ibm.com) + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "cifspdu.h" +#include "cifsglob.h" +#include "cifsproto.h" +#include "cifs_unicode.h" +#include "cifs_debug.h" +#include "ntlmssp.h" +#include "nterr.h" +#include <linux/utsname.h> + +extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, + unsigned char *p24); + +static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB) +{ + __u32 capabilities = 0; + + /* init fields common to all four types of SessSetup */ + /* note that header is initialized to zero in header_assemble */ + pSMB->req.AndXCommand = 0xFF; + pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); + pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); + + /* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */ + + /* BB verify whether signing required on neg or just on auth frame + (and NTLM case) */ + + capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS | + CAP_LARGE_WRITE_X | CAP_LARGE_READ_X; + + if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) + pSMB->req.hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE; + + if (ses->capabilities & CAP_UNICODE) { + pSMB->req.hdr.Flags2 |= SMBFLG2_UNICODE; + capabilities |= CAP_UNICODE; + } + if (ses->capabilities & CAP_STATUS32) { + pSMB->req.hdr.Flags2 |= SMBFLG2_ERR_STATUS; + capabilities |= CAP_STATUS32; + } + if (ses->capabilities & CAP_DFS) { + pSMB->req.hdr.Flags2 |= SMBFLG2_DFS; + capabilities |= CAP_DFS; + } + if (ses->capabilities & CAP_UNIX) { + capabilities |= CAP_UNIX; + } + + /* BB check whether to init vcnum BB */ + return capabilities; +} + +static void unicode_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, + const struct nls_table * nls_cp) +{ + char * bcc_ptr = *pbcc_area; + int bytes_ret = 0; + + /* BB FIXME add check that strings total less + than 335 or will need to send them as arrays */ + + /* unicode strings, must be word aligned before the call */ +/* if ((long) bcc_ptr % 2) { + *bcc_ptr = 0; + bcc_ptr++; + } */ + /* copy user */ + if(ses->userName == NULL) { + /* BB what about null user mounts - check that we do this BB */ + } else { /* 300 should be long enough for any conceivable user name */ + bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName, + 300, nls_cp); + } + bcc_ptr += 2 * bytes_ret; + bcc_ptr += 2; /* account for null termination */ + /* copy domain */ + if(ses->domainName == NULL) + bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, + "CIFS_LINUX_DOM", 32, nls_cp); + else + bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName, + 256, nls_cp); + bcc_ptr += 2 * bytes_ret; + bcc_ptr += 2; /* account for null terminator */ + + /* Copy OS version */ + bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32, + nls_cp); + bcc_ptr += 2 * bytes_ret; + bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, system_utsname.release, + 32, nls_cp); + bcc_ptr += 2 * bytes_ret; + bcc_ptr += 2; /* trailing null */ + + bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, + 32, nls_cp); + bcc_ptr += 2 * bytes_ret; + bcc_ptr += 2; /* trailing null */ + + *pbcc_area = bcc_ptr; +} + +static void ascii_ssetup_strings(char ** pbcc_area, struct cifsSesInfo *ses, + const struct nls_table * nls_cp) +{ + char * bcc_ptr = *pbcc_area; + + /* copy user */ + /* BB what about null user mounts - check that we do this BB */ + /* copy user */ + if(ses->userName == NULL) { + /* BB what about null user mounts - check that we do this BB */ + } else { /* 300 should be long enough for any conceivable user name */ + strncpy(bcc_ptr, ses->userName, 300); + } + /* BB improve check for overflow */ + bcc_ptr += strnlen(ses->userName, 300); + *bcc_ptr = 0; + bcc_ptr++; /* account for null termination */ + + /* copy domain */ + + if(ses->domainName == NULL) { + strcpy(bcc_ptr, "CIFS_LINUX_DOM"); + bcc_ptr += 14; /* strlen(CIFS_LINUX_DOM) */ + } else { + strncpy(bcc_ptr, ses->domainName, 256); + bcc_ptr += strnlen(ses->domainName, 256); + } + *bcc_ptr = 0; + bcc_ptr++; + + /* BB check for overflow here */ + + strcpy(bcc_ptr, "Linux version "); + bcc_ptr += strlen("Linux version "); + strcpy(bcc_ptr, system_utsname.release); + bcc_ptr += strlen(system_utsname.release) + 1; + + strcpy(bcc_ptr, CIFS_NETWORK_OPSYS); + bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1; + + *pbcc_area = bcc_ptr; +} + +static int decode_unicode_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses, + const struct nls_table * nls_cp) +{ + int rc = 0; + int words_left, len; + char * data = *pbcc_area; + + + + cFYI(1,("bleft %d",bleft)); + + + /* word align, if bytes remaining is not even */ + if(bleft % 2) { + bleft--; + data++; + } + words_left = bleft / 2; + + /* save off server operating system */ + len = UniStrnlen((wchar_t *) data, words_left); + +/* We look for obvious messed up bcc or strings in response so we do not go off + the end since (at least) WIN2K and Windows XP have a major bug in not null + terminating last Unicode string in response */ + if(len >= words_left) + return rc; + + if(ses->serverOS) + kfree(ses->serverOS); + /* UTF-8 string will not grow more than four times as big as UCS-16 */ + ses->serverOS = kzalloc(4 * len, GFP_KERNEL); + if(ses->serverOS != NULL) { + cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, + nls_cp); + } + data += 2 * (len + 1); + words_left -= len + 1; + + /* save off server network operating system */ + len = UniStrnlen((wchar_t *) data, words_left); + + if(len >= words_left) + return rc; + + if(ses->serverNOS) + kfree(ses->serverNOS); + ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */ + if(ses->serverNOS != NULL) { + cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len, + nls_cp); + if(strncmp(ses->serverNOS, "NT LAN Manager 4",16) == 0) { + cFYI(1,("NT4 server")); + ses->flags |= CIFS_SES_NT4; + } + } + data += 2 * (len + 1); + words_left -= len + 1; + + /* save off server domain */ + len = UniStrnlen((wchar_t *) data, words_left); + + if(len > words_left) + return rc; + + if(ses->serverDomain) + kfree(ses->serverDomain); + ses->serverDomain = kzalloc(2 * (len + 1), GFP_KERNEL); /* BB FIXME wrong length */ + if(ses->serverDomain != NULL) { + cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len, + nls_cp); + ses->serverDomain[2*len] = 0; + ses->serverDomain[(2*len) + 1] = 0; + } + data += 2 * (len + 1); + words_left -= len + 1; + + cFYI(1,("words left: %d",words_left)); + + return rc; +} + +static int decode_ascii_ssetup(char ** pbcc_area, int bleft, struct cifsSesInfo *ses, + const struct nls_table * nls_cp) +{ + int rc = 0; + int len; + char * bcc_ptr = *pbcc_area; + + cFYI(1,("decode sessetup ascii. bleft %d", bleft)); + + len = strnlen(bcc_ptr, bleft); + if(len >= bleft) + return rc; + + if(ses->serverOS) + kfree(ses->serverOS); + + ses->serverOS = kzalloc(len + 1, GFP_KERNEL); + if(ses->serverOS) + strncpy(ses->serverOS, bcc_ptr, len); + + bcc_ptr += len + 1; + bleft -= len + 1; + + len = strnlen(bcc_ptr, bleft); + if(len >= bleft) + return rc; + + if(ses->serverNOS) + kfree(ses->serverNOS); + + ses->serverNOS = kzalloc(len + 1, GFP_KERNEL); + if(ses->serverNOS) + strncpy(ses->serverNOS, bcc_ptr, len); + + bcc_ptr += len + 1; + bleft -= len + 1; + + len = strnlen(bcc_ptr, bleft); + if(len > bleft) + return rc; + + if(ses->serverDomain) + kfree(ses->serverDomain); + + ses->serverDomain = kzalloc(len + 1, GFP_KERNEL); + if(ses->serverOS) + strncpy(ses->serverOS, bcc_ptr, len); + + bcc_ptr += len + 1; + bleft -= len + 1; + + cFYI(1,("ascii: bytes left %d",bleft)); + + return rc; +} + +int +CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time, + const struct nls_table *nls_cp) +{ + int rc = 0; + int wct; + struct smb_hdr *smb_buf; + char *bcc_ptr; + char *str_area; + SESSION_SETUP_ANDX *pSMB; + __u32 capabilities; + int count; + int resp_buf_type = 0; + struct kvec iov[2]; + enum securityEnum type; + __u16 action; + int bytes_remaining; + + if(ses == NULL) + return -EINVAL; + + type = ses->server->secType; + + cFYI(1,("sess setup type %d",type)); + if(type == LANMAN) { +#ifndef CONFIG_CIFS_WEAK_PW_HASH + /* LANMAN and plaintext are less secure and off by default. + So we make this explicitly be turned on in kconfig (in the + build) and turned on at runtime (changed from the default) + in proc/fs/cifs or via mount parm. Unfortunately this is + needed for old Win (e.g. Win95), some obscure NAS and OS/2 */ + return -EOPNOTSUPP; +#endif + wct = 10; /* lanman 2 style sessionsetup */ + } else if((type == NTLM) || (type == NTLMv2)) { + /* For NTLMv2 failures eventually may need to retry NTLM */ + wct = 13; /* old style NTLM sessionsetup */ + } else /* same size for negotiate or auth, NTLMSSP or extended security */ + wct = 12; + + rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses, + (void **)&smb_buf); + if(rc) + return rc; + + pSMB = (SESSION_SETUP_ANDX *)smb_buf; + + capabilities = cifs_ssetup_hdr(ses, pSMB); + + /* we will send the SMB in two pieces, + a fixed length beginning part, and a + second part which will include the strings + and rest of bcc area, in order to avoid having + to do a large buffer 17K allocation */ + iov[0].iov_base = (char *)pSMB; + iov[0].iov_len = smb_buf->smb_buf_length + 4; + + /* 2000 big enough to fit max user, domain, NOS name etc. */ + str_area = kmalloc(2000, GFP_KERNEL); + bcc_ptr = str_area; + + if(type == LANMAN) { +#ifdef CONFIG_CIFS_WEAK_PW_HASH + char lnm_session_key[CIFS_SESS_KEY_SIZE]; + + /* no capabilities flags in old lanman negotiation */ + + pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE); + /* BB calculate hash with password */ + /* and copy into bcc */ + + calc_lanman_hash(ses, lnm_session_key); + +/* #ifdef CONFIG_CIFS_DEBUG2 + cifs_dump_mem("cryptkey: ",ses->server->cryptKey, + CIFS_SESS_KEY_SIZE); +#endif */ + memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE); + bcc_ptr += CIFS_SESS_KEY_SIZE; + + /* can not sign if LANMAN negotiated so no need + to calculate signing key? but what if server + changed to do higher than lanman dialect and + we reconnected would we ever calc signing_key? */ + + cFYI(1,("Negotiating LANMAN setting up strings")); + /* Unicode not allowed for LANMAN dialects */ + ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); +#endif + } else if (type == NTLM) { + char ntlm_session_key[CIFS_SESS_KEY_SIZE]; + + pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); + pSMB->req_no_secext.CaseInsensitivePasswordLength = + cpu_to_le16(CIFS_SESS_KEY_SIZE); + pSMB->req_no_secext.CaseSensitivePasswordLength = + cpu_to_le16(CIFS_SESS_KEY_SIZE); + + /* calculate session key */ + SMBNTencrypt(ses->password, ses->server->cryptKey, + ntlm_session_key); + + if(first_time) /* should this be moved into common code + with similar ntlmv2 path? */ + cifs_calculate_mac_key(ses->server->mac_signing_key, + ntlm_session_key, ses->password); + /* copy session key */ + + memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE); + bcc_ptr += CIFS_SESS_KEY_SIZE; + memcpy(bcc_ptr, (char *)ntlm_session_key,CIFS_SESS_KEY_SIZE); + bcc_ptr += CIFS_SESS_KEY_SIZE; + if(ses->capabilities & CAP_UNICODE) { + /* unicode strings must be word aligned */ + if (iov[0].iov_len % 2) { + *bcc_ptr = 0; + bcc_ptr++; + } + unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); + } else + ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); + } else if (type == NTLMv2) { + char * v2_sess_key = + kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL); + + /* BB FIXME change all users of v2_sess_key to + struct ntlmv2_resp */ + + if(v2_sess_key == NULL) { + cifs_small_buf_release(smb_buf); + return -ENOMEM; + } + + pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities); + + /* LM2 password would be here if we supported it */ + pSMB->req_no_secext.CaseInsensitivePasswordLength = 0; + /* cpu_to_le16(LM2_SESS_KEY_SIZE); */ + + pSMB->req_no_secext.CaseSensitivePasswordLength = + cpu_to_le16(sizeof(struct ntlmv2_resp)); + + /* calculate session key */ + setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp); + if(first_time) /* should this be moved into common code + with similar ntlmv2 path? */ + /* cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key, + response BB FIXME, v2_sess_key); */ + + /* copy session key */ + + /* memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE); + bcc_ptr += LM2_SESS_KEY_SIZE; */ + memcpy(bcc_ptr, (char *)v2_sess_key, sizeof(struct ntlmv2_resp)); + bcc_ptr += sizeof(struct ntlmv2_resp); + kfree(v2_sess_key); + if(ses->capabilities & CAP_UNICODE) { + if(iov[0].iov_len % 2) { + *bcc_ptr = 0; + } bcc_ptr++; + unicode_ssetup_strings(&bcc_ptr, ses, nls_cp); + } else + ascii_ssetup_strings(&bcc_ptr, ses, nls_cp); + } else /* NTLMSSP or SPNEGO */ { + pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC; + capabilities |= CAP_EXTENDED_SECURITY; + pSMB->req.Capabilities = cpu_to_le32(capabilities); + /* BB set password lengths */ + } + + count = (long) bcc_ptr - (long) str_area; + smb_buf->smb_buf_length += count; + + BCC_LE(smb_buf) = cpu_to_le16(count); + + iov[1].iov_base = str_area; + iov[1].iov_len = count; + rc = SendReceive2(xid, ses, iov, 2 /* num_iovecs */, &resp_buf_type, 0); + /* SMB request buf freed in SendReceive2 */ + + cFYI(1,("ssetup rc from sendrecv2 is %d",rc)); + if(rc) + goto ssetup_exit; + + pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base; + smb_buf = (struct smb_hdr *)iov[0].iov_base; + + if((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) { + rc = -EIO; + cERROR(1,("bad word count %d", smb_buf->WordCount)); + goto ssetup_exit; + } + action = le16_to_cpu(pSMB->resp.Action); + if (action & GUEST_LOGIN) + cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */ + ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */ + cFYI(1, ("UID = %d ", ses->Suid)); + /* response can have either 3 or 4 word count - Samba sends 3 */ + /* and lanman response is 3 */ + bytes_remaining = BCC(smb_buf); + bcc_ptr = pByteArea(smb_buf); + + if(smb_buf->WordCount == 4) { + __u16 blob_len; + blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength); + bcc_ptr += blob_len; + if(blob_len > bytes_remaining) { + cERROR(1,("bad security blob length %d", blob_len)); + rc = -EINVAL; + goto ssetup_exit; + } + bytes_remaining -= blob_len; + } + + /* BB check if Unicode and decode strings */ + if(smb_buf->Flags2 & SMBFLG2_UNICODE) + rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining, + ses, nls_cp); + else + rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining, ses,nls_cp); + +ssetup_exit: + kfree(str_area); + if(resp_buf_type == CIFS_SMALL_BUFFER) { + cFYI(1,("ssetup freeing small buf %p", iov[0].iov_base)); + cifs_small_buf_release(iov[0].iov_base); + } else if(resp_buf_type == CIFS_LARGE_BUFFER) + cifs_buf_release(iov[0].iov_base); + + return rc; +} diff --git a/fs/fscache/Makefile b/fs/fscache/Makefile new file mode 100644 index 000000000..10f17a38f --- /dev/null +++ b/fs/fscache/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for general filesystem caching code +# + +fscache-objs := \ + cookie.o \ + fsdef.o \ + main.o \ + page.o + +obj-$(CONFIG_FSCACHE) := fscache.o diff --git a/fs/fscache/cookie.c b/fs/fscache/cookie.c new file mode 100644 index 000000000..9a6ac8b70 --- /dev/null +++ b/fs/fscache/cookie.c @@ -0,0 +1,1045 @@ +/* cookie.c: general filesystem cache cookie management + * + * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/module.h> +#include "fscache-int.h" + +static LIST_HEAD(fscache_cache_tag_list); +static LIST_HEAD(fscache_cache_list); +static LIST_HEAD(fscache_netfs_list); +static DECLARE_RWSEM(fscache_addremove_sem); +static struct fscache_cache_tag fscache_nomem_tag; + +kmem_cache_t *fscache_cookie_jar; + +static void fscache_withdraw_object(struct fscache_cache *cache, + struct fscache_object *object); + +static void __fscache_cookie_put(struct fscache_cookie *cookie); + +static inline void fscache_cookie_put(struct fscache_cookie *cookie) +{ + /* check to see whether the cookie has already been released by looking + * for the poison when slab debugging is on */ +#ifdef CONFIG_DEBUG_SLAB + BUG_ON((atomic_read(&cookie->usage) & 0xffff0000) == 0x6b6b0000); +#endif + + BUG_ON(atomic_read(&cookie->usage) <= 0); + + if (atomic_dec_and_test(&cookie->usage)) + __fscache_cookie_put(cookie); + +} + +/*****************************************************************************/ +/* + * look up a cache tag + */ +struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name) +{ + struct fscache_cache_tag *tag, *xtag; + + /* firstly check for the existence of the tag under read lock */ + down_read(&fscache_addremove_sem); + + list_for_each_entry(tag, &fscache_cache_tag_list, link) { + if (strcmp(tag->name, name) == 0) { + atomic_inc(&tag->usage); + up_read(&fscache_addremove_sem); + return tag; + } + } + + up_read(&fscache_addremove_sem); + + /* the tag does not exist - create a candidate */ + xtag = kmalloc(sizeof(*xtag) + strlen(name) + 1, GFP_KERNEL); + if (!xtag) + /* return a dummy tag if out of memory */ + return &fscache_nomem_tag; + + atomic_set(&xtag->usage, 1); + strcpy(xtag->name, name); + + /* write lock, search again and add if still not present */ + down_write(&fscache_addremove_sem); + + list_for_each_entry(tag, &fscache_cache_tag_list, link) { + if (strcmp(tag->name, name) == 0) { + atomic_inc(&tag->usage); + up_write(&fscache_addremove_sem); + kfree(xtag); + return tag; + } + } + + list_add_tail(&xtag->link, &fscache_cache_tag_list); + up_write(&fscache_addremove_sem); + return xtag; +} + +/*****************************************************************************/ +/* + * release a reference to a cache tag + */ +void __fscache_release_cache_tag(struct fscache_cache_tag *tag) +{ + if (tag != &fscache_nomem_tag) { + down_write(&fscache_addremove_sem); + + if (atomic_dec_and_test(&tag->usage)) + list_del_init(&tag->link); + else + tag = NULL; + + up_write(&fscache_addremove_sem); + + kfree(tag); + } +} + +/*****************************************************************************/ +/* + * register a network filesystem for caching + */ +int __fscache_register_netfs(struct fscache_netfs *netfs) +{ + struct fscache_netfs *ptr; + int ret; + + _enter("{%s}", netfs->name); + + INIT_LIST_HEAD(&netfs->link); + + /* allocate a cookie for the primary index */ + netfs->primary_index = + kmem_cache_zalloc(fscache_cookie_jar, SLAB_KERNEL); + + if (!netfs->primary_index) { + _leave(" = -ENOMEM"); + return -ENOMEM; + } + + /* initialise the primary index cookie */ + atomic_set(&netfs->primary_index->usage, 1); + atomic_set(&netfs->primary_index->children, 0); + + netfs->primary_index->def = &fscache_fsdef_netfs_def; + netfs->primary_index->parent = &fscache_fsdef_index; + netfs->primary_index->netfs = netfs; + netfs->primary_index->netfs_data = netfs; + + atomic_inc(&netfs->primary_index->parent->usage); + atomic_inc(&netfs->primary_index->parent->children); + + init_rwsem(&netfs->primary_index->sem); + INIT_HLIST_HEAD(&netfs->primary_index->backing_objects); + + /* check the netfs type is not already present */ + down_write(&fscache_addremove_sem); + + ret = -EEXIST; + list_for_each_entry(ptr, &fscache_netfs_list, link) { + if (strcmp(ptr->name, netfs->name) == 0) + goto already_registered; + } + + list_add(&netfs->link, &fscache_netfs_list); + ret = 0; + + printk("FS-Cache: netfs '%s' registered for caching\n", netfs->name); + +already_registered: + up_write(&fscache_addremove_sem); + + if (ret < 0) { + netfs->primary_index->parent = NULL; + __fscache_cookie_put(netfs->primary_index); + netfs->primary_index = NULL; + } + + _leave(" = %d", ret); + return ret; +} + +EXPORT_SYMBOL(__fscache_register_netfs); + +/*****************************************************************************/ +/* + * unregister a network filesystem from the cache + * - all cookies must have been released first + */ +void __fscache_unregister_netfs(struct fscache_netfs *netfs) +{ + _enter("{%s.%u}", netfs->name, netfs->version); + + down_write(&fscache_addremove_sem); + + list_del(&netfs->link); + fscache_relinquish_cookie(netfs->primary_index, 0); + + up_write(&fscache_addremove_sem); + + printk("FS-Cache: netfs '%s' unregistered from caching\n", + netfs->name); + + _leave(""); +} + +EXPORT_SYMBOL(__fscache_unregister_netfs); + +/*****************************************************************************/ +/* + * initialise a cache record + */ +void fscache_init_cache(struct fscache_cache *cache, + struct fscache_cache_ops *ops, + const char *idfmt, + ...) +{ + va_list va; + + memset(cache, 0, sizeof(*cache)); + + cache->ops = ops; + + va_start(va, idfmt); + vsnprintf(cache->identifier, sizeof(cache->identifier), idfmt, va); + va_end(va); + + INIT_LIST_HEAD(&cache->link); + INIT_LIST_HEAD(&cache->object_list); + spin_lock_init(&cache->object_list_lock); + init_rwsem(&cache->withdrawal_sem); +} + +EXPORT_SYMBOL(fscache_init_cache); + +/*****************************************************************************/ +/* + * declare a mounted cache as being open for business + */ +int fscache_add_cache(struct fscache_cache *cache, + struct fscache_object *ifsdef, + const char *tagname) +{ + struct fscache_cache_tag *tag; + + BUG_ON(!cache->ops); + BUG_ON(!ifsdef); + + cache->flags = 0; + + if (!tagname) + tagname = cache->identifier; + + BUG_ON(!tagname[0]); + + _enter("{%s.%s},,%s", cache->ops->name, cache->identifier, tagname); + + if (!cache->ops->grab_object(ifsdef)) + BUG(); + + ifsdef->cookie = &fscache_fsdef_index; + ifsdef->cache = cache; + cache->fsdef = ifsdef; + + down_write(&fscache_addremove_sem); + + /* instantiate or allocate a cache tag */ + list_for_each_entry(tag, &fscache_cache_tag_list, link) { + if (strcmp(tag->name, tagname) == 0) { + if (tag->cache) { + printk(KERN_ERR + "FS-Cache: cache tag '%s' already in use\n", + tagname); + up_write(&fscache_addremove_sem); + return -EEXIST; + } + + atomic_inc(&tag->usage); + goto found_cache_tag; + } + } + + tag = kmalloc(sizeof(*tag) + strlen(tagname) + 1, GFP_KERNEL); + if (!tag) { + up_write(&fscache_addremove_sem); + return -ENOMEM; + } + + atomic_set(&tag->usage, 1); + strcpy(tag->name, tagname); + list_add_tail(&tag->link, &fscache_cache_tag_list); + +found_cache_tag: + tag->cache = cache; + cache->tag = tag; + + /* add the cache to the list */ + list_add(&cache->link, &fscache_cache_list); + + /* add the cache's netfs definition index object to the cache's + * list */ + spin_lock(&cache->object_list_lock); + list_add_tail(&ifsdef->cache_link, &cache->object_list); + spin_unlock(&cache->object_list_lock); + + /* add the cache's netfs definition index object to the top level index + * cookie as a known backing object */ + down_write(&fscache_fsdef_index.sem); + + hlist_add_head(&ifsdef->cookie_link, + &fscache_fsdef_index.backing_objects); + + atomic_inc(&fscache_fsdef_index.usage); + + /* done */ + up_write(&fscache_fsdef_index.sem); + up_write(&fscache_addremove_sem); + + printk(KERN_NOTICE + "FS-Cache: Cache \"%s\" added (type %s)\n", + cache->tag->name, cache->ops->name); + + _leave(" = 0 [%s]", cache->identifier); + return 0; +} + +EXPORT_SYMBOL(fscache_add_cache); + +/*****************************************************************************/ +/* + * note a cache I/O error + */ +void fscache_io_error(struct fscache_cache *cache) +{ + set_bit(FSCACHE_IOERROR, &cache->flags); + + printk(KERN_ERR "FS-Cache: Cache %s stopped due to I/O error\n", + cache->ops->name); +} + +EXPORT_SYMBOL(fscache_io_error); + +/*****************************************************************************/ +/* + * withdraw an unmounted cache from the active service + */ +void fscache_withdraw_cache(struct fscache_cache *cache) +{ + struct fscache_object *object; + + _enter(""); + + printk(KERN_NOTICE + "FS-Cache: Withdrawing cache \"%s\"\n", + cache->tag->name); + + /* make the cache unavailable for cookie acquisition */ + down_write(&cache->withdrawal_sem); + + down_write(&fscache_addremove_sem); + list_del_init(&cache->link); + cache->tag->cache = NULL; + up_write(&fscache_addremove_sem); + + /* mark all objects as being withdrawn */ + spin_lock(&cache->object_list_lock); + list_for_each_entry(object, &cache->object_list, cache_link) { + set_bit(FSCACHE_OBJECT_WITHDRAWN, &object->flags); + } + spin_unlock(&cache->object_list_lock); + + /* make sure all pages pinned by operations on behalf of the netfs are + * written to disc */ + cache->ops->sync_cache(cache); + + /* dissociate all the netfs pages backed by this cache from the block + * mappings in the cache */ + cache->ops->dissociate_pages(cache); + + /* we now have to destroy all the active objects pertaining to this + * cache */ + spin_lock(&cache->object_list_lock); + + while (!list_empty(&cache->object_list)) { + object = list_entry(cache->object_list.next, + struct fscache_object, cache_link); + list_del_init(&object->cache_link); + spin_unlock(&cache->object_list_lock); + + _debug("withdraw %p", object->cookie); + + /* we've extracted an active object from the tree - now dispose + * of it */ + fscache_withdraw_object(cache, object); + + spin_lock(&cache->object_list_lock); + } + + spin_unlock(&cache->object_list_lock); + + fscache_release_cache_tag(cache->tag); + cache->tag = NULL; + + _leave(""); +} + +EXPORT_SYMBOL(fscache_withdraw_cache); + +/*****************************************************************************/ +/* + * withdraw an object from active service at the behest of the cache + * - need break the links to a cached object cookie + * - called under two situations: + * (1) recycler decides to reclaim an in-use object + * (2) a cache is unmounted + * - have to take care as the cookie can be being relinquished by the netfs + * simultaneously + * - the active object is pinned by the caller holding a refcount on it + */ +static void fscache_withdraw_object(struct fscache_cache *cache, + struct fscache_object *object) +{ + struct fscache_cookie *cookie, *xcookie = NULL; + + _enter(",%p", object); + + /* first of all we have to break the links between the object and the + * cookie + * - we have to hold both semaphores BUT we have to get the cookie sem + * FIRST + */ + cache->ops->lock_object(object); + + cookie = object->cookie; + if (cookie) { + /* pin the cookie so that is doesn't escape */ + atomic_inc(&cookie->usage); + + /* re-order the locks to avoid deadlock */ + cache->ops->unlock_object(object); + down_write(&cookie->sem); + cache->ops->lock_object(object); + + /* erase references from the object to the cookie */ + hlist_del_init(&object->cookie_link); + + xcookie = object->cookie; + object->cookie = NULL; + + up_write(&cookie->sem); + } + + cache->ops->unlock_object(object); + + /* we've broken the links between cookie and object */ + if (xcookie) { + fscache_cookie_put(xcookie); + cache->ops->put_object(object); + } + + /* unpin the cookie */ + if (cookie) { + if (cookie->def && cookie->def->now_uncached) + cookie->def->now_uncached(cookie->netfs_data); + fscache_cookie_put(cookie); + } + + _leave(""); +} + +/*****************************************************************************/ +/* + * select a cache on which to store an object + * - the cache addremove semaphore must be at least read-locked by the caller + * - the object will never be an index + */ +static struct fscache_cache *fscache_select_cache_for_object(struct fscache_cookie *cookie) +{ + struct fscache_cache_tag *tag; + struct fscache_object *object; + struct fscache_cache *cache; + + _enter(""); + + if (list_empty(&fscache_cache_list)) { + _leave(" = NULL [no cache]"); + return NULL; + } + + /* we check the parent to determine the cache to use */ + down_read(&cookie->parent->sem); + + /* the first in the parent's backing list should be the preferred + * cache */ + if (!hlist_empty(&cookie->parent->backing_objects)) { + object = hlist_entry(cookie->parent->backing_objects.first, + struct fscache_object, cookie_link); + + cache = object->cache; + if (test_bit(FSCACHE_IOERROR, &cache->flags)) + cache = NULL; + + up_read(&cookie->parent->sem); + _leave(" = %p [parent]", cache); + return cache; + } + + /* the parent is unbacked */ + if (cookie->parent->def->type != FSCACHE_COOKIE_TYPE_INDEX) { + /* parent not an index and is unbacked */ + up_read(&cookie->parent->sem); + _leave(" = NULL [parent ubni]"); + return NULL; + } + + up_read(&cookie->parent->sem); + + if (!cookie->parent->def->select_cache) + goto no_preference; + + /* ask the netfs for its preference */ + tag = cookie->parent->def->select_cache( + cookie->parent->parent->netfs_data, + cookie->parent->netfs_data); + + if (!tag) + goto no_preference; + + if (tag == &fscache_nomem_tag) { + _leave(" = NULL [nomem tag]"); + return NULL; + } + + if (!tag->cache) { + _leave(" = NULL [unbacked tag]"); + return NULL; + } + + if (test_bit(FSCACHE_IOERROR, &tag->cache->flags)) + return NULL; + + _leave(" = %p [specific]", tag->cache); + return tag->cache; + +no_preference: + /* netfs has no preference - just select first cache */ + cache = list_entry(fscache_cache_list.next, + struct fscache_cache, link); + _leave(" = %p [first]", cache); + return cache; +} + +/*****************************************************************************/ +/* + * get a backing object for a cookie from the chosen cache + * - the cookie must be write-locked by the caller + * - all parent indexes will be obtained recursively first + */ +static struct fscache_object *fscache_lookup_object(struct fscache_cookie *cookie, + struct fscache_cache *cache) +{ + struct fscache_cookie *parent = cookie->parent; + struct fscache_object *pobject, *object; + struct hlist_node *_p; + + _enter("{%s/%s},", + parent && parent->def ? parent->def->name : "", + cookie->def ? (char *) cookie->def->name : "<file>"); + + if (test_bit(FSCACHE_IOERROR, &cache->flags)) + return NULL; + + /* see if we have the backing object for this cookie + cache immediately + * to hand + */ + object = NULL; + hlist_for_each_entry(object, _p, + &cookie->backing_objects, cookie_link + ) { + if (object->cache == cache) + break; + } + + if (object) { + _leave(" = %p [old]", object); + return object; + } + + BUG_ON(!parent); /* FSDEF entries don't have a parent */ + + /* we don't have a backing cookie, so we need to consult the object's + * parent index in the selected cache and maybe insert an entry + * therein; so the first thing to do is make sure that the parent index + * is represented on disc + */ + down_read(&parent->sem); + + pobject = NULL; + hlist_for_each_entry(pobject, _p, + &parent->backing_objects, cookie_link + ) { + if (pobject->cache == cache) + break; + } + + if (!pobject) { + /* we don't know about the parent object */ + up_read(&parent->sem); + down_write(&parent->sem); + + pobject = fscache_lookup_object(parent, cache); + if (IS_ERR(pobject)) { + up_write(&parent->sem); + _leave(" = %ld [no ipobj]", PTR_ERR(pobject)); + return pobject; + } + + _debug("pobject=%p", pobject); + + BUG_ON(pobject->cookie != parent); + + downgrade_write(&parent->sem); + } + + /* now we can attempt to look up this object in the parent, possibly + * creating a representation on disc when we do so + */ + object = cache->ops->lookup_object(cache, pobject, cookie); + up_read(&parent->sem); + + if (IS_ERR(object)) { + _leave(" = %ld [no obj]", PTR_ERR(object)); + return object; + } + + /* keep track of it */ + cache->ops->lock_object(object); + + BUG_ON(!hlist_unhashed(&object->cookie_link)); + + /* attach to the cache's object list */ + if (list_empty(&object->cache_link)) { + spin_lock(&cache->object_list_lock); + list_add(&object->cache_link, &cache->object_list); + spin_unlock(&cache->object_list_lock); + } + + /* attach to the cookie */ + object->cookie = cookie; + atomic_inc(&cookie->usage); + hlist_add_head(&object->cookie_link, &cookie->backing_objects); + + /* done */ + cache->ops->unlock_object(object); + _leave(" = %p [new]", object); + return object; +} + +/*****************************************************************************/ +/* + * request a cookie to represent an object (index, datafile, xattr, etc) + * - parent specifies the parent object + * - the top level index cookie for each netfs is stored in the fscache_netfs + * struct upon registration + * - idef points to the definition + * - the netfs_data will be passed to the functions pointed to in *def + * - all attached caches will be searched to see if they contain this object + * - index objects aren't stored on disk until there's a dependent file that + * needs storing + * - other objects are stored in a selected cache immediately, and all the + * indexes forming the path to it are instantiated if necessary + * - we never let on to the netfs about errors + * - we may set a negative cookie pointer, but that's okay + */ +struct fscache_cookie *__fscache_acquire_cookie(struct fscache_cookie *parent, + struct fscache_cookie_def *def, + void *netfs_data) +{ + struct fscache_cookie *cookie; + struct fscache_cache *cache; + struct fscache_object *object; + int ret = 0; + + BUG_ON(!def); + + _enter("{%s},{%s},%p", + parent ? (char *) parent->def->name : "<no-parent>", + def->name, netfs_data); + + /* if there's no parent cookie, then we don't create one here either */ + if (!parent) { + _leave(" [no parent]"); + return NULL; + } + + /* validate the definition */ + BUG_ON(!def->get_key); + BUG_ON(!def->name[0]); + + BUG_ON(def->type == FSCACHE_COOKIE_TYPE_INDEX && + parent->def->type != FSCACHE_COOKIE_TYPE_INDEX); + + /* allocate and initialise a cookie */ + cookie = kmem_cache_alloc(fscache_cookie_jar, SLAB_KERNEL); + if (!cookie) { + _leave(" [ENOMEM]"); + return NULL; + } + + atomic_set(&cookie->usage, 1); + atomic_set(&cookie->children, 0); + + atomic_inc(&parent->usage); + atomic_inc(&parent->children); + + cookie->def = def; + cookie->parent = parent; + cookie->netfs = parent->netfs; + cookie->netfs_data = netfs_data; + + /* now we need to see whether the backing objects for this cookie yet + * exist, if not there'll be nothing to search */ + down_read(&fscache_addremove_sem); + + if (list_empty(&fscache_cache_list)) { + up_read(&fscache_addremove_sem); + _leave(" = %p [no caches]", cookie); + return cookie; + } + + /* if the object is an index then we need do nothing more here - we + * create indexes on disk when we need them as an index may exist in + * multiple caches */ + if (cookie->def->type != FSCACHE_COOKIE_TYPE_INDEX) { + down_write(&cookie->sem); + + /* the object is a file - we need to select a cache in which to + * store it */ + cache = fscache_select_cache_for_object(cookie); + if (!cache) + goto no_cache; /* couldn't decide on a cache */ + + /* create a file index entry on disc, along with all the + * indexes required to find it again later */ + object = fscache_lookup_object(cookie, cache); + if (IS_ERR(object)) { + ret = PTR_ERR(object); + goto error; + } + + up_write(&cookie->sem); + } +out: + up_read(&fscache_addremove_sem); + _leave(" = %p", cookie); + return cookie; + +no_cache: + ret = -ENOMEDIUM; + goto error_cleanup; +error: + printk(KERN_ERR "FS-Cache: error from cache: %d\n", ret); +error_cleanup: + if (cookie) { + up_write(&cookie->sem); + __fscache_cookie_put(cookie); + cookie = NULL; + atomic_dec(&parent->children); + } + + goto out; +} + +EXPORT_SYMBOL(__fscache_acquire_cookie); + +/*****************************************************************************/ +/* + * release a cookie back to the cache + * - the object will be marked as recyclable on disc if retire is true + * - all dependents of this cookie must have already been unregistered + * (indexes/files/pages) + */ +void __fscache_relinquish_cookie(struct fscache_cookie *cookie, int retire) +{ + struct fscache_cache *cache; + struct fscache_object *object; + struct hlist_node *_p; + + if (!cookie) { + _leave(" [no cookie]"); + return; + } + + _enter("%p{%s},%d", cookie, cookie->def->name, retire); + + if (atomic_read(&cookie->children) != 0) { + printk("FS-Cache: cookie still has children\n"); + BUG(); + } + + /* detach pointers back to the netfs */ + down_write(&cookie->sem); + + cookie->netfs_data = NULL; + cookie->def = NULL; + + /* mark retired objects for recycling */ + if (retire) { + hlist_for_each_entry(object, _p, + &cookie->backing_objects, + cookie_link + ) { + set_bit(FSCACHE_OBJECT_RECYCLING, &object->flags); + } + } + + /* break links with all the active objects */ + while (!hlist_empty(&cookie->backing_objects)) { + object = hlist_entry(cookie->backing_objects.first, + struct fscache_object, + cookie_link); + + /* detach each cache object from the object cookie */ + set_bit(FSCACHE_OBJECT_RELEASING, &object->flags); + + hlist_del_init(&object->cookie_link); + + cache = object->cache; + cache->ops->lock_object(object); + object->cookie = NULL; + cache->ops->unlock_object(object); + + if (atomic_dec_and_test(&cookie->usage)) + /* the cookie refcount shouldn't be reduced to 0 yet */ + BUG(); + + spin_lock(&cache->object_list_lock); + list_del_init(&object->cache_link); + spin_unlock(&cache->object_list_lock); + + cache->ops->put_object(object); + } + + up_write(&cookie->sem); + + if (cookie->parent) { +#ifdef CONFIG_DEBUG_SLAB + BUG_ON((atomic_read(&cookie->parent->children) & 0xffff0000) == 0x6b6b0000); +#endif + atomic_dec(&cookie->parent->children); + } + + /* finally dispose of the cookie */ + fscache_cookie_put(cookie); + + _leave(""); +} + +EXPORT_SYMBOL(__fscache_relinquish_cookie); + +/*****************************************************************************/ +/* + * update the index entries backing a cookie + */ +void __fscache_update_cookie(struct fscache_cookie *cookie) +{ + struct fscache_object *object; + struct hlist_node *_p; + + if (!cookie) { + _leave(" [no cookie]"); + return; + } + + _enter("{%s}", cookie->def->name); + + BUG_ON(!cookie->def->get_aux); + + down_write(&cookie->sem); + down_read(&cookie->parent->sem); + + /* update the index entry on disc in each cache backing this cookie */ + hlist_for_each_entry(object, _p, + &cookie->backing_objects, cookie_link + ) { + if (!test_bit(FSCACHE_IOERROR, &object->cache->flags)) + object->cache->ops->update_object(object); + } + + up_read(&cookie->parent->sem); + up_write(&cookie->sem); + _leave(""); +} + +EXPORT_SYMBOL(__fscache_update_cookie); + +/*****************************************************************************/ +/* + * destroy a cookie + */ +static void __fscache_cookie_put(struct fscache_cookie *cookie) +{ + struct fscache_cookie *parent; + + _enter("%p", cookie); + + for (;;) { + parent = cookie->parent; + BUG_ON(!hlist_empty(&cookie->backing_objects)); + kmem_cache_free(fscache_cookie_jar, cookie); + + if (!parent) + break; + + cookie = parent; + BUG_ON(atomic_read(&cookie->usage) <= 0); + if (!atomic_dec_and_test(&cookie->usage)) + break; + } + + _leave(""); +} + +/*****************************************************************************/ +/* + * initialise an cookie jar slab element prior to any use + */ +void fscache_cookie_init_once(void *_cookie, kmem_cache_t *cachep, + unsigned long flags) +{ + struct fscache_cookie *cookie = _cookie; + + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == + SLAB_CTOR_CONSTRUCTOR) { + memset(cookie, 0, sizeof(*cookie)); + init_rwsem(&cookie->sem); + INIT_HLIST_HEAD(&cookie->backing_objects); + } +} + +/*****************************************************************************/ +/* + * pin an object into the cache + */ +int __fscache_pin_cookie(struct fscache_cookie *cookie) +{ + struct fscache_object *object; + int ret; + + _enter("%p", cookie); + + if (hlist_empty(&cookie->backing_objects)) { + _leave(" = -ENOBUFS"); + return -ENOBUFS; + } + + /* not supposed to use this for indexes */ + BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX); + + /* prevent the file from being uncached whilst we access it and exclude + * read and write attempts on pages + */ + down_write(&cookie->sem); + + ret = -ENOBUFS; + if (!hlist_empty(&cookie->backing_objects)) { + /* get and pin the backing object */ + object = hlist_entry(cookie->backing_objects.first, + struct fscache_object, cookie_link); + + if (test_bit(FSCACHE_IOERROR, &object->cache->flags)) + goto out; + + if (!object->cache->ops->pin_object) { + ret = -EOPNOTSUPP; + goto out; + } + + /* prevent the cache from being withdrawn */ + if (fscache_operation_lock(object)) { + if (object->cache->ops->grab_object(object)) { + /* ask the cache to honour the operation */ + ret = object->cache->ops->pin_object(object); + + object->cache->ops->put_object(object); + } + + fscache_operation_unlock(object); + } + } + +out: + up_write(&cookie->sem); + _leave(" = %d", ret); + return ret; +} + +EXPORT_SYMBOL(__fscache_pin_cookie); + +/*****************************************************************************/ +/* + * unpin an object into the cache + */ +void __fscache_unpin_cookie(struct fscache_cookie *cookie) +{ + struct fscache_object *object; + int ret; + + _enter("%p", cookie); + + if (hlist_empty(&cookie->backing_objects)) { + _leave(" [no obj]"); + return; + } + + /* not supposed to use this for indexes */ + BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX); + + /* prevent the file from being uncached whilst we access it and exclude + * read and write attempts on pages + */ + down_write(&cookie->sem); + + ret = -ENOBUFS; + if (!hlist_empty(&cookie->backing_objects)) { + /* get and unpin the backing object */ + object = hlist_entry(cookie->backing_objects.first, + struct fscache_object, cookie_link); + + if (test_bit(FSCACHE_IOERROR, &object->cache->flags)) + goto out; + + if (!object->cache->ops->unpin_object) + goto out; + + /* prevent the cache from being withdrawn */ + if (fscache_operation_lock(object)) { + if (object->cache->ops->grab_object(object)) { + /* ask the cache to honour the operation */ + object->cache->ops->unpin_object(object); + + object->cache->ops->put_object(object); + } + + fscache_operation_unlock(object); + } + } + +out: + up_write(&cookie->sem); + _leave(""); +} + +EXPORT_SYMBOL(__fscache_unpin_cookie); diff --git a/fs/fscache/fscache-int.h b/fs/fscache/fscache-int.h new file mode 100644 index 000000000..d075660c4 --- /dev/null +++ b/fs/fscache/fscache-int.h @@ -0,0 +1,93 @@ +/* fscache-int.h: internal definitions + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _FSCACHE_INT_H +#define _FSCACHE_INT_H + +#include <linux/fscache-cache.h> +#include <linux/timer.h> +#include <linux/bio.h> + +extern kmem_cache_t *fscache_cookie_jar; + +extern struct fscache_cookie fscache_fsdef_index; +extern struct fscache_cookie_def fscache_fsdef_netfs_def; + +extern void fscache_cookie_init_once(void *_cookie, kmem_cache_t *cachep, unsigned long flags); + +/* + * prevent the cache from being withdrawn whilst an operation is in progress + * - returns false if the cache is being withdrawn already or if the cache is + * waiting to withdraw itself + * - returns true if the cache was not being withdrawn + * - fscache_withdraw_cache() will wait using down_write() until all ops are + * complete + */ +static inline int fscache_operation_lock(struct fscache_object *object) +{ + return down_read_trylock(&object->cache->withdrawal_sem); +} + +/* + * release the operation lock + */ +static inline void fscache_operation_unlock(struct fscache_object *object) +{ + up_read(&object->cache->withdrawal_sem); +} + + +/*****************************************************************************/ +/* + * debug tracing + */ +#define dbgprintk(FMT,...) \ + printk("[%-6.6s] "FMT"\n",current->comm ,##__VA_ARGS__) +#define _dbprintk(FMT,...) do { } while(0) + +#define kenter(FMT,...) dbgprintk("==> %s("FMT")",__FUNCTION__ ,##__VA_ARGS__) +#define kleave(FMT,...) dbgprintk("<== %s()"FMT"",__FUNCTION__ ,##__VA_ARGS__) +#define kdebug(FMT,...) dbgprintk(FMT ,##__VA_ARGS__) + +#define kjournal(FMT,...) _dbprintk(FMT ,##__VA_ARGS__) + +#define dbgfree(ADDR) _dbprintk("%p:%d: FREEING %p",__FILE__,__LINE__,ADDR) + +#define dbgpgalloc(PAGE) \ +do { \ + _dbprintk("PGALLOC %s:%d: %p {%lx,%lu}\n", \ + __FILE__,__LINE__, \ + (PAGE),(PAGE)->mapping->host->i_ino,(PAGE)->index \ + ); \ +} while(0) + +#define dbgpgfree(PAGE) \ +do { \ + if ((PAGE)) \ + _dbprintk("PGFREE %s:%d: %p {%lx,%lu}\n", \ + __FILE__,__LINE__, \ + (PAGE), \ + (PAGE)->mapping->host->i_ino, \ + (PAGE)->index \ + ); \ +} while(0) + +#ifdef __KDEBUG +#define _enter(FMT,...) kenter(FMT,##__VA_ARGS__) +#define _leave(FMT,...) kleave(FMT,##__VA_ARGS__) +#define _debug(FMT,...) kdebug(FMT,##__VA_ARGS__) +#else +#define _enter(FMT,...) do { } while(0) +#define _leave(FMT,...) do { } while(0) +#define _debug(FMT,...) do { } while(0) +#endif + +#endif /* _FSCACHE_INT_H */ diff --git a/fs/fscache/fsdef.c b/fs/fscache/fsdef.c new file mode 100644 index 000000000..495f63355 --- /dev/null +++ b/fs/fscache/fsdef.c @@ -0,0 +1,110 @@ +/* fsdef.c: filesystem index definition + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/module.h> +#include "fscache-int.h" + +static uint16_t fscache_fsdef_netfs_get_key(const void *cookie_netfs_data, + void *buffer, uint16_t bufmax); + +static uint16_t fscache_fsdef_netfs_get_aux(const void *cookie_netfs_data, + void *buffer, uint16_t bufmax); + +static fscache_checkaux_t fscache_fsdef_netfs_check_aux(void *cookie_netfs_data, + const void *data, + uint16_t datalen); + +struct fscache_cookie_def fscache_fsdef_netfs_def = { + .name = "FSDEF.netfs", + .type = FSCACHE_COOKIE_TYPE_INDEX, + .get_key = fscache_fsdef_netfs_get_key, + .get_aux = fscache_fsdef_netfs_get_aux, + .check_aux = fscache_fsdef_netfs_check_aux, +}; + +struct fscache_cookie fscache_fsdef_index = { + .usage = ATOMIC_INIT(1), + .def = NULL, + .sem = __RWSEM_INITIALIZER(fscache_fsdef_index.sem), + .backing_objects = HLIST_HEAD_INIT, +}; + +EXPORT_SYMBOL(fscache_fsdef_index); + +/*****************************************************************************/ +/* + * get the key data for an FSDEF index record + */ +static uint16_t fscache_fsdef_netfs_get_key(const void *cookie_netfs_data, + void *buffer, uint16_t bufmax) +{ + const struct fscache_netfs *netfs = cookie_netfs_data; + unsigned klen; + + _enter("{%s.%u},", netfs->name, netfs->version); + + klen = strlen(netfs->name); + if (klen > bufmax) + return 0; + + memcpy(buffer, netfs->name, klen); + return klen; +} + +/*****************************************************************************/ +/* + * get the auxilliary data for an FSDEF index record + */ +static uint16_t fscache_fsdef_netfs_get_aux(const void *cookie_netfs_data, + void *buffer, uint16_t bufmax) +{ + const struct fscache_netfs *netfs = cookie_netfs_data; + unsigned dlen; + + _enter("{%s.%u},", netfs->name, netfs->version); + + dlen = sizeof(uint32_t); + if (dlen > bufmax) + return 0; + + memcpy(buffer, &netfs->version, dlen); + return dlen; +} + +/*****************************************************************************/ +/* + * check that the version stored in the auxilliary data is correct + */ +static fscache_checkaux_t fscache_fsdef_netfs_check_aux(void *cookie_netfs_data, + const void *data, + uint16_t datalen) +{ + struct fscache_netfs *netfs = cookie_netfs_data; + uint32_t version; + + _enter("{%s},,%hu", netfs->name, datalen); + + if (datalen != sizeof(version)) { + _leave(" = OBSOLETE [dl=%d v=%d]", + datalen, sizeof(version)); + return FSCACHE_CHECKAUX_OBSOLETE; + } + + memcpy(&version, data, sizeof(version)); + if (version != netfs->version) { + _leave(" = OBSOLETE [ver=%x net=%x]", + version, netfs->version); + return FSCACHE_CHECKAUX_OBSOLETE; + } + + _leave(" = OKAY"); + return FSCACHE_CHECKAUX_OKAY; +} diff --git a/fs/fscache/main.c b/fs/fscache/main.c new file mode 100644 index 000000000..d73068cb0 --- /dev/null +++ b/fs/fscache/main.c @@ -0,0 +1,105 @@ +/* main.c: general filesystem caching manager + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/completion.h> +#include <linux/slab.h> +#include "fscache-int.h" + +int fscache_debug; + +static int fscache_init(void); +static void fscache_exit(void); + +fs_initcall(fscache_init); +module_exit(fscache_exit); + +MODULE_DESCRIPTION("FS Cache Manager"); +MODULE_AUTHOR("Red Hat, Inc."); +MODULE_LICENSE("GPL"); + +static void fscache_ktype_release(struct kobject *kobject); + +static struct sysfs_ops fscache_sysfs_ops = { + .show = NULL, + .store = NULL, +}; + +static struct kobj_type fscache_ktype = { + .release = fscache_ktype_release, + .sysfs_ops = &fscache_sysfs_ops, + .default_attrs = NULL, +}; + +struct kset fscache_kset = { + .kobj.name = "fscache", + .kobj.kset = &fs_subsys.kset, + .ktype = &fscache_ktype, +}; + +EXPORT_SYMBOL(fscache_kset); + +/*****************************************************************************/ +/* + * initialise the fs caching module + */ +static int __init fscache_init(void) +{ + int ret; + + fscache_cookie_jar = + kmem_cache_create("fscache_cookie_jar", + sizeof(struct fscache_cookie), + 0, + 0, + fscache_cookie_init_once, + NULL); + + if (!fscache_cookie_jar) { + printk(KERN_NOTICE + "FS-Cache: Failed to allocate a cookie jar\n"); + return -ENOMEM; + } + + ret = kset_register(&fscache_kset); + if (ret < 0) { + kmem_cache_destroy(fscache_cookie_jar); + return ret; + } + + printk(KERN_NOTICE "FS-Cache: Loaded\n"); + return 0; + +} + +/*****************************************************************************/ +/* + * clean up on module removal + */ +static void __exit fscache_exit(void) +{ + _enter(""); + + kset_unregister(&fscache_kset); + kmem_cache_destroy(fscache_cookie_jar); + printk(KERN_NOTICE "FS-Cache: unloaded\n"); + +} + +/*****************************************************************************/ +/* + * release the ktype + */ +static void fscache_ktype_release(struct kobject *kobject) +{ +} diff --git a/fs/fscache/page.c b/fs/fscache/page.c new file mode 100644 index 000000000..fbb771606 --- /dev/null +++ b/fs/fscache/page.c @@ -0,0 +1,537 @@ +/* page.c: general filesystem cache cookie management + * + * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/module.h> +#include <linux/fscache-cache.h> +#include <linux/buffer_head.h> +#include <linux/pagevec.h> +#include "fscache-int.h" + +/*****************************************************************************/ +/* + * set the data file size on an object in the cache + */ +int __fscache_set_i_size(struct fscache_cookie *cookie, loff_t i_size) +{ + struct fscache_object *object; + int ret; + + _enter("%p,%llu,", cookie, i_size); + + if (hlist_empty(&cookie->backing_objects)) { + _leave(" = -ENOBUFS"); + return -ENOBUFS; + } + + /* not supposed to use this for indexes */ + BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX); + + /* prevent the file from being uncached whilst we access it and exclude + * read and write attempts on pages + */ + down_write(&cookie->sem); + + ret = -ENOBUFS; + if (!hlist_empty(&cookie->backing_objects)) { + /* get and pin the backing object */ + object = hlist_entry(cookie->backing_objects.first, + struct fscache_object, cookie_link); + + if (test_bit(FSCACHE_IOERROR, &object->cache->flags)) + goto out; + + /* prevent the cache from being withdrawn */ + if (object->cache->ops->set_i_size && + fscache_operation_lock(object) + ) { + if (object->cache->ops->grab_object(object)) { + /* ask the cache to honour the operation */ + ret = object->cache->ops->set_i_size(object, + i_size); + + object->cache->ops->put_object(object); + } + + fscache_operation_unlock(object); + } + } + +out: + up_write(&cookie->sem); + _leave(" = %d", ret); + return ret; +} + +EXPORT_SYMBOL(__fscache_set_i_size); + +/*****************************************************************************/ +/* + * reserve space for an object + */ +int __fscache_reserve_space(struct fscache_cookie *cookie, loff_t size) +{ + struct fscache_object *object; + int ret; + + _enter("%p,%llu,", cookie, size); + + if (hlist_empty(&cookie->backing_objects)) { + _leave(" = -ENOBUFS"); + return -ENOBUFS; + } + + /* not supposed to use this for indexes */ + BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX); + + /* prevent the file from being uncached whilst we access it and exclude + * read and write attempts on pages + */ + down_write(&cookie->sem); + + ret = -ENOBUFS; + if (!hlist_empty(&cookie->backing_objects)) { + /* get and pin the backing object */ + object = hlist_entry(cookie->backing_objects.first, + struct fscache_object, cookie_link); + + if (test_bit(FSCACHE_IOERROR, &object->cache->flags)) + goto out; + + if (!object->cache->ops->reserve_space) { + ret = -EOPNOTSUPP; + goto out; + } + + /* prevent the cache from being withdrawn */ + if (fscache_operation_lock(object)) { + if (object->cache->ops->grab_object(object)) { + /* ask the cache to honour the operation */ + ret = object->cache->ops->reserve_space(object, + size); + + object->cache->ops->put_object(object); + } + + fscache_operation_unlock(object); + } + } + +out: + up_write(&cookie->sem); + _leave(" = %d", ret); + return ret; +} + +EXPORT_SYMBOL(__fscache_reserve_space); + +/*****************************************************************************/ +/* + * read a page from the cache or allocate a block in which to store it + * - we return: + * -ENOMEM - out of memory, nothing done + * -EINTR - interrupted + * -ENOBUFS - no backing object available in which to cache the block + * -ENODATA - no data available in the backing object for this block + * 0 - dispatched a read - it'll call end_io_func() when finished + */ +int __fscache_read_or_alloc_page(struct fscache_cookie *cookie, + struct page *page, + fscache_rw_complete_t end_io_func, + void *context, + gfp_t gfp) +{ + struct fscache_object *object; + int ret; + + _enter("%p,{%lu},", cookie, page->index); + + if (hlist_empty(&cookie->backing_objects)) { + _leave(" -ENOBUFS [no backing objects]"); + return -ENOBUFS; + } + + /* not supposed to use this for indexes */ + BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX); + + /* prevent the file from being uncached whilst we access it */ + down_read(&cookie->sem); + + ret = -ENOBUFS; + if (!hlist_empty(&cookie->backing_objects)) { + /* get and pin the backing object */ + object = hlist_entry(cookie->backing_objects.first, + struct fscache_object, cookie_link); + + if (test_bit(FSCACHE_IOERROR, &object->cache->flags)) + goto out; + + /* prevent the cache from being withdrawn */ + if (fscache_operation_lock(object)) { + if (object->cache->ops->grab_object(object)) { + /* ask the cache to honour the operation */ + ret = object->cache->ops->read_or_alloc_page( + object, + page, + end_io_func, + context, + gfp); + + object->cache->ops->put_object(object); + } + + fscache_operation_unlock(object); + } + } + +out: + up_read(&cookie->sem); + _leave(" = %d", ret); + return ret; +} + +EXPORT_SYMBOL(__fscache_read_or_alloc_page); + +/*****************************************************************************/ +/* + * read a list of page from the cache or allocate a block in which to store + * them + * - we return: + * -ENOMEM - out of memory, some pages may be being read + * -EINTR - interrupted, some pages may be being read + * -ENOBUFS - no backing object or space available in which to cache any + * pages not being read + * -ENODATA - no data available in the backing object for some or all of + * the pages + * 0 - dispatched a read on all pages + * + * end_io_func() will be called for each page read from the cache as it is + * finishes being read + * + * any pages for which a read is dispatched will be removed from pages and + * nr_pages + */ +int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie, + struct address_space *mapping, + struct list_head *pages, + unsigned *nr_pages, + fscache_rw_complete_t end_io_func, + void *context, + gfp_t gfp) +{ + struct fscache_object *object; + int ret; + + _enter("%p,,%d,,,", cookie, *nr_pages); + + if (hlist_empty(&cookie->backing_objects)) { + _leave(" -ENOBUFS [no backing objects]"); + return -ENOBUFS; + } + + /* not supposed to use this for indexes */ + BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX); + BUG_ON(list_empty(pages)); + BUG_ON(*nr_pages <= 0); + + /* prevent the file from being uncached whilst we access it */ + down_read(&cookie->sem); + + ret = -ENOBUFS; + if (!hlist_empty(&cookie->backing_objects)) { + /* get and pin the backing object */ + object = hlist_entry(cookie->backing_objects.first, + struct fscache_object, cookie_link); + + if (test_bit(FSCACHE_IOERROR, &object->cache->flags)) + goto out; + + /* prevent the cache from being withdrawn */ + if (fscache_operation_lock(object)) { + if (object->cache->ops->grab_object(object)) { + /* ask the cache to honour the operation */ + ret = object->cache->ops->read_or_alloc_pages( + object, + mapping, + pages, + nr_pages, + end_io_func, + context, + gfp); + + object->cache->ops->put_object(object); + } + + fscache_operation_unlock(object); + } + } + +out: + up_read(&cookie->sem); + _leave(" = %d", ret); + return ret; +} + +EXPORT_SYMBOL(__fscache_read_or_alloc_pages); + +/*****************************************************************************/ +/* + * allocate a block in the cache on which to store a page + * - we return: + * -ENOMEM - out of memory, nothing done + * -EINTR - interrupted + * -ENOBUFS - no backing object available in which to cache the block + * 0 - block allocated + */ +int __fscache_alloc_page(struct fscache_cookie *cookie, + struct page *page, + gfp_t gfp) +{ + struct fscache_object *object; + int ret; + + _enter("%p,{%lu},", cookie, page->index); + + if (hlist_empty(&cookie->backing_objects)) { + _leave(" -ENOBUFS [no backing objects]"); + return -ENOBUFS; + } + + /* not supposed to use this for indexes */ + BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX); + + /* prevent the file from being uncached whilst we access it */ + down_read(&cookie->sem); + + ret = -ENOBUFS; + if (!hlist_empty(&cookie->backing_objects)) { + /* get and pin the backing object */ + object = hlist_entry(cookie->backing_objects.first, + struct fscache_object, cookie_link); + + if (test_bit(FSCACHE_IOERROR, &object->cache->flags)) + goto out; + + /* prevent the cache from being withdrawn */ + if (fscache_operation_lock(object)) { + if (object->cache->ops->grab_object(object)) { + /* ask the cache to honour the operation */ + ret = object->cache->ops->allocate_page(object, + page, + gfp); + + object->cache->ops->put_object(object); + } + + fscache_operation_unlock(object); + } + } + +out: + up_read(&cookie->sem); + _leave(" = %d", ret); + return ret; +} + +EXPORT_SYMBOL(__fscache_alloc_page); + +/*****************************************************************************/ +/* + * request a page be stored in the cache + * - returns: + * -ENOMEM - out of memory, nothing done + * -EINTR - interrupted + * -ENOBUFS - no backing object available in which to cache the page + * 0 - dispatched a write - it'll call end_io_func() when finished + */ +int __fscache_write_page(struct fscache_cookie *cookie, + struct page *page, + fscache_rw_complete_t end_io_func, + void *context, + gfp_t gfp) +{ + struct fscache_object *object; + int ret; + + _enter("%p,{%lu},", cookie, page->index); + + /* not supposed to use this for indexes */ + BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX); + + /* prevent the file from been uncached whilst we deal with it */ + down_read(&cookie->sem); + + ret = -ENOBUFS; + if (!hlist_empty(&cookie->backing_objects)) { + object = hlist_entry(cookie->backing_objects.first, + struct fscache_object, cookie_link); + + if (test_bit(FSCACHE_IOERROR, &object->cache->flags)) + goto out; + + /* prevent the cache from being withdrawn */ + if (fscache_operation_lock(object)) { + /* ask the cache to honour the operation */ + ret = object->cache->ops->write_page(object, + page, + end_io_func, + context, + gfp); + fscache_operation_unlock(object); + } + } + +out: + up_read(&cookie->sem); + _leave(" = %d", ret); + return ret; +} + +EXPORT_SYMBOL(__fscache_write_page); + +/*****************************************************************************/ +/* + * request several pages be stored in the cache + * - returns: + * -ENOMEM - out of memory, nothing done + * -EINTR - interrupted + * -ENOBUFS - no backing object available in which to cache the page + * 0 - dispatched a write - it'll call end_io_func() when finished + */ +int __fscache_write_pages(struct fscache_cookie *cookie, + struct pagevec *pagevec, + fscache_rw_complete_t end_io_func, + void *context, + gfp_t gfp) +{ + struct fscache_object *object; + int ret; + + _enter("%p,{%ld},", cookie, pagevec->nr); + + /* not supposed to use this for indexes */ + BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX); + + /* prevent the file from been uncached whilst we deal with it */ + down_read(&cookie->sem); + + ret = -ENOBUFS; + if (!hlist_empty(&cookie->backing_objects)) { + object = hlist_entry(cookie->backing_objects.first, + struct fscache_object, cookie_link); + + if (test_bit(FSCACHE_IOERROR, &object->cache->flags)) + goto out; + + /* prevent the cache from being withdrawn */ + if (fscache_operation_lock(object)) { + /* ask the cache to honour the operation */ + ret = object->cache->ops->write_pages(object, + pagevec, + end_io_func, + context, + gfp); + fscache_operation_unlock(object); + } + } + +out: + up_read(&cookie->sem); + _leave(" = %d", ret); + return ret; +} + +EXPORT_SYMBOL(__fscache_write_pages); + +/*****************************************************************************/ +/* + * remove a page from the cache + */ +void __fscache_uncache_page(struct fscache_cookie *cookie, struct page *page) +{ + struct fscache_object *object; + struct pagevec pagevec; + + _enter(",{%lu}", page->index); + + /* not supposed to use this for indexes */ + BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX); + + if (hlist_empty(&cookie->backing_objects)) { + _leave(" [no backing]"); + return; + } + + pagevec_init(&pagevec, 0); + pagevec_add(&pagevec, page); + + /* ask the cache to honour the operation */ + down_read(&cookie->sem); + + if (!hlist_empty(&cookie->backing_objects)) { + object = hlist_entry(cookie->backing_objects.first, + struct fscache_object, cookie_link); + + /* prevent the cache from being withdrawn */ + if (fscache_operation_lock(object)) { + object->cache->ops->uncache_pages(object, &pagevec); + fscache_operation_unlock(object); + } + } + + up_read(&cookie->sem); + + _leave(""); +} + +EXPORT_SYMBOL(__fscache_uncache_page); + +/*****************************************************************************/ +/* + * remove a bunch of pages from the cache + */ +void __fscache_uncache_pages(struct fscache_cookie *cookie, + struct pagevec *pagevec) +{ + struct fscache_object *object; + + _enter(",{%ld}", pagevec->nr); + + BUG_ON(pagevec->nr <= 0); + BUG_ON(!pagevec->pages[0]); + + /* not supposed to use this for indexes */ + BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX); + + if (hlist_empty(&cookie->backing_objects)) { + _leave(" [no backing]"); + return; + } + + /* ask the cache to honour the operation */ + down_read(&cookie->sem); + + if (!hlist_empty(&cookie->backing_objects)) { + object = hlist_entry(cookie->backing_objects.first, + struct fscache_object, cookie_link); + + /* prevent the cache from being withdrawn */ + if (fscache_operation_lock(object)) { + object->cache->ops->uncache_pages(object, pagevec); + fscache_operation_unlock(object); + } + } + + up_read(&cookie->sem); + + _leave(""); +} + +EXPORT_SYMBOL(__fscache_uncache_pages); diff --git a/fs/fuse/control.c b/fs/fuse/control.c new file mode 100644 index 000000000..79ec1f23d --- /dev/null +++ b/fs/fuse/control.c @@ -0,0 +1,218 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu> + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. +*/ + +#include "fuse_i.h" + +#include <linux/init.h> +#include <linux/module.h> + +#define FUSE_CTL_SUPER_MAGIC 0x65735543 + +/* + * This is non-NULL when the single instance of the control filesystem + * exists. Protected by fuse_mutex + */ +static struct super_block *fuse_control_sb; + +static struct fuse_conn *fuse_ctl_file_conn_get(struct file *file) +{ + struct fuse_conn *fc; + mutex_lock(&fuse_mutex); + fc = file->f_dentry->d_inode->i_private; + if (fc) + fc = fuse_conn_get(fc); + mutex_unlock(&fuse_mutex); + return fc; +} + +static ssize_t fuse_conn_abort_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct fuse_conn *fc = fuse_ctl_file_conn_get(file); + if (fc) { + fuse_abort_conn(fc); + fuse_conn_put(fc); + } + return count; +} + +static ssize_t fuse_conn_waiting_read(struct file *file, char __user *buf, + size_t len, loff_t *ppos) +{ + char tmp[32]; + size_t size; + + if (!*ppos) { + struct fuse_conn *fc = fuse_ctl_file_conn_get(file); + if (!fc) + return 0; + + file->private_data=(void *)(long)atomic_read(&fc->num_waiting); + fuse_conn_put(fc); + } + size = sprintf(tmp, "%ld\n", (long)file->private_data); + return simple_read_from_buffer(buf, len, ppos, tmp, size); +} + +static const struct file_operations fuse_ctl_abort_ops = { + .open = nonseekable_open, + .write = fuse_conn_abort_write, +}; + +static const struct file_operations fuse_ctl_waiting_ops = { + .open = nonseekable_open, + .read = fuse_conn_waiting_read, +}; + +static struct dentry *fuse_ctl_add_dentry(struct dentry *parent, + struct fuse_conn *fc, + const char *name, + int mode, int nlink, + struct inode_operations *iop, + const struct file_operations *fop) +{ + struct dentry *dentry; + struct inode *inode; + + BUG_ON(fc->ctl_ndents >= FUSE_CTL_NUM_DENTRIES); + dentry = d_alloc_name(parent, name); + if (!dentry) + return NULL; + + fc->ctl_dentry[fc->ctl_ndents++] = dentry; + inode = new_inode(fuse_control_sb); + if (!inode) + return NULL; + + inode->i_mode = mode; + inode->i_uid = fc->user_id; + inode->i_gid = fc->group_id; + inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; + /* setting ->i_op to NULL is not allowed */ + if (iop) + inode->i_op = iop; + inode->i_fop = fop; + inode->i_nlink = nlink; + inode->i_private = fc; + d_add(dentry, inode); + return dentry; +} + +/* + * Add a connection to the control filesystem (if it exists). Caller + * must hold fuse_mutex + */ +int fuse_ctl_add_conn(struct fuse_conn *fc) +{ + struct dentry *parent; + char name[32]; + + if (!fuse_control_sb) + return 0; + + parent = fuse_control_sb->s_root; + parent->d_inode->i_nlink++; + sprintf(name, "%llu", (unsigned long long) fc->id); + parent = fuse_ctl_add_dentry(parent, fc, name, S_IFDIR | 0500, 2, + &simple_dir_inode_operations, + &simple_dir_operations); + if (!parent) + goto err; + + if (!fuse_ctl_add_dentry(parent, fc, "waiting", S_IFREG | 0400, 1, + NULL, &fuse_ctl_waiting_ops) || + !fuse_ctl_add_dentry(parent, fc, "abort", S_IFREG | 0200, 1, + NULL, &fuse_ctl_abort_ops)) + goto err; + + return 0; + + err: + fuse_ctl_remove_conn(fc); + return -ENOMEM; +} + +/* + * Remove a connection from the control filesystem (if it exists). + * Caller must hold fuse_mutex + */ +void fuse_ctl_remove_conn(struct fuse_conn *fc) +{ + int i; + + if (!fuse_control_sb) + return; + + for (i = fc->ctl_ndents - 1; i >= 0; i--) { + struct dentry *dentry = fc->ctl_dentry[i]; + dentry->d_inode->i_private = NULL; + d_drop(dentry); + dput(dentry); + } + fuse_control_sb->s_root->d_inode->i_nlink--; +} + +static int fuse_ctl_fill_super(struct super_block *sb, void *data, int silent) +{ + struct tree_descr empty_descr = {""}; + struct fuse_conn *fc; + int err; + + err = simple_fill_super(sb, FUSE_CTL_SUPER_MAGIC, &empty_descr); + if (err) + return err; + + mutex_lock(&fuse_mutex); + BUG_ON(fuse_control_sb); + fuse_control_sb = sb; + list_for_each_entry(fc, &fuse_conn_list, entry) { + err = fuse_ctl_add_conn(fc); + if (err) { + fuse_control_sb = NULL; + mutex_unlock(&fuse_mutex); + return err; + } + } + mutex_unlock(&fuse_mutex); + + return 0; +} + +static int fuse_ctl_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *raw_data, + struct vfsmount *mnt) +{ + return get_sb_single(fs_type, flags, raw_data, + fuse_ctl_fill_super, mnt); +} + +static void fuse_ctl_kill_sb(struct super_block *sb) +{ + mutex_lock(&fuse_mutex); + fuse_control_sb = NULL; + mutex_unlock(&fuse_mutex); + + kill_litter_super(sb); +} + +static struct file_system_type fuse_ctl_fs_type = { + .owner = THIS_MODULE, + .name = "fusectl", + .get_sb = fuse_ctl_get_sb, + .kill_sb = fuse_ctl_kill_sb, +}; + +int __init fuse_ctl_init(void) +{ + return register_filesystem(&fuse_ctl_fs_type); +} + +void fuse_ctl_cleanup(void) +{ + unregister_filesystem(&fuse_ctl_fs_type); +} diff --git a/fs/inotify_user.c b/fs/inotify_user.c new file mode 100644 index 000000000..017cb0f13 --- /dev/null +++ b/fs/inotify_user.c @@ -0,0 +1,719 @@ +/* + * fs/inotify_user.c - inotify support for userspace + * + * Authors: + * John McCutchan <ttb@tentacle.dhs.org> + * Robert Love <rml@novell.com> + * + * Copyright (C) 2005 John McCutchan + * Copyright 2006 Hewlett-Packard Development Company, L.P. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/fs.h> +#include <linux/file.h> +#include <linux/mount.h> +#include <linux/namei.h> +#include <linux/poll.h> +#include <linux/init.h> +#include <linux/list.h> +#include <linux/inotify.h> +#include <linux/syscalls.h> + +#include <asm/ioctls.h> + +static kmem_cache_t *watch_cachep __read_mostly; +static kmem_cache_t *event_cachep __read_mostly; + +static struct vfsmount *inotify_mnt __read_mostly; + +/* these are configurable via /proc/sys/fs/inotify/ */ +int inotify_max_user_instances __read_mostly; +int inotify_max_user_watches __read_mostly; +int inotify_max_queued_events __read_mostly; + +/* + * Lock ordering: + * + * inotify_dev->up_mutex (ensures we don't re-add the same watch) + * inode->inotify_mutex (protects inode's watch list) + * inotify_handle->mutex (protects inotify_handle's watch list) + * inotify_dev->ev_mutex (protects device's event queue) + */ + +/* + * Lifetimes of the main data structures: + * + * inotify_device: Lifetime is managed by reference count, from + * sys_inotify_init() until release. Additional references can bump the count + * via get_inotify_dev() and drop the count via put_inotify_dev(). + * + * inotify_user_watch: Lifetime is from create_watch() to the receipt of an + * IN_IGNORED event from inotify, or when using IN_ONESHOT, to receipt of the + * first event, or to inotify_destroy(). + */ + +/* + * struct inotify_device - represents an inotify instance + * + * This structure is protected by the mutex 'mutex'. + */ +struct inotify_device { + wait_queue_head_t wq; /* wait queue for i/o */ + struct mutex ev_mutex; /* protects event queue */ + struct mutex up_mutex; /* synchronizes watch updates */ + struct list_head events; /* list of queued events */ + atomic_t count; /* reference count */ + struct user_struct *user; /* user who opened this dev */ + struct inotify_handle *ih; /* inotify handle */ + unsigned int queue_size; /* size of the queue (bytes) */ + unsigned int event_count; /* number of pending events */ + unsigned int max_events; /* maximum number of events */ +}; + +/* + * struct inotify_kernel_event - An inotify event, originating from a watch and + * queued for user-space. A list of these is attached to each instance of the + * device. In read(), this list is walked and all events that can fit in the + * buffer are returned. + * + * Protected by dev->ev_mutex of the device in which we are queued. + */ +struct inotify_kernel_event { + struct inotify_event event; /* the user-space event */ + struct list_head list; /* entry in inotify_device's list */ + char *name; /* filename, if any */ +}; + +/* + * struct inotify_user_watch - our version of an inotify_watch, we add + * a reference to the associated inotify_device. + */ +struct inotify_user_watch { + struct inotify_device *dev; /* associated device */ + struct inotify_watch wdata; /* inotify watch data */ +}; + +#ifdef CONFIG_SYSCTL + +#include <linux/sysctl.h> + +static int zero; + +ctl_table inotify_table[] = { + { + .ctl_name = INOTIFY_MAX_USER_INSTANCES, + .procname = "max_user_instances", + .data = &inotify_max_user_instances, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec_minmax, + .strategy = &sysctl_intvec, + .extra1 = &zero, + }, + { + .ctl_name = INOTIFY_MAX_USER_WATCHES, + .procname = "max_user_watches", + .data = &inotify_max_user_watches, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec_minmax, + .strategy = &sysctl_intvec, + .extra1 = &zero, + }, + { + .ctl_name = INOTIFY_MAX_QUEUED_EVENTS, + .procname = "max_queued_events", + .data = &inotify_max_queued_events, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec_minmax, + .strategy = &sysctl_intvec, + .extra1 = &zero + }, + { .ctl_name = 0 } +}; +#endif /* CONFIG_SYSCTL */ + +static inline void get_inotify_dev(struct inotify_device *dev) +{ + atomic_inc(&dev->count); +} + +static inline void put_inotify_dev(struct inotify_device *dev) +{ + if (atomic_dec_and_test(&dev->count)) { + atomic_dec(&dev->user->inotify_devs); + free_uid(dev->user); + kfree(dev); + } +} + +/* + * free_inotify_user_watch - cleans up the watch and its references + */ +static void free_inotify_user_watch(struct inotify_watch *w) +{ + struct inotify_user_watch *watch; + struct inotify_device *dev; + + watch = container_of(w, struct inotify_user_watch, wdata); + dev = watch->dev; + + atomic_dec(&dev->user->inotify_watches); + put_inotify_dev(dev); + kmem_cache_free(watch_cachep, watch); +} + +/* + * kernel_event - create a new kernel event with the given parameters + * + * This function can sleep. + */ +static struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie, + const char *name) +{ + struct inotify_kernel_event *kevent; + + kevent = kmem_cache_alloc(event_cachep, GFP_NOFS); + if (unlikely(!kevent)) + return NULL; + + /* we hand this out to user-space, so zero it just in case */ + memset(&kevent->event, 0, sizeof(struct inotify_event)); + + kevent->event.wd = wd; + kevent->event.mask = mask; + kevent->event.cookie = cookie; + + INIT_LIST_HEAD(&kevent->list); + + if (name) { + size_t len, rem, event_size = sizeof(struct inotify_event); + + /* + * We need to pad the filename so as to properly align an + * array of inotify_event structures. Because the structure is + * small and the common case is a small filename, we just round + * up to the next multiple of the structure's sizeof. This is + * simple and safe for all architectures. + */ + len = strlen(name) + 1; + rem = event_size - len; + if (len > event_size) { + rem = event_size - (len % event_size); + if (len % event_size == 0) + rem = 0; + } + + kevent->name = kmalloc(len + rem, GFP_KERNEL); + if (unlikely(!kevent->name)) { + kmem_cache_free(event_cachep, kevent); + return NULL; + } + memcpy(kevent->name, name, len); + if (rem) + memset(kevent->name + len, 0, rem); + kevent->event.len = len + rem; + } else { + kevent->event.len = 0; + kevent->name = NULL; + } + + return kevent; +} + +/* + * inotify_dev_get_event - return the next event in the given dev's queue + * + * Caller must hold dev->ev_mutex. + */ +static inline struct inotify_kernel_event * +inotify_dev_get_event(struct inotify_device *dev) +{ + return list_entry(dev->events.next, struct inotify_kernel_event, list); +} + +/* + * inotify_dev_queue_event - event handler registered with core inotify, adds + * a new event to the given device + * + * Can sleep (calls kernel_event()). + */ +static void inotify_dev_queue_event(struct inotify_watch *w, u32 wd, u32 mask, + u32 cookie, const char *name, + struct inode *ignored) +{ + struct inotify_user_watch *watch; + struct inotify_device *dev; + struct inotify_kernel_event *kevent, *last; + + watch = container_of(w, struct inotify_user_watch, wdata); + dev = watch->dev; + + mutex_lock(&dev->ev_mutex); + + /* we can safely put the watch as we don't reference it while + * generating the event + */ + if (mask & IN_IGNORED || mask & IN_ONESHOT) + put_inotify_watch(w); /* final put */ + + /* coalescing: drop this event if it is a dupe of the previous */ + last = inotify_dev_get_event(dev); + if (last && last->event.mask == mask && last->event.wd == wd && + last->event.cookie == cookie) { + const char *lastname = last->name; + + if (!name && !lastname) + goto out; + if (name && lastname && !strcmp(lastname, name)) + goto out; + } + + /* the queue overflowed and we already sent the Q_OVERFLOW event */ + if (unlikely(dev->event_count > dev->max_events)) + goto out; + + /* if the queue overflows, we need to notify user space */ + if (unlikely(dev->event_count == dev->max_events)) + kevent = kernel_event(-1, IN_Q_OVERFLOW, cookie, NULL); + else + kevent = kernel_event(wd, mask, cookie, name); + + if (unlikely(!kevent)) + goto out; + + /* queue the event and wake up anyone waiting */ + dev->event_count++; + dev->queue_size += sizeof(struct inotify_event) + kevent->event.len; + list_add_tail(&kevent->list, &dev->events); + wake_up_interruptible(&dev->wq); + +out: + mutex_unlock(&dev->ev_mutex); +} + +/* + * remove_kevent - cleans up and ultimately frees the given kevent + * + * Caller must hold dev->ev_mutex. + */ +static void remove_kevent(struct inotify_device *dev, + struct inotify_kernel_event *kevent) +{ + list_del(&kevent->list); + + dev->event_count--; + dev->queue_size -= sizeof(struct inotify_event) + kevent->event.len; + + kfree(kevent->name); + kmem_cache_free(event_cachep, kevent); +} + +/* + * inotify_dev_event_dequeue - destroy an event on the given device + * + * Caller must hold dev->ev_mutex. + */ +static void inotify_dev_event_dequeue(struct inotify_device *dev) +{ + if (!list_empty(&dev->events)) { + struct inotify_kernel_event *kevent; + kevent = inotify_dev_get_event(dev); + remove_kevent(dev, kevent); + } +} + +/* + * find_inode - resolve a user-given path to a specific inode and return a nd + */ +static int find_inode(const char __user *dirname, struct nameidata *nd, + unsigned flags) +{ + int error; + + error = __user_walk(dirname, flags, nd); + if (error) + return error; + /* you can only watch an inode if you have read permissions on it */ + error = vfs_permission(nd, MAY_READ); + if (error) + path_release(nd); + return error; +} + +/* + * create_watch - creates a watch on the given device. + * + * Callers must hold dev->up_mutex. + */ +static int create_watch(struct inotify_device *dev, struct inode *inode, + u32 mask) +{ + struct inotify_user_watch *watch; + int ret; + + if (atomic_read(&dev->user->inotify_watches) >= + inotify_max_user_watches) + return -ENOSPC; + + watch = kmem_cache_alloc(watch_cachep, GFP_KERNEL); + if (unlikely(!watch)) + return -ENOMEM; + + /* save a reference to device and bump the count to make it official */ + get_inotify_dev(dev); + watch->dev = dev; + + atomic_inc(&dev->user->inotify_watches); + + inotify_init_watch(&watch->wdata); + ret = inotify_add_watch(dev->ih, &watch->wdata, inode, mask); + if (ret < 0) + free_inotify_user_watch(&watch->wdata); + + return ret; +} + +/* Device Interface */ + +static unsigned int inotify_poll(struct file *file, poll_table *wait) +{ + struct inotify_device *dev = file->private_data; + int ret = 0; + + poll_wait(file, &dev->wq, wait); + mutex_lock(&dev->ev_mutex); + if (!list_empty(&dev->events)) + ret = POLLIN | POLLRDNORM; + mutex_unlock(&dev->ev_mutex); + + return ret; +} + +static ssize_t inotify_read(struct file *file, char __user *buf, + size_t count, loff_t *pos) +{ + size_t event_size = sizeof (struct inotify_event); + struct inotify_device *dev; + char __user *start; + int ret; + DEFINE_WAIT(wait); + + start = buf; + dev = file->private_data; + + while (1) { + int events; + + prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE); + + mutex_lock(&dev->ev_mutex); + events = !list_empty(&dev->events); + mutex_unlock(&dev->ev_mutex); + if (events) { + ret = 0; + break; + } + + if (file->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + break; + } + + if (signal_pending(current)) { + ret = -EINTR; + break; + } + + schedule(); + } + + finish_wait(&dev->wq, &wait); + if (ret) + return ret; + + mutex_lock(&dev->ev_mutex); + while (1) { + struct inotify_kernel_event *kevent; + + ret = buf - start; + if (list_empty(&dev->events)) + break; + + kevent = inotify_dev_get_event(dev); + if (event_size + kevent->event.len > count) + break; + + if (copy_to_user(buf, &kevent->event, event_size)) { + ret = -EFAULT; + break; + } + buf += event_size; + count -= event_size; + + if (kevent->name) { + if (copy_to_user(buf, kevent->name, kevent->event.len)){ + ret = -EFAULT; + break; + } + buf += kevent->event.len; + count -= kevent->event.len; + } + + remove_kevent(dev, kevent); + } + mutex_unlock(&dev->ev_mutex); + + return ret; +} + +static int inotify_release(struct inode *ignored, struct file *file) +{ + struct inotify_device *dev = file->private_data; + + inotify_destroy(dev->ih); + + /* destroy all of the events on this device */ + mutex_lock(&dev->ev_mutex); + while (!list_empty(&dev->events)) + inotify_dev_event_dequeue(dev); + mutex_unlock(&dev->ev_mutex); + + /* free this device: the put matching the get in inotify_init() */ + put_inotify_dev(dev); + + return 0; +} + +static long inotify_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct inotify_device *dev; + void __user *p; + int ret = -ENOTTY; + + dev = file->private_data; + p = (void __user *) arg; + + switch (cmd) { + case FIONREAD: + ret = put_user(dev->queue_size, (int __user *) p); + break; + } + + return ret; +} + +static const struct file_operations inotify_fops = { + .poll = inotify_poll, + .read = inotify_read, + .release = inotify_release, + .unlocked_ioctl = inotify_ioctl, + .compat_ioctl = inotify_ioctl, +}; + +static const struct inotify_operations inotify_user_ops = { + .handle_event = inotify_dev_queue_event, + .destroy_watch = free_inotify_user_watch, +}; + +asmlinkage long sys_inotify_init(void) +{ + struct inotify_device *dev; + struct inotify_handle *ih; + struct user_struct *user; + struct file *filp; + int fd, ret; + + fd = get_unused_fd(); + if (fd < 0) + return fd; + + filp = get_empty_filp(); + if (!filp) { + ret = -ENFILE; + goto out_put_fd; + } + + user = get_uid(current->user); + if (unlikely(atomic_read(&user->inotify_devs) >= + inotify_max_user_instances)) { + ret = -EMFILE; + goto out_free_uid; + } + + dev = kmalloc(sizeof(struct inotify_device), GFP_KERNEL); + if (unlikely(!dev)) { + ret = -ENOMEM; + goto out_free_uid; + } + + ih = inotify_init(&inotify_user_ops); + if (unlikely(IS_ERR(ih))) { + ret = PTR_ERR(ih); + goto out_free_dev; + } + dev->ih = ih; + + filp->f_op = &inotify_fops; + filp->f_vfsmnt = mntget(inotify_mnt); + filp->f_dentry = dget(inotify_mnt->mnt_root); + filp->f_mapping = filp->f_dentry->d_inode->i_mapping; + filp->f_mode = FMODE_READ; + filp->f_flags = O_RDONLY; + filp->private_data = dev; + + INIT_LIST_HEAD(&dev->events); + init_waitqueue_head(&dev->wq); + mutex_init(&dev->ev_mutex); + mutex_init(&dev->up_mutex); + dev->event_count = 0; + dev->queue_size = 0; + dev->max_events = inotify_max_queued_events; + dev->user = user; + atomic_set(&dev->count, 0); + + get_inotify_dev(dev); + atomic_inc(&user->inotify_devs); + fd_install(fd, filp); + + return fd; +out_free_dev: + kfree(dev); +out_free_uid: + free_uid(user); + put_filp(filp); +out_put_fd: + put_unused_fd(fd); + return ret; +} + +asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) +{ + struct inode *inode; + struct inotify_device *dev; + struct nameidata nd; + struct file *filp; + int ret, fput_needed; + unsigned flags = 0; + + filp = fget_light(fd, &fput_needed); + if (unlikely(!filp)) + return -EBADF; + + /* verify that this is indeed an inotify instance */ + if (unlikely(filp->f_op != &inotify_fops)) { + ret = -EINVAL; + goto fput_and_out; + } + + if (!(mask & IN_DONT_FOLLOW)) + flags |= LOOKUP_FOLLOW; + if (mask & IN_ONLYDIR) + flags |= LOOKUP_DIRECTORY; + + ret = find_inode(path, &nd, flags); + if (unlikely(ret)) + goto fput_and_out; + + /* inode held in place by reference to nd; dev by fget on fd */ + inode = nd.dentry->d_inode; + dev = filp->private_data; + + mutex_lock(&dev->up_mutex); + ret = inotify_find_update_watch(dev->ih, inode, mask); + if (ret == -ENOENT) + ret = create_watch(dev, inode, mask); + mutex_unlock(&dev->up_mutex); + + path_release(&nd); +fput_and_out: + fput_light(filp, fput_needed); + return ret; +} + +asmlinkage long sys_inotify_rm_watch(int fd, u32 wd) +{ + struct file *filp; + struct inotify_device *dev; + int ret, fput_needed; + + filp = fget_light(fd, &fput_needed); + if (unlikely(!filp)) + return -EBADF; + + /* verify that this is indeed an inotify instance */ + if (unlikely(filp->f_op != &inotify_fops)) { + ret = -EINVAL; + goto out; + } + + dev = filp->private_data; + + /* we free our watch data when we get IN_IGNORED */ + ret = inotify_rm_wd(dev->ih, wd); + +out: + fput_light(filp, fput_needed); + return ret; +} + +static int +inotify_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, struct vfsmount *mnt) +{ + return get_sb_pseudo(fs_type, "inotify", NULL, 0xBAD1DEA, mnt); +} + +static struct file_system_type inotify_fs_type = { + .name = "inotifyfs", + .get_sb = inotify_get_sb, + .kill_sb = kill_anon_super, +}; + +/* + * inotify_user_setup - Our initialization function. Note that we cannnot return + * error because we have compiled-in VFS hooks. So an (unlikely) failure here + * must result in panic(). + */ +static int __init inotify_user_setup(void) +{ + int ret; + + ret = register_filesystem(&inotify_fs_type); + if (unlikely(ret)) + panic("inotify: register_filesystem returned %d!\n", ret); + + inotify_mnt = kern_mount(&inotify_fs_type); + if (IS_ERR(inotify_mnt)) + panic("inotify: kern_mount ret %ld!\n", PTR_ERR(inotify_mnt)); + + inotify_max_queued_events = 16384; + inotify_max_user_instances = 128; + inotify_max_user_watches = 8192; + + watch_cachep = kmem_cache_create("inotify_watch_cache", + sizeof(struct inotify_user_watch), + 0, SLAB_PANIC, NULL, NULL); + event_cachep = kmem_cache_create("inotify_event_cache", + sizeof(struct inotify_kernel_event), + 0, SLAB_PANIC, NULL, NULL); + + return 0; +} + +module_init(inotify_user_setup); diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c new file mode 100644 index 000000000..0ae3cd107 --- /dev/null +++ b/fs/jffs2/acl.c @@ -0,0 +1,485 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright (C) 2006 NEC Corporation + * + * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> + * + * For licensing information, see the file 'LICENCE' in this directory. + * + */ +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/fs.h> +#include <linux/time.h> +#include <linux/crc32.h> +#include <linux/jffs2.h> +#include <linux/xattr.h> +#include <linux/posix_acl_xattr.h> +#include <linux/mtd/mtd.h> +#include "nodelist.h" + +static size_t jffs2_acl_size(int count) +{ + if (count <= 4) { + return sizeof(struct jffs2_acl_header) + + count * sizeof(struct jffs2_acl_entry_short); + } else { + return sizeof(struct jffs2_acl_header) + + 4 * sizeof(struct jffs2_acl_entry_short) + + (count - 4) * sizeof(struct jffs2_acl_entry); + } +} + +static int jffs2_acl_count(size_t size) +{ + size_t s; + + size -= sizeof(struct jffs2_acl_header); + s = size - 4 * sizeof(struct jffs2_acl_entry_short); + if (s < 0) { + if (size % sizeof(struct jffs2_acl_entry_short)) + return -1; + return size / sizeof(struct jffs2_acl_entry_short); + } else { + if (s % sizeof(struct jffs2_acl_entry)) + return -1; + return s / sizeof(struct jffs2_acl_entry) + 4; + } +} + +static struct posix_acl *jffs2_acl_from_medium(void *value, size_t size) +{ + void *end = value + size; + struct jffs2_acl_header *header = value; + struct jffs2_acl_entry *entry; + struct posix_acl *acl; + uint32_t ver; + int i, count; + + if (!value) + return NULL; + if (size < sizeof(struct jffs2_acl_header)) + return ERR_PTR(-EINVAL); + ver = je32_to_cpu(header->a_version); + if (ver != JFFS2_ACL_VERSION) { + JFFS2_WARNING("Invalid ACL version. (=%u)\n", ver); + return ERR_PTR(-EINVAL); + } + + value += sizeof(struct jffs2_acl_header); + count = jffs2_acl_count(size); + if (count < 0) + return ERR_PTR(-EINVAL); + if (count == 0) + return NULL; + + acl = posix_acl_alloc(count, GFP_KERNEL); + if (!acl) + return ERR_PTR(-ENOMEM); + + for (i=0; i < count; i++) { + entry = value; + if (value + sizeof(struct jffs2_acl_entry_short) > end) + goto fail; + acl->a_entries[i].e_tag = je16_to_cpu(entry->e_tag); + acl->a_entries[i].e_perm = je16_to_cpu(entry->e_perm); + switch (acl->a_entries[i].e_tag) { + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + case ACL_MASK: + case ACL_OTHER: + value += sizeof(struct jffs2_acl_entry_short); + acl->a_entries[i].e_id = ACL_UNDEFINED_ID; + break; + + case ACL_USER: + case ACL_GROUP: + value += sizeof(struct jffs2_acl_entry); + if (value > end) + goto fail; + acl->a_entries[i].e_id = je32_to_cpu(entry->e_id); + break; + + default: + goto fail; + } + } + if (value != end) + goto fail; + return acl; + fail: + posix_acl_release(acl); + return ERR_PTR(-EINVAL); +} + +static void *jffs2_acl_to_medium(const struct posix_acl *acl, size_t *size) +{ + struct jffs2_acl_header *header; + struct jffs2_acl_entry *entry; + void *e; + size_t i; + + *size = jffs2_acl_size(acl->a_count); + header = kmalloc(sizeof(*header) + acl->a_count * sizeof(*entry), GFP_KERNEL); + if (!header) + return ERR_PTR(-ENOMEM); + header->a_version = cpu_to_je32(JFFS2_ACL_VERSION); + e = header + 1; + for (i=0; i < acl->a_count; i++) { + entry = e; + entry->e_tag = cpu_to_je16(acl->a_entries[i].e_tag); + entry->e_perm = cpu_to_je16(acl->a_entries[i].e_perm); + switch(acl->a_entries[i].e_tag) { + case ACL_USER: + case ACL_GROUP: + entry->e_id = cpu_to_je32(acl->a_entries[i].e_id); + e += sizeof(struct jffs2_acl_entry); + break; + + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + case ACL_MASK: + case ACL_OTHER: + e += sizeof(struct jffs2_acl_entry_short); + break; + + default: + goto fail; + } + } + return header; + fail: + kfree(header); + return ERR_PTR(-EINVAL); +} + +static struct posix_acl *jffs2_iget_acl(struct inode *inode, struct posix_acl **i_acl) +{ + struct posix_acl *acl = JFFS2_ACL_NOT_CACHED; + + spin_lock(&inode->i_lock); + if (*i_acl != JFFS2_ACL_NOT_CACHED) + acl = posix_acl_dup(*i_acl); + spin_unlock(&inode->i_lock); + return acl; +} + +static void jffs2_iset_acl(struct inode *inode, struct posix_acl **i_acl, struct posix_acl *acl) +{ + spin_lock(&inode->i_lock); + if (*i_acl != JFFS2_ACL_NOT_CACHED) + posix_acl_release(*i_acl); + *i_acl = posix_acl_dup(acl); + spin_unlock(&inode->i_lock); +} + +static struct posix_acl *jffs2_get_acl(struct inode *inode, int type) +{ + struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); + struct posix_acl *acl; + char *value = NULL; + int rc, xprefix; + + switch (type) { + case ACL_TYPE_ACCESS: + acl = jffs2_iget_acl(inode, &f->i_acl_access); + if (acl != JFFS2_ACL_NOT_CACHED) + return acl; + xprefix = JFFS2_XPREFIX_ACL_ACCESS; + break; + case ACL_TYPE_DEFAULT: + acl = jffs2_iget_acl(inode, &f->i_acl_default); + if (acl != JFFS2_ACL_NOT_CACHED) + return acl; + xprefix = JFFS2_XPREFIX_ACL_DEFAULT; + break; + default: + return ERR_PTR(-EINVAL); + } + rc = do_jffs2_getxattr(inode, xprefix, "", NULL, 0); + if (rc > 0) { + value = kmalloc(rc, GFP_KERNEL); + if (!value) + return ERR_PTR(-ENOMEM); + rc = do_jffs2_getxattr(inode, xprefix, "", value, rc); + } + if (rc > 0) { + acl = jffs2_acl_from_medium(value, rc); + } else if (rc == -ENODATA || rc == -ENOSYS) { + acl = NULL; + } else { + acl = ERR_PTR(rc); + } + if (value) + kfree(value); + if (!IS_ERR(acl)) { + switch (type) { + case ACL_TYPE_ACCESS: + jffs2_iset_acl(inode, &f->i_acl_access, acl); + break; + case ACL_TYPE_DEFAULT: + jffs2_iset_acl(inode, &f->i_acl_default, acl); + break; + } + } + return acl; +} + +static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) +{ + struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); + size_t size = 0; + char *value = NULL; + int rc, xprefix; + + if (S_ISLNK(inode->i_mode)) + return -EOPNOTSUPP; + + switch (type) { + case ACL_TYPE_ACCESS: + xprefix = JFFS2_XPREFIX_ACL_ACCESS; + if (acl) { + mode_t mode = inode->i_mode; + rc = posix_acl_equiv_mode(acl, &mode); + if (rc < 0) + return rc; + if (inode->i_mode != mode) { + inode->i_mode = mode; + jffs2_dirty_inode(inode); + } + if (rc == 0) + acl = NULL; + } + break; + case ACL_TYPE_DEFAULT: + xprefix = JFFS2_XPREFIX_ACL_DEFAULT; + if (!S_ISDIR(inode->i_mode)) + return acl ? -EACCES : 0; + break; + default: + return -EINVAL; + } + if (acl) { + value = jffs2_acl_to_medium(acl, &size); + if (IS_ERR(value)) + return PTR_ERR(value); + } + + rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0); + if (!value && rc == -ENODATA) + rc = 0; + if (value) + kfree(value); + if (!rc) { + switch(type) { + case ACL_TYPE_ACCESS: + jffs2_iset_acl(inode, &f->i_acl_access, acl); + break; + case ACL_TYPE_DEFAULT: + jffs2_iset_acl(inode, &f->i_acl_default, acl); + break; + } + } + return rc; +} + +static int jffs2_check_acl(struct inode *inode, int mask) +{ + struct posix_acl *acl; + int rc; + + acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS); + if (IS_ERR(acl)) + return PTR_ERR(acl); + if (acl) { + rc = posix_acl_permission(inode, acl, mask); + posix_acl_release(acl); + return rc; + } + return -EAGAIN; +} + +int jffs2_permission(struct inode *inode, int mask, struct nameidata *nd) +{ + return generic_permission(inode, mask, jffs2_check_acl); +} + +int jffs2_init_acl(struct inode *inode, struct inode *dir) +{ + struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); + struct posix_acl *acl = NULL, *clone; + mode_t mode; + int rc = 0; + + f->i_acl_access = JFFS2_ACL_NOT_CACHED; + f->i_acl_default = JFFS2_ACL_NOT_CACHED; + if (!S_ISLNK(inode->i_mode)) { + acl = jffs2_get_acl(dir, ACL_TYPE_DEFAULT); + if (IS_ERR(acl)) + return PTR_ERR(acl); + if (!acl) + inode->i_mode &= ~current->fs->umask; + } + if (acl) { + if (S_ISDIR(inode->i_mode)) { + rc = jffs2_set_acl(inode, ACL_TYPE_DEFAULT, acl); + if (rc) + goto cleanup; + } + clone = posix_acl_clone(acl, GFP_KERNEL); + rc = -ENOMEM; + if (!clone) + goto cleanup; + mode = inode->i_mode; + rc = posix_acl_create_masq(clone, &mode); + if (rc >= 0) { + inode->i_mode = mode; + if (rc > 0) + rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone); + } + posix_acl_release(clone); + } + cleanup: + posix_acl_release(acl); + return rc; +} + +void jffs2_clear_acl(struct jffs2_inode_info *f) +{ + if (f->i_acl_access && f->i_acl_access != JFFS2_ACL_NOT_CACHED) { + posix_acl_release(f->i_acl_access); + f->i_acl_access = JFFS2_ACL_NOT_CACHED; + } + if (f->i_acl_default && f->i_acl_default != JFFS2_ACL_NOT_CACHED) { + posix_acl_release(f->i_acl_default); + f->i_acl_default = JFFS2_ACL_NOT_CACHED; + } +} + +int jffs2_acl_chmod(struct inode *inode) +{ + struct posix_acl *acl, *clone; + int rc; + + if (S_ISLNK(inode->i_mode)) + return -EOPNOTSUPP; + acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS); + if (IS_ERR(acl) || !acl) + return PTR_ERR(acl); + clone = posix_acl_clone(acl, GFP_KERNEL); + posix_acl_release(acl); + if (!clone) + return -ENOMEM; + rc = posix_acl_chmod_masq(clone, inode->i_mode); + if (!rc) + rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone); + posix_acl_release(clone); + return rc; +} + +static size_t jffs2_acl_access_listxattr(struct inode *inode, char *list, size_t list_size, + const char *name, size_t name_len) +{ + const int retlen = sizeof(POSIX_ACL_XATTR_ACCESS); + + if (list && retlen <= list_size) + strcpy(list, POSIX_ACL_XATTR_ACCESS); + return retlen; +} + +static size_t jffs2_acl_default_listxattr(struct inode *inode, char *list, size_t list_size, + const char *name, size_t name_len) +{ + const int retlen = sizeof(POSIX_ACL_XATTR_DEFAULT); + + if (list && retlen <= list_size) + strcpy(list, POSIX_ACL_XATTR_DEFAULT); + return retlen; +} + +static int jffs2_acl_getxattr(struct inode *inode, int type, void *buffer, size_t size) +{ + struct posix_acl *acl; + int rc; + + acl = jffs2_get_acl(inode, type); + if (IS_ERR(acl)) + return PTR_ERR(acl); + if (!acl) + return -ENODATA; + rc = posix_acl_to_xattr(acl, buffer, size); + posix_acl_release(acl); + + return rc; +} + +static int jffs2_acl_access_getxattr(struct inode *inode, const char *name, void *buffer, size_t size) +{ + if (name[0] != '\0') + return -EINVAL; + return jffs2_acl_getxattr(inode, ACL_TYPE_ACCESS, buffer, size); +} + +static int jffs2_acl_default_getxattr(struct inode *inode, const char *name, void *buffer, size_t size) +{ + if (name[0] != '\0') + return -EINVAL; + return jffs2_acl_getxattr(inode, ACL_TYPE_DEFAULT, buffer, size); +} + +static int jffs2_acl_setxattr(struct inode *inode, int type, const void *value, size_t size) +{ + struct posix_acl *acl; + int rc; + + if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) + return -EPERM; + + if (value) { + acl = posix_acl_from_xattr(value, size); + if (IS_ERR(acl)) + return PTR_ERR(acl); + if (acl) { + rc = posix_acl_valid(acl); + if (rc) + goto out; + } + } else { + acl = NULL; + } + rc = jffs2_set_acl(inode, type, acl); + out: + posix_acl_release(acl); + return rc; +} + +static int jffs2_acl_access_setxattr(struct inode *inode, const char *name, + const void *buffer, size_t size, int flags) +{ + if (name[0] != '\0') + return -EINVAL; + return jffs2_acl_setxattr(inode, ACL_TYPE_ACCESS, buffer, size); +} + +static int jffs2_acl_default_setxattr(struct inode *inode, const char *name, + const void *buffer, size_t size, int flags) +{ + if (name[0] != '\0') + return -EINVAL; + return jffs2_acl_setxattr(inode, ACL_TYPE_DEFAULT, buffer, size); +} + +struct xattr_handler jffs2_acl_access_xattr_handler = { + .prefix = POSIX_ACL_XATTR_ACCESS, + .list = jffs2_acl_access_listxattr, + .get = jffs2_acl_access_getxattr, + .set = jffs2_acl_access_setxattr, +}; + +struct xattr_handler jffs2_acl_default_xattr_handler = { + .prefix = POSIX_ACL_XATTR_DEFAULT, + .list = jffs2_acl_default_listxattr, + .get = jffs2_acl_default_getxattr, + .set = jffs2_acl_default_setxattr, +}; diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h new file mode 100644 index 000000000..fa327dbd3 --- /dev/null +++ b/fs/jffs2/acl.h @@ -0,0 +1,45 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright (C) 2006 NEC Corporation + * + * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> + * + * For licensing information, see the file 'LICENCE' in this directory. + * + */ +struct jffs2_acl_entry { + jint16_t e_tag; + jint16_t e_perm; + jint32_t e_id; +}; + +struct jffs2_acl_entry_short { + jint16_t e_tag; + jint16_t e_perm; +}; + +struct jffs2_acl_header { + jint32_t a_version; +}; + +#ifdef CONFIG_JFFS2_FS_POSIX_ACL + +#define JFFS2_ACL_NOT_CACHED ((void *)-1) + +extern int jffs2_permission(struct inode *, int, struct nameidata *); +extern int jffs2_acl_chmod(struct inode *); +extern int jffs2_init_acl(struct inode *, struct inode *); +extern void jffs2_clear_acl(struct jffs2_inode_info *); + +extern struct xattr_handler jffs2_acl_access_xattr_handler; +extern struct xattr_handler jffs2_acl_default_xattr_handler; + +#else + +#define jffs2_permission NULL +#define jffs2_acl_chmod(inode) (0) +#define jffs2_init_acl(inode,dir) (0) +#define jffs2_clear_acl(f) + +#endif /* CONFIG_JFFS2_FS_POSIX_ACL */ diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h new file mode 100644 index 000000000..2e0cc8e00 --- /dev/null +++ b/fs/jffs2/jffs2_fs_i.h @@ -0,0 +1,55 @@ +/* $Id: jffs2_fs_i.h,v 1.19 2005/11/07 11:14:52 gleixner Exp $ */ + +#ifndef _JFFS2_FS_I +#define _JFFS2_FS_I + +#include <linux/version.h> +#include <linux/rbtree.h> +#include <linux/posix_acl.h> +#include <asm/semaphore.h> + +struct jffs2_inode_info { + /* We need an internal mutex similar to inode->i_mutex. + Unfortunately, we can't used the existing one, because + either the GC would deadlock, or we'd have to release it + before letting GC proceed. Or we'd have to put ugliness + into the GC code so it didn't attempt to obtain the i_mutex + for the inode(s) which are already locked */ + struct semaphore sem; + + /* The highest (datanode) version number used for this ino */ + uint32_t highest_version; + + /* List of data fragments which make up the file */ + struct rb_root fragtree; + + /* There may be one datanode which isn't referenced by any of the + above fragments, if it contains a metadata update but no actual + data - or if this is a directory inode */ + /* This also holds the _only_ dnode for symlinks/device nodes, + etc. */ + struct jffs2_full_dnode *metadata; + + /* Directory entries */ + struct jffs2_full_dirent *dents; + + /* The target path if this is the inode of a symlink */ + unsigned char *target; + + /* Some stuff we just have to keep in-core at all times, for each inode. */ + struct jffs2_inode_cache *inocache; + + uint16_t flags; + uint8_t usercompr; +#if !defined (__ECOS) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2) + struct inode vfs_inode; +#endif +#endif +#ifdef CONFIG_JFFS2_FS_POSIX_ACL + struct posix_acl *i_acl_access; + struct posix_acl *i_acl_default; +#endif +}; + +#endif /* _JFFS2_FS_I */ diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h new file mode 100644 index 000000000..b98594992 --- /dev/null +++ b/fs/jffs2/jffs2_fs_sb.h @@ -0,0 +1,136 @@ +/* $Id: jffs2_fs_sb.h,v 1.54 2005/09/21 13:37:34 dedekind Exp $ */ + +#ifndef _JFFS2_FS_SB +#define _JFFS2_FS_SB + +#include <linux/types.h> +#include <linux/spinlock.h> +#include <linux/workqueue.h> +#include <linux/completion.h> +#include <asm/semaphore.h> +#include <linux/timer.h> +#include <linux/wait.h> +#include <linux/list.h> +#include <linux/rwsem.h> + +#define JFFS2_SB_FLAG_RO 1 +#define JFFS2_SB_FLAG_SCANNING 2 /* Flash scanning is in progress */ +#define JFFS2_SB_FLAG_BUILDING 4 /* File system building is in progress */ + +struct jffs2_inodirty; + +/* A struct for the overall file system control. Pointers to + jffs2_sb_info structs are named `c' in the source code. + Nee jffs_control +*/ +struct jffs2_sb_info { + struct mtd_info *mtd; + + uint32_t highest_ino; + uint32_t checked_ino; + + unsigned int flags; + + struct task_struct *gc_task; /* GC task struct */ + struct completion gc_thread_start; /* GC thread start completion */ + struct completion gc_thread_exit; /* GC thread exit completion port */ + + struct semaphore alloc_sem; /* Used to protect all the following + fields, and also to protect against + out-of-order writing of nodes. And GC. */ + uint32_t cleanmarker_size; /* Size of an _inline_ CLEANMARKER + (i.e. zero for OOB CLEANMARKER */ + + uint32_t flash_size; + uint32_t used_size; + uint32_t dirty_size; + uint32_t wasted_size; + uint32_t free_size; + uint32_t erasing_size; + uint32_t bad_size; + uint32_t sector_size; + uint32_t unchecked_size; + + uint32_t nr_free_blocks; + uint32_t nr_erasing_blocks; + + /* Number of free blocks there must be before we... */ + uint8_t resv_blocks_write; /* ... allow a normal filesystem write */ + uint8_t resv_blocks_deletion; /* ... allow a normal filesystem deletion */ + uint8_t resv_blocks_gctrigger; /* ... wake up the GC thread */ + uint8_t resv_blocks_gcbad; /* ... pick a block from the bad_list to GC */ + uint8_t resv_blocks_gcmerge; /* ... merge pages when garbage collecting */ + + uint32_t nospc_dirty_size; + + uint32_t nr_blocks; + struct jffs2_eraseblock *blocks; /* The whole array of blocks. Used for getting blocks + * from the offset (blocks[ofs / sector_size]) */ + struct jffs2_eraseblock *nextblock; /* The block we're currently filling */ + + struct jffs2_eraseblock *gcblock; /* The block we're currently garbage-collecting */ + + struct list_head clean_list; /* Blocks 100% full of clean data */ + struct list_head very_dirty_list; /* Blocks with lots of dirty space */ + struct list_head dirty_list; /* Blocks with some dirty space */ + struct list_head erasable_list; /* Blocks which are completely dirty, and need erasing */ + struct list_head erasable_pending_wbuf_list; /* Blocks which need erasing but only after the current wbuf is flushed */ + struct list_head erasing_list; /* Blocks which are currently erasing */ + struct list_head erase_pending_list; /* Blocks which need erasing now */ + struct list_head erase_complete_list; /* Blocks which are erased and need the clean marker written to them */ + struct list_head free_list; /* Blocks which are free and ready to be used */ + struct list_head bad_list; /* Bad blocks. */ + struct list_head bad_used_list; /* Bad blocks with valid data in. */ + + spinlock_t erase_completion_lock; /* Protect free_list and erasing_list + against erase completion handler */ + wait_queue_head_t erase_wait; /* For waiting for erases to complete */ + + wait_queue_head_t inocache_wq; + struct jffs2_inode_cache **inocache_list; + spinlock_t inocache_lock; + + /* Sem to allow jffs2_garbage_collect_deletion_dirent to + drop the erase_completion_lock while it's holding a pointer + to an obsoleted node. I don't like this. Alternatives welcomed. */ + struct semaphore erase_free_sem; + + uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */ + +#ifdef CONFIG_JFFS2_FS_WRITEBUFFER + /* Write-behind buffer for NAND flash */ + unsigned char *wbuf; + unsigned char *oobbuf; + uint32_t wbuf_ofs; + uint32_t wbuf_len; + struct jffs2_inodirty *wbuf_inodes; + + struct rw_semaphore wbuf_sem; /* Protects the write buffer */ + + /* Information about out-of-band area usage... */ + struct nand_ecclayout *ecclayout; + uint32_t badblock_pos; + uint32_t fsdata_pos; + uint32_t fsdata_len; +#endif + + struct jffs2_summary *summary; /* Summary information */ + +#ifdef CONFIG_JFFS2_FS_XATTR +#define XATTRINDEX_HASHSIZE (57) + uint32_t highest_xid; + uint32_t highest_xseqno; + struct list_head xattrindex[XATTRINDEX_HASHSIZE]; + struct list_head xattr_unchecked; + struct list_head xattr_dead_list; + struct jffs2_xattr_ref *xref_dead_list; + struct jffs2_xattr_ref *xref_temp; + struct rw_semaphore xattr_sem; + uint32_t xdatum_mem_usage; + uint32_t xdatum_mem_threshold; +#endif + /* OS-private pointer for getting back to master superblock info */ + void *os_priv; +}; + +#endif /* _JFFS2_FB_SB */ diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c new file mode 100644 index 000000000..52a9894a6 --- /dev/null +++ b/fs/jffs2/security.c @@ -0,0 +1,82 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright (C) 2006 NEC Corporation + * + * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> + * + * For licensing information, see the file 'LICENCE' in this directory. + * + */ +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/fs.h> +#include <linux/time.h> +#include <linux/pagemap.h> +#include <linux/highmem.h> +#include <linux/crc32.h> +#include <linux/jffs2.h> +#include <linux/xattr.h> +#include <linux/mtd/mtd.h> +#include <linux/security.h> +#include "nodelist.h" + +/* ---- Initial Security Label Attachment -------------- */ +int jffs2_init_security(struct inode *inode, struct inode *dir) +{ + int rc; + size_t len; + void *value; + char *name; + + rc = security_inode_init_security(inode, dir, &name, &value, &len); + if (rc) { + if (rc == -EOPNOTSUPP) + return 0; + return rc; + } + rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0); + + kfree(name); + kfree(value); + return rc; +} + +/* ---- XATTR Handler for "security.*" ----------------- */ +static int jffs2_security_getxattr(struct inode *inode, const char *name, + void *buffer, size_t size) +{ + if (!strcmp(name, "")) + return -EINVAL; + + return do_jffs2_getxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size); +} + +static int jffs2_security_setxattr(struct inode *inode, const char *name, const void *buffer, + size_t size, int flags) +{ + if (!strcmp(name, "")) + return -EINVAL; + + return do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size, flags); +} + +static size_t jffs2_security_listxattr(struct inode *inode, char *list, size_t list_size, + const char *name, size_t name_len) +{ + size_t retlen = XATTR_SECURITY_PREFIX_LEN + name_len + 1; + + if (list && retlen <= list_size) { + strcpy(list, XATTR_SECURITY_PREFIX); + strcpy(list + XATTR_SECURITY_PREFIX_LEN, name); + } + + return retlen; +} + +struct xattr_handler jffs2_security_xattr_handler = { + .prefix = XATTR_SECURITY_PREFIX, + .list = jffs2_security_listxattr, + .set = jffs2_security_setxattr, + .get = jffs2_security_getxattr +}; diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c new file mode 100644 index 000000000..4da09ce1d --- /dev/null +++ b/fs/jffs2/xattr.c @@ -0,0 +1,1324 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright (C) 2006 NEC Corporation + * + * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> + * + * For licensing information, see the file 'LICENCE' in this directory. + * + */ +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/fs.h> +#include <linux/time.h> +#include <linux/pagemap.h> +#include <linux/highmem.h> +#include <linux/crc32.h> +#include <linux/jffs2.h> +#include <linux/xattr.h> +#include <linux/mtd/mtd.h> +#include "nodelist.h" +/* -------- xdatum related functions ---------------- + * xattr_datum_hashkey(xprefix, xname, xvalue, xsize) + * is used to calcurate xdatum hashkey. The reminder of hashkey into XATTRINDEX_HASHSIZE is + * the index of the xattr name/value pair cache (c->xattrindex). + * is_xattr_datum_unchecked(c, xd) + * returns 1, if xdatum contains any unchecked raw nodes. if all raw nodes are not + * unchecked, it returns 0. + * unload_xattr_datum(c, xd) + * is used to release xattr name/value pair and detach from c->xattrindex. + * reclaim_xattr_datum(c) + * is used to reclaim xattr name/value pairs on the xattr name/value pair cache when + * memory usage by cache is over c->xdatum_mem_threshold. Currentry, this threshold + * is hard coded as 32KiB. + * do_verify_xattr_datum(c, xd) + * is used to load the xdatum informations without name/value pair from the medium. + * It's necessary once, because those informations are not collected during mounting + * process when EBS is enabled. + * 0 will be returned, if success. An negative return value means recoverable error, and + * positive return value means unrecoverable error. Thus, caller must remove this xdatum + * and xref when it returned positive value. + * do_load_xattr_datum(c, xd) + * is used to load name/value pair from the medium. + * The meanings of return value is same as do_verify_xattr_datum(). + * load_xattr_datum(c, xd) + * is used to be as a wrapper of do_verify_xattr_datum() and do_load_xattr_datum(). + * If xd need to call do_verify_xattr_datum() at first, it's called before calling + * do_load_xattr_datum(). The meanings of return value is same as do_verify_xattr_datum(). + * save_xattr_datum(c, xd) + * is used to write xdatum to medium. xd->version will be incremented. + * create_xattr_datum(c, xprefix, xname, xvalue, xsize) + * is used to create new xdatum and write to medium. + * unrefer_xattr_datum(c, xd) + * is used to delete a xdatum. When nobody refers this xdatum, JFFS2_XFLAGS_DEAD + * is set on xd->flags and chained xattr_dead_list or release it immediately. + * In the first case, the garbage collector release it later. + * -------------------------------------------------- */ +static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize) +{ + int name_len = strlen(xname); + + return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize); +} + +static int is_xattr_datum_unchecked(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) +{ + struct jffs2_raw_node_ref *raw; + int rc = 0; + + spin_lock(&c->erase_completion_lock); + for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) { + if (ref_flags(raw) == REF_UNCHECKED) { + rc = 1; + break; + } + } + spin_unlock(&c->erase_completion_lock); + return rc; +} + +static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) +{ + /* must be called under down_write(xattr_sem) */ + D1(dbg_xattr("%s: xid=%u, version=%u\n", __FUNCTION__, xd->xid, xd->version)); + if (xd->xname) { + c->xdatum_mem_usage -= (xd->name_len + 1 + xd->value_len); + kfree(xd->xname); + } + + list_del_init(&xd->xindex); + xd->hashkey = 0; + xd->xname = NULL; + xd->xvalue = NULL; +} + +static void reclaim_xattr_datum(struct jffs2_sb_info *c) +{ + /* must be called under down_write(xattr_sem) */ + struct jffs2_xattr_datum *xd, *_xd; + uint32_t target, before; + static int index = 0; + int count; + + if (c->xdatum_mem_threshold > c->xdatum_mem_usage) + return; + + before = c->xdatum_mem_usage; + target = c->xdatum_mem_usage * 4 / 5; /* 20% reduction */ + for (count = 0; count < XATTRINDEX_HASHSIZE; count++) { + list_for_each_entry_safe(xd, _xd, &c->xattrindex[index], xindex) { + if (xd->flags & JFFS2_XFLAGS_HOT) { + xd->flags &= ~JFFS2_XFLAGS_HOT; + } else if (!(xd->flags & JFFS2_XFLAGS_BIND)) { + unload_xattr_datum(c, xd); + } + if (c->xdatum_mem_usage <= target) + goto out; + } + index = (index+1) % XATTRINDEX_HASHSIZE; + } + out: + JFFS2_NOTICE("xdatum_mem_usage from %u byte to %u byte (%u byte reclaimed)\n", + before, c->xdatum_mem_usage, before - c->xdatum_mem_usage); +} + +static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) +{ + /* must be called under down_write(xattr_sem) */ + struct jffs2_eraseblock *jeb; + struct jffs2_raw_node_ref *raw; + struct jffs2_raw_xattr rx; + size_t readlen; + uint32_t crc, offset, totlen; + int rc; + + spin_lock(&c->erase_completion_lock); + offset = ref_offset(xd->node); + if (ref_flags(xd->node) == REF_PRISTINE) + goto complete; + spin_unlock(&c->erase_completion_lock); + + rc = jffs2_flash_read(c, offset, sizeof(rx), &readlen, (char *)&rx); + if (rc || readlen != sizeof(rx)) { + JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n", + rc, sizeof(rx), readlen, offset); + return rc ? rc : -EIO; + } + crc = crc32(0, &rx, sizeof(rx) - 4); + if (crc != je32_to_cpu(rx.node_crc)) { + JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", + offset, je32_to_cpu(rx.hdr_crc), crc); + xd->flags |= JFFS2_XFLAGS_INVALID; + return EIO; + } + totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len)); + if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK + || je16_to_cpu(rx.nodetype) != JFFS2_NODETYPE_XATTR + || je32_to_cpu(rx.totlen) != totlen + || je32_to_cpu(rx.xid) != xd->xid + || je32_to_cpu(rx.version) != xd->version) { + JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, " + "nodetype=%#04x/%#04x, totlen=%u/%u, xid=%u/%u, version=%u/%u\n", + offset, je16_to_cpu(rx.magic), JFFS2_MAGIC_BITMASK, + je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR, + je32_to_cpu(rx.totlen), totlen, + je32_to_cpu(rx.xid), xd->xid, + je32_to_cpu(rx.version), xd->version); + xd->flags |= JFFS2_XFLAGS_INVALID; + return EIO; + } + xd->xprefix = rx.xprefix; + xd->name_len = rx.name_len; + xd->value_len = je16_to_cpu(rx.value_len); + xd->data_crc = je32_to_cpu(rx.data_crc); + + spin_lock(&c->erase_completion_lock); + complete: + for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) { + jeb = &c->blocks[ref_offset(raw) / c->sector_size]; + totlen = PAD(ref_totlen(c, jeb, raw)); + if (ref_flags(raw) == REF_UNCHECKED) { + c->unchecked_size -= totlen; c->used_size += totlen; + jeb->unchecked_size -= totlen; jeb->used_size += totlen; + } + raw->flash_offset = ref_offset(raw) | ((xd->node==raw) ? REF_PRISTINE : REF_NORMAL); + } + spin_unlock(&c->erase_completion_lock); + + /* unchecked xdatum is chained with c->xattr_unchecked */ + list_del_init(&xd->xindex); + + dbg_xattr("success on verfying xdatum (xid=%u, version=%u)\n", + xd->xid, xd->version); + + return 0; +} + +static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) +{ + /* must be called under down_write(xattr_sem) */ + char *data; + size_t readlen; + uint32_t crc, length; + int i, ret, retry = 0; + + BUG_ON(ref_flags(xd->node) != REF_PRISTINE); + BUG_ON(!list_empty(&xd->xindex)); + retry: + length = xd->name_len + 1 + xd->value_len; + data = kmalloc(length, GFP_KERNEL); + if (!data) + return -ENOMEM; + + ret = jffs2_flash_read(c, ref_offset(xd->node)+sizeof(struct jffs2_raw_xattr), + length, &readlen, data); + + if (ret || length!=readlen) { + JFFS2_WARNING("jffs2_flash_read() returned %d, request=%d, readlen=%zu, at %#08x\n", + ret, length, readlen, ref_offset(xd->node)); + kfree(data); + return ret ? ret : -EIO; + } + + data[xd->name_len] = '\0'; + crc = crc32(0, data, length); + if (crc != xd->data_crc) { + JFFS2_WARNING("node CRC failed (JFFS2_NODETYPE_XREF)" + " at %#08x, read: 0x%08x calculated: 0x%08x\n", + ref_offset(xd->node), xd->data_crc, crc); + kfree(data); + xd->flags |= JFFS2_XFLAGS_INVALID; + return EIO; + } + + xd->flags |= JFFS2_XFLAGS_HOT; + xd->xname = data; + xd->xvalue = data + xd->name_len+1; + + c->xdatum_mem_usage += length; + + xd->hashkey = xattr_datum_hashkey(xd->xprefix, xd->xname, xd->xvalue, xd->value_len); + i = xd->hashkey % XATTRINDEX_HASHSIZE; + list_add(&xd->xindex, &c->xattrindex[i]); + if (!retry) { + retry = 1; + reclaim_xattr_datum(c); + if (!xd->xname) + goto retry; + } + + dbg_xattr("success on loading xdatum (xid=%u, xprefix=%u, xname='%s')\n", + xd->xid, xd->xprefix, xd->xname); + + return 0; +} + +static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) +{ + /* must be called under down_write(xattr_sem); + * rc < 0 : recoverable error, try again + * rc = 0 : success + * rc > 0 : Unrecoverable error, this node should be deleted. + */ + int rc = 0; + + BUG_ON(xd->flags & JFFS2_XFLAGS_DEAD); + if (xd->xname) + return 0; + if (xd->flags & JFFS2_XFLAGS_INVALID) + return EIO; + if (unlikely(is_xattr_datum_unchecked(c, xd))) + rc = do_verify_xattr_datum(c, xd); + if (!rc) + rc = do_load_xattr_datum(c, xd); + return rc; +} + +static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) +{ + /* must be called under down_write(xattr_sem) */ + struct jffs2_raw_xattr rx; + struct kvec vecs[2]; + size_t length; + int rc, totlen; + uint32_t phys_ofs = write_ofs(c); + + BUG_ON(!xd->xname); + BUG_ON(xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID)); + + vecs[0].iov_base = ℞ + vecs[0].iov_len = sizeof(rx); + vecs[1].iov_base = xd->xname; + vecs[1].iov_len = xd->name_len + 1 + xd->value_len; + totlen = vecs[0].iov_len + vecs[1].iov_len; + + /* Setup raw-xattr */ + memset(&rx, 0, sizeof(rx)); + rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR); + rx.totlen = cpu_to_je32(PAD(totlen)); + rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4)); + + rx.xid = cpu_to_je32(xd->xid); + rx.version = cpu_to_je32(++xd->version); + rx.xprefix = xd->xprefix; + rx.name_len = xd->name_len; + rx.value_len = cpu_to_je16(xd->value_len); + rx.data_crc = cpu_to_je32(crc32(0, vecs[1].iov_base, vecs[1].iov_len)); + rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_raw_xattr) - 4)); + + rc = jffs2_flash_writev(c, vecs, 2, phys_ofs, &length, 0); + if (rc || totlen != length) { + JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%zu, at %#08x\n", + rc, totlen, length, phys_ofs); + rc = rc ? rc : -EIO; + if (length) + jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(totlen), NULL); + + return rc; + } + /* success */ + jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), (void *)xd); + + dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n", + xd->xid, xd->version, xd->xprefix, xd->xname); + + return 0; +} + +static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c, + int xprefix, const char *xname, + const char *xvalue, int xsize) +{ + /* must be called under down_write(xattr_sem) */ + struct jffs2_xattr_datum *xd; + uint32_t hashkey, name_len; + char *data; + int i, rc; + + /* Search xattr_datum has same xname/xvalue by index */ + hashkey = xattr_datum_hashkey(xprefix, xname, xvalue, xsize); + i = hashkey % XATTRINDEX_HASHSIZE; + list_for_each_entry(xd, &c->xattrindex[i], xindex) { + if (xd->hashkey==hashkey + && xd->xprefix==xprefix + && xd->value_len==xsize + && !strcmp(xd->xname, xname) + && !memcmp(xd->xvalue, xvalue, xsize)) { + atomic_inc(&xd->refcnt); + return xd; + } + } + + /* Not found, Create NEW XATTR-Cache */ + name_len = strlen(xname); + + xd = jffs2_alloc_xattr_datum(); + if (!xd) + return ERR_PTR(-ENOMEM); + + data = kmalloc(name_len + 1 + xsize, GFP_KERNEL); + if (!data) { + jffs2_free_xattr_datum(xd); + return ERR_PTR(-ENOMEM); + } + strcpy(data, xname); + memcpy(data + name_len + 1, xvalue, xsize); + + atomic_set(&xd->refcnt, 1); + xd->xid = ++c->highest_xid; + xd->flags |= JFFS2_XFLAGS_HOT; + xd->xprefix = xprefix; + + xd->hashkey = hashkey; + xd->xname = data; + xd->xvalue = data + name_len + 1; + xd->name_len = name_len; + xd->value_len = xsize; + xd->data_crc = crc32(0, data, xd->name_len + 1 + xd->value_len); + + rc = save_xattr_datum(c, xd); + if (rc) { + kfree(xd->xname); + jffs2_free_xattr_datum(xd); + return ERR_PTR(rc); + } + + /* Insert Hash Index */ + i = hashkey % XATTRINDEX_HASHSIZE; + list_add(&xd->xindex, &c->xattrindex[i]); + + c->xdatum_mem_usage += (xd->name_len + 1 + xd->value_len); + reclaim_xattr_datum(c); + + return xd; +} + +static void unrefer_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) +{ + /* must be called under down_write(xattr_sem) */ + if (atomic_dec_and_lock(&xd->refcnt, &c->erase_completion_lock)) { + uint32_t xid = xd->xid, version = xd->version; + + unload_xattr_datum(c, xd); + xd->flags |= JFFS2_XFLAGS_DEAD; + if (xd->node == (void *)xd) { + BUG_ON(!(xd->flags & JFFS2_XFLAGS_INVALID)); + jffs2_free_xattr_datum(xd); + } else { + list_add(&xd->xindex, &c->xattr_dead_list); + } + spin_unlock(&c->erase_completion_lock); + + dbg_xattr("xdatum(xid=%u, version=%u) was removed.\n", xid, version); + } +} + +/* -------- xref related functions ------------------ + * verify_xattr_ref(c, ref) + * is used to load xref information from medium. Because summary data does not + * contain xid/ino, it's necessary to verify once while mounting process. + * save_xattr_ref(c, ref) + * is used to write xref to medium. If delete marker is marked, it write + * a delete marker of xref into medium. + * create_xattr_ref(c, ic, xd) + * is used to create a new xref and write to medium. + * delete_xattr_ref(c, ref) + * is used to delete jffs2_xattr_ref. It marks xref XREF_DELETE_MARKER, + * and allows GC to reclaim those physical nodes. + * jffs2_xattr_delete_inode(c, ic) + * is called to remove xrefs related to obsolete inode when inode is unlinked. + * jffs2_xattr_free_inode(c, ic) + * is called to release xattr related objects when unmounting. + * check_xattr_ref_inode(c, ic) + * is used to confirm inode does not have duplicate xattr name/value pair. + * -------------------------------------------------- */ +static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) +{ + struct jffs2_eraseblock *jeb; + struct jffs2_raw_node_ref *raw; + struct jffs2_raw_xref rr; + size_t readlen; + uint32_t crc, offset, totlen; + int rc; + + spin_lock(&c->erase_completion_lock); + if (ref_flags(ref->node) != REF_UNCHECKED) + goto complete; + offset = ref_offset(ref->node); + spin_unlock(&c->erase_completion_lock); + + rc = jffs2_flash_read(c, offset, sizeof(rr), &readlen, (char *)&rr); + if (rc || sizeof(rr) != readlen) { + JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n", + rc, sizeof(rr), readlen, offset); + return rc ? rc : -EIO; + } + /* obsolete node */ + crc = crc32(0, &rr, sizeof(rr) - 4); + if (crc != je32_to_cpu(rr.node_crc)) { + JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", + offset, je32_to_cpu(rr.node_crc), crc); + return EIO; + } + if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK + || je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF + || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) { + JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, " + "nodetype=%#04x/%#04x, totlen=%u/%zu\n", + offset, je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK, + je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF, + je32_to_cpu(rr.totlen), PAD(sizeof(rr))); + return EIO; + } + ref->ino = je32_to_cpu(rr.ino); + ref->xid = je32_to_cpu(rr.xid); + ref->xseqno = je32_to_cpu(rr.xseqno); + if (ref->xseqno > c->highest_xseqno) + c->highest_xseqno = (ref->xseqno & ~XREF_DELETE_MARKER); + + spin_lock(&c->erase_completion_lock); + complete: + for (raw=ref->node; raw != (void *)ref; raw=raw->next_in_ino) { + jeb = &c->blocks[ref_offset(raw) / c->sector_size]; + totlen = PAD(ref_totlen(c, jeb, raw)); + if (ref_flags(raw) == REF_UNCHECKED) { + c->unchecked_size -= totlen; c->used_size += totlen; + jeb->unchecked_size -= totlen; jeb->used_size += totlen; + } + raw->flash_offset = ref_offset(raw) | ((ref->node==raw) ? REF_PRISTINE : REF_NORMAL); + } + spin_unlock(&c->erase_completion_lock); + + dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n", + ref->ino, ref->xid, ref_offset(ref->node)); + return 0; +} + +static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) +{ + /* must be called under down_write(xattr_sem) */ + struct jffs2_raw_xref rr; + size_t length; + uint32_t xseqno, phys_ofs = write_ofs(c); + int ret; + + rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF); + rr.totlen = cpu_to_je32(PAD(sizeof(rr))); + rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4)); + + xseqno = (c->highest_xseqno += 2); + if (is_xattr_ref_dead(ref)) { + xseqno |= XREF_DELETE_MARKER; + rr.ino = cpu_to_je32(ref->ino); + rr.xid = cpu_to_je32(ref->xid); + } else { + rr.ino = cpu_to_je32(ref->ic->ino); + rr.xid = cpu_to_je32(ref->xd->xid); + } + rr.xseqno = cpu_to_je32(xseqno); + rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4)); + + ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr); + if (ret || sizeof(rr) != length) { + JFFS2_WARNING("jffs2_flash_write() returned %d, request=%zu, retlen=%zu, at %#08x\n", + ret, sizeof(rr), length, phys_ofs); + ret = ret ? ret : -EIO; + if (length) + jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(sizeof(rr)), NULL); + + return ret; + } + /* success */ + ref->xseqno = xseqno; + jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), (void *)ref); + + dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid); + + return 0; +} + +static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, + struct jffs2_xattr_datum *xd) +{ + /* must be called under down_write(xattr_sem) */ + struct jffs2_xattr_ref *ref; + int ret; + + ref = jffs2_alloc_xattr_ref(); + if (!ref) + return ERR_PTR(-ENOMEM); + ref->ic = ic; + ref->xd = xd; + + ret = save_xattr_ref(c, ref); + if (ret) { + jffs2_free_xattr_ref(ref); + return ERR_PTR(ret); + } + + /* Chain to inode */ + ref->next = ic->xref; + ic->xref = ref; + + return ref; /* success */ +} + +static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) +{ + /* must be called under down_write(xattr_sem) */ + struct jffs2_xattr_datum *xd; + + xd = ref->xd; + ref->xseqno |= XREF_DELETE_MARKER; + ref->ino = ref->ic->ino; + ref->xid = ref->xd->xid; + spin_lock(&c->erase_completion_lock); + ref->next = c->xref_dead_list; + c->xref_dead_list = ref; + spin_unlock(&c->erase_completion_lock); + + dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) was removed.\n", + ref->ino, ref->xid, ref->xseqno); + + unrefer_xattr_datum(c, xd); +} + +void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) +{ + /* It's called from jffs2_clear_inode() on inode removing. + When an inode with XATTR is removed, those XATTRs must be removed. */ + struct jffs2_xattr_ref *ref, *_ref; + + if (!ic || ic->nlink > 0) + return; + + down_write(&c->xattr_sem); + for (ref = ic->xref; ref; ref = _ref) { + _ref = ref->next; + delete_xattr_ref(c, ref); + } + ic->xref = NULL; + up_write(&c->xattr_sem); +} + +void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) +{ + /* It's called from jffs2_free_ino_caches() until unmounting FS. */ + struct jffs2_xattr_datum *xd; + struct jffs2_xattr_ref *ref, *_ref; + + down_write(&c->xattr_sem); + for (ref = ic->xref; ref; ref = _ref) { + _ref = ref->next; + xd = ref->xd; + if (atomic_dec_and_test(&xd->refcnt)) { + unload_xattr_datum(c, xd); + jffs2_free_xattr_datum(xd); + } + jffs2_free_xattr_ref(ref); + } + ic->xref = NULL; + up_write(&c->xattr_sem); +} + +static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) +{ + /* success of check_xattr_ref_inode() means taht inode (ic) dose not have + * duplicate name/value pairs. If duplicate name/value pair would be found, + * one will be removed. + */ + struct jffs2_xattr_ref *ref, *cmp, **pref, **pcmp; + int rc = 0; + + if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED)) + return 0; + down_write(&c->xattr_sem); + retry: + rc = 0; + for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) { + if (!ref->xd->xname) { + rc = load_xattr_datum(c, ref->xd); + if (unlikely(rc > 0)) { + *pref = ref->next; + delete_xattr_ref(c, ref); + goto retry; + } else if (unlikely(rc < 0)) + goto out; + } + for (cmp=ref->next, pcmp=&ref->next; cmp; pcmp=&cmp->next, cmp=cmp->next) { + if (!cmp->xd->xname) { + ref->xd->flags |= JFFS2_XFLAGS_BIND; + rc = load_xattr_datum(c, cmp->xd); + ref->xd->flags &= ~JFFS2_XFLAGS_BIND; + if (unlikely(rc > 0)) { + *pcmp = cmp->next; + delete_xattr_ref(c, cmp); + goto retry; + } else if (unlikely(rc < 0)) + goto out; + } + if (ref->xd->xprefix == cmp->xd->xprefix + && !strcmp(ref->xd->xname, cmp->xd->xname)) { + if (ref->xseqno > cmp->xseqno) { + *pcmp = cmp->next; + delete_xattr_ref(c, cmp); + } else { + *pref = ref->next; + delete_xattr_ref(c, ref); + } + goto retry; + } + } + } + ic->flags |= INO_FLAGS_XATTR_CHECKED; + out: + up_write(&c->xattr_sem); + + return rc; +} + +/* -------- xattr subsystem functions --------------- + * jffs2_init_xattr_subsystem(c) + * is used to initialize semaphore and list_head, and some variables. + * jffs2_find_xattr_datum(c, xid) + * is used to lookup xdatum while scanning process. + * jffs2_clear_xattr_subsystem(c) + * is used to release any xattr related objects. + * jffs2_build_xattr_subsystem(c) + * is used to associate xdatum and xref while super block building process. + * jffs2_setup_xattr_datum(c, xid, version) + * is used to insert xdatum while scanning process. + * -------------------------------------------------- */ +void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c) +{ + int i; + + for (i=0; i < XATTRINDEX_HASHSIZE; i++) + INIT_LIST_HEAD(&c->xattrindex[i]); + INIT_LIST_HEAD(&c->xattr_unchecked); + INIT_LIST_HEAD(&c->xattr_dead_list); + c->xref_dead_list = NULL; + c->xref_temp = NULL; + + init_rwsem(&c->xattr_sem); + c->highest_xid = 0; + c->highest_xseqno = 0; + c->xdatum_mem_usage = 0; + c->xdatum_mem_threshold = 32 * 1024; /* Default 32KB */ +} + +static struct jffs2_xattr_datum *jffs2_find_xattr_datum(struct jffs2_sb_info *c, uint32_t xid) +{ + struct jffs2_xattr_datum *xd; + int i = xid % XATTRINDEX_HASHSIZE; + + /* It's only used in scanning/building process. */ + BUG_ON(!(c->flags & (JFFS2_SB_FLAG_SCANNING|JFFS2_SB_FLAG_BUILDING))); + + list_for_each_entry(xd, &c->xattrindex[i], xindex) { + if (xd->xid==xid) + return xd; + } + return NULL; +} + +void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c) +{ + struct jffs2_xattr_datum *xd, *_xd; + struct jffs2_xattr_ref *ref, *_ref; + int i; + + for (ref=c->xref_temp; ref; ref = _ref) { + _ref = ref->next; + jffs2_free_xattr_ref(ref); + } + + for (ref=c->xref_dead_list; ref; ref = _ref) { + _ref = ref->next; + jffs2_free_xattr_ref(ref); + } + + for (i=0; i < XATTRINDEX_HASHSIZE; i++) { + list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { + list_del(&xd->xindex); + if (xd->xname) + kfree(xd->xname); + jffs2_free_xattr_datum(xd); + } + } + + list_for_each_entry_safe(xd, _xd, &c->xattr_dead_list, xindex) { + list_del(&xd->xindex); + jffs2_free_xattr_datum(xd); + } +} + +#define XREF_TMPHASH_SIZE (128) +void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) +{ + struct jffs2_xattr_ref *ref, *_ref; + struct jffs2_xattr_ref *xref_tmphash[XREF_TMPHASH_SIZE]; + struct jffs2_xattr_datum *xd, *_xd; + struct jffs2_inode_cache *ic; + struct jffs2_raw_node_ref *raw; + int i, xdatum_count = 0, xdatum_unchecked_count = 0, xref_count = 0; + int xdatum_orphan_count = 0, xref_orphan_count = 0, xref_dead_count = 0; + + BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING)); + + /* Phase.1 : Merge same xref */ + for (i=0; i < XREF_TMPHASH_SIZE; i++) + xref_tmphash[i] = NULL; + for (ref=c->xref_temp; ref; ref=_ref) { + struct jffs2_xattr_ref *tmp; + + _ref = ref->next; + if (ref_flags(ref->node) != REF_PRISTINE) { + if (verify_xattr_ref(c, ref)) { + BUG_ON(ref->node->next_in_ino != (void *)ref); + ref->node->next_in_ino = NULL; + jffs2_mark_node_obsolete(c, ref->node); + jffs2_free_xattr_ref(ref); + continue; + } + } + + i = (ref->ino ^ ref->xid) % XREF_TMPHASH_SIZE; + for (tmp=xref_tmphash[i]; tmp; tmp=tmp->next) { + if (tmp->ino == ref->ino && tmp->xid == ref->xid) + break; + } + if (tmp) { + raw = ref->node; + if (ref->xseqno > tmp->xseqno) { + tmp->xseqno = ref->xseqno; + raw->next_in_ino = tmp->node; + tmp->node = raw; + } else { + raw->next_in_ino = tmp->node->next_in_ino; + tmp->node->next_in_ino = raw; + } + jffs2_free_xattr_ref(ref); + continue; + } else { + ref->next = xref_tmphash[i]; + xref_tmphash[i] = ref; + } + } + c->xref_temp = NULL; + + /* Phase.2 : Bind xref with inode_cache and xattr_datum */ + for (i=0; i < XREF_TMPHASH_SIZE; i++) { + for (ref=xref_tmphash[i]; ref; ref=_ref) { + xref_count++; + _ref = ref->next; + if (is_xattr_ref_dead(ref)) { + ref->next = c->xref_dead_list; + c->xref_dead_list = ref; + xref_dead_count++; + continue; + } + /* At this point, ref->xid and ref->ino contain XID and inode number. + ref->xd and ref->ic are not valid yet. */ + xd = jffs2_find_xattr_datum(c, ref->xid); + ic = jffs2_get_ino_cache(c, ref->ino); + if (!xd || !ic) { + dbg_xattr("xref(ino=%u, xid=%u, xseqno=%u) is orphan.\n", + ref->ino, ref->xid, ref->xseqno); + ref->xseqno |= XREF_DELETE_MARKER; + ref->next = c->xref_dead_list; + c->xref_dead_list = ref; + xref_orphan_count++; + continue; + } + ref->xd = xd; + ref->ic = ic; + atomic_inc(&xd->refcnt); + ref->next = ic->xref; + ic->xref = ref; + } + } + + /* Phase.3 : Link unchecked xdatum to xattr_unchecked list */ + for (i=0; i < XATTRINDEX_HASHSIZE; i++) { + list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { + xdatum_count++; + list_del_init(&xd->xindex); + if (!atomic_read(&xd->refcnt)) { + dbg_xattr("xdatum(xid=%u, version=%u) is orphan.\n", + xd->xid, xd->version); + xd->flags |= JFFS2_XFLAGS_DEAD; + list_add(&xd->xindex, &c->xattr_unchecked); + xdatum_orphan_count++; + continue; + } + if (is_xattr_datum_unchecked(c, xd)) { + dbg_xattr("unchecked xdatum(xid=%u, version=%u)\n", + xd->xid, xd->version); + list_add(&xd->xindex, &c->xattr_unchecked); + xdatum_unchecked_count++; + } + } + } + /* build complete */ + JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum" + " (%u unchecked, %u orphan) and " + "%u of xref (%u dead, %u orphan) found.\n", + xdatum_count, xdatum_unchecked_count, xdatum_orphan_count, + xref_count, xref_dead_count, xref_orphan_count); +} + +struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, + uint32_t xid, uint32_t version) +{ + struct jffs2_xattr_datum *xd; + + xd = jffs2_find_xattr_datum(c, xid); + if (!xd) { + xd = jffs2_alloc_xattr_datum(); + if (!xd) + return ERR_PTR(-ENOMEM); + xd->xid = xid; + xd->version = version; + if (xd->xid > c->highest_xid) + c->highest_xid = xd->xid; + list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]); + } + return xd; +} + +/* -------- xattr subsystem functions --------------- + * xprefix_to_handler(xprefix) + * is used to translate xprefix into xattr_handler. + * jffs2_listxattr(dentry, buffer, size) + * is an implementation of listxattr handler on jffs2. + * do_jffs2_getxattr(inode, xprefix, xname, buffer, size) + * is an implementation of getxattr handler on jffs2. + * do_jffs2_setxattr(inode, xprefix, xname, buffer, size, flags) + * is an implementation of setxattr handler on jffs2. + * -------------------------------------------------- */ +struct xattr_handler *jffs2_xattr_handlers[] = { + &jffs2_user_xattr_handler, +#ifdef CONFIG_JFFS2_FS_SECURITY + &jffs2_security_xattr_handler, +#endif +#ifdef CONFIG_JFFS2_FS_POSIX_ACL + &jffs2_acl_access_xattr_handler, + &jffs2_acl_default_xattr_handler, +#endif + &jffs2_trusted_xattr_handler, + NULL +}; + +static struct xattr_handler *xprefix_to_handler(int xprefix) { + struct xattr_handler *ret; + + switch (xprefix) { + case JFFS2_XPREFIX_USER: + ret = &jffs2_user_xattr_handler; + break; +#ifdef CONFIG_JFFS2_FS_SECURITY + case JFFS2_XPREFIX_SECURITY: + ret = &jffs2_security_xattr_handler; + break; +#endif +#ifdef CONFIG_JFFS2_FS_POSIX_ACL + case JFFS2_XPREFIX_ACL_ACCESS: + ret = &jffs2_acl_access_xattr_handler; + break; + case JFFS2_XPREFIX_ACL_DEFAULT: + ret = &jffs2_acl_default_xattr_handler; + break; +#endif + case JFFS2_XPREFIX_TRUSTED: + ret = &jffs2_trusted_xattr_handler; + break; + default: + ret = NULL; + break; + } + return ret; +} + +ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size) +{ + struct inode *inode = dentry->d_inode; + struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); + struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); + struct jffs2_inode_cache *ic = f->inocache; + struct jffs2_xattr_ref *ref, **pref; + struct jffs2_xattr_datum *xd; + struct xattr_handler *xhandle; + ssize_t len, rc; + int retry = 0; + + rc = check_xattr_ref_inode(c, ic); + if (unlikely(rc)) + return rc; + + down_read(&c->xattr_sem); + retry: + len = 0; + for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) { + BUG_ON(ref->ic != ic); + xd = ref->xd; + if (!xd->xname) { + /* xdatum is unchached */ + if (!retry) { + retry = 1; + up_read(&c->xattr_sem); + down_write(&c->xattr_sem); + goto retry; + } else { + rc = load_xattr_datum(c, xd); + if (unlikely(rc > 0)) { + *pref = ref->next; + delete_xattr_ref(c, ref); + goto retry; + } else if (unlikely(rc < 0)) + goto out; + } + } + xhandle = xprefix_to_handler(xd->xprefix); + if (!xhandle) + continue; + if (buffer) { + rc = xhandle->list(inode, buffer+len, size-len, xd->xname, xd->name_len); + } else { + rc = xhandle->list(inode, NULL, 0, xd->xname, xd->name_len); + } + if (rc < 0) + goto out; + len += rc; + } + rc = len; + out: + if (!retry) { + up_read(&c->xattr_sem); + } else { + up_write(&c->xattr_sem); + } + return rc; +} + +int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname, + char *buffer, size_t size) +{ + struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); + struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); + struct jffs2_inode_cache *ic = f->inocache; + struct jffs2_xattr_datum *xd; + struct jffs2_xattr_ref *ref, **pref; + int rc, retry = 0; + + rc = check_xattr_ref_inode(c, ic); + if (unlikely(rc)) + return rc; + + down_read(&c->xattr_sem); + retry: + for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) { + BUG_ON(ref->ic!=ic); + + xd = ref->xd; + if (xd->xprefix != xprefix) + continue; + if (!xd->xname) { + /* xdatum is unchached */ + if (!retry) { + retry = 1; + up_read(&c->xattr_sem); + down_write(&c->xattr_sem); + goto retry; + } else { + rc = load_xattr_datum(c, xd); + if (unlikely(rc > 0)) { + *pref = ref->next; + delete_xattr_ref(c, ref); + goto retry; + } else if (unlikely(rc < 0)) { + goto out; + } + } + } + if (!strcmp(xname, xd->xname)) { + rc = xd->value_len; + if (buffer) { + if (size < rc) { + rc = -ERANGE; + } else { + memcpy(buffer, xd->xvalue, rc); + } + } + goto out; + } + } + rc = -ENODATA; + out: + if (!retry) { + up_read(&c->xattr_sem); + } else { + up_write(&c->xattr_sem); + } + return rc; +} + +int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, + const char *buffer, size_t size, int flags) +{ + struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); + struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); + struct jffs2_inode_cache *ic = f->inocache; + struct jffs2_xattr_datum *xd; + struct jffs2_xattr_ref *ref, *newref, **pref; + uint32_t length, request; + int rc; + + rc = check_xattr_ref_inode(c, ic); + if (unlikely(rc)) + return rc; + + request = PAD(sizeof(struct jffs2_raw_xattr) + strlen(xname) + 1 + size); + rc = jffs2_reserve_space(c, request, &length, + ALLOC_NORMAL, JFFS2_SUMMARY_XATTR_SIZE); + if (rc) { + JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request); + return rc; + } + + /* Find existing xattr */ + down_write(&c->xattr_sem); + retry: + for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) { + xd = ref->xd; + if (xd->xprefix != xprefix) + continue; + if (!xd->xname) { + rc = load_xattr_datum(c, xd); + if (unlikely(rc > 0)) { + *pref = ref->next; + delete_xattr_ref(c, ref); + goto retry; + } else if (unlikely(rc < 0)) + goto out; + } + if (!strcmp(xd->xname, xname)) { + if (flags & XATTR_CREATE) { + rc = -EEXIST; + goto out; + } + if (!buffer) { + ref->ino = ic->ino; + ref->xid = xd->xid; + ref->xseqno |= XREF_DELETE_MARKER; + rc = save_xattr_ref(c, ref); + if (!rc) { + *pref = ref->next; + spin_lock(&c->erase_completion_lock); + ref->next = c->xref_dead_list; + c->xref_dead_list = ref; + spin_unlock(&c->erase_completion_lock); + unrefer_xattr_datum(c, xd); + } else { + ref->ic = ic; + ref->xd = xd; + ref->xseqno &= ~XREF_DELETE_MARKER; + } + goto out; + } + goto found; + } + } + /* not found */ + if (flags & XATTR_REPLACE) { + rc = -ENODATA; + goto out; + } + if (!buffer) { + rc = -ENODATA; + goto out; + } + found: + xd = create_xattr_datum(c, xprefix, xname, buffer, size); + if (IS_ERR(xd)) { + rc = PTR_ERR(xd); + goto out; + } + up_write(&c->xattr_sem); + jffs2_complete_reservation(c); + + /* create xattr_ref */ + request = PAD(sizeof(struct jffs2_raw_xref)); + rc = jffs2_reserve_space(c, request, &length, + ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE); + down_write(&c->xattr_sem); + if (rc) { + JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request); + unrefer_xattr_datum(c, xd); + up_write(&c->xattr_sem); + return rc; + } + if (ref) + *pref = ref->next; + newref = create_xattr_ref(c, ic, xd); + if (IS_ERR(newref)) { + if (ref) { + ref->next = ic->xref; + ic->xref = ref; + } + rc = PTR_ERR(newref); + unrefer_xattr_datum(c, xd); + } else if (ref) { + delete_xattr_ref(c, ref); + } + out: + up_write(&c->xattr_sem); + jffs2_complete_reservation(c); + return rc; +} + +/* -------- garbage collector functions ------------- + * jffs2_garbage_collect_xattr_datum(c, xd, raw) + * is used to move xdatum into new node. + * jffs2_garbage_collect_xattr_ref(c, ref, raw) + * is used to move xref into new node. + * jffs2_verify_xattr(c) + * is used to call do_verify_xattr_datum() before garbage collecting. + * jffs2_release_xattr_datum(c, xd) + * is used to release an in-memory object of xdatum. + * jffs2_release_xattr_ref(c, ref) + * is used to release an in-memory object of xref. + * -------------------------------------------------- */ +int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd, + struct jffs2_raw_node_ref *raw) +{ + uint32_t totlen, length, old_ofs; + int rc = 0; + + down_write(&c->xattr_sem); + if (xd->node != raw) + goto out; + if (xd->flags & (JFFS2_XFLAGS_DEAD|JFFS2_XFLAGS_INVALID)) + goto out; + + rc = load_xattr_datum(c, xd); + if (unlikely(rc)) { + rc = (rc > 0) ? 0 : rc; + goto out; + } + old_ofs = ref_offset(xd->node); + totlen = PAD(sizeof(struct jffs2_raw_xattr) + + xd->name_len + 1 + xd->value_len); + rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE); + if (rc) { + JFFS2_WARNING("jffs2_reserve_space_gc()=%d, request=%u\n", rc, totlen); + goto out; + } + rc = save_xattr_datum(c, xd); + if (!rc) + dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n", + xd->xid, xd->version, old_ofs, ref_offset(xd->node)); + out: + if (!rc) + jffs2_mark_node_obsolete(c, raw); + up_write(&c->xattr_sem); + return rc; +} + +int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, + struct jffs2_raw_node_ref *raw) +{ + uint32_t totlen, length, old_ofs; + int rc = 0; + + down_write(&c->xattr_sem); + BUG_ON(!ref->node); + + if (ref->node != raw) + goto out; + if (is_xattr_ref_dead(ref) && (raw->next_in_ino == (void *)ref)) + goto out; + + old_ofs = ref_offset(ref->node); + totlen = ref_totlen(c, c->gcblock, ref->node); + + rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE); + if (rc) { + JFFS2_WARNING("%s: jffs2_reserve_space_gc() = %d, request = %u\n", + __FUNCTION__, rc, totlen); + rc = rc ? rc : -EBADFD; + goto out; + } + rc = save_xattr_ref(c, ref); + if (!rc) + dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n", + ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node)); + out: + if (!rc) + jffs2_mark_node_obsolete(c, raw); + up_write(&c->xattr_sem); + return rc; +} + +int jffs2_verify_xattr(struct jffs2_sb_info *c) +{ + struct jffs2_xattr_datum *xd, *_xd; + struct jffs2_eraseblock *jeb; + struct jffs2_raw_node_ref *raw; + uint32_t totlen; + int rc; + + down_write(&c->xattr_sem); + list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) { + rc = do_verify_xattr_datum(c, xd); + if (rc < 0) + continue; + list_del_init(&xd->xindex); + spin_lock(&c->erase_completion_lock); + for (raw=xd->node; raw != (void *)xd; raw=raw->next_in_ino) { + if (ref_flags(raw) != REF_UNCHECKED) + continue; + jeb = &c->blocks[ref_offset(raw) / c->sector_size]; + totlen = PAD(ref_totlen(c, jeb, raw)); + c->unchecked_size -= totlen; c->used_size += totlen; + jeb->unchecked_size -= totlen; jeb->used_size += totlen; + raw->flash_offset = ref_offset(raw) + | ((xd->node == (void *)raw) ? REF_PRISTINE : REF_NORMAL); + } + if (xd->flags & JFFS2_XFLAGS_DEAD) + list_add(&xd->xindex, &c->xattr_dead_list); + spin_unlock(&c->erase_completion_lock); + } + up_write(&c->xattr_sem); + return list_empty(&c->xattr_unchecked) ? 1 : 0; +} + +void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) +{ + /* must be called under spin_lock(&c->erase_completion_lock) */ + if (atomic_read(&xd->refcnt) || xd->node != (void *)xd) + return; + + list_del(&xd->xindex); + jffs2_free_xattr_datum(xd); +} + +void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) +{ + /* must be called under spin_lock(&c->erase_completion_lock) */ + struct jffs2_xattr_ref *tmp, **ptmp; + + if (ref->node != (void *)ref) + return; + + for (tmp=c->xref_dead_list, ptmp=&c->xref_dead_list; tmp; ptmp=&tmp->next, tmp=tmp->next) { + if (ref == tmp) { + *ptmp = tmp->next; + break; + } + } + jffs2_free_xattr_ref(ref); +} diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h new file mode 100644 index 000000000..06a5c69dc --- /dev/null +++ b/fs/jffs2/xattr.h @@ -0,0 +1,129 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright (C) 2006 NEC Corporation + * + * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> + * + * For licensing information, see the file 'LICENCE' in this directory. + * + */ +#ifndef _JFFS2_FS_XATTR_H_ +#define _JFFS2_FS_XATTR_H_ + +#include <linux/xattr.h> +#include <linux/list.h> + +#define JFFS2_XFLAGS_HOT (0x01) /* This datum is HOT */ +#define JFFS2_XFLAGS_BIND (0x02) /* This datum is not reclaimed */ +#define JFFS2_XFLAGS_DEAD (0x40) /* This datum is already dead */ +#define JFFS2_XFLAGS_INVALID (0x80) /* This datum contains crc error */ + +struct jffs2_xattr_datum +{ + void *always_null; + struct jffs2_raw_node_ref *node; + uint8_t class; + uint8_t flags; + uint16_t xprefix; /* see JFFS2_XATTR_PREFIX_* */ + + struct list_head xindex; /* chained from c->xattrindex[n] */ + atomic_t refcnt; /* # of xattr_ref refers this */ + uint32_t xid; + uint32_t version; + + uint32_t data_crc; + uint32_t hashkey; + char *xname; /* XATTR name without prefix */ + uint32_t name_len; /* length of xname */ + char *xvalue; /* XATTR value */ + uint32_t value_len; /* length of xvalue */ +}; + +struct jffs2_inode_cache; +struct jffs2_xattr_ref +{ + void *always_null; + struct jffs2_raw_node_ref *node; + uint8_t class; + uint8_t flags; /* Currently unused */ + u16 unused; + + uint32_t xseqno; + union { + struct jffs2_inode_cache *ic; /* reference to jffs2_inode_cache */ + uint32_t ino; /* only used in scanning/building */ + }; + union { + struct jffs2_xattr_datum *xd; /* reference to jffs2_xattr_datum */ + uint32_t xid; /* only used in sccanning/building */ + }; + struct jffs2_xattr_ref *next; /* chained from ic->xref_list */ +}; + +#define XREF_DELETE_MARKER (0x00000001) +static inline int is_xattr_ref_dead(struct jffs2_xattr_ref *ref) +{ + return ((ref->xseqno & XREF_DELETE_MARKER) != 0); +} + +#ifdef CONFIG_JFFS2_FS_XATTR + +extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c); +extern void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c); +extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c); + +extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, + uint32_t xid, uint32_t version); + +extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); +extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); + +extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd, + struct jffs2_raw_node_ref *raw); +extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref, + struct jffs2_raw_node_ref *raw); +extern int jffs2_verify_xattr(struct jffs2_sb_info *c); +extern void jffs2_release_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd); +extern void jffs2_release_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref); + +extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname, + char *buffer, size_t size); +extern int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, + const char *buffer, size_t size, int flags); + +extern struct xattr_handler *jffs2_xattr_handlers[]; +extern struct xattr_handler jffs2_user_xattr_handler; +extern struct xattr_handler jffs2_trusted_xattr_handler; + +extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t); +#define jffs2_getxattr generic_getxattr +#define jffs2_setxattr generic_setxattr +#define jffs2_removexattr generic_removexattr + +#else + +#define jffs2_init_xattr_subsystem(c) +#define jffs2_build_xattr_subsystem(c) +#define jffs2_clear_xattr_subsystem(c) + +#define jffs2_xattr_delete_inode(c, ic) +#define jffs2_xattr_free_inode(c, ic) +#define jffs2_verify_xattr(c) (1) + +#define jffs2_xattr_handlers NULL +#define jffs2_listxattr NULL +#define jffs2_getxattr NULL +#define jffs2_setxattr NULL +#define jffs2_removexattr NULL + +#endif /* CONFIG_JFFS2_FS_XATTR */ + +#ifdef CONFIG_JFFS2_FS_SECURITY +extern int jffs2_init_security(struct inode *inode, struct inode *dir); +extern struct xattr_handler jffs2_security_xattr_handler; +#else +#define jffs2_init_security(inode,dir) (0) +#endif /* CONFIG_JFFS2_FS_SECURITY */ + +#endif /* _JFFS2_FS_XATTR_H_ */ diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c new file mode 100644 index 000000000..ed046e19d --- /dev/null +++ b/fs/jffs2/xattr_trusted.c @@ -0,0 +1,52 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright (C) 2006 NEC Corporation + * + * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> + * + * For licensing information, see the file 'LICENCE' in this directory. + * + */ +#include <linux/kernel.h> +#include <linux/fs.h> +#include <linux/jffs2.h> +#include <linux/xattr.h> +#include <linux/mtd/mtd.h> +#include "nodelist.h" + +static int jffs2_trusted_getxattr(struct inode *inode, const char *name, + void *buffer, size_t size) +{ + if (!strcmp(name, "")) + return -EINVAL; + return do_jffs2_getxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size); +} + +static int jffs2_trusted_setxattr(struct inode *inode, const char *name, const void *buffer, + size_t size, int flags) +{ + if (!strcmp(name, "")) + return -EINVAL; + return do_jffs2_setxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size, flags); +} + +static size_t jffs2_trusted_listxattr(struct inode *inode, char *list, size_t list_size, + const char *name, size_t name_len) +{ + size_t retlen = XATTR_TRUSTED_PREFIX_LEN + name_len + 1; + + if (list && retlen<=list_size) { + strcpy(list, XATTR_TRUSTED_PREFIX); + strcpy(list + XATTR_TRUSTED_PREFIX_LEN, name); + } + + return retlen; +} + +struct xattr_handler jffs2_trusted_xattr_handler = { + .prefix = XATTR_TRUSTED_PREFIX, + .list = jffs2_trusted_listxattr, + .set = jffs2_trusted_setxattr, + .get = jffs2_trusted_getxattr +}; diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c new file mode 100644 index 000000000..2f8e9aa01 --- /dev/null +++ b/fs/jffs2/xattr_user.c @@ -0,0 +1,52 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright (C) 2006 NEC Corporation + * + * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> + * + * For licensing information, see the file 'LICENCE' in this directory. + * + */ +#include <linux/kernel.h> +#include <linux/fs.h> +#include <linux/jffs2.h> +#include <linux/xattr.h> +#include <linux/mtd/mtd.h> +#include "nodelist.h" + +static int jffs2_user_getxattr(struct inode *inode, const char *name, + void *buffer, size_t size) +{ + if (!strcmp(name, "")) + return -EINVAL; + return do_jffs2_getxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size); +} + +static int jffs2_user_setxattr(struct inode *inode, const char *name, const void *buffer, + size_t size, int flags) +{ + if (!strcmp(name, "")) + return -EINVAL; + return do_jffs2_setxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size, flags); +} + +static size_t jffs2_user_listxattr(struct inode *inode, char *list, size_t list_size, + const char *name, size_t name_len) +{ + size_t retlen = XATTR_USER_PREFIX_LEN + name_len + 1; + + if (list && retlen <= list_size) { + strcpy(list, XATTR_USER_PREFIX); + strcpy(list + XATTR_USER_PREFIX_LEN, name); + } + + return retlen; +} + +struct xattr_handler jffs2_user_xattr_handler = { + .prefix = XATTR_USER_PREFIX, + .list = jffs2_user_listxattr, + .set = jffs2_user_setxattr, + .get = jffs2_user_getxattr +}; diff --git a/fs/nfs/client.c b/fs/nfs/client.c new file mode 100644 index 000000000..aa9e41219 --- /dev/null +++ b/fs/nfs/client.c @@ -0,0 +1,1436 @@ +/* client.c: NFS client sharing and management code + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + + +#include <linux/module.h> +#include <linux/init.h> + +#include <linux/time.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/string.h> +#include <linux/stat.h> +#include <linux/errno.h> +#include <linux/unistd.h> +#include <linux/sunrpc/clnt.h> +#include <linux/sunrpc/stats.h> +#include <linux/sunrpc/metrics.h> +#include <linux/nfs_fs.h> +#include <linux/nfs_mount.h> +#include <linux/nfs4_mount.h> +#include <linux/lockd/bind.h> +#include <linux/smp_lock.h> +#include <linux/seq_file.h> +#include <linux/mount.h> +#include <linux/nfs_idmap.h> +#include <linux/vfs.h> +#include <linux/inet.h> +#include <linux/nfs_xdr.h> + +#include <asm/system.h> + +#include "nfs4_fs.h" +#include "callback.h" +#include "delegation.h" +#include "iostat.h" +#include "internal.h" + +#define NFSDBG_FACILITY NFSDBG_CLIENT + +static DEFINE_SPINLOCK(nfs_client_lock); +static LIST_HEAD(nfs_client_list); +static LIST_HEAD(nfs_volume_list); +static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); + +/* + * RPC cruft for NFS + */ +static struct rpc_version *nfs_version[5] = { + [2] = &nfs_version2, +#ifdef CONFIG_NFS_V3 + [3] = &nfs_version3, +#endif +#ifdef CONFIG_NFS_V4 + [4] = &nfs_version4, +#endif +}; + +struct rpc_program nfs_program = { + .name = "nfs", + .number = NFS_PROGRAM, + .nrvers = ARRAY_SIZE(nfs_version), + .version = nfs_version, + .stats = &nfs_rpcstat, + .pipe_dir_name = "/nfs", +}; + +struct rpc_stat nfs_rpcstat = { + .program = &nfs_program +}; + + +#ifdef CONFIG_NFS_V3_ACL +static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program }; +static struct rpc_version * nfsacl_version[] = { + [3] = &nfsacl_version3, +}; + +struct rpc_program nfsacl_program = { + .name = "nfsacl", + .number = NFS_ACL_PROGRAM, + .nrvers = ARRAY_SIZE(nfsacl_version), + .version = nfsacl_version, + .stats = &nfsacl_rpcstat, +}; +#endif /* CONFIG_NFS_V3_ACL */ + +/* + * Allocate a shared client record + * + * Since these are allocated/deallocated very rarely, we don't + * bother putting them in a slab cache... + */ +static struct nfs_client *nfs_alloc_client(const char *hostname, + const struct sockaddr_in *addr, + int nfsversion) +{ + struct nfs_client *clp; + int error; + + if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) + goto error_0; + + error = rpciod_up(); + if (error < 0) { + dprintk("%s: couldn't start rpciod! Error = %d\n", + __FUNCTION__, error); + goto error_1; + } + __set_bit(NFS_CS_RPCIOD, &clp->cl_res_state); + + if (nfsversion == 4) { + if (nfs_callback_up() < 0) + goto error_2; + __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state); + } + + atomic_set(&clp->cl_count, 1); + clp->cl_cons_state = NFS_CS_INITING; + + clp->cl_nfsversion = nfsversion; + memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr)); + + if (hostname) { + clp->cl_hostname = kstrdup(hostname, GFP_KERNEL); + if (!clp->cl_hostname) + goto error_3; + } + + INIT_LIST_HEAD(&clp->cl_superblocks); + clp->cl_rpcclient = ERR_PTR(-EINVAL); + +#ifdef CONFIG_NFS_V4 + init_rwsem(&clp->cl_sem); + INIT_LIST_HEAD(&clp->cl_delegations); + INIT_LIST_HEAD(&clp->cl_state_owners); + INIT_LIST_HEAD(&clp->cl_unused); + spin_lock_init(&clp->cl_lock); + INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp); + rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); + clp->cl_boot_time = CURRENT_TIME; + clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; +#endif + + nfs_fscache_get_client_cookie(clp); + + return clp; + +error_3: + if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) + nfs_callback_down(); +error_2: + rpciod_down(); + __clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state); +error_1: + kfree(clp); +error_0: + return NULL; +} + +static void nfs4_shutdown_client(struct nfs_client *clp) +{ +#ifdef CONFIG_NFS_V4 + if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state)) + nfs4_kill_renewd(clp); + while (!list_empty(&clp->cl_unused)) { + struct nfs4_state_owner *sp; + + sp = list_entry(clp->cl_unused.next, + struct nfs4_state_owner, + so_list); + list_del(&sp->so_list); + kfree(sp); + } + BUG_ON(!list_empty(&clp->cl_state_owners)); + if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state)) + nfs_idmap_delete(clp); +#endif +} + +/* + * Destroy a shared client record + */ +static void nfs_free_client(struct nfs_client *clp) +{ + dprintk("--> nfs_free_client(%d)\n", clp->cl_nfsversion); + + nfs4_shutdown_client(clp); + + nfs_fscache_release_client_cookie(clp); + + /* -EIO all pending I/O */ + if (!IS_ERR(clp->cl_rpcclient)) + rpc_shutdown_client(clp->cl_rpcclient); + + if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) + nfs_callback_down(); + + if (__test_and_clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state)) + rpciod_down(); + + kfree(clp->cl_hostname); + kfree(clp); + + dprintk("<-- nfs_free_client()\n"); +} + +/* + * Release a reference to a shared client record + */ +void nfs_put_client(struct nfs_client *clp) +{ + if (!clp) + return; + + dprintk("--> nfs_put_client({%d})\n", atomic_read(&clp->cl_count)); + + if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) { + list_del(&clp->cl_share_link); + spin_unlock(&nfs_client_lock); + + BUG_ON(!list_empty(&clp->cl_superblocks)); + + nfs_free_client(clp); + } +} + +/* + * Find a client by address + * - caller must hold nfs_client_lock + */ +static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr, int nfsversion) +{ + struct nfs_client *clp; + + list_for_each_entry(clp, &nfs_client_list, cl_share_link) { + /* Different NFS versions cannot share the same nfs_client */ + if (clp->cl_nfsversion != nfsversion) + continue; + + if (memcmp(&clp->cl_addr.sin_addr, &addr->sin_addr, + sizeof(clp->cl_addr.sin_addr)) != 0) + continue; + + if (clp->cl_addr.sin_port == addr->sin_port) + goto found; + } + + return NULL; + +found: + atomic_inc(&clp->cl_count); + return clp; +} + +/* + * Find a client by IP address and protocol version + * - returns NULL if no such client + */ +struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversion) +{ + struct nfs_client *clp; + + spin_lock(&nfs_client_lock); + clp = __nfs_find_client(addr, nfsversion); + spin_unlock(&nfs_client_lock); + + BUG_ON(clp->cl_cons_state == 0); + + return clp; +} + +/* + * Look up a client by IP address and protocol version + * - creates a new record if one doesn't yet exist + */ +static struct nfs_client *nfs_get_client(const char *hostname, + const struct sockaddr_in *addr, + int nfsversion) +{ + struct nfs_client *clp, *new = NULL; + int error; + + dprintk("--> nfs_get_client(%s,"NIPQUAD_FMT":%d,%d)\n", + hostname ?: "", NIPQUAD(addr->sin_addr), + addr->sin_port, nfsversion); + + /* see if the client already exists */ + do { + spin_lock(&nfs_client_lock); + + clp = __nfs_find_client(addr, nfsversion); + if (clp) + goto found_client; + if (new) + goto install_client; + + spin_unlock(&nfs_client_lock); + + new = nfs_alloc_client(hostname, addr, nfsversion); + } while (new); + + return ERR_PTR(-ENOMEM); + + /* install a new client and return with it unready */ +install_client: + clp = new; + list_add(&clp->cl_share_link, &nfs_client_list); + spin_unlock(&nfs_client_lock); + dprintk("--> nfs_get_client() = %p [new]\n", clp); + return clp; + + /* found an existing client + * - make sure it's ready before returning + */ +found_client: + spin_unlock(&nfs_client_lock); + + if (new) + nfs_free_client(new); + + error = wait_event_interruptible(nfs_client_active_wq, + clp->cl_cons_state != NFS_CS_INITING); + if (error < 0) { + nfs_put_client(clp); + return ERR_PTR(-ERESTARTSYS); + } + + if (clp->cl_cons_state < NFS_CS_READY) { + error = clp->cl_cons_state; + nfs_put_client(clp); + return ERR_PTR(error); + } + + BUG_ON(clp->cl_cons_state != NFS_CS_READY); + + dprintk("--> nfs_get_client() = %p [share]\n", clp); + return clp; +} + +/* + * Mark a server as ready or failed + */ +static void nfs_mark_client_ready(struct nfs_client *clp, int state) +{ + clp->cl_cons_state = state; + wake_up_all(&nfs_client_active_wq); +} + +/* + * Initialise the timeout values for a connection + */ +static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, + unsigned int timeo, unsigned int retrans) +{ + to->to_initval = timeo * HZ / 10; + to->to_retries = retrans; + if (!to->to_retries) + to->to_retries = 2; + + switch (proto) { + case IPPROTO_TCP: + if (!to->to_initval) + to->to_initval = 60 * HZ; + if (to->to_initval > NFS_MAX_TCP_TIMEOUT) + to->to_initval = NFS_MAX_TCP_TIMEOUT; + to->to_increment = to->to_initval; + to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); + to->to_exponential = 0; + break; + case IPPROTO_UDP: + default: + if (!to->to_initval) + to->to_initval = 11 * HZ / 10; + if (to->to_initval > NFS_MAX_UDP_TIMEOUT) + to->to_initval = NFS_MAX_UDP_TIMEOUT; + to->to_maxval = NFS_MAX_UDP_TIMEOUT; + to->to_exponential = 1; + break; + } +} + +/* + * Create an RPC client handle + */ +static int nfs_create_rpc_client(struct nfs_client *clp, int proto, + unsigned int timeo, + unsigned int retrans, + rpc_authflavor_t flavor) +{ + struct rpc_timeout timeparms; + struct rpc_xprt *xprt = NULL; + struct rpc_clnt *clnt = NULL; + + if (!IS_ERR(clp->cl_rpcclient)) + return 0; + + nfs_init_timeout_values(&timeparms, proto, timeo, retrans); + clp->retrans_timeo = timeparms.to_initval; + clp->retrans_count = timeparms.to_retries; + + /* create transport and client */ + xprt = xprt_create_proto(proto, &clp->cl_addr, &timeparms); + if (IS_ERR(xprt)) { + dprintk("%s: cannot create RPC transport. Error = %ld\n", + __FUNCTION__, PTR_ERR(xprt)); + return PTR_ERR(xprt); + } + + /* Bind to a reserved port! */ + xprt->resvport = 1; + /* Create the client RPC handle */ + clnt = rpc_create_client(xprt, clp->cl_hostname, &nfs_program, + clp->rpc_ops->version, RPC_AUTH_UNIX); + if (IS_ERR(clnt)) { + dprintk("%s: cannot create RPC client. Error = %ld\n", + __FUNCTION__, PTR_ERR(clnt)); + return PTR_ERR(clnt); + } + + clnt->cl_intr = 1; + clnt->cl_softrtry = 1; + clnt->cl_tagxid = 1; + clp->cl_rpcclient = clnt; + return 0; +} + +/* + * Version 2 or 3 client destruction + */ +static void nfs_destroy_server(struct nfs_server *server) +{ + if (!IS_ERR(server->client_acl)) + rpc_shutdown_client(server->client_acl); + + if (!(server->flags & NFS_MOUNT_NONLM)) + lockd_down(); /* release rpc.lockd */ +} + +/* + * Version 2 or 3 lockd setup + */ +static int nfs_start_lockd(struct nfs_server *server) +{ + int error = 0; + + if (server->nfs_client->cl_nfsversion > 3) + goto out; + if (server->flags & NFS_MOUNT_NONLM) + goto out; + error = lockd_up(); + if (error < 0) + server->flags |= NFS_MOUNT_NONLM; + else + server->destroy = nfs_destroy_server; +out: + return error; +} + +/* + * Initialise an NFSv3 ACL client connection + */ +#ifdef CONFIG_NFS_V3_ACL +static void nfs_init_server_aclclient(struct nfs_server *server) +{ + if (server->nfs_client->cl_nfsversion != 3) + goto out_noacl; + if (server->flags & NFS_MOUNT_NOACL) + goto out_noacl; + + server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3); + if (IS_ERR(server->client_acl)) + goto out_noacl; + + /* No errors! Assume that Sun nfsacls are supported */ + server->caps |= NFS_CAP_ACLS; + return; + +out_noacl: + server->caps &= ~NFS_CAP_ACLS; +} +#else +static inline void nfs_init_server_aclclient(struct nfs_server *server) +{ + server->flags &= ~NFS_MOUNT_NOACL; + server->caps &= ~NFS_CAP_ACLS; +} +#endif + +/* + * Create a general RPC client + */ +static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t pseudoflavour) +{ + struct nfs_client *clp = server->nfs_client; + + server->client = rpc_clone_client(clp->cl_rpcclient); + if (IS_ERR(server->client)) { + dprintk("%s: couldn't create rpc_client!\n", __FUNCTION__); + return PTR_ERR(server->client); + } + + if (pseudoflavour != clp->cl_rpcclient->cl_auth->au_flavor) { + struct rpc_auth *auth; + + auth = rpcauth_create(pseudoflavour, server->client); + if (IS_ERR(auth)) { + dprintk("%s: couldn't create credcache!\n", __FUNCTION__); + return PTR_ERR(auth); + } + } + server->client->cl_softrtry = 0; + if (server->flags & NFS_MOUNT_SOFT) + server->client->cl_softrtry = 1; + + server->client->cl_intr = 0; + if (server->flags & NFS4_MOUNT_INTR) + server->client->cl_intr = 1; + + server->client->cl_tagxid = (server->flags & NFS_MOUNT_TAGXID) ? 1 : 0; + + return 0; +} + +/* + * Initialise an NFS2 or NFS3 client + */ +static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data *data) +{ + int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP; + int error; + + if (clp->cl_cons_state == NFS_CS_READY) { + /* the client is already initialised */ + dprintk("<-- nfs_init_client() = 0 [already %p]\n", clp); + return 0; + } + + /* Check NFS protocol revision and initialize RPC op vector */ + clp->rpc_ops = &nfs_v2_clientops; +#ifdef CONFIG_NFS_V3 + if (clp->cl_nfsversion == 3) + clp->rpc_ops = &nfs_v3_clientops; +#endif + /* + * Create a client RPC handle for doing FSSTAT with UNIX auth only + * - RFC 2623, sec 2.3.2 + */ + error = nfs_create_rpc_client(clp, proto, data->timeo, data->retrans, + RPC_AUTH_UNIX); + if (error < 0) + goto error; + nfs_mark_client_ready(clp, NFS_CS_READY); + return 0; + +error: + nfs_mark_client_ready(clp, error); + dprintk("<-- nfs_init_client() = xerror %d\n", error); + return error; +} + +/* + * Create a version 2 or 3 client + */ +static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_data *data) +{ + struct nfs_client *clp; + int error, nfsvers = 2; + + dprintk("--> nfs_init_server()\n"); + +#ifdef CONFIG_NFS_V3 + if (data->flags & NFS_MOUNT_VER3) + nfsvers = 3; +#endif + + /* Allocate or find a client reference we can use */ + clp = nfs_get_client(data->hostname, &data->addr, nfsvers); + if (IS_ERR(clp)) { + dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp)); + return PTR_ERR(clp); + } + + error = nfs_init_client(clp, data); + if (error < 0) + goto error; + + server->nfs_client = clp; + + /* Initialise the client representation from the mount data */ + server->flags = data->flags & NFS_MOUNT_FLAGMASK; + + if (data->rsize) + server->rsize = nfs_block_size(data->rsize, NULL); + if (data->wsize) + server->wsize = nfs_block_size(data->wsize, NULL); + + server->acregmin = data->acregmin * HZ; + server->acregmax = data->acregmax * HZ; + server->acdirmin = data->acdirmin * HZ; + server->acdirmax = data->acdirmax * HZ; + + /* Start lockd here, before we might error out */ + error = nfs_start_lockd(server); + if (error < 0) + goto error; + + error = nfs_init_server_rpcclient(server, data->pseudoflavor); + if (error < 0) + goto error; + + server->namelen = data->namlen; + /* Create a client RPC handle for the NFSv3 ACL management interface */ + nfs_init_server_aclclient(server); + if (clp->cl_nfsversion == 3) { + if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) + server->namelen = NFS3_MAXNAMLEN; + server->caps |= NFS_CAP_READDIRPLUS; + } else { + if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) + server->namelen = NFS2_MAXNAMLEN; + } + + dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp); + return 0; + +error: + server->nfs_client = NULL; + nfs_put_client(clp); + dprintk("<-- nfs_init_server() = xerror %d\n", error); + return error; +} + +/* + * Load up the server record from information gained in an fsinfo record + */ +static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *fsinfo) +{ + unsigned long max_rpc_payload; + + /* Work out a lot of parameters */ + if (server->rsize == 0) + server->rsize = nfs_block_size(fsinfo->rtpref, NULL); + if (server->wsize == 0) + server->wsize = nfs_block_size(fsinfo->wtpref, NULL); + + if (fsinfo->rtmax >= 512 && server->rsize > fsinfo->rtmax) + server->rsize = nfs_block_size(fsinfo->rtmax, NULL); + if (fsinfo->wtmax >= 512 && server->wsize > fsinfo->wtmax) + server->wsize = nfs_block_size(fsinfo->wtmax, NULL); + + max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL); + if (server->rsize > max_rpc_payload) + server->rsize = max_rpc_payload; + if (server->rsize > NFS_MAX_FILE_IO_SIZE) + server->rsize = NFS_MAX_FILE_IO_SIZE; + server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD; + + if (server->wsize > max_rpc_payload) + server->wsize = max_rpc_payload; + if (server->wsize > NFS_MAX_FILE_IO_SIZE) + server->wsize = NFS_MAX_FILE_IO_SIZE; + server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; + server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL); + + server->dtsize = nfs_block_size(fsinfo->dtpref, NULL); + if (server->dtsize > PAGE_CACHE_SIZE) + server->dtsize = PAGE_CACHE_SIZE; + if (server->dtsize > server->rsize) + server->dtsize = server->rsize; + + if (server->flags & NFS_MOUNT_NOAC) { + server->acregmin = server->acregmax = 0; + server->acdirmin = server->acdirmax = 0; + } + + server->maxfilesize = fsinfo->maxfilesize; + + /* We're airborne Set socket buffersize */ + rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100); +} + +/* + * Probe filesystem information, including the FSID on v2/v3 + */ +static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr) +{ + struct nfs_fsinfo fsinfo; + struct nfs_client *clp = server->nfs_client; + int error; + + dprintk("--> nfs_probe_fsinfo()\n"); + + if (clp->rpc_ops->set_capabilities != NULL) { + error = clp->rpc_ops->set_capabilities(server, mntfh); + if (error < 0) + goto out_error; + } + + fsinfo.fattr = fattr; + nfs_fattr_init(fattr); + error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo); + if (error < 0) + goto out_error; + + nfs_server_set_fsinfo(server, &fsinfo); + + /* Get some general file system info */ + if (server->namelen == 0) { + struct nfs_pathconf pathinfo; + + pathinfo.fattr = fattr; + nfs_fattr_init(fattr); + + if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0) + server->namelen = pathinfo.max_namelen; + } + + dprintk("<-- nfs_probe_fsinfo() = 0\n"); + return 0; + +out_error: + dprintk("nfs_probe_fsinfo: error = %d\n", -error); + return error; +} + +/* + * Copy useful information when duplicating a server record + */ +static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source) +{ + target->flags = source->flags; + target->acregmin = source->acregmin; + target->acregmax = source->acregmax; + target->acdirmin = source->acdirmin; + target->acdirmax = source->acdirmax; + target->caps = source->caps; +} + +/* + * Allocate and initialise a server record + */ +static struct nfs_server *nfs_alloc_server(void) +{ + struct nfs_server *server; + + server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); + if (!server) + return NULL; + + server->client = server->client_acl = ERR_PTR(-EINVAL); + + /* Zero out the NFS state stuff */ + INIT_LIST_HEAD(&server->client_link); + INIT_LIST_HEAD(&server->master_link); + + server->io_stats = nfs_alloc_iostats(); + if (!server->io_stats) { + kfree(server); + return NULL; + } + + return server; +} + +/* + * Free up a server record + */ +void nfs_free_server(struct nfs_server *server) +{ + dprintk("--> nfs_free_server()\n"); + + spin_lock(&nfs_client_lock); + list_del(&server->client_link); + list_del(&server->master_link); + spin_unlock(&nfs_client_lock); + + if (server->destroy != NULL) + server->destroy(server); + if (!IS_ERR(server->client)) + rpc_shutdown_client(server->client); + + nfs_put_client(server->nfs_client); + + nfs_free_iostats(server->io_stats); + kfree(server); + nfs_release_automount_timer(); + dprintk("<-- nfs_free_server()\n"); +} + +/* + * Create a version 2 or 3 volume record + * - keyed on server and FSID + */ +struct nfs_server *nfs_create_server(const struct nfs_mount_data *data, + struct nfs_fh *mntfh) +{ + struct nfs_server *server; + struct nfs_fattr fattr; + int error; + + server = nfs_alloc_server(); + if (!server) + return ERR_PTR(-ENOMEM); + + /* Get a client representation */ + error = nfs_init_server(server, data); + if (error < 0) + goto error; + + BUG_ON(!server->nfs_client); + BUG_ON(!server->nfs_client->rpc_ops); + BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); + + /* Probe the root fh to retrieve its FSID */ + error = nfs_probe_fsinfo(server, mntfh, &fattr); + if (error < 0) + goto error; + if (!(fattr.valid & NFS_ATTR_FATTR)) { + error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr); + if (error < 0) { + dprintk("nfs_create_server: getattr error = %d\n", -error); + goto error; + } + } + memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid)); + + dprintk("Server FSID: %llx:%llx\n", server->fsid.major, server->fsid.minor); + + BUG_ON(!server->nfs_client); + BUG_ON(!server->nfs_client->rpc_ops); + BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); + + spin_lock(&nfs_client_lock); + list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); + list_add_tail(&server->master_link, &nfs_volume_list); + spin_unlock(&nfs_client_lock); + + server->mount_time = jiffies; + return server; + +error: + nfs_free_server(server); + return ERR_PTR(error); +} + +#ifdef CONFIG_NFS_V4 +/* + * Initialise an NFS4 client record + */ +static int nfs4_init_client(struct nfs_client *clp, + int proto, int timeo, int retrans, + rpc_authflavor_t authflavour) +{ + int error; + + if (clp->cl_cons_state == NFS_CS_READY) { + /* the client is initialised already */ + dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp); + return 0; + } + + /* Check NFS protocol revision and initialize RPC op vector */ + clp->rpc_ops = &nfs_v4_clientops; + + error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour); + if (error < 0) + goto error; + + error = nfs_idmap_new(clp); + if (error < 0) { + dprintk("%s: failed to create idmapper. Error = %d\n", + __FUNCTION__, error); + goto error; + } + __set_bit(NFS_CS_IDMAP, &clp->cl_res_state); + + nfs_mark_client_ready(clp, NFS_CS_READY); + return 0; + +error: + nfs_mark_client_ready(clp, error); + dprintk("<-- nfs4_init_client() = xerror %d\n", error); + return error; +} + +/* + * Set up an NFS4 client + */ +static int nfs4_set_client(struct nfs_server *server, + const char *hostname, const struct sockaddr_in *addr, + rpc_authflavor_t authflavour, + int proto, int timeo, int retrans) +{ + struct nfs_client *clp; + int error; + + dprintk("--> nfs4_set_client()\n"); + + /* Allocate or find a client reference we can use */ + clp = nfs_get_client(hostname, addr, 4); + if (IS_ERR(clp)) { + error = PTR_ERR(clp); + goto error; + } + error = nfs4_init_client(clp, proto, timeo, retrans, authflavour); + if (error < 0) + goto error_put; + + server->nfs_client = clp; + dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp); + return 0; + +error_put: + nfs_put_client(clp); +error: + dprintk("<-- nfs4_set_client() = xerror %d\n", error); + return error; +} + +/* + * Create a version 4 volume record + */ +static int nfs4_init_server(struct nfs_server *server, + const struct nfs4_mount_data *data, rpc_authflavor_t authflavour) +{ + int error; + + dprintk("--> nfs4_init_server()\n"); + + /* Initialise the client representation from the mount data */ + server->flags = data->flags & NFS_MOUNT_FLAGMASK; + server->caps |= NFS_CAP_ATOMIC_OPEN; + + if (data->rsize) + server->rsize = nfs_block_size(data->rsize, NULL); + if (data->wsize) + server->wsize = nfs_block_size(data->wsize, NULL); + + server->acregmin = data->acregmin * HZ; + server->acregmax = data->acregmax * HZ; + server->acdirmin = data->acdirmin * HZ; + server->acdirmax = data->acdirmax * HZ; + + error = nfs_init_server_rpcclient(server, authflavour); + + /* Done */ + dprintk("<-- nfs4_init_server() = %d\n", error); + return error; +} + +/* + * Create a version 4 volume record + * - keyed on server and FSID + */ +struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data, + const char *hostname, + const struct sockaddr_in *addr, + const char *mntpath, + const char *ip_addr, + rpc_authflavor_t authflavour, + struct nfs_fh *mntfh) +{ + struct nfs_fattr fattr; + struct nfs_server *server; + int error; + + dprintk("--> nfs4_create_server()\n"); + + server = nfs_alloc_server(); + if (!server) + return ERR_PTR(-ENOMEM); + + /* Get a client record */ + error = nfs4_set_client(server, hostname, addr, authflavour, + data->proto, data->timeo, data->retrans); + if (error < 0) + goto error; + + /* set up the general RPC client */ + error = nfs4_init_server(server, data, authflavour); + if (error < 0) + goto error; + + BUG_ON(!server->nfs_client); + BUG_ON(!server->nfs_client->rpc_ops); + BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); + + /* Probe the root fh to retrieve its FSID */ + error = nfs4_path_walk(server, mntfh, mntpath); + if (error < 0) + goto error; + + dprintk("Server FSID: %llx:%llx\n", server->fsid.major, server->fsid.minor); + dprintk("Mount FH: %d\n", mntfh->size); + + error = nfs_probe_fsinfo(server, mntfh, &fattr); + if (error < 0) + goto error; + + BUG_ON(!server->nfs_client); + BUG_ON(!server->nfs_client->rpc_ops); + BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); + + spin_lock(&nfs_client_lock); + list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); + list_add_tail(&server->master_link, &nfs_volume_list); + spin_unlock(&nfs_client_lock); + + server->mount_time = jiffies; + dprintk("<-- nfs4_create_server() = %p\n", server); + return server; + +error: + nfs_free_server(server); + dprintk("<-- nfs4_create_server() = error %d\n", error); + return ERR_PTR(error); +} + +/* + * Create an NFS4 referral server record + */ +struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, + struct nfs_fh *fh) +{ + struct nfs_client *parent_client; + struct nfs_server *server, *parent_server; + struct nfs_fattr fattr; + int error; + + dprintk("--> nfs4_create_referral_server()\n"); + + server = nfs_alloc_server(); + if (!server) + return ERR_PTR(-ENOMEM); + + parent_server = NFS_SB(data->sb); + parent_client = parent_server->nfs_client; + + /* Get a client representation. + * Note: NFSv4 always uses TCP, */ + error = nfs4_set_client(server, data->hostname, data->addr, + data->authflavor, + parent_server->client->cl_xprt->prot, + parent_client->retrans_timeo, + parent_client->retrans_count); + + /* Initialise the client representation from the parent server */ + nfs_server_copy_userdata(server, parent_server); + server->caps |= NFS_CAP_ATOMIC_OPEN; + + error = nfs_init_server_rpcclient(server, data->authflavor); + if (error < 0) + goto error; + + BUG_ON(!server->nfs_client); + BUG_ON(!server->nfs_client->rpc_ops); + BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); + + /* probe the filesystem info for this server filesystem */ + error = nfs_probe_fsinfo(server, fh, &fattr); + if (error < 0) + goto error; + + dprintk("Referral FSID: %llx:%llx\n", + server->fsid.major, server->fsid.minor); + + spin_lock(&nfs_client_lock); + list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); + list_add_tail(&server->master_link, &nfs_volume_list); + spin_unlock(&nfs_client_lock); + + server->mount_time = jiffies; + + dprintk("<-- nfs_create_referral_server() = %p\n", server); + return server; + +error: + nfs_free_server(server); + dprintk("<-- nfs4_create_referral_server() = error %d\n", error); + return ERR_PTR(error); +} + +#endif /* CONFIG_NFS_V4 */ + +/* + * Clone an NFS2, NFS3 or NFS4 server record + */ +struct nfs_server *nfs_clone_server(struct nfs_server *source, + struct nfs_fh *fh, + struct nfs_fattr *fattr) +{ + struct nfs_server *server; + struct nfs_fattr fattr_fsinfo; + int error; + + dprintk("--> nfs_clone_server(,%llx:%llx,)\n", + fattr->fsid.major, fattr->fsid.minor); + + server = nfs_alloc_server(); + if (!server) + return ERR_PTR(-ENOMEM); + + /* Copy data from the source */ + server->nfs_client = source->nfs_client; + atomic_inc(&server->nfs_client->cl_count); + nfs_server_copy_userdata(server, source); + + server->fsid = fattr->fsid; + + error = nfs_init_server_rpcclient(server, source->client->cl_auth->au_flavor); + if (error < 0) + goto out_free_server; + if (!IS_ERR(source->client_acl)) + nfs_init_server_aclclient(server); + + /* probe the filesystem info for this server filesystem */ + error = nfs_probe_fsinfo(server, fh, &fattr_fsinfo); + if (error < 0) + goto out_free_server; + + dprintk("Cloned FSID: %llx:%llx\n", + server->fsid.major, server->fsid.minor); + + error = nfs_start_lockd(server); + if (error < 0) + goto out_free_server; + + spin_lock(&nfs_client_lock); + list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); + list_add_tail(&server->master_link, &nfs_volume_list); + spin_unlock(&nfs_client_lock); + + server->mount_time = jiffies; + + dprintk("<-- nfs_clone_server() = %p\n", server); + return server; + +out_free_server: + nfs_free_server(server); + dprintk("<-- nfs_clone_server() = error %d\n", error); + return ERR_PTR(error); +} + +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry *proc_fs_nfs; + +static int nfs_server_list_open(struct inode *inode, struct file *file); +static void *nfs_server_list_start(struct seq_file *p, loff_t *pos); +static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos); +static void nfs_server_list_stop(struct seq_file *p, void *v); +static int nfs_server_list_show(struct seq_file *m, void *v); + +static struct seq_operations nfs_server_list_ops = { + .start = nfs_server_list_start, + .next = nfs_server_list_next, + .stop = nfs_server_list_stop, + .show = nfs_server_list_show, +}; + +static struct file_operations nfs_server_list_fops = { + .open = nfs_server_list_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static int nfs_volume_list_open(struct inode *inode, struct file *file); +static void *nfs_volume_list_start(struct seq_file *p, loff_t *pos); +static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos); +static void nfs_volume_list_stop(struct seq_file *p, void *v); +static int nfs_volume_list_show(struct seq_file *m, void *v); + +static struct seq_operations nfs_volume_list_ops = { + .start = nfs_volume_list_start, + .next = nfs_volume_list_next, + .stop = nfs_volume_list_stop, + .show = nfs_volume_list_show, +}; + +static struct file_operations nfs_volume_list_fops = { + .open = nfs_volume_list_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +/* + * open "/proc/fs/nfsfs/servers" which provides a summary of servers with which + * we're dealing + */ +static int nfs_server_list_open(struct inode *inode, struct file *file) +{ + struct seq_file *m; + int ret; + + ret = seq_open(file, &nfs_server_list_ops); + if (ret < 0) + return ret; + + m = file->private_data; + m->private = PDE(inode)->data; + + return 0; +} + +/* + * set up the iterator to start reading from the server list and return the first item + */ +static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos) +{ + struct list_head *_p; + loff_t pos = *_pos; + + /* lock the list against modification */ + spin_lock(&nfs_client_lock); + + /* allow for the header line */ + if (!pos) + return SEQ_START_TOKEN; + pos--; + + /* find the n'th element in the list */ + list_for_each(_p, &nfs_client_list) + if (!pos--) + break; + + return _p != &nfs_client_list ? _p : NULL; +} + +/* + * move to next server + */ +static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos) +{ + struct list_head *_p; + + (*pos)++; + + _p = v; + _p = (v == SEQ_START_TOKEN) ? nfs_client_list.next : _p->next; + + return _p != &nfs_client_list ? _p : NULL; +} + +/* + * clean up after reading from the transports list + */ +static void nfs_server_list_stop(struct seq_file *p, void *v) +{ + spin_unlock(&nfs_client_lock); +} + +/* + * display a header line followed by a load of call lines + */ +static int nfs_server_list_show(struct seq_file *m, void *v) +{ + struct nfs_client *clp; + + /* display header on line 1 */ + if (v == SEQ_START_TOKEN) { + seq_puts(m, "NV SERVER PORT USE HOSTNAME\n"); + return 0; + } + + /* display one transport per line on subsequent lines */ + clp = list_entry(v, struct nfs_client, cl_share_link); + + seq_printf(m, "v%d %02x%02x%02x%02x %4hx %3d %s\n", + clp->cl_nfsversion, + NIPQUAD(clp->cl_addr.sin_addr), + ntohs(clp->cl_addr.sin_port), + atomic_read(&clp->cl_count), + clp->cl_hostname); + + return 0; +} + +/* + * open "/proc/fs/nfsfs/volumes" which provides a summary of extant volumes + */ +static int nfs_volume_list_open(struct inode *inode, struct file *file) +{ + struct seq_file *m; + int ret; + + ret = seq_open(file, &nfs_volume_list_ops); + if (ret < 0) + return ret; + + m = file->private_data; + m->private = PDE(inode)->data; + + return 0; +} + +/* + * set up the iterator to start reading from the volume list and return the first item + */ +static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos) +{ + struct list_head *_p; + loff_t pos = *_pos; + + /* lock the list against modification */ + spin_lock(&nfs_client_lock); + + /* allow for the header line */ + if (!pos) + return SEQ_START_TOKEN; + pos--; + + /* find the n'th element in the list */ + list_for_each(_p, &nfs_volume_list) + if (!pos--) + break; + + return _p != &nfs_volume_list ? _p : NULL; +} + +/* + * move to next volume + */ +static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos) +{ + struct list_head *_p; + + (*pos)++; + + _p = v; + _p = (v == SEQ_START_TOKEN) ? nfs_volume_list.next : _p->next; + + return _p != &nfs_volume_list ? _p : NULL; +} + +/* + * clean up after reading from the transports list + */ +static void nfs_volume_list_stop(struct seq_file *p, void *v) +{ + spin_unlock(&nfs_client_lock); +} + +/* + * display a header line followed by a load of call lines + */ +static int nfs_volume_list_show(struct seq_file *m, void *v) +{ + struct nfs_server *server; + struct nfs_client *clp; + char dev[8], fsid[17]; + + /* display header on line 1 */ + if (v == SEQ_START_TOKEN) { + seq_puts(m, "NV SERVER PORT DEV FSID FSC\n"); + return 0; + } + /* display one transport per line on subsequent lines */ + server = list_entry(v, struct nfs_server, master_link); + clp = server->nfs_client; + + snprintf(dev, 8, "%u:%u", + MAJOR(server->s_dev), MINOR(server->s_dev)); + + snprintf(fsid, 17, "%llx:%llx", + server->fsid.major, server->fsid.minor); + + seq_printf(m, "v%d %02x%02x%02x%02x %4hx %-7s %-17s %s\n", + clp->cl_nfsversion, + NIPQUAD(clp->cl_addr.sin_addr), + ntohs(clp->cl_addr.sin_port), + dev, + fsid, + nfs_server_fscache_state(server)); + + return 0; +} + +/* + * initialise the /proc/fs/nfsfs/ directory + */ +int __init nfs_fs_proc_init(void) +{ + struct proc_dir_entry *p; + + proc_fs_nfs = proc_mkdir("nfsfs", proc_root_fs); + if (!proc_fs_nfs) + goto error_0; + + proc_fs_nfs->owner = THIS_MODULE; + + /* a file of servers with which we're dealing */ + p = create_proc_entry("servers", S_IFREG|S_IRUGO, proc_fs_nfs); + if (!p) + goto error_1; + + p->proc_fops = &nfs_server_list_fops; + p->owner = THIS_MODULE; + + /* a file of volumes that we have mounted */ + p = create_proc_entry("volumes", S_IFREG|S_IRUGO, proc_fs_nfs); + if (!p) + goto error_2; + + p->proc_fops = &nfs_volume_list_fops; + p->owner = THIS_MODULE; + return 0; + +error_2: + remove_proc_entry("servers", proc_fs_nfs); +error_1: + remove_proc_entry("nfsfs", proc_root_fs); +error_0: + return -ENOMEM; +} + +/* + * clean up the /proc/fs/nfsfs/ directory + */ +void nfs_fs_proc_exit(void) +{ + remove_proc_entry("volumes", proc_fs_nfs); + remove_proc_entry("servers", proc_fs_nfs); + remove_proc_entry("nfsfs", proc_root_fs); +} + +#endif /* CONFIG_PROC_FS */ diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c new file mode 100644 index 000000000..0949bacdb --- /dev/null +++ b/fs/nfs/fscache.c @@ -0,0 +1,345 @@ +/* fscache.c: NFS filesystem cache interface + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/nfs_fs.h> +#include <linux/nfs_fs_sb.h> +#include <linux/in6.h> + +#include "internal.h" + +/* + * Sysctl variables + */ +atomic_t nfs_fscache_to_pages; +atomic_t nfs_fscache_from_pages; +atomic_t nfs_fscache_uncache_page; +int nfs_fscache_from_error; +int nfs_fscache_to_error; + +#define NFSDBG_FACILITY NFSDBG_FSCACHE + +/* the auxiliary data in the cache (used for coherency management) */ +struct nfs_fh_auxdata { + struct timespec i_mtime; + struct timespec i_ctime; + loff_t i_size; +}; + +static struct fscache_netfs_operations nfs_cache_ops = { +}; + +struct fscache_netfs nfs_cache_netfs = { + .name = "nfs", + .version = 0, + .ops = &nfs_cache_ops, +}; + +static const uint8_t nfs_cache_ipv6_wrapper_for_ipv4[12] = { + [0 ... 9] = 0x00, + [10 ... 11] = 0xff +}; + +struct nfs_server_key { + uint16_t nfsversion; + uint16_t port; + union { + struct { + uint8_t ipv6wrapper[12]; + struct in_addr addr; + } ipv4_addr; + struct in6_addr ipv6_addr; + }; +}; + +static uint16_t nfs_server_get_key(const void *cookie_netfs_data, + void *buffer, uint16_t bufmax) +{ + const struct nfs_client *clp = cookie_netfs_data; + struct nfs_server_key *key = buffer; + uint16_t len = 0; + + key->nfsversion = clp->cl_nfsversion; + + switch (clp->cl_addr.sin_family) { + case AF_INET: + key->port = clp->cl_addr.sin_port; + + memcpy(&key->ipv4_addr.ipv6wrapper, + &nfs_cache_ipv6_wrapper_for_ipv4, + sizeof(key->ipv4_addr.ipv6wrapper)); + memcpy(&key->ipv4_addr.addr, + &clp->cl_addr.sin_addr, + sizeof(key->ipv4_addr.addr)); + len = sizeof(struct nfs_server_key); + break; + + case AF_INET6: + key->port = clp->cl_addr.sin_port; + + memcpy(&key->ipv6_addr, + &clp->cl_addr.sin_addr, + sizeof(key->ipv6_addr)); + len = sizeof(struct nfs_server_key); + break; + + default: + len = 0; + printk(KERN_WARNING "NFS: Unknown network family '%d'\n", + clp->cl_addr.sin_family); + break; + } + + return len; +} + +/* + * the root index for the filesystem is defined by nfsd IP address and ports + */ +struct fscache_cookie_def nfs_cache_server_index_def = { + .name = "NFS.servers", + .type = FSCACHE_COOKIE_TYPE_INDEX, + .get_key = nfs_server_get_key, +}; + +static uint16_t nfs_fh_get_key(const void *cookie_netfs_data, + void *buffer, uint16_t bufmax) +{ + const struct nfs_inode *nfsi = cookie_netfs_data; + uint16_t nsize; + + /* set the file handle */ + nsize = nfsi->fh.size; + memcpy(buffer, nfsi->fh.data, nsize); + return nsize; +} + +/* + * indication of pages that now have cache metadata retained + * - this function should mark the specified pages as now being cached + */ +static void nfs_fh_mark_pages_cached(void *cookie_netfs_data, + struct address_space *mapping, + struct pagevec *cached_pvec) +{ + struct nfs_inode *nfsi = cookie_netfs_data; + unsigned long loop; + + dprintk("NFS: nfs_fh_mark_pages_cached: nfs_inode 0x%p pages %ld\n", + nfsi, cached_pvec->nr); + + for (loop = 0; loop < cached_pvec->nr; loop++) + SetPageNfsCached(cached_pvec->pages[loop]); +} + +/* + * get an extra reference on a read context + * - this function can be absent if the completion function doesn't + * require a context + */ +static void nfs_fh_get_context(void *cookie_netfs_data, void *context) +{ + get_nfs_open_context(context); +} + +/* + * release an extra reference on a read context + * - this function can be absent if the completion function doesn't + * require a context + */ +static void nfs_fh_put_context(void *cookie_netfs_data, void *context) +{ + if (context) + put_nfs_open_context(context); +} + +/* + * indication the cookie is no longer uncached + * - this function is called when the backing store currently caching a cookie + * is removed + * - the netfs should use this to clean up any markers indicating cached pages + * - this is mandatory for any object that may have data + */ +static void nfs_fh_now_uncached(void *cookie_netfs_data) +{ + struct nfs_inode *nfsi = cookie_netfs_data; + struct pagevec pvec; + pgoff_t first; + int loop, nr_pages; + + pagevec_init(&pvec, 0); + first = 0; + + dprintk("NFS: nfs_fh_now_uncached: nfs_inode 0x%p\n", nfsi); + + for (;;) { + /* grab a bunch of pages to clean */ + nr_pages = pagevec_lookup(&pvec, + nfsi->vfs_inode.i_mapping, + first, + PAGEVEC_SIZE - pagevec_count(&pvec)); + if (!nr_pages) + break; + + for (loop = 0; loop < nr_pages; loop++) + ClearPageNfsCached(pvec.pages[loop]); + + first = pvec.pages[nr_pages - 1]->index + 1; + + pvec.nr = nr_pages; + pagevec_release(&pvec); + cond_resched(); + } +} + +/* + * get certain file attributes from the netfs data + * - this function can be absent for an index + * - not permitted to return an error + * - the netfs data from the cookie being used as the source is + * presented + */ +static void nfs_fh_get_attr(const void *cookie_netfs_data, uint64_t *size) +{ + const struct nfs_inode *nfsi = cookie_netfs_data; + + *size = nfsi->vfs_inode.i_size; +} + +/* + * get the auxilliary data from netfs data + * - this function can be absent if the index carries no state data + * - should store the auxilliary data in the buffer + * - should return the amount of amount stored + * - not permitted to return an error + * - the netfs data from the cookie being used as the source is + * presented + */ +static uint16_t nfs_fh_get_aux(const void *cookie_netfs_data, + void *buffer, uint16_t bufmax) +{ + struct nfs_fh_auxdata auxdata; + const struct nfs_inode *nfsi = cookie_netfs_data; + + auxdata.i_size = nfsi->vfs_inode.i_size; + auxdata.i_mtime = nfsi->vfs_inode.i_mtime; + auxdata.i_ctime = nfsi->vfs_inode.i_ctime; + + if (bufmax > sizeof(auxdata)) + bufmax = sizeof(auxdata); + + memcpy(buffer, &auxdata, bufmax); + return bufmax; +} + +/* + * consult the netfs about the state of an object + * - this function can be absent if the index carries no state data + * - the netfs data from the cookie being used as the target is + * presented, as is the auxilliary data + */ +static fscache_checkaux_t nfs_fh_check_aux(void *cookie_netfs_data, + const void *data, uint16_t datalen) +{ + struct nfs_fh_auxdata auxdata; + struct nfs_inode *nfsi = cookie_netfs_data; + + if (datalen > sizeof(auxdata)) + return FSCACHE_CHECKAUX_OBSOLETE; + + auxdata.i_size = nfsi->vfs_inode.i_size; + auxdata.i_mtime = nfsi->vfs_inode.i_mtime; + auxdata.i_ctime = nfsi->vfs_inode.i_ctime; + + if (memcmp(data, &auxdata, datalen) != 0) + return FSCACHE_CHECKAUX_OBSOLETE; + + return FSCACHE_CHECKAUX_OKAY; +} + +/* + * the primary index for each server is simply made up of a series of NFS file + * handles + */ +struct fscache_cookie_def nfs_cache_fh_index_def = { + .name = "NFS.fh", + .type = FSCACHE_COOKIE_TYPE_DATAFILE, + .get_key = nfs_fh_get_key, + .get_attr = nfs_fh_get_attr, + .get_aux = nfs_fh_get_aux, + .check_aux = nfs_fh_check_aux, + .get_context = nfs_fh_get_context, + .put_context = nfs_fh_put_context, + .mark_pages_cached = nfs_fh_mark_pages_cached, + .now_uncached = nfs_fh_now_uncached, +}; + +static int nfs_file_page_mkwrite(struct vm_area_struct *vma, struct page *page) +{ + wait_on_page_fs_misc(page); + return 0; +} + +struct vm_operations_struct nfs_fs_vm_operations = { + .nopage = filemap_nopage, + .populate = filemap_populate, + .page_mkwrite = nfs_file_page_mkwrite, +}; + +/* + * handle completion of a page being stored in the cache + */ +void nfs_readpage_to_fscache_complete(struct page *page, void *data, int error) +{ + dfprintk(FSCACHE, + "NFS: readpage_to_fscache_complete (p:%p(i:%lx f:%lx)/%d)\n", + page, page->index, page->flags, error); + + end_page_fs_misc(page); +} + +/* + * handle completion of a page being read from the cache + * - called in process (keventd) context + */ +void nfs_readpage_from_fscache_complete(struct page *page, + void *context, + int error) +{ + dfprintk(FSCACHE, + "NFS: readpage_from_fscache_complete (0x%p/0x%p/%d)\n", + page, context, error); + + /* if the read completes with an error, we just unlock the page and let + * the VM reissue the readpage */ + if (!error) { + SetPageUptodate(page); + unlock_page(page); + } else { + error = nfs_readpage_async(context, page->mapping->host, page); + if (error) + unlock_page(page); + } +} + +/* + * handle completion of a page being read from the cache + * - really need to synchronise the end of writeback, probably using a page + * flag, but for the moment we disable caching on writable files + */ +void nfs_writepage_to_fscache_complete(struct page *page, + void *data, + int error) +{ +} diff --git a/fs/nfs/fscache.h b/fs/nfs/fscache.h new file mode 100644 index 000000000..69f0f4041 --- /dev/null +++ b/fs/nfs/fscache.h @@ -0,0 +1,466 @@ +/* fscache.h: NFS filesystem cache interface definitions + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _NFS_FSCACHE_H +#define _NFS_FSCACHE_H + +#include <linux/nfs_fs.h> +#include <linux/nfs_mount.h> +#include <linux/nfs4_mount.h> + +#ifdef CONFIG_NFS_FSCACHE +#include <linux/fscache.h> + +extern struct fscache_netfs nfs_cache_netfs; +extern struct fscache_cookie_def nfs_cache_server_index_def; +extern struct fscache_cookie_def nfs_cache_fh_index_def; +extern struct vm_operations_struct nfs_fs_vm_operations; + +extern void nfs_invalidatepage(struct page *, unsigned long); +extern int nfs_releasepage(struct page *, gfp_t); + +extern atomic_t nfs_fscache_to_pages; +extern atomic_t nfs_fscache_from_pages; +extern atomic_t nfs_fscache_uncache_page; +extern int nfs_fscache_from_error; +extern int nfs_fscache_to_error; + +/* + * register NFS for caching + */ +static inline int nfs_fscache_register(void) +{ + return fscache_register_netfs(&nfs_cache_netfs); +} + +/* + * unregister NFS for caching + */ +static inline void nfs_fscache_unregister(void) +{ + fscache_unregister_netfs(&nfs_cache_netfs); +} + +/* + * get the per-client index cookie for an NFS client if the appropriate mount + * flag was set + * - we always try and get an index cookie for the client, but get filehandle + * cookies on a per-superblock basis, depending on the mount flags + */ +static inline void nfs_fscache_get_client_cookie(struct nfs_client *clp) +{ + /* create a cache index for looking up filehandles */ + clp->fscache = fscache_acquire_cookie(nfs_cache_netfs.primary_index, + &nfs_cache_server_index_def, + clp); + dfprintk(FSCACHE,"NFS: get client cookie (0x%p/0x%p)\n", + clp, clp->fscache); +} + +/* + * dispose of a per-client cookie + */ +static inline void nfs_fscache_release_client_cookie(struct nfs_client *clp) +{ + dfprintk(FSCACHE,"NFS: releasing client cookie (0x%p/0x%p)\n", + clp, clp->fscache); + + fscache_relinquish_cookie(clp->fscache, 0); + clp->fscache = NULL; +} + +/* + * indicate the client caching state as readable text + */ +static inline const char *nfs_server_fscache_state(struct nfs_server *server) +{ + if (server->nfs_client->fscache && (server->flags & NFS_MOUNT_FSCACHE)) + return "yes"; + return "no "; +} + +/* + * get the per-filehandle cookie for an NFS inode + */ +static inline void nfs_fscache_get_fh_cookie(struct super_block *sb, + struct nfs_inode *nfsi, + int maycache) +{ + nfsi->fscache = NULL; + if (maycache && (NFS_SB(sb)->flags & NFS_MOUNT_FSCACHE)) { + nfsi->fscache = fscache_acquire_cookie( + NFS_SB(sb)->nfs_client->fscache, + &nfs_cache_fh_index_def, + nfsi); + + fscache_set_i_size(nfsi->fscache, nfsi->vfs_inode.i_size); + + dfprintk(FSCACHE, "NFS: get FH cookie (0x%p/0x%p/0x%p)\n", + sb, nfsi, nfsi->fscache); + } +} + +/* + * change the filesize associated with a per-filehandle cookie + */ +static inline void nfs_fscache_set_size(struct nfs_server *server, + struct nfs_inode *nfsi, + loff_t i_size) +{ + fscache_set_i_size(nfsi->fscache, i_size); +} + +/* + * replace a per-filehandle cookie due to revalidation detecting a file having + * changed on the server + */ +static inline void nfs_fscache_renew_fh_cookie(struct nfs_server *server, + struct nfs_inode *nfsi) +{ + struct fscache_cookie *old = nfsi->fscache; + + if (nfsi->fscache) { + /* retire the current fscache cache and get a new one */ + fscache_relinquish_cookie(nfsi->fscache, 1); + + nfsi->fscache = fscache_acquire_cookie( + server->nfs_client->fscache, + &nfs_cache_fh_index_def, + nfsi); + fscache_set_i_size(nfsi->fscache, nfsi->vfs_inode.i_size); + + dfprintk(FSCACHE, + "NFS: revalidation new cookie (0x%p/0x%p/0x%p/0x%p)\n", + server, nfsi, old, nfsi->fscache); + } +} + +/* + * release a per-filehandle cookie + */ +static inline void nfs_fscache_release_fh_cookie(struct nfs_server *server, + struct nfs_inode *nfsi) +{ + dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", + nfsi, nfsi->fscache); + + fscache_relinquish_cookie(nfsi->fscache, 0); + nfsi->fscache = NULL; +} + +/* + * retire a per-filehandle cookie, destroying the data attached to it + */ +static inline void nfs_fscache_zap_fh_cookie(struct nfs_server *server, + struct nfs_inode *nfsi) +{ + dfprintk(FSCACHE,"NFS: zapping cookie (0x%p/0x%p)\n", + nfsi, nfsi->fscache); + + fscache_relinquish_cookie(nfsi->fscache, 1); + nfsi->fscache = NULL; +} + +/* + * turn off the cache with regard to a filehandle cookie if opened for writing, + * invalidating all the pages in the page cache relating to the associated + * inode to clear the per-page caching + */ +static inline void nfs_fscache_disable_fh_cookie(struct inode *inode) +{ + if (NFS_I(inode)->fscache) { + dfprintk(FSCACHE, + "NFS: nfsi 0x%p turning cache off\n", NFS_I(inode)); + + /* Need to invalided any mapped pages that were read in before + * turning off the cache. + */ + if (inode->i_mapping && inode->i_mapping->nrpages) + invalidate_inode_pages2(inode->i_mapping); + + nfs_fscache_zap_fh_cookie(NFS_SERVER(inode), NFS_I(inode)); + } +} + +/* + * install the VM ops for mmap() of an NFS file so that we can hold up writes + * to pages on shared writable mappings until the store to the cache is + * complete + */ +static inline void nfs_fscache_install_vm_ops(struct inode *inode, + struct vm_area_struct *vma) +{ + if (NFS_I(inode)->fscache) + vma->vm_ops = &nfs_fs_vm_operations; +} + +/* + * release the caching state associated with a page + */ +static void nfs_fscache_release_page(struct page *page) +{ + if (PageNfsCached(page)) { + struct nfs_inode *nfsi = NFS_I(page->mapping->host); + + BUG_ON(nfsi->fscache == NULL); + + dfprintk(FSCACHE, "NFS: fscache releasepage (0x%p/0x%p/0x%p)\n", + nfsi->fscache, page, nfsi); + + wait_on_page_fs_misc(page); + fscache_uncache_page(nfsi->fscache, page); + atomic_inc(&nfs_fscache_uncache_page); + ClearPageNfsCached(page); + } +} + +/* + * release the caching state associated with a page if undergoing complete page + * invalidation + */ +static inline void nfs_fscache_invalidate_page(struct page *page, + struct inode *inode, + unsigned long offset) +{ + if (PageNfsCached(page)) { + struct nfs_inode *nfsi = NFS_I(page->mapping->host); + + BUG_ON(!nfsi->fscache); + + dfprintk(FSCACHE, + "NFS: fscache invalidatepage (0x%p/0x%p/0x%p)\n", + nfsi->fscache, page, nfsi); + + if (offset == 0) { + BUG_ON(!PageLocked(page)); + if (!PageWriteback(page)) + nfs_fscache_release_page(page); + } + } +} + +/* + * store a newly fetched page in fscache + */ +extern void nfs_readpage_to_fscache_complete(struct page *, void *, int); + +static inline void nfs_readpage_to_fscache(struct inode *inode, + struct page *page, + int sync) +{ + int ret; + + if (PageNfsCached(page)) { + dfprintk(FSCACHE, + "NFS: " + "readpage_to_fscache(fsc:%p/p:%p(i:%lx f:%lx)/%d)\n", + NFS_I(inode)->fscache, page, page->index, page->flags, + sync); + + if (TestSetPageFsMisc(page)) + BUG(); + + ret = fscache_write_page(NFS_I(inode)->fscache, page, + nfs_readpage_to_fscache_complete, + NULL, GFP_KERNEL); + dfprintk(FSCACHE, + "NFS: " + "readpage_to_fscache: p:%p(i:%lu f:%lx) ret %d\n", + page, page->index, page->flags, ret); + + if (ret != 0) { + fscache_uncache_page(NFS_I(inode)->fscache, page); + atomic_inc(&nfs_fscache_uncache_page); + ClearPageNfsCached(page); + end_page_fs_misc(page); + nfs_fscache_to_error = ret; + } else { + atomic_inc(&nfs_fscache_to_pages); + } + } +} + +/* + * retrieve a page from fscache + */ +extern void nfs_readpage_from_fscache_complete(struct page *, void *, int); + +static inline +int nfs_readpage_from_fscache(struct nfs_open_context *ctx, + struct inode *inode, + struct page *page) +{ + int ret; + + if (!NFS_I(inode)->fscache) + return 1; + + dfprintk(FSCACHE, + "NFS: readpage_from_fscache(fsc:%p/p:%p(i:%lx f:%lx)/0x%p)\n", + NFS_I(inode)->fscache, page, page->index, page->flags, inode); + + ret = fscache_read_or_alloc_page(NFS_I(inode)->fscache, + page, + nfs_readpage_from_fscache_complete, + ctx, + GFP_KERNEL); + + switch (ret) { + case 0: /* read BIO submitted (page in fscache) */ + dfprintk(FSCACHE, + "NFS: readpage_from_fscache: BIO submitted\n"); + atomic_inc(&nfs_fscache_from_pages); + return ret; + + case -ENOBUFS: /* inode not in cache */ + case -ENODATA: /* page not in cache */ + dfprintk(FSCACHE, + "NFS: readpage_from_fscache error %d\n", ret); + return 1; + + default: + dfprintk(FSCACHE, "NFS: readpage_from_fscache %d\n", ret); + nfs_fscache_from_error = ret; + } + return ret; +} + +/* + * retrieve a set of pages from fscache + */ +static inline int nfs_readpages_from_fscache(struct nfs_open_context *ctx, + struct inode *inode, + struct address_space *mapping, + struct list_head *pages, + unsigned *nr_pages) +{ + int ret, npages = *nr_pages; + + if (!NFS_I(inode)->fscache) + return 1; + + dfprintk(FSCACHE, + "NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n", + NFS_I(inode)->fscache, *nr_pages, inode); + + ret = fscache_read_or_alloc_pages(NFS_I(inode)->fscache, + mapping, pages, nr_pages, + nfs_readpage_from_fscache_complete, + ctx, + mapping_gfp_mask(mapping)); + + + switch (ret) { + case 0: /* read BIO submitted (page in fscache) */ + BUG_ON(!list_empty(pages)); + BUG_ON(*nr_pages != 0); + dfprintk(FSCACHE, + "NFS: nfs_getpages_from_fscache: BIO submitted\n"); + + atomic_add(npages, &nfs_fscache_from_pages); + return ret; + + case -ENOBUFS: /* inode not in cache */ + case -ENODATA: /* page not in cache */ + dfprintk(FSCACHE, + "NFS: nfs_getpages_from_fscache: no page: %d\n", ret); + return 1; + + default: + dfprintk(FSCACHE, + "NFS: nfs_getpages_from_fscache: ret %d\n", ret); + nfs_fscache_from_error = ret; + } + + return ret; +} + +/* + * store an updated page in fscache + */ +extern void nfs_writepage_to_fscache_complete(struct page *page, void *data, int error); + +static inline void nfs_writepage_to_fscache(struct inode *inode, + struct page *page) +{ + int error; + + if (PageNfsCached(page) && NFS_I(inode)->fscache) { + dfprintk(FSCACHE, + "NFS: writepage_to_fscache (0x%p/0x%p/0x%p)\n", + NFS_I(inode)->fscache, page, inode); + + error = fscache_write_page(NFS_I(inode)->fscache, page, + nfs_writepage_to_fscache_complete, + NULL, GFP_KERNEL); + if (error != 0) { + dfprintk(FSCACHE, + "NFS: fscache_write_page error %d\n", + error); + fscache_uncache_page(NFS_I(inode)->fscache, page); + } + } +} + +#else /* CONFIG_NFS_FSCACHE */ +static inline int nfs_fscache_register(void) { return 0; } +static inline void nfs_fscache_unregister(void) {} +static inline void nfs_fscache_get_client_cookie(struct nfs_client *clp) {} +static inline void nfs4_fscache_get_client_cookie(struct nfs_client *clp) {} +static inline void nfs_fscache_release_client_cookie(struct nfs_client *clp) {} +static inline const char *nfs_server_fscache_state(struct nfs_server *server) { return "no "; } + +static inline void nfs_fscache_get_fh_cookie(struct super_block *sb, + struct nfs_inode *nfsi, + int maycache) +{ +} +static inline void nfs_fscache_set_size(struct nfs_server *server, + struct nfs_inode *nfsi, + loff_t i_size) +{ +} +static inline void nfs_fscache_release_fh_cookie(struct nfs_server *server, + struct nfs_inode *nfsi) +{ +} +static inline void nfs_fscache_zap_fh_cookie(struct nfs_server *server, struct nfs_inode *nfsi) {} +static inline void nfs_fscache_renew_fh_cookie(struct nfs_server *server, struct nfs_inode *nfsi) {} +static inline void nfs_fscache_disable_fh_cookie(struct inode *inode) {} +static inline void nfs_fscache_install_vm_ops(struct inode *inode, struct vm_area_struct *vma) {} +static inline void nfs_fscache_release_page(struct page *page) {} +static inline void nfs_fscache_invalidate_page(struct page *page, + struct inode *inode, + unsigned long offset) +{ +} +static inline void nfs_readpage_to_fscache(struct inode *inode, struct page *page, int sync) {} +static inline int nfs_readpage_from_fscache(struct nfs_open_context *ctx, + struct inode *inode, struct page *page) +{ + return -ENOBUFS; +} +static inline int nfs_readpages_from_fscache(struct nfs_open_context *ctx, + struct inode *inode, + struct address_space *mapping, + struct list_head *pages, + unsigned *nr_pages) +{ + return -ENOBUFS; +} + +static inline void nfs_writepage_to_fscache(struct inode *inode, struct page *page) +{ + BUG_ON(PageNfsCached(page)); +} + +#endif /* CONFIG_NFS_FSCACHE */ +#endif /* _NFS_FSCACHE_H */ diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c new file mode 100644 index 000000000..20c6f39ea --- /dev/null +++ b/fs/nfs/getroot.c @@ -0,0 +1,310 @@ +/* getroot.c: get the root dentry for an NFS mount + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/module.h> +#include <linux/init.h> + +#include <linux/time.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/string.h> +#include <linux/stat.h> +#include <linux/errno.h> +#include <linux/unistd.h> +#include <linux/sunrpc/clnt.h> +#include <linux/sunrpc/stats.h> +#include <linux/nfs_fs.h> +#include <linux/nfs_mount.h> +#include <linux/nfs4_mount.h> +#include <linux/lockd/bind.h> +#include <linux/smp_lock.h> +#include <linux/seq_file.h> +#include <linux/mount.h> +#include <linux/nfs_idmap.h> +#include <linux/vfs.h> +#include <linux/namei.h> +#include <linux/namespace.h> +#include <linux/security.h> + +#include <asm/system.h> +#include <asm/uaccess.h> + +#include "nfs4_fs.h" +#include "delegation.h" +#include "internal.h" + +#define NFSDBG_FACILITY NFSDBG_CLIENT +#define NFS_PARANOIA 1 + +/* + * get an NFS2/NFS3 root dentry from the root filehandle + */ +struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) +{ + struct nfs_server *server = NFS_SB(sb); + struct nfs_fsinfo fsinfo; + struct nfs_fattr fattr; + struct dentry *mntroot; + struct inode *inode; + int error; + + /* create a dummy root dentry with dummy inode for this superblock */ + if (!sb->s_root) { + struct nfs_fh dummyfh; + struct dentry *root; + struct inode *iroot; + + memset(&dummyfh, 0, sizeof(dummyfh)); + memset(&fattr, 0, sizeof(fattr)); + nfs_fattr_init(&fattr); + fattr.valid = NFS_ATTR_FATTR; + fattr.type = NFDIR; + fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR; + fattr.nlink = 2; + + iroot = nfs_fhget(sb, &dummyfh, &fattr); + if (IS_ERR(iroot)) + return ERR_PTR(PTR_ERR(iroot)); + + root = d_alloc_root(iroot); + if (!root) { + iput(iroot); + return ERR_PTR(-ENOMEM); + } + + sb->s_root = root; + } + + /* get the actual root for this mount */ + fsinfo.fattr = &fattr; + + error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); + if (error < 0) { + dprintk("nfs_get_root: getattr error = %d\n", -error); + return ERR_PTR(error); + } + + inode = nfs_fhget(sb, mntfh, fsinfo.fattr); + if (IS_ERR(inode)) { + dprintk("nfs_get_root: get root inode failed\n"); + return ERR_PTR(PTR_ERR(inode)); + } + + /* root dentries normally start off anonymous and get spliced in later + * if the dentry tree reaches them; however if the dentry already + * exists, we'll pick it up at this point and use it as the root + */ + mntroot = d_alloc_anon(inode); + if (!mntroot) { + iput(inode); + dprintk("nfs_get_root: get root dentry failed\n"); + return ERR_PTR(-ENOMEM); + } + + security_d_instantiate(mntroot, inode); + + if (!mntroot->d_op) + mntroot->d_op = server->nfs_client->rpc_ops->dentry_ops; + + return mntroot; +} + +#ifdef CONFIG_NFS_V4 + +/* + * Do a simple pathwalk from the root FH of the server to the nominated target + * of the mountpoint + * - give error on symlinks + * - give error on ".." occurring in the path + * - follow traversals + */ +int nfs4_path_walk(struct nfs_server *server, + struct nfs_fh *mntfh, + const char *path) +{ + struct nfs_fsinfo fsinfo; + struct nfs_fattr fattr; + struct nfs_fh lastfh; + struct qstr name; + int ret; + //int referral_count = 0; + + dprintk("--> nfs4_path_walk(,,%s)\n", path); + + fsinfo.fattr = &fattr; + nfs_fattr_init(&fattr); + + if (*path++ != '/') { + dprintk("nfs4_get_root: Path does not begin with a slash\n"); + return -EINVAL; + } + + /* Start by getting the root filehandle from the server */ + ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); + if (ret < 0) { + dprintk("nfs4_get_root: getroot error = %d\n", -ret); + return ret; + } + + if (fattr.type != NFDIR) { + printk(KERN_ERR "nfs4_get_root:" + " getroot encountered non-directory\n"); + return -ENOTDIR; + } + + if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) { + printk(KERN_ERR "nfs4_get_root:" + " getroot obtained referral\n"); + return -EREMOTE; + } + +next_component: + dprintk("Next: %s\n", path); + + /* extract the next bit of the path */ + if (!*path) + goto path_walk_complete; + + name.name = path; + while (*path && *path != '/') + path++; + name.len = path - (const char *) name.name; + +eat_dot_dir: + while (*path == '/') + path++; + + if (path[0] == '.' && (path[1] == '/' || !path[1])) { + path += 2; + goto eat_dot_dir; + } + + if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || !path[2]) + ) { + printk(KERN_ERR "nfs4_get_root:" + " Mount path contains reference to \"..\"\n"); + return -EINVAL; + } + + /* lookup the next FH in the sequence */ + memcpy(&lastfh, mntfh, sizeof(lastfh)); + + dprintk("LookupFH: %*.*s [%s]\n", name.len, name.len, name.name, path); + + ret = server->nfs_client->rpc_ops->lookupfh(server, &lastfh, &name, + mntfh, &fattr); + if (ret < 0) { + dprintk("nfs4_get_root: getroot error = %d\n", -ret); + return ret; + } + + if (fattr.type != NFDIR) { + printk(KERN_ERR "nfs4_get_root:" + " lookupfh encountered non-directory\n"); + return -ENOTDIR; + } + + if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) { + printk(KERN_ERR "nfs4_get_root:" + " lookupfh obtained referral\n"); + return -EREMOTE; + } + + goto next_component; + +path_walk_complete: + memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid)); + dprintk("<-- nfs4_path_walk() = 0\n"); + return 0; +} + +/* + * get an NFS4 root dentry from the root filehandle + */ +struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) +{ + struct nfs_server *server = NFS_SB(sb); + struct nfs_fattr fattr; + struct dentry *mntroot; + struct inode *inode; + int error; + + dprintk("--> nfs4_get_root()\n"); + + /* create a dummy root dentry with dummy inode for this superblock */ + if (!sb->s_root) { + struct nfs_fh dummyfh; + struct dentry *root; + struct inode *iroot; + + memset(&dummyfh, 0, sizeof(dummyfh)); + memset(&fattr, 0, sizeof(fattr)); + nfs_fattr_init(&fattr); + fattr.valid = NFS_ATTR_FATTR; + fattr.type = NFDIR; + fattr.mode = S_IFDIR | S_IRUSR | S_IWUSR; + fattr.nlink = 2; + + iroot = nfs_fhget(sb, &dummyfh, &fattr); + if (IS_ERR(iroot)) + return ERR_PTR(PTR_ERR(iroot)); + + root = d_alloc_root(iroot); + if (!root) { + iput(iroot); + return ERR_PTR(-ENOMEM); + } + + sb->s_root = root; + } + + /* get the info about the server and filesystem */ + error = nfs4_server_capabilities(server, mntfh); + if (error < 0) { + dprintk("nfs_get_root: getcaps error = %d\n", + -error); + return ERR_PTR(error); + } + + /* get the actual root for this mount */ + error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr); + if (error < 0) { + dprintk("nfs_get_root: getattr error = %d\n", -error); + return ERR_PTR(error); + } + + inode = nfs_fhget(sb, mntfh, &fattr); + if (IS_ERR(inode)) { + dprintk("nfs_get_root: get root inode failed\n"); + return ERR_PTR(PTR_ERR(inode)); + } + + /* root dentries normally start off anonymous and get spliced in later + * if the dentry tree reaches them; however if the dentry already + * exists, we'll pick it up at this point and use it as the root + */ + mntroot = d_alloc_anon(inode); + if (!mntroot) { + iput(inode); + dprintk("nfs_get_root: get root dentry failed\n"); + return ERR_PTR(-ENOMEM); + } + + security_d_instantiate(mntroot, inode); + + if (!mntroot->d_op) + mntroot->d_op = server->nfs_client->rpc_ops->dentry_ops; + + dprintk("<-- nfs4_get_root()\n"); + return mntroot; +} + +#endif /* CONFIG_NFS_V4 */ diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h new file mode 100644 index 000000000..18febb4c2 --- /dev/null +++ b/fs/nfs/internal.h @@ -0,0 +1,248 @@ +/* + * NFS internal definitions + */ + +#include <linux/mount.h> + +#define NFS_PAGE_WRITING 0 +#define NFS_PAGE_CACHED 1 + +#define PageNfsBit(bit, page) test_bit(bit, &(page)->private) + +#define SetPageNfsBit(bit, page) \ +do { \ + SetPagePrivate((page)); \ + set_bit(bit, &(page)->private); \ +} while(0) + +#define ClearPageNfsBit(bit, page) \ +do { \ + clear_bit(bit, &(page)->private); \ +} while(0) + +#define PageNfsWriting(page) PageNfsBit(NFS_PAGE_WRITING, (page)) +#define SetPageNfsWriting(page) SetPageNfsBit(NFS_PAGE_WRITING, (page)) +#define ClearPageNfsWriting(page) ClearPageNfsBit(NFS_PAGE_WRITING, (page)) + +#define PageNfsCached(page) PageNfsBit(NFS_PAGE_CACHED, (page)) +#define SetPageNfsCached(page) SetPageNfsBit(NFS_PAGE_CACHED, (page)) +#define ClearPageNfsCached(page) ClearPageNfsBit(NFS_PAGE_CACHED, (page)) + +struct nfs_string; +struct nfs_mount_data; +struct nfs4_mount_data; + +/* Maximum number of readahead requests + * FIXME: this should really be a sysctl so that users may tune it to suit + * their needs. People that do NFS over a slow network, might for + * instance want to reduce it to something closer to 1 for improved + * interactive response. + */ +#define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) + +struct nfs_clone_mount { + const struct super_block *sb; + const struct dentry *dentry; + struct nfs_fh *fh; + struct nfs_fattr *fattr; + char *hostname; + char *mnt_path; + struct sockaddr_in *addr; + rpc_authflavor_t authflavor; +}; + +/* + * include filesystem caching stuff here + */ +#include "fscache.h" + +/* client.c */ +extern struct rpc_program nfs_program; + +extern void nfs_put_client(struct nfs_client *); +extern struct nfs_client *nfs_find_client(const struct sockaddr_in *, int); +extern struct nfs_server *nfs_create_server(const struct nfs_mount_data *, + struct nfs_fh *); +extern struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *, + const char *, + const struct sockaddr_in *, + const char *, + const char *, + rpc_authflavor_t, + struct nfs_fh *); +extern struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *, + struct nfs_fh *); +extern void nfs_free_server(struct nfs_server *server); +extern struct nfs_server *nfs_clone_server(struct nfs_server *, + struct nfs_fh *, + struct nfs_fattr *); +#ifdef CONFIG_PROC_FS +extern int __init nfs_fs_proc_init(void); +extern void nfs_fs_proc_exit(void); +#else +static inline int nfs_fs_proc_init(void) +{ + return 0; +} +static inline void nfs_fs_proc_exit(void) +{ +} +#endif + +/* nfs4namespace.c */ +#ifdef CONFIG_NFS_V4 +extern struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry); +#else +static inline +struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry) +{ + return ERR_PTR(-ENOENT); +} +#endif + +/* callback_xdr.c */ +extern struct svc_version nfs4_callback_version1; + +/* pagelist.c */ +extern int __init nfs_init_nfspagecache(void); +extern void nfs_destroy_nfspagecache(void); +extern int __init nfs_init_readpagecache(void); +extern void nfs_destroy_readpagecache(void); +extern int __init nfs_init_writepagecache(void); +extern void nfs_destroy_writepagecache(void); + +#ifdef CONFIG_NFS_DIRECTIO +extern int __init nfs_init_directcache(void); +extern void nfs_destroy_directcache(void); +#else +#define nfs_init_directcache() (0) +#define nfs_destroy_directcache() do {} while(0) +#endif + +/* nfs2xdr.c */ +extern int nfs_stat_to_errno(int); +extern struct rpc_procinfo nfs_procedures[]; +extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int); + +/* nfs3xdr.c */ +extern struct rpc_procinfo nfs3_procedures[]; +extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int); + +/* nfs4xdr.c */ +#ifdef CONFIG_NFS_V4 +extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus); +#endif + +/* nfs4proc.c */ +#ifdef CONFIG_NFS_V4 +extern struct rpc_procinfo nfs4_procedures[]; + +extern int nfs4_proc_fs_locations(struct inode *dir, struct dentry *dentry, + struct nfs4_fs_locations *fs_locations, + struct page *page); +#endif + +/* inode.c */ +extern struct inode *nfs_alloc_inode(struct super_block *sb); +extern void nfs_destroy_inode(struct inode *); +extern int nfs_write_inode(struct inode *,int); +extern void nfs_clear_inode(struct inode *); +#ifdef CONFIG_NFS_V4 +extern void nfs4_clear_inode(struct inode *); +#endif + +/* super.c */ +extern struct file_system_type nfs_xdev_fs_type; +#ifdef CONFIG_NFS_V4 +extern struct file_system_type nfs4_xdev_fs_type; +extern struct file_system_type nfs4_referral_fs_type; +#endif + +extern struct rpc_stat nfs_rpcstat; + +extern int __init register_nfs_fs(void); +extern void __exit unregister_nfs_fs(void); + +/* namespace.c */ +extern char *nfs_path(const char *base, + const struct dentry *droot, + const struct dentry *dentry, + char *buffer, ssize_t buflen); + +/* getroot.c */ +extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *); +#ifdef CONFIG_NFS_V4 +extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *); + +extern int nfs4_path_walk(struct nfs_server *server, + struct nfs_fh *mntfh, + const char *path); +#endif + +/* read.c */ +extern int nfs_readpage_async(struct nfs_open_context *, struct inode *, struct page *); + +/* + * Determine the device name as a string + */ +static inline char *nfs_devname(const struct vfsmount *mnt_parent, + const struct dentry *dentry, + char *buffer, ssize_t buflen) +{ + return nfs_path(mnt_parent->mnt_devname, mnt_parent->mnt_root, + dentry, buffer, buflen); +} + +/* + * Determine the actual block size (and log2 thereof) + */ +static inline +unsigned long nfs_block_bits(unsigned long bsize, unsigned char *nrbitsp) +{ + /* make sure blocksize is a power of two */ + if ((bsize & (bsize - 1)) || nrbitsp) { + unsigned char nrbits; + + for (nrbits = 31; nrbits && !(bsize & (1 << nrbits)); nrbits--) + ; + bsize = 1 << nrbits; + if (nrbitsp) + *nrbitsp = nrbits; + } + + return bsize; +} + +/* + * Calculate the number of 512byte blocks used. + */ +static inline unsigned long nfs_calc_block_size(u64 tsize) +{ + loff_t used = (tsize + 511) >> 9; + return (used > ULONG_MAX) ? ULONG_MAX : used; +} + +/* + * Compute and set NFS server blocksize + */ +static inline +unsigned long nfs_block_size(unsigned long bsize, unsigned char *nrbitsp) +{ + if (bsize < NFS_MIN_FILE_IO_SIZE) + bsize = NFS_DEF_FILE_IO_SIZE; + else if (bsize >= NFS_MAX_FILE_IO_SIZE) + bsize = NFS_MAX_FILE_IO_SIZE; + + return nfs_block_bits(bsize, nrbitsp); +} + +/* + * Determine the maximum file size for a superblock + */ +static inline +void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize) +{ + sb->s_maxbytes = (loff_t)maxfilesize; + if (sb->s_maxbytes > MAX_LFS_FILESIZE || sb->s_maxbytes <= 0) + sb->s_maxbytes = MAX_LFS_FILESIZE; +} diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c new file mode 100644 index 000000000..f4763c181 --- /dev/null +++ b/fs/nfs/namespace.c @@ -0,0 +1,243 @@ +/* + * linux/fs/nfs/namespace.c + * + * Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com> + * - Modified by David Howells <dhowells@redhat.com> + * + * NFS namespace + */ + +#include <linux/dcache.h> +#include <linux/mount.h> +#include <linux/namei.h> +#include <linux/nfs_fs.h> +#include <linux/string.h> +#include <linux/sunrpc/clnt.h> +#include <linux/vfs.h> +#include "internal.h" + +#define NFSDBG_FACILITY NFSDBG_VFS + +static void nfs_expire_automounts(void *list); + +LIST_HEAD(nfs_automount_list); +static DECLARE_WORK(nfs_automount_task, nfs_expire_automounts, &nfs_automount_list); +int nfs_mountpoint_expiry_timeout = 500 * HZ; + +/* + * nfs_path - reconstruct the path given an arbitrary dentry + * @base - arbitrary string to prepend to the path + * @droot - pointer to root dentry for mountpoint + * @dentry - pointer to dentry + * @buffer - result buffer + * @buflen - length of buffer + * + * Helper function for constructing the path from the + * root dentry to an arbitrary hashed dentry. + * + * This is mainly for use in figuring out the path on the + * server side when automounting on top of an existing partition. + */ +char *nfs_path(const char *base, + const struct dentry *droot, + const struct dentry *dentry, + char *buffer, ssize_t buflen) +{ + char *end = buffer+buflen; + int namelen; + + *--end = '\0'; + buflen--; + spin_lock(&dcache_lock); + while (!IS_ROOT(dentry) && dentry != droot) { + namelen = dentry->d_name.len; + buflen -= namelen + 1; + if (buflen < 0) + goto Elong_unlock; + end -= namelen; + memcpy(end, dentry->d_name.name, namelen); + *--end = '/'; + dentry = dentry->d_parent; + } + spin_unlock(&dcache_lock); + namelen = strlen(base); + /* Strip off excess slashes in base string */ + while (namelen > 0 && base[namelen - 1] == '/') + namelen--; + buflen -= namelen; + if (buflen < 0) + goto Elong; + end -= namelen; + memcpy(end, base, namelen); + return end; +Elong_unlock: + spin_unlock(&dcache_lock); +Elong: + return ERR_PTR(-ENAMETOOLONG); +} + +/* + * nfs_follow_mountpoint - handle crossing a mountpoint on the server + * @dentry - dentry of mountpoint + * @nd - nameidata info + * + * When we encounter a mountpoint on the server, we want to set up + * a mountpoint on the client too, to prevent inode numbers from + * colliding, and to allow "df" to work properly. + * On NFSv4, we also want to allow for the fact that different + * filesystems may be migrated to different servers in a failover + * situation, and that different filesystems may want to use + * different security flavours. + */ +static void * nfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) +{ + struct vfsmount *mnt; + struct nfs_server *server = NFS_SERVER(dentry->d_inode); + struct dentry *parent; + struct nfs_fh fh; + struct nfs_fattr fattr; + int err; + + dprintk("--> nfs_follow_mountpoint()\n"); + + BUG_ON(IS_ROOT(dentry)); + dprintk("%s: enter\n", __FUNCTION__); + dput(nd->dentry); + nd->dentry = dget(dentry); + + /* Look it up again */ + parent = dget_parent(nd->dentry); + err = server->nfs_client->rpc_ops->lookup(parent->d_inode, + &nd->dentry->d_name, + &fh, &fattr); + dput(parent); + if (err != 0) + goto out_err; + + if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) + mnt = nfs_do_refmount(nd->mnt, nd->dentry); + else + mnt = nfs_do_submount(nd->mnt, nd->dentry, &fh, &fattr); + err = PTR_ERR(mnt); + if (IS_ERR(mnt)) + goto out_err; + + mntget(mnt); + err = do_add_mount(mnt, nd, nd->mnt->mnt_flags|MNT_SHRINKABLE, &nfs_automount_list); + if (err < 0) { + mntput(mnt); + if (err == -EBUSY) + goto out_follow; + goto out_err; + } + mntput(nd->mnt); + dput(nd->dentry); + nd->mnt = mnt; + nd->dentry = dget(mnt->mnt_root); + schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout); +out: + dprintk("%s: done, returned %d\n", __FUNCTION__, err); + + dprintk("<-- nfs_follow_mountpoint() = %d\n", err); + return ERR_PTR(err); +out_err: + path_release(nd); + goto out; +out_follow: + while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) + ; + err = 0; + goto out; +} + +struct inode_operations nfs_mountpoint_inode_operations = { + .follow_link = nfs_follow_mountpoint, + .getattr = nfs_getattr, +}; + +struct inode_operations nfs_referral_inode_operations = { + .follow_link = nfs_follow_mountpoint, +}; + +static void nfs_expire_automounts(void *data) +{ + struct list_head *list = (struct list_head *)data; + + mark_mounts_for_expiry(list); + if (!list_empty(list)) + schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout); +} + +void nfs_release_automount_timer(void) +{ + if (list_empty(&nfs_automount_list)) { + cancel_delayed_work(&nfs_automount_task); + flush_scheduled_work(); + } +} + +/* + * Clone a mountpoint of the appropriate type + */ +static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server, + const char *devname, + struct nfs_clone_mount *mountdata) +{ +#ifdef CONFIG_NFS_V4 + struct vfsmount *mnt = NULL; + switch (server->nfs_client->cl_nfsversion) { + case 2: + case 3: + mnt = vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata); + break; + case 4: + mnt = vfs_kern_mount(&nfs4_xdev_fs_type, 0, devname, mountdata); + } + return mnt; +#else + return vfs_kern_mount(&nfs_xdev_fs_type, 0, devname, mountdata); +#endif +} + +/** + * nfs_do_submount - set up mountpoint when crossing a filesystem boundary + * @mnt_parent - mountpoint of parent directory + * @dentry - parent directory + * @fh - filehandle for new root dentry + * @fattr - attributes for new root inode + * + */ +struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent, + const struct dentry *dentry, struct nfs_fh *fh, + struct nfs_fattr *fattr) +{ + struct nfs_clone_mount mountdata = { + .sb = mnt_parent->mnt_sb, + .dentry = dentry, + .fh = fh, + .fattr = fattr, + }; + struct vfsmount *mnt = ERR_PTR(-ENOMEM); + char *page = (char *) __get_free_page(GFP_USER); + char *devname; + + dprintk("--> nfs_do_submount()\n"); + + dprintk("%s: submounting on %s/%s\n", __FUNCTION__, + dentry->d_parent->d_name.name, + dentry->d_name.name); + if (page == NULL) + goto out; + devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE); + mnt = (struct vfsmount *)devname; + if (IS_ERR(devname)) + goto free_page; + mnt = nfs_do_clone_mount(NFS_SB(mnt_parent->mnt_sb), devname, &mountdata); +free_page: + free_page((unsigned long)page); +out: + dprintk("%s: done\n", __FUNCTION__); + + dprintk("<-- nfs_do_submount() = %p\n", mnt); + return mnt; +} diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c new file mode 100644 index 000000000..b872779d7 --- /dev/null +++ b/fs/nfs/nfs4namespace.c @@ -0,0 +1,259 @@ +/* + * linux/fs/nfs/nfs4namespace.c + * + * Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com> + * - Modified by David Howells <dhowells@redhat.com> + * + * NFSv4 namespace + */ + +#include <linux/dcache.h> +#include <linux/mount.h> +#include <linux/namei.h> +#include <linux/nfs_fs.h> +#include <linux/string.h> +#include <linux/sunrpc/clnt.h> +#include <linux/vfs.h> +#include <linux/inet.h> +#include "internal.h" + +#define NFSDBG_FACILITY NFSDBG_VFS + +/* + * Check if fs_root is valid + */ +static inline char *nfs4_pathname_string(const struct nfs4_pathname *pathname, + char *buffer, ssize_t buflen) +{ + char *end = buffer + buflen; + int n; + + *--end = '\0'; + buflen--; + + n = pathname->ncomponents; + while (--n >= 0) { + const struct nfs4_string *component = &pathname->components[n]; + buflen -= component->len + 1; + if (buflen < 0) + goto Elong; + end -= component->len; + memcpy(end, component->data, component->len); + *--end = '/'; + } + return end; +Elong: + return ERR_PTR(-ENAMETOOLONG); +} + +/* + * Determine the mount path as a string + */ +static char *nfs4_path(const struct vfsmount *mnt_parent, + const struct dentry *dentry, + char *buffer, ssize_t buflen) +{ + const char *srvpath; + + srvpath = strchr(mnt_parent->mnt_devname, ':'); + if (srvpath) + srvpath++; + else + srvpath = mnt_parent->mnt_devname; + + return nfs_path(srvpath, mnt_parent->mnt_root, dentry, buffer, buflen); +} + +/* + * Check that fs_locations::fs_root [RFC3530 6.3] is a prefix for what we + * believe to be the server path to this dentry + */ +static int nfs4_validate_fspath(const struct vfsmount *mnt_parent, + const struct dentry *dentry, + const struct nfs4_fs_locations *locations, + char *page, char *page2) +{ + const char *path, *fs_path; + + path = nfs4_path(mnt_parent, dentry, page, PAGE_SIZE); + if (IS_ERR(path)) + return PTR_ERR(path); + + fs_path = nfs4_pathname_string(&locations->fs_path, page2, PAGE_SIZE); + if (IS_ERR(fs_path)) + return PTR_ERR(fs_path); + + if (strncmp(path, fs_path, strlen(fs_path)) != 0) { + dprintk("%s: path %s does not begin with fsroot %s\n", + __FUNCTION__, path, fs_path); + return -ENOENT; + } + + return 0; +} + +/* + * Check if the string represents a "valid" IPv4 address + */ +static inline int valid_ipaddr4(const char *buf) +{ + int rc, count, in[4]; + + rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]); + if (rc != 4) + return -EINVAL; + for (count = 0; count < 4; count++) { + if (in[count] > 255) + return -EINVAL; + } + return 0; +} + +/** + * nfs_follow_referral - set up mountpoint when hitting a referral on moved error + * @mnt_parent - mountpoint of parent directory + * @dentry - parent directory + * @fspath - fs path returned in fs_locations + * @mntpath - mount path to new server + * @hostname - hostname of new server + * @addr - host addr of new server + * + */ +static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, + const struct dentry *dentry, + const struct nfs4_fs_locations *locations) +{ + struct vfsmount *mnt = ERR_PTR(-ENOENT); + struct nfs_clone_mount mountdata = { + .sb = mnt_parent->mnt_sb, + .dentry = dentry, + .authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor, + }; + char *page = NULL, *page2 = NULL; + char *devname; + int loc, s, error; + + if (locations == NULL || locations->nlocations <= 0) + goto out; + + dprintk("%s: referral at %s/%s\n", __FUNCTION__, + dentry->d_parent->d_name.name, dentry->d_name.name); + + page = (char *) __get_free_page(GFP_USER); + if (!page) + goto out; + + page2 = (char *) __get_free_page(GFP_USER); + if (!page2) + goto out; + + /* Ensure fs path is a prefix of current dentry path */ + error = nfs4_validate_fspath(mnt_parent, dentry, locations, page, page2); + if (error < 0) { + mnt = ERR_PTR(error); + goto out; + } + + devname = nfs_devname(mnt_parent, dentry, page, PAGE_SIZE); + if (IS_ERR(devname)) { + mnt = (struct vfsmount *)devname; + goto out; + } + + loc = 0; + while (loc < locations->nlocations && IS_ERR(mnt)) { + const struct nfs4_fs_location *location = &locations->locations[loc]; + char *mnt_path; + + if (location == NULL || location->nservers <= 0 || + location->rootpath.ncomponents == 0) { + loc++; + continue; + } + + mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE); + if (IS_ERR(mnt_path)) { + loc++; + continue; + } + mountdata.mnt_path = mnt_path; + + s = 0; + while (s < location->nservers) { + struct sockaddr_in addr = {}; + + if (location->servers[s].len <= 0 || + valid_ipaddr4(location->servers[s].data) < 0) { + s++; + continue; + } + + mountdata.hostname = location->servers[s].data; + addr.sin_addr.s_addr = in_aton(mountdata.hostname); + addr.sin_family = AF_INET; + addr.sin_port = htons(NFS_PORT); + mountdata.addr = &addr; + + mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, devname, &mountdata); + if (!IS_ERR(mnt)) { + break; + } + s++; + } + loc++; + } + +out: + free_page((unsigned long) page); + free_page((unsigned long) page2); + dprintk("%s: done\n", __FUNCTION__); + return mnt; +} + +/* + * nfs_do_refmount - handle crossing a referral on server + * @dentry - dentry of referral + * @nd - nameidata info + * + */ +struct vfsmount *nfs_do_refmount(const struct vfsmount *mnt_parent, struct dentry *dentry) +{ + struct vfsmount *mnt = ERR_PTR(-ENOMEM); + struct dentry *parent; + struct nfs4_fs_locations *fs_locations = NULL; + struct page *page; + int err; + + /* BUG_ON(IS_ROOT(dentry)); */ + dprintk("%s: enter\n", __FUNCTION__); + + page = alloc_page(GFP_KERNEL); + if (page == NULL) + goto out; + + fs_locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL); + if (fs_locations == NULL) + goto out_free; + + /* Get locations */ + mnt = ERR_PTR(-ENOENT); + + parent = dget_parent(dentry); + dprintk("%s: getting locations for %s/%s\n", + __FUNCTION__, parent->d_name.name, dentry->d_name.name); + + err = nfs4_proc_fs_locations(parent->d_inode, dentry, fs_locations, page); + dput(parent); + if (err != 0 || + fs_locations->nlocations <= 0 || + fs_locations->fs_path.ncomponents <= 0) + goto out_free; + + mnt = nfs_follow_referral(mnt_parent, dentry, fs_locations); +out_free: + __free_page(page); + kfree(fs_locations); +out: + dprintk("%s: done\n", __FUNCTION__); + return mnt; +} diff --git a/fs/nfs/super.c b/fs/nfs/super.c new file mode 100644 index 000000000..62e627b47 --- /dev/null +++ b/fs/nfs/super.c @@ -0,0 +1,1068 @@ +/* + * linux/fs/nfs/super.c + * + * Copyright (C) 1992 Rick Sladkey + * + * nfs superblock handling functions + * + * Modularised by Alan Cox <Alan.Cox@linux.org>, while hacking some + * experimental NFS changes. Modularisation taken straight from SYS5 fs. + * + * Change to nfs_read_super() to permit NFS mounts to multi-homed hosts. + * J.S.Peatfield@damtp.cam.ac.uk + * + * Split from inode.c by David Howells <dhowells@redhat.com> + * + * - superblocks are indexed on server only - all inodes, dentries, etc. associated with a + * particular server are held in the same superblock + * - NFS superblocks can have several effective roots to the dentry tree + * - directory type roots are spliced into the tree when a path from one root reaches the root + * of another (see nfs_lookup()) + */ + +#include <linux/module.h> +#include <linux/init.h> + +#include <linux/time.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/string.h> +#include <linux/stat.h> +#include <linux/errno.h> +#include <linux/unistd.h> +#include <linux/sunrpc/clnt.h> +#include <linux/sunrpc/stats.h> +#include <linux/sunrpc/metrics.h> +#include <linux/nfs_fs.h> +#include <linux/nfs_mount.h> +#include <linux/nfs4_mount.h> +#include <linux/lockd/bind.h> +#include <linux/smp_lock.h> +#include <linux/seq_file.h> +#include <linux/mount.h> +#include <linux/nfs_idmap.h> +#include <linux/vfs.h> +#include <linux/inet.h> +#include <linux/nfs_xdr.h> +#include <linux/vserver/xid.h> + +#include <asm/system.h> +#include <asm/uaccess.h> + +#include "nfs4_fs.h" +#include "callback.h" +#include "delegation.h" +#include "iostat.h" +#include "internal.h" + +#define NFSDBG_FACILITY NFSDBG_VFS + +static void nfs_umount_begin(struct vfsmount *, int); +static int nfs_statfs(struct dentry *, struct kstatfs *); +static int nfs_show_options(struct seq_file *, struct vfsmount *); +static int nfs_show_stats(struct seq_file *, struct vfsmount *); +static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *); +static int nfs_xdev_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); +static void nfs_kill_super(struct super_block *); + +static struct file_system_type nfs_fs_type = { + .owner = THIS_MODULE, + .name = "nfs", + .get_sb = nfs_get_sb, + .kill_sb = nfs_kill_super, + .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, +}; + +struct file_system_type nfs_xdev_fs_type = { + .owner = THIS_MODULE, + .name = "nfs", + .get_sb = nfs_xdev_get_sb, + .kill_sb = nfs_kill_super, + .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, +}; + +static struct super_operations nfs_sops = { + .alloc_inode = nfs_alloc_inode, + .destroy_inode = nfs_destroy_inode, + .write_inode = nfs_write_inode, + .statfs = nfs_statfs, + .clear_inode = nfs_clear_inode, + .umount_begin = nfs_umount_begin, + .show_options = nfs_show_options, + .show_stats = nfs_show_stats, +}; + +#ifdef CONFIG_NFS_V4 +static int nfs4_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); +static int nfs4_xdev_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); +static int nfs4_referral_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); +static void nfs4_kill_super(struct super_block *sb); + +static struct file_system_type nfs4_fs_type = { + .owner = THIS_MODULE, + .name = "nfs4", + .get_sb = nfs4_get_sb, + .kill_sb = nfs4_kill_super, + .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, +}; + +struct file_system_type nfs4_xdev_fs_type = { + .owner = THIS_MODULE, + .name = "nfs4", + .get_sb = nfs4_xdev_get_sb, + .kill_sb = nfs4_kill_super, + .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, +}; + +struct file_system_type nfs4_referral_fs_type = { + .owner = THIS_MODULE, + .name = "nfs4", + .get_sb = nfs4_referral_get_sb, + .kill_sb = nfs4_kill_super, + .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, +}; + +static struct super_operations nfs4_sops = { + .alloc_inode = nfs_alloc_inode, + .destroy_inode = nfs_destroy_inode, + .write_inode = nfs_write_inode, + .statfs = nfs_statfs, + .clear_inode = nfs4_clear_inode, + .umount_begin = nfs_umount_begin, + .show_options = nfs_show_options, + .show_stats = nfs_show_stats, +}; +#endif + +/* + * Register the NFS filesystems + */ +int __init register_nfs_fs(void) +{ + int ret; + + ret = register_filesystem(&nfs_fs_type); + if (ret < 0) + goto error_0; + +#ifdef CONFIG_NFS_V4 + ret = nfs_register_sysctl(); + if (ret < 0) + goto error_1; + ret = register_filesystem(&nfs4_fs_type); + if (ret < 0) + goto error_2; +#endif + return 0; + +#ifdef CONFIG_NFS_V4 +error_2: + nfs_unregister_sysctl(); +error_1: + unregister_filesystem(&nfs_fs_type); +#endif +error_0: + return ret; +} + +/* + * Unregister the NFS filesystems + */ +void __exit unregister_nfs_fs(void) +{ +#ifdef CONFIG_NFS_V4 + unregister_filesystem(&nfs4_fs_type); + nfs_unregister_sysctl(); +#endif + unregister_filesystem(&nfs_fs_type); +} + +/* + * Deliver file system statistics to userspace + */ +static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct nfs_server *server = NFS_SB(dentry->d_sb); + unsigned char blockbits; + unsigned long blockres; + struct nfs_fh *fh = NFS_FH(dentry->d_inode); + struct nfs_fattr fattr; + struct nfs_fsstat res = { + .fattr = &fattr, + }; + int error; + + lock_kernel(); + + error = server->nfs_client->rpc_ops->statfs(server, fh, &res); + buf->f_type = NFS_SUPER_MAGIC; + if (error < 0) + goto out_err; + + /* + * Current versions of glibc do not correctly handle the + * case where f_frsize != f_bsize. Eventually we want to + * report the value of wtmult in this field. + */ + buf->f_frsize = dentry->d_sb->s_blocksize; + + /* + * On most *nix systems, f_blocks, f_bfree, and f_bavail + * are reported in units of f_frsize. Linux hasn't had + * an f_frsize field in its statfs struct until recently, + * thus historically Linux's sys_statfs reports these + * fields in units of f_bsize. + */ + buf->f_bsize = dentry->d_sb->s_blocksize; + blockbits = dentry->d_sb->s_blocksize_bits; + blockres = (1 << blockbits) - 1; + buf->f_blocks = (res.tbytes + blockres) >> blockbits; + buf->f_bfree = (res.fbytes + blockres) >> blockbits; + buf->f_bavail = (res.abytes + blockres) >> blockbits; + + buf->f_files = res.tfiles; + buf->f_ffree = res.afiles; + + buf->f_namelen = server->namelen; + out: + unlock_kernel(); + return 0; + + out_err: + dprintk("%s: statfs error = %d\n", __FUNCTION__, -error); + buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; + goto out; + +} + +/* + * Map the security flavour number to a name + */ +static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour) +{ + static const struct { + rpc_authflavor_t flavour; + const char *str; + } sec_flavours[] = { + { RPC_AUTH_NULL, "null" }, + { RPC_AUTH_UNIX, "sys" }, + { RPC_AUTH_GSS_KRB5, "krb5" }, + { RPC_AUTH_GSS_KRB5I, "krb5i" }, + { RPC_AUTH_GSS_KRB5P, "krb5p" }, + { RPC_AUTH_GSS_LKEY, "lkey" }, + { RPC_AUTH_GSS_LKEYI, "lkeyi" }, + { RPC_AUTH_GSS_LKEYP, "lkeyp" }, + { RPC_AUTH_GSS_SPKM, "spkm" }, + { RPC_AUTH_GSS_SPKMI, "spkmi" }, + { RPC_AUTH_GSS_SPKMP, "spkmp" }, + { -1, "unknown" } + }; + int i; + + for (i=0; sec_flavours[i].flavour != -1; i++) { + if (sec_flavours[i].flavour == flavour) + break; + } + return sec_flavours[i].str; +} + +/* + * Describe the mount options in force on this server representation + */ +static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults) +{ + static const struct proc_nfs_info { + int flag; + const char *str; + const char *nostr; + } nfs_info[] = { + { NFS_MOUNT_SOFT, ",soft", ",hard" }, + { NFS_MOUNT_INTR, ",intr", "" }, + { NFS_MOUNT_NOCTO, ",nocto", "" }, + { NFS_MOUNT_NOAC, ",noac", "" }, + { NFS_MOUNT_NONLM, ",nolock", "" }, + { NFS_MOUNT_NOACL, ",noacl", "" }, + { NFS_MOUNT_FSCACHE, ",fsc", "" }, + { NFS_MOUNT_TAGXID, ",tagxid", "" }, + { 0, NULL, NULL } + }; + const struct proc_nfs_info *nfs_infop; + struct nfs_client *clp = nfss->nfs_client; + char buf[12]; + const char *proto; + + seq_printf(m, ",vers=%d", clp->rpc_ops->version); + seq_printf(m, ",rsize=%d", nfss->rsize); + seq_printf(m, ",wsize=%d", nfss->wsize); + if (nfss->acregmin != 3*HZ || showdefaults) + seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ); + if (nfss->acregmax != 60*HZ || showdefaults) + seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ); + if (nfss->acdirmin != 30*HZ || showdefaults) + seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ); + if (nfss->acdirmax != 60*HZ || showdefaults) + seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ); + for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) { + if (nfss->flags & nfs_infop->flag) + seq_puts(m, nfs_infop->str); + else + seq_puts(m, nfs_infop->nostr); + } + switch (nfss->client->cl_xprt->prot) { + case IPPROTO_TCP: + proto = "tcp"; + break; + case IPPROTO_UDP: + proto = "udp"; + break; + default: + snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot); + proto = buf; + } + seq_printf(m, ",proto=%s", proto); + seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ); + seq_printf(m, ",retrans=%u", clp->retrans_count); + seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor)); +} + +/* + * Describe the mount options on this VFS mountpoint + */ +static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) +{ + struct nfs_server *nfss = NFS_SB(mnt->mnt_sb); + + nfs_show_mount_options(m, nfss, 0); + + seq_puts(m, ",addr="); + seq_escape(m, nfss->nfs_client->cl_hostname, " \t\n\\"); + + return 0; +} + +/* + * Present statistical information for this VFS mountpoint + */ +static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt) +{ + int i, cpu; + struct nfs_server *nfss = NFS_SB(mnt->mnt_sb); + struct rpc_auth *auth = nfss->client->cl_auth; + struct nfs_iostats totals = { }; + + seq_printf(m, "statvers=%s", NFS_IOSTAT_VERS); + + /* + * Display all mount option settings + */ + seq_printf(m, "\n\topts:\t"); + seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw"); + seq_puts(m, mnt->mnt_sb->s_flags & MS_SYNCHRONOUS ? ",sync" : ""); + seq_puts(m, mnt->mnt_sb->s_flags & MS_NOATIME ? ",noatime" : ""); + seq_puts(m, mnt->mnt_sb->s_flags & MS_NODIRATIME ? ",nodiratime" : ""); + nfs_show_mount_options(m, nfss, 1); + + seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ); + + seq_printf(m, "\n\tcaps:\t"); + seq_printf(m, "caps=0x%x", nfss->caps); + seq_printf(m, ",wtmult=%d", nfss->wtmult); + seq_printf(m, ",dtsize=%d", nfss->dtsize); + seq_printf(m, ",bsize=%d", nfss->bsize); + seq_printf(m, ",namelen=%d", nfss->namelen); + +#ifdef CONFIG_NFS_V4 + if (nfss->nfs_client->cl_nfsversion == 4) { + seq_printf(m, "\n\tnfsv4:\t"); + seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); + seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]); + seq_printf(m, ",acl=0x%x", nfss->acl_bitmask); + } +#endif + + /* + * Display security flavor in effect for this mount + */ + seq_printf(m, "\n\tsec:\tflavor=%d", auth->au_ops->au_flavor); + if (auth->au_flavor) + seq_printf(m, ",pseudoflavor=%d", auth->au_flavor); + + /* + * Display superblock I/O counters + */ + for_each_possible_cpu(cpu) { + struct nfs_iostats *stats; + + preempt_disable(); + stats = per_cpu_ptr(nfss->io_stats, cpu); + + for (i = 0; i < __NFSIOS_COUNTSMAX; i++) + totals.events[i] += stats->events[i]; + for (i = 0; i < __NFSIOS_BYTESMAX; i++) + totals.bytes[i] += stats->bytes[i]; + + preempt_enable(); + } + + seq_printf(m, "\n\tevents:\t"); + for (i = 0; i < __NFSIOS_COUNTSMAX; i++) + seq_printf(m, "%lu ", totals.events[i]); + seq_printf(m, "\n\tbytes:\t"); + for (i = 0; i < __NFSIOS_BYTESMAX; i++) + seq_printf(m, "%Lu ", totals.bytes[i]); + seq_printf(m, "\n"); + + rpc_print_iostats(m, nfss->client); + + return 0; +} + +/* + * Begin unmount by attempting to remove all automounted mountpoints we added + * in response to xdev traversals and referrals + */ +static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags) +{ + shrink_submounts(vfsmnt, &nfs_automount_list); +} + +/* + * Validate the NFS2/NFS3 mount data + * - fills in the mount root filehandle + */ +static int nfs_validate_mount_data(struct nfs_mount_data *data, + struct nfs_fh *mntfh) +{ + if (data == NULL) { + dprintk("%s: missing data argument\n", __FUNCTION__); + return -EINVAL; + } + + if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { + dprintk("%s: bad mount version\n", __FUNCTION__); + return -EINVAL; + } + + switch (data->version) { + case 1: + data->namlen = 0; + case 2: + data->bsize = 0; + case 3: + if (data->flags & NFS_MOUNT_VER3) { + dprintk("%s: mount structure version %d does not support NFSv3\n", + __FUNCTION__, + data->version); + return -EINVAL; + } + data->root.size = NFS2_FHSIZE; + memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); + case 4: + if (data->flags & NFS_MOUNT_SECFLAVOUR) { + dprintk("%s: mount structure version %d does not support strong security\n", + __FUNCTION__, + data->version); + return -EINVAL; + } + /* Fill in pseudoflavor for mount version < 5 */ + data->pseudoflavor = RPC_AUTH_UNIX; + case 5: + memset(data->context, 0, sizeof(data->context)); + } + +#ifndef CONFIG_NFS_V3 + /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ + if (data->flags & NFS_MOUNT_VER3) { + dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); + return -EPROTONOSUPPORT; + } +#endif /* CONFIG_NFS_V3 */ + + /* We now require that the mount process passes the remote address */ + if (data->addr.sin_addr.s_addr == INADDR_ANY) { + dprintk("%s: mount program didn't pass remote address!\n", + __FUNCTION__); + return -EINVAL; + } + + /* Prepare the root filehandle */ + if (data->flags & NFS_MOUNT_VER3) + mntfh->size = data->root.size; + else + mntfh->size = NFS2_FHSIZE; + + if (mntfh->size > sizeof(mntfh->data)) { + dprintk("%s: invalid root filehandle\n", __FUNCTION__); + return -EINVAL; + } + + memcpy(mntfh->data, data->root.data, mntfh->size); + if (mntfh->size < sizeof(mntfh->data)) + memset(mntfh->data + mntfh->size, 0, + sizeof(mntfh->data) - mntfh->size); + + return 0; +} + +/* + * Initialise the common bits of the superblock + */ +static inline void nfs_initialise_sb(struct super_block *sb) +{ + struct nfs_server *server = NFS_SB(sb); + + sb->s_magic = NFS_SUPER_MAGIC; + + /* We probably want something more informative here */ + snprintf(sb->s_id, sizeof(sb->s_id), + "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev)); + + if (sb->s_blocksize == 0) + sb->s_blocksize = nfs_block_bits(server->wsize, + &sb->s_blocksize_bits); + + if (server->flags & NFS_MOUNT_NOAC) + sb->s_flags |= MS_SYNCHRONOUS; + if (server->flags & NFS_MOUNT_TAGXID) + sb->s_flags |= MS_TAGXID; + + nfs_super_set_maxbytes(sb, server->maxfilesize); +} + +/* + * Finish setting up an NFS2/3 superblock + */ +static void nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data) +{ + struct nfs_server *server = NFS_SB(sb); + + sb->s_blocksize_bits = 0; + sb->s_blocksize = 0; + if (data->bsize) + sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits); + + if (server->flags & NFS_MOUNT_VER3) { + /* The VFS shouldn't apply the umask to mode bits. We will do + * so ourselves when necessary. + */ + sb->s_flags |= MS_POSIXACL; + sb->s_time_gran = 1; + } + + sb->s_op = &nfs_sops; + nfs_initialise_sb(sb); +} + +/* + * Finish setting up a cloned NFS2/3 superblock + */ +static void nfs_clone_super(struct super_block *sb, + const struct super_block *old_sb) +{ + struct nfs_server *server = NFS_SB(sb); + + sb->s_blocksize_bits = old_sb->s_blocksize_bits; + sb->s_blocksize = old_sb->s_blocksize; + sb->s_maxbytes = old_sb->s_maxbytes; + + if (server->flags & NFS_MOUNT_VER3) { + /* The VFS shouldn't apply the umask to mode bits. We will do + * so ourselves when necessary. + */ + sb->s_flags |= MS_POSIXACL; + sb->s_time_gran = 1; + } + + sb->s_op = old_sb->s_op; + nfs_initialise_sb(sb); +} + +static int nfs_set_super(struct super_block *s, void *_server) +{ + struct nfs_server *server = _server; + int ret; + + s->s_fs_info = server; + ret = set_anon_super(s, server); + if (ret == 0) + server->s_dev = s->s_dev; + return ret; +} + +static int nfs_compare_super(struct super_block *sb, void *data) +{ + struct nfs_server *server = data, *old = NFS_SB(sb); + + if (old->nfs_client != server->nfs_client) + return 0; + if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0) + return 0; + return 1; +} + +static int nfs_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) +{ + struct nfs_server *server = NULL; + struct super_block *s; + struct nfs_fh mntfh; + struct nfs_mount_data *data = raw_data; + struct dentry *mntroot; + int error; + + /* Validate the mount data */ + error = nfs_validate_mount_data(data, &mntfh); + if (error < 0) + return error; + + /* Get a volume representation */ + server = nfs_create_server(data, &mntfh); + if (IS_ERR(server)) { + error = PTR_ERR(server); + goto out_err_noserver; + } + + /* Get a superblock - note that we may end up sharing one that already exists */ + s = sget(fs_type, nfs_compare_super, nfs_set_super, server); + if (IS_ERR(s)) { + error = PTR_ERR(s); + goto out_err_nosb; + } + + if (s->s_fs_info != server) { + nfs_free_server(server); + server = NULL; + } + + if (!s->s_root) { + /* initial superblock/root creation */ + s->s_flags = flags; + nfs_fill_super(s, data); + } + + mntroot = nfs_get_root(s, &mntfh); + if (IS_ERR(mntroot)) { + error = PTR_ERR(mntroot); + goto error_splat_super; + } + + s->s_flags |= MS_ACTIVE; + mnt->mnt_sb = s; + mnt->mnt_root = mntroot; + return 0; + +out_err_nosb: + nfs_free_server(server); +out_err_noserver: + return error; + +error_splat_super: + up_write(&s->s_umount); + deactivate_super(s); + return error; +} + +/* + * Destroy an NFS2/3 superblock + */ +static void nfs_kill_super(struct super_block *s) +{ + struct nfs_server *server = NFS_SB(s); + + kill_anon_super(s); + nfs_free_server(server); +} + +/* + * Clone an NFS2/3 server record on xdev traversal (FSID-change) + */ +static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *raw_data, + struct vfsmount *mnt) +{ + struct nfs_clone_mount *data = raw_data; + struct super_block *s; + struct nfs_server *server; + struct dentry *mntroot; + int error; + + dprintk("--> nfs_xdev_get_sb()\n"); + + /* create a new volume representation */ + server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); + if (IS_ERR(server)) { + error = PTR_ERR(server); + goto out_err_noserver; + } + + /* Get a superblock - note that we may end up sharing one that already exists */ + s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); + if (IS_ERR(s)) { + error = PTR_ERR(s); + goto out_err_nosb; + } + + if (s->s_fs_info != server) { + nfs_free_server(server); + server = NULL; + } + + if (!s->s_root) { + /* initial superblock/root creation */ + s->s_flags = flags; + nfs_clone_super(s, data->sb); + } + + mntroot = nfs_get_root(s, data->fh); + if (IS_ERR(mntroot)) { + error = PTR_ERR(mntroot); + goto error_splat_super; + } + + s->s_flags |= MS_ACTIVE; + mnt->mnt_sb = s; + mnt->mnt_root = mntroot; + + dprintk("<-- nfs_xdev_get_sb() = 0\n"); + return 0; + +out_err_nosb: + nfs_free_server(server); +out_err_noserver: + dprintk("<-- nfs_xdev_get_sb() = %d [error]\n", error); + return error; + +error_splat_super: + up_write(&s->s_umount); + deactivate_super(s); + dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error); + return error; +} + +#ifdef CONFIG_NFS_V4 + +/* + * Finish setting up a cloned NFS4 superblock + */ +static void nfs4_clone_super(struct super_block *sb, + const struct super_block *old_sb) +{ + sb->s_blocksize_bits = old_sb->s_blocksize_bits; + sb->s_blocksize = old_sb->s_blocksize; + sb->s_maxbytes = old_sb->s_maxbytes; + sb->s_time_gran = 1; + sb->s_op = old_sb->s_op; + nfs_initialise_sb(sb); +} + +/* + * Set up an NFS4 superblock + */ +static void nfs4_fill_super(struct super_block *sb) +{ + sb->s_time_gran = 1; + sb->s_op = &nfs4_sops; + nfs_initialise_sb(sb); +} + +static void *nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen) +{ + void *p = NULL; + + if (!src->len) + return ERR_PTR(-EINVAL); + if (src->len < maxlen) + maxlen = src->len; + if (dst == NULL) { + p = dst = kmalloc(maxlen + 1, GFP_KERNEL); + if (p == NULL) + return ERR_PTR(-ENOMEM); + } + if (copy_from_user(dst, src->data, maxlen)) { + kfree(p); + return ERR_PTR(-EFAULT); + } + dst[maxlen] = '\0'; + return dst; +} + +/* + * Get the superblock for an NFS4 mountpoint + */ +static int nfs4_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) +{ + struct nfs4_mount_data *data = raw_data; + struct super_block *s; + struct nfs_server *server; + struct sockaddr_in addr; + rpc_authflavor_t authflavour; + struct nfs_fh mntfh; + struct dentry *mntroot; + char *mntpath = NULL, *hostname = NULL, ip_addr[16]; + void *p; + int error; + + if (data == NULL) { + dprintk("%s: missing data argument\n", __FUNCTION__); + return -EINVAL; + } + if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { + dprintk("%s: bad mount version\n", __FUNCTION__); + return -EINVAL; + } + + /* We now require that the mount process passes the remote address */ + if (data->host_addrlen != sizeof(addr)) + return -EINVAL; + + if (copy_from_user(&addr, data->host_addr, sizeof(addr))) + return -EFAULT; + + if (addr.sin_family != AF_INET || + addr.sin_addr.s_addr == INADDR_ANY + ) { + dprintk("%s: mount program didn't pass remote IP address!\n", + __FUNCTION__); + return -EINVAL; + } + + /* Grab the authentication type */ + authflavour = RPC_AUTH_UNIX; + if (data->auth_flavourlen != 0) { + if (data->auth_flavourlen != 1) { + dprintk("%s: Invalid number of RPC auth flavours %d.\n", + __FUNCTION__, data->auth_flavourlen); + error = -EINVAL; + goto out_err_noserver; + } + + if (copy_from_user(&authflavour, data->auth_flavours, + sizeof(authflavour))) { + error = -EFAULT; + goto out_err_noserver; + } + } + + p = nfs_copy_user_string(NULL, &data->hostname, 256); + if (IS_ERR(p)) + goto out_err; + hostname = p; + + p = nfs_copy_user_string(NULL, &data->mnt_path, 1024); + if (IS_ERR(p)) + goto out_err; + mntpath = p; + + dprintk("MNTPATH: %s\n", mntpath); + + p = nfs_copy_user_string(ip_addr, &data->client_addr, + sizeof(ip_addr) - 1); + if (IS_ERR(p)) + goto out_err; + + /* Get a volume representation */ + server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr, + authflavour, &mntfh); + if (IS_ERR(server)) { + error = PTR_ERR(server); + goto out_err_noserver; + } + + /* Get a superblock - note that we may end up sharing one that already exists */ + s = sget(fs_type, nfs_compare_super, nfs_set_super, server); + if (IS_ERR(s)) { + error = PTR_ERR(s); + goto out_free; + } + + if (s->s_fs_info != server) { + nfs_free_server(server); + server = NULL; + } + + if (!s->s_root) { + /* initial superblock/root creation */ + s->s_flags = flags; + nfs4_fill_super(s); + } + + mntroot = nfs4_get_root(s, &mntfh); + if (IS_ERR(mntroot)) { + error = PTR_ERR(mntroot); + goto error_splat_super; + } + + s->s_flags |= MS_ACTIVE; + mnt->mnt_sb = s; + mnt->mnt_root = mntroot; + kfree(mntpath); + kfree(hostname); + return 0; + +out_err: + error = PTR_ERR(p); + goto out_err_noserver; + +out_free: + nfs_free_server(server); +out_err_noserver: + kfree(mntpath); + kfree(hostname); + return error; + +error_splat_super: + up_write(&s->s_umount); + deactivate_super(s); + goto out_err_noserver; +} + +static void nfs4_kill_super(struct super_block *sb) +{ + struct nfs_server *server = NFS_SB(sb); + + nfs_return_all_delegations(sb); + kill_anon_super(sb); + + nfs4_renewd_prepare_shutdown(server); + nfs_free_server(server); +} + +/* + * Clone an NFS4 server record on xdev traversal (FSID-change) + */ +static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *raw_data, + struct vfsmount *mnt) +{ + struct nfs_clone_mount *data = raw_data; + struct super_block *s; + struct nfs_server *server; + struct dentry *mntroot; + int error; + + dprintk("--> nfs4_xdev_get_sb()\n"); + + /* create a new volume representation */ + server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); + if (IS_ERR(server)) { + error = PTR_ERR(server); + goto out_err_noserver; + } + + /* Get a superblock - note that we may end up sharing one that already exists */ + s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); + if (IS_ERR(s)) { + error = PTR_ERR(s); + goto out_err_nosb; + } + + if (s->s_fs_info != server) { + nfs_free_server(server); + server = NULL; + } + + if (!s->s_root) { + /* initial superblock/root creation */ + s->s_flags = flags; + nfs4_clone_super(s, data->sb); + } + + mntroot = nfs4_get_root(s, data->fh); + if (IS_ERR(mntroot)) { + error = PTR_ERR(mntroot); + goto error_splat_super; + } + + s->s_flags |= MS_ACTIVE; + mnt->mnt_sb = s; + mnt->mnt_root = mntroot; + + dprintk("<-- nfs4_xdev_get_sb() = 0\n"); + return 0; + +out_err_nosb: + nfs_free_server(server); +out_err_noserver: + dprintk("<-- nfs4_xdev_get_sb() = %d [error]\n", error); + return error; + +error_splat_super: + up_write(&s->s_umount); + deactivate_super(s); + dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error); + return error; +} + +/* + * Create an NFS4 server record on referral traversal + */ +static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *raw_data, + struct vfsmount *mnt) +{ + struct nfs_clone_mount *data = raw_data; + struct super_block *s; + struct nfs_server *server; + struct dentry *mntroot; + struct nfs_fh mntfh; + int error; + + dprintk("--> nfs4_referral_get_sb()\n"); + + /* create a new volume representation */ + server = nfs4_create_referral_server(data, &mntfh); + if (IS_ERR(server)) { + error = PTR_ERR(server); + goto out_err_noserver; + } + + /* Get a superblock - note that we may end up sharing one that already exists */ + s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); + if (IS_ERR(s)) { + error = PTR_ERR(s); + goto out_err_nosb; + } + + if (s->s_fs_info != server) { + nfs_free_server(server); + server = NULL; + } + + if (!s->s_root) { + /* initial superblock/root creation */ + s->s_flags = flags; + nfs4_fill_super(s); + } + + mntroot = nfs4_get_root(s, data->fh); + if (IS_ERR(mntroot)) { + error = PTR_ERR(mntroot); + goto error_splat_super; + } + + s->s_flags |= MS_ACTIVE; + mnt->mnt_sb = s; + mnt->mnt_root = mntroot; + + dprintk("<-- nfs4_referral_get_sb() = 0\n"); + return 0; + +out_err_nosb: + nfs_free_server(server); +out_err_noserver: + dprintk("<-- nfs4_referral_get_sb() = %d [error]\n", error); + return error; + +error_splat_super: + up_write(&s->s_umount); + deactivate_super(s); + dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error); + return error; +} + +#endif /* CONFIG_NFS_V4 */ diff --git a/fs/squashfs/squashfs.h b/fs/squashfs/squashfs.h new file mode 100644 index 000000000..dcbef0d11 --- /dev/null +++ b/fs/squashfs/squashfs.h @@ -0,0 +1,86 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006 + * Phillip Lougher <phillip@lougher.org.uk> + * + * 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, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs.h + */ + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY +#endif + +#ifdef SQUASHFS_TRACE +#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args) +#else +#define TRACE(s, args...) {} +#endif + +#define ERROR(s, args...) printk(KERN_ERR "SQUASHFS error: "s, ## args) + +#define SERROR(s, args...) do { \ + if (!silent) \ + printk(KERN_ERR "SQUASHFS error: "s, ## args);\ + } while(0) + +#define WARNING(s, args...) printk(KERN_WARNING "SQUASHFS: "s, ## args) + +static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode) +{ + return list_entry(inode, struct squashfs_inode_info, vfs_inode); +} + +#if defined(CONFIG_SQUASHFS_1_0_COMPATIBILITY ) || defined(CONFIG_SQUASHFS_2_0_COMPATIBILITY) +#define SQSH_EXTERN +extern unsigned int squashfs_read_data(struct super_block *s, char *buffer, + long long index, unsigned int length, + long long *next_index); +extern int squashfs_get_cached_block(struct super_block *s, char *buffer, + long long block, unsigned int offset, + int length, long long *next_block, + unsigned int *next_offset); +extern void release_cached_fragment(struct squashfs_sb_info *msblk, struct + squashfs_fragment_cache *fragment); +extern struct squashfs_fragment_cache *get_cached_fragment(struct super_block + *s, long long start_block, + int length); +extern struct address_space_operations squashfs_symlink_aops; +extern struct address_space_operations squashfs_aops; +extern struct address_space_operations squashfs_aops_4K; +extern struct inode_operations squashfs_dir_inode_ops; +#else +#define SQSH_EXTERN static +#endif + +#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY +extern int squashfs_1_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_1_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif + +#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY +extern int squashfs_2_0_supported(struct squashfs_sb_info *msblk); +#else +static inline int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + return 0; +} +#endif diff --git a/fs/squashfs/squashfs2_0.c b/fs/squashfs/squashfs2_0.c new file mode 100644 index 000000000..53ce95e26 --- /dev/null +++ b/fs/squashfs/squashfs2_0.c @@ -0,0 +1,758 @@ +/* + * Squashfs - a compressed read only filesystem for Linux + * + * Copyright (c) 2002, 2003, 2004, 2005, 2006 + * Phillip Lougher <phillip@lougher.org.uk> + * + * 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, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * squashfs2_0.c + */ + +#include <linux/types.h> +#include <linux/squashfs_fs.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/slab.h> +#include <linux/zlib.h> +#include <linux/fs.h> +#include <linux/smp_lock.h> +#include <linux/slab.h> +#include <linux/squashfs_fs_sb.h> +#include <linux/squashfs_fs_i.h> +#include <linux/buffer_head.h> +#include <linux/vfs.h> +#include <linux/init.h> +#include <linux/dcache.h> +#include <linux/wait.h> +#include <linux/zlib.h> +#include <linux/blkdev.h> +#include <linux/vmalloc.h> +#include <asm/uaccess.h> +#include <asm/semaphore.h> + +#include "squashfs.h" +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir); +static struct dentry *squashfs_lookup_2(struct inode *, struct dentry *, + struct nameidata *); + +static struct file_operations squashfs_dir_ops_2 = { + .read = generic_read_dir, + .readdir = squashfs_readdir_2 +}; + +static struct inode_operations squashfs_dir_inode_ops_2 = { + .lookup = squashfs_lookup_2 +}; + +static unsigned char squashfs_filetype_table[] = { + DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK +}; + +static int read_fragment_index_table_2(struct super_block *s) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + + if (!(msblk->fragment_index_2 = kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments), GFP_KERNEL))) { + ERROR("Failed to allocate uid/gid table\n"); + return 0; + } + + if (SQUASHFS_FRAGMENT_INDEX_BYTES_2(sblk->fragments) && + !squashfs_read_data(s, (char *) + msblk->fragment_index_2, + sblk->fragment_table_start, + SQUASHFS_FRAGMENT_INDEX_BYTES_2 + (sblk->fragments) | + SQUASHFS_COMPRESSED_BIT_BLOCK, NULL)) { + ERROR("unable to read fragment index table\n"); + return 0; + } + + if (msblk->swap) { + int i; + unsigned int fragment; + + for (i = 0; i < SQUASHFS_FRAGMENT_INDEXES_2(sblk->fragments); + i++) { + SQUASHFS_SWAP_FRAGMENT_INDEXES_2((&fragment), + &msblk->fragment_index_2[i], 1); + msblk->fragment_index_2[i] = fragment; + } + } + + return 1; +} + + +static int get_fragment_location_2(struct super_block *s, unsigned int fragment, + long long *fragment_start_block, + unsigned int *fragment_size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + long long start_block = + msblk->fragment_index_2[SQUASHFS_FRAGMENT_INDEX_2(fragment)]; + int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET_2(fragment); + struct squashfs_fragment_entry_2 fragment_entry; + + if (msblk->swap) { + struct squashfs_fragment_entry_2 sfragment_entry; + + if (!squashfs_get_cached_block(s, (char *) &sfragment_entry, + start_block, offset, + sizeof(sfragment_entry), &start_block, + &offset)) + goto out; + SQUASHFS_SWAP_FRAGMENT_ENTRY_2(&fragment_entry, &sfragment_entry); + } else + if (!squashfs_get_cached_block(s, (char *) &fragment_entry, + start_block, offset, + sizeof(fragment_entry), &start_block, + &offset)) + goto out; + + *fragment_start_block = fragment_entry.start_block; + *fragment_size = fragment_entry.size; + + return 1; + +out: + return 0; +} + + +static struct inode *squashfs_new_inode(struct super_block *s, + struct squashfs_base_inode_header_2 *inodeb, unsigned int ino) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + struct inode *i = new_inode(s); + + if (i) { + i->i_ino = ino; + i->i_mtime.tv_sec = sblk->mkfs_time; + i->i_atime.tv_sec = sblk->mkfs_time; + i->i_ctime.tv_sec = sblk->mkfs_time; + i->i_uid = msblk->uid[inodeb->uid]; + i->i_mode = inodeb->mode; + i->i_nlink = 1; + i->i_size = 0; + if (inodeb->guid == SQUASHFS_GUIDS) + i->i_gid = i->i_uid; + else + i->i_gid = msblk->guid[inodeb->guid]; + } + + return i; +} + + +static struct inode *squashfs_iget_2(struct super_block *s, squashfs_inode_t inode) +{ + struct inode *i; + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + unsigned int block = SQUASHFS_INODE_BLK(inode) + + sblk->inode_table_start; + unsigned int offset = SQUASHFS_INODE_OFFSET(inode); + unsigned int ino = SQUASHFS_MK_VFS_INODE(block + - sblk->inode_table_start, offset); + long long next_block; + unsigned int next_offset; + union squashfs_inode_header_2 id, sid; + struct squashfs_base_inode_header_2 *inodeb = &id.base, + *sinodeb = &sid.base; + + TRACE("Entered squashfs_iget\n"); + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) sinodeb, block, + offset, sizeof(*sinodeb), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_BASE_INODE_HEADER_2(inodeb, sinodeb, + sizeof(*sinodeb)); + } else + if (!squashfs_get_cached_block(s, (char *) inodeb, block, + offset, sizeof(*inodeb), &next_block, + &next_offset)) + goto failed_read; + + switch(inodeb->inode_type) { + case SQUASHFS_FILE_TYPE: { + struct squashfs_reg_inode_header_2 *inodep = &id.reg; + struct squashfs_reg_inode_header_2 *sinodep = &sid.reg; + long long frag_blk; + unsigned int frag_size; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_REG_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + frag_blk = SQUASHFS_INVALID_BLK; + if (inodep->fragment != SQUASHFS_INVALID_FRAG && + !get_fragment_location_2(s, + inodep->fragment, &frag_blk, &frag_size)) + goto failed_read; + + if((i = squashfs_new_inode(s, inodeb, ino)) == NULL) + goto failed_read1; + + i->i_size = inodep->file_size; + i->i_fop = &generic_ro_fops; + i->i_mode |= S_IFREG; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + i->i_blocks = ((i->i_size - 1) >> 9) + 1; + SQUASHFS_I(i)->u.s1.fragment_start_block = frag_blk; + SQUASHFS_I(i)->u.s1.fragment_size = frag_size; + SQUASHFS_I(i)->u.s1.fragment_offset = inodep->offset; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->u.s1.block_list_start = next_block; + SQUASHFS_I(i)->offset = next_offset; + if (sblk->block_size > 4096) + i->i_data.a_ops = &squashfs_aops; + else + i->i_data.a_ops = &squashfs_aops_4K; + + TRACE("File inode %x:%x, start_block %x, " + "block_list_start %llx, offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, next_block, + next_offset); + break; + } + case SQUASHFS_DIR_TYPE: { + struct squashfs_dir_inode_header_2 *inodep = &id.dir; + struct squashfs_dir_inode_header_2 *sinodep = &sid.dir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DIR_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + if((i = squashfs_new_inode(s, inodeb, ino)) == NULL) + goto failed_read1; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_count = 0; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Directory inode %x:%x, start_block %x, offset " + "%x\n", SQUASHFS_INODE_BLK(inode), + offset, inodep->start_block, + inodep->offset); + break; + } + case SQUASHFS_LDIR_TYPE: { + struct squashfs_ldir_inode_header_2 *inodep = &id.ldir; + struct squashfs_ldir_inode_header_2 *sinodep = &sid.ldir; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_LDIR_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + if((i = squashfs_new_inode(s, inodeb, ino)) == NULL) + goto failed_read1; + + i->i_size = inodep->file_size; + i->i_op = &squashfs_dir_inode_ops_2; + i->i_fop = &squashfs_dir_ops_2; + i->i_mode |= S_IFDIR; + i->i_mtime.tv_sec = inodep->mtime; + i->i_atime.tv_sec = inodep->mtime; + i->i_ctime.tv_sec = inodep->mtime; + SQUASHFS_I(i)->start_block = inodep->start_block; + SQUASHFS_I(i)->offset = inodep->offset; + SQUASHFS_I(i)->u.s2.directory_index_start = next_block; + SQUASHFS_I(i)->u.s2.directory_index_offset = + next_offset; + SQUASHFS_I(i)->u.s2.directory_index_count = + inodep->i_count; + SQUASHFS_I(i)->u.s2.parent_inode = 0; + + TRACE("Long directory inode %x:%x, start_block %x, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->start_block, inodep->offset); + break; + } + case SQUASHFS_SYMLINK_TYPE: { + struct squashfs_symlink_inode_header_2 *inodep = + &id.symlink; + struct squashfs_symlink_inode_header_2 *sinodep = + &sid.symlink; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_SYMLINK_INODE_HEADER_2(inodep, + sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + if((i = squashfs_new_inode(s, inodeb, ino)) == NULL) + goto failed_read1; + + i->i_size = inodep->symlink_size; + i->i_op = &page_symlink_inode_operations; + i->i_data.a_ops = &squashfs_symlink_aops; + i->i_mode |= S_IFLNK; + SQUASHFS_I(i)->start_block = next_block; + SQUASHFS_I(i)->offset = next_offset; + + TRACE("Symbolic link inode %x:%x, start_block %llx, " + "offset %x\n", + SQUASHFS_INODE_BLK(inode), offset, + next_block, next_offset); + break; + } + case SQUASHFS_BLKDEV_TYPE: + case SQUASHFS_CHRDEV_TYPE: { + struct squashfs_dev_inode_header_2 *inodep = &id.dev; + struct squashfs_dev_inode_header_2 *sinodep = &sid.dev; + + if (msblk->swap) { + if (!squashfs_get_cached_block(s, (char *) + sinodep, block, offset, + sizeof(*sinodep), &next_block, + &next_offset)) + goto failed_read; + SQUASHFS_SWAP_DEV_INODE_HEADER_2(inodep, sinodep); + } else + if (!squashfs_get_cached_block(s, (char *) + inodep, block, offset, + sizeof(*inodep), &next_block, + &next_offset)) + goto failed_read; + + if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL) + goto failed_read1; + + i->i_mode |= (inodeb->inode_type == + SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : + S_IFBLK; + init_special_inode(i, i->i_mode, + old_decode_dev(inodep->rdev)); + + TRACE("Device inode %x:%x, rdev %x\n", + SQUASHFS_INODE_BLK(inode), offset, + inodep->rdev); + break; + } + case SQUASHFS_FIFO_TYPE: + case SQUASHFS_SOCKET_TYPE: { + if ((i = squashfs_new_inode(s, inodeb, ino)) == NULL) + goto failed_read1; + + i->i_mode |= (inodeb->inode_type == SQUASHFS_FIFO_TYPE) + ? S_IFIFO : S_IFSOCK; + init_special_inode(i, i->i_mode, 0); + break; + } + default: + ERROR("Unknown inode type %d in squashfs_iget!\n", + inodeb->inode_type); + goto failed_read1; + } + + insert_inode_hash(i); + return i; + +failed_read: + ERROR("Unable to read inode [%x:%x]\n", block, offset); + +failed_read1: + return NULL; +} + + +static int get_dir_index_using_offset(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + long long f_pos) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + struct squashfs_dir_index_2 index; + + TRACE("Entered get_dir_index_using_offset, i_count %d, f_pos %d\n", + i_count, (unsigned int) f_pos); + + if (f_pos == 0) + goto finish; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(&index, &sindex); + } else + squashfs_get_cached_block(s, (char *) &index, + index_start, index_offset, + sizeof(index), &index_start, + &index_offset); + + if (index.index > f_pos) + break; + + squashfs_get_cached_block(s, NULL, index_start, index_offset, + index.size + 1, &index_start, + &index_offset); + + length = index.index; + *next_block = index.start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + +finish: + return length; +} + + +static int get_dir_index_using_name(struct super_block *s, long long + *next_block, unsigned int *next_offset, + long long index_start, + unsigned int index_offset, int i_count, + const char *name, int size) +{ + struct squashfs_sb_info *msblk = s->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + int i, length = 0; + char buffer[sizeof(struct squashfs_dir_index_2) + SQUASHFS_NAME_LEN + 1]; + struct squashfs_dir_index_2 *index = (struct squashfs_dir_index_2 *) buffer; + char str[SQUASHFS_NAME_LEN + 1]; + + TRACE("Entered get_dir_index_using_name, i_count %d\n", i_count); + + strncpy(str, name, size); + str[size] = '\0'; + + for (i = 0; i < i_count; i++) { + if (msblk->swap) { + struct squashfs_dir_index_2 sindex; + squashfs_get_cached_block(s, (char *) &sindex, + index_start, index_offset, + sizeof(sindex), &index_start, + &index_offset); + SQUASHFS_SWAP_DIR_INDEX_2(index, &sindex); + } else + squashfs_get_cached_block(s, (char *) index, + index_start, index_offset, + sizeof(struct squashfs_dir_index_2), + &index_start, &index_offset); + + squashfs_get_cached_block(s, index->name, index_start, + index_offset, index->size + 1, + &index_start, &index_offset); + + index->name[index->size + 1] = '\0'; + + if (strcmp(index->name, str) > 0) + break; + + length = index->index; + *next_block = index->start_block + sblk->directory_table_start; + } + + *next_offset = (length + *next_offset) % SQUASHFS_METADATA_SIZE; + return length; +} + + +static int squashfs_readdir_2(struct file *file, void *dirent, filldir_t filldir) +{ + struct inode *i = file->f_dentry->d_inode; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, dirs_read = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN + 1]; + struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer; + + TRACE("Entered squashfs_readdir_2 [%llx:%x]\n", next_block, next_offset); + + length = get_dir_index_using_offset(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, + file->f_pos); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block, next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block, next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, + dire->size + 1, &next_block, + &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (file->f_pos >= length) + continue; + + dire->name[dire->size + 1] = '\0'; + + TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", + (unsigned int) dirent, dire->name, + dire->size + 1, (int) file->f_pos, + dirh.start_block, dire->offset, + squashfs_filetype_table[dire->type]); + + if (filldir(dirent, dire->name, dire->size + 1, + file->f_pos, SQUASHFS_MK_VFS_INODE( + dirh.start_block, dire->offset), + squashfs_filetype_table[dire->type]) + < 0) { + TRACE("Filldir returned less than 0\n"); + goto finish; + } + file->f_pos = length; + dirs_read++; + } + } + +finish: + return dirs_read; + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + return 0; +} + + +static struct dentry *squashfs_lookup_2(struct inode *i, struct dentry *dentry, + struct nameidata *nd) +{ + const unsigned char *name = dentry->d_name.name; + int len = dentry->d_name.len; + struct inode *inode = NULL; + struct squashfs_sb_info *msblk = i->i_sb->s_fs_info; + struct squashfs_super_block *sblk = &msblk->sblk; + long long next_block = SQUASHFS_I(i)->start_block + + sblk->directory_table_start; + int next_offset = SQUASHFS_I(i)->offset, length = 0, + dir_count; + struct squashfs_dir_header_2 dirh; + char buffer[sizeof(struct squashfs_dir_entry_2) + SQUASHFS_NAME_LEN]; + struct squashfs_dir_entry_2 *dire = (struct squashfs_dir_entry_2 *) buffer; + int sorted = sblk->s_major == 2 && sblk->s_minor >= 1; + + TRACE("Entered squashfs_lookup [%llx:%x]\n", next_block, next_offset); + + if (len > SQUASHFS_NAME_LEN) + goto exit_loop; + + length = get_dir_index_using_name(i->i_sb, &next_block, &next_offset, + SQUASHFS_I(i)->u.s2.directory_index_start, + SQUASHFS_I(i)->u.s2.directory_index_offset, + SQUASHFS_I(i)->u.s2.directory_index_count, name, + len); + + while (length < i_size_read(i)) { + /* read directory header */ + if (msblk->swap) { + struct squashfs_dir_header_2 sdirh; + if (!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, + next_block, next_offset, sizeof(sdirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(sdirh); + SQUASHFS_SWAP_DIR_HEADER_2(&dirh, &sdirh); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) &dirh, + next_block, next_offset, sizeof(dirh), + &next_block, &next_offset)) + goto failed_read; + + length += sizeof(dirh); + } + + dir_count = dirh.count + 1; + while (dir_count--) { + if (msblk->swap) { + struct squashfs_dir_entry_2 sdire; + if (!squashfs_get_cached_block(i->i_sb, (char *) + &sdire, next_block,next_offset, + sizeof(sdire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(sdire); + SQUASHFS_SWAP_DIR_ENTRY_2(dire, &sdire); + } else { + if (!squashfs_get_cached_block(i->i_sb, (char *) + dire, next_block,next_offset, + sizeof(*dire), &next_block, + &next_offset)) + goto failed_read; + + length += sizeof(*dire); + } + + if (!squashfs_get_cached_block(i->i_sb, dire->name, + next_block, next_offset, dire->size + 1, + &next_block, &next_offset)) + goto failed_read; + + length += dire->size + 1; + + if (sorted && name[0] < dire->name[0]) + goto exit_loop; + + if ((len == dire->size + 1) && !strncmp(name, + dire->name, len)) { + squashfs_inode_t ino = + SQUASHFS_MKINODE(dirh.start_block, + dire->offset); + + TRACE("calling squashfs_iget for directory " + "entry %s, inode %x:%x, %lld\n", name, + dirh.start_block, dire->offset, ino); + + inode = (msblk->iget)(i->i_sb, ino); + + goto exit_loop; + } + } + } + +exit_loop: + d_add(dentry, inode); + return ERR_PTR(0); + +failed_read: + ERROR("Unable to read directory block [%llx:%x]\n", next_block, + next_offset); + goto exit_loop; +} + + +int squashfs_2_0_supported(struct squashfs_sb_info *msblk) +{ + struct squashfs_super_block *sblk = &msblk->sblk; + + msblk->iget = squashfs_iget_2; + msblk->read_fragment_index_table = read_fragment_index_table_2; + + sblk->bytes_used = sblk->bytes_used_2; + sblk->uid_start = sblk->uid_start_2; + sblk->guid_start = sblk->guid_start_2; + sblk->inode_table_start = sblk->inode_table_start_2; + sblk->directory_table_start = sblk->directory_table_start_2; + sblk->fragment_table_start = sblk->fragment_table_start_2; + + return 1; +} diff --git a/include/Kbuild b/include/Kbuild new file mode 100644 index 000000000..2d03f9958 --- /dev/null +++ b/include/Kbuild @@ -0,0 +1,9 @@ +header-y += asm-generic/ +header-y += linux/ +header-y += scsi/ +header-y += sound/ +header-y += mtd/ +header-y += rdma/ +header-y += video/ + +header-y += asm-$(ARCH)/ diff --git a/include/acpi/acpi_numa.h b/include/acpi/acpi_numa.h new file mode 100644 index 000000000..1049f2a0a --- /dev/null +++ b/include/acpi/acpi_numa.h @@ -0,0 +1,23 @@ +#ifndef __ACPI_NUMA_H +#define __ACPI_NUMA_H + +#ifdef CONFIG_ACPI_NUMA +#include <linux/kernel.h> + +/* Proximity bitmap length */ +#if MAX_NUMNODES > 256 +#define MAX_PXM_DOMAINS MAX_NUMNODES +#else +#define MAX_PXM_DOMAINS (256) /* Old pxm spec is defined 8 bit */ +#endif + +extern int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS]; +extern int __cpuinitdata node_to_pxm_map[MAX_NUMNODES]; + +extern int __cpuinit pxm_to_node(int); +extern int __cpuinit node_to_pxm(int); +extern int __cpuinit acpi_map_pxm_to_node(int); +extern void __cpuinit acpi_unmap_pxm_to_node(int); + +#endif /* CONFIG_ACPI_NUMA */ +#endif /* __ACP_NUMA_H */ diff --git a/include/asm-alpha/Kbuild b/include/asm-alpha/Kbuild new file mode 100644 index 000000000..b7c8f188b --- /dev/null +++ b/include/asm-alpha/Kbuild @@ -0,0 +1,11 @@ +include include/asm-generic/Kbuild.asm + +header-y += gentrap.h +header-y += regdef.h +header-y += pal.h +header-y += reg.h + +unifdef-y += console.h +unifdef-y += fpu.h +unifdef-y += sysinfo.h +unifdef-y += compiler.h diff --git a/include/asm-arm/Kbuild b/include/asm-arm/Kbuild new file mode 100644 index 000000000..c68e1680d --- /dev/null +++ b/include/asm-arm/Kbuild @@ -0,0 +1 @@ +include include/asm-generic/Kbuild.asm diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_spi.h b/include/asm-arm/arch-at91rm9200/at91rm9200_spi.h new file mode 100644 index 000000000..bff5ea45f --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91rm9200_spi.h @@ -0,0 +1,81 @@ +/* + * include/asm-arm/arch-at91rm9200/at91rm9200_spi.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * Serial Peripheral Interface (SPI) registers. + * Based on AT91RM9200 datasheet revision E. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef AT91RM9200_SPI_H +#define AT91RM9200_SPI_H + +#define AT91_SPI_CR 0x00 /* Control Register */ +#define AT91_SPI_SPIEN (1 << 0) /* SPI Enable */ +#define AT91_SPI_SPIDIS (1 << 1) /* SPI Disable */ +#define AT91_SPI_SWRST (1 << 7) /* SPI Software Reset */ +#define AT91_SPI_LASTXFER (1 << 24) /* Last Transfer [SAM9261 only] */ + +#define AT91_SPI_MR 0x04 /* Mode Register */ +#define AT91_SPI_MSTR (1 << 0) /* Master/Slave Mode */ +#define AT91_SPI_PS (1 << 1) /* Peripheral Select */ +#define AT91_SPI_PS_FIXED (0 << 1) +#define AT91_SPI_PS_VARIABLE (1 << 1) +#define AT91_SPI_PCSDEC (1 << 2) /* Chip Select Decode */ +#define AT91_SPI_DIV32 (1 << 3) /* Clock Selection */ +#define AT91_SPI_MODFDIS (1 << 4) /* Mode Fault Detection */ +#define AT91_SPI_LLB (1 << 7) /* Local Loopback Enable */ +#define AT91_SPI_PCS (0xf << 16) /* Peripheral Chip Select */ +#define AT91_SPI_DLYBCS (0xff << 24) /* Delay Between Chip Selects */ + +#define AT91_SPI_RDR 0x08 /* Receive Data Register */ +#define AT91_SPI_RD (0xffff << 0) /* Receive Data */ +#define AT91_SPI_PCS (0xf << 16) /* Peripheral Chip Select */ + +#define AT91_SPI_TDR 0x0c /* Transmit Data Register */ +#define AT91_SPI_TD (0xffff << 0) /* Transmit Data */ +#define AT91_SPI_PCS (0xf << 16) /* Peripheral Chip Select */ +#define AT91_SPI_LASTXFER (1 << 24) /* Last Transfer [SAM9261 only] */ + +#define AT91_SPI_SR 0x10 /* Status Register */ +#define AT91_SPI_RDRF (1 << 0) /* Receive Data Register Full */ +#define AT91_SPI_TDRE (1 << 1) /* Transmit Data Register Full */ +#define AT91_SPI_MODF (1 << 2) /* Mode Fault Error */ +#define AT91_SPI_OVRES (1 << 3) /* Overrun Error Status */ +#define AT91_SPI_ENDRX (1 << 4) /* End of RX buffer */ +#define AT91_SPI_ENDTX (1 << 5) /* End of TX buffer */ +#define AT91_SPI_RXBUFF (1 << 6) /* RX Buffer Full */ +#define AT91_SPI_TXBUFE (1 << 7) /* TX Buffer Empty */ +#define AT91_SPI_NSSR (1 << 8) /* NSS Rising [SAM9261 only] */ +#define AT91_SPI_TXEMPTY (1 << 9) /* Transmission Register Empty [SAM9261 only] */ +#define AT91_SPI_SPIENS (1 << 16) /* SPI Enable Status */ + +#define AT91_SPI_IER 0x14 /* Interrupt Enable Register */ +#define AT91_SPI_IDR 0x18 /* Interrupt Disable Register */ +#define AT91_SPI_IMR 0x1c /* Interrupt Mask Register */ + +#define AT91_SPI_CSR(n) (0x30 + ((n) * 4)) /* Chip Select Registers 0-3 */ +#define AT91_SPI_CPOL (1 << 0) /* Clock Polarity */ +#define AT91_SPI_NCPHA (1 << 1) /* Clock Phase */ +#define AT91_SPI_CSAAT (1 << 3) /* Chip Select Active After Transfer [SAM9261 only] */ +#define AT91_SPI_BITS (0xf << 4) /* Bits Per Transfer */ +#define AT91_SPI_BITS_8 (0 << 4) +#define AT91_SPI_BITS_9 (1 << 4) +#define AT91_SPI_BITS_10 (2 << 4) +#define AT91_SPI_BITS_11 (3 << 4) +#define AT91_SPI_BITS_12 (4 << 4) +#define AT91_SPI_BITS_13 (5 << 4) +#define AT91_SPI_BITS_14 (6 << 4) +#define AT91_SPI_BITS_15 (7 << 4) +#define AT91_SPI_BITS_16 (8 << 4) +#define AT91_SPI_SCBR (0xff << 8) /* Serial Clock Baud Rate */ +#define AT91_SPI_DLYBS (0xff << 16) /* Delay before SPCK */ +#define AT91_SPI_DLYBCT (0xff << 24) /* Delay between Consecutive Transfers */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h b/include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h new file mode 100644 index 000000000..ac8802271 --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h @@ -0,0 +1,96 @@ +/* + * include/asm-arm/arch-at91rm9200/at91rm9200_ssc.h + * + * Copyright (C) SAN People + * + * Serial Synchronous Controller (SSC) registers. + * Based on AT91RM9200 datasheet revision E. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef AT91RM9200_SSC_H +#define AT91RM9200_SSC_H + +#define AT91_SSC_CR 0x00 /* Control Register */ +#define AT91_SSC_RXEN (1 << 0) /* Receive Enable */ +#define AT91_SSC_RXDIS (1 << 1) /* Receive Disable */ +#define AT91_SSC_TXEN (1 << 8) /* Transmit Enable */ +#define AT91_SSC_TXDIS (1 << 9) /* Transmit Disable */ +#define AT91_SSC_SWRST (1 << 15) /* Software Reset */ + +#define AT91_SSC_CMR 0x04 /* Clock Mode Register */ +#define AT91_SSC_CMR_DIV (0xfff << 0) /* Clock Divider */ + +#define AT91_SSC_RCMR 0x10 /* Receive Clock Mode Register */ +#define AT91_SSC_CKS (3 << 0) /* Clock Selection */ +#define AT91_SSC_CKS_DIV (0 << 0) +#define AT91_SSC_CKS_CLOCK (1 << 0) +#define AT91_SSC_CKS_PIN (2 << 0) +#define AT91_SSC_CKO (7 << 2) /* Clock Output Mode Selection */ +#define AT91_SSC_CKO_NONE (0 << 2) +#define AT91_SSC_CKO_CONTINUOUS (1 << 2) +#define AT91_SSC_CKI (1 << 5) /* Clock Inversion */ +#define AT91_SSC_CKI_FALLING (0 << 5) +#define AT91_SSC_CK_RISING (1 << 5) +#define AT91_SSC_START (0xf << 8) /* Start Selection */ +#define AT91_SSC_START_CONTINUOUS (0 << 8) +#define AT91_SSC_START_TX_RX (1 << 8) +#define AT91_SSC_START_LOW_RF (2 << 8) +#define AT91_SSC_START_HIGH_RF (3 << 8) +#define AT91_SSC_START_FALLING_RF (4 << 8) +#define AT91_SSC_START_RISING_RF (5 << 8) +#define AT91_SSC_START_LEVEL_RF (6 << 8) +#define AT91_SSC_START_EDGE_RF (7 << 8) +#define AT91_SSC_STTDLY (0xff << 16) /* Start Delay */ +#define AT91_SSC_PERIOD (0xff << 24) /* Period Divider Selection */ + +#define AT91_SSC_RFMR 0x14 /* Receive Frame Mode Register */ +#define AT91_SSC_DATALEN (0x1f << 0) /* Data Length */ +#define AT91_SSC_LOOP (1 << 5) /* Loop Mode */ +#define AT91_SSC_MSBF (1 << 7) /* Most Significant Bit First */ +#define AT91_SSC_DATNB (0xf << 8) /* Data Number per Frame */ +#define AT91_SSC_FSLEN (0xf << 16) /* Frame Sync Length */ +#define AT91_SSC_FSOS (7 << 20) /* Frame Sync Output Selection */ +#define AT91_SSC_FSOS_NONE (0 << 20) +#define AT91_SSC_FSOS_NEGATIVE (1 << 20) +#define AT91_SSC_FSOS_POSITIVE (2 << 20) +#define AT91_SSC_FSOS_LOW (3 << 20) +#define AT91_SSC_FSOS_HIGH (4 << 20) +#define AT91_SSC_FSOS_TOGGLE (5 << 20) +#define AT91_SSC_FSEDGE (1 << 24) /* Frame Sync Edge Detection */ +#define AT91_SSC_FSEDGE_POSITIVE (0 << 24) +#define AT91_SSC_FSEDGE_NEGATIVE (1 << 24) + +#define AT91_SSC_TCMR 0x18 /* Transmit Clock Mode Register */ +#define AT91_SSC_TFMR 0x1c /* Transmit Fram Mode Register */ +#define AT91_SSC_DATDEF (1 << 5) /* Data Default Value */ +#define AT91_SSC_FSDEN (1 << 23) /* Frame Sync Data Enable */ + +#define AT91_SSC_RHR 0x20 /* Receive Holding Register */ +#define AT91_SSC_THR 0x24 /* Transmit Holding Register */ +#define AT91_SSC_RSHR 0x30 /* Receive Sync Holding Register */ +#define AT91_SSC_TSHR 0x34 /* Transmit Sync Holding Register */ + +#define AT91_SSC_SR 0x40 /* Status Register */ +#define AT91_SSC_TXRDY (1 << 0) /* Transmit Ready */ +#define AT91_SSC_TXEMPTY (1 << 1) /* Transmit Empty */ +#define AT91_SSC_ENDTX (1 << 2) /* End of Transmission */ +#define AT91_SSC_TXBUFE (1 << 3) /* Transmit Buffer Empty */ +#define AT91_SSC_RXRDY (1 << 4) /* Receive Ready */ +#define AT91_SSC_OVRUN (1 << 5) /* Receive Overrun */ +#define AT91_SSC_ENDRX (1 << 6) /* End of Reception */ +#define AT91_SSC_RXBUFF (1 << 7) /* Receive Buffer Full */ +#define AT91_SSC_TXSYN (1 << 10) /* Transmit Sync */ +#define AT91_SSC_RXSYN (1 << 11) /* Receive Sync */ +#define AT91_SSC_TXENA (1 << 16) /* Transmit Enable */ +#define AT91_SSC_RXENA (1 << 17) /* Receive Enable */ + +#define AT91_SSC_IER 0x44 /* Interrupt Enable Register */ +#define AT91_SSC_IDR 0x48 /* Interrupt Disable Register */ +#define AT91_SSC_IMR 0x4c /* Interrupt Mask Register */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_tc.h b/include/asm-arm/arch-at91rm9200/at91rm9200_tc.h new file mode 100644 index 000000000..f4da752bb --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91rm9200_tc.h @@ -0,0 +1,146 @@ +/* + * include/asm-arm/arch-at91rm9200/at91rm9200_tc.h + * + * Copyright (C) SAN People + * + * Timer/Counter Unit (TC) registers. + * Based on AT91RM9200 datasheet revision E. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef AT91RM9200_TC_H +#define AT91RM9200_TC_H + +#define AT91_TC_BCR 0xc0 /* TC Block Control Register */ +#define AT91_TC_SYNC (1 << 0) /* Synchro Command */ + +#define AT91_TC_BMR 0xc4 /* TC Block Mode Register */ +#define AT91_TC_TC0XC0S (3 << 0) /* External Clock Signal 0 Selection */ +#define AT91_TC_TC0XC0S_TCLK0 (0 << 0) +#define AT91_TC_TC0XC0S_NONE (1 << 0) +#define AT91_TC_TC0XC0S_TIOA1 (2 << 0) +#define AT91_TC_TC0XC0S_TIOA2 (3 << 0) +#define AT91_TC_TC1XC1S (3 << 2) /* External Clock Signal 1 Selection */ +#define AT91_TC_TC1XC1S_TCLK1 (0 << 2) +#define AT91_TC_TC1XC1S_NONE (1 << 2) +#define AT91_TC_TC1XC1S_TIOA0 (2 << 2) +#define AT91_TC_TC1XC1S_TIOA2 (3 << 2) +#define AT91_TC_TC2XC2S (3 << 4) /* External Clock Signal 2 Selection */ +#define AT91_TC_TC2XC2S_TCLK2 (0 << 4) +#define AT91_TC_TC2XC2S_NONE (1 << 4) +#define AT91_TC_TC2XC2S_TIOA0 (2 << 4) +#define AT91_TC_TC2XC2S_TIOA1 (3 << 4) + + +#define AT91_TC_CCR 0x00 /* Channel Control Register */ +#define AT91_TC_CLKEN (1 << 0) /* Counter Clock Enable Command */ +#define AT91_TC_CLKDIS (1 << 1) /* Counter CLock Disable Command */ +#define AT91_TC_SWTRG (1 << 2) /* Software Trigger Command */ + +#define AT91_TC_CMR 0x04 /* Channel Mode Register */ +#define AT91_TC_TCCLKS (7 << 0) /* Capture/Waveform Mode: Clock Selection */ +#define AT91_TC_TIMER_CLOCK1 (0 << 0) +#define AT91_TC_TIMER_CLOCK2 (1 << 0) +#define AT91_TC_TIMER_CLOCK3 (2 << 0) +#define AT91_TC_TIMER_CLOCK4 (3 << 0) +#define AT91_TC_TIMER_CLOCK5 (4 << 0) +#define AT91_TC_XC0 (5 << 0) +#define AT91_TC_XC1 (6 << 0) +#define AT91_TC_XC2 (7 << 0) +#define AT91_TC_CLKI (1 << 3) /* Capture/Waveform Mode: Clock Invert */ +#define AT91_TC_BURST (3 << 4) /* Capture/Waveform Mode: Burst Signal Selection */ +#define AT91_TC_LDBSTOP (1 << 6) /* Capture Mode: Counter Clock Stopped with TB Loading */ +#define AT91_TC_LDBDIS (1 << 7) /* Capture Mode: Counter Clock Disable with RB Loading */ +#define AT91_TC_ETRGEDG (3 << 8) /* Capture Mode: External Trigger Edge Selection */ +#define AT91_TC_ABETRG (1 << 10) /* Capture Mode: TIOA or TIOB External Trigger Selection */ +#define AT91_TC_CPCTRG (1 << 14) /* Capture Mode: RC Compare Trigger Enable */ +#define AT91_TC_WAVE (1 << 15) /* Capture/Waveform mode */ +#define AT91_TC_LDRA (3 << 16) /* Capture Mode: RA Loading Selection */ +#define AT91_TC_LDRB (3 << 18) /* Capture Mode: RB Loading Selection */ + +#define AT91_TC_CPCSTOP (1 << 6) /* Waveform Mode: Counter Clock Stopped with RC Compare */ +#define AT91_TC_CPCDIS (1 << 7) /* Waveform Mode: Counter Clock Disable with RC Compare */ +#define AT91_TC_EEVTEDG (3 << 8) /* Waveform Mode: External Event Edge Selection */ +#define AT91_TC_EEVTEDG_NONE (0 << 8) +#define AT91_TC_EEVTEDG_RISING (1 << 8) +#define AT91_TC_EEVTEDG_FALLING (2 << 8) +#define AT91_TC_EEVTEDG_BOTH (3 << 8) +#define AT91_TC_EEVT (3 << 10) /* Waveform Mode: External Event Selection */ +#define AT91_TC_EEVT_TIOB (0 << 10) +#define AT91_TC_EEVT_XC0 (1 << 10) +#define AT91_TC_EEVT_XC1 (2 << 10) +#define AT91_TC_EEVT_XC2 (3 << 10) +#define AT91_TC_ENETRG (1 << 12) /* Waveform Mode: External Event Trigger Enable */ +#define AT91_TC_WAVESEL (3 << 13) /* Waveform Mode: Waveform Selection */ +#define AT91_TC_WAVESEL_UP (0 << 13) +#define AT91_TC_WAVESEL_UP_AUTO (2 << 13) +#define AT91_TC_WAVESEL_UPDOWN (1 << 13) +#define AT91_TC_WAVESEL_UPDOWN_AUTO (3 << 13) +#define AT91_TC_ACPA (3 << 16) /* Waveform Mode: RA Compare Effect on TIOA */ +#define AT91_TC_ACPA_NONE (0 << 16) +#define AT91_TC_ACPA_SET (1 << 16) +#define AT91_TC_ACPA_CLEAR (2 << 16) +#define AT91_TC_ACPA_TOGGLE (3 << 16) +#define AT91_TC_ACPC (3 << 18) /* Waveform Mode: RC Compre Effect on TIOA */ +#define AT91_TC_ACPC_NONE (0 << 18) +#define AT91_TC_ACPC_SET (1 << 18) +#define AT91_TC_ACPC_CLEAR (2 << 18) +#define AT91_TC_ACPC_TOGGLE (3 << 18) +#define AT91_TC_AEEVT (3 << 20) /* Waveform Mode: External Event Effect on TIOA */ +#define AT91_TC_AEEVT_NONE (0 << 20) +#define AT91_TC_AEEVT_SET (1 << 20) +#define AT91_TC_AEEVT_CLEAR (2 << 20) +#define AT91_TC_AEEVT_TOGGLE (3 << 20) +#define AT91_TC_ASWTRG (3 << 22) /* Waveform Mode: Software Trigger Effect on TIOA */ +#define AT91_TC_ASWTRG_NONE (0 << 22) +#define AT91_TC_ASWTRG_SET (1 << 22) +#define AT91_TC_ASWTRG_CLEAR (2 << 22) +#define AT91_TC_ASWTRG_TOGGLE (3 << 22) +#define AT91_TC_BCPB (3 << 24) /* Waveform Mode: RB Compare Effect on TIOB */ +#define AT91_TC_BCPB_NONE (0 << 24) +#define AT91_TC_BCPB_SET (1 << 24) +#define AT91_TC_BCPB_CLEAR (2 << 24) +#define AT91_TC_BCPB_TOGGLE (3 << 24) +#define AT91_TC_BCPC (3 << 26) /* Waveform Mode: RC Compare Effect on TIOB */ +#define AT91_TC_BCPC_NONE (0 << 26) +#define AT91_TC_BCPC_SET (1 << 26) +#define AT91_TC_BCPC_CLEAR (2 << 26) +#define AT91_TC_BCPC_TOGGLE (3 << 26) +#define AT91_TC_BEEVT (3 << 28) /* Waveform Mode: External Event Effect on TIOB */ +#define AT91_TC_BEEVT_NONE (0 << 28) +#define AT91_TC_BEEVT_SET (1 << 28) +#define AT91_TC_BEEVT_CLEAR (2 << 28) +#define AT91_TC_BEEVT_TOGGLE (3 << 28) +#define AT91_TC_BSWTRG (3 << 30) /* Waveform Mode: Software Trigger Effect on TIOB */ +#define AT91_TC_BSWTRG_NONE (0 << 30) +#define AT91_TC_BSWTRG_SET (1 << 30) +#define AT91_TC_BSWTRG_CLEAR (2 << 30) +#define AT91_TC_BSWTRG_TOGGLE (3 << 30) + +#define AT91_TC_CV 0x10 /* Counter Value */ +#define AT91_TC_RA 0x14 /* Register A */ +#define AT91_TC_RB 0x18 /* Register B */ +#define AT91_TC_RC 0x1c /* Register C */ + +#define AT91_TC_SR 0x20 /* Status Register */ +#define AT91_TC_COVFS (1 << 0) /* Counter Overflow Status */ +#define AT91_TC_LOVRS (1 << 1) /* Load Overrun Status */ +#define AT91_TC_CPAS (1 << 2) /* RA Compare Status */ +#define AT91_TC_CPBS (1 << 3) /* RB Compare Status */ +#define AT91_TC_CPCS (1 << 4) /* RC Compare Status */ +#define AT91_TC_LDRAS (1 << 5) /* RA Loading Status */ +#define AT91_TC_LDRBS (1 << 6) /* RB Loading Status */ +#define AT91_TC_ETRGS (1 << 7) /* External Trigger Status */ +#define AT91_TC_CLKSTA (1 << 16) /* Clock Enabling Status */ +#define AT91_TC_MTIOA (1 << 17) /* TIOA Mirror */ +#define AT91_TC_MTIOB (1 << 18) /* TIOB Mirror */ + +#define AT91_TC_IER 0x24 /* Interrupt Enable Register */ +#define AT91_TC_IDR 0x28 /* Interrupt Disable Register */ +#define AT91_TC_IMR 0x2c /* Interrupt Mask Register */ + +#endif diff --git a/include/asm-arm/arch-at91rm9200/at91rm9200_udp.h b/include/asm-arm/arch-at91rm9200/at91rm9200_udp.h new file mode 100644 index 000000000..951e3f61c --- /dev/null +++ b/include/asm-arm/arch-at91rm9200/at91rm9200_udp.h @@ -0,0 +1,77 @@ +/* + * include/asm-arm/arch-at91rm9200/at91rm9200_udp.h + * + * Copyright (C) 2005 Ivan Kokshaysky + * Copyright (C) SAN People + * + * USB Device Port (UDP) registers. + * Based on AT91RM9200 datasheet revision E. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef AT91RM9200_UDP_H +#define AT91RM9200_UDP_H + +#define AT91_UDP_FRM_NUM 0x00 /* Frame Number Register */ +#define AT91_UDP_NUM (0x7ff << 0) /* Frame Number */ +#define AT91_UDP_FRM_ERR (1 << 16) /* Frame Error */ +#define AT91_UDP_FRM_OK (1 << 17) /* Frame OK */ + +#define AT91_UDP_GLB_STAT 0x04 /* Global State Register */ +#define AT91_UDP_FADDEN (1 << 0) /* Function Address Enable */ +#define AT91_UDP_CONFG (1 << 1) /* Configured */ +#define AT91_UDP_ESR (1 << 2) /* Enable Send Resume */ +#define AT91_UDP_RSMINPR (1 << 3) /* Resume has been sent */ +#define AT91_UDP_RMWUPE (1 << 4) /* Remote Wake Up Enable */ + +#define AT91_UDP_FADDR 0x08 /* Function Address Register */ +#define AT91_UDP_FADD (0x7f << 0) /* Function Address Value */ +#define AT91_UDP_FEN (1 << 8) /* Function Enable */ + +#define AT91_UDP_IER 0x10 /* Interrupt Enable Register */ +#define AT91_UDP_IDR 0x14 /* Interrupt Disable Register */ +#define AT91_UDP_IMR 0x18 /* Interrupt Mask Register */ + +#define AT91_UDP_ISR 0x1c /* Interrupt Status Register */ +#define AT91_UDP_EP(n) (1 << (n)) /* Endpoint Interrupt Status */ +#define AT91_UDP_RXSUSP (1 << 8) /* USB Suspend Interrupt Status */ +#define AT91_UDP_RXRSM (1 << 9) /* USB Resume Interrupt Status */ +#define AT91_UDP_EXTRSM (1 << 10) /* External Resume Interrupt Status */ +#define AT91_UDP_SOFINT (1 << 11) /* Start of Frame Interrupt Status */ +#define AT91_UDP_ENDBUSRES (1 << 12) /* End of Bus Reset Interrpt Status */ +#define AT91_UDP_WAKEUP (1 << 13) /* USB Wakeup Interrupt Status */ + +#define AT91_UDP_ICR 0x20 /* Interrupt Clear Register */ +#define AT91_UDP_RST_EP 0x28 /* Reset Endpoint Register */ + +#define AT91_UDP_CSR(n) (0x30 + ((n) * 4)) /* Endpoint Control/Status Registers 0-7 */ +#define AT91_UDP_TXCOMP (1 << 0) /* Generates IN packet with data previously written in DPR */ +#define AT91_UDP_RX_DATA_BK0 (1 << 1) /* Receive Data Bank 0 */ +#define AT91_UDP_RXSETUP (1 << 2) /* Send STALL to the host */ +#define AT91_UDP_STALLSENT (1 << 3) /* Stall Sent / Isochronous error (Isochronous endpoints) */ +#define AT91_UDP_TXPKTRDY (1 << 4) /* Transmit Packet Ready */ +#define AT91_UDP_FORCESTALL (1 << 5) /* Force Stall */ +#define AT91_UDP_RX_DATA_BK1 (1 << 6) /* Receive Data Bank 1 */ +#define AT91_UDP_DIR (1 << 7) /* Transfer Direction */ +#define AT91_UDP_EPTYPE (7 << 8) /* Endpoint Type */ +#define AT91_UDP_EPTYPE_CTRL (0 << 8) +#define AT91_UDP_EPTYPE_ISO_OUT (1 << 8) +#define AT91_UDP_EPTYPE_BULK_OUT (2 << 8) +#define AT91_UDP_EPTYPE_INT_OUT (3 << 8) +#define AT91_UDP_EPTYPE_ISO_IN (5 << 8) +#define AT91_UDP_EPTYPE_BULK_IN (6 << 8) +#define AT91_UDP_EPTYPE_INT_IN (7 << 8) +#define AT91_UDP_DTGLE (1 << 11) /* Data Toggle */ +#define AT91_UDP_EPEDS (1 << 15) /* Endpoint Enable/Disable */ +#define AT91_UDP_RXBYTECNT (0x7ff << 16) /* Number of bytes in FIFO */ + +#define AT91_UDP_FDR(n) (0x50 + ((n) * 4)) /* Endpoint FIFO Data Registers 0-7 */ + +#define AT91_UDP_TXVC 0x74 /* Transceiver Control Register */ +#define AT91_UDP_TXVC_TXVDIS (1 << 8) /* Transceiver Disable */ + +#endif diff --git a/include/asm-arm/arch-lh7a40x/clocks.h b/include/asm-arm/arch-lh7a40x/clocks.h new file mode 100644 index 000000000..7d0ba18ad --- /dev/null +++ b/include/asm-arm/arch-lh7a40x/clocks.h @@ -0,0 +1,18 @@ +/* include/asm-arm/arch-lh7a40x/clocks.h + * + * Copyright (C) 2004 Marc Singer + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + */ + +#ifndef __ASM_ARCH_CLOCKS_H +#define __ASM_ARCH_CLOCKS_H + +unsigned int fclkfreq_get (void); +unsigned int hclkfreq_get (void); +unsigned int pclkfreq_get (void); + +#endif /* _ASM_ARCH_CLOCKS_H */ diff --git a/include/asm-arm/arch-lh7a40x/ssp.h b/include/asm-arm/arch-lh7a40x/ssp.h new file mode 100644 index 000000000..132b1c4d5 --- /dev/null +++ b/include/asm-arm/arch-lh7a40x/ssp.h @@ -0,0 +1,71 @@ +/* ssp.h + $Id$ + + written by Marc Singer + 6 Dec 2004 + + Copyright (C) 2004 Marc Singer + + ----------- + DESCRIPTION + ----------- + + This SSP header is available throughout the kernel, for this + machine/architecture, because drivers that use it may be dispersed. + + This file was cloned from the 7952x implementation. It would be + better to share them, but we're taking an easier approach for the + time being. + +*/ + +#if !defined (__SSP_H__) +# define __SSP_H__ + +/* ----- Includes */ + +/* ----- Types */ + +struct ssp_driver { + int (*init) (void); + void (*exit) (void); + void (*acquire) (void); + void (*release) (void); + int (*configure) (int device, int mode, int speed, + int frame_size_write, int frame_size_read); + void (*chip_select) (int enable); + void (*set_callbacks) (void* handle, + irqreturn_t (*callback_tx)(void*), + irqreturn_t (*callback_rx)(void*)); + void (*enable) (void); + void (*disable) (void); +// int (*save_state) (void*); +// void (*restore_state) (void*); + int (*read) (void); + int (*write) (u16 data); + int (*write_read) (u16 data); + void (*flush) (void); + void (*write_async) (void* pv, size_t cb); + size_t (*write_pos) (void); +}; + + /* These modes are only available on the LH79524 */ +#define SSP_MODE_SPI (1) +#define SSP_MODE_SSI (2) +#define SSP_MODE_MICROWIRE (3) +#define SSP_MODE_I2S (4) + + /* CPLD SPI devices */ +#define DEVICE_EEPROM 0 /* Configuration eeprom */ +#define DEVICE_MAC 1 /* MAC eeprom (LPD79524) */ +#define DEVICE_CODEC 2 /* Audio codec */ +#define DEVICE_TOUCH 3 /* Touch screen (LPD79520) */ + +/* ----- Globals */ + +/* ----- Prototypes */ + +//extern struct ssp_driver lh79520_i2s_driver; +extern struct ssp_driver lh7a400_cpld_ssp_driver; + +#endif /* __SSP_H__ */ diff --git a/include/asm-arm/arch-netx/debug-macro.S b/include/asm-arm/arch-netx/debug-macro.S new file mode 100644 index 000000000..a940d0e80 --- /dev/null +++ b/include/asm-arm/arch-netx/debug-macro.S @@ -0,0 +1,38 @@ +/* linux/include/asm-arm/arch-netx/debug-macro.S + * + * Debugging macro include header + * + * Copyright (C) 1994-1999 Russell King + * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include "hardware.h" + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + moveq \rx, #0x00100000 @ physical + movne \rx, #io_p2v(0x00100000) @ virtual + orr \rx, \rx, #0x00000a00 + .endm + + .macro senduart,rd,rx + str \rd, [\rx, #0] + .endm + + .macro busyuart,rd,rx +1002: ldr \rd, [\rx, #0x18] + tst \rd, #(1 << 3) + bne 1002b + .endm + + .macro waituart,rd,rx +1001: ldr \rd, [\rx, #0x18] + tst \rd, #(1 << 3) + bne 1001b + .endm diff --git a/include/asm-arm/arch-netx/dma.h b/include/asm-arm/arch-netx/dma.h new file mode 100644 index 000000000..4eda5feed --- /dev/null +++ b/include/asm-arm/arch-netx/dma.h @@ -0,0 +1,21 @@ +/* + * linux/include/asm-arm/arch-netx/dma.h + * + * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define MAX_DMA_CHANNELS 0 +#define MAX_DMA_ADDRESS ~0 diff --git a/include/asm-arm/arch-netx/entry-macro.S b/include/asm-arm/arch-netx/entry-macro.S new file mode 100644 index 000000000..658df4d60 --- /dev/null +++ b/include/asm-arm/arch-netx/entry-macro.S @@ -0,0 +1,35 @@ +/* + * include/asm-arm/arch-netx/entry-macro.S + * + * Low-level IRQ helper macros for Hilscher netX based platforms + * + * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <asm/hardware.h> + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + mov \base, #io_p2v(0x00100000) + add \base, \base, #0x000ff000 + + ldr \irqstat, [\base, #0] + clz \irqnr, \irqstat + rsb \irqnr, \irqnr, #31 + cmp \irqstat, #0 + .endm + diff --git a/include/asm-arm/arch-netx/eth.h b/include/asm-arm/arch-netx/eth.h new file mode 100644 index 000000000..643c90ef8 --- /dev/null +++ b/include/asm-arm/arch-netx/eth.h @@ -0,0 +1,27 @@ +/* + * include/asm-arm/arch-netx/eth.h + * + * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef ASMARM_ARCH_ETH_H +#define ASMARM_ARCH_ETH_H + +struct netxeth_platform_data { + unsigned int xcno; /* number of xmac/xpec engine this eth uses */ +}; + +#endif diff --git a/include/asm-arm/arch-netx/hardware.h b/include/asm-arm/arch-netx/hardware.h new file mode 100644 index 000000000..7786c4545 --- /dev/null +++ b/include/asm-arm/arch-netx/hardware.h @@ -0,0 +1,39 @@ +/* + * include/asm-arm/arch-netx/hardware.h + * + * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +#define NETX_IO_PHYS 0x00100000 +#define NETX_IO_VIRT 0xe0000000 +#define NETX_IO_SIZE 0x00100000 + +#define SRAM_INTERNAL_PHYS_0 0x00000 +#define SRAM_INTERNAL_PHYS_1 0x08000 +#define SRAM_INTERNAL_PHYS_2 0x10000 +#define SRAM_INTERNAL_PHYS_3 0x18000 +#define SRAM_INTERNAL_PHYS(no) ((no) * 0x8000) + +#define XPEC_MEM_SIZE 0x4000 +#define XMAC_MEM_SIZE 0x1000 +#define SRAM_MEM_SIZE 0x8000 + +#define io_p2v(x) ((x) - NETX_IO_PHYS + NETX_IO_VIRT) +#define io_v2p(x) ((x) - NETX_IO_VIRT + NETX_IO_PHYS) + +#endif diff --git a/include/asm-arm/arch-netx/io.h b/include/asm-arm/arch-netx/io.h new file mode 100644 index 000000000..a7a53f801 --- /dev/null +++ b/include/asm-arm/arch-netx/io.h @@ -0,0 +1,28 @@ +/* + * linux/include/asm-arm/arch-netx/io.h + * + * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +#define __io(a) ((void __iomem *)(a)) +#define __mem_pci(a) (a) + +#endif diff --git a/include/asm-arm/arch-netx/irqs.h b/include/asm-arm/arch-netx/irqs.h new file mode 100644 index 000000000..a487dc6e2 --- /dev/null +++ b/include/asm-arm/arch-netx/irqs.h @@ -0,0 +1,70 @@ +/* + * include/asm-arm/arch-netx/irqs.h + * + * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define NETX_IRQ_VIC_START 0 +#define NETX_IRQ_SOFTINT 0 +#define NETX_IRQ_TIMER0 1 +#define NETX_IRQ_TIMER1 2 +#define NETX_IRQ_TIMER2 3 +#define NETX_IRQ_SYSTIME_NS 4 +#define NETX_IRQ_SYSTIME_S 5 +#define NETX_IRQ_GPIO_15 6 +#define NETX_IRQ_WATCHDOG 7 +#define NETX_IRQ_UART0 8 +#define NETX_IRQ_UART1 9 +#define NETX_IRQ_UART2 10 +#define NETX_IRQ_USB 11 +#define NETX_IRQ_SPI 12 +#define NETX_IRQ_I2C 13 +#define NETX_IRQ_LCD 14 +#define NETX_IRQ_HIF 15 +#define NETX_IRQ_GPIO_0_14 16 +#define NETX_IRQ_XPEC0 17 +#define NETX_IRQ_XPEC1 18 +#define NETX_IRQ_XPEC2 19 +#define NETX_IRQ_XPEC3 20 +#define NETX_IRQ_XPEC(no) (17 + (no)) +#define NETX_IRQ_MSYNC0 21 +#define NETX_IRQ_MSYNC1 22 +#define NETX_IRQ_MSYNC2 23 +#define NETX_IRQ_MSYNC3 24 +#define NETX_IRQ_IRQ_PHY 25 +#define NETX_IRQ_ISO_AREA 26 +/* int 27 is reserved */ +/* int 28 is reserved */ +#define NETX_IRQ_TIMER3 29 +#define NETX_IRQ_TIMER4 30 +/* int 31 is reserved */ + +#define NETX_IRQS 32 + +/* for multiplexed irqs on gpio 0..14 */ +#define NETX_IRQ_GPIO(x) (NETX_IRQS + (x)) +#define NETX_IRQ_GPIO_LAST NETX_IRQ_GPIO(14) + +/* Host interface interrupts */ +#define NETX_IRQ_HIF_CHAINED(x) (NETX_IRQ_GPIO_LAST + 1 + (x)) +#define NETX_IRQ_HIF_PIO35 NETX_IRQ_HIF_CHAINED(0) +#define NETX_IRQ_HIF_PIO36 NETX_IRQ_HIF_CHAINED(1) +#define NETX_IRQ_HIF_PIO40 NETX_IRQ_HIF_CHAINED(2) +#define NETX_IRQ_HIF_PIO47 NETX_IRQ_HIF_CHAINED(3) +#define NETX_IRQ_HIF_PIO72 NETX_IRQ_HIF_CHAINED(4) +#define NETX_IRQ_HIF_LAST NETX_IRQ_HIF_CHAINED(4) + +#define NR_IRQS (NETX_IRQ_HIF_LAST + 1) diff --git a/include/asm-arm/arch-netx/memory.h b/include/asm-arm/arch-netx/memory.h new file mode 100644 index 000000000..6d8d2df3e --- /dev/null +++ b/include/asm-arm/arch-netx/memory.h @@ -0,0 +1,36 @@ +/* + * linux/include/asm-arm/arch-netx/memory.h + * + * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +#define PHYS_OFFSET UL(0x80000000) + +/* + * Virtual view <-> DMA view memory address translations + * virt_to_bus: Used to translate the virtual address to an + * address suitable to be passed to set_dma_addr + * bus_to_virt: Used to convert an address for DMA operations + * to an address that the kernel can use. + */ +#define __virt_to_bus(x) __virt_to_phys(x) +#define __bus_to_virt(x) __phys_to_virt(x) + +#endif + diff --git a/include/asm-arm/arch-netx/netx-regs.h b/include/asm-arm/arch-netx/netx-regs.h new file mode 100644 index 000000000..8ab45bea8 --- /dev/null +++ b/include/asm-arm/arch-netx/netx-regs.h @@ -0,0 +1,410 @@ +/* + * include/asm-arm/arch-netx/netx-regs.h + * + * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ASM_ARCH_NETX_REGS_H +#define __ASM_ARCH_NETX_REGS_H + +/* offsets relative to the beginning of the io space */ +#define NETX_OFS_SYSTEM 0x00000 +#define NETX_OFS_MEMCR 0x00100 +#define NETX_OFS_DPMAS 0x03000 +#define NETX_OFS_GPIO 0x00800 +#define NETX_OFS_PIO 0x00900 +#define NETX_OFS_UART0 0x00a00 +#define NETX_OFS_UART1 0x00a40 +#define NETX_OFS_UART2 0x00a80 +#define NETX_OF_MIIMU 0x00b00 +#define NETX_OFS_SPI 0x00c00 +#define NETX_OFS_I2C 0x00d00 +#define NETX_OFS_SYSTIME 0x01100 +#define NETX_OFS_RTC 0x01200 +#define NETX_OFS_EXTBUS 0x03600 +#define NETX_OFS_LCD 0x04000 +#define NETX_OFS_USB 0x20000 +#define NETX_OFS_XMAC0 0x60000 +#define NETX_OFS_XMAC1 0x61000 +#define NETX_OFS_XMAC2 0x62000 +#define NETX_OFS_XMAC3 0x63000 +#define NETX_OFS_XMAC(no) (0x60000 + (no) * 0x1000) +#define NETX_OFS_PFIFO 0x64000 +#define NETX_OFS_XPEC0 0x70000 +#define NETX_OFS_XPEC1 0x74000 +#define NETX_OFS_XPEC2 0x78000 +#define NETX_OFS_XPEC3 0x7c000 +#define NETX_OFS_XPEC(no) (0x70000 + (no) * 0x4000) +#define NETX_OFS_VIC 0xff000 + +/* physical addresses */ +#define NETX_PA_SYSTEM (NETX_IO_PHYS + NETX_OFS_SYSTEM) +#define NETX_PA_MEMCR (NETX_IO_PHYS + NETX_OFS_MEMCR) +#define NETX_PA_DPMAS (NETX_IO_PHYS + NETX_OFS_DPMAS) +#define NETX_PA_GPIO (NETX_IO_PHYS + NETX_OFS_GPIO) +#define NETX_PA_PIO (NETX_IO_PHYS + NETX_OFS_PIO) +#define NETX_PA_UART0 (NETX_IO_PHYS + NETX_OFS_UART0) +#define NETX_PA_UART1 (NETX_IO_PHYS + NETX_OFS_UART1) +#define NETX_PA_UART2 (NETX_IO_PHYS + NETX_OFS_UART2) +#define NETX_PA_MIIMU (NETX_IO_PHYS + NETX_OF_MIIMU) +#define NETX_PA_SPI (NETX_IO_PHYS + NETX_OFS_SPI) +#define NETX_PA_I2C (NETX_IO_PHYS + NETX_OFS_I2C) +#define NETX_PA_SYSTIME (NETX_IO_PHYS + NETX_OFS_SYSTIME) +#define NETX_PA_RTC (NETX_IO_PHYS + NETX_OFS_RTC) +#define NETX_PA_EXTBUS (NETX_IO_PHYS + NETX_OFS_EXTBUS) +#define NETX_PA_LCD (NETX_IO_PHYS + NETX_OFS_LCD) +#define NETX_PA_USB (NETX_IO_PHYS + NETX_OFS_USB) +#define NETX_PA_XMAC0 (NETX_IO_PHYS + NETX_OFS_XMAC0) +#define NETX_PA_XMAC1 (NETX_IO_PHYS + NETX_OFS_XMAC1) +#define NETX_PA_XMAC2 (NETX_IO_PHYS + NETX_OFS_XMAC2) +#define NETX_PA_XMAC3 (NETX_IO_PHYS + NETX_OFS_XMAC3) +#define NETX_PA_XMAC(no) (NETX_IO_PHYS + NETX_OFS_XMAC(no)) +#define NETX_PA_PFIFO (NETX_IO_PHYS + NETX_OFS_PFIFO) +#define NETX_PA_XPEC0 (NETX_IO_PHYS + NETX_OFS_XPEC0) +#define NETX_PA_XPEC1 (NETX_IO_PHYS + NETX_OFS_XPEC1) +#define NETX_PA_XPEC2 (NETX_IO_PHYS + NETX_OFS_XPEC2) +#define NETX_PA_XPEC3 (NETX_IO_PHYS + NETX_OFS_XPEC3) +#define NETX_PA_XPEC(no) (NETX_IO_PHYS + NETX_OFS_XPEC(no)) +#define NETX_PA_VIC (NETX_IO_PHYS + NETX_OFS_VIC) + +/* virual addresses */ +#define NETX_VA_SYSTEM (NETX_IO_VIRT + NETX_OFS_SYSTEM) +#define NETX_VA_MEMCR (NETX_IO_VIRT + NETX_OFS_MEMCR) +#define NETX_VA_DPMAS (NETX_IO_VIRT + NETX_OFS_DPMAS) +#define NETX_VA_GPIO (NETX_IO_VIRT + NETX_OFS_GPIO) +#define NETX_VA_PIO (NETX_IO_VIRT + NETX_OFS_PIO) +#define NETX_VA_UART0 (NETX_IO_VIRT + NETX_OFS_UART0) +#define NETX_VA_UART1 (NETX_IO_VIRT + NETX_OFS_UART1) +#define NETX_VA_UART2 (NETX_IO_VIRT + NETX_OFS_UART2) +#define NETX_VA_MIIMU (NETX_IO_VIRT + NETX_OF_MIIMU) +#define NETX_VA_SPI (NETX_IO_VIRT + NETX_OFS_SPI) +#define NETX_VA_I2C (NETX_IO_VIRT + NETX_OFS_I2C) +#define NETX_VA_SYSTIME (NETX_IO_VIRT + NETX_OFS_SYSTIME) +#define NETX_VA_RTC (NETX_IO_VIRT + NETX_OFS_RTC) +#define NETX_VA_EXTBUS (NETX_IO_VIRT + NETX_OFS_EXTBUS) +#define NETX_VA_LCD (NETX_IO_VIRT + NETX_OFS_LCD) +#define NETX_VA_USB (NETX_IO_VIRT + NETX_OFS_USB) +#define NETX_VA_XMAC0 (NETX_IO_VIRT + NETX_OFS_XMAC0) +#define NETX_VA_XMAC1 (NETX_IO_VIRT + NETX_OFS_XMAC1) +#define NETX_VA_XMAC2 (NETX_IO_VIRT + NETX_OFS_XMAC2) +#define NETX_VA_XMAC3 (NETX_IO_VIRT + NETX_OFS_XMAC3) +#define NETX_VA_XMAC(no) (NETX_IO_VIRT + NETX_OFS_XMAC(no)) +#define NETX_VA_PFIFO (NETX_IO_VIRT + NETX_OFS_PFIFO) +#define NETX_VA_XPEC0 (NETX_IO_VIRT + NETX_OFS_XPEC0) +#define NETX_VA_XPEC1 (NETX_IO_VIRT + NETX_OFS_XPEC1) +#define NETX_VA_XPEC2 (NETX_IO_VIRT + NETX_OFS_XPEC2) +#define NETX_VA_XPEC3 (NETX_IO_VIRT + NETX_OFS_XPEC3) +#define NETX_VA_XPEC(no) (NETX_IO_VIRT + NETX_OFS_XPEC(no)) +#define NETX_VA_VIC (NETX_IO_VIRT + NETX_OFS_VIC) + +/********************************* + * System functions * + *********************************/ + +/* Registers */ +#define NETX_SYSTEM_REG(ofs) __io(NETX_VA_SYSTEM + (ofs)) +#define NETX_SYSTEM_BOO_SR NETX_SYSTEM_REG(0x00) +#define NETX_SYSTEM_IOC_CR NETX_SYSTEM_REG(0x04) +#define NETX_SYSTEM_IOC_MR NETX_SYSTEM_REG(0x08) + +/* FIXME: Docs are not consistent */ +#define NETX_SYSTEM_RES_CR NETX_SYSTEM_REG(0x08) +/* #define NETX_SYSTEM_RES_CR NETX_SYSTEM_REG(0x0c) */ + +#define NETX_SYSTEM_PHY_CONTROL NETX_SYSTEM_REG(0x10) +#define NETX_SYSTEM_REV NETX_SYSTEM_REG(0x34) +#define NETX_SYSTEM_IOC_ACCESS_KEY NETX_SYSTEM_REG(0x70) +#define NETX_SYSTEM_WDG_TR NETX_SYSTEM_REG(0x200) +#define NETX_SYSTEM_WDG_CTR NETX_SYSTEM_REG(0x204) +#define NETX_SYSTEM_WDG_IRQ_TIMEOUT NETX_SYSTEM_REG(0x208) +#define NETX_SYSTEM_WDG_RES_TIMEOUT NETX_SYSTEM_REG(0x20c) + +/* Bits */ +#define NETX_SYSTEM_RES_CR_RSTIN (1<<0) +#define NETX_SYSTEM_RES_CR_WDG_RES (1<<1) +#define NETX_SYSTEM_RES_CR_HOST_RES (1<<2) +#define NETX_SYSTEM_RES_CR_FIRMW_RES (1<<3) +#define NETX_SYSTEM_RES_CR_XPEC0_RES (1<<4) +#define NETX_SYSTEM_RES_CR_XPEC1_RES (1<<5) +#define NETX_SYSTEM_RES_CR_XPEC2_RES (1<<6) +#define NETX_SYSTEM_RES_CR_XPEC3_RES (1<<7) +#define NETX_SYSTEM_RES_CR_DIS_XPEC0_RES (1<<16) +#define NETX_SYSTEM_RES_CR_DIS_XPEC1_RES (1<<17) +#define NETX_SYSTEM_RES_CR_DIS_XPEC2_RES (1<<18) +#define NETX_SYSTEM_RES_CR_DIS_XPEC3_RES (1<<19) +#define NETX_SYSTEM_RES_CR_FIRMW_FLG0 (1<<20) +#define NETX_SYSTEM_RES_CR_FIRMW_FLG1 (1<<21) +#define NETX_SYSTEM_RES_CR_FIRMW_FLG2 (1<<22) +#define NETX_SYSTEM_RES_CR_FIRMW_FLG3 (1<<23) +#define NETX_SYSTEM_RES_CR_FIRMW_RES_EN (1<<24) +#define NETX_SYSTEM_RES_CR_RSTOUT (1<<25) +#define NETX_SYSTEM_RES_CR_EN_RSTOUT (1<<26) + +#define PHY_CONTROL_RESET (1<<31) +#define PHY_CONTROL_SIM_BYP (1<<30) +#define PHY_CONTROL_CLK_XLATIN (1<<29) +#define PHY_CONTROL_PHY1_EN (1<<21) +#define PHY_CONTROL_PHY1_NP_MSG_CODE +#define PHY_CONTROL_PHY1_AUTOMDIX (1<<17) +#define PHY_CONTROL_PHY1_FIXMODE (1<<16) +#define PHY_CONTROL_PHY1_MODE(mode) (((mode) & 0x7) << 13) +#define PHY_CONTROL_PHY0_EN (1<<12) +#define PHY_CONTROL_PHY0_NP_MSG_CODE +#define PHY_CONTROL_PHY0_AUTOMDIX (1<<8) +#define PHY_CONTROL_PHY0_FIXMODE (1<<7) +#define PHY_CONTROL_PHY0_MODE(mode) (((mode) & 0x7) << 4) +#define PHY_CONTROL_PHY_ADDRESS(adr) ((adr) & 0xf) + +#define PHY_MODE_10BASE_T_HALF 0 +#define PHY_MODE_10BASE_T_FULL 1 +#define PHY_MODE_100BASE_TX_FX_FULL 2 +#define PHY_MODE_100BASE_TX_FX_HALF 3 +#define PHY_MODE_100BASE_TX_HALF 4 +#define PHY_MODE_REPEATER 5 +#define PHY_MODE_POWER_DOWN 6 +#define PHY_MODE_ALL 7 + +/* Bits */ +#define VECT_CNTL_ENABLE (1 << 5) + +/******************************* + * GPIO and timer module * + *******************************/ + +/* Registers */ +#define NETX_GPIO_REG(ofs) __io(NETX_VA_GPIO + (ofs)) +#define NETX_GPIO_CFG(gpio) NETX_GPIO_REG(0x0 + ((gpio)<<2)) +#define NETX_GPIO_THRESHOLD_CAPTURE(gpio) NETX_GPIO_REG(0x40 + ((gpio)<<2)) +#define NETX_GPIO_COUNTER_CTRL(counter) NETX_GPIO_REG(0x80 + ((counter)<<2)) +#define NETX_GPIO_COUNTER_MAX(counter) NETX_GPIO_REG(0x94 + ((counter)<<2)) +#define NETX_GPIO_COUNTER_CURRENT(counter) NETX_GPIO_REG(0xa8 + ((counter)<<2)) +#define NETX_GPIO_IRQ_ENABLE NETX_GPIO_REG(0xbc) +#define NETX_GPIO_IRQ_DISABLE NETX_GPIO_REG(0xc0) +#define NETX_GPIO_SYSTIME_NS_CMP NETX_GPIO_REG(0xc4) +#define NETX_GPIO_LINE NETX_GPIO_REG(0xc8) +#define NETX_GPIO_IRQ NETX_GPIO_REG(0xd0) + +/* Bits */ +#define NETX_GPIO_CFG_IOCFG_GP_INPUT (0x0) +#define NETX_GPIO_CFG_IOCFG_GP_OUTPUT (0x1) +#define NETX_GPIO_CFG_IOCFG_GP_UART (0x2) +#define NETX_GPIO_CFG_INV (1<<2) +#define NETX_GPIO_CFG_MODE_INPUT_READ (0<<3) +#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_CONT_RISING (1<<3) +#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_ONCE_RISING (2<<3) +#define NETX_GPIO_CFG_MODE_INPUT_CAPTURE_HIGH_LEVEL (3<<3) +#define NETX_GPIO_CFG_COUNT_REF_COUNTER0 (0<<5) +#define NETX_GPIO_CFG_COUNT_REF_COUNTER1 (1<<5) +#define NETX_GPIO_CFG_COUNT_REF_COUNTER2 (2<<5) +#define NETX_GPIO_CFG_COUNT_REF_COUNTER3 (3<<5) +#define NETX_GPIO_CFG_COUNT_REF_COUNTER4 (4<<5) +#define NETX_GPIO_CFG_COUNT_REF_SYSTIME (7<<5) + +#define NETX_GPIO_COUNTER_CTRL_RUN (1<<0) +#define NETX_GPIO_COUNTER_CTRL_SYM (1<<1) +#define NETX_GPIO_COUNTER_CTRL_ONCE (1<<2) +#define NETX_GPIO_COUNTER_CTRL_IRQ_EN (1<<3) +#define NETX_GPIO_COUNTER_CTRL_CNT_EVENT (1<<4) +#define NETX_GPIO_COUNTER_CTRL_RST_EN (1<<5) +#define NETX_GPIO_COUNTER_CTRL_SEL_EVENT (1<<6) +#define NETX_GPIO_COUNTER_CTRL_GPIO_REF /* FIXME */ + +#define GPIO_BIT(gpio) (1<<(gpio)) +#define COUNTER_BIT(counter) ((1<<16)<<(counter)) + +/******************************* + * PIO * + *******************************/ + +/* Registers */ +#define NETX_PIO_REG(ofs) __io(NETX_VA_PIO + (ofs)) +#define NETX_PIO_INPIO NETX_PIO_REG(0x0) +#define NETX_PIO_OUTPIO NETX_PIO_REG(0x4) +#define NETX_PIO_OEPIO NETX_PIO_REG(0x8) + +/******************************* + * MII Unit * + *******************************/ + +/* Registers */ +#define NETX_MIIMU __io(NETX_VA_MIIMU) + +/* Bits */ +#define MIIMU_SNRDY (1<<0) +#define MIIMU_PREAMBLE (1<<1) +#define MIIMU_OPMODE_WRITE (1<<2) +#define MIIMU_MDC_PERIOD (1<<3) +#define MIIMU_PHY_NRES (1<<4) +#define MIIMU_RTA (1<<5) +#define MIIMU_REGADDR(adr) (((adr) & 0x1f) << 6) +#define MIIMU_PHYADDR(adr) (((adr) & 0x1f) << 11) +#define MIIMU_DATA(data) (((data) & 0xffff) << 16) + +/******************************* + * xmac / xpec * + *******************************/ + +/* XPEC register offsets relative to NETX_VA_XPEC(no) */ +#define NETX_XPEC_R0_OFS 0x00 +#define NETX_XPEC_R1_OFS 0x04 +#define NETX_XPEC_R2_OFS 0x08 +#define NETX_XPEC_R3_OFS 0x0c +#define NETX_XPEC_R4_OFS 0x10 +#define NETX_XPEC_R5_OFS 0x14 +#define NETX_XPEC_R6_OFS 0x18 +#define NETX_XPEC_R7_OFS 0x1c +#define NETX_XPEC_RANGE01_OFS 0x20 +#define NETX_XPEC_RANGE23_OFS 0x24 +#define NETX_XPEC_RANGE45_OFS 0x28 +#define NETX_XPEC_RANGE67_OFS 0x2c +#define NETX_XPEC_PC_OFS 0x48 +#define NETX_XPEC_TIMER_OFS(timer) (0x30 + ((timer)<<2)) +#define NETX_XPEC_IRQ_OFS 0x8c +#define NETX_XPEC_SYSTIME_NS_OFS 0x90 +#define NETX_XPEC_FIFO_DATA_OFS 0x94 +#define NETX_XPEC_SYSTIME_S_OFS 0x98 +#define NETX_XPEC_ADC_OFS 0x9c +#define NETX_XPEC_URX_COUNT_OFS 0x40 +#define NETX_XPEC_UTX_COUNT_OFS 0x44 +#define NETX_XPEC_PC_OFS 0x48 +#define NETX_XPEC_ZERO_OFS 0x4c +#define NETX_XPEC_STATCFG_OFS 0x50 +#define NETX_XPEC_EC_MASKA_OFS 0x54 +#define NETX_XPEC_EC_MASKB_OFS 0x58 +#define NETX_XPEC_EC_MASK0_OFS 0x5c +#define NETX_XPEC_EC_MASK8_OFS 0x7c +#define NETX_XPEC_EC_MASK9_OFS 0x80 +#define NETX_XPEC_XPU_HOLD_PC_OFS 0x100 +#define NETX_XPEC_RAM_START_OFS 0x2000 + +/* Bits */ +#define XPU_HOLD_PC (1<<0) + +/* XMAC register offsets relative to NETX_VA_XMAC(no) */ +#define NETX_XMAC_RPU_PROGRAM_START_OFS 0x000 +#define NETX_XMAC_RPU_PROGRAM_END_OFS 0x3ff +#define NETX_XMAC_TPU_PROGRAM_START_OFS 0x400 +#define NETX_XMAC_TPU_PROGRAM_END_OFS 0x7ff +#define NETX_XMAC_RPU_HOLD_PC_OFS 0xa00 +#define NETX_XMAC_TPU_HOLD_PC_OFS 0xa04 +#define NETX_XMAC_STATUS_SHARED0_OFS 0x840 +#define NETX_XMAC_CONFIG_SHARED0_OFS 0x844 +#define NETX_XMAC_STATUS_SHARED1_OFS 0x848 +#define NETX_XMAC_CONFIG_SHARED1_OFS 0x84c +#define NETX_XMAC_STATUS_SHARED2_OFS 0x850 +#define NETX_XMAC_CONFIG_SHARED2_OFS 0x854 +#define NETX_XMAC_STATUS_SHARED3_OFS 0x858 +#define NETX_XMAC_CONFIG_SHARED3_OFS 0x85c + +#define RPU_HOLD_PC (1<<15) +#define TPU_HOLD_PC (1<<15) + +/******************************* + * Pointer FIFO * + *******************************/ + +/* Registers */ +#define NETX_PFIFO_REG(ofs) __io(NETX_VA_PFIFO + (ofs)) +#define NETX_PFIFO_BASE(pfifo) NETX_PFIFO_REG(0x00 + ((pfifo)<<2)) +#define NETX_PFIFO_BORDER_BASE(pfifo) NETX_PFIFO_REG(0x80 + ((pfifo)<<2)) +#define NETX_PFIFO_RESET NETX_PFIFO_REG(0x100) +#define NETX_PFIFO_FULL NETX_PFIFO_REG(0x104) +#define NETX_PFIFO_EMPTY NETX_PFIFO_REG(0x108) +#define NETX_PFIFO_OVEFLOW NETX_PFIFO_REG(0x10c) +#define NETX_PFIFO_UNDERRUN NETX_PFIFO_REG(0x110) +#define NETX_PFIFO_FILL_LEVEL(pfifo) NETX_PFIFO_REG(0x180 + ((pfifo)<<2)) +#define NETX_PFIFO_XPEC_ISR(xpec) NETX_PFIFO_REG(0x400 + ((xpec) << 2)) + +/******************************* + * Dual Port Memory * + *******************************/ + +/* Registers */ +#define NETX_DPMAS_REG(ofs) __io(NETX_VA_DPMAS + (ofs)) +#define NETX_DPMAS_SYS_STAT NETX_DPMAS_REG(0x4d8) +#define NETX_DPMAS_INT_STAT NETX_DPMAS_REG(0x4e0) +#define NETX_DPMAS_INT_EN NETX_DPMAS_REG(0x4f0) +#define NETX_DPMAS_IF_CONF0 NETX_DPMAS_REG(0x608) +#define NETX_DPMAS_IF_CONF1 NETX_DPMAS_REG(0x60c) +#define NETX_DPMAS_EXT_CONFIG(cs) NETX_DPMAS_REG(0x610 + 4 * (cs)) +#define NETX_DPMAS_IO_MODE0 NETX_DPMAS_REG(0x620) /* I/O 32..63 */ +#define NETX_DPMAS_DRV_EN0 NETX_DPMAS_REG(0x624) +#define NETX_DPMAS_DATA0 NETX_DPMAS_REG(0x628) +#define NETX_DPMAS_IO_MODE1 NETX_DPMAS_REG(0x630) /* I/O 64..84 */ +#define NETX_DPMAS_DRV_EN1 NETX_DPMAS_REG(0x634) +#define NETX_DPMAS_DATA1 NETX_DPMAS_REG(0x638) + +/* Bits */ +#define NETX_DPMAS_INT_EN_GLB_EN (1<<31) +#define NETX_DPMAS_INT_EN_MEM_LCK (1<<30) +#define NETX_DPMAS_INT_EN_WDG (1<<29) +#define NETX_DPMAS_INT_EN_PIO72 (1<<28) +#define NETX_DPMAS_INT_EN_PIO47 (1<<27) +#define NETX_DPMAS_INT_EN_PIO40 (1<<26) +#define NETX_DPMAS_INT_EN_PIO36 (1<<25) +#define NETX_DPMAS_INT_EN_PIO35 (1<<24) + +#define NETX_DPMAS_IF_CONF0_HIF_DISABLED (0<<28) +#define NETX_DPMAS_IF_CONF0_HIF_EXT_BUS (1<<28) +#define NETX_DPMAS_IF_CONF0_HIF_UP_8BIT (2<<28) +#define NETX_DPMAS_IF_CONF0_HIF_UP_16BIT (3<<28) +#define NETX_DPMAS_IF_CONF0_HIF_IO (4<<28) +#define NETX_DPMAS_IF_CONF0_WAIT_DRV_PP (1<<14) +#define NETX_DPMAS_IF_CONF0_WAIT_DRV_OD (2<<14) +#define NETX_DPMAS_IF_CONF0_WAIT_DRV_TRI (3<<14) + +#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO35 (1<<26) +#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO36 (1<<27) +#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO40 (1<<28) +#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO47 (1<<29) +#define NETX_DPMAS_IF_CONF1_IRQ_POL_PIO72 (1<<30) + +#define NETX_EXT_CONFIG_TALEWIDTH(x) (((x) & 0x7) << 29) +#define NETX_EXT_CONFIG_TADRHOLD(x) (((x) & 0x7) << 26) +#define NETX_EXT_CONFIG_TCSON(x) (((x) & 0x7) << 23) +#define NETX_EXT_CONFIG_TRDON(x) (((x) & 0x7) << 20) +#define NETX_EXT_CONFIG_TWRON(x) (((x) & 0x7) << 17) +#define NETX_EXT_CONFIG_TWROFF(x) (((x) & 0x1f) << 12) +#define NETX_EXT_CONFIG_TRDWRCYC(x) (((x) & 0x1f) << 7) +#define NETX_EXT_CONFIG_WAIT_POL (1<<6) +#define NETX_EXT_CONFIG_WAIT_EN (1<<5) +#define NETX_EXT_CONFIG_NRD_MODE (1<<4) +#define NETX_EXT_CONFIG_DS_MODE (1<<3) +#define NETX_EXT_CONFIG_NWR_MODE (1<<2) +#define NETX_EXT_CONFIG_16BIT (1<<1) +#define NETX_EXT_CONFIG_CS_ENABLE (1<<0) + +#define NETX_DPMAS_IO_MODE0_WRL (1<<13) +#define NETX_DPMAS_IO_MODE0_WAIT (1<<14) +#define NETX_DPMAS_IO_MODE0_READY (1<<15) +#define NETX_DPMAS_IO_MODE0_CS0 (1<<19) +#define NETX_DPMAS_IO_MODE0_EXTRD (1<<20) + +#define NETX_DPMAS_IO_MODE1_CS2 (1<<15) +#define NETX_DPMAS_IO_MODE1_CS1 (1<<16) +#define NETX_DPMAS_IO_MODE1_SAMPLE_NPOR (0<<30) +#define NETX_DPMAS_IO_MODE1_SAMPLE_100MHZ (1<<30) +#define NETX_DPMAS_IO_MODE1_SAMPLE_NPIO36 (2<<30) +#define NETX_DPMAS_IO_MODE1_SAMPLE_PIO36 (3<<30) + +/******************************* + * I2C * + *******************************/ +#define NETX_I2C_REG(ofs) __io(NETX_VA_I2C, (ofs)) +#define NETX_I2C_CTRL NETX_I2C_REG(0x0) +#define NETX_I2C_DATA NETX_I2C_REG(0x4) + +#endif /* __ASM_ARCH_NETX_REGS_H */ diff --git a/include/asm-arm/arch-netx/param.h b/include/asm-arm/arch-netx/param.h new file mode 100644 index 000000000..7a80c2617 --- /dev/null +++ b/include/asm-arm/arch-netx/param.h @@ -0,0 +1,18 @@ +/* + * linux/include/asm-arm/arch-netx/param.h + * + * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ diff --git a/include/asm-arm/arch-netx/pfifo.h b/include/asm-arm/arch-netx/pfifo.h new file mode 100644 index 000000000..4af2ee4a3 --- /dev/null +++ b/include/asm-arm/arch-netx/pfifo.h @@ -0,0 +1,54 @@ +/* + * include/asm-arm/arch-netx/pfifo.h + * + * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef ASM_ARCH_PFIFO_H +#define ASM_ARCH_PFIFO_H + +static inline int pfifo_push(int no, unsigned int pointer) +{ + writel(pointer, NETX_PFIFO_BASE(no)); + return 0; +} + +static inline unsigned int pfifo_pop(int no) +{ + return readl(NETX_PFIFO_BASE(no)); +} + +static inline int pfifo_fill_level(int no) +{ + + return readl(NETX_PFIFO_FILL_LEVEL(no)); +} + +static inline int pfifo_full(int no) +{ + return readl(NETX_PFIFO_FULL) & (1<<no) ? 1 : 0; +} + +static inline int pfifo_empty(int no) +{ + return readl(NETX_PFIFO_EMPTY) & (1<<no) ? 1 : 0; +} + +int pfifo_request(unsigned int pfifo_mask); +void pfifo_free(unsigned int pfifo_mask); + +#endif /* ASM_ARCH_PFIFO_H */ diff --git a/include/asm-arm/arch-netx/system.h b/include/asm-arm/arch-netx/system.h new file mode 100644 index 000000000..52adf368d --- /dev/null +++ b/include/asm-arm/arch-netx/system.h @@ -0,0 +1,38 @@ +/* + * include/asm-arm/arch-netx/system.h + * + * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +#include <asm/io.h> +#include <asm/hardware.h> +#include "netx-regs.h" + +static inline void arch_idle(void) +{ + cpu_do_idle(); +} + +static inline void arch_reset(char mode) +{ + writel(NETX_SYSTEM_RES_CR_FIRMW_RES_EN | NETX_SYSTEM_RES_CR_FIRMW_RES, + NETX_SYSTEM_RES_CR); +} + +#endif + diff --git a/include/asm-arm/arch-netx/timex.h b/include/asm-arm/arch-netx/timex.h new file mode 100644 index 000000000..7fdb42da0 --- /dev/null +++ b/include/asm-arm/arch-netx/timex.h @@ -0,0 +1,20 @@ +/* + * include/asm-arm/arch-netx/timex.h + * + * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define CLOCK_TICK_RATE 100000000 diff --git a/include/asm-arm/arch-netx/uncompress.h b/include/asm-arm/arch-netx/uncompress.h new file mode 100644 index 000000000..f89434547 --- /dev/null +++ b/include/asm-arm/arch-netx/uncompress.h @@ -0,0 +1,76 @@ +/* + * include/asm-arm/arch-netx/uncompress.h + * + * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * The following code assumes the serial port has already been + * initialized by the bootloader. We search for the first enabled + * port in the most probable order. If you didn't setup a port in + * your bootloader then nothing will appear (which might be desired). + * + * This does not append a newline + */ + +#define REG(x) (*(volatile unsigned long *)(x)) + +#define UART1_BASE 0x100a00 +#define UART2_BASE 0x100a80 + +#define UART_DR 0x0 + +#define UART_CR 0x14 +#define CR_UART_EN (1<<0) + +#define UART_FR 0x18 +#define FR_BUSY (1<<3) +#define FR_TXFF (1<<5) + +static void putc(char c) +{ + unsigned long base; + + if (REG(UART1_BASE + UART_CR) & CR_UART_EN) + base = UART1_BASE; + else if (REG(UART2_BASE + UART_CR) & CR_UART_EN) + base = UART2_BASE; + else + return; + + while (REG(base + UART_FR) & FR_TXFF); + REG(base + UART_DR) = c; +} + +static inline void flush(void) +{ + unsigned long base; + + if (REG(UART1_BASE + UART_CR) & CR_UART_EN) + base = UART1_BASE; + else if (REG(UART2_BASE + UART_CR) & CR_UART_EN) + base = UART2_BASE; + else + return; + + while (REG(base + UART_FR) & FR_BUSY); +} + +/* + * nothing to do + */ +#define arch_decomp_setup() +#define arch_decomp_wdog() diff --git a/include/asm-arm/arch-netx/vmalloc.h b/include/asm-arm/arch-netx/vmalloc.h new file mode 100644 index 000000000..da2da5a59 --- /dev/null +++ b/include/asm-arm/arch-netx/vmalloc.h @@ -0,0 +1,19 @@ +/* + * linux/include/asm-arm/arch-netx/vmalloc.h + * + * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#define VMALLOC_END (PAGE_OFFSET + 0x10000000) diff --git a/include/asm-arm/arch-netx/xc.h b/include/asm-arm/arch-netx/xc.h new file mode 100644 index 000000000..659af1951 --- /dev/null +++ b/include/asm-arm/arch-netx/xc.h @@ -0,0 +1,42 @@ +/* + * linux/include/asm-arm/arch-netx/xc.h + * + * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __ASM_ARCH_XC_H +#define __ASM_ARCH_XC_H + +struct xc { + int no; + unsigned int type; + unsigned int version; + void __iomem *xpec_base; + void __iomem *xmac_base; + void __iomem *sram_base; + int irq; + struct device *dev; +}; + +int xc_reset(struct xc *x); +int xc_stop(struct xc* x); +int xc_start(struct xc *x); +int xc_running(struct xc *x); +int xc_request_firmware(struct xc* x); +struct xc* request_xc(int xcno, struct device *dev); +void free_xc(struct xc *x); + +#endif /* __ASM_ARCH_XC_H */ diff --git a/include/asm-arm/arch-omap/board-fsample.h b/include/asm-arm/arch-omap/board-fsample.h new file mode 100644 index 000000000..89a1e529f --- /dev/null +++ b/include/asm-arm/arch-omap/board-fsample.h @@ -0,0 +1,51 @@ +/* + * linux/include/asm-arm/arch-omap/board-fsample.h + * + * Board-specific goodies for TI F-Sample. + * + * Copyright (C) 2006 Google, Inc. + * Author: Brian Swetland <swetland@google.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_ARCH_OMAP_FSAMPLE_H +#define __ASM_ARCH_OMAP_FSAMPLE_H + +/* fsample is pretty close to p2-sample */ +#include <asm/arch/board-perseus2.h> + +#define fsample_cpld_read(reg) __raw_readb(reg) +#define fsample_cpld_write(val, reg) __raw_writeb(val, reg) + +#define FSAMPLE_CPLD_BASE 0xE8100000 +#define FSAMPLE_CPLD_SIZE SZ_4K +#define FSAMPLE_CPLD_START 0x05080000 + +#define FSAMPLE_CPLD_REG_A (FSAMPLE_CPLD_BASE + 0x00) +#define FSAMPLE_CPLD_SWITCH (FSAMPLE_CPLD_BASE + 0x02) +#define FSAMPLE_CPLD_UART (FSAMPLE_CPLD_BASE + 0x02) +#define FSAMPLE_CPLD_REG_B (FSAMPLE_CPLD_BASE + 0x04) +#define FSAMPLE_CPLD_VERSION (FSAMPLE_CPLD_BASE + 0x06) +#define FSAMPLE_CPLD_SET_CLR (FSAMPLE_CPLD_BASE + 0x06) + +#define FSAMPLE_CPLD_BIT_BT_RESET 0 +#define FSAMPLE_CPLD_BIT_LCD_RESET 1 +#define FSAMPLE_CPLD_BIT_CAM_PWDN 2 +#define FSAMPLE_CPLD_BIT_CHARGER_ENABLE 3 +#define FSAMPLE_CPLD_BIT_SD_MMC_EN 4 +#define FSAMPLE_CPLD_BIT_aGPS_PWREN 5 +#define FSAMPLE_CPLD_BIT_BACKLIGHT 6 +#define FSAMPLE_CPLD_BIT_aGPS_EN_RESET 7 +#define FSAMPLE_CPLD_BIT_aGPS_SLEEPx_N 8 +#define FSAMPLE_CPLD_BIT_OTG_RESET 9 + +#define fsample_cpld_set(bit) \ + fsample_cpld_write((((bit) & 15) << 4) | 0x0f, FSAMPLE_CPLD_SET_CLR) + +#define fsample_cpld_clear(bit) \ + fsample_cpld_write(0xf0 | ((bit) & 15), FSAMPLE_CPLD_SET_CLR) + +#endif diff --git a/include/asm-arm/arch-omap/gpmc.h b/include/asm-arm/arch-omap/gpmc.h new file mode 100644 index 000000000..1a0a52078 --- /dev/null +++ b/include/asm-arm/arch-omap/gpmc.h @@ -0,0 +1,91 @@ +/* + * General-Purpose Memory Controller for OMAP2 + * + * Copyright (C) 2005-2006 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __OMAP2_GPMC_H +#define __OMAP2_GPMC_H + +#define GPMC_CS_CONFIG1 0x00 +#define GPMC_CS_CONFIG2 0x04 +#define GPMC_CS_CONFIG3 0x08 +#define GPMC_CS_CONFIG4 0x0c +#define GPMC_CS_CONFIG5 0x10 +#define GPMC_CS_CONFIG6 0x14 +#define GPMC_CS_CONFIG7 0x18 +#define GPMC_CS_NAND_COMMAND 0x1c +#define GPMC_CS_NAND_ADDRESS 0x20 +#define GPMC_CS_NAND_DATA 0x24 + +#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) +#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 20) +#define GPMC_CONFIG1_READTYPE_ASYNC (0 << 29) +#define GPMC_CONFIG1_READTYPE_SYNC (1 << 29) +#define GPMC_CONFIG1_WRITETYPE_ASYNC (0 << 27) +#define GPMC_CONFIG1_WRITETYPE_SYNC (1 << 27) +#define GPMC_CONFIG1_CLKACTIVATIONTIME(val) ((val & 3) << 25) +#define GPMC_CONFIG1_PAGE_LEN(val) ((val & 3) << 23) +#define GPMC_CONFIG1_WAIT_READ_MON (1 << 22) +#define GPMC_CONFIG1_WAIT_WRITE_MON (1 << 21) +#define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18) +#define GPMC_CONFIG1_WAIT_PIN_SEL(val) ((val & 3) << 16) +#define GPMC_CONFIG1_DEVICESIZE(val) ((val & 3) << 12) +#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1) +#define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10) +#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0) +#define GPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(1) +#define GPMC_CONFIG1_MUXADDDATA (1 << 9) +#define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4) +#define GPMC_CONFIG1_FCLK_DIV(val) (val & 3) +#define GPMC_CONFIG1_FCLK_DIV2 (GPMC_CONFIG1_FCLK_DIV(1)) +#define GPMC_CONFIG1_FCLK_DIV3 (GPMC_CONFIG1_FCLK_DIV(2)) +#define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3)) + +/* + * Note that all values in this struct are in nanoseconds, while + * the register values are in gpmc_fck cycles. + */ +struct gpmc_timings { + /* Minimum clock period for synchronous mode */ + u16 sync_clk; + + /* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */ + u16 cs_on; /* Assertion time */ + u16 cs_rd_off; /* Read deassertion time */ + u16 cs_wr_off; /* Write deassertion time */ + + /* ADV signal timings corresponding to GPMC_CONFIG3 */ + u16 adv_on; /* Assertion time */ + u16 adv_rd_off; /* Read deassertion time */ + u16 adv_wr_off; /* Write deassertion time */ + + /* WE signals timings corresponding to GPMC_CONFIG4 */ + u16 we_on; /* WE assertion time */ + u16 we_off; /* WE deassertion time */ + + /* OE signals timings corresponding to GPMC_CONFIG4 */ + u16 oe_on; /* OE assertion time */ + u16 oe_off; /* OE deassertion time */ + + /* Access time and cycle time timings corresponding to GPMC_CONFIG5 */ + u16 page_burst_access; /* Multiple access word delay */ + u16 access; /* Start-cycle to first data valid delay */ + u16 rd_cycle; /* Total read cycle time */ + u16 wr_cycle; /* Total write cycle time */ +}; + +extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns); + +extern void gpmc_cs_write_reg(int cs, int idx, u32 val); +extern u32 gpmc_cs_read_reg(int cs, int idx); +extern int gpmc_cs_calc_divider(int cs, unsigned int sync_clk); +extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t); +extern unsigned long gpmc_cs_get_base_addr(int cs); + + +#endif diff --git a/include/asm-arm/arch-pnx4008/clock.h b/include/asm-arm/arch-pnx4008/clock.h new file mode 100644 index 000000000..91ae0030f --- /dev/null +++ b/include/asm-arm/arch-pnx4008/clock.h @@ -0,0 +1,61 @@ +/* + * include/asm-arm/arch-pnx4008/clock.h + * + * Clock control driver for PNX4008 - header file + * + * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com> + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#ifndef __PNX4008_CLOCK_H__ +#define __PNX4008_CLOCK_H__ + +struct module; +struct clk; + +#define PWRMAN_VA_BASE IO_ADDRESS(PNX4008_PWRMAN_BASE) +#define HCLKDIVCTRL_REG (PWRMAN_VA_BASE + 0x40) +#define PWRCTRL_REG (PWRMAN_VA_BASE + 0x44) +#define PLLCTRL_REG (PWRMAN_VA_BASE + 0x48) +#define OSC13CTRL_REG (PWRMAN_VA_BASE + 0x4c) +#define SYSCLKCTRL_REG (PWRMAN_VA_BASE + 0x50) +#define HCLKPLLCTRL_REG (PWRMAN_VA_BASE + 0x58) +#define USBCTRL_REG (PWRMAN_VA_BASE + 0x64) +#define SDRAMCLKCTRL_REG (PWRMAN_VA_BASE + 0x68) +#define MSCTRL_REG (PWRMAN_VA_BASE + 0x80) +#define BTCLKCTRL (PWRMAN_VA_BASE + 0x84) +#define DUMCLKCTRL_REG (PWRMAN_VA_BASE + 0x90) +#define I2CCLKCTRL_REG (PWRMAN_VA_BASE + 0xac) +#define KEYCLKCTRL_REG (PWRMAN_VA_BASE + 0xb0) +#define TSCLKCTRL_REG (PWRMAN_VA_BASE + 0xb4) +#define PWMCLKCTRL_REG (PWRMAN_VA_BASE + 0xb8) +#define SPICTRL_REG (PWRMAN_VA_BASE + 0xc4) +#define FLASHCLKCTRL_REG (PWRMAN_VA_BASE + 0xc8) +#define UART3CLK_REG (PWRMAN_VA_BASE + 0xd0) +#define UARTCLKCTRL_REG (PWRMAN_VA_BASE + 0xe4) +#define DMACLKCTRL_REG (PWRMAN_VA_BASE + 0xe8) +#define AUTOCLK_CTRL (PWRMAN_VA_BASE + 0xec) +#define JPEGCLKCTRL_REG (PWRMAN_VA_BASE + 0xfc) + +#define AUDIOCONFIG_VA_BASE IO_ADDRESS(PNX4008_AUDIOCONFIG_BASE) +#define DSPPLLCTRL_REG (AUDIOCONFIG_VA_BASE + 0x60) +#define DSPCLKCTRL_REG (AUDIOCONFIG_VA_BASE + 0x64) +#define AUDIOCLKCTRL_REG (AUDIOCONFIG_VA_BASE + 0x68) +#define AUDIOPLLCTRL_REG (AUDIOCONFIG_VA_BASE + 0x6C) + +#define USB_OTG_CLKCTRL_REG IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xff4) + +#define VFP9CLKCTRL_REG IO_ADDRESS(PNX4008_DEBUG_BASE) + +#define CLK_RATE_13MHZ 13000 +#define CLK_RATE_1MHZ 1000 +#define CLK_RATE_208MHZ 208000 +#define CLK_RATE_48MHZ 48000 +#define CLK_RATE_32KHZ 32 + +#define PNX4008_UART_CLK CLK_RATE_13MHZ * 1000 /* in MHz */ + +#endif diff --git a/include/asm-arm/arch-pnx4008/debug-macro.S b/include/asm-arm/arch-pnx4008/debug-macro.S new file mode 100644 index 000000000..67d18a203 --- /dev/null +++ b/include/asm-arm/arch-pnx4008/debug-macro.S @@ -0,0 +1,23 @@ +/* linux/include/asm-arm/arch-pnx4008/debug-macro.S + * + * Debugging macro include header + * + * Copyright (C) 1994-1999 Russell King + * Moved from linux/arch/arm/kernel/debug.S by Ben Dooks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + mov \rx, #0x00090000 + addeq \rx, \rx, #0x40000000 + addne \rx, \rx, #0xf4000000 + .endm + +#define UART_SHIFT 2 +#include <asm/hardware/debug-8250.S> diff --git a/include/asm-arm/arch-pnx4008/dma.h b/include/asm-arm/arch-pnx4008/dma.h new file mode 100644 index 000000000..3aee12047 --- /dev/null +++ b/include/asm-arm/arch-pnx4008/dma.h @@ -0,0 +1,162 @@ +/* + * linux/include/asm-arm/arch-pnx4008/dma.h + * + * PNX4008 DMA header file + * + * Author: Vitaly Wool + * Copyright: MontaVista Software Inc. (c) 2005 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_ARCH_DMA_H +#define __ASM_ARCH_DMA_H + +#include "platform.h" + +#define MAX_DMA_ADDRESS 0xffffffff + +#define MAX_DMA_CHANNELS 8 + +#define DMAC_BASE IO_ADDRESS(PNX4008_DMA_CONFIG_BASE) +#define DMAC_INT_STAT (DMAC_BASE + 0x0000) +#define DMAC_INT_TC_STAT (DMAC_BASE + 0x0004) +#define DMAC_INT_TC_CLEAR (DMAC_BASE + 0x0008) +#define DMAC_INT_ERR_STAT (DMAC_BASE + 0x000c) +#define DMAC_INT_ERR_CLEAR (DMAC_BASE + 0x0010) +#define DMAC_SOFT_SREQ (DMAC_BASE + 0x0024) +#define DMAC_CONFIG (DMAC_BASE + 0x0030) +#define DMAC_Cx_SRC_ADDR(c) (DMAC_BASE + 0x0100 + (c) * 0x20) +#define DMAC_Cx_DEST_ADDR(c) (DMAC_BASE + 0x0104 + (c) * 0x20) +#define DMAC_Cx_LLI(c) (DMAC_BASE + 0x0108 + (c) * 0x20) +#define DMAC_Cx_CONTROL(c) (DMAC_BASE + 0x010c + (c) * 0x20) +#define DMAC_Cx_CONFIG(c) (DMAC_BASE + 0x0110 + (c) * 0x20) + +enum { + WIDTH_BYTE = 0, + WIDTH_HWORD, + WIDTH_WORD +}; + +enum { + FC_MEM2MEM_DMA, + FC_MEM2PER_DMA, + FC_PER2MEM_DMA, + FC_PER2PER_DMA, + FC_PER2PER_DPER, + FC_MEM2PER_PER, + FC_PER2MEM_PER, + FC_PER2PER_SPER +}; + +enum { + DMA_INT_UNKNOWN = 0, + DMA_ERR_INT = 1, + DMA_TC_INT = 2, +}; + +enum { + DMA_BUFFER_ALLOCATED = 1, + DMA_HAS_LL = 2, +}; + +enum { + PER_CAM_DMA_1 = 0, + PER_NDF_FLASH = 1, + PER_MBX_SLAVE_FIFO = 2, + PER_SPI2_REC_XMIT = 3, + PER_MS_SD_RX_XMIT = 4, + PER_HS_UART_1_XMIT = 5, + PER_HS_UART_1_RX = 6, + PER_HS_UART_2_XMIT = 7, + PER_HS_UART_2_RX = 8, + PER_HS_UART_7_XMIT = 9, + PER_HS_UART_7_RX = 10, + PER_SPI1_REC_XMIT = 11, + PER_MLC_NDF_SREC = 12, + PER_CAM_DMA_2 = 13, + PER_PRNG_INFIFO = 14, + PER_PRNG_OUTFIFO = 15, +}; + +struct pnx4008_dma_ch_ctrl { + int tc_mask; + int cacheable; + int bufferable; + int priv_mode; + int di; + int si; + int dest_ahb1; + int src_ahb1; + int dwidth; + int swidth; + int dbsize; + int sbsize; + int tr_size; +}; + +struct pnx4008_dma_ch_config { + int halt; + int active; + int lock; + int itc; + int ie; + int flow_cntrl; + int dest_per; + int src_per; +}; + +struct pnx4008_dma_ll { + unsigned long src_addr; + unsigned long dest_addr; + u32 next_dma; + unsigned long ch_ctrl; + struct pnx4008_dma_ll *next; + int flags; + void *alloc_data; + int (*free) (void *); +}; + +struct pnx4008_dma_config { + int is_ll; + unsigned long src_addr; + unsigned long dest_addr; + unsigned long ch_ctrl; + unsigned long ch_cfg; + struct pnx4008_dma_ll *ll; + u32 ll_dma; + int flags; + void *alloc_data; + int (*free) (void *); +}; + +extern struct pnx4008_dma_ll *pnx4008_alloc_ll_entry(dma_addr_t *); +extern void pnx4008_free_ll_entry(struct pnx4008_dma_ll *, dma_addr_t); +extern void pnx4008_free_ll(u32 ll_dma, struct pnx4008_dma_ll *); + +extern int pnx4008_request_channel(char *, int, + void (*)(int, int, void *, struct pt_regs *), + void *); +extern void pnx4008_free_channel(int); +extern int pnx4008_config_dma(int, int, int); +extern int pnx4008_dma_pack_control(const struct pnx4008_dma_ch_ctrl *, + unsigned long *); +extern int pnx4008_dma_parse_control(unsigned long, + struct pnx4008_dma_ch_ctrl *); +extern int pnx4008_dma_pack_config(const struct pnx4008_dma_ch_config *, + unsigned long *); +extern int pnx4008_dma_parse_config(unsigned long, + struct pnx4008_dma_ch_config *); +extern int pnx4008_config_channel(int, struct pnx4008_dma_config *); +extern int pnx4008_channel_get_config(int, struct pnx4008_dma_config *); +extern int pnx4008_dma_ch_enable(int); +extern int pnx4008_dma_ch_disable(int); +extern int pnx4008_dma_ch_enabled(int); +extern void pnx4008_dma_split_head_entry(struct pnx4008_dma_config *, + struct pnx4008_dma_ch_ctrl *); +extern void pnx4008_dma_split_ll_entry(struct pnx4008_dma_ll *, + struct pnx4008_dma_ch_ctrl *); + +#endif /* _ASM_ARCH_DMA_H */ diff --git a/include/asm-arm/arch-pnx4008/entry-macro.S b/include/asm-arm/arch-pnx4008/entry-macro.S new file mode 100644 index 000000000..c1c198e36 --- /dev/null +++ b/include/asm-arm/arch-pnx4008/entry-macro.S @@ -0,0 +1,121 @@ +/* + * include/asm-arm/arch-pnx4008/entry-macro.S + * + * Low-level IRQ helper macros for PNX4008-based platforms + * + * 2005-2006 (c) MontaVista Software, Inc. + * Author: Vitaly Wool <vwool@ru.mvista.com> + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include "platform.h" + +#define IO_BASE 0xF0000000 +#define IO_ADDRESS(x) (((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) | IO_BASE) + +#define INTRC_MASK 0x00 +#define INTRC_RAW_STAT 0x04 +#define INTRC_STAT 0x08 +#define INTRC_POLAR 0x0C +#define INTRC_ACT_TYPE 0x10 +#define INTRC_TYPE 0x14 + +#define SIC1_BASE_INT 32 +#define SIC2_BASE_INT 64 + + .macro disable_fiq + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp +/* decode the MIC interrupt numbers */ + ldr \base, =IO_ADDRESS(PNX4008_INTCTRLMIC_BASE) + ldr \irqstat, [\base, #INTRC_STAT] + + cmp \irqstat,#1<<16 + movhs \irqnr,#16 + movlo \irqnr,#0 + movhs \irqstat,\irqstat,lsr#16 + cmp \irqstat,#1<<8 + addhs \irqnr,\irqnr,#8 + movhs \irqstat,\irqstat,lsr#8 + cmp \irqstat,#1<<4 + addhs \irqnr,\irqnr,#4 + movhs \irqstat,\irqstat,lsr#4 + cmp \irqstat,#1<<2 + addhs \irqnr,\irqnr,#2 + movhs \irqstat,\irqstat,lsr#2 + cmp \irqstat,#1<<1 + addhs \irqnr,\irqnr,#1 + +/* was there an interrupt ? if not then drop out with EQ status */ + teq \irqstat,#0 + beq 1003f + +/* and now check for extended IRQ reasons */ + cmp \irqnr,#1 + bls 1003f + cmp \irqnr,#30 + blo 1002f + +/* IRQ 31,30 : High priority cascade IRQ handle */ +/* read the correct SIC */ +/* decoding status after compare : eq is 30 (SIC1) , ne is 31 (SIC2) */ +/* set the base IRQ number */ + ldreq \base, =IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE) + moveq \irqnr,#SIC1_BASE_INT + ldrne \base, =IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE) + movne \irqnr,#SIC2_BASE_INT + ldr \irqstat, [\base, #INTRC_STAT] + ldr \tmp, [\base, #INTRC_TYPE] +/* and with inverted mask : low priority interrupts */ + and \irqstat,\irqstat,\tmp + b 1004f + +1003: +/* IRQ 1,0 : Low priority cascade IRQ handle */ +/* read the correct SIC */ +/* decoding status after compare : eq is 1 (SIC2) , ne is 0 (SIC1)*/ +/* read the correct SIC */ +/* set the base IRQ number */ + ldrne \base, =IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE) + movne \irqnr,#SIC1_BASE_INT + ldreq \base, =IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE) + moveq \irqnr,#SIC2_BASE_INT + ldr \irqstat, [\base, #INTRC_STAT] + ldr \tmp, [\base, #INTRC_TYPE] +/* and with inverted mask : low priority interrupts */ + bic \irqstat,\irqstat,\tmp + +1004: + + cmp \irqstat,#1<<16 + addhs \irqnr,\irqnr,#16 + movhs \irqstat,\irqstat,lsr#16 + cmp \irqstat,#1<<8 + addhs \irqnr,\irqnr,#8 + movhs \irqstat,\irqstat,lsr#8 + cmp \irqstat,#1<<4 + addhs \irqnr,\irqnr,#4 + movhs \irqstat,\irqstat,lsr#4 + cmp \irqstat,#1<<2 + addhs \irqnr,\irqnr,#2 + movhs \irqstat,\irqstat,lsr#2 + cmp \irqstat,#1<<1 + addhs \irqnr,\irqnr,#1 + + +/* is irqstat not zero */ + +1002: +/* we assert that irqstat is not equal to zero and return ne status if true*/ + teq \irqstat,#0 +1003: + .endm + + + .macro irq_prio_table + .endm + + diff --git a/include/asm-arm/arch-pnx4008/gpio.h b/include/asm-arm/arch-pnx4008/gpio.h new file mode 100644 index 000000000..d01bf83d5 --- /dev/null +++ b/include/asm-arm/arch-pnx4008/gpio.h @@ -0,0 +1,241 @@ +/* + * include/asm-arm/arch-pnx4008/gpio.h + * + * PNX4008 GPIO driver - header file + * + * Author: Dmitry Chigirev <source@mvista.com> + * + * Based on reference code by Iwo Mergler and Z.Tabaaloute from Philips: + * Copyright (c) 2005 Koninklijke Philips Electronics N.V. + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#ifndef _PNX4008_GPIO_H_ +#define _PNX4008_GPIO_H_ + + +/* Block numbers */ +#define GPIO_IN (0) +#define GPIO_OUT (0x100) +#define GPIO_BID (0x200) +#define GPIO_RAM (0x300) +#define GPIO_MUX (0x400) + +#define GPIO_TYPE_MASK(K) ((K) & 0x700) + +/* INPUT GPIOs */ +/* GPI */ +#define GPI_00 (GPIO_IN | 0) +#define GPI_01 (GPIO_IN | 1) +#define GPI_02 (GPIO_IN | 2) +#define GPI_03 (GPIO_IN | 3) +#define GPI_04 (GPIO_IN | 4) +#define GPI_05 (GPIO_IN | 5) +#define GPI_06 (GPIO_IN | 6) +#define GPI_07 (GPIO_IN | 7) +#define GPI_08 (GPIO_IN | 8) +#define GPI_09 (GPIO_IN | 9) +#define U1_RX (GPIO_IN | 15) +#define U2_HTCS (GPIO_IN | 16) +#define U2_RX (GPIO_IN | 17) +#define U3_RX (GPIO_IN | 18) +#define U4_RX (GPIO_IN | 19) +#define U5_RX (GPIO_IN | 20) +#define U6_IRRX (GPIO_IN | 21) +#define U7_HCTS (GPIO_IN | 22) +#define U7_RX (GPIO_IN | 23) +/* MISC IN */ +#define SPI1_DATIN (GPIO_IN | 25) +#define DISP_SYNC (GPIO_IN | 26) +#define SPI2_DATIN (GPIO_IN | 27) +#define GPI_11 (GPIO_IN | 28) + +#define GPIO_IN_MASK 0x1eff83ff + +/* OUTPUT GPIOs */ +/* GPO */ +#define GPO_00 (GPIO_OUT | 0) +#define GPO_01 (GPIO_OUT | 1) +#define GPO_02 (GPIO_OUT | 2) +#define GPO_03 (GPIO_OUT | 3) +#define GPO_04 (GPIO_OUT | 4) +#define GPO_05 (GPIO_OUT | 5) +#define GPO_06 (GPIO_OUT | 6) +#define GPO_07 (GPIO_OUT | 7) +#define GPO_08 (GPIO_OUT | 8) +#define GPO_09 (GPIO_OUT | 9) +#define GPO_10 (GPIO_OUT | 10) +#define GPO_11 (GPIO_OUT | 11) +#define GPO_12 (GPIO_OUT | 12) +#define GPO_13 (GPIO_OUT | 13) +#define GPO_14 (GPIO_OUT | 14) +#define GPO_15 (GPIO_OUT | 15) +#define GPO_16 (GPIO_OUT | 16) +#define GPO_17 (GPIO_OUT | 17) +#define GPO_18 (GPIO_OUT | 18) +#define GPO_19 (GPIO_OUT | 19) +#define GPO_20 (GPIO_OUT | 20) +#define GPO_21 (GPIO_OUT | 21) +#define GPO_22 (GPIO_OUT | 22) +#define GPO_23 (GPIO_OUT | 23) + +#define GPIO_OUT_MASK 0xffffff + +/* BIDIRECTIONAL GPIOs */ +/* RAM pins */ +#define RAM_D19 (GPIO_RAM | 0) +#define RAM_D20 (GPIO_RAM | 1) +#define RAM_D21 (GPIO_RAM | 2) +#define RAM_D22 (GPIO_RAM | 3) +#define RAM_D23 (GPIO_RAM | 4) +#define RAM_D24 (GPIO_RAM | 5) +#define RAM_D25 (GPIO_RAM | 6) +#define RAM_D26 (GPIO_RAM | 7) +#define RAM_D27 (GPIO_RAM | 8) +#define RAM_D28 (GPIO_RAM | 9) +#define RAM_D29 (GPIO_RAM | 10) +#define RAM_D30 (GPIO_RAM | 11) +#define RAM_D31 (GPIO_RAM | 12) + +#define GPIO_RAM_MASK 0x1fff + +/* I/O pins */ +#define GPIO_00 (GPIO_BID | 25) +#define GPIO_01 (GPIO_BID | 26) +#define GPIO_02 (GPIO_BID | 27) +#define GPIO_03 (GPIO_BID | 28) +#define GPIO_04 (GPIO_BID | 29) +#define GPIO_05 (GPIO_BID | 30) + +#define GPIO_BID_MASK 0x7e000000 + +/* Non-GPIO multiplexed PIOs. For multiplexing with GPIO, please use GPIO macros */ +#define GPIO_SDRAM_SEL (GPIO_MUX | 3) + +#define GPIO_MUX_MASK 0x8 + +/* Extraction/assembly macros */ +#define GPIO_BIT_MASK(K) ((K) & 0x1F) +#define GPIO_BIT(K) (1 << GPIO_BIT_MASK(K)) +#define GPIO_ISMUX(K) ((GPIO_TYPE_MASK(K) == GPIO_MUX) && (GPIO_BIT(K) & GPIO_MUX_MASK)) +#define GPIO_ISRAM(K) ((GPIO_TYPE_MASK(K) == GPIO_RAM) && (GPIO_BIT(K) & GPIO_RAM_MASK)) +#define GPIO_ISBID(K) ((GPIO_TYPE_MASK(K) == GPIO_BID) && (GPIO_BIT(K) & GPIO_BID_MASK)) +#define GPIO_ISOUT(K) ((GPIO_TYPE_MASK(K) == GPIO_OUT) && (GPIO_BIT(K) & GPIO_OUT_MASK)) +#define GPIO_ISIN(K) ((GPIO_TYPE_MASK(K) == GPIO_IN) && (GPIO_BIT(K) & GPIO_IN_MASK)) + +/* Start Enable Pin Interrupts - table 58 page 66 */ + +#define SE_PIN_BASE_INT 32 + +#define SE_U7_RX_INT 63 +#define SE_U7_HCTS_INT 62 +#define SE_BT_CLKREQ_INT 61 +#define SE_U6_IRRX_INT 60 +/*59 unused*/ +#define SE_U5_RX_INT 58 +#define SE_GPI_11_INT 57 +#define SE_U3_RX_INT 56 +#define SE_U2_HCTS_INT 55 +#define SE_U2_RX_INT 54 +#define SE_U1_RX_INT 53 +#define SE_DISP_SYNC_INT 52 +/*51 unused*/ +#define SE_SDIO_INT_N 50 +#define SE_MSDIO_START_INT 49 +#define SE_GPI_06_INT 48 +#define SE_GPI_05_INT 47 +#define SE_GPI_04_INT 46 +#define SE_GPI_03_INT 45 +#define SE_GPI_02_INT 44 +#define SE_GPI_01_INT 43 +#define SE_GPI_00_INT 42 +#define SE_SYSCLKEN_PIN_INT 41 +#define SE_SPI1_DATAIN_INT 40 +#define SE_GPI_07_INT 39 +#define SE_SPI2_DATAIN_INT 38 +#define SE_GPI_10_INT 37 +#define SE_GPI_09_INT 36 +#define SE_GPI_08_INT 35 +/*34-32 unused*/ + +/* Start Enable Internal Interrupts - table 57 page 65 */ + +#define SE_INT_BASE_INT 0 + +#define SE_TS_IRQ 31 +#define SE_TS_P_INT 30 +#define SE_TS_AUX_INT 29 +/*27-28 unused*/ +#define SE_USB_AHB_NEED_CLK_INT 26 +#define SE_MSTIMER_INT 25 +#define SE_RTC_INT 24 +#define SE_USB_NEED_CLK_INT 23 +#define SE_USB_INT 22 +#define SE_USB_I2C_INT 21 +#define SE_USB_OTG_TIMER_INT 20 +#define SE_USB_OTG_ATX_INT_N 19 +/*18 unused*/ +#define SE_DSP_GPIO4_INT 17 +#define SE_KEY_IRQ 16 +#define SE_DSP_SLAVEPORT_INT 15 +#define SE_DSP_GPIO1_INT 14 +#define SE_DSP_GPIO0_INT 13 +#define SE_DSP_AHB_INT 12 +/*11-6 unused*/ +#define SE_GPIO_05_INT 5 +#define SE_GPIO_04_INT 4 +#define SE_GPIO_03_INT 3 +#define SE_GPIO_02_INT 2 +#define SE_GPIO_01_INT 1 +#define SE_GPIO_00_INT 0 + +#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F)) + +#define START_INT_ER_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1))) +#define START_INT_RSR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1))) +#define START_INT_SR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1))) +#define START_INT_APR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1))) + +extern int pnx4008_gpio_register_pin(unsigned short pin); +extern int pnx4008_gpio_unregister_pin(unsigned short pin); +extern unsigned long pnx4008_gpio_read_pin(unsigned short pin); +extern int pnx4008_gpio_write_pin(unsigned short pin, int output); +extern int pnx4008_gpio_set_pin_direction(unsigned short pin, int output); +extern int pnx4008_gpio_read_pin_direction(unsigned short pin); +extern int pnx4008_gpio_set_pin_mux(unsigned short pin, int output); +extern int pnx4008_gpio_read_pin_mux(unsigned short pin); + +static inline void start_int_umask(u8 irq) +{ + __raw_writel(__raw_readl(START_INT_ER_REG(irq)) | + START_INT_REG_BIT(irq), START_INT_ER_REG(irq)); +} + +static inline void start_int_mask(u8 irq) +{ + __raw_writel(__raw_readl(START_INT_ER_REG(irq)) & + ~START_INT_REG_BIT(irq), START_INT_ER_REG(irq)); +} + +static inline void start_int_ack(u8 irq) +{ + __raw_writel(START_INT_REG_BIT(irq), START_INT_RSR_REG(irq)); +} + +static inline void start_int_set_falling_edge(u8 irq) +{ + __raw_writel(__raw_readl(START_INT_APR_REG(irq)) & + ~START_INT_REG_BIT(irq), START_INT_APR_REG(irq)); +} + +static inline void start_int_set_rising_edge(u8 irq) +{ + __raw_writel(__raw_readl(START_INT_APR_REG(irq)) | + START_INT_REG_BIT(irq), START_INT_APR_REG(irq)); +} + +#endif /* _PNX4008_GPIO_H_ */ diff --git a/include/asm-arm/arch-pnx4008/hardware.h b/include/asm-arm/arch-pnx4008/hardware.h new file mode 100644 index 000000000..a4410397a --- /dev/null +++ b/include/asm-arm/arch-pnx4008/hardware.h @@ -0,0 +1,32 @@ +/* + * linux/include/asm-arm/arch-pnx4008/hardware.h + * + * Copyright (c) 2005 MontaVista Software, Inc. <source@mvista.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +#include <asm/sizes.h> +#include <asm/arch/platform.h> + +/* Start of virtual addresses for IO devices */ +#define IO_BASE 0xF0000000 + +/* This macro relies on fact that for all HW i/o addresses bits 20-23 are 0 */ +#define IO_ADDRESS(x) (((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) | IO_BASE) + +#endif diff --git a/include/asm-arm/arch-pnx4008/io.h b/include/asm-arm/arch-pnx4008/io.h new file mode 100644 index 000000000..29ee43955 --- /dev/null +++ b/include/asm-arm/arch-pnx4008/io.h @@ -0,0 +1,21 @@ + +/* + * include/asm-arm/arch-pnx4008/io.h + * + * Author: Dmitry Chigirev <chigirev@ru.mvista.com> + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#ifndef __ASM_ARM_ARCH_IO_H +#define __ASM_ARM_ARCH_IO_H + +#define IO_SPACE_LIMIT 0xffffffff + +#define __io(a) ((void __iomem *)(a)) +#define __mem_pci(a) (a) + +#endif diff --git a/include/asm-arm/arch-pnx4008/irq.h b/include/asm-arm/arch-pnx4008/irq.h new file mode 100644 index 000000000..fabff5dc3 --- /dev/null +++ b/include/asm-arm/arch-pnx4008/irq.h @@ -0,0 +1,42 @@ +/* + * include/asm-arm/arch-pnx4008/irq.h + * + * PNX4008 IRQ controller driver - header file + * this one is used in entry-arnv.S as well so it cannot contain C code + * + * Copyright (c) 2005 Philips Semiconductors + * Copyright (c) 2005 MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#ifndef __PNX4008_IRQ_H__ +#define __PNX4008_IRQ_H__ + +#define MIC_VA_BASE IO_ADDRESS(PNX4008_INTCTRLMIC_BASE) +#define SIC1_VA_BASE IO_ADDRESS(PNX4008_INTCTRLSIC1_BASE) +#define SIC2_VA_BASE IO_ADDRESS(PNX4008_INTCTRLSIC2_BASE) + +/* Manual: Chapter 20, page 195 */ + +#define INTC_BIT(irq) (1<< ((irq) & 0x1F)) + +#define INTC_ER(irq) IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x0 + (((irq)&(0x3<<5))<<9))) +#define INTC_RSR(irq) IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x4 + (((irq)&(0x3<<5))<<9))) +#define INTC_SR(irq) IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x8 + (((irq)&(0x3<<5))<<9))) +#define INTC_APR(irq) IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0xC + (((irq)&(0x3<<5))<<9))) +#define INTC_ATR(irq) IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x10 + (((irq)&(0x3<<5))<<9))) +#define INTC_ITR(irq) IO_ADDRESS((PNX4008_INTCTRLMIC_BASE + 0x14 + (((irq)&(0x3<<5))<<9))) + +#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F)) + +#define START_INT_ER_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1))) +#define START_INT_RSR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1))) +#define START_INT_SR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1))) +#define START_INT_APR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1))) + +extern void __init pnx4008_init_irq(void); + +#endif /* __PNX4008_IRQ_H__ */ diff --git a/include/asm-arm/arch-pnx4008/irqs.h b/include/asm-arm/arch-pnx4008/irqs.h new file mode 100644 index 000000000..13ec7ed0f --- /dev/null +++ b/include/asm-arm/arch-pnx4008/irqs.h @@ -0,0 +1,215 @@ +/* + * include/asm-arm/arch-pnx4008/irqs.h + * + * PNX4008 IRQ controller driver - header file + * + * Author: Dmitry Chigirev <source@mvista.com> + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#ifndef __PNX4008_IRQS_h__ +#define __PNX4008_IRQS_h__ + +#define NR_IRQS 96 + +/*Manual: table 259, page 199*/ + +/*SUB2 Interrupt Routing (SIC2)*/ + +#define SIC2_BASE_INT 64 + +#define CLK_SWITCH_ARM_INT 95 /*manual: Clkswitch ARM */ +#define CLK_SWITCH_DSP_INT 94 /*manual: ClkSwitch DSP */ +#define CLK_SWITCH_AUD_INT 93 /*manual: Clkswitch AUD */ +#define GPI_06_INT 92 +#define GPI_05_INT 91 +#define GPI_04_INT 90 +#define GPI_03_INT 89 +#define GPI_02_INT 88 +#define GPI_01_INT 87 +#define GPI_00_INT 86 +#define BT_CLKREQ_INT 85 +#define SPI1_DATIN_INT 84 +#define U5_RX_INT 83 +#define SDIO_INT_N 82 +#define CAM_HS_INT 81 +#define CAM_VS_INT 80 +#define GPI_07_INT 79 +#define DISP_SYNC_INT 78 +#define DSP_INT8 77 +#define U7_HCTS_INT 76 +#define GPI_10_INT 75 +#define GPI_09_INT 74 +#define GPI_08_INT 73 +#define DSP_INT7 72 +#define U2_HCTS_INT 71 +#define SPI2_DATIN_INT 70 +#define GPIO_05_INT 69 +#define GPIO_04_INT 68 +#define GPIO_03_INT 67 +#define GPIO_02_INT 66 +#define GPIO_01_INT 65 +#define GPIO_00_INT 64 + +/*Manual: table 258, page 198*/ + +/*SUB1 Interrupt Routing (SIC1)*/ + +#define SIC1_BASE_INT 32 + +#define USB_I2C_INT 63 +#define USB_DEV_HP_INT 62 +#define USB_DEV_LP_INT 61 +#define USB_DEV_DMA_INT 60 +#define USB_HOST_INT 59 +#define USB_OTG_ATX_INT_N 58 +#define USB_OTG_TIMER_INT 57 +#define SW_INT 56 +#define SPI1_INT 55 +#define KEY_IRQ 54 +#define DSP_M_INT 53 +#define RTC_INT 52 +#define I2C_1_INT 51 +#define I2C_2_INT 50 +#define PLL1_LOCK_INT 49 +#define PLL2_LOCK_INT 48 +#define PLL3_LOCK_INT 47 +#define PLL4_LOCK_INT 46 +#define PLL5_LOCK_INT 45 +#define SPI2_INT 44 +#define DSP_INT1 43 +#define DSP_INT2 42 +#define DSP_TDM_INT2 41 +#define TS_AUX_INT 40 +#define TS_IRQ 39 +#define TS_P_INT 38 +#define UOUT1_TO_PAD_INT 37 +#define GPI_11_INT 36 +#define DSP_INT4 35 +#define JTAG_COMM_RX_INT 34 +#define JTAG_COMM_TX_INT 33 +#define DSP_INT3 32 + +/*Manual: table 257, page 197*/ + +/*MAIN Interrupt Routing*/ + +#define MAIN_BASE_INT 0 + +#define SUB2_FIQ_N 31 /*active low */ +#define SUB1_FIQ_N 30 /*active low */ +#define JPEG_INT 29 +#define DMA_INT 28 +#define MSTIMER_INT 27 +#define IIR1_INT 26 +#define IIR2_INT 25 +#define IIR7_INT 24 +#define DSP_TDM_INT0 23 +#define DSP_TDM_INT1 22 +#define DSP_P_INT 21 +#define DSP_INT0 20 +#define DUM_INT 19 +#define UOUT0_TO_PAD_INT 18 +#define MP4_ENC_INT 17 +#define MP4_DEC_INT 16 +#define SD0_INT 15 +#define MBX_INT 14 +#define SD1_INT 13 +#define MS_INT_N 12 +#define FLASH_INT 11 /*NAND*/ +#define IIR6_INT 10 +#define IIR5_INT 9 +#define IIR4_INT 8 +#define IIR3_INT 7 +#define WATCH_INT 6 +#define HSTIMER_INT 5 +#define ARCH_TIMER_IRQ HSTIMER_INT +#define CAM_INT 4 +#define PRNG_INT 3 +#define CRYPTO_INT 2 +#define SUB2_IRQ_N 1 /*active low */ +#define SUB1_IRQ_N 0 /*active low */ + +#define PNX4008_IRQ_TYPES \ +{ /*IRQ #'s: */ \ +IRQT_LOW, IRQT_LOW, IRQT_LOW, IRQT_HIGH, /* 0, 1, 2, 3 */ \ +IRQT_LOW, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 4, 5, 6, 7 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 8, 9,10,11 */ \ +IRQT_LOW, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 12,13,14,15 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 16,17,18,19 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 20,21,22,23 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 24,25,26,27 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_LOW, IRQT_LOW, /* 28,29,30,31 */ \ +IRQT_HIGH, IRQT_LOW, IRQT_HIGH, IRQT_HIGH, /* 32,33,34,35 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_FALLING, IRQT_HIGH, /* 36,37,38,39 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 40,41,42,43 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 44,45,46,47 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_LOW, IRQT_LOW, /* 48,49,50,51 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 52,53,54,55 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_LOW, IRQT_HIGH, /* 56,57,58,59 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 60,61,62,63 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 64,65,66,67 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 68,69,70,71 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 72,73,74,75 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 76,77,78,79 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 80,81,82,83 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 84,85,86,87 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 88,89,90,91 */ \ +IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, IRQT_HIGH, /* 92,93,94,95 */ \ +} + +/* Start Enable Pin Interrupts - table 58 page 66 */ + +#define SE_PIN_BASE_INT 32 + +#define SE_U7_RX_INT 63 +#define SE_U7_HCTS_INT 62 +#define SE_BT_CLKREQ_INT 61 +#define SE_U6_IRRX_INT 60 +/*59 unused*/ +#define SE_U5_RX_INT 58 +#define SE_GPI_11_INT 57 +#define SE_U3_RX_INT 56 +#define SE_U2_HCTS_INT 55 +#define SE_U2_RX_INT 54 +#define SE_U1_RX_INT 53 +#define SE_DISP_SYNC_INT 52 +/*51 unused*/ +#define SE_SDIO_INT_N 50 +#define SE_MSDIO_START_INT 49 +#define SE_GPI_06_INT 48 +#define SE_GPI_05_INT 47 +#define SE_GPI_04_INT 46 +#define SE_GPI_03_INT 45 +#define SE_GPI_02_INT 44 +#define SE_GPI_01_INT 43 +#define SE_GPI_00_INT 42 +#define SE_SYSCLKEN_PIN_INT 41 +#define SE_SPI1_DATAIN_INT 40 +#define SE_GPI_07_INT 39 +#define SE_SPI2_DATAIN_INT 38 +#define SE_GPI_10_INT 37 +#define SE_GPI_09_INT 36 +#define SE_GPI_08_INT 35 +/*34-32 unused*/ + +/* Start Enable Internal Interrupts - table 57 page 65 */ + +#define SE_INT_BASE_INT 0 + +#define SE_TS_IRQ 31 +#define SE_TS_P_INT 30 +#define SE_TS_AUX_INT 29 +/*27-28 unused*/ +#define SE_USB_AHB_NEED_CLK_INT 26 +#define SE_MSTIMER_INT 25 +#define SE_RTC_INT 24 +#define SE_USB_NEED_CLK_INT 23 +#define SE_USB_INT 22 +#define SE_USB_I2C_INT 21 +#define SE_USB_OTG_TIMER_INT 20 + +#endif /* __PNX4008_IRQS_h__ */ diff --git a/include/asm-arm/arch-pnx4008/memory.h b/include/asm-arm/arch-pnx4008/memory.h new file mode 100644 index 000000000..0d8268a95 --- /dev/null +++ b/include/asm-arm/arch-pnx4008/memory.h @@ -0,0 +1,24 @@ +/* + * linux/include/asm-arm/arch-pnx4008/memory.h + * + * Copyright (c) 2005 Philips Semiconductors + * Copyright (c) 2005 MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +/* + * Physical DRAM offset. + */ +#define PHYS_OFFSET (0x80000000) + +#define __virt_to_bus(x) ((x) - PAGE_OFFSET + PHYS_OFFSET) +#define __bus_to_virt(x) ((x) + PAGE_OFFSET - PHYS_OFFSET) + +#endif diff --git a/include/asm-arm/arch-pnx4008/param.h b/include/asm-arm/arch-pnx4008/param.h new file mode 100644 index 000000000..95d5f547b --- /dev/null +++ b/include/asm-arm/arch-pnx4008/param.h @@ -0,0 +1,21 @@ +/* + * linux/include/asm-arm/arch-pnx4008/param.h + * + * Copyright (C) 1999 ARM Limited + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define HZ 100 diff --git a/include/asm-arm/arch-pnx4008/platform.h b/include/asm-arm/arch-pnx4008/platform.h new file mode 100644 index 000000000..485a3651b --- /dev/null +++ b/include/asm-arm/arch-pnx4008/platform.h @@ -0,0 +1,69 @@ +/* + * include/asm-arm/arch-pnx4008/platfrom.h + * + * PNX4008 Base addresses - header file + * + * Author: Dmitry Chigirev <source@mvista.com> + * + * Based on reference code received from Philips: + * Copyright (C) 2003 Philips Semiconductors + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + + +#ifndef __ASM_ARCH_PLATFORM_H__ +#define __ASM_ARCH_PLATFORM_H__ + +#define PNX4008_IRAM_BASE 0x08000000 +#define PNX4008_IRAM_SIZE 0x00010000 +#define PNX4008_YUV_SLAVE_BASE 0x10000000 +#define PNX4008_DUM_SLAVE_BASE 0x18000000 +#define PNX4008_NDF_FLASH_BASE 0x20020000 +#define PNX4008_SPI1_BASE 0x20088000 +#define PNX4008_SPI2_BASE 0x20090000 +#define PNX4008_SD_CONFIG_BASE 0x20098000 +#define PNX4008_FLASH_DATA 0x200B0000 +#define PNX4008_MLC_FLASH_BASE 0x200B8000 +#define PNX4008_JPEG_CONFIG_BASE 0x300A0000 +#define PNX4008_DMA_CONFIG_BASE 0x31000000 +#define PNX4008_USB_CONFIG_BASE 0x31020000 +#define PNX4008_SDRAM_CFG_BASE 0x31080000 +#define PNX4008_AHB2FAB_BASE 0x40000000 +#define PNX4008_PWRMAN_BASE 0x40004000 +#define PNX4008_INTCTRLMIC_BASE 0x40008000 +#define PNX4008_INTCTRLSIC1_BASE 0x4000C000 +#define PNX4008_INTCTRLSIC2_BASE 0x40010000 +#define PNX4008_HSUART1_BASE 0x40014000 +#define PNX4008_HSUART2_BASE 0x40018000 +#define PNX4008_HSUART7_BASE 0x4001C000 +#define PNX4008_RTC_BASE 0x40024000 +#define PNX4008_PIO_BASE 0x40028000 +#define PNX4008_MSTIMER_BASE 0x40034000 +#define PNX4008_HSTIMER_BASE 0x40038000 +#define PNX4008_WDOG_BASE 0x4003C000 +#define PNX4008_DEBUG_BASE 0x40040000 +#define PNX4008_TOUCH1_BASE 0x40048000 +#define PNX4008_KEYSCAN_BASE 0x40050000 +#define PNX4008_UARTCTRL_BASE 0x40054000 +#define PNX4008_PWM_BASE 0x4005C000 +#define PNX4008_UART3_BASE 0x40080000 +#define PNX4008_UART4_BASE 0x40088000 +#define PNX4008_UART5_BASE 0x40090000 +#define PNX4008_UART6_BASE 0x40098000 +#define PNX4008_I2C1_BASE 0x400A0000 +#define PNX4008_I2C2_BASE 0x400A8000 +#define PNX4008_MAGICGATE_BASE 0x400B0000 +#define PNX4008_DUMCONF_BASE 0x400B8000 +#define PNX4008_DUM_MAINCFG_BASE 0x400BC000 +#define PNX4008_DSP_BASE 0x400C0000 +#define PNX4008_PROFCOUNTER_BASE 0x400C8000 +#define PNX4008_CRYPTO_BASE 0x400D0000 +#define PNX4008_CAMIFCONF_BASE 0x400D8000 +#define PNX4008_YUV2RGB_BASE 0x400E0000 +#define PNX4008_AUDIOCONFIG_BASE 0x400E8000 + +#endif diff --git a/include/asm-arm/arch-pnx4008/pm.h b/include/asm-arm/arch-pnx4008/pm.h new file mode 100644 index 000000000..bac1634cb --- /dev/null +++ b/include/asm-arm/arch-pnx4008/pm.h @@ -0,0 +1,33 @@ +/* + * include/asm-arm/arch-pnx4008/pm.h + * + * PNX4008 Power Management Routiness - header file + * + * Authors: Vitaly Wool, Dmitry Chigirev <source@mvista.com> + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#ifndef __ASM_ARCH_PNX4008_PM_H +#define __ASM_ARCH_PNX4008_PM_H + +#ifndef __ASSEMBLER__ +#include "irq.h" +#include "irqs.h" +#include "clock.h" + +extern void pnx4008_pm_idle(void); +extern void pnx4008_pm_suspend(void); +extern unsigned int pnx4008_cpu_suspend_sz; +extern void pnx4008_cpu_suspend(void); +extern unsigned int pnx4008_cpu_standby_sz; +extern void pnx4008_cpu_standby(void); + +extern int pnx4008_startup_pll(struct clk *); +extern int pnx4008_shutdown_pll(struct clk *); + +#endif /* ASSEMBLER */ +#endif /* __ASM_ARCH_PNX4008_PM_H */ diff --git a/include/asm-arm/arch-pnx4008/system.h b/include/asm-arm/arch-pnx4008/system.h new file mode 100644 index 000000000..6e3da70ab --- /dev/null +++ b/include/asm-arm/arch-pnx4008/system.h @@ -0,0 +1,38 @@ +/* + * linux/include/asm-arm/arch-pnx4008/system.h + * + * Copyright (C) 2003 Philips Semiconductors + * Copyright (C) 2005 MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_ARCH_SYSTEM_H +#define __ASM_ARCH_SYSTEM_H + +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/arch/platform.h> + +static void arch_idle(void) +{ + cpu_do_idle(); +} + +static inline void arch_reset(char mode) +{ + cpu_reset(0); +} + +#endif diff --git a/include/asm-arm/arch-pnx4008/timex.h b/include/asm-arm/arch-pnx4008/timex.h new file mode 100644 index 000000000..ee470a390 --- /dev/null +++ b/include/asm-arm/arch-pnx4008/timex.h @@ -0,0 +1,73 @@ +/* + * include/asm-arm/arch-pnx4008/timex.h + * + * PNX4008 timers header file + * + * Author: Dmitry Chigirev <source@mvista.com> + * + * 2005 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#ifndef __PNX4008_TIMEX_H +#define __PNX4008_TIMEX_H + +#include <asm/hardware.h> +#include <asm/io.h> + +#define CLOCK_TICK_RATE 1000000 + +#define TICKS2USECS(x) (x) + +/* MilliSecond Timer - Chapter 21 Page 202 */ + +#define MSTIM_INT IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x0)) +#define MSTIM_CTRL IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x4)) +#define MSTIM_COUNTER IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x8)) +#define MSTIM_MCTRL IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x14)) +#define MSTIM_MATCH0 IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x18)) +#define MSTIM_MATCH1 IO_ADDRESS((PNX4008_MSTIMER_BASE + 0x1c)) + +/* High Speed Timer - Chpater 22, Page 205 */ + +#define HSTIM_INT IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x0)) +#define HSTIM_CTRL IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x4)) +#define HSTIM_COUNTER IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x8)) +#define HSTIM_PMATCH IO_ADDRESS((PNX4008_HSTIMER_BASE + 0xC)) +#define HSTIM_PCOUNT IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x10)) +#define HSTIM_MCTRL IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x14)) +#define HSTIM_MATCH0 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x18)) +#define HSTIM_MATCH1 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x1c)) +#define HSTIM_MATCH2 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x20)) +#define HSTIM_CCR IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x28)) +#define HSTIM_CR0 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x2C)) +#define HSTIM_CR1 IO_ADDRESS((PNX4008_HSTIMER_BASE + 0x30)) + +/* IMPORTANT: both timers are UPCOUNTING */ + +/* xSTIM_MCTRL bit definitions */ +#define MR0_INT 1 +#define RESET_COUNT0 (1<<1) +#define STOP_COUNT0 (1<<2) +#define MR1_INT (1<<3) +#define RESET_COUNT1 (1<<4) +#define STOP_COUNT1 (1<<5) +#define MR2_INT (1<<6) +#define RESET_COUNT2 (1<<7) +#define STOP_COUNT2 (1<<8) + +/* xSTIM_CTRL bit definitions */ +#define COUNT_ENAB 1 +#define RESET_COUNT (1<<1) +#define DEBUG_EN (1<<2) + +/* xSTIM_INT bit definitions */ +#define MATCH0_INT 1 +#define MATCH1_INT (1<<1) +#define MATCH2_INT (1<<2) +#define RTC_TICK0 (1<<4) +#define RTC_TICK1 (1<<5) + +#endif diff --git a/include/asm-arm/arch-pnx4008/uncompress.h b/include/asm-arm/arch-pnx4008/uncompress.h new file mode 100644 index 000000000..8fa4d24b7 --- /dev/null +++ b/include/asm-arm/arch-pnx4008/uncompress.h @@ -0,0 +1,46 @@ +/* + * linux/include/asm-arm/arch-pnx4008/uncompress.h + * + * Copyright (C) 1999 ARM Limited + * Copyright (C) 2006 MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define UART5_BASE 0x40090000 + +#define UART5_DR (*(volatile unsigned char *) (UART5_BASE)) +#define UART5_FR (*(volatile unsigned char *) (UART5_BASE + 18)) + +static __inline__ void putc(char c) +{ + while (UART5_FR & (1 << 5)) + barrier(); + + UART5_DR = c; +} + +/* + * This does not append a newline + */ +static inline void flush(void) +{ +} + +/* + * nothing to do + */ +#define arch_decomp_setup() +#define arch_decomp_wdog() diff --git a/include/asm-arm/arch-pnx4008/vmalloc.h b/include/asm-arm/arch-pnx4008/vmalloc.h new file mode 100644 index 000000000..140d925f6 --- /dev/null +++ b/include/asm-arm/arch-pnx4008/vmalloc.h @@ -0,0 +1,20 @@ +/* + * include/asm-arm/arch-pnx4008/vmalloc.h + * + * Author: Vitaly Wool <source@mvista.com> + * + * 2006 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +/* + * Just any arbitrary offset to the start of the vmalloc VM area: the + * current 8MB value just means that there will be a 8MB "hole" after the + * physical memory until the kernel virtual memory starts. That means that + * any out-of-bounds memory accesses will hopefully be caught. + * The vmalloc() routines leaves a hole of 4kB between each vmalloced + * area for the same reason. ;) + */ +#define VMALLOC_END (PAGE_OFFSET + 0x10000000) diff --git a/include/asm-arm/arch-pxa/trizeps4.h b/include/asm-arm/arch-pxa/trizeps4.h new file mode 100644 index 000000000..641d0ec11 --- /dev/null +++ b/include/asm-arm/arch-pxa/trizeps4.h @@ -0,0 +1,106 @@ +/************************************************************************ + * Include file for TRIZEPS4 SoM and ConXS eval-board + * Copyright (c) Jürgen Schindele + * 2006 + ************************************************************************/ + +/* + * Includes/Defines + */ +#ifndef _TRIPEPS4_H_ +#define _TRIPEPS4_H_ + +/* physical memory regions */ +#define TRIZEPS4_FLASH_PHYS (PXA_CS0_PHYS) /* Flash region */ +#define TRIZEPS4_DISK_PHYS (PXA_CS1_PHYS) /* Disk On Chip region */ +#define TRIZEPS4_ETH_PHYS (PXA_CS2_PHYS) /* Ethernet DM9000 region */ +#define TRIZEPS4_PIC_PHYS (PXA_CS3_PHYS) /* Logic chip on ConXS-Board */ +#define TRIZEPS4_SDRAM_BASE 0xa0000000 /* SDRAM region */ + +#define TRIZEPS4_CFSR_PHYS (PXA_CS3_PHYS) /* Logic chip on ConXS-Board CSFR register */ +#define TRIZEPS4_BOCR_PHYS (PXA_CS3_PHYS+0x02000000) /* Logic chip on ConXS-Board BOCR register */ +#define TRIZEPS4_IRCR_PHYS (PXA_CS3_PHYS+0x02400000) /* Logic chip on ConXS-Board IRCR register*/ +#define TRIZEPS4_UPSR_PHYS (PXA_CS3_PHYS+0x02800000) /* Logic chip on ConXS-Board UPSR register*/ +#define TRIZEPS4_DICR_PHYS (PXA_CS3_PHYS+0x03800000) /* Logic chip on ConXS-Board DICR register*/ + +/* virtual memory regions */ +#define TRIZEPS4_DISK_VIRT 0xF0000000 /* Disk On Chip region */ + +#define TRIZEPS4_PIC_VIRT 0xF0100000 /* not used */ +#define TRIZEPS4_CFSR_VIRT 0xF0100000 +#define TRIZEPS4_BOCR_VIRT 0xF0200000 +#define TRIZEPS4_DICR_VIRT 0xF0300000 +#define TRIZEPS4_IRCR_VIRT 0xF0400000 +#define TRIZEPS4_UPSR_VIRT 0xF0500000 + +/* size of flash */ +#define TRIZEPS4_FLASH_SIZE 0x02000000 /* Flash size 32 MB */ + +/* Ethernet Controller Davicom DM9000 */ +#define GPIO_DM9000 101 +#define TRIZEPS4_ETH_IRQ IRQ_GPIO(GPIO_DM9000) + +/* UCB1400 audio / TS-controller */ +#define GPIO_UCB1400 1 +#define TRIZEPS4_UCB1400_IRQ IRQ_GPIO(GPIO_UCB1400) + +/* PCMCIA socket Compact Flash */ +#define GPIO_PCD 11 /* PCMCIA Card Detect */ +#define TRIZEPS4_CD_IRQ IRQ_GPIO(GPIO_PCD) +#define GPIO_PRDY 13 /* READY / nINT */ +#define TRIZEPS4_READY_NINT IRQ_GPIO(GPIO_PRDY) + +/* MMC socket */ +#define GPIO_MMC_DET 12 +#define TRIZEPS4_MMC_IRQ IRQ_GPIO(GPIO_MMC_DET) + +/* LEDS using tx2 / rx2 */ +#define GPIO_SYS_BUSY_LED 46 +#define GPIO_HEARTBEAT_LED 47 + +/* Off-module PIC on ConXS board */ +#define GPIO_PIC 0 +#define TRIZEPS4_PIC_IRQ IRQ_GPIO(GPIO_PIC) + +#define CFSR_P2V(x) ((x) - TRIZEPS4_CFSR_PHYS + TRIZEPS4_CFSR_VIRT) +#define CFSR_V2P(x) ((x) - TRIZEPS4_CFSR_VIRT + TRIZEPS4_CFSR_PHYS) + +#define BCR_P2V(x) ((x) - TRIZEPS4_BOCR_PHYS + TRIZEPS4_BOCR_VIRT) +#define BCR_V2P(x) ((x) - TRIZEPS4_BOCR_VIRT + TRIZEPS4_BOCR_PHYS) + +#define DCR_P2V(x) ((x) - TRIZEPS4_DICR_PHYS + TRIZEPS4_DICR_VIRT) +#define DCR_V2P(x) ((x) - TRIZEPS4_DICR_VIRT + TRIZEPS4_DICR_PHYS) + +#ifndef __ASSEMBLY__ +#define ConXS_CFSR (*((volatile unsigned short *)CFSR_P2V(0x0C000000))) +#define ConXS_BCR (*((volatile unsigned short *)BCR_P2V(0x0E000000))) +#define ConXS_DCR (*((volatile unsigned short *)DCR_P2V(0x0F800000))) +#else +#define ConXS_CFSR CFSR_P2V(0x0C000000) +#define ConXS_BCR BCR_P2V(0x0E000000) +#define ConXS_DCR DCR_P2V(0x0F800000) +#endif + +#define ConXS_CFSR_BVD_MASK 0x0003 +#define ConXS_CFSR_BVD1 (1 << 0) +#define ConXS_CFSR_BVD2 (1 << 1) +#define ConXS_CFSR_VS_MASK 0x000C +#define ConXS_CFSR_VS1 (1 << 2) +#define ConXS_CFSR_VS2 (1 << 3) +#define ConXS_CFSR_VS_5V (0x3 << 2) +#define ConXS_CFSR_VS_3V3 0x0 + +#define ConXS_BCR_S0_POW_EN0 (1 << 0) +#define ConXS_BCR_S0_POW_EN1 (1 << 1) +#define ConXS_BCR_L_DISP (1 << 4) +#define ConXS_BCR_CF_BUF_EN (1 << 5) +#define ConXS_BCR_CF_RESET (1 << 7) +#define ConXS_BCR_S0_VCC_3V3 0x1 +#define ConXS_BCR_S0_VCC_5V0 0x2 +#define ConXS_BCR_S0_VPP_12V 0x4 +#define ConXS_BCR_S0_VPP_3V3 0x8 + +#define ConXS_IRCR_MODE (1 << 0) +#define ConXS_IRCR_SD (1 << 1) + +#endif /* _TRIPEPS4_H_ */ diff --git a/include/asm-arm/arch-s3c2410/regs-power.h b/include/asm-arm/arch-s3c2410/regs-power.h new file mode 100644 index 000000000..6c319ea2a --- /dev/null +++ b/include/asm-arm/arch-s3c2410/regs-power.h @@ -0,0 +1,34 @@ +/* linux/include/asm/arch-s3c2410/regs-power.h + * + * Copyright (c) 2003,2004,2005,2006 Simtec Electronics <linux@simtec.co.uk> + * http://armlinux.simtec.co.uk/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * S3C24XX power control register definitions +*/ + +#ifndef __ASM_ARM_REGS_PWR +#define __ASM_ARM_REGS_PWR __FILE__ + +#define S3C24XX_PWRREG(x) ((x) + S3C24XX_VA_CLKPWR) + +#define S3C2412_PWRMODECON S3C24XX_PWRREG(0x20) +#define S3C2412_PWRCFG S3C24XX_PWRREG(0x24) + +#define S3C2412_PWRCFG_BATF_IGNORE (0<<0) +#define S3C2412_PWRCFG_BATF_SLEEP (3<<0) +#define S3C2412_PWRCFG_BATF_MASK (3<<0) + +#define S3C2412_PWRCFG_STANDBYWFI_IGNORE (0<<6) +#define S3C2412_PWRCFG_STANDBYWFI_IDLE (1<<6) +#define S3C2412_PWRCFG_STANDBYWFI_STOP (2<<6) +#define S3C2412_PWRCFG_STANDBYWFI_SLEEP (3<<6) +#define S3C2412_PWRCFG_STANDBYWFI_MASK (3<<6) + +#define S3C2412_PWRCFG_RTC_MASKIRQ (1<<8) +#define S3C2412_PWRCFG_NAND_NORST (1<<9) + +#endif /* __ASM_ARM_REGS_PWR */ diff --git a/include/asm-arm/dyntick.h b/include/asm-arm/dyntick.h new file mode 100644 index 000000000..19fab2d2b --- /dev/null +++ b/include/asm-arm/dyntick.h @@ -0,0 +1,6 @@ +#ifndef _ASMARM_DYNTICK_H +#define _ASMARM_DYNTICK_H + +#include <asm/mach/time.h> + +#endif /* _ASMARM_DYNTICK_H */ diff --git a/include/asm-arm/hw_irq.h b/include/asm-arm/hw_irq.h new file mode 100644 index 000000000..ea8569719 --- /dev/null +++ b/include/asm-arm/hw_irq.h @@ -0,0 +1,20 @@ +/* + * Nothing to see here yet + */ +#ifndef _ARCH_ARM_HW_IRQ_H +#define _ARCH_ARM_HW_IRQ_H + +#include <asm/mach/irq.h> + +#if defined(CONFIG_NO_IDLE_HZ) +# include <asm/dyntick.h> +# define handle_dynamic_tick(action) \ + if (!(action->flags & IRQF_TIMER) && system_timer->dyn_tick) { \ + write_seqlock(&xtime_lock); \ + if (system_timer->dyn_tick->state & DYN_TICK_ENABLED) \ + system_timer->dyn_tick->handler(irq, 0, regs); \ + write_sequnlock(&xtime_lock); \ + } +#endif + +#endif diff --git a/include/asm-arm/mach/serial_at91.h b/include/asm-arm/mach/serial_at91.h new file mode 100644 index 000000000..1290bb328 --- /dev/null +++ b/include/asm-arm/mach/serial_at91.h @@ -0,0 +1,33 @@ +/* + * linux/include/asm-arm/mach/serial_at91.h + * + * Based on serial_sa1100.h by Nicolas Pitre + * + * Copyright (C) 2002 ATMEL Rousset + * + * Low level machine dependent UART functions. + */ + +struct uart_port; + +/* + * This is a temporary structure for registering these + * functions; it is intended to be discarded after boot. + */ +struct at91_port_fns { + void (*set_mctrl)(struct uart_port *, u_int); + u_int (*get_mctrl)(struct uart_port *); + void (*enable_ms)(struct uart_port *); + void (*pm)(struct uart_port *, u_int, u_int); + int (*set_wake)(struct uart_port *, u_int); + int (*open)(struct uart_port *); + void (*close)(struct uart_port *); +}; + +#if defined(CONFIG_SERIAL_AT91) +void at91_register_uart_fns(struct at91_port_fns *fns); +#else +#define at91_register_uart_fns(fns) do { } while (0) +#endif + + diff --git a/include/asm-arm/page-nommu.h b/include/asm-arm/page-nommu.h new file mode 100644 index 000000000..a1bcad060 --- /dev/null +++ b/include/asm-arm/page-nommu.h @@ -0,0 +1,51 @@ +/* + * linux/include/asm-arm/page-nommu.h + * + * Copyright (C) 2004 Hyok S. Choi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef _ASMARM_PAGE_NOMMU_H +#define _ASMARM_PAGE_NOMMU_H + +#if !defined(CONFIG_SMALL_TASKS) && PAGE_SHIFT < 13 +#define KTHREAD_SIZE (8192) +#else +#define KTHREAD_SIZE PAGE_SIZE +#endif + +#define get_user_page(vaddr) __get_free_page(GFP_KERNEL) +#define free_user_page(page, addr) free_page(addr) + +#define clear_page(page) memset((page), 0, PAGE_SIZE) +#define copy_page(to,from) memcpy((to), (from), PAGE_SIZE) + +#define clear_user_page(page, vaddr, pg) clear_page(page) +#define copy_user_page(to, from, vaddr, pg) copy_page(to, from) + +/* + * These are used to make use of C type-checking.. + */ +typedef unsigned long pte_t; +typedef unsigned long pmd_t; +typedef unsigned long pgd_t[2]; +typedef unsigned long pgprot_t; + +#define pte_val(x) (x) +#define pmd_val(x) (x) +#define pgd_val(x) ((x)[0]) +#define pgprot_val(x) (x) + +#define __pte(x) (x) +#define __pmd(x) (x) +#define __pgprot(x) (x) + +/* to align the pointer to the (next) page boundary */ +#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) + +extern unsigned long memory_start; +extern unsigned long memory_end; + +#endif diff --git a/include/asm-arm/pgtable-nommu.h b/include/asm-arm/pgtable-nommu.h new file mode 100644 index 000000000..c1b264dff --- /dev/null +++ b/include/asm-arm/pgtable-nommu.h @@ -0,0 +1,122 @@ +/* + * linux/include/asm-arm/pgtable-nommu.h + * + * Copyright (C) 1995-2002 Russell King + * Copyright (C) 2004 Hyok S. Choi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef _ASMARM_PGTABLE_NOMMU_H +#define _ASMARM_PGTABLE_NOMMU_H + +#ifndef __ASSEMBLY__ + +#include <linux/slab.h> +#include <asm/processor.h> +#include <asm/page.h> +#include <asm/io.h> + +/* + * Trivial page table functions. + */ +#define pgd_present(pgd) (1) +#define pgd_none(pgd) (0) +#define pgd_bad(pgd) (0) +#define pgd_clear(pgdp) +#define kern_addr_valid(addr) (1) +#define pmd_offset(a, b) ((void *)0) +/* FIXME */ +/* + * PMD_SHIFT determines the size of the area a second-level page table can map + * PGDIR_SHIFT determines what a third-level page table entry can map + */ +#define PGDIR_SHIFT 21 + +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE-1)) +/* FIXME */ + +#define PAGE_NONE __pgprot(0) +#define PAGE_SHARED __pgprot(0) +#define PAGE_COPY __pgprot(0) +#define PAGE_READONLY __pgprot(0) +#define PAGE_KERNEL __pgprot(0) + +//extern void paging_init(struct meminfo *, struct machine_desc *); +#define swapper_pg_dir ((pgd_t *) 0) + +#define __swp_type(x) (0) +#define __swp_offset(x) (0) +#define __swp_entry(typ,off) ((swp_entry_t) { ((typ) | ((off) << 7)) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) + + +typedef pte_t *pte_addr_t; + +static inline int pte_file(pte_t pte) { return 0; } + +/* + * ZERO_PAGE is a global shared page that is always zero: used + * for zero-mapped memory areas etc.. + */ +#define ZERO_PAGE(vaddr) (virt_to_page(0)) + +/* + * Mark the prot value as uncacheable and unbufferable. + */ +#define pgprot_noncached(prot) __pgprot(0) +#define pgprot_writecombine(prot) __pgprot(0) + + +/* + * These would be in other places but having them here reduces the diffs. + */ +extern unsigned int kobjsize(const void *objp); +extern int is_in_rom(unsigned long); + +/* + * No page table caches to initialise. + */ +#define pgtable_cache_init() do { } while (0) +#define io_remap_page_range remap_page_range +#define io_remap_pfn_range remap_pfn_range + +#define MK_IOSPACE_PFN(space, pfn) (pfn) +#define GET_IOSPACE(pfn) 0 +#define GET_PFN(pfn) (pfn) + + +/* + * All 32bit addresses are effectively valid for vmalloc... + * Sort of meaningless for non-VM targets. + */ +#define VMALLOC_START 0 +#define VMALLOC_END 0xffffffff + +#define FIRST_USER_ADDRESS (0) + +#else + +/* + * dummy tlb and user structures. + */ +#define v3_tlb_fns (0) +#define v4_tlb_fns (0) +#define v4wb_tlb_fns (0) +#define v4wbi_tlb_fns (0) +#define v6_tlb_fns (0) + +#define v3_user_fns (0) +#define v4_user_fns (0) +#define v4_mc_user_fns (0) +#define v4wb_user_fns (0) +#define v4wt_user_fns (0) +#define v6_user_fns (0) +#define xscale_mc_user_fns (0) + +#endif /*__ASSEMBLY__*/ + +#endif /* _ASMARM_PGTABLE_H */ diff --git a/include/asm-arm/thread_notify.h b/include/asm-arm/thread_notify.h new file mode 100644 index 000000000..8866e5216 --- /dev/null +++ b/include/asm-arm/thread_notify.h @@ -0,0 +1,48 @@ +/* + * linux/include/asm-arm/thread_notify.h + * + * Copyright (C) 2006 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef ASMARM_THREAD_NOTIFY_H +#define ASMARM_THREAD_NOTIFY_H + +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ + +#include <linux/notifier.h> +#include <asm/thread_info.h> + +static inline int thread_register_notifier(struct notifier_block *n) +{ + extern struct atomic_notifier_head thread_notify_head; + return atomic_notifier_chain_register(&thread_notify_head, n); +} + +static inline void thread_unregister_notifier(struct notifier_block *n) +{ + extern struct atomic_notifier_head thread_notify_head; + atomic_notifier_chain_unregister(&thread_notify_head, n); +} + +static inline void thread_notify(unsigned long rc, struct thread_info *thread) +{ + extern struct atomic_notifier_head thread_notify_head; + atomic_notifier_call_chain(&thread_notify_head, rc, thread); +} + +#endif + +/* + * These are the reason codes for the thread notifier. + */ +#define THREAD_NOTIFY_FLUSH 0 +#define THREAD_NOTIFY_RELEASE 1 +#define THREAD_NOTIFY_SWITCH 2 + +#endif +#endif diff --git a/include/asm-cris/Kbuild b/include/asm-cris/Kbuild new file mode 100644 index 000000000..14498d5a2 --- /dev/null +++ b/include/asm-cris/Kbuild @@ -0,0 +1,5 @@ +include include/asm-generic/Kbuild.asm + +header-y += arch-v10/ arch-v32/ + +unifdef-y += rs485.h diff --git a/include/asm-cris/arch-v10/Kbuild b/include/asm-cris/arch-v10/Kbuild new file mode 100644 index 000000000..d7f27dc09 --- /dev/null +++ b/include/asm-cris/arch-v10/Kbuild @@ -0,0 +1,2 @@ +header-y += ptrace.h +header-y += user.h diff --git a/include/asm-cris/arch-v32/Kbuild b/include/asm-cris/arch-v32/Kbuild new file mode 100644 index 000000000..d7f27dc09 --- /dev/null +++ b/include/asm-cris/arch-v32/Kbuild @@ -0,0 +1,2 @@ +header-y += ptrace.h +header-y += user.h diff --git a/include/asm-frv/Kbuild b/include/asm-frv/Kbuild new file mode 100644 index 000000000..c68e1680d --- /dev/null +++ b/include/asm-frv/Kbuild @@ -0,0 +1 @@ +include include/asm-generic/Kbuild.asm diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild new file mode 100644 index 000000000..3c06be381 --- /dev/null +++ b/include/asm-generic/Kbuild @@ -0,0 +1,12 @@ +header-y += atomic.h +header-y += errno-base.h +header-y += errno.h +header-y += fcntl.h +header-y += ioctl.h +header-y += ipc.h +header-y += mman.h +header-y += signal.h +header-y += statfs.h + +unifdef-y += resource.h +unifdef-y += siginfo.h diff --git a/include/asm-generic/Kbuild.asm b/include/asm-generic/Kbuild.asm new file mode 100644 index 000000000..a84c3d88a --- /dev/null +++ b/include/asm-generic/Kbuild.asm @@ -0,0 +1,34 @@ +unifdef-y += a.out.h +unifdef-y += auxvec.h +unifdef-y += byteorder.h +unifdef-y += errno.h +unifdef-y += fcntl.h +unifdef-y += ioctl.h +unifdef-y += ioctls.h +unifdef-y += ipcbuf.h +unifdef-y += mman.h +unifdef-y += msgbuf.h +unifdef-y += param.h +unifdef-y += poll.h +unifdef-y += posix_types.h +unifdef-y += ptrace.h +unifdef-y += resource.h +unifdef-y += sembuf.h +unifdef-y += shmbuf.h +unifdef-y += sigcontext.h +unifdef-y += siginfo.h +unifdef-y += signal.h +unifdef-y += socket.h +unifdef-y += sockios.h +unifdef-y += stat.h +unifdef-y += statfs.h +unifdef-y += termbits.h +unifdef-y += termios.h +unifdef-y += types.h +unifdef-y += unistd.h +unifdef-y += user.h + +# These probably shouldn't be exported +unifdef-y += shmparam.h +unifdef-y += elf.h +unifdef-y += page.h diff --git a/include/asm-generic/audit_change_attr.h b/include/asm-generic/audit_change_attr.h new file mode 100644 index 000000000..50764550a --- /dev/null +++ b/include/asm-generic/audit_change_attr.h @@ -0,0 +1,22 @@ +__NR_chmod, +__NR_fchmod, +#ifdef __NR_chown +__NR_chown, +__NR_fchown, +__NR_lchown, +#endif +__NR_setxattr, +__NR_lsetxattr, +__NR_fsetxattr, +__NR_removexattr, +__NR_lremovexattr, +__NR_fremovexattr, +#ifdef __NR_fchownat +__NR_fchownat, +__NR_fchmodat, +#endif +#ifdef __NR_chown32 +__NR_chown32, +__NR_fchown32, +__NR_lchown32, +#endif diff --git a/include/asm-generic/audit_dir_write.h b/include/asm-generic/audit_dir_write.h new file mode 100644 index 000000000..6621bd82c --- /dev/null +++ b/include/asm-generic/audit_dir_write.h @@ -0,0 +1,18 @@ +__NR_rename, +__NR_mkdir, +__NR_rmdir, +#ifdef __NR_creat +__NR_creat, +#endif +__NR_link, +__NR_unlink, +__NR_symlink, +__NR_mknod, +#ifdef __NR_mkdirat +__NR_mkdirat, +__NR_mknodat, +__NR_unlinkat, +__NR_renameat, +__NR_linkat, +__NR_symlinkat, +#endif diff --git a/include/asm-generic/audit_read.h b/include/asm-generic/audit_read.h new file mode 100644 index 000000000..0e87464d9 --- /dev/null +++ b/include/asm-generic/audit_read.h @@ -0,0 +1,8 @@ +__NR_readlink, +__NR_quotactl, +__NR_listxattr, +__NR_llistxattr, +__NR_flistxattr, +__NR_getxattr, +__NR_lgetxattr, +__NR_fgetxattr, diff --git a/include/asm-generic/audit_write.h b/include/asm-generic/audit_write.h new file mode 100644 index 000000000..f10d367fb --- /dev/null +++ b/include/asm-generic/audit_write.h @@ -0,0 +1,11 @@ +#include <asm-generic/audit_dir_write.h> +__NR_acct, +__NR_swapon, +__NR_quotactl, +__NR_truncate, +#ifdef __NR_truncate64 +__NR_truncate64, +#endif +#ifdef __NR_bind +__NR_bind, /* bind can affect fs object only in one way... */ +#endif diff --git a/include/asm-h8300/Kbuild b/include/asm-h8300/Kbuild new file mode 100644 index 000000000..c68e1680d --- /dev/null +++ b/include/asm-h8300/Kbuild @@ -0,0 +1 @@ +include include/asm-generic/Kbuild.asm diff --git a/include/asm-i386/Kbuild b/include/asm-i386/Kbuild new file mode 100644 index 000000000..b75a348d0 --- /dev/null +++ b/include/asm-i386/Kbuild @@ -0,0 +1,10 @@ +include include/asm-generic/Kbuild.asm + +header-y += boot.h +header-y += debugreg.h +header-y += ldt.h +header-y += ucontext.h + +unifdef-y += mtrr.h +unifdef-y += setup.h +unifdef-y += vm86.h diff --git a/include/asm-i386/dwarf2.h b/include/asm-i386/dwarf2.h new file mode 100644 index 000000000..5d1a8db5a --- /dev/null +++ b/include/asm-i386/dwarf2.h @@ -0,0 +1,54 @@ +#ifndef _DWARF2_H +#define _DWARF2_H + +#ifndef __ASSEMBLY__ +#warning "asm/dwarf2.h should be only included in pure assembly files" +#endif + +/* + Macros for dwarf2 CFI unwind table entries. + See "as.info" for details on these pseudo ops. Unfortunately + they are only supported in very new binutils, so define them + away for older version. + */ + +#ifdef CONFIG_UNWIND_INFO + +#define CFI_STARTPROC .cfi_startproc +#define CFI_ENDPROC .cfi_endproc +#define CFI_DEF_CFA .cfi_def_cfa +#define CFI_DEF_CFA_REGISTER .cfi_def_cfa_register +#define CFI_DEF_CFA_OFFSET .cfi_def_cfa_offset +#define CFI_ADJUST_CFA_OFFSET .cfi_adjust_cfa_offset +#define CFI_OFFSET .cfi_offset +#define CFI_REL_OFFSET .cfi_rel_offset +#define CFI_REGISTER .cfi_register +#define CFI_RESTORE .cfi_restore +#define CFI_REMEMBER_STATE .cfi_remember_state +#define CFI_RESTORE_STATE .cfi_restore_state +#define CFI_UNDEFINED .cfi_undefined + +#else + +/* Due to the structure of pre-exisiting code, don't use assembler line + comment character # to ignore the arguments. Instead, use a dummy macro. */ +.macro ignore a=0, b=0, c=0, d=0 +.endm + +#define CFI_STARTPROC ignore +#define CFI_ENDPROC ignore +#define CFI_DEF_CFA ignore +#define CFI_DEF_CFA_REGISTER ignore +#define CFI_DEF_CFA_OFFSET ignore +#define CFI_ADJUST_CFA_OFFSET ignore +#define CFI_OFFSET ignore +#define CFI_REL_OFFSET ignore +#define CFI_REGISTER ignore +#define CFI_RESTORE ignore +#define CFI_REMEMBER_STATE ignore +#define CFI_RESTORE_STATE ignore +#define CFI_UNDEFINED ignore + +#endif + +#endif diff --git a/include/asm-i386/intel_arch_perfmon.h b/include/asm-i386/intel_arch_perfmon.h new file mode 100644 index 000000000..134ea9cc5 --- /dev/null +++ b/include/asm-i386/intel_arch_perfmon.h @@ -0,0 +1,19 @@ +#ifndef X86_INTEL_ARCH_PERFMON_H +#define X86_INTEL_ARCH_PERFMON_H 1 + +#define MSR_ARCH_PERFMON_PERFCTR0 0xc1 +#define MSR_ARCH_PERFMON_PERFCTR1 0xc2 + +#define MSR_ARCH_PERFMON_EVENTSEL0 0x186 +#define MSR_ARCH_PERFMON_EVENTSEL1 0x187 + +#define ARCH_PERFMON_EVENTSEL0_ENABLE (1 << 22) +#define ARCH_PERFMON_EVENTSEL_INT (1 << 20) +#define ARCH_PERFMON_EVENTSEL_OS (1 << 17) +#define ARCH_PERFMON_EVENTSEL_USR (1 << 16) + +#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL (0x3c) +#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8) +#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT (1 << 0) + +#endif /* X86_INTEL_ARCH_PERFMON_H */ diff --git a/include/asm-i386/irqflags.h b/include/asm-i386/irqflags.h new file mode 100644 index 000000000..e1bdb97c0 --- /dev/null +++ b/include/asm-i386/irqflags.h @@ -0,0 +1,127 @@ +/* + * include/asm-i386/irqflags.h + * + * IRQ flags handling + * + * This file gets included from lowlevel asm headers too, to provide + * wrapped versions of the local_irq_*() APIs, based on the + * raw_local_irq_*() functions from the lowlevel headers. + */ +#ifndef _ASM_IRQFLAGS_H +#define _ASM_IRQFLAGS_H + +#ifndef __ASSEMBLY__ + +static inline unsigned long __raw_local_save_flags(void) +{ + unsigned long flags; + + __asm__ __volatile__( + "pushfl ; popl %0" + : "=g" (flags) + : /* no input */ + ); + + return flags; +} + +#define raw_local_save_flags(flags) \ + do { (flags) = __raw_local_save_flags(); } while (0) + +static inline void raw_local_irq_restore(unsigned long flags) +{ + __asm__ __volatile__( + "pushl %0 ; popfl" + : /* no output */ + :"g" (flags) + :"memory", "cc" + ); +} + +static inline void raw_local_irq_disable(void) +{ + __asm__ __volatile__("cli" : : : "memory"); +} + +static inline void raw_local_irq_enable(void) +{ + __asm__ __volatile__("sti" : : : "memory"); +} + +/* + * Used in the idle loop; sti takes one instruction cycle + * to complete: + */ +static inline void raw_safe_halt(void) +{ + __asm__ __volatile__("sti; hlt" : : : "memory"); +} + +/* + * Used when interrupts are already enabled or to + * shutdown the processor: + */ +static inline void halt(void) +{ + __asm__ __volatile__("hlt": : :"memory"); +} + +static inline int raw_irqs_disabled_flags(unsigned long flags) +{ + return !(flags & (1 << 9)); +} + +static inline int raw_irqs_disabled(void) +{ + unsigned long flags = __raw_local_save_flags(); + + return raw_irqs_disabled_flags(flags); +} + +/* + * For spinlocks, etc: + */ +static inline unsigned long __raw_local_irq_save(void) +{ + unsigned long flags = __raw_local_save_flags(); + + raw_local_irq_disable(); + + return flags; +} + +#define raw_local_irq_save(flags) \ + do { (flags) = __raw_local_irq_save(); } while (0) + +#endif /* __ASSEMBLY__ */ + +/* + * Do the CPU's IRQ-state tracing from assembly code. We call a + * C function, so save all the C-clobbered registers: + */ +#ifdef CONFIG_TRACE_IRQFLAGS + +# define TRACE_IRQS_ON \ + pushl %eax; \ + pushl %ecx; \ + pushl %edx; \ + call trace_hardirqs_on; \ + popl %edx; \ + popl %ecx; \ + popl %eax; + +# define TRACE_IRQS_OFF \ + pushl %eax; \ + pushl %ecx; \ + pushl %edx; \ + call trace_hardirqs_off; \ + popl %edx; \ + popl %ecx; \ + popl %eax; + +#else +# define TRACE_IRQS_ON +# define TRACE_IRQS_OFF +#endif + +#endif diff --git a/include/asm-i386/k8.h b/include/asm-i386/k8.h new file mode 100644 index 000000000..dfd88a6e6 --- /dev/null +++ b/include/asm-i386/k8.h @@ -0,0 +1 @@ +#include <asm-x86_64/k8.h> diff --git a/include/asm-i386/mach-default/setup_arch.h b/include/asm-i386/mach-default/setup_arch.h new file mode 100644 index 000000000..fb42099e7 --- /dev/null +++ b/include/asm-i386/mach-default/setup_arch.h @@ -0,0 +1,5 @@ +/* Hook to call BIOS initialisation function */ + +/* no action for generic */ + +#define ARCH_SETUP diff --git a/include/asm-i386/mach-visws/setup_arch.h b/include/asm-i386/mach-visws/setup_arch.h new file mode 100644 index 000000000..33f700ef6 --- /dev/null +++ b/include/asm-i386/mach-visws/setup_arch.h @@ -0,0 +1,8 @@ +/* Hook to call BIOS initialisation function */ + +extern unsigned long sgivwfb_mem_phys; +extern unsigned long sgivwfb_mem_size; + +/* no action for visws */ + +#define ARCH_SETUP diff --git a/include/asm-i386/mach-voyager/setup_arch.h b/include/asm-i386/mach-voyager/setup_arch.h new file mode 100644 index 000000000..84d01ad33 --- /dev/null +++ b/include/asm-i386/mach-voyager/setup_arch.h @@ -0,0 +1,10 @@ +#include <asm/voyager.h> +#define VOYAGER_BIOS_INFO ((struct voyager_bios_info *)(PARAM+0x40)) + +/* Hook to call BIOS initialisation function */ + +/* for voyager, pass the voyager BIOS/SUS info area to the detection + * routines */ + +#define ARCH_SETUP voyager_detect(VOYAGER_BIOS_INFO); + diff --git a/include/asm-i386/mach-xen/asm/irqflags.h b/include/asm-i386/mach-xen/asm/irqflags.h new file mode 100644 index 000000000..dc7fd071a --- /dev/null +++ b/include/asm-i386/mach-xen/asm/irqflags.h @@ -0,0 +1,80 @@ +/* + * include/asm-i386/irqflags.h + * + * IRQ flags handling + * + * This file gets included from lowlevel asm headers too, to provide + * wrapped versions of the local_irq_*() APIs, based on the + * raw_local_irq_*() functions from the lowlevel headers. + */ +#ifndef _ASM_IRQFLAGS_H +#define _ASM_IRQFLAGS_H + +#ifndef __ASSEMBLY__ + +#define raw_local_save_flags(flags) \ + do { (flags) = __raw_local_save_flags(); } while (0) + +unsigned long __raw_local_save_flags(void); +void raw_local_irq_restore(unsigned long flags); +void raw_local_irq_disable(void); +void raw_local_irq_enable(void); + +/* + * Used in the idle loop; sti takes one instruction cycle + * to complete: + */ +void raw_safe_halt(void); + +/* + * Used when interrupts are already enabled or to + * shutdown the processor: + */ +void halt(void); + +static inline int raw_irqs_disabled_flags(unsigned long flags) +{ + return flags != 0; +} + +int raw_irqs_disabled(void); + +/* + * For spinlocks, etc: + */ +unsigned long __raw_local_irq_save(void); +#define raw_local_irq_save(flags) \ + do { (flags) = __raw_local_irq_save(); } while (0) + +#endif /* __ASSEMBLY__ */ + +/* + * Do the CPU's IRQ-state tracing from assembly code. We call a + * C function, so save all the C-clobbered registers: + */ +#ifdef CONFIG_TRACE_IRQFLAGS + +# define TRACE_IRQS_ON \ + pushl %eax; \ + pushl %ecx; \ + pushl %edx; \ + call trace_hardirqs_on; \ + popl %edx; \ + popl %ecx; \ + popl %eax; + +# define TRACE_IRQS_OFF \ + pushl %eax; \ + pushl %ecx; \ + pushl %edx; \ + call trace_hardirqs_off; \ + popl %edx; \ + popl %ecx; \ + popl %eax; + +#else +# define TRACE_IRQS_ON +# define TRACE_IRQS_OFF +#endif + +#endif diff --git a/include/asm-i386/mach-xen/asm/maddr.h b/include/asm-i386/mach-xen/asm/maddr.h new file mode 100644 index 000000000..b467320d5 --- /dev/null +++ b/include/asm-i386/mach-xen/asm/maddr.h @@ -0,0 +1,160 @@ +#ifndef _I386_MADDR_H +#define _I386_MADDR_H + +#include <xen/features.h> +#include <xen/interface/xen.h> + +/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/ +#define INVALID_P2M_ENTRY (~0UL) +#define FOREIGN_FRAME_BIT (1UL<<31) +#define FOREIGN_FRAME(m) ((m) | FOREIGN_FRAME_BIT) + +#ifdef CONFIG_XEN + +extern unsigned long *phys_to_machine_mapping; + +#undef machine_to_phys_mapping +extern unsigned long *machine_to_phys_mapping; +extern unsigned int machine_to_phys_order; + +static inline unsigned long pfn_to_mfn(unsigned long pfn) +{ + if (xen_feature(XENFEAT_auto_translated_physmap)) + return pfn; + return phys_to_machine_mapping[(unsigned int)(pfn)] & + ~FOREIGN_FRAME_BIT; +} + +static inline int phys_to_machine_mapping_valid(unsigned long pfn) +{ + if (xen_feature(XENFEAT_auto_translated_physmap)) + return 1; + return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY); +} + +static inline unsigned long mfn_to_pfn(unsigned long mfn) +{ + extern unsigned long max_mapnr; + unsigned long pfn; + + if (xen_feature(XENFEAT_auto_translated_physmap)) + return mfn; + + if (unlikely((mfn >> machine_to_phys_order) != 0)) + return max_mapnr; + + /* The array access can fail (e.g., device space beyond end of RAM). */ + asm ( + "1: movl %1,%0\n" + "2:\n" + ".section .fixup,\"ax\"\n" + "3: movl %2,%0\n" + " jmp 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,3b\n" + ".previous" + : "=r" (pfn) + : "m" (machine_to_phys_mapping[mfn]), "m" (max_mapnr) ); + + return pfn; +} + +/* + * We detect special mappings in one of two ways: + * 1. If the MFN is an I/O page then Xen will set the m2p entry + * to be outside our maximum possible pseudophys range. + * 2. If the MFN belongs to a different domain then we will certainly + * not have MFN in our p2m table. Conversely, if the page is ours, + * then we'll have p2m(m2p(MFN))==MFN. + * If we detect a special mapping then it doesn't have a 'struct page'. + * We force !pfn_valid() by returning an out-of-range pointer. + * + * NB. These checks require that, for any MFN that is not in our reservation, + * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if + * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN. + * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety. + * + * NB2. When deliberately mapping foreign pages into the p2m table, you *must* + * use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we + * require. In all the cases we care about, the FOREIGN_FRAME bit is + * masked (e.g., pfn_to_mfn()) so behaviour there is correct. + */ +static inline unsigned long mfn_to_local_pfn(unsigned long mfn) +{ + extern unsigned long max_mapnr; + unsigned long pfn = mfn_to_pfn(mfn); + if ((pfn < max_mapnr) + && !xen_feature(XENFEAT_auto_translated_physmap) + && (phys_to_machine_mapping[pfn] != mfn)) + return max_mapnr; /* force !pfn_valid() */ + return pfn; +} + +static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn) +{ + if (xen_feature(XENFEAT_auto_translated_physmap)) { + BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); + return; + } + phys_to_machine_mapping[pfn] = mfn; +} + + +#else /* !CONFIG_XEN */ + +#define pfn_to_mfn(pfn) (pfn) +#define mfn_to_pfn(mfn) (mfn) +#define mfn_to_local_pfn(mfn) (mfn) +#define set_phys_to_machine(pfn, mfn) BUG_ON((pfn) != (mfn)) +#define phys_to_machine_mapping_valid(pfn) (1) + +#endif /* !CONFIG_XEN */ + +/* Definitions for machine and pseudophysical addresses. */ +#ifdef CONFIG_X86_PAE +typedef unsigned long long paddr_t; +typedef unsigned long long maddr_t; +#else +typedef unsigned long paddr_t; +typedef unsigned long maddr_t; +#endif + +static inline maddr_t phys_to_machine(paddr_t phys) +{ + maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT); + machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK); + return machine; +} +static inline paddr_t machine_to_phys(maddr_t machine) +{ + paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT); + phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK); + return phys; +} + +/* VIRT <-> MACHINE conversion */ +#define virt_to_machine(v) (phys_to_machine(__pa(v))) +#define virt_to_mfn(v) (pfn_to_mfn(__pa(v) >> PAGE_SHIFT)) +#define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT)) + +#ifdef CONFIG_X86_PAE +static inline pte_t pfn_pte_ma(unsigned long page_nr, pgprot_t pgprot) +{ + pte_t pte; + + pte.pte_high = (page_nr >> (32 - PAGE_SHIFT)) | \ + (pgprot_val(pgprot) >> 32); + pte.pte_high &= (__supported_pte_mask >> 32); + pte.pte_low = ((page_nr << PAGE_SHIFT) | pgprot_val(pgprot)) & \ + __supported_pte_mask; + return pte; +} +#else +#define pfn_pte_ma(pfn, prot) __pte_ma(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) +#endif + +#define __pte_ma(x) ((pte_t) { (x) } ) + +#endif /* _I386_MADDR_H */ diff --git a/include/asm-i386/mach-xen/asm/stacktrace.h b/include/asm-i386/mach-xen/asm/stacktrace.h new file mode 100644 index 000000000..5eb9799be --- /dev/null +++ b/include/asm-i386/mach-xen/asm/stacktrace.h @@ -0,0 +1,18 @@ +#ifndef _ASM_STACKTRACE_H +#define _ASM_STACKTRACE_H 1 + +/* Generic stack tracer with callbacks */ + +struct stacktrace_ops { + void (*warning)(void *data, char *msg); + /* msg must contain %s for the symbol */ + void (*warning_symbol)(void *data, char *msg, unsigned long symbol); + void (*address)(void *data, unsigned long address); + /* On negative return stop dumping */ + int (*stack)(void *data, char *name); +}; + +void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack, + struct stacktrace_ops *ops, void *data); + +#endif diff --git a/include/asm-i386/mach-xen/asm/timer.h b/include/asm-i386/mach-xen/asm/timer.h new file mode 100644 index 000000000..aed164374 --- /dev/null +++ b/include/asm-i386/mach-xen/asm/timer.h @@ -0,0 +1,70 @@ +#ifndef _ASMi386_TIMER_H +#define _ASMi386_TIMER_H +#include <linux/init.h> +#include <linux/pm.h> + +/** + * struct timer_ops - used to define a timer source + * + * @name: name of the timer. + * @init: Probes and initializes the timer. Takes clock= override + * string as an argument. Returns 0 on success, anything else + * on failure. + * @mark_offset: called by the timer interrupt. + * @get_offset: called by gettimeofday(). Returns the number of microseconds + * since the last timer interupt. + * @monotonic_clock: returns the number of nanoseconds since the init of the + * timer. + * @delay: delays this many clock cycles. + */ +struct timer_opts { + char* name; + void (*mark_offset)(void); + unsigned long (*get_offset)(void); + unsigned long long (*monotonic_clock)(void); + void (*delay)(unsigned long); + unsigned long (*read_timer)(void); + int (*suspend)(pm_message_t state); + int (*resume)(void); +}; + +struct init_timer_opts { + int (*init)(char *override); + struct timer_opts *opts; +}; + +#define TICK_SIZE (tick_nsec / 1000) + +extern struct timer_opts* __init select_timer(void); +extern void clock_fallback(void); +void setup_pit_timer(void); + +/* Modifiers for buggy PIT handling */ + +extern int pit_latch_buggy; + +extern struct timer_opts *cur_timer; +extern int timer_ack; + +/* list of externed timers */ +extern struct timer_opts timer_none; +extern struct timer_opts timer_pit; +extern struct init_timer_opts timer_pit_init; +extern struct init_timer_opts timer_tsc_init; +#ifdef CONFIG_X86_CYCLONE_TIMER +extern struct init_timer_opts timer_cyclone_init; +#endif + +extern unsigned long calibrate_tsc(void); +extern unsigned long read_timer_tsc(void); +extern void init_cpu_khz(void); +extern int recalibrate_cpu_khz(void); +#ifdef CONFIG_HPET_TIMER +extern struct init_timer_opts timer_hpet_init; +extern unsigned long calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr); +#endif + +#ifdef CONFIG_X86_PM_TIMER +extern struct init_timer_opts timer_pmtmr_init; +#endif +#endif diff --git a/include/asm-i386/mach-xen/setup_arch.h b/include/asm-i386/mach-xen/setup_arch.h new file mode 100644 index 000000000..ad1995778 --- /dev/null +++ b/include/asm-i386/mach-xen/setup_arch.h @@ -0,0 +1,5 @@ +/* Hook to call BIOS initialisation function */ + +#define ARCH_SETUP machine_specific_arch_setup(); + +void __init machine_specific_arch_setup(void); diff --git a/include/asm-i386/mce.h b/include/asm-i386/mce.h new file mode 100644 index 000000000..7cc1a973b --- /dev/null +++ b/include/asm-i386/mce.h @@ -0,0 +1,5 @@ +#ifdef CONFIG_X86_MCE +extern void mcheck_init(struct cpuinfo_x86 *c); +#else +#define mcheck_init(c) do {} while(0) +#endif diff --git a/include/asm-i386/stacktrace.h b/include/asm-i386/stacktrace.h new file mode 100644 index 000000000..7d1f6a5cb --- /dev/null +++ b/include/asm-i386/stacktrace.h @@ -0,0 +1 @@ +#include <asm-x86_64/stacktrace.h> diff --git a/include/asm-i386/tracehook.h b/include/asm-i386/tracehook.h new file mode 100644 index 000000000..ca49dbf78 --- /dev/null +++ b/include/asm-i386/tracehook.h @@ -0,0 +1,49 @@ +/* + * Tracing hooks, i386 CPU support + */ + +#ifndef _ASM_TRACEHOOK_H +#define _ASM_TRACEHOOK_H 1 + +#include <linux/sched.h> +#include <asm/ptrace.h> + +/* + * See linux/tracehook.h for the descriptions of what these need to do. + */ + +#define ARCH_HAS_SINGLE_STEP (1) + +/* These two are defined in arch/i386/kernel/ptrace.c. */ +void tracehook_enable_single_step(struct task_struct *tsk); +void tracehook_disable_single_step(struct task_struct *tsk); + +static inline int tracehook_single_step_enabled(struct task_struct *tsk) +{ + return test_tsk_thread_flag(tsk, TIF_SINGLESTEP); +} + +static inline void tracehook_enable_syscall_trace(struct task_struct *tsk) +{ + set_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE); +} + +static inline void tracehook_disable_syscall_trace(struct task_struct *tsk) +{ + clear_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE); +} + +static inline void tracehook_abort_syscall(struct pt_regs *regs) +{ + regs->orig_eax = -1; +} + +extern const struct utrace_regset_view utrace_i386_native; +static inline const struct utrace_regset_view * +utrace_native_view(struct task_struct *tsk) +{ + return &utrace_i386_native; +} + + +#endif diff --git a/include/asm-i386/tsc.h b/include/asm-i386/tsc.h new file mode 100644 index 000000000..c13933185 --- /dev/null +++ b/include/asm-i386/tsc.h @@ -0,0 +1,48 @@ +/* + * linux/include/asm-i386/tsc.h + * + * i386 TSC related functions + */ +#ifndef _ASM_i386_TSC_H +#define _ASM_i386_TSC_H + +#include <asm/processor.h> + +/* + * Standard way to access the cycle counter on i586+ CPUs. + * Currently only used on SMP. + * + * If you really have a SMP machine with i486 chips or older, + * compile for that, and this will just always return zero. + * That's ok, it just means that the nicer scheduling heuristics + * won't work for you. + * + * We only use the low 32 bits, and we'd simply better make sure + * that we reschedule before that wraps. Scheduling at least every + * four billion cycles just basically sounds like a good idea, + * regardless of how fast the machine is. + */ +typedef unsigned long long cycles_t; + +extern unsigned int cpu_khz; +extern unsigned int tsc_khz; + +static inline cycles_t get_cycles(void) +{ + unsigned long long ret = 0; + +#ifndef CONFIG_X86_TSC + if (!cpu_has_tsc) + return 0; +#endif + +#if defined(CONFIG_X86_GENERIC) || defined(CONFIG_X86_TSC) + rdtscll(ret); +#endif + return ret; +} + +extern void tsc_init(void); +extern void mark_tsc_unstable(void); + +#endif diff --git a/include/asm-i386/unwind.h b/include/asm-i386/unwind.h new file mode 100644 index 000000000..f0ac399ba --- /dev/null +++ b/include/asm-i386/unwind.h @@ -0,0 +1,102 @@ +#ifndef _ASM_I386_UNWIND_H +#define _ASM_I386_UNWIND_H + +/* + * Copyright (C) 2002-2006 Novell, Inc. + * Jan Beulich <jbeulich@novell.com> + * This code is released under version 2 of the GNU GPL. + */ + +#ifdef CONFIG_STACK_UNWIND + +#include <linux/sched.h> +#include <asm/fixmap.h> +#include <asm/ptrace.h> +#include <asm/uaccess.h> + +struct unwind_frame_info +{ + struct pt_regs regs; + struct task_struct *task; +}; + +#define UNW_PC(frame) (frame)->regs.eip +#define UNW_SP(frame) (frame)->regs.esp +#ifdef CONFIG_FRAME_POINTER +#define UNW_FP(frame) (frame)->regs.ebp +#define FRAME_RETADDR_OFFSET 4 +#define FRAME_LINK_OFFSET 0 +#define STACK_BOTTOM(tsk) STACK_LIMIT((tsk)->thread.esp0) +#define STACK_TOP(tsk) ((tsk)->thread.esp0) +#else +#define UNW_FP(frame) ((void)(frame), 0) +#endif +#define STACK_LIMIT(ptr) (((ptr) - 1) & ~(THREAD_SIZE - 1)) + +#define UNW_REGISTER_INFO \ + PTREGS_INFO(eax), \ + PTREGS_INFO(ecx), \ + PTREGS_INFO(edx), \ + PTREGS_INFO(ebx), \ + PTREGS_INFO(esp), \ + PTREGS_INFO(ebp), \ + PTREGS_INFO(esi), \ + PTREGS_INFO(edi), \ + PTREGS_INFO(eip) + +static inline void arch_unw_init_frame_info(struct unwind_frame_info *info, + /*const*/ struct pt_regs *regs) +{ + if (user_mode_vm(regs)) + info->regs = *regs; + else { + memcpy(&info->regs, regs, offsetof(struct pt_regs, esp)); + info->regs.esp = (unsigned long)®s->esp; + info->regs.xss = __KERNEL_DS; + } +} + +static inline void arch_unw_init_blocked(struct unwind_frame_info *info) +{ + memset(&info->regs, 0, sizeof(info->regs)); + info->regs.eip = info->task->thread.eip; + info->regs.xcs = __KERNEL_CS; + __get_user(info->regs.ebp, (long *)info->task->thread.esp); + info->regs.esp = info->task->thread.esp; + info->regs.xss = __KERNEL_DS; + info->regs.xds = __USER_DS; + info->regs.xes = __USER_DS; +} + +extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *, + asmlinkage int (*callback)(struct unwind_frame_info *, + void *arg), + void *arg); + +static inline int arch_unw_user_mode(const struct unwind_frame_info *info) +{ +#if 0 /* This can only work when selector register and EFLAGS saves/restores + are properly annotated (and tracked in UNW_REGISTER_INFO). */ + return user_mode_vm(&info->regs); +#else + return info->regs.eip < PAGE_OFFSET + || (info->regs.eip >= __fix_to_virt(FIX_VDSO) + && info->regs.eip < __fix_to_virt(FIX_VDSO) + PAGE_SIZE) + || info->regs.esp < PAGE_OFFSET; +#endif +} + +#else + +#define UNW_PC(frame) ((void)(frame), 0) +#define UNW_SP(frame) ((void)(frame), 0) +#define UNW_FP(frame) ((void)(frame), 0) + +static inline int arch_unw_user_mode(const void *info) +{ + return 0; +} + +#endif + +#endif /* _ASM_I386_UNWIND_H */ diff --git a/include/asm-ia64/Kbuild b/include/asm-ia64/Kbuild new file mode 100644 index 000000000..15818a18b --- /dev/null +++ b/include/asm-ia64/Kbuild @@ -0,0 +1,17 @@ +include include/asm-generic/Kbuild.asm + +header-y += break.h +header-y += fpu.h +header-y += fpswa.h +header-y += gcc_intrin.h +header-y += ia64regs.h +header-y += intel_intrin.h +header-y += intrinsics.h +header-y += perfmon_default_smpl.h +header-y += ptrace_offsets.h +header-y += rse.h +header-y += setup.h +header-y += ucontext.h + +unifdef-y += perfmon.h +unifdef-y += ustack.h diff --git a/include/asm-ia64/fixmap.h b/include/asm-ia64/fixmap.h new file mode 100644 index 000000000..4b32a8298 --- /dev/null +++ b/include/asm-ia64/fixmap.h @@ -0,0 +1,2 @@ +#define clear_fixmap(x) do {} while (0) +#define set_fixmap(x,y) do {} while (0) diff --git a/include/asm-ia64/hypercall.h b/include/asm-ia64/hypercall.h new file mode 100644 index 000000000..837533694 --- /dev/null +++ b/include/asm-ia64/hypercall.h @@ -0,0 +1,423 @@ +/****************************************************************************** + * hypercall.h + * + * Linux-specific hypervisor handling. + * + * Copyright (c) 2002-2004, K A Fraser + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef __HYPERCALL_H__ +#define __HYPERCALL_H__ + +#include <linux/string.h> /* memcpy() */ + +#ifndef __HYPERVISOR_H__ +# error "please don't include this file directly" +#endif + +/* + * Assembler stubs for hyper-calls. + */ + +#define _hypercall0(type, name) \ +({ \ + long __res; \ + __asm__ __volatile__ (";;\n" \ + "mov r2=%1\n" \ + "break 0x1000 ;;\n" \ + "mov %0=r8 ;;\n" \ + : "=r" (__res) \ + : "J" (__HYPERVISOR_##name) \ + : "r2","r8", \ + "memory" ); \ + (type)__res; \ +}) + +#define _hypercall1(type, name, a1) \ +({ \ + long __res; \ + __asm__ __volatile__ (";;\n" \ + "mov r14=%2\n" \ + "mov r2=%1\n" \ + "break 0x1000 ;;\n" \ + "mov %0=r8 ;;\n" \ + : "=r" (__res) \ + : "J" (__HYPERVISOR_##name), \ + "rI" ((unsigned long)(a1)) \ + : "r14","r2","r8", \ + "memory" ); \ + (type)__res; \ +}) + +#define _hypercall2(type, name, a1, a2) \ +({ \ + long __res; \ + __asm__ __volatile__ (";;\n" \ + "mov r14=%2\n" \ + "mov r15=%3\n" \ + "mov r2=%1\n" \ + "break 0x1000 ;;\n" \ + "mov %0=r8 ;;\n" \ + : "=r" (__res) \ + : "J" (__HYPERVISOR_##name), \ + "rI" ((unsigned long)(a1)), \ + "rI" ((unsigned long)(a2)) \ + : "r14","r15","r2","r8", \ + "memory" ); \ + (type)__res; \ +}) + +#define _hypercall3(type, name, a1, a2, a3) \ +({ \ + long __res; \ + __asm__ __volatile__ (";;\n" \ + "mov r14=%2\n" \ + "mov r15=%3\n" \ + "mov r16=%4\n" \ + "mov r2=%1\n" \ + "break 0x1000 ;;\n" \ + "mov %0=r8 ;;\n" \ + : "=r" (__res) \ + : "J" (__HYPERVISOR_##name), \ + "rI" ((unsigned long)(a1)), \ + "rI" ((unsigned long)(a2)), \ + "rI" ((unsigned long)(a3)) \ + : "r14","r15","r16","r2","r8", \ + "memory" ); \ + (type)__res; \ +}) + +#define _hypercall4(type, name, a1, a2, a3, a4) \ +({ \ + long __res; \ + __asm__ __volatile__ (";;\n" \ + "mov r14=%2\n" \ + "mov r15=%3\n" \ + "mov r16=%4\n" \ + "mov r17=%5\n" \ + "mov r2=%1\n" \ + "break 0x1000 ;;\n" \ + "mov %0=r8 ;;\n" \ + : "=r" (__res) \ + : "J" (__HYPERVISOR_##name), \ + "rI" ((unsigned long)(a1)), \ + "rI" ((unsigned long)(a2)), \ + "rI" ((unsigned long)(a3)), \ + "rI" ((unsigned long)(a4)) \ + : "r14","r15","r16","r2","r8", \ + "r17","memory" ); \ + (type)__res; \ +}) + +#define _hypercall5(type, name, a1, a2, a3, a4, a5) \ +({ \ + long __res; \ + __asm__ __volatile__ (";;\n" \ + "mov r14=%2\n" \ + "mov r15=%3\n" \ + "mov r16=%4\n" \ + "mov r17=%5\n" \ + "mov r18=%6\n" \ + "mov r2=%1\n" \ + "break 0x1000 ;;\n" \ + "mov %0=r8 ;;\n" \ + : "=r" (__res) \ + : "J" (__HYPERVISOR_##name), \ + "rI" ((unsigned long)(a1)), \ + "rI" ((unsigned long)(a2)), \ + "rI" ((unsigned long)(a3)), \ + "rI" ((unsigned long)(a4)), \ + "rI" ((unsigned long)(a5)) \ + : "r14","r15","r16","r2","r8", \ + "r17","r18","memory" ); \ + (type)__res; \ +}) + +static inline int +HYPERVISOR_sched_op_compat( + int cmd, unsigned long arg) +{ + return _hypercall2(int, sched_op_compat, cmd, arg); +} + +static inline int +HYPERVISOR_sched_op( + int cmd, void *arg) +{ + return _hypercall2(int, sched_op, cmd, arg); +} + +static inline long +HYPERVISOR_set_timer_op( + u64 timeout) +{ + unsigned long timeout_hi = (unsigned long)(timeout>>32); + unsigned long timeout_lo = (unsigned long)timeout; + return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi); +} + +static inline int +HYPERVISOR_dom0_op( + dom0_op_t *dom0_op) +{ + dom0_op->interface_version = DOM0_INTERFACE_VERSION; + return _hypercall1(int, dom0_op, dom0_op); +} + +static inline int +HYPERVISOR_multicall( + void *call_list, int nr_calls) +{ + return _hypercall2(int, multicall, call_list, nr_calls); +} + +//XXX xen/ia64 copy_from_guest() is broken. +// This is a temporal work around until it is fixed. +static inline int +____HYPERVISOR_memory_op( + unsigned int cmd, void *arg) +{ + return _hypercall2(int, memory_op, cmd, arg); +} + +#include <xen/interface/memory.h> +#ifdef CONFIG_VMX_GUEST +# define ia64_xenmem_reservation_op(op, xmr) (0) +#else +int ia64_xenmem_reservation_op(unsigned long op, + struct xen_memory_reservation* reservation__); +#endif +static inline int +HYPERVISOR_memory_op( + unsigned int cmd, void *arg) +{ + switch (cmd) { + case XENMEM_increase_reservation: + case XENMEM_decrease_reservation: + case XENMEM_populate_physmap: + return ia64_xenmem_reservation_op(cmd, + (struct xen_memory_reservation*)arg); + default: + return ____HYPERVISOR_memory_op(cmd, arg); + } + /* NOTREACHED */ +} + +static inline int +HYPERVISOR_event_channel_op( + int cmd, void *arg) +{ + int rc = _hypercall2(int, event_channel_op, cmd, arg); + if (unlikely(rc == -ENOSYS)) { + struct evtchn_op op; + op.cmd = cmd; + memcpy(&op.u, arg, sizeof(op.u)); + rc = _hypercall1(int, event_channel_op_compat, &op); + } + return rc; +} + +static inline int +HYPERVISOR_acm_op( + unsigned int cmd, void *arg) +{ + return _hypercall2(int, acm_op, cmd, arg); +} + +static inline int +HYPERVISOR_xen_version( + int cmd, void *arg) +{ + return _hypercall2(int, xen_version, cmd, arg); +} + +static inline int +HYPERVISOR_console_io( + int cmd, int count, char *str) +{ + return _hypercall3(int, console_io, cmd, count, str); +} + +static inline int +HYPERVISOR_physdev_op( + int cmd, void *arg) +{ + int rc = _hypercall2(int, physdev_op, cmd, arg); + if (unlikely(rc == -ENOSYS)) { + struct physdev_op op; + op.cmd = cmd; + memcpy(&op.u, arg, sizeof(op.u)); + rc = _hypercall1(int, physdev_op_compat, &op); + } + return rc; +} + +//XXX __HYPERVISOR_grant_table_op is used for this hypercall constant. +static inline int +____HYPERVISOR_grant_table_op( + unsigned int cmd, void *uop, unsigned int count, + unsigned long pa1, unsigned long pa2) +{ + return _hypercall5(int, grant_table_op, cmd, uop, count, pa1, pa2); +} + +int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count); + +static inline int +HYPERVISOR_vcpu_op( + int cmd, int vcpuid, void *extra_args) +{ + return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args); +} + +extern int HYPERVISOR_suspend(unsigned long srec); + +static inline unsigned long +HYPERVISOR_hvm_op( + int cmd, void *arg) +{ + return _hypercall2(unsigned long, hvm_op, cmd, arg); +} + +static inline int +HYPERVISOR_callback_op( + int cmd, void *arg) +{ + return _hypercall2(int, callback_op, cmd, arg); +} + +extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs); +static inline void exit_idle(void) {} +#define do_IRQ(irq, regs) ({ \ + irq_enter(); \ + __do_IRQ((irq), (regs)); \ + irq_exit(); \ +}) + +#include <linux/err.h> +#ifdef CONFIG_XEN +#include <asm/xen/privop.h> +#endif /* CONFIG_XEN */ + +static inline unsigned long +__HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size) +{ + return _hypercall3(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_ioremap, ioaddr, size); +} + +static inline unsigned long +HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size) +{ + unsigned long ret = ioaddr; + if (is_running_on_xen()) { + ret = __HYPERVISOR_ioremap(ioaddr, size); + if (unlikely(ret == -ENOSYS)) + panic("hypercall %s failed with %ld. " + "Please check Xen and Linux config mismatch\n", + __func__, -ret); + else if (unlikely(IS_ERR_VALUE(ret))) + ret = ioaddr; + } + return ret; +} + +static inline unsigned long +__HYPERVISOR_phystomach(unsigned long gpfn) +{ + return _hypercall2(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_phystomach, gpfn); +} + +static inline unsigned long +HYPERVISOR_phystomach(unsigned long gpfn) +{ + unsigned long ret = gpfn; + if (is_running_on_xen()) { + ret = __HYPERVISOR_phystomach(gpfn); + } + return ret; +} + +static inline unsigned long +__HYPERVISOR_machtophys(unsigned long mfn) +{ + return _hypercall2(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_machtophys, mfn); +} + +static inline unsigned long +HYPERVISOR_machtophys(unsigned long mfn) +{ + unsigned long ret = mfn; + if (is_running_on_xen()) { + ret = __HYPERVISOR_machtophys(mfn); + } + return ret; +} + +static inline unsigned long +__HYPERVISOR_zap_physmap(unsigned long gpfn, unsigned int extent_order) +{ + return _hypercall3(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_zap_physmap, gpfn, extent_order); +} + +static inline unsigned long +HYPERVISOR_zap_physmap(unsigned long gpfn, unsigned int extent_order) +{ + unsigned long ret = 0; + if (is_running_on_xen()) { + ret = __HYPERVISOR_zap_physmap(gpfn, extent_order); + } + return ret; +} + +static inline unsigned long +__HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn, + unsigned long flags, domid_t domid) +{ + return _hypercall5(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_add_physmap, gpfn, mfn, flags, domid); +} + +static inline unsigned long +HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn, + unsigned long flags, domid_t domid) +{ + unsigned long ret = 0; + BUG_ON(!is_running_on_xen());//XXX + if (is_running_on_xen()) { + ret = __HYPERVISOR_add_physmap(gpfn, mfn, flags, domid); + } + return ret; +} + +// for balloon driver +#define HYPERVISOR_update_va_mapping(va, new_val, flags) (0) + +#endif /* __HYPERCALL_H__ */ diff --git a/include/asm-ia64/hypervisor.h b/include/asm-ia64/hypervisor.h new file mode 100644 index 000000000..3c190aea3 --- /dev/null +++ b/include/asm-ia64/hypervisor.h @@ -0,0 +1,218 @@ +/****************************************************************************** + * hypervisor.h + * + * Linux-specific hypervisor handling. + * + * Copyright (c) 2002-2004, K A Fraser + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef __HYPERVISOR_H__ +#define __HYPERVISOR_H__ + +#ifdef CONFIG_XEN +extern int running_on_xen; +#define is_running_on_xen() (running_on_xen) +#else /* CONFIG_XEN */ +# ifdef CONFIG_VMX_GUEST +# define is_running_on_xen() (1) +# else /* CONFIG_VMX_GUEST */ +# define is_running_on_xen() (0) +# define HYPERVISOR_ioremap(offset, size) (offset) +# endif /* CONFIG_VMX_GUEST */ +#endif /* CONFIG_XEN */ + +#if defined(CONFIG_XEN) || defined(CONFIG_VMX_GUEST) +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/version.h> +#include <linux/errno.h> +#include <xen/interface/xen.h> +#include <xen/interface/dom0_ops.h> +#include <xen/interface/event_channel.h> +#include <xen/interface/physdev.h> +#include <xen/interface/sched.h> +#include <asm/hypercall.h> +#include <asm/ptrace.h> +#include <asm/page.h> + +extern shared_info_t *HYPERVISOR_shared_info; +extern start_info_t *xen_start_info; + +void force_evtchn_callback(void); + +#ifndef CONFIG_VMX_GUEST +/* Turn jiffies into Xen system time. XXX Implement me. */ +#define jiffies_to_st(j) 0 + +static inline int +HYPERVISOR_yield( + void) +{ + int rc = HYPERVISOR_sched_op(SCHEDOP_yield, NULL); + + if (rc == -ENOSYS) + rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0); + + return rc; +} + +static inline int +HYPERVISOR_block( + void) +{ + int rc = HYPERVISOR_sched_op(SCHEDOP_block, NULL); + + if (rc == -ENOSYS) + rc = HYPERVISOR_sched_op_compat(SCHEDOP_block, 0); + + return rc; +} + +static inline int +HYPERVISOR_shutdown( + unsigned int reason) +{ + struct sched_shutdown sched_shutdown = { + .reason = reason + }; + + int rc = HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown); + + if (rc == -ENOSYS) + rc = HYPERVISOR_sched_op_compat(SCHEDOP_shutdown, reason); + + return rc; +} + +static inline int +HYPERVISOR_poll( + evtchn_port_t *ports, unsigned int nr_ports, u64 timeout) +{ + struct sched_poll sched_poll = { + .nr_ports = nr_ports, + .timeout = jiffies_to_st(timeout) + }; + + int rc; + + set_xen_guest_handle(sched_poll.ports, ports); + rc = HYPERVISOR_sched_op(SCHEDOP_poll, &sched_poll); + if (rc == -ENOSYS) + rc = HYPERVISOR_sched_op_compat(SCHEDOP_yield, 0); + + return rc; +} + +#include <asm/hypercall.h> + +// for drivers/xen/privcmd/privcmd.c +#define machine_to_phys_mapping 0 +struct vm_area_struct; +int direct_remap_pfn_range(struct vm_area_struct *vma, + unsigned long address, + unsigned long mfn, + unsigned long size, + pgprot_t prot, + domid_t domid); +struct file; +int privcmd_mmap(struct file * file, struct vm_area_struct * vma); +#define HAVE_ARCH_PRIVCMD_MMAP + +// for drivers/xen/balloon/balloon.c +#ifdef CONFIG_XEN_SCRUB_PAGES +#define scrub_pages(_p,_n) memset((void *)(_p), 0, (_n) << PAGE_SHIFT) +#else +#define scrub_pages(_p,_n) ((void)0) +#endif +#define pte_mfn(_x) pte_pfn(_x) +#define phys_to_machine_mapping_valid(_x) (1) + +#endif /* !CONFIG_VMX_GUEST */ + +#define __pte_ma(_x) ((pte_t) {(_x)}) /* unmodified use */ +#define pfn_pte_ma(_x,_y) __pte_ma(0) /* unmodified use */ + +#ifndef CONFIG_VMX_GUEST +int __xen_create_contiguous_region(unsigned long vstart, unsigned int order, unsigned int address_bits); +static inline int +xen_create_contiguous_region(unsigned long vstart, + unsigned int order, unsigned int address_bits) +{ + int ret = 0; + if (is_running_on_xen()) { + ret = __xen_create_contiguous_region(vstart, order, + address_bits); + } + return ret; +} + +void __xen_destroy_contiguous_region(unsigned long vstart, unsigned int order); +static inline void +xen_destroy_contiguous_region(unsigned long vstart, unsigned int order) +{ + if (is_running_on_xen()) + __xen_destroy_contiguous_region(vstart, order); +} + +#endif /* !CONFIG_VMX_GUEST */ + +// for netfront.c, netback.c +#define MULTI_UVMFLAGS_INDEX 0 //XXX any value + +static inline void +MULTI_update_va_mapping( + multicall_entry_t *mcl, unsigned long va, + pte_t new_val, unsigned long flags) +{ + mcl->op = __HYPERVISOR_update_va_mapping; + mcl->result = 0; +} + +static inline void +MULTI_grant_table_op(multicall_entry_t *mcl, unsigned int cmd, + void *uop, unsigned int count) +{ + mcl->op = __HYPERVISOR_grant_table_op; + mcl->args[0] = cmd; + mcl->args[1] = (unsigned long)uop; + mcl->args[2] = count; +} + +// for debug +asmlinkage int xprintk(const char *fmt, ...); +#define xprintd(fmt, ...) xprintk("%s:%d " fmt, __func__, __LINE__, \ + ##__VA_ARGS__) + +#endif /* CONFIG_XEN || CONFIG_VMX_GUEST */ + +#ifdef CONFIG_XEN_PRIVILEGED_GUEST +#define is_initial_xendomain() (xen_start_info->flags & SIF_INITDOMAIN) +#else +#define is_initial_xendomain() 0 +#endif + +#endif /* __HYPERVISOR_H__ */ diff --git a/include/asm-ia64/maddr.h b/include/asm-ia64/maddr.h new file mode 100644 index 000000000..55c6f94d1 --- /dev/null +++ b/include/asm-ia64/maddr.h @@ -0,0 +1,92 @@ +#ifndef _ASM_IA64_MADDR_H +#define _ASM_IA64_MADDR_H + +#include <linux/kernel.h> +#include <asm/hypervisor.h> +#include <xen/features.h> +#include <xen/interface/xen.h> + +#ifdef CONFIG_XEN + +#define INVALID_P2M_ENTRY (~0UL) + +/* XXX xen page size != page size */ +static inline unsigned long +pfn_to_mfn_for_dma(unsigned long pfn) +{ + unsigned long mfn; + mfn = HYPERVISOR_phystomach(pfn); + BUG_ON(mfn == 0); // XXX + BUG_ON(mfn == INVALID_P2M_ENTRY); // XXX + BUG_ON(mfn == INVALID_MFN); + return mfn; +} + +static inline unsigned long +phys_to_machine_for_dma(unsigned long phys) +{ + unsigned long machine = + pfn_to_mfn_for_dma(phys >> PAGE_SHIFT) << PAGE_SHIFT; + machine |= (phys & ~PAGE_MASK); + return machine; +} + +static inline unsigned long +mfn_to_pfn_for_dma(unsigned long mfn) +{ + unsigned long pfn; + pfn = HYPERVISOR_machtophys(mfn); + BUG_ON(pfn == 0); + //BUG_ON(pfn == INVALID_M2P_ENTRY); + return pfn; +} + +static inline unsigned long +machine_to_phys_for_dma(unsigned long machine) +{ + unsigned long phys = + mfn_to_pfn_for_dma(machine >> PAGE_SHIFT) << PAGE_SHIFT; + phys |= (machine & ~PAGE_MASK); + return phys; +} + +static inline unsigned long +mfn_to_local_pfn(unsigned long mfn) +{ + extern unsigned long max_mapnr; + unsigned long pfn = mfn_to_pfn_for_dma(mfn); + if (!pfn_valid(pfn)) + return INVALID_P2M_ENTRY; + return pfn; +} + +#else /* !CONFIG_XEN */ + +#define pfn_to_mfn_for_dma(pfn) (pfn) +#define mfn_to_pfn_for_dma(mfn) (mfn) +#define phys_to_machine_for_dma(phys) (phys) +#define machine_to_phys_for_dma(machine) (machine) +#define mfn_to_local_pfn(mfn) (mfn) + +#endif /* !CONFIG_XEN */ + +/* XXX to compile set_phys_to_machine(vaddr, FOREIGN_FRAME(m)) */ +#define FOREIGN_FRAME(m) (INVALID_P2M_ENTRY) + +#define mfn_to_pfn(mfn) (mfn) +#define pfn_to_mfn(pfn) (pfn) + +#define mfn_to_virt(mfn) (__va((mfn) << PAGE_SHIFT)) +#define virt_to_mfn(virt) (__pa(virt) >> PAGE_SHIFT) +#define virt_to_machine(virt) __pa(virt) // for tpmfront.c + +#define set_phys_to_machine(pfn, mfn) do { } while (0) +#ifdef CONFIG_VMX_GUEST +extern void xen_machphys_update(unsigned long mfn, unsigned long pfn); +#else /* CONFIG_VMX_GUEST */ +#define xen_machphys_update(mfn, pfn) do { } while (0) +#endif /* CONFIG_VMX_GUEST */ + +typedef unsigned long maddr_t; // to compile netback, netfront + +#endif /* _ASM_IA64_MADDR_H */ diff --git a/include/asm-ia64/privop.h b/include/asm-ia64/privop.h new file mode 100644 index 000000000..28c1e886c --- /dev/null +++ b/include/asm-ia64/privop.h @@ -0,0 +1,59 @@ +#ifndef _ASM_IA64_PRIVOP_H +#define _ASM_IA64_PRIVOP_H + +/* + * Copyright (C) 2005 Hewlett-Packard Co + * Dan Magenheimer <dan.magenheimer@hp.com> + * + */ + +#ifdef CONFIG_XEN +#include <asm/xen/privop.h> +#endif + +#ifndef __ASSEMBLY + +#ifndef IA64_PARAVIRTUALIZED + +#define ia64_getreg __ia64_getreg +#define ia64_setreg __ia64_setreg +#define ia64_hint __ia64_hint +#define ia64_thash __ia64_thash +#define ia64_itci __ia64_itci +#define ia64_itcd __ia64_itcd +#define ia64_itri __ia64_itri +#define ia64_itrd __ia64_itrd +#define ia64_tpa __ia64_tpa +#define ia64_set_ibr __ia64_set_ibr +#define ia64_set_pkr __ia64_set_pkr +#define ia64_set_pmc __ia64_set_pmc +#define ia64_set_pmd __ia64_set_pmd +#define ia64_set_rr __ia64_set_rr +#define ia64_get_cpuid __ia64_get_cpuid +#define ia64_get_ibr __ia64_get_ibr +#define ia64_get_pkr __ia64_get_pkr +#define ia64_get_pmc __ia64_get_pmc +#define ia64_get_pmd __ia64_get_pmd +#define ia64_get_rr __ia64_get_rr +#define ia64_fc __ia64_fc +#define ia64_ssm __ia64_ssm +#define ia64_rsm __ia64_rsm +#define ia64_ptce __ia64_ptce +#define ia64_ptcga __ia64_ptcga +#define ia64_ptcl __ia64_ptcl +#define ia64_ptri __ia64_ptri +#define ia64_ptrd __ia64_ptrd +#define ia64_get_psr_i __ia64_get_psr_i +#define ia64_intrin_local_irq_restore __ia64_intrin_local_irq_restore +#define ia64_pal_halt_light __ia64_pal_halt_light +#define ia64_leave_kernel __ia64_leave_kernel +#define ia64_leave_syscall __ia64_leave_syscall +#define ia64_trace_syscall __ia64_trace_syscall +#define ia64_switch_to __ia64_switch_to +#define ia64_pal_call_static __ia64_pal_call_static + +#endif /* !IA64_PARAVIRTUALIZED */ + +#endif /* !__ASSEMBLY */ + +#endif /* _ASM_IA64_PRIVOP_H */ diff --git a/include/asm-ia64/synch_bitops.h b/include/asm-ia64/synch_bitops.h new file mode 100644 index 000000000..21b7f8cd1 --- /dev/null +++ b/include/asm-ia64/synch_bitops.h @@ -0,0 +1,61 @@ +#ifndef __XEN_SYNCH_BITOPS_H__ +#define __XEN_SYNCH_BITOPS_H__ + +/* + * Copyright 1992, Linus Torvalds. + * Heavily modified to provide guaranteed strong synchronisation + * when communicating with Xen or other guest OSes running on other CPUs. + */ + +#define ADDR (*(volatile long *) addr) + +static __inline__ void synch_set_bit(int nr, volatile void * addr) +{ + set_bit(nr, addr); +} + +static __inline__ void synch_clear_bit(int nr, volatile void * addr) +{ + clear_bit(nr, addr); +} + +static __inline__ void synch_change_bit(int nr, volatile void * addr) +{ + change_bit(nr, addr); +} + +static __inline__ int synch_test_and_set_bit(int nr, volatile void * addr) +{ + return test_and_set_bit(nr, addr); +} + +static __inline__ int synch_test_and_clear_bit(int nr, volatile void * addr) +{ + return test_and_clear_bit(nr, addr); +} + +static __inline__ int synch_test_and_change_bit(int nr, volatile void * addr) +{ + return test_and_change_bit(nr, addr); +} + +static __inline__ int synch_const_test_bit(int nr, const volatile void * addr) +{ + return test_bit(nr, addr); +} + +static __inline__ int synch_var_test_bit(int nr, volatile void * addr) +{ + return test_bit(nr, addr); +} + +#define synch_cmpxchg ia64_cmpxchg4_acq + +#define synch_test_bit(nr,addr) \ +(__builtin_constant_p(nr) ? \ + synch_const_test_bit((nr),(addr)) : \ + synch_var_test_bit((nr),(addr))) + +#define synch_cmpxchg_subword synch_cmpxchg + +#endif /* __XEN_SYNCH_BITOPS_H__ */ diff --git a/include/asm-ia64/tracehook.h b/include/asm-ia64/tracehook.h new file mode 100644 index 000000000..ffea9431f --- /dev/null +++ b/include/asm-ia64/tracehook.h @@ -0,0 +1,81 @@ +/* + * Copyright (C)2006 Intel Co + * Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> + * and Bibo Mao <bibo.mao@intel.com> adapted from i386. + * + * Tracing hooks, ia64 CPU support + */ + +#ifndef _ASM_TRACEHOOK_H +#define _ASM_TRACEHOOK_H 1 + +#include <linux/sched.h> +#include <asm/ptrace.h> + +/* + * See linux/tracehook.h for the descriptions of what these need to do. + */ + +#define ARCH_HAS_SINGLE_STEP (1) +#define ARCH_HAS_BLOCK_STEP (1) + +static inline void tracehook_enable_single_step(struct task_struct *tsk) +{ + struct pt_regs *pt = task_pt_regs(tsk); + ia64_psr(pt)->ss = 1; +} + +static inline void tracehook_disable_single_step(struct task_struct *tsk) +{ + struct pt_regs *pt = task_pt_regs(tsk); + ia64_psr(pt)->ss = 0; +} + +static inline void tracehook_enable_block_step(struct task_struct *tsk) +{ + struct pt_regs *pt = task_pt_regs(tsk); + ia64_psr(pt)->tb = 1; +} + +static inline void tracehook_disable_block_step(struct task_struct *tsk) +{ + struct pt_regs *pt = task_pt_regs(tsk); + ia64_psr(pt)->tb = 0; +} + +static inline void tracehook_enable_syscall_trace(struct task_struct *tsk) +{ + set_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE); +} + +static inline void tracehook_disable_syscall_trace(struct task_struct *tsk) +{ + clear_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE); +} + +static inline int tracehook_single_step_enabled(struct task_struct *tsk) +{ + struct pt_regs *pt = task_pt_regs(tsk); + return ia64_psr(pt)->ss; +} + +static inline void tracehook_abort_syscall(struct pt_regs *regs) +{ + regs->r15 = -1L; +} + +extern const struct utrace_regset_view utrace_ia64_native; +static inline const struct utrace_regset_view * +utrace_native_view(struct task_struct *tsk) +{ +#if 0 //CONFIG_IA32_SUPPORT + extern const struct utrace_regset_view utrace_ia32_view; + + struct pt_regs *pt = task_pt_regs(tsk); + if (pt->cr_ipsr & IA64_PSR_IS) + return &utrace_ia32_view; +#endif + return &utrace_ia64_native; +} + +#endif diff --git a/include/asm-ia64/xen/privop.h b/include/asm-ia64/xen/privop.h new file mode 100644 index 000000000..073b3a2a7 --- /dev/null +++ b/include/asm-ia64/xen/privop.h @@ -0,0 +1,304 @@ +#ifndef _ASM_IA64_XEN_PRIVOP_H +#define _ASM_IA64_XEN_PRIVOP_H + +/* + * Copyright (C) 2005 Hewlett-Packard Co + * Dan Magenheimer <dan.magenheimer@hp.com> + * + * Paravirtualizations of privileged operations for Xen/ia64 + * + */ + + +#include <xen/interface/arch-ia64.h> + +#define IA64_PARAVIRTUALIZED + +#if 0 +#undef XSI_BASE +/* At 1 MB, before per-cpu space but still addressable using addl instead + of movl. */ +#define XSI_BASE 0xfffffffffff00000 +#endif + +/* Address of mapped regs. */ +#define XMAPPEDREGS_BASE (XSI_BASE + XSI_SIZE) + +#ifdef __ASSEMBLY__ +#define XEN_HYPER_RFI break HYPERPRIVOP_RFI +#define XEN_HYPER_RSM_PSR_DT break HYPERPRIVOP_RSM_DT +#define XEN_HYPER_SSM_PSR_DT break HYPERPRIVOP_SSM_DT +#define XEN_HYPER_COVER break HYPERPRIVOP_COVER +#define XEN_HYPER_ITC_D break HYPERPRIVOP_ITC_D +#define XEN_HYPER_ITC_I break HYPERPRIVOP_ITC_I +#define XEN_HYPER_SSM_I break HYPERPRIVOP_SSM_I +#define XEN_HYPER_GET_IVR break HYPERPRIVOP_GET_IVR +#define XEN_HYPER_GET_TPR break HYPERPRIVOP_GET_TPR +#define XEN_HYPER_SET_TPR break HYPERPRIVOP_SET_TPR +#define XEN_HYPER_EOI break HYPERPRIVOP_EOI +#define XEN_HYPER_SET_ITM break HYPERPRIVOP_SET_ITM +#define XEN_HYPER_THASH break HYPERPRIVOP_THASH +#define XEN_HYPER_PTC_GA break HYPERPRIVOP_PTC_GA +#define XEN_HYPER_ITR_D break HYPERPRIVOP_ITR_D +#define XEN_HYPER_GET_RR break HYPERPRIVOP_GET_RR +#define XEN_HYPER_SET_RR break HYPERPRIVOP_SET_RR +#define XEN_HYPER_SET_KR break HYPERPRIVOP_SET_KR +#define XEN_HYPER_FC break HYPERPRIVOP_FC +#define XEN_HYPER_GET_CPUID break HYPERPRIVOP_GET_CPUID +#define XEN_HYPER_GET_PMD break HYPERPRIVOP_GET_PMD +#define XEN_HYPER_GET_EFLAG break HYPERPRIVOP_GET_EFLAG +#define XEN_HYPER_SET_EFLAG break HYPERPRIVOP_SET_EFLAG +#define XEN_HYPER_RSM_BE break HYPERPRIVOP_RSM_BE +#define XEN_HYPER_GET_PSR break HYPERPRIVOP_GET_PSR + +#define XSI_IFS (XSI_BASE + XSI_IFS_OFS) +#define XSI_PRECOVER_IFS (XSI_BASE + XSI_PRECOVER_IFS_OFS) +#define XSI_INCOMPL_REGFR (XSI_BASE + XSI_INCOMPL_REGFR_OFS) +#define XSI_IFA (XSI_BASE + XSI_IFA_OFS) +#define XSI_ISR (XSI_BASE + XSI_ISR_OFS) +#define XSI_IIM (XSI_BASE + XSI_IIM_OFS) +#define XSI_ITIR (XSI_BASE + XSI_ITIR_OFS) +#define XSI_PSR_I_ADDR (XSI_BASE + XSI_PSR_I_ADDR_OFS) +#define XSI_PSR_IC (XSI_BASE + XSI_PSR_IC_OFS) +#define XSI_IPSR (XSI_BASE + XSI_IPSR_OFS) +#define XSI_IIP (XSI_BASE + XSI_IIP_OFS) +#define XSI_BANK1_R16 (XSI_BASE + XSI_BANK1_R16_OFS) +#define XSI_BANKNUM (XSI_BASE + XSI_BANKNUM_OFS) +#define XSI_IHA (XSI_BASE + XSI_IHA_OFS) +#endif + +#ifndef __ASSEMBLY__ +#define XEN_HYPER_SSM_I asm("break %0" : : "i" (HYPERPRIVOP_SSM_I)) +#define XEN_HYPER_GET_IVR asm("break %0" : : "i" (HYPERPRIVOP_GET_IVR)) + +/************************************************/ +/* Instructions paravirtualized for correctness */ +/************************************************/ + +/* "fc" and "thash" are privilege-sensitive instructions, meaning they + * may have different semantics depending on whether they are executed + * at PL0 vs PL!=0. When paravirtualized, these instructions mustn't + * be allowed to execute directly, lest incorrect semantics result. */ +extern unsigned long xen_fc(unsigned long addr); +#define ia64_fc(addr) xen_fc((unsigned long)(addr)) +extern unsigned long xen_thash(unsigned long addr); +#define ia64_thash(addr) xen_thash((unsigned long)(addr)) +/* Note that "ttag" and "cover" are also privilege-sensitive; "ttag" + * is not currently used (though it may be in a long-format VHPT system!) + * and the semantics of cover only change if psr.ic is off which is very + * rare (and currently non-existent outside of assembly code */ + +/* There are also privilege-sensitive registers. These registers are + * readable at any privilege level but only writable at PL0. */ +extern unsigned long xen_get_cpuid(int index); +#define ia64_get_cpuid(i) xen_get_cpuid(i) +extern unsigned long xen_get_pmd(int index); +#define ia64_get_pmd(i) xen_get_pmd(i) +extern unsigned long xen_get_eflag(void); /* see xen_ia64_getreg */ +extern void xen_set_eflag(unsigned long); /* see xen_ia64_setreg */ + +/************************************************/ +/* Instructions paravirtualized for performance */ +/************************************************/ + +/* Xen uses memory-mapped virtual privileged registers for access to many + * performance-sensitive privileged registers. Some, like the processor + * status register (psr), are broken up into multiple memory locations. + * Others, like "pend", are abstractions based on privileged registers. + * "Pend" is guaranteed to be set if reading cr.ivr would return a + * (non-spurious) interrupt. */ +#define XEN_MAPPEDREGS ((struct mapped_regs *)XMAPPEDREGS_BASE) +#define XSI_PSR_I \ + (*XEN_MAPPEDREGS->interrupt_mask_addr) +#define xen_get_virtual_psr_i() \ + (!XSI_PSR_I) +#define xen_set_virtual_psr_i(_val) \ + ({ XSI_PSR_I = (uint8_t)(_val) ? 0 : 1; }) +#define xen_set_virtual_psr_ic(_val) \ + ({ XEN_MAPPEDREGS->interrupt_collection_enabled = _val ? 1 : 0; }) +#define xen_get_virtual_pend() (XEN_MAPPEDREGS->pending_interruption) + +/* Hyperprivops are "break" instructions with a well-defined API. + * In particular, the virtual psr.ic bit must be off; in this way + * it is guaranteed to never conflict with a linux break instruction. + * Normally, this is done in a xen stub but this one is frequent enough + * that we inline it */ +#define xen_hyper_ssm_i() \ +({ \ + xen_set_virtual_psr_i(0); \ + xen_set_virtual_psr_ic(0); \ + XEN_HYPER_SSM_I; \ +}) + +/* turning off interrupts can be paravirtualized simply by writing + * to a memory-mapped virtual psr.i bit (implemented as a 16-bit bool) */ +#define xen_rsm_i() xen_set_virtual_psr_i(0) + +/* turning on interrupts is a bit more complicated.. write to the + * memory-mapped virtual psr.i bit first (to avoid race condition), + * then if any interrupts were pending, we have to execute a hyperprivop + * to ensure the pending interrupt gets delivered; else we're done! */ +#define xen_ssm_i() \ +({ \ + int old = xen_get_virtual_psr_i(); \ + xen_set_virtual_psr_i(1); \ + if (!old && xen_get_virtual_pend()) xen_hyper_ssm_i(); \ +}) + +#define xen_ia64_intrin_local_irq_restore(x) \ +{ \ + if (is_running_on_xen()) { \ + if ((x) & IA64_PSR_I) { xen_ssm_i(); } \ + else { xen_rsm_i(); } \ + } \ + else __ia64_intrin_local_irq_restore((x)); \ +} + +#define xen_get_psr_i() \ +( \ + (is_running_on_xen()) ? \ + (xen_get_virtual_psr_i() ? IA64_PSR_I : 0) \ + : __ia64_get_psr_i() \ +) + +#define xen_ia64_ssm(mask) \ +{ \ + if ((mask)==IA64_PSR_I) { \ + if (is_running_on_xen()) { xen_ssm_i(); } \ + else { __ia64_ssm(mask); } \ + } \ + else { __ia64_ssm(mask); } \ +} + +#define xen_ia64_rsm(mask) \ +{ \ + if ((mask)==IA64_PSR_I) { \ + if (is_running_on_xen()) { xen_rsm_i(); } \ + else { __ia64_rsm(mask); } \ + } \ + else { __ia64_rsm(mask); } \ +} + + +/* Although all privileged operations can be left to trap and will + * be properly handled by Xen, some are frequent enough that we use + * hyperprivops for performance. */ + +extern unsigned long xen_get_ivr(void); +extern unsigned long xen_get_tpr(void); +extern void xen_set_itm(unsigned long); +extern void xen_set_tpr(unsigned long); +extern void xen_eoi(void); +extern void xen_set_rr(unsigned long index, unsigned long val); +extern unsigned long xen_get_rr(unsigned long index); +extern void xen_set_kr(unsigned long index, unsigned long val); +extern void xen_ptcga(unsigned long addr, unsigned long size); + +/* Note: It may look wrong to test for is_running_on_xen() in each case. + * However regnum is always a constant so, as written, the compiler + * eliminates the switch statement, whereas is_running_on_xen() must be + * tested dynamically. */ +#define xen_ia64_getreg(regnum) \ +({ \ + __u64 ia64_intri_res; \ + \ + switch(regnum) { \ + case _IA64_REG_CR_IVR: \ + ia64_intri_res = (is_running_on_xen()) ? \ + xen_get_ivr() : \ + __ia64_getreg(regnum); \ + break; \ + case _IA64_REG_CR_TPR: \ + ia64_intri_res = (is_running_on_xen()) ? \ + xen_get_tpr() : \ + __ia64_getreg(regnum); \ + break; \ + case _IA64_REG_AR_EFLAG: \ + ia64_intri_res = (is_running_on_xen()) ? \ + xen_get_eflag() : \ + __ia64_getreg(regnum); \ + break; \ + default: \ + ia64_intri_res = __ia64_getreg(regnum); \ + break; \ + } \ + ia64_intri_res; \ +}) + +#define xen_ia64_setreg(regnum,val) \ +({ \ + switch(regnum) { \ + case _IA64_REG_AR_KR0 ... _IA64_REG_AR_KR7: \ + (is_running_on_xen()) ? \ + xen_set_kr((regnum-_IA64_REG_AR_KR0), val) : \ + __ia64_setreg(regnum,val); \ + break; \ + case _IA64_REG_CR_ITM: \ + (is_running_on_xen()) ? \ + xen_set_itm(val) : \ + __ia64_setreg(regnum,val); \ + break; \ + case _IA64_REG_CR_TPR: \ + (is_running_on_xen()) ? \ + xen_set_tpr(val) : \ + __ia64_setreg(regnum,val); \ + break; \ + case _IA64_REG_CR_EOI: \ + (is_running_on_xen()) ? \ + xen_eoi() : \ + __ia64_setreg(regnum,val); \ + break; \ + case _IA64_REG_AR_EFLAG: \ + (is_running_on_xen()) ? \ + xen_set_eflag(val) : \ + __ia64_setreg(regnum,val); \ + break; \ + default: \ + __ia64_setreg(regnum,val); \ + break; \ + } \ +}) + +#define ia64_ssm xen_ia64_ssm +#define ia64_rsm xen_ia64_rsm +#define ia64_intrin_local_irq_restore xen_ia64_intrin_local_irq_restore +#define ia64_ptcga xen_ptcga +#define ia64_set_rr(index,val) xen_set_rr(index,val) +#define ia64_get_rr(index) xen_get_rr(index) +#define ia64_getreg xen_ia64_getreg +#define ia64_setreg xen_ia64_setreg +#define ia64_get_psr_i xen_get_psr_i + +/* the remainder of these are not performance-sensitive so its + * OK to not paravirtualize and just take a privop trap and emulate */ +#define ia64_hint __ia64_hint +#define ia64_set_pmd __ia64_set_pmd +#define ia64_itci __ia64_itci +#define ia64_itcd __ia64_itcd +#define ia64_itri __ia64_itri +#define ia64_itrd __ia64_itrd +#define ia64_tpa __ia64_tpa +#define ia64_set_ibr __ia64_set_ibr +#define ia64_set_pkr __ia64_set_pkr +#define ia64_set_pmc __ia64_set_pmc +#define ia64_get_ibr __ia64_get_ibr +#define ia64_get_pkr __ia64_get_pkr +#define ia64_get_pmc __ia64_get_pmc +#define ia64_ptce __ia64_ptce +#define ia64_ptcl __ia64_ptcl +#define ia64_ptri __ia64_ptri +#define ia64_ptrd __ia64_ptrd + +#endif /* !__ASSEMBLY__ */ + +/* these routines utilize privilege-sensitive or performance-sensitive + * privileged instructions so the code must be replaced with + * paravirtualized versions */ +#define ia64_pal_halt_light xen_pal_halt_light +#define ia64_leave_kernel xen_leave_kernel +#define ia64_leave_syscall xen_leave_syscall +#define ia64_trace_syscall xen_trace_syscall +#define ia64_switch_to xen_switch_to +#define ia64_pal_call_static xen_pal_call_static + +#endif /* _ASM_IA64_XEN_PRIVOP_H */ diff --git a/include/asm-m32r/Kbuild b/include/asm-m32r/Kbuild new file mode 100644 index 000000000..c68e1680d --- /dev/null +++ b/include/asm-m32r/Kbuild @@ -0,0 +1 @@ +include include/asm-generic/Kbuild.asm diff --git a/include/asm-m68k/Kbuild b/include/asm-m68k/Kbuild new file mode 100644 index 000000000..c68e1680d --- /dev/null +++ b/include/asm-m68k/Kbuild @@ -0,0 +1 @@ +include include/asm-generic/Kbuild.asm diff --git a/include/asm-m68knommu/Kbuild b/include/asm-m68knommu/Kbuild new file mode 100644 index 000000000..c68e1680d --- /dev/null +++ b/include/asm-m68knommu/Kbuild @@ -0,0 +1 @@ +include include/asm-generic/Kbuild.asm diff --git a/include/asm-m68knommu/m532xsim.h b/include/asm-m68knommu/m532xsim.h new file mode 100644 index 000000000..1835fd20a --- /dev/null +++ b/include/asm-m68knommu/m532xsim.h @@ -0,0 +1,2238 @@ +/****************************************************************************/ + +/* + * m532xsim.h -- ColdFire 5329 registers + */ + +/****************************************************************************/ +#ifndef m532xsim_h +#define m532xsim_h +/****************************************************************************/ + +#define MCF_REG32(x) (*(volatile unsigned long *)(x)) +#define MCF_REG16(x) (*(volatile unsigned short *)(x)) +#define MCF_REG08(x) (*(volatile unsigned char *)(x)) + +#define MCFINT_VECBASE 64 +#define MCFINT_UART0 26 /* Interrupt number for UART0 */ +#define MCFINT_UART1 27 /* Interrupt number for UART1 */ + +#define MCF_WTM_WCR MCF_REG16(0xFC098000) + +/* + * Define the 532x SIM register set addresses. + */ +#define MCFSIM_IPRL 0xFC048004 +#define MCFSIM_IPRH 0xFC048000 +#define MCFSIM_IPR MCFSIM_IPRL +#define MCFSIM_IMRL 0xFC04800C +#define MCFSIM_IMRH 0xFC048008 +#define MCFSIM_IMR MCFSIM_IMRL +#define MCFSIM_ICR0 0xFC048040 +#define MCFSIM_ICR1 0xFC048041 +#define MCFSIM_ICR2 0xFC048042 +#define MCFSIM_ICR3 0xFC048043 +#define MCFSIM_ICR4 0xFC048044 +#define MCFSIM_ICR5 0xFC048045 +#define MCFSIM_ICR6 0xFC048046 +#define MCFSIM_ICR7 0xFC048047 +#define MCFSIM_ICR8 0xFC048048 +#define MCFSIM_ICR9 0xFC048049 +#define MCFSIM_ICR10 0xFC04804A +#define MCFSIM_ICR11 0xFC04804B + +/* + * Some symbol defines for the above... + */ +#define MCFSIM_SWDICR MCFSIM_ICR0 /* Watchdog timer ICR */ +#define MCFSIM_TIMER1ICR MCFSIM_ICR1 /* Timer 1 ICR */ +#define MCFSIM_TIMER2ICR MCFSIM_ICR2 /* Timer 2 ICR */ +#define MCFSIM_UART1ICR MCFSIM_ICR4 /* UART 1 ICR */ +#define MCFSIM_UART2ICR MCFSIM_ICR5 /* UART 2 ICR */ +#define MCFSIM_DMA0ICR MCFSIM_ICR6 /* DMA 0 ICR */ +#define MCFSIM_DMA1ICR MCFSIM_ICR7 /* DMA 1 ICR */ +#define MCFSIM_DMA2ICR MCFSIM_ICR8 /* DMA 2 ICR */ +#define MCFSIM_DMA3ICR MCFSIM_ICR9 /* DMA 3 ICR */ + + +#define MCFSIM_IMR_MASKALL 0xFFFFFFFF /* All SIM intr sources */ + +#define MCFSIM_IMR_SIMR0 0xFC04801C +#define MCFSIM_IMR_SIMR1 0xFC04C01C +#define MCFSIM_IMR_CIMR0 0xFC04801D +#define MCFSIM_IMR_CIMR1 0xFC04C01D + +#define MCFSIM_ICR_TIMER1 (0xFC048040+32) +#define MCFSIM_ICR_TIMER2 (0xFC048040+33) + + +/* + * Macro to set IMR register. It is 32 bits on the 5307. + */ +#define mcf_getimr() \ + *((volatile unsigned long *) (MCF_MBAR + MCFSIM_IMR)) + +#define mcf_setimr(imr) \ + *((volatile unsigned long *) (MCF_MBAR + MCFSIM_IMR)) = (imr); + +#define mcf_getipr() \ + *((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPR)) + +#define mcf_getiprl() \ + *((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPRL)) + +#define mcf_getiprh() \ + *((volatile unsigned long *) (MCF_MBAR + MCFSIM_IPRH)) + + +#define mcf_enable_irq0(irq) \ + *((volatile unsigned char*) (MCFSIM_IMR_CIMR0)) = (irq); + +#define mcf_enable_irq1(irq) \ + *((volatile unsigned char*) (MCFSIM_IMR_CIMR1)) = (irq); + +#define mcf_disable_irq0(irq) \ + *((volatile unsigned char*) (MCFSIM_IMR_SIMR0)) = (irq); + +#define mcf_disable_irq1(irq) \ + *((volatile unsigned char*) (MCFSIM_IMR_SIMR1)) = (irq); + +/* + * Define the Cache register flags. + */ +#define CACR_EC (1<<31) +#define CACR_ESB (1<<29) +#define CACR_DPI (1<<28) +#define CACR_HLCK (1<<27) +#define CACR_CINVA (1<<24) +#define CACR_DNFB (1<<10) +#define CACR_DCM_WTHRU (0<<8) +#define CACR_DCM_WBACK (1<<8) +#define CACR_DCM_OFF_PRE (2<<8) +#define CACR_DCM_OFF_IMP (3<<8) +#define CACR_DW (1<<5) + +#define ACR_BASE_POS 24 +#define ACR_MASK_POS 16 +#define ACR_ENABLE (1<<15) +#define ACR_USER (0<<13) +#define ACR_SUPER (1<<13) +#define ACR_ANY (2<<13) +#define ACR_CM_WTHRU (0<<5) +#define ACR_CM_WBACK (1<<5) +#define ACR_CM_OFF_PRE (2<<5) +#define ACR_CM_OFF_IMP (3<<5) +#define ACR_WPROTECT (1<<2) + +/********************************************************************* + * + * Inter-IC (I2C) Module + * + *********************************************************************/ + +/* Read/Write access macros for general use */ +#define MCF532x_I2C_I2ADR (volatile u8 *) (0xFC058000) // Address +#define MCF532x_I2C_I2FDR (volatile u8 *) (0xFC058004) // Freq Divider +#define MCF532x_I2C_I2CR (volatile u8 *) (0xFC058008) // Control +#define MCF532x_I2C_I2SR (volatile u8 *) (0xFC05800C) // Status +#define MCF532x_I2C_I2DR (volatile u8 *) (0xFC058010) // Data I/O + +/* Bit level definitions and macros */ +#define MCF532x_I2C_I2ADR_ADDR(x) (((x)&0x7F)<<0x01) + +#define MCF532x_I2C_I2FDR_IC(x) (((x)&0x3F)) + +#define MCF532x_I2C_I2CR_IEN (0x80) // I2C enable +#define MCF532x_I2C_I2CR_IIEN (0x40) // interrupt enable +#define MCF532x_I2C_I2CR_MSTA (0x20) // master/slave mode +#define MCF532x_I2C_I2CR_MTX (0x10) // transmit/receive mode +#define MCF532x_I2C_I2CR_TXAK (0x08) // transmit acknowledge enable +#define MCF532x_I2C_I2CR_RSTA (0x04) // repeat start + +#define MCF532x_I2C_I2SR_ICF (0x80) // data transfer bit +#define MCF532x_I2C_I2SR_IAAS (0x40) // I2C addressed as a slave +#define MCF532x_I2C_I2SR_IBB (0x20) // I2C bus busy +#define MCF532x_I2C_I2SR_IAL (0x10) // aribitration lost +#define MCF532x_I2C_I2SR_SRW (0x04) // slave read/write +#define MCF532x_I2C_I2SR_IIF (0x02) // I2C interrupt +#define MCF532x_I2C_I2SR_RXAK (0x01) // received acknowledge + +#define MCF532x_PAR_FECI2C (volatile u8 *) (0xFC0A4053) + + +/* + * The M5329EVB board needs a help getting its devices initialized + * at kernel start time if dBUG doesn't set it up (for example + * it is not used), so we need to do it manually. + */ +#ifdef __ASSEMBLER__ +.macro m5329EVB_setup + movel #0xFC098000, %a7 + movel #0x0, (%a7) +#define CORE_SRAM 0x80000000 +#define CORE_SRAM_SIZE 0x8000 + movel #CORE_SRAM, %d0 + addl #0x221, %d0 + movec %d0,%RAMBAR1 + movel #CORE_SRAM, %sp + addl #CORE_SRAM_SIZE, %sp + jsr sysinit +.endm +#define PLATFORM_SETUP m5329EVB_setup + +#endif /* __ASSEMBLER__ */ + +/********************************************************************* + * + * Chip Configuration Module (CCM) + * + *********************************************************************/ + +/* Register read/write macros */ +#define MCF_CCM_CCR MCF_REG16(0xFC0A0004) +#define MCF_CCM_RCON MCF_REG16(0xFC0A0008) +#define MCF_CCM_CIR MCF_REG16(0xFC0A000A) +#define MCF_CCM_MISCCR MCF_REG16(0xFC0A0010) +#define MCF_CCM_CDR MCF_REG16(0xFC0A0012) +#define MCF_CCM_UHCSR MCF_REG16(0xFC0A0014) +#define MCF_CCM_UOCSR MCF_REG16(0xFC0A0016) + +/* Bit definitions and macros for MCF_CCM_CCR */ +#define MCF_CCM_CCR_RESERVED (0x0001) +#define MCF_CCM_CCR_PLL_MODE (0x0003) +#define MCF_CCM_CCR_OSC_MODE (0x0005) +#define MCF_CCM_CCR_BOOTPS(x) (((x)&0x0003)<<3|0x0001) +#define MCF_CCM_CCR_LOAD (0x0021) +#define MCF_CCM_CCR_LIMP (0x0041) +#define MCF_CCM_CCR_CSC(x) (((x)&0x0003)<<8|0x0001) + +/* Bit definitions and macros for MCF_CCM_RCON */ +#define MCF_CCM_RCON_RESERVED (0x0001) +#define MCF_CCM_RCON_PLL_MODE (0x0003) +#define MCF_CCM_RCON_OSC_MODE (0x0005) +#define MCF_CCM_RCON_BOOTPS(x) (((x)&0x0003)<<3|0x0001) +#define MCF_CCM_RCON_LOAD (0x0021) +#define MCF_CCM_RCON_LIMP (0x0041) +#define MCF_CCM_RCON_CSC(x) (((x)&0x0003)<<8|0x0001) + +/* Bit definitions and macros for MCF_CCM_CIR */ +#define MCF_CCM_CIR_PRN(x) (((x)&0x003F)<<0) +#define MCF_CCM_CIR_PIN(x) (((x)&0x03FF)<<6) + +/* Bit definitions and macros for MCF_CCM_MISCCR */ +#define MCF_CCM_MISCCR_USBSRC (0x0001) +#define MCF_CCM_MISCCR_USBDIV (0x0002) +#define MCF_CCM_MISCCR_SSI_SRC (0x0010) +#define MCF_CCM_MISCCR_TIM_DMA (0x0020) +#define MCF_CCM_MISCCR_SSI_PUS (0x0040) +#define MCF_CCM_MISCCR_SSI_PUE (0x0080) +#define MCF_CCM_MISCCR_LCD_CHEN (0x0100) +#define MCF_CCM_MISCCR_LIMP (0x1000) +#define MCF_CCM_MISCCR_PLL_LOCK (0x2000) + +/* Bit definitions and macros for MCF_CCM_CDR */ +#define MCF_CCM_CDR_SSIDIV(x) (((x)&0x000F)<<0) +#define MCF_CCM_CDR_LPDIV(x) (((x)&0x000F)<<8) + +/* Bit definitions and macros for MCF_CCM_UHCSR */ +#define MCF_CCM_UHCSR_XPDE (0x0001) +#define MCF_CCM_UHCSR_UHMIE (0x0002) +#define MCF_CCM_UHCSR_WKUP (0x0004) +#define MCF_CCM_UHCSR_PORTIND(x) (((x)&0x0003)<<14) + +/* Bit definitions and macros for MCF_CCM_UOCSR */ +#define MCF_CCM_UOCSR_XPDE (0x0001) +#define MCF_CCM_UOCSR_UOMIE (0x0002) +#define MCF_CCM_UOCSR_WKUP (0x0004) +#define MCF_CCM_UOCSR_PWRFLT (0x0008) +#define MCF_CCM_UOCSR_SEND (0x0010) +#define MCF_CCM_UOCSR_VVLD (0x0020) +#define MCF_CCM_UOCSR_BVLD (0x0040) +#define MCF_CCM_UOCSR_AVLD (0x0080) +#define MCF_CCM_UOCSR_DPPU (0x0100) +#define MCF_CCM_UOCSR_DCR_VBUS (0x0200) +#define MCF_CCM_UOCSR_CRG_VBUS (0x0400) +#define MCF_CCM_UOCSR_DRV_VBUS (0x0800) +#define MCF_CCM_UOCSR_DMPD (0x1000) +#define MCF_CCM_UOCSR_DPPD (0x2000) +#define MCF_CCM_UOCSR_PORTIND(x) (((x)&0x0003)<<14) + +/********************************************************************* + * + * DMA Timers (DTIM) + * + *********************************************************************/ + +/* Register read/write macros */ +#define MCF_DTIM0_DTMR MCF_REG16(0xFC070000) +#define MCF_DTIM0_DTXMR MCF_REG08(0xFC070002) +#define MCF_DTIM0_DTER MCF_REG08(0xFC070003) +#define MCF_DTIM0_DTRR MCF_REG32(0xFC070004) +#define MCF_DTIM0_DTCR MCF_REG32(0xFC070008) +#define MCF_DTIM0_DTCN MCF_REG32(0xFC07000C) +#define MCF_DTIM1_DTMR MCF_REG16(0xFC074000) +#define MCF_DTIM1_DTXMR MCF_REG08(0xFC074002) +#define MCF_DTIM1_DTER MCF_REG08(0xFC074003) +#define MCF_DTIM1_DTRR MCF_REG32(0xFC074004) +#define MCF_DTIM1_DTCR MCF_REG32(0xFC074008) +#define MCF_DTIM1_DTCN MCF_REG32(0xFC07400C) +#define MCF_DTIM2_DTMR MCF_REG16(0xFC078000) +#define MCF_DTIM2_DTXMR MCF_REG08(0xFC078002) +#define MCF_DTIM2_DTER MCF_REG08(0xFC078003) +#define MCF_DTIM2_DTRR MCF_REG32(0xFC078004) +#define MCF_DTIM2_DTCR MCF_REG32(0xFC078008) +#define MCF_DTIM2_DTCN MCF_REG32(0xFC07800C) +#define MCF_DTIM3_DTMR MCF_REG16(0xFC07C000) +#define MCF_DTIM3_DTXMR MCF_REG08(0xFC07C002) +#define MCF_DTIM3_DTER MCF_REG08(0xFC07C003) +#define MCF_DTIM3_DTRR MCF_REG32(0xFC07C004) +#define MCF_DTIM3_DTCR MCF_REG32(0xFC07C008) +#define MCF_DTIM3_DTCN MCF_REG32(0xFC07C00C) +#define MCF_DTIM_DTMR(x) MCF_REG16(0xFC070000+((x)*0x4000)) +#define MCF_DTIM_DTXMR(x) MCF_REG08(0xFC070002+((x)*0x4000)) +#define MCF_DTIM_DTER(x) MCF_REG08(0xFC070003+((x)*0x4000)) +#define MCF_DTIM_DTRR(x) MCF_REG32(0xFC070004+((x)*0x4000)) +#define MCF_DTIM_DTCR(x) MCF_REG32(0xFC070008+((x)*0x4000)) +#define MCF_DTIM_DTCN(x) MCF_REG32(0xFC07000C+((x)*0x4000)) + +/* Bit definitions and macros for MCF_DTIM_DTMR */ +#define MCF_DTIM_DTMR_RST (0x0001) +#define MCF_DTIM_DTMR_CLK(x) (((x)&0x0003)<<1) +#define MCF_DTIM_DTMR_FRR (0x0008) +#define MCF_DTIM_DTMR_ORRI (0x0010) +#define MCF_DTIM_DTMR_OM (0x0020) +#define MCF_DTIM_DTMR_CE(x) (((x)&0x0003)<<6) +#define MCF_DTIM_DTMR_PS(x) (((x)&0x00FF)<<8) +#define MCF_DTIM_DTMR_CE_ANY (0x00C0) +#define MCF_DTIM_DTMR_CE_FALL (0x0080) +#define MCF_DTIM_DTMR_CE_RISE (0x0040) +#define MCF_DTIM_DTMR_CE_NONE (0x0000) +#define MCF_DTIM_DTMR_CLK_DTIN (0x0006) +#define MCF_DTIM_DTMR_CLK_DIV16 (0x0004) +#define MCF_DTIM_DTMR_CLK_DIV1 (0x0002) +#define MCF_DTIM_DTMR_CLK_STOP (0x0000) + +/* Bit definitions and macros for MCF_DTIM_DTXMR */ +#define MCF_DTIM_DTXMR_MODE16 (0x01) +#define MCF_DTIM_DTXMR_DMAEN (0x80) + +/* Bit definitions and macros for MCF_DTIM_DTER */ +#define MCF_DTIM_DTER_CAP (0x01) +#define MCF_DTIM_DTER_REF (0x02) + +/* Bit definitions and macros for MCF_DTIM_DTRR */ +#define MCF_DTIM_DTRR_REF(x) (((x)&0xFFFFFFFF)<<0) + +/* Bit definitions and macros for MCF_DTIM_DTCR */ +#define MCF_DTIM_DTCR_CAP(x) (((x)&0xFFFFFFFF)<<0) + +/* Bit definitions and macros for MCF_DTIM_DTCN */ +#define MCF_DTIM_DTCN_CNT(x) (((x)&0xFFFFFFFF)<<0) + +/********************************************************************* + * + * FlexBus Chip Selects (FBCS) + * + *********************************************************************/ + +/* Register read/write macros */ +#define MCF_FBCS0_CSAR MCF_REG32(0xFC008000) +#define MCF_FBCS0_CSMR MCF_REG32(0xFC008004) +#define MCF_FBCS0_CSCR MCF_REG32(0xFC008008) +#define MCF_FBCS1_CSAR MCF_REG32(0xFC00800C) +#define MCF_FBCS1_CSMR MCF_REG32(0xFC008010) +#define MCF_FBCS1_CSCR MCF_REG32(0xFC008014) +#define MCF_FBCS2_CSAR MCF_REG32(0xFC008018) +#define MCF_FBCS2_CSMR MCF_REG32(0xFC00801C) +#define MCF_FBCS2_CSCR MCF_REG32(0xFC008020) +#define MCF_FBCS3_CSAR MCF_REG32(0xFC008024) +#define MCF_FBCS3_CSMR MCF_REG32(0xFC008028) +#define MCF_FBCS3_CSCR MCF_REG32(0xFC00802C) +#define MCF_FBCS4_CSAR MCF_REG32(0xFC008030) +#define MCF_FBCS4_CSMR MCF_REG32(0xFC008034) +#define MCF_FBCS4_CSCR MCF_REG32(0xFC008038) +#define MCF_FBCS5_CSAR MCF_REG32(0xFC00803C) +#define MCF_FBCS5_CSMR MCF_REG32(0xFC008040) +#define MCF_FBCS5_CSCR MCF_REG32(0xFC008044) +#define MCF_FBCS_CSAR(x) MCF_REG32(0xFC008000+((x)*0x00C)) +#define MCF_FBCS_CSMR(x) MCF_REG32(0xFC008004+((x)*0x00C)) +#define MCF_FBCS_CSCR(x) MCF_REG32(0xFC008008+((x)*0x00C)) + +/* Bit definitions and macros for MCF_FBCS_CSAR */ +#define MCF_FBCS_CSAR_BA(x) ((x)&0xFFFF0000) + +/* Bit definitions and macros for MCF_FBCS_CSMR */ +#define MCF_FBCS_CSMR_V (0x00000001) +#define MCF_FBCS_CSMR_WP (0x00000100) +#define MCF_FBCS_CSMR_BAM(x) (((x)&0x0000FFFF)<<16) +#define MCF_FBCS_CSMR_BAM_4G (0xFFFF0000) +#define MCF_FBCS_CSMR_BAM_2G (0x7FFF0000) +#define MCF_FBCS_CSMR_BAM_1G (0x3FFF0000) +#define MCF_FBCS_CSMR_BAM_1024M (0x3FFF0000) +#define MCF_FBCS_CSMR_BAM_512M (0x1FFF0000) +#define MCF_FBCS_CSMR_BAM_256M (0x0FFF0000) +#define MCF_FBCS_CSMR_BAM_128M (0x07FF0000) +#define MCF_FBCS_CSMR_BAM_64M (0x03FF0000) +#define MCF_FBCS_CSMR_BAM_32M (0x01FF0000) +#define MCF_FBCS_CSMR_BAM_16M (0x00FF0000) +#define MCF_FBCS_CSMR_BAM_8M (0x007F0000) +#define MCF_FBCS_CSMR_BAM_4M (0x003F0000) +#define MCF_FBCS_CSMR_BAM_2M (0x001F0000) +#define MCF_FBCS_CSMR_BAM_1M (0x000F0000) +#define MCF_FBCS_CSMR_BAM_1024K (0x000F0000) +#define MCF_FBCS_CSMR_BAM_512K (0x00070000) +#define MCF_FBCS_CSMR_BAM_256K (0x00030000) +#define MCF_FBCS_CSMR_BAM_128K (0x00010000) +#define MCF_FBCS_CSMR_BAM_64K (0x00000000) + +/* Bit definitions and macros for MCF_FBCS_CSCR */ +#define MCF_FBCS_CSCR_BSTW (0x00000008) +#define MCF_FBCS_CSCR_BSTR (0x00000010) +#define MCF_FBCS_CSCR_BEM (0x00000020) +#define MCF_FBCS_CSCR_PS(x) (((x)&0x00000003)<<6) +#define MCF_FBCS_CSCR_AA (0x00000100) +#define MCF_FBCS_CSCR_SBM (0x00000200) +#define MCF_FBCS_CSCR_WS(x) (((x)&0x0000003F)<<10) +#define MCF_FBCS_CSCR_WRAH(x) (((x)&0x00000003)<<16) +#define MCF_FBCS_CSCR_RDAH(x) (((x)&0x00000003)<<18) +#define MCF_FBCS_CSCR_ASET(x) (((x)&0x00000003)<<20) +#define MCF_FBCS_CSCR_SWSEN (0x00800000) +#define MCF_FBCS_CSCR_SWS(x) (((x)&0x0000003F)<<26) +#define MCF_FBCS_CSCR_PS_8 (0x0040) +#define MCF_FBCS_CSCR_PS_16 (0x0080) +#define MCF_FBCS_CSCR_PS_32 (0x0000) + +/********************************************************************* + * + * General Purpose I/O (GPIO) + * + *********************************************************************/ + +/* Register read/write macros */ +#define MCF_GPIO_PODR_FECH MCF_REG08(0xFC0A4000) +#define MCF_GPIO_PODR_FECL MCF_REG08(0xFC0A4001) +#define MCF_GPIO_PODR_SSI MCF_REG08(0xFC0A4002) +#define MCF_GPIO_PODR_BUSCTL MCF_REG08(0xFC0A4003) +#define MCF_GPIO_PODR_BE MCF_REG08(0xFC0A4004) +#define MCF_GPIO_PODR_CS MCF_REG08(0xFC0A4005) +#define MCF_GPIO_PODR_PWM MCF_REG08(0xFC0A4006) +#define MCF_GPIO_PODR_FECI2C MCF_REG08(0xFC0A4007) +#define MCF_GPIO_PODR_UART MCF_REG08(0xFC0A4009) +#define MCF_GPIO_PODR_QSPI MCF_REG08(0xFC0A400A) +#define MCF_GPIO_PODR_TIMER MCF_REG08(0xFC0A400B) +#define MCF_GPIO_PODR_LCDDATAH MCF_REG08(0xFC0A400D) +#define MCF_GPIO_PODR_LCDDATAM MCF_REG08(0xFC0A400E) +#define MCF_GPIO_PODR_LCDDATAL MCF_REG08(0xFC0A400F) +#define MCF_GPIO_PODR_LCDCTLH MCF_REG08(0xFC0A4010) +#define MCF_GPIO_PODR_LCDCTLL MCF_REG08(0xFC0A4011) +#define MCF_GPIO_PDDR_FECH MCF_REG08(0xFC0A4014) +#define MCF_GPIO_PDDR_FECL MCF_REG08(0xFC0A4015) +#define MCF_GPIO_PDDR_SSI MCF_REG08(0xFC0A4016) +#define MCF_GPIO_PDDR_BUSCTL MCF_REG08(0xFC0A4017) +#define MCF_GPIO_PDDR_BE MCF_REG08(0xFC0A4018) +#define MCF_GPIO_PDDR_CS MCF_REG08(0xFC0A4019) +#define MCF_GPIO_PDDR_PWM MCF_REG08(0xFC0A401A) +#define MCF_GPIO_PDDR_FECI2C MCF_REG08(0xFC0A401B) +#define MCF_GPIO_PDDR_UART MCF_REG08(0xFC0A401C) +#define MCF_GPIO_PDDR_QSPI MCF_REG08(0xFC0A401E) +#define MCF_GPIO_PDDR_TIMER MCF_REG08(0xFC0A401F) +#define MCF_GPIO_PDDR_LCDDATAH MCF_REG08(0xFC0A4021) +#define MCF_GPIO_PDDR_LCDDATAM MCF_REG08(0xFC0A4022) +#define MCF_GPIO_PDDR_LCDDATAL MCF_REG08(0xFC0A4023) +#define MCF_GPIO_PDDR_LCDCTLH MCF_REG08(0xFC0A4024) +#define MCF_GPIO_PDDR_LCDCTLL MCF_REG08(0xFC0A4025) +#define MCF_GPIO_PPDSDR_FECH MCF_REG08(0xFC0A4028) +#define MCF_GPIO_PPDSDR_FECL MCF_REG08(0xFC0A4029) +#define MCF_GPIO_PPDSDR_SSI MCF_REG08(0xFC0A402A) +#define MCF_GPIO_PPDSDR_BUSCTL MCF_REG08(0xFC0A402B) +#define MCF_GPIO_PPDSDR_BE MCF_REG08(0xFC0A402C) +#define MCF_GPIO_PPDSDR_CS MCF_REG08(0xFC0A402D) +#define MCF_GPIO_PPDSDR_PWM MCF_REG08(0xFC0A402E) +#define MCF_GPIO_PPDSDR_FECI2C MCF_REG08(0xFC0A402F) +#define MCF_GPIO_PPDSDR_UART MCF_REG08(0xFC0A4031) +#define MCF_GPIO_PPDSDR_QSPI MCF_REG08(0xFC0A4032) +#define MCF_GPIO_PPDSDR_TIMER MCF_REG08(0xFC0A4033) +#define MCF_GPIO_PPDSDR_LCDDATAH MCF_REG08(0xFC0A4035) +#define MCF_GPIO_PPDSDR_LCDDATAM MCF_REG08(0xFC0A4036) +#define MCF_GPIO_PPDSDR_LCDDATAL MCF_REG08(0xFC0A4037) +#define MCF_GPIO_PPDSDR_LCDCTLH MCF_REG08(0xFC0A4038) +#define MCF_GPIO_PPDSDR_LCDCTLL MCF_REG08(0xFC0A4039) +#define MCF_GPIO_PCLRR_FECH MCF_REG08(0xFC0A403C) +#define MCF_GPIO_PCLRR_FECL MCF_REG08(0xFC0A403D) +#define MCF_GPIO_PCLRR_SSI MCF_REG08(0xFC0A403E) +#define MCF_GPIO_PCLRR_BUSCTL MCF_REG08(0xFC0A403F) +#define MCF_GPIO_PCLRR_BE MCF_REG08(0xFC0A4040) +#define MCF_GPIO_PCLRR_CS MCF_REG08(0xFC0A4041) +#define MCF_GPIO_PCLRR_PWM MCF_REG08(0xFC0A4042) +#define MCF_GPIO_PCLRR_FECI2C MCF_REG08(0xFC0A4043) +#define MCF_GPIO_PCLRR_UART MCF_REG08(0xFC0A4045) +#define MCF_GPIO_PCLRR_QSPI MCF_REG08(0xFC0A4046) +#define MCF_GPIO_PCLRR_TIMER MCF_REG08(0xFC0A4047) +#define MCF_GPIO_PCLRR_LCDDATAH MCF_REG08(0xFC0A4049) +#define MCF_GPIO_PCLRR_LCDDATAM MCF_REG08(0xFC0A404A) +#define MCF_GPIO_PCLRR_LCDDATAL MCF_REG08(0xFC0A404B) +#define MCF_GPIO_PCLRR_LCDCTLH MCF_REG08(0xFC0A404C) +#define MCF_GPIO_PCLRR_LCDCTLL MCF_REG08(0xFC0A404D) +#define MCF_GPIO_PAR_FEC MCF_REG08(0xFC0A4050) +#define MCF_GPIO_PAR_PWM MCF_REG08(0xFC0A4051) +#define MCF_GPIO_PAR_BUSCTL MCF_REG08(0xFC0A4052) +#define MCF_GPIO_PAR_FECI2C MCF_REG08(0xFC0A4053) +#define MCF_GPIO_PAR_BE MCF_REG08(0xFC0A4054) +#define MCF_GPIO_PAR_CS MCF_REG08(0xFC0A4055) +#define MCF_GPIO_PAR_SSI MCF_REG16(0xFC0A4056) +#define MCF_GPIO_PAR_UART MCF_REG16(0xFC0A4058) +#define MCF_GPIO_PAR_QSPI MCF_REG16(0xFC0A405A) +#define MCF_GPIO_PAR_TIMER MCF_REG08(0xFC0A405C) +#define MCF_GPIO_PAR_LCDDATA MCF_REG08(0xFC0A405D) +#define MCF_GPIO_PAR_LCDCTL MCF_REG16(0xFC0A405E) +#define MCF_GPIO_PAR_IRQ MCF_REG16(0xFC0A4060) +#define MCF_GPIO_MSCR_FLEXBUS MCF_REG08(0xFC0A4064) +#define MCF_GPIO_MSCR_SDRAM MCF_REG08(0xFC0A4065) +#define MCF_GPIO_DSCR_I2C MCF_REG08(0xFC0A4068) +#define MCF_GPIO_DSCR_PWM MCF_REG08(0xFC0A4069) +#define MCF_GPIO_DSCR_FEC MCF_REG08(0xFC0A406A) +#define MCF_GPIO_DSCR_UART MCF_REG08(0xFC0A406B) +#define MCF_GPIO_DSCR_QSPI MCF_REG08(0xFC0A406C) +#define MCF_GPIO_DSCR_TIMER MCF_REG08(0xFC0A406D) +#define MCF_GPIO_DSCR_SSI MCF_REG08(0xFC0A406E) +#define MCF_GPIO_DSCR_LCD MCF_REG08(0xFC0A406F) +#define MCF_GPIO_DSCR_DEBUG MCF_REG08(0xFC0A4070) +#define MCF_GPIO_DSCR_CLKRST MCF_REG08(0xFC0A4071) +#define MCF_GPIO_DSCR_IRQ MCF_REG08(0xFC0A4072) + +/* Bit definitions and macros for MCF_GPIO_PODR_FECH */ +#define MCF_GPIO_PODR_FECH_PODR_FECH0 (0x01) +#define MCF_GPIO_PODR_FECH_PODR_FECH1 (0x02) +#define MCF_GPIO_PODR_FECH_PODR_FECH2 (0x04) +#define MCF_GPIO_PODR_FECH_PODR_FECH3 (0x08) +#define MCF_GPIO_PODR_FECH_PODR_FECH4 (0x10) +#define MCF_GPIO_PODR_FECH_PODR_FECH5 (0x20) +#define MCF_GPIO_PODR_FECH_PODR_FECH6 (0x40) +#define MCF_GPIO_PODR_FECH_PODR_FECH7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PODR_FECL */ +#define MCF_GPIO_PODR_FECL_PODR_FECL0 (0x01) +#define MCF_GPIO_PODR_FECL_PODR_FECL1 (0x02) +#define MCF_GPIO_PODR_FECL_PODR_FECL2 (0x04) +#define MCF_GPIO_PODR_FECL_PODR_FECL3 (0x08) +#define MCF_GPIO_PODR_FECL_PODR_FECL4 (0x10) +#define MCF_GPIO_PODR_FECL_PODR_FECL5 (0x20) +#define MCF_GPIO_PODR_FECL_PODR_FECL6 (0x40) +#define MCF_GPIO_PODR_FECL_PODR_FECL7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PODR_SSI */ +#define MCF_GPIO_PODR_SSI_PODR_SSI0 (0x01) +#define MCF_GPIO_PODR_SSI_PODR_SSI1 (0x02) +#define MCF_GPIO_PODR_SSI_PODR_SSI2 (0x04) +#define MCF_GPIO_PODR_SSI_PODR_SSI3 (0x08) +#define MCF_GPIO_PODR_SSI_PODR_SSI4 (0x10) + +/* Bit definitions and macros for MCF_GPIO_PODR_BUSCTL */ +#define MCF_GPIO_PODR_BUSCTL_POSDR_BUSCTL0 (0x01) +#define MCF_GPIO_PODR_BUSCTL_PODR_BUSCTL1 (0x02) +#define MCF_GPIO_PODR_BUSCTL_PODR_BUSCTL2 (0x04) +#define MCF_GPIO_PODR_BUSCTL_PODR_BUSCTL3 (0x08) + +/* Bit definitions and macros for MCF_GPIO_PODR_BE */ +#define MCF_GPIO_PODR_BE_PODR_BE0 (0x01) +#define MCF_GPIO_PODR_BE_PODR_BE1 (0x02) +#define MCF_GPIO_PODR_BE_PODR_BE2 (0x04) +#define MCF_GPIO_PODR_BE_PODR_BE3 (0x08) + +/* Bit definitions and macros for MCF_GPIO_PODR_CS */ +#define MCF_GPIO_PODR_CS_PODR_CS1 (0x02) +#define MCF_GPIO_PODR_CS_PODR_CS2 (0x04) +#define MCF_GPIO_PODR_CS_PODR_CS3 (0x08) +#define MCF_GPIO_PODR_CS_PODR_CS4 (0x10) +#define MCF_GPIO_PODR_CS_PODR_CS5 (0x20) + +/* Bit definitions and macros for MCF_GPIO_PODR_PWM */ +#define MCF_GPIO_PODR_PWM_PODR_PWM2 (0x04) +#define MCF_GPIO_PODR_PWM_PODR_PWM3 (0x08) +#define MCF_GPIO_PODR_PWM_PODR_PWM4 (0x10) +#define MCF_GPIO_PODR_PWM_PODR_PWM5 (0x20) + +/* Bit definitions and macros for MCF_GPIO_PODR_FECI2C */ +#define MCF_GPIO_PODR_FECI2C_PODR_FECI2C0 (0x01) +#define MCF_GPIO_PODR_FECI2C_PODR_FECI2C1 (0x02) +#define MCF_GPIO_PODR_FECI2C_PODR_FECI2C2 (0x04) +#define MCF_GPIO_PODR_FECI2C_PODR_FECI2C3 (0x08) + +/* Bit definitions and macros for MCF_GPIO_PODR_UART */ +#define MCF_GPIO_PODR_UART_PODR_UART0 (0x01) +#define MCF_GPIO_PODR_UART_PODR_UART1 (0x02) +#define MCF_GPIO_PODR_UART_PODR_UART2 (0x04) +#define MCF_GPIO_PODR_UART_PODR_UART3 (0x08) +#define MCF_GPIO_PODR_UART_PODR_UART4 (0x10) +#define MCF_GPIO_PODR_UART_PODR_UART5 (0x20) +#define MCF_GPIO_PODR_UART_PODR_UART6 (0x40) +#define MCF_GPIO_PODR_UART_PODR_UART7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PODR_QSPI */ +#define MCF_GPIO_PODR_QSPI_PODR_QSPI0 (0x01) +#define MCF_GPIO_PODR_QSPI_PODR_QSPI1 (0x02) +#define MCF_GPIO_PODR_QSPI_PODR_QSPI2 (0x04) +#define MCF_GPIO_PODR_QSPI_PODR_QSPI3 (0x08) +#define MCF_GPIO_PODR_QSPI_PODR_QSPI4 (0x10) +#define MCF_GPIO_PODR_QSPI_PODR_QSPI5 (0x20) + +/* Bit definitions and macros for MCF_GPIO_PODR_TIMER */ +#define MCF_GPIO_PODR_TIMER_PODR_TIMER0 (0x01) +#define MCF_GPIO_PODR_TIMER_PODR_TIMER1 (0x02) +#define MCF_GPIO_PODR_TIMER_PODR_TIMER2 (0x04) +#define MCF_GPIO_PODR_TIMER_PODR_TIMER3 (0x08) + +/* Bit definitions and macros for MCF_GPIO_PODR_LCDDATAH */ +#define MCF_GPIO_PODR_LCDDATAH_PODR_LCDDATAH0 (0x01) +#define MCF_GPIO_PODR_LCDDATAH_PODR_LCDDATAH1 (0x02) + +/* Bit definitions and macros for MCF_GPIO_PODR_LCDDATAM */ +#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM0 (0x01) +#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM1 (0x02) +#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM2 (0x04) +#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM3 (0x08) +#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM4 (0x10) +#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM5 (0x20) +#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM6 (0x40) +#define MCF_GPIO_PODR_LCDDATAM_PODR_LCDDATAM7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PODR_LCDDATAL */ +#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL0 (0x01) +#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL1 (0x02) +#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL2 (0x04) +#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL3 (0x08) +#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL4 (0x10) +#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL5 (0x20) +#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL6 (0x40) +#define MCF_GPIO_PODR_LCDDATAL_PODR_LCDDATAL7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PODR_LCDCTLH */ +#define MCF_GPIO_PODR_LCDCTLH_PODR_LCDCTLH0 (0x01) + +/* Bit definitions and macros for MCF_GPIO_PODR_LCDCTLL */ +#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL0 (0x01) +#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL1 (0x02) +#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL2 (0x04) +#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL3 (0x08) +#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL4 (0x10) +#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL5 (0x20) +#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL6 (0x40) +#define MCF_GPIO_PODR_LCDCTLL_PODR_LCDCTLL7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PDDR_FECH */ +#define MCF_GPIO_PDDR_FECH_PDDR_FECH0 (0x01) +#define MCF_GPIO_PDDR_FECH_PDDR_FECH1 (0x02) +#define MCF_GPIO_PDDR_FECH_PDDR_FECH2 (0x04) +#define MCF_GPIO_PDDR_FECH_PDDR_FECH3 (0x08) +#define MCF_GPIO_PDDR_FECH_PDDR_FECH4 (0x10) +#define MCF_GPIO_PDDR_FECH_PDDR_FECH5 (0x20) +#define MCF_GPIO_PDDR_FECH_PDDR_FECH6 (0x40) +#define MCF_GPIO_PDDR_FECH_PDDR_FECH7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PDDR_FECL */ +#define MCF_GPIO_PDDR_FECL_PDDR_FECL0 (0x01) +#define MCF_GPIO_PDDR_FECL_PDDR_FECL1 (0x02) +#define MCF_GPIO_PDDR_FECL_PDDR_FECL2 (0x04) +#define MCF_GPIO_PDDR_FECL_PDDR_FECL3 (0x08) +#define MCF_GPIO_PDDR_FECL_PDDR_FECL4 (0x10) +#define MCF_GPIO_PDDR_FECL_PDDR_FECL5 (0x20) +#define MCF_GPIO_PDDR_FECL_PDDR_FECL6 (0x40) +#define MCF_GPIO_PDDR_FECL_PDDR_FECL7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PDDR_SSI */ +#define MCF_GPIO_PDDR_SSI_PDDR_SSI0 (0x01) +#define MCF_GPIO_PDDR_SSI_PDDR_SSI1 (0x02) +#define MCF_GPIO_PDDR_SSI_PDDR_SSI2 (0x04) +#define MCF_GPIO_PDDR_SSI_PDDR_SSI3 (0x08) +#define MCF_GPIO_PDDR_SSI_PDDR_SSI4 (0x10) + +/* Bit definitions and macros for MCF_GPIO_PDDR_BUSCTL */ +#define MCF_GPIO_PDDR_BUSCTL_POSDR_BUSCTL0 (0x01) +#define MCF_GPIO_PDDR_BUSCTL_PDDR_BUSCTL1 (0x02) +#define MCF_GPIO_PDDR_BUSCTL_PDDR_BUSCTL2 (0x04) +#define MCF_GPIO_PDDR_BUSCTL_PDDR_BUSCTL3 (0x08) + +/* Bit definitions and macros for MCF_GPIO_PDDR_BE */ +#define MCF_GPIO_PDDR_BE_PDDR_BE0 (0x01) +#define MCF_GPIO_PDDR_BE_PDDR_BE1 (0x02) +#define MCF_GPIO_PDDR_BE_PDDR_BE2 (0x04) +#define MCF_GPIO_PDDR_BE_PDDR_BE3 (0x08) + +/* Bit definitions and macros for MCF_GPIO_PDDR_CS */ +#define MCF_GPIO_PDDR_CS_PDDR_CS1 (0x02) +#define MCF_GPIO_PDDR_CS_PDDR_CS2 (0x04) +#define MCF_GPIO_PDDR_CS_PDDR_CS3 (0x08) +#define MCF_GPIO_PDDR_CS_PDDR_CS4 (0x10) +#define MCF_GPIO_PDDR_CS_PDDR_CS5 (0x20) + +/* Bit definitions and macros for MCF_GPIO_PDDR_PWM */ +#define MCF_GPIO_PDDR_PWM_PDDR_PWM2 (0x04) +#define MCF_GPIO_PDDR_PWM_PDDR_PWM3 (0x08) +#define MCF_GPIO_PDDR_PWM_PDDR_PWM4 (0x10) +#define MCF_GPIO_PDDR_PWM_PDDR_PWM5 (0x20) + +/* Bit definitions and macros for MCF_GPIO_PDDR_FECI2C */ +#define MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C0 (0x01) +#define MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C1 (0x02) +#define MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C2 (0x04) +#define MCF_GPIO_PDDR_FECI2C_PDDR_FECI2C3 (0x08) + +/* Bit definitions and macros for MCF_GPIO_PDDR_UART */ +#define MCF_GPIO_PDDR_UART_PDDR_UART0 (0x01) +#define MCF_GPIO_PDDR_UART_PDDR_UART1 (0x02) +#define MCF_GPIO_PDDR_UART_PDDR_UART2 (0x04) +#define MCF_GPIO_PDDR_UART_PDDR_UART3 (0x08) +#define MCF_GPIO_PDDR_UART_PDDR_UART4 (0x10) +#define MCF_GPIO_PDDR_UART_PDDR_UART5 (0x20) +#define MCF_GPIO_PDDR_UART_PDDR_UART6 (0x40) +#define MCF_GPIO_PDDR_UART_PDDR_UART7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PDDR_QSPI */ +#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI0 (0x01) +#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI1 (0x02) +#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI2 (0x04) +#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI3 (0x08) +#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI4 (0x10) +#define MCF_GPIO_PDDR_QSPI_PDDR_QSPI5 (0x20) + +/* Bit definitions and macros for MCF_GPIO_PDDR_TIMER */ +#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER0 (0x01) +#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER1 (0x02) +#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER2 (0x04) +#define MCF_GPIO_PDDR_TIMER_PDDR_TIMER3 (0x08) + +/* Bit definitions and macros for MCF_GPIO_PDDR_LCDDATAH */ +#define MCF_GPIO_PDDR_LCDDATAH_PDDR_LCDDATAH0 (0x01) +#define MCF_GPIO_PDDR_LCDDATAH_PDDR_LCDDATAH1 (0x02) + +/* Bit definitions and macros for MCF_GPIO_PDDR_LCDDATAM */ +#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM0 (0x01) +#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM1 (0x02) +#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM2 (0x04) +#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM3 (0x08) +#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM4 (0x10) +#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM5 (0x20) +#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM6 (0x40) +#define MCF_GPIO_PDDR_LCDDATAM_PDDR_LCDDATAM7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PDDR_LCDDATAL */ +#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL0 (0x01) +#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL1 (0x02) +#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL2 (0x04) +#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL3 (0x08) +#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL4 (0x10) +#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL5 (0x20) +#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL6 (0x40) +#define MCF_GPIO_PDDR_LCDDATAL_PDDR_LCDDATAL7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PDDR_LCDCTLH */ +#define MCF_GPIO_PDDR_LCDCTLH_PDDR_LCDCTLH0 (0x01) + +/* Bit definitions and macros for MCF_GPIO_PDDR_LCDCTLL */ +#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL0 (0x01) +#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL1 (0x02) +#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL2 (0x04) +#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL3 (0x08) +#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL4 (0x10) +#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL5 (0x20) +#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL6 (0x40) +#define MCF_GPIO_PDDR_LCDCTLL_PDDR_LCDCTLL7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PPDSDR_FECH */ +#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH0 (0x01) +#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH1 (0x02) +#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH2 (0x04) +#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH3 (0x08) +#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH4 (0x10) +#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH5 (0x20) +#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH6 (0x40) +#define MCF_GPIO_PPDSDR_FECH_PPDSDR_FECH7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PPDSDR_FECL */ +#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL0 (0x01) +#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL1 (0x02) +#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL2 (0x04) +#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL3 (0x08) +#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL4 (0x10) +#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL5 (0x20) +#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL6 (0x40) +#define MCF_GPIO_PPDSDR_FECL_PPDSDR_FECL7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PPDSDR_SSI */ +#define MCF_GPIO_PPDSDR_SSI_PPDSDR_SSI0 (0x01) +#define MCF_GPIO_PPDSDR_SSI_PPDSDR_SSI1 (0x02) +#define MCF_GPIO_PPDSDR_SSI_PPDSDR_SSI2 (0x04) +#define MCF_GPIO_PPDSDR_SSI_PPDSDR_SSI3 (0x08) +#define MCF_GPIO_PPDSDR_SSI_PPDSDR_SSI4 (0x10) + +/* Bit definitions and macros for MCF_GPIO_PPDSDR_BUSCTL */ +#define MCF_GPIO_PPDSDR_BUSCTL_POSDR_BUSCTL0 (0x01) +#define MCF_GPIO_PPDSDR_BUSCTL_PPDSDR_BUSCTL1 (0x02) +#define MCF_GPIO_PPDSDR_BUSCTL_PPDSDR_BUSCTL2 (0x04) +#define MCF_GPIO_PPDSDR_BUSCTL_PPDSDR_BUSCTL3 (0x08) + +/* Bit definitions and macros for MCF_GPIO_PPDSDR_BE */ +#define MCF_GPIO_PPDSDR_BE_PPDSDR_BE0 (0x01) +#define MCF_GPIO_PPDSDR_BE_PPDSDR_BE1 (0x02) +#define MCF_GPIO_PPDSDR_BE_PPDSDR_BE2 (0x04) +#define MCF_GPIO_PPDSDR_BE_PPDSDR_BE3 (0x08) + +/* Bit definitions and macros for MCF_GPIO_PPDSDR_CS */ +#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS1 (0x02) +#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS2 (0x04) +#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS3 (0x08) +#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS4 (0x10) +#define MCF_GPIO_PPDSDR_CS_PPDSDR_CS5 (0x20) + +/* Bit definitions and macros for MCF_GPIO_PPDSDR_PWM */ +#define MCF_GPIO_PPDSDR_PWM_PPDSDR_PWM2 (0x04) +#define MCF_GPIO_PPDSDR_PWM_PPDSDR_PWM3 (0x08) +#define MCF_GPIO_PPDSDR_PWM_PPDSDR_PWM4 (0x10) +#define MCF_GPIO_PPDSDR_PWM_PPDSDR_PWM5 (0x20) + +/* Bit definitions and macros for MCF_GPIO_PPDSDR_FECI2C */ +#define MCF_GPIO_PPDSDR_FECI2C_PPDSDR_FECI2C0 (0x01) +#define MCF_GPIO_PPDSDR_FECI2C_PPDSDR_FECI2C1 (0x02) +#define MCF_GPIO_PPDSDR_FECI2C_PPDSDR_FECI2C2 (0x04) +#define MCF_GPIO_PPDSDR_FECI2C_PPDSDR_FECI2C3 (0x08) + +/* Bit definitions and macros for MCF_GPIO_PPDSDR_UART */ +#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART0 (0x01) +#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART1 (0x02) +#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART2 (0x04) +#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART3 (0x08) +#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART4 (0x10) +#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART5 (0x20) +#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART6 (0x40) +#define MCF_GPIO_PPDSDR_UART_PPDSDR_UART7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PPDSDR_QSPI */ +#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI0 (0x01) +#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI1 (0x02) +#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI2 (0x04) +#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI3 (0x08) +#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI4 (0x10) +#define MCF_GPIO_PPDSDR_QSPI_PPDSDR_QSPI5 (0x20) + +/* Bit definitions and macros for MCF_GPIO_PPDSDR_TIMER */ +#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER0 (0x01) +#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER1 (0x02) +#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER2 (0x04) +#define MCF_GPIO_PPDSDR_TIMER_PPDSDR_TIMER3 (0x08) + +/* Bit definitions and macros for MCF_GPIO_PPDSDR_LCDDATAH */ +#define MCF_GPIO_PPDSDR_LCDDATAH_PPDSDR_LCDDATAH0 (0x01) +#define MCF_GPIO_PPDSDR_LCDDATAH_PPDSDR_LCDDATAH1 (0x02) + +/* Bit definitions and macros for MCF_GPIO_PPDSDR_LCDDATAM */ +#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM0 (0x01) +#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM1 (0x02) +#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM2 (0x04) +#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM3 (0x08) +#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM4 (0x10) +#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM5 (0x20) +#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM6 (0x40) +#define MCF_GPIO_PPDSDR_LCDDATAM_PPDSDR_LCDDATAM7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PPDSDR_LCDDATAL */ +#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL0 (0x01) +#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL1 (0x02) +#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL2 (0x04) +#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL3 (0x08) +#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL4 (0x10) +#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL5 (0x20) +#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL6 (0x40) +#define MCF_GPIO_PPDSDR_LCDDATAL_PPDSDR_LCDDATAL7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PPDSDR_LCDCTLH */ +#define MCF_GPIO_PPDSDR_LCDCTLH_PPDSDR_LCDCTLH0 (0x01) + +/* Bit definitions and macros for MCF_GPIO_PPDSDR_LCDCTLL */ +#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL0 (0x01) +#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL1 (0x02) +#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL2 (0x04) +#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL3 (0x08) +#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL4 (0x10) +#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL5 (0x20) +#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL6 (0x40) +#define MCF_GPIO_PPDSDR_LCDCTLL_PPDSDR_LCDCTLL7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PCLRR_FECH */ +#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH0 (0x01) +#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH1 (0x02) +#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH2 (0x04) +#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH3 (0x08) +#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH4 (0x10) +#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH5 (0x20) +#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH6 (0x40) +#define MCF_GPIO_PCLRR_FECH_PCLRR_FECH7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PCLRR_FECL */ +#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL0 (0x01) +#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL1 (0x02) +#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL2 (0x04) +#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL3 (0x08) +#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL4 (0x10) +#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL5 (0x20) +#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL6 (0x40) +#define MCF_GPIO_PCLRR_FECL_PCLRR_FECL7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PCLRR_SSI */ +#define MCF_GPIO_PCLRR_SSI_PCLRR_SSI0 (0x01) +#define MCF_GPIO_PCLRR_SSI_PCLRR_SSI1 (0x02) +#define MCF_GPIO_PCLRR_SSI_PCLRR_SSI2 (0x04) +#define MCF_GPIO_PCLRR_SSI_PCLRR_SSI3 (0x08) +#define MCF_GPIO_PCLRR_SSI_PCLRR_SSI4 (0x10) + +/* Bit definitions and macros for MCF_GPIO_PCLRR_BUSCTL */ +#define MCF_GPIO_PCLRR_BUSCTL_POSDR_BUSCTL0 (0x01) +#define MCF_GPIO_PCLRR_BUSCTL_PCLRR_BUSCTL1 (0x02) +#define MCF_GPIO_PCLRR_BUSCTL_PCLRR_BUSCTL2 (0x04) +#define MCF_GPIO_PCLRR_BUSCTL_PCLRR_BUSCTL3 (0x08) + +/* Bit definitions and macros for MCF_GPIO_PCLRR_BE */ +#define MCF_GPIO_PCLRR_BE_PCLRR_BE0 (0x01) +#define MCF_GPIO_PCLRR_BE_PCLRR_BE1 (0x02) +#define MCF_GPIO_PCLRR_BE_PCLRR_BE2 (0x04) +#define MCF_GPIO_PCLRR_BE_PCLRR_BE3 (0x08) + +/* Bit definitions and macros for MCF_GPIO_PCLRR_CS */ +#define MCF_GPIO_PCLRR_CS_PCLRR_CS1 (0x02) +#define MCF_GPIO_PCLRR_CS_PCLRR_CS2 (0x04) +#define MCF_GPIO_PCLRR_CS_PCLRR_CS3 (0x08) +#define MCF_GPIO_PCLRR_CS_PCLRR_CS4 (0x10) +#define MCF_GPIO_PCLRR_CS_PCLRR_CS5 (0x20) + +/* Bit definitions and macros for MCF_GPIO_PCLRR_PWM */ +#define MCF_GPIO_PCLRR_PWM_PCLRR_PWM2 (0x04) +#define MCF_GPIO_PCLRR_PWM_PCLRR_PWM3 (0x08) +#define MCF_GPIO_PCLRR_PWM_PCLRR_PWM4 (0x10) +#define MCF_GPIO_PCLRR_PWM_PCLRR_PWM5 (0x20) + +/* Bit definitions and macros for MCF_GPIO_PCLRR_FECI2C */ +#define MCF_GPIO_PCLRR_FECI2C_PCLRR_FECI2C0 (0x01) +#define MCF_GPIO_PCLRR_FECI2C_PCLRR_FECI2C1 (0x02) +#define MCF_GPIO_PCLRR_FECI2C_PCLRR_FECI2C2 (0x04) +#define MCF_GPIO_PCLRR_FECI2C_PCLRR_FECI2C3 (0x08) + +/* Bit definitions and macros for MCF_GPIO_PCLRR_UART */ +#define MCF_GPIO_PCLRR_UART_PCLRR_UART0 (0x01) +#define MCF_GPIO_PCLRR_UART_PCLRR_UART1 (0x02) +#define MCF_GPIO_PCLRR_UART_PCLRR_UART2 (0x04) +#define MCF_GPIO_PCLRR_UART_PCLRR_UART3 (0x08) +#define MCF_GPIO_PCLRR_UART_PCLRR_UART4 (0x10) +#define MCF_GPIO_PCLRR_UART_PCLRR_UART5 (0x20) +#define MCF_GPIO_PCLRR_UART_PCLRR_UART6 (0x40) +#define MCF_GPIO_PCLRR_UART_PCLRR_UART7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PCLRR_QSPI */ +#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI0 (0x01) +#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI1 (0x02) +#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI2 (0x04) +#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI3 (0x08) +#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI4 (0x10) +#define MCF_GPIO_PCLRR_QSPI_PCLRR_QSPI5 (0x20) + +/* Bit definitions and macros for MCF_GPIO_PCLRR_TIMER */ +#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER0 (0x01) +#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER1 (0x02) +#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER2 (0x04) +#define MCF_GPIO_PCLRR_TIMER_PCLRR_TIMER3 (0x08) + +/* Bit definitions and macros for MCF_GPIO_PCLRR_LCDDATAH */ +#define MCF_GPIO_PCLRR_LCDDATAH_PCLRR_LCDDATAH0 (0x01) +#define MCF_GPIO_PCLRR_LCDDATAH_PCLRR_LCDDATAH1 (0x02) + +/* Bit definitions and macros for MCF_GPIO_PCLRR_LCDDATAM */ +#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM0 (0x01) +#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM1 (0x02) +#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM2 (0x04) +#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM3 (0x08) +#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM4 (0x10) +#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM5 (0x20) +#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM6 (0x40) +#define MCF_GPIO_PCLRR_LCDDATAM_PCLRR_LCDDATAM7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PCLRR_LCDDATAL */ +#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL0 (0x01) +#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL1 (0x02) +#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL2 (0x04) +#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL3 (0x08) +#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL4 (0x10) +#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL5 (0x20) +#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL6 (0x40) +#define MCF_GPIO_PCLRR_LCDDATAL_PCLRR_LCDDATAL7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PCLRR_LCDCTLH */ +#define MCF_GPIO_PCLRR_LCDCTLH_PCLRR_LCDCTLH0 (0x01) + +/* Bit definitions and macros for MCF_GPIO_PCLRR_LCDCTLL */ +#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL0 (0x01) +#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL1 (0x02) +#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL2 (0x04) +#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL3 (0x08) +#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL4 (0x10) +#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL5 (0x20) +#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL6 (0x40) +#define MCF_GPIO_PCLRR_LCDCTLL_PCLRR_LCDCTLL7 (0x80) + +/* Bit definitions and macros for MCF_GPIO_PAR_FEC */ +#define MCF_GPIO_PAR_FEC_PAR_FEC_MII(x) (((x)&0x03)<<0) +#define MCF_GPIO_PAR_FEC_PAR_FEC_7W(x) (((x)&0x03)<<2) +#define MCF_GPIO_PAR_FEC_PAR_FEC_7W_GPIO (0x00) +#define MCF_GPIO_PAR_FEC_PAR_FEC_7W_URTS1 (0x04) +#define MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC (0x0C) +#define MCF_GPIO_PAR_FEC_PAR_FEC_MII_GPIO (0x00) +#define MCF_GPIO_PAR_FEC_PAR_FEC_MII_UART (0x01) +#define MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC (0x03) + +/* Bit definitions and macros for MCF_GPIO_PAR_PWM */ +#define MCF_GPIO_PAR_PWM_PAR_PWM1(x) (((x)&0x03)<<0) +#define MCF_GPIO_PAR_PWM_PAR_PWM3(x) (((x)&0x03)<<2) +#define MCF_GPIO_PAR_PWM_PAR_PWM5 (0x10) +#define MCF_GPIO_PAR_PWM_PAR_PWM7 (0x20) + +/* Bit definitions and macros for MCF_GPIO_PAR_BUSCTL */ +#define MCF_GPIO_PAR_BUSCTL_PAR_TS(x) (((x)&0x03)<<3) +#define MCF_GPIO_PAR_BUSCTL_PAR_RWB (0x20) +#define MCF_GPIO_PAR_BUSCTL_PAR_TA (0x40) +#define MCF_GPIO_PAR_BUSCTL_PAR_OE (0x80) +#define MCF_GPIO_PAR_BUSCTL_PAR_OE_GPIO (0x00) +#define MCF_GPIO_PAR_BUSCTL_PAR_OE_OE (0x80) +#define MCF_GPIO_PAR_BUSCTL_PAR_TA_GPIO (0x00) +#define MCF_GPIO_PAR_BUSCTL_PAR_TA_TA (0x40) +#define MCF_GPIO_PAR_BUSCTL_PAR_RWB_GPIO (0x00) +#define MCF_GPIO_PAR_BUSCTL_PAR_RWB_RWB (0x20) +#define MCF_GPIO_PAR_BUSCTL_PAR_TS_GPIO (0x00) +#define MCF_GPIO_PAR_BUSCTL_PAR_TS_DACK0 (0x10) +#define MCF_GPIO_PAR_BUSCTL_PAR_TS_TS (0x18) + +/* Bit definitions and macros for MCF_GPIO_PAR_FECI2C */ +#define MCF_GPIO_PAR_FECI2C_PAR_SDA(x) (((x)&0x03)<<0) +#define MCF_GPIO_PAR_FECI2C_PAR_SCL(x) (((x)&0x03)<<2) +#define MCF_GPIO_PAR_FECI2C_PAR_MDIO(x) (((x)&0x03)<<4) +#define MCF_GPIO_PAR_FECI2C_PAR_MDC(x) (((x)&0x03)<<6) +#define MCF_GPIO_PAR_FECI2C_PAR_MDC_GPIO (0x00) +#define MCF_GPIO_PAR_FECI2C_PAR_MDC_UTXD2 (0x40) +#define MCF_GPIO_PAR_FECI2C_PAR_MDC_SCL (0x80) +#define MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC (0xC0) +#define MCF_GPIO_PAR_FECI2C_PAR_MDIO_GPIO (0x00) +#define MCF_GPIO_PAR_FECI2C_PAR_MDIO_URXD2 (0x10) +#define MCF_GPIO_PAR_FECI2C_PAR_MDIO_SDA (0x20) +#define MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO (0x30) +#define MCF_GPIO_PAR_FECI2C_PAR_SCL_GPIO (0x00) +#define MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2 (0x04) +#define MCF_GPIO_PAR_FECI2C_PAR_SCL_SCL (0x0C) +#define MCF_GPIO_PAR_FECI2C_PAR_SDA_GPIO (0x00) +#define MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2 (0x02) +#define MCF_GPIO_PAR_FECI2C_PAR_SDA_SDA (0x03) + +/* Bit definitions and macros for MCF_GPIO_PAR_BE */ +#define MCF_GPIO_PAR_BE_PAR_BE0 (0x01) +#define MCF_GPIO_PAR_BE_PAR_BE1 (0x02) +#define MCF_GPIO_PAR_BE_PAR_BE2 (0x04) +#define MCF_GPIO_PAR_BE_PAR_BE3 (0x08) + +/* Bit definitions and macros for MCF_GPIO_PAR_CS */ +#define MCF_GPIO_PAR_CS_PAR_CS1 (0x02) +#define MCF_GPIO_PAR_CS_PAR_CS2 (0x04) +#define MCF_GPIO_PAR_CS_PAR_CS3 (0x08) +#define MCF_GPIO_PAR_CS_PAR_CS4 (0x10) +#define MCF_GPIO_PAR_CS_PAR_CS5 (0x20) +#define MCF_GPIO_PAR_CS_PAR_CS_CS1_GPIO (0x00) +#define MCF_GPIO_PAR_CS_PAR_CS_CS1_SDCS1 (0x01) +#define MCF_GPIO_PAR_CS_PAR_CS_CS1_CS1 (0x03) + +/* Bit definitions and macros for MCF_GPIO_PAR_SSI */ +#define MCF_GPIO_PAR_SSI_PAR_MCLK (0x0080) +#define MCF_GPIO_PAR_SSI_PAR_TXD(x) (((x)&0x0003)<<8) +#define MCF_GPIO_PAR_SSI_PAR_RXD(x) (((x)&0x0003)<<10) +#define MCF_GPIO_PAR_SSI_PAR_FS(x) (((x)&0x0003)<<12) +#define MCF_GPIO_PAR_SSI_PAR_BCLK(x) (((x)&0x0003)<<14) + +/* Bit definitions and macros for MCF_GPIO_PAR_UART */ +#define MCF_GPIO_PAR_UART_PAR_UTXD0 (0x0001) +#define MCF_GPIO_PAR_UART_PAR_URXD0 (0x0002) +#define MCF_GPIO_PAR_UART_PAR_URTS0 (0x0004) +#define MCF_GPIO_PAR_UART_PAR_UCTS0 (0x0008) +#define MCF_GPIO_PAR_UART_PAR_UTXD1(x) (((x)&0x0003)<<4) +#define MCF_GPIO_PAR_UART_PAR_URXD1(x) (((x)&0x0003)<<6) +#define MCF_GPIO_PAR_UART_PAR_URTS1(x) (((x)&0x0003)<<8) +#define MCF_GPIO_PAR_UART_PAR_UCTS1(x) (((x)&0x0003)<<10) +#define MCF_GPIO_PAR_UART_PAR_UCTS1_GPIO (0x0000) +#define MCF_GPIO_PAR_UART_PAR_UCTS1_SSI_BCLK (0x0800) +#define MCF_GPIO_PAR_UART_PAR_UCTS1_ULPI_D7 (0x0400) +#define MCF_GPIO_PAR_UART_PAR_UCTS1_UCTS1 (0x0C00) +#define MCF_GPIO_PAR_UART_PAR_URTS1_GPIO (0x0000) +#define MCF_GPIO_PAR_UART_PAR_URTS1_SSI_FS (0x0200) +#define MCF_GPIO_PAR_UART_PAR_URTS1_ULPI_D6 (0x0100) +#define MCF_GPIO_PAR_UART_PAR_URTS1_URTS1 (0x0300) +#define MCF_GPIO_PAR_UART_PAR_URXD1_GPIO (0x0000) +#define MCF_GPIO_PAR_UART_PAR_URXD1_SSI_RXD (0x0080) +#define MCF_GPIO_PAR_UART_PAR_URXD1_ULPI_D5 (0x0040) +#define MCF_GPIO_PAR_UART_PAR_URXD1_URXD1 (0x00C0) +#define MCF_GPIO_PAR_UART_PAR_UTXD1_GPIO (0x0000) +#define MCF_GPIO_PAR_UART_PAR_UTXD1_SSI_TXD (0x0020) +#define MCF_GPIO_PAR_UART_PAR_UTXD1_ULPI_D4 (0x0010) +#define MCF_GPIO_PAR_UART_PAR_UTXD1_UTXD1 (0x0030) + +/* Bit definitions and macros for MCF_GPIO_PAR_QSPI */ +#define MCF_GPIO_PAR_QSPI_PAR_SCK(x) (((x)&0x0003)<<4) +#define MCF_GPIO_PAR_QSPI_PAR_DOUT(x) (((x)&0x0003)<<6) +#define MCF_GPIO_PAR_QSPI_PAR_DIN(x) (((x)&0x0003)<<8) +#define MCF_GPIO_PAR_QSPI_PAR_PCS0(x) (((x)&0x0003)<<10) +#define MCF_GPIO_PAR_QSPI_PAR_PCS1(x) (((x)&0x0003)<<12) +#define MCF_GPIO_PAR_QSPI_PAR_PCS2(x) (((x)&0x0003)<<14) + +/* Bit definitions and macros for MCF_GPIO_PAR_TIMER */ +#define MCF_GPIO_PAR_TIMER_PAR_TIN0(x) (((x)&0x03)<<0) +#define MCF_GPIO_PAR_TIMER_PAR_TIN1(x) (((x)&0x03)<<2) +#define MCF_GPIO_PAR_TIMER_PAR_TIN2(x) (((x)&0x03)<<4) +#define MCF_GPIO_PAR_TIMER_PAR_TIN3(x) (((x)&0x03)<<6) +#define MCF_GPIO_PAR_TIMER_PAR_TIN3_GPIO (0x00) +#define MCF_GPIO_PAR_TIMER_PAR_TIN3_TOUT3 (0x80) +#define MCF_GPIO_PAR_TIMER_PAR_TIN3_URXD2 (0x40) +#define MCF_GPIO_PAR_TIMER_PAR_TIN3_TIN3 (0xC0) +#define MCF_GPIO_PAR_TIMER_PAR_TIN2_GPIO (0x00) +#define MCF_GPIO_PAR_TIMER_PAR_TIN2_TOUT2 (0x20) +#define MCF_GPIO_PAR_TIMER_PAR_TIN2_UTXD2 (0x10) +#define MCF_GPIO_PAR_TIMER_PAR_TIN2_TIN2 (0x30) +#define MCF_GPIO_PAR_TIMER_PAR_TIN1_GPIO (0x00) +#define MCF_GPIO_PAR_TIMER_PAR_TIN1_TOUT1 (0x08) +#define MCF_GPIO_PAR_TIMER_PAR_TIN1_DACK1 (0x04) +#define MCF_GPIO_PAR_TIMER_PAR_TIN1_TIN1 (0x0C) +#define MCF_GPIO_PAR_TIMER_PAR_TIN0_GPIO (0x00) +#define MCF_GPIO_PAR_TIMER_PAR_TIN0_TOUT0 (0x02) +#define MCF_GPIO_PAR_TIMER_PAR_TIN0_DREQ0 (0x01) +#define MCF_GPIO_PAR_TIMER_PAR_TIN0_TIN0 (0x03) + +/* Bit definitions and macros for MCF_GPIO_PAR_LCDDATA */ +#define MCF_GPIO_PAR_LCDDATA_PAR_LD7_0(x) (((x)&0x03)<<0) +#define MCF_GPIO_PAR_LCDDATA_PAR_LD15_8(x) (((x)&0x03)<<2) +#define MCF_GPIO_PAR_LCDDATA_PAR_LD16(x) (((x)&0x03)<<4) +#define MCF_GPIO_PAR_LCDDATA_PAR_LD17(x) (((x)&0x03)<<6) + +/* Bit definitions and macros for MCF_GPIO_PAR_LCDCTL */ +#define MCF_GPIO_PAR_LCDCTL_PAR_CLS (0x0001) +#define MCF_GPIO_PAR_LCDCTL_PAR_PS (0x0002) +#define MCF_GPIO_PAR_LCDCTL_PAR_REV (0x0004) +#define MCF_GPIO_PAR_LCDCTL_PAR_SPL_SPR (0x0008) +#define MCF_GPIO_PAR_LCDCTL_PAR_CONTRAST (0x0010) +#define MCF_GPIO_PAR_LCDCTL_PAR_LSCLK (0x0020) +#define MCF_GPIO_PAR_LCDCTL_PAR_LP_HSYNC (0x0040) +#define MCF_GPIO_PAR_LCDCTL_PAR_FLM_VSYNC (0x0080) +#define MCF_GPIO_PAR_LCDCTL_PAR_ACD_OE (0x0100) + +/* Bit definitions and macros for MCF_GPIO_PAR_IRQ */ +#define MCF_GPIO_PAR_IRQ_PAR_IRQ1(x) (((x)&0x0003)<<4) +#define MCF_GPIO_PAR_IRQ_PAR_IRQ2(x) (((x)&0x0003)<<6) +#define MCF_GPIO_PAR_IRQ_PAR_IRQ4(x) (((x)&0x0003)<<8) +#define MCF_GPIO_PAR_IRQ_PAR_IRQ5(x) (((x)&0x0003)<<10) +#define MCF_GPIO_PAR_IRQ_PAR_IRQ6(x) (((x)&0x0003)<<12) + +/* Bit definitions and macros for MCF_GPIO_MSCR_FLEXBUS */ +#define MCF_GPIO_MSCR_FLEXBUS_MSCR_ADDRCTL(x) (((x)&0x03)<<0) +#define MCF_GPIO_MSCR_FLEXBUS_MSCR_DLOWER(x) (((x)&0x03)<<2) +#define MCF_GPIO_MSCR_FLEXBUS_MSCR_DUPPER(x) (((x)&0x03)<<4) + +/* Bit definitions and macros for MCF_GPIO_MSCR_SDRAM */ +#define MCF_GPIO_MSCR_SDRAM_MSCR_SDRAM(x) (((x)&0x03)<<0) +#define MCF_GPIO_MSCR_SDRAM_MSCR_SDCLK(x) (((x)&0x03)<<2) +#define MCF_GPIO_MSCR_SDRAM_MSCR_SDCLKB(x) (((x)&0x03)<<4) + +/* Bit definitions and macros for MCF_GPIO_DSCR_I2C */ +#define MCF_GPIO_DSCR_I2C_I2C_DSE(x) (((x)&0x03)<<0) + +/* Bit definitions and macros for MCF_GPIO_DSCR_PWM */ +#define MCF_GPIO_DSCR_PWM_PWM_DSE(x) (((x)&0x03)<<0) + +/* Bit definitions and macros for MCF_GPIO_DSCR_FEC */ +#define MCF_GPIO_DSCR_FEC_FEC_DSE(x) (((x)&0x03)<<0) + +/* Bit definitions and macros for MCF_GPIO_DSCR_UART */ +#define MCF_GPIO_DSCR_UART_UART0_DSE(x) (((x)&0x03)<<0) +#define MCF_GPIO_DSCR_UART_UART1_DSE(x) (((x)&0x03)<<2) + +/* Bit definitions and macros for MCF_GPIO_DSCR_QSPI */ +#define MCF_GPIO_DSCR_QSPI_QSPI_DSE(x) (((x)&0x03)<<0) + +/* Bit definitions and macros for MCF_GPIO_DSCR_TIMER */ +#define MCF_GPIO_DSCR_TIMER_TIMER_DSE(x) (((x)&0x03)<<0) + +/* Bit definitions and macros for MCF_GPIO_DSCR_SSI */ +#define MCF_GPIO_DSCR_SSI_SSI_DSE(x) (((x)&0x03)<<0) + +/* Bit definitions and macros for MCF_GPIO_DSCR_LCD */ +#define MCF_GPIO_DSCR_LCD_LCD_DSE(x) (((x)&0x03)<<0) + +/* Bit definitions and macros for MCF_GPIO_DSCR_DEBUG */ +#define MCF_GPIO_DSCR_DEBUG_DEBUG_DSE(x) (((x)&0x03)<<0) + +/* Bit definitions and macros for MCF_GPIO_DSCR_CLKRST */ +#define MCF_GPIO_DSCR_CLKRST_CLKRST_DSE(x) (((x)&0x03)<<0) + +/* Bit definitions and macros for MCF_GPIO_DSCR_IRQ */ +#define MCF_GPIO_DSCR_IRQ_IRQ_DSE(x) (((x)&0x03)<<0) + +/********************************************************************* + * + * Interrupt Controller (INTC) + * + *********************************************************************/ + +/* Register read/write macros */ +#define MCF_INTC0_IPRH MCF_REG32(0xFC048000) +#define MCF_INTC0_IPRL MCF_REG32(0xFC048004) +#define MCF_INTC0_IMRH MCF_REG32(0xFC048008) +#define MCF_INTC0_IMRL MCF_REG32(0xFC04800C) +#define MCF_INTC0_INTFRCH MCF_REG32(0xFC048010) +#define MCF_INTC0_INTFRCL MCF_REG32(0xFC048014) +#define MCF_INTC0_ICONFIG MCF_REG16(0xFC04801A) +#define MCF_INTC0_SIMR MCF_REG08(0xFC04801C) +#define MCF_INTC0_CIMR MCF_REG08(0xFC04801D) +#define MCF_INTC0_CLMASK MCF_REG08(0xFC04801E) +#define MCF_INTC0_SLMASK MCF_REG08(0xFC04801F) +#define MCF_INTC0_ICR0 MCF_REG08(0xFC048040) +#define MCF_INTC0_ICR1 MCF_REG08(0xFC048041) +#define MCF_INTC0_ICR2 MCF_REG08(0xFC048042) +#define MCF_INTC0_ICR3 MCF_REG08(0xFC048043) +#define MCF_INTC0_ICR4 MCF_REG08(0xFC048044) +#define MCF_INTC0_ICR5 MCF_REG08(0xFC048045) +#define MCF_INTC0_ICR6 MCF_REG08(0xFC048046) +#define MCF_INTC0_ICR7 MCF_REG08(0xFC048047) +#define MCF_INTC0_ICR8 MCF_REG08(0xFC048048) +#define MCF_INTC0_ICR9 MCF_REG08(0xFC048049) +#define MCF_INTC0_ICR10 MCF_REG08(0xFC04804A) +#define MCF_INTC0_ICR11 MCF_REG08(0xFC04804B) +#define MCF_INTC0_ICR12 MCF_REG08(0xFC04804C) +#define MCF_INTC0_ICR13 MCF_REG08(0xFC04804D) +#define MCF_INTC0_ICR14 MCF_REG08(0xFC04804E) +#define MCF_INTC0_ICR15 MCF_REG08(0xFC04804F) +#define MCF_INTC0_ICR16 MCF_REG08(0xFC048050) +#define MCF_INTC0_ICR17 MCF_REG08(0xFC048051) +#define MCF_INTC0_ICR18 MCF_REG08(0xFC048052) +#define MCF_INTC0_ICR19 MCF_REG08(0xFC048053) +#define MCF_INTC0_ICR20 MCF_REG08(0xFC048054) +#define MCF_INTC0_ICR21 MCF_REG08(0xFC048055) +#define MCF_INTC0_ICR22 MCF_REG08(0xFC048056) +#define MCF_INTC0_ICR23 MCF_REG08(0xFC048057) +#define MCF_INTC0_ICR24 MCF_REG08(0xFC048058) +#define MCF_INTC0_ICR25 MCF_REG08(0xFC048059) +#define MCF_INTC0_ICR26 MCF_REG08(0xFC04805A) +#define MCF_INTC0_ICR27 MCF_REG08(0xFC04805B) +#define MCF_INTC0_ICR28 MCF_REG08(0xFC04805C) +#define MCF_INTC0_ICR29 MCF_REG08(0xFC04805D) +#define MCF_INTC0_ICR30 MCF_REG08(0xFC04805E) +#define MCF_INTC0_ICR31 MCF_REG08(0xFC04805F) +#define MCF_INTC0_ICR32 MCF_REG08(0xFC048060) +#define MCF_INTC0_ICR33 MCF_REG08(0xFC048061) +#define MCF_INTC0_ICR34 MCF_REG08(0xFC048062) +#define MCF_INTC0_ICR35 MCF_REG08(0xFC048063) +#define MCF_INTC0_ICR36 MCF_REG08(0xFC048064) +#define MCF_INTC0_ICR37 MCF_REG08(0xFC048065) +#define MCF_INTC0_ICR38 MCF_REG08(0xFC048066) +#define MCF_INTC0_ICR39 MCF_REG08(0xFC048067) +#define MCF_INTC0_ICR40 MCF_REG08(0xFC048068) +#define MCF_INTC0_ICR41 MCF_REG08(0xFC048069) +#define MCF_INTC0_ICR42 MCF_REG08(0xFC04806A) +#define MCF_INTC0_ICR43 MCF_REG08(0xFC04806B) +#define MCF_INTC0_ICR44 MCF_REG08(0xFC04806C) +#define MCF_INTC0_ICR45 MCF_REG08(0xFC04806D) +#define MCF_INTC0_ICR46 MCF_REG08(0xFC04806E) +#define MCF_INTC0_ICR47 MCF_REG08(0xFC04806F) +#define MCF_INTC0_ICR48 MCF_REG08(0xFC048070) +#define MCF_INTC0_ICR49 MCF_REG08(0xFC048071) +#define MCF_INTC0_ICR50 MCF_REG08(0xFC048072) +#define MCF_INTC0_ICR51 MCF_REG08(0xFC048073) +#define MCF_INTC0_ICR52 MCF_REG08(0xFC048074) +#define MCF_INTC0_ICR53 MCF_REG08(0xFC048075) +#define MCF_INTC0_ICR54 MCF_REG08(0xFC048076) +#define MCF_INTC0_ICR55 MCF_REG08(0xFC048077) +#define MCF_INTC0_ICR56 MCF_REG08(0xFC048078) +#define MCF_INTC0_ICR57 MCF_REG08(0xFC048079) +#define MCF_INTC0_ICR58 MCF_REG08(0xFC04807A) +#define MCF_INTC0_ICR59 MCF_REG08(0xFC04807B) +#define MCF_INTC0_ICR60 MCF_REG08(0xFC04807C) +#define MCF_INTC0_ICR61 MCF_REG08(0xFC04807D) +#define MCF_INTC0_ICR62 MCF_REG08(0xFC04807E) +#define MCF_INTC0_ICR63 MCF_REG08(0xFC04807F) +#define MCF_INTC0_ICR(x) MCF_REG08(0xFC048040+((x)*0x001)) +#define MCF_INTC0_SWIACK MCF_REG08(0xFC0480E0) +#define MCF_INTC0_L1IACK MCF_REG08(0xFC0480E4) +#define MCF_INTC0_L2IACK MCF_REG08(0xFC0480E8) +#define MCF_INTC0_L3IACK MCF_REG08(0xFC0480EC) +#define MCF_INTC0_L4IACK MCF_REG08(0xFC0480F0) +#define MCF_INTC0_L5IACK MCF_REG08(0xFC0480F4) +#define MCF_INTC0_L6IACK MCF_REG08(0xFC0480F8) +#define MCF_INTC0_L7IACK MCF_REG08(0xFC0480FC) +#define MCF_INTC0_LIACK(x) MCF_REG08(0xFC0480E4+((x)*0x004)) +#define MCF_INTC1_IPRH MCF_REG32(0xFC04C000) +#define MCF_INTC1_IPRL MCF_REG32(0xFC04C004) +#define MCF_INTC1_IMRH MCF_REG32(0xFC04C008) +#define MCF_INTC1_IMRL MCF_REG32(0xFC04C00C) +#define MCF_INTC1_INTFRCH MCF_REG32(0xFC04C010) +#define MCF_INTC1_INTFRCL MCF_REG32(0xFC04C014) +#define MCF_INTC1_ICONFIG MCF_REG16(0xFC04C01A) +#define MCF_INTC1_SIMR MCF_REG08(0xFC04C01C) +#define MCF_INTC1_CIMR MCF_REG08(0xFC04C01D) +#define MCF_INTC1_CLMASK MCF_REG08(0xFC04C01E) +#define MCF_INTC1_SLMASK MCF_REG08(0xFC04C01F) +#define MCF_INTC1_ICR0 MCF_REG08(0xFC04C040) +#define MCF_INTC1_ICR1 MCF_REG08(0xFC04C041) +#define MCF_INTC1_ICR2 MCF_REG08(0xFC04C042) +#define MCF_INTC1_ICR3 MCF_REG08(0xFC04C043) +#define MCF_INTC1_ICR4 MCF_REG08(0xFC04C044) +#define MCF_INTC1_ICR5 MCF_REG08(0xFC04C045) +#define MCF_INTC1_ICR6 MCF_REG08(0xFC04C046) +#define MCF_INTC1_ICR7 MCF_REG08(0xFC04C047) +#define MCF_INTC1_ICR8 MCF_REG08(0xFC04C048) +#define MCF_INTC1_ICR9 MCF_REG08(0xFC04C049) +#define MCF_INTC1_ICR10 MCF_REG08(0xFC04C04A) +#define MCF_INTC1_ICR11 MCF_REG08(0xFC04C04B) +#define MCF_INTC1_ICR12 MCF_REG08(0xFC04C04C) +#define MCF_INTC1_ICR13 MCF_REG08(0xFC04C04D) +#define MCF_INTC1_ICR14 MCF_REG08(0xFC04C04E) +#define MCF_INTC1_ICR15 MCF_REG08(0xFC04C04F) +#define MCF_INTC1_ICR16 MCF_REG08(0xFC04C050) +#define MCF_INTC1_ICR17 MCF_REG08(0xFC04C051) +#define MCF_INTC1_ICR18 MCF_REG08(0xFC04C052) +#define MCF_INTC1_ICR19 MCF_REG08(0xFC04C053) +#define MCF_INTC1_ICR20 MCF_REG08(0xFC04C054) +#define MCF_INTC1_ICR21 MCF_REG08(0xFC04C055) +#define MCF_INTC1_ICR22 MCF_REG08(0xFC04C056) +#define MCF_INTC1_ICR23 MCF_REG08(0xFC04C057) +#define MCF_INTC1_ICR24 MCF_REG08(0xFC04C058) +#define MCF_INTC1_ICR25 MCF_REG08(0xFC04C059) +#define MCF_INTC1_ICR26 MCF_REG08(0xFC04C05A) +#define MCF_INTC1_ICR27 MCF_REG08(0xFC04C05B) +#define MCF_INTC1_ICR28 MCF_REG08(0xFC04C05C) +#define MCF_INTC1_ICR29 MCF_REG08(0xFC04C05D) +#define MCF_INTC1_ICR30 MCF_REG08(0xFC04C05E) +#define MCF_INTC1_ICR31 MCF_REG08(0xFC04C05F) +#define MCF_INTC1_ICR32 MCF_REG08(0xFC04C060) +#define MCF_INTC1_ICR33 MCF_REG08(0xFC04C061) +#define MCF_INTC1_ICR34 MCF_REG08(0xFC04C062) +#define MCF_INTC1_ICR35 MCF_REG08(0xFC04C063) +#define MCF_INTC1_ICR36 MCF_REG08(0xFC04C064) +#define MCF_INTC1_ICR37 MCF_REG08(0xFC04C065) +#define MCF_INTC1_ICR38 MCF_REG08(0xFC04C066) +#define MCF_INTC1_ICR39 MCF_REG08(0xFC04C067) +#define MCF_INTC1_ICR40 MCF_REG08(0xFC04C068) +#define MCF_INTC1_ICR41 MCF_REG08(0xFC04C069) +#define MCF_INTC1_ICR42 MCF_REG08(0xFC04C06A) +#define MCF_INTC1_ICR43 MCF_REG08(0xFC04C06B) +#define MCF_INTC1_ICR44 MCF_REG08(0xFC04C06C) +#define MCF_INTC1_ICR45 MCF_REG08(0xFC04C06D) +#define MCF_INTC1_ICR46 MCF_REG08(0xFC04C06E) +#define MCF_INTC1_ICR47 MCF_REG08(0xFC04C06F) +#define MCF_INTC1_ICR48 MCF_REG08(0xFC04C070) +#define MCF_INTC1_ICR49 MCF_REG08(0xFC04C071) +#define MCF_INTC1_ICR50 MCF_REG08(0xFC04C072) +#define MCF_INTC1_ICR51 MCF_REG08(0xFC04C073) +#define MCF_INTC1_ICR52 MCF_REG08(0xFC04C074) +#define MCF_INTC1_ICR53 MCF_REG08(0xFC04C075) +#define MCF_INTC1_ICR54 MCF_REG08(0xFC04C076) +#define MCF_INTC1_ICR55 MCF_REG08(0xFC04C077) +#define MCF_INTC1_ICR56 MCF_REG08(0xFC04C078) +#define MCF_INTC1_ICR57 MCF_REG08(0xFC04C079) +#define MCF_INTC1_ICR58 MCF_REG08(0xFC04C07A) +#define MCF_INTC1_ICR59 MCF_REG08(0xFC04C07B) +#define MCF_INTC1_ICR60 MCF_REG08(0xFC04C07C) +#define MCF_INTC1_ICR61 MCF_REG08(0xFC04C07D) +#define MCF_INTC1_ICR62 MCF_REG08(0xFC04C07E) +#define MCF_INTC1_ICR63 MCF_REG08(0xFC04C07F) +#define MCF_INTC1_ICR(x) MCF_REG08(0xFC04C040+((x)*0x001)) +#define MCF_INTC1_SWIACK MCF_REG08(0xFC04C0E0) +#define MCF_INTC1_L1IACK MCF_REG08(0xFC04C0E4) +#define MCF_INTC1_L2IACK MCF_REG08(0xFC04C0E8) +#define MCF_INTC1_L3IACK MCF_REG08(0xFC04C0EC) +#define MCF_INTC1_L4IACK MCF_REG08(0xFC04C0F0) +#define MCF_INTC1_L5IACK MCF_REG08(0xFC04C0F4) +#define MCF_INTC1_L6IACK MCF_REG08(0xFC04C0F8) +#define MCF_INTC1_L7IACK MCF_REG08(0xFC04C0FC) +#define MCF_INTC1_LIACK(x) MCF_REG08(0xFC04C0E4+((x)*0x004)) +#define MCF_INTC_IPRH(x) MCF_REG32(0xFC048000+((x)*0x4000)) +#define MCF_INTC_IPRL(x) MCF_REG32(0xFC048004+((x)*0x4000)) +#define MCF_INTC_IMRH(x) MCF_REG32(0xFC048008+((x)*0x4000)) +#define MCF_INTC_IMRL(x) MCF_REG32(0xFC04800C+((x)*0x4000)) +#define MCF_INTC_INTFRCH(x) MCF_REG32(0xFC048010+((x)*0x4000)) +#define MCF_INTC_INTFRCL(x) MCF_REG32(0xFC048014+((x)*0x4000)) +#define MCF_INTC_ICONFIG(x) MCF_REG16(0xFC04801A+((x)*0x4000)) +#define MCF_INTC_SIMR(x) MCF_REG08(0xFC04801C+((x)*0x4000)) +#define MCF_INTC_CIMR(x) MCF_REG08(0xFC04801D+((x)*0x4000)) +#define MCF_INTC_CLMASK(x) MCF_REG08(0xFC04801E+((x)*0x4000)) +#define MCF_INTC_SLMASK(x) MCF_REG08(0xFC04801F+((x)*0x4000)) +#define MCF_INTC_ICR0(x) MCF_REG08(0xFC048040+((x)*0x4000)) +#define MCF_INTC_ICR1(x) MCF_REG08(0xFC048041+((x)*0x4000)) +#define MCF_INTC_ICR2(x) MCF_REG08(0xFC048042+((x)*0x4000)) +#define MCF_INTC_ICR3(x) MCF_REG08(0xFC048043+((x)*0x4000)) +#define MCF_INTC_ICR4(x) MCF_REG08(0xFC048044+((x)*0x4000)) +#define MCF_INTC_ICR5(x) MCF_REG08(0xFC048045+((x)*0x4000)) +#define MCF_INTC_ICR6(x) MCF_REG08(0xFC048046+((x)*0x4000)) +#define MCF_INTC_ICR7(x) MCF_REG08(0xFC048047+((x)*0x4000)) +#define MCF_INTC_ICR8(x) MCF_REG08(0xFC048048+((x)*0x4000)) +#define MCF_INTC_ICR9(x) MCF_REG08(0xFC048049+((x)*0x4000)) +#define MCF_INTC_ICR10(x) MCF_REG08(0xFC04804A+((x)*0x4000)) +#define MCF_INTC_ICR11(x) MCF_REG08(0xFC04804B+((x)*0x4000)) +#define MCF_INTC_ICR12(x) MCF_REG08(0xFC04804C+((x)*0x4000)) +#define MCF_INTC_ICR13(x) MCF_REG08(0xFC04804D+((x)*0x4000)) +#define MCF_INTC_ICR14(x) MCF_REG08(0xFC04804E+((x)*0x4000)) +#define MCF_INTC_ICR15(x) MCF_REG08(0xFC04804F+((x)*0x4000)) +#define MCF_INTC_ICR16(x) MCF_REG08(0xFC048050+((x)*0x4000)) +#define MCF_INTC_ICR17(x) MCF_REG08(0xFC048051+((x)*0x4000)) +#define MCF_INTC_ICR18(x) MCF_REG08(0xFC048052+((x)*0x4000)) +#define MCF_INTC_ICR19(x) MCF_REG08(0xFC048053+((x)*0x4000)) +#define MCF_INTC_ICR20(x) MCF_REG08(0xFC048054+((x)*0x4000)) +#define MCF_INTC_ICR21(x) MCF_REG08(0xFC048055+((x)*0x4000)) +#define MCF_INTC_ICR22(x) MCF_REG08(0xFC048056+((x)*0x4000)) +#define MCF_INTC_ICR23(x) MCF_REG08(0xFC048057+((x)*0x4000)) +#define MCF_INTC_ICR24(x) MCF_REG08(0xFC048058+((x)*0x4000)) +#define MCF_INTC_ICR25(x) MCF_REG08(0xFC048059+((x)*0x4000)) +#define MCF_INTC_ICR26(x) MCF_REG08(0xFC04805A+((x)*0x4000)) +#define MCF_INTC_ICR27(x) MCF_REG08(0xFC04805B+((x)*0x4000)) +#define MCF_INTC_ICR28(x) MCF_REG08(0xFC04805C+((x)*0x4000)) +#define MCF_INTC_ICR29(x) MCF_REG08(0xFC04805D+((x)*0x4000)) +#define MCF_INTC_ICR30(x) MCF_REG08(0xFC04805E+((x)*0x4000)) +#define MCF_INTC_ICR31(x) MCF_REG08(0xFC04805F+((x)*0x4000)) +#define MCF_INTC_ICR32(x) MCF_REG08(0xFC048060+((x)*0x4000)) +#define MCF_INTC_ICR33(x) MCF_REG08(0xFC048061+((x)*0x4000)) +#define MCF_INTC_ICR34(x) MCF_REG08(0xFC048062+((x)*0x4000)) +#define MCF_INTC_ICR35(x) MCF_REG08(0xFC048063+((x)*0x4000)) +#define MCF_INTC_ICR36(x) MCF_REG08(0xFC048064+((x)*0x4000)) +#define MCF_INTC_ICR37(x) MCF_REG08(0xFC048065+((x)*0x4000)) +#define MCF_INTC_ICR38(x) MCF_REG08(0xFC048066+((x)*0x4000)) +#define MCF_INTC_ICR39(x) MCF_REG08(0xFC048067+((x)*0x4000)) +#define MCF_INTC_ICR40(x) MCF_REG08(0xFC048068+((x)*0x4000)) +#define MCF_INTC_ICR41(x) MCF_REG08(0xFC048069+((x)*0x4000)) +#define MCF_INTC_ICR42(x) MCF_REG08(0xFC04806A+((x)*0x4000)) +#define MCF_INTC_ICR43(x) MCF_REG08(0xFC04806B+((x)*0x4000)) +#define MCF_INTC_ICR44(x) MCF_REG08(0xFC04806C+((x)*0x4000)) +#define MCF_INTC_ICR45(x) MCF_REG08(0xFC04806D+((x)*0x4000)) +#define MCF_INTC_ICR46(x) MCF_REG08(0xFC04806E+((x)*0x4000)) +#define MCF_INTC_ICR47(x) MCF_REG08(0xFC04806F+((x)*0x4000)) +#define MCF_INTC_ICR48(x) MCF_REG08(0xFC048070+((x)*0x4000)) +#define MCF_INTC_ICR49(x) MCF_REG08(0xFC048071+((x)*0x4000)) +#define MCF_INTC_ICR50(x) MCF_REG08(0xFC048072+((x)*0x4000)) +#define MCF_INTC_ICR51(x) MCF_REG08(0xFC048073+((x)*0x4000)) +#define MCF_INTC_ICR52(x) MCF_REG08(0xFC048074+((x)*0x4000)) +#define MCF_INTC_ICR53(x) MCF_REG08(0xFC048075+((x)*0x4000)) +#define MCF_INTC_ICR54(x) MCF_REG08(0xFC048076+((x)*0x4000)) +#define MCF_INTC_ICR55(x) MCF_REG08(0xFC048077+((x)*0x4000)) +#define MCF_INTC_ICR56(x) MCF_REG08(0xFC048078+((x)*0x4000)) +#define MCF_INTC_ICR57(x) MCF_REG08(0xFC048079+((x)*0x4000)) +#define MCF_INTC_ICR58(x) MCF_REG08(0xFC04807A+((x)*0x4000)) +#define MCF_INTC_ICR59(x) MCF_REG08(0xFC04807B+((x)*0x4000)) +#define MCF_INTC_ICR60(x) MCF_REG08(0xFC04807C+((x)*0x4000)) +#define MCF_INTC_ICR61(x) MCF_REG08(0xFC04807D+((x)*0x4000)) +#define MCF_INTC_ICR62(x) MCF_REG08(0xFC04807E+((x)*0x4000)) +#define MCF_INTC_ICR63(x) MCF_REG08(0xFC04807F+((x)*0x4000)) +#define MCF_INTC_SWIACK(x) MCF_REG08(0xFC0480E0+((x)*0x4000)) +#define MCF_INTC_L1IACK(x) MCF_REG08(0xFC0480E4+((x)*0x4000)) +#define MCF_INTC_L2IACK(x) MCF_REG08(0xFC0480E8+((x)*0x4000)) +#define MCF_INTC_L3IACK(x) MCF_REG08(0xFC0480EC+((x)*0x4000)) +#define MCF_INTC_L4IACK(x) MCF_REG08(0xFC0480F0+((x)*0x4000)) +#define MCF_INTC_L5IACK(x) MCF_REG08(0xFC0480F4+((x)*0x4000)) +#define MCF_INTC_L6IACK(x) MCF_REG08(0xFC0480F8+((x)*0x4000)) +#define MCF_INTC_L7IACK(x) MCF_REG08(0xFC0480FC+((x)*0x4000)) + +/* Bit definitions and macros for MCF_INTC_IPRH */ +#define MCF_INTC_IPRH_INT32 (0x00000001) +#define MCF_INTC_IPRH_INT33 (0x00000002) +#define MCF_INTC_IPRH_INT34 (0x00000004) +#define MCF_INTC_IPRH_INT35 (0x00000008) +#define MCF_INTC_IPRH_INT36 (0x00000010) +#define MCF_INTC_IPRH_INT37 (0x00000020) +#define MCF_INTC_IPRH_INT38 (0x00000040) +#define MCF_INTC_IPRH_INT39 (0x00000080) +#define MCF_INTC_IPRH_INT40 (0x00000100) +#define MCF_INTC_IPRH_INT41 (0x00000200) +#define MCF_INTC_IPRH_INT42 (0x00000400) +#define MCF_INTC_IPRH_INT43 (0x00000800) +#define MCF_INTC_IPRH_INT44 (0x00001000) +#define MCF_INTC_IPRH_INT45 (0x00002000) +#define MCF_INTC_IPRH_INT46 (0x00004000) +#define MCF_INTC_IPRH_INT47 (0x00008000) +#define MCF_INTC_IPRH_INT48 (0x00010000) +#define MCF_INTC_IPRH_INT49 (0x00020000) +#define MCF_INTC_IPRH_INT50 (0x00040000) +#define MCF_INTC_IPRH_INT51 (0x00080000) +#define MCF_INTC_IPRH_INT52 (0x00100000) +#define MCF_INTC_IPRH_INT53 (0x00200000) +#define MCF_INTC_IPRH_INT54 (0x00400000) +#define MCF_INTC_IPRH_INT55 (0x00800000) +#define MCF_INTC_IPRH_INT56 (0x01000000) +#define MCF_INTC_IPRH_INT57 (0x02000000) +#define MCF_INTC_IPRH_INT58 (0x04000000) +#define MCF_INTC_IPRH_INT59 (0x08000000) +#define MCF_INTC_IPRH_INT60 (0x10000000) +#define MCF_INTC_IPRH_INT61 (0x20000000) +#define MCF_INTC_IPRH_INT62 (0x40000000) +#define MCF_INTC_IPRH_INT63 (0x80000000) + +/* Bit definitions and macros for MCF_INTC_IPRL */ +#define MCF_INTC_IPRL_INT0 (0x00000001) +#define MCF_INTC_IPRL_INT1 (0x00000002) +#define MCF_INTC_IPRL_INT2 (0x00000004) +#define MCF_INTC_IPRL_INT3 (0x00000008) +#define MCF_INTC_IPRL_INT4 (0x00000010) +#define MCF_INTC_IPRL_INT5 (0x00000020) +#define MCF_INTC_IPRL_INT6 (0x00000040) +#define MCF_INTC_IPRL_INT7 (0x00000080) +#define MCF_INTC_IPRL_INT8 (0x00000100) +#define MCF_INTC_IPRL_INT9 (0x00000200) +#define MCF_INTC_IPRL_INT10 (0x00000400) +#define MCF_INTC_IPRL_INT11 (0x00000800) +#define MCF_INTC_IPRL_INT12 (0x00001000) +#define MCF_INTC_IPRL_INT13 (0x00002000) +#define MCF_INTC_IPRL_INT14 (0x00004000) +#define MCF_INTC_IPRL_INT15 (0x00008000) +#define MCF_INTC_IPRL_INT16 (0x00010000) +#define MCF_INTC_IPRL_INT17 (0x00020000) +#define MCF_INTC_IPRL_INT18 (0x00040000) +#define MCF_INTC_IPRL_INT19 (0x00080000) +#define MCF_INTC_IPRL_INT20 (0x00100000) +#define MCF_INTC_IPRL_INT21 (0x00200000) +#define MCF_INTC_IPRL_INT22 (0x00400000) +#define MCF_INTC_IPRL_INT23 (0x00800000) +#define MCF_INTC_IPRL_INT24 (0x01000000) +#define MCF_INTC_IPRL_INT25 (0x02000000) +#define MCF_INTC_IPRL_INT26 (0x04000000) +#define MCF_INTC_IPRL_INT27 (0x08000000) +#define MCF_INTC_IPRL_INT28 (0x10000000) +#define MCF_INTC_IPRL_INT29 (0x20000000) +#define MCF_INTC_IPRL_INT30 (0x40000000) +#define MCF_INTC_IPRL_INT31 (0x80000000) + +/* Bit definitions and macros for MCF_INTC_IMRH */ +#define MCF_INTC_IMRH_INT_MASK32 (0x00000001) +#define MCF_INTC_IMRH_INT_MASK33 (0x00000002) +#define MCF_INTC_IMRH_INT_MASK34 (0x00000004) +#define MCF_INTC_IMRH_INT_MASK35 (0x00000008) +#define MCF_INTC_IMRH_INT_MASK36 (0x00000010) +#define MCF_INTC_IMRH_INT_MASK37 (0x00000020) +#define MCF_INTC_IMRH_INT_MASK38 (0x00000040) +#define MCF_INTC_IMRH_INT_MASK39 (0x00000080) +#define MCF_INTC_IMRH_INT_MASK40 (0x00000100) +#define MCF_INTC_IMRH_INT_MASK41 (0x00000200) +#define MCF_INTC_IMRH_INT_MASK42 (0x00000400) +#define MCF_INTC_IMRH_INT_MASK43 (0x00000800) +#define MCF_INTC_IMRH_INT_MASK44 (0x00001000) +#define MCF_INTC_IMRH_INT_MASK45 (0x00002000) +#define MCF_INTC_IMRH_INT_MASK46 (0x00004000) +#define MCF_INTC_IMRH_INT_MASK47 (0x00008000) +#define MCF_INTC_IMRH_INT_MASK48 (0x00010000) +#define MCF_INTC_IMRH_INT_MASK49 (0x00020000) +#define MCF_INTC_IMRH_INT_MASK50 (0x00040000) +#define MCF_INTC_IMRH_INT_MASK51 (0x00080000) +#define MCF_INTC_IMRH_INT_MASK52 (0x00100000) +#define MCF_INTC_IMRH_INT_MASK53 (0x00200000) +#define MCF_INTC_IMRH_INT_MASK54 (0x00400000) +#define MCF_INTC_IMRH_INT_MASK55 (0x00800000) +#define MCF_INTC_IMRH_INT_MASK56 (0x01000000) +#define MCF_INTC_IMRH_INT_MASK57 (0x02000000) +#define MCF_INTC_IMRH_INT_MASK58 (0x04000000) +#define MCF_INTC_IMRH_INT_MASK59 (0x08000000) +#define MCF_INTC_IMRH_INT_MASK60 (0x10000000) +#define MCF_INTC_IMRH_INT_MASK61 (0x20000000) +#define MCF_INTC_IMRH_INT_MASK62 (0x40000000) +#define MCF_INTC_IMRH_INT_MASK63 (0x80000000) + +/* Bit definitions and macros for MCF_INTC_IMRL */ +#define MCF_INTC_IMRL_INT_MASK0 (0x00000001) +#define MCF_INTC_IMRL_INT_MASK1 (0x00000002) +#define MCF_INTC_IMRL_INT_MASK2 (0x00000004) +#define MCF_INTC_IMRL_INT_MASK3 (0x00000008) +#define MCF_INTC_IMRL_INT_MASK4 (0x00000010) +#define MCF_INTC_IMRL_INT_MASK5 (0x00000020) +#define MCF_INTC_IMRL_INT_MASK6 (0x00000040) +#define MCF_INTC_IMRL_INT_MASK7 (0x00000080) +#define MCF_INTC_IMRL_INT_MASK8 (0x00000100) +#define MCF_INTC_IMRL_INT_MASK9 (0x00000200) +#define MCF_INTC_IMRL_INT_MASK10 (0x00000400) +#define MCF_INTC_IMRL_INT_MASK11 (0x00000800) +#define MCF_INTC_IMRL_INT_MASK12 (0x00001000) +#define MCF_INTC_IMRL_INT_MASK13 (0x00002000) +#define MCF_INTC_IMRL_INT_MASK14 (0x00004000) +#define MCF_INTC_IMRL_INT_MASK15 (0x00008000) +#define MCF_INTC_IMRL_INT_MASK16 (0x00010000) +#define MCF_INTC_IMRL_INT_MASK17 (0x00020000) +#define MCF_INTC_IMRL_INT_MASK18 (0x00040000) +#define MCF_INTC_IMRL_INT_MASK19 (0x00080000) +#define MCF_INTC_IMRL_INT_MASK20 (0x00100000) +#define MCF_INTC_IMRL_INT_MASK21 (0x00200000) +#define MCF_INTC_IMRL_INT_MASK22 (0x00400000) +#define MCF_INTC_IMRL_INT_MASK23 (0x00800000) +#define MCF_INTC_IMRL_INT_MASK24 (0x01000000) +#define MCF_INTC_IMRL_INT_MASK25 (0x02000000) +#define MCF_INTC_IMRL_INT_MASK26 (0x04000000) +#define MCF_INTC_IMRL_INT_MASK27 (0x08000000) +#define MCF_INTC_IMRL_INT_MASK28 (0x10000000) +#define MCF_INTC_IMRL_INT_MASK29 (0x20000000) +#define MCF_INTC_IMRL_INT_MASK30 (0x40000000) +#define MCF_INTC_IMRL_INT_MASK31 (0x80000000) + +/* Bit definitions and macros for MCF_INTC_INTFRCH */ +#define MCF_INTC_INTFRCH_INTFRC32 (0x00000001) +#define MCF_INTC_INTFRCH_INTFRC33 (0x00000002) +#define MCF_INTC_INTFRCH_INTFRC34 (0x00000004) +#define MCF_INTC_INTFRCH_INTFRC35 (0x00000008) +#define MCF_INTC_INTFRCH_INTFRC36 (0x00000010) +#define MCF_INTC_INTFRCH_INTFRC37 (0x00000020) +#define MCF_INTC_INTFRCH_INTFRC38 (0x00000040) +#define MCF_INTC_INTFRCH_INTFRC39 (0x00000080) +#define MCF_INTC_INTFRCH_INTFRC40 (0x00000100) +#define MCF_INTC_INTFRCH_INTFRC41 (0x00000200) +#define MCF_INTC_INTFRCH_INTFRC42 (0x00000400) +#define MCF_INTC_INTFRCH_INTFRC43 (0x00000800) +#define MCF_INTC_INTFRCH_INTFRC44 (0x00001000) +#define MCF_INTC_INTFRCH_INTFRC45 (0x00002000) +#define MCF_INTC_INTFRCH_INTFRC46 (0x00004000) +#define MCF_INTC_INTFRCH_INTFRC47 (0x00008000) +#define MCF_INTC_INTFRCH_INTFRC48 (0x00010000) +#define MCF_INTC_INTFRCH_INTFRC49 (0x00020000) +#define MCF_INTC_INTFRCH_INTFRC50 (0x00040000) +#define MCF_INTC_INTFRCH_INTFRC51 (0x00080000) +#define MCF_INTC_INTFRCH_INTFRC52 (0x00100000) +#define MCF_INTC_INTFRCH_INTFRC53 (0x00200000) +#define MCF_INTC_INTFRCH_INTFRC54 (0x00400000) +#define MCF_INTC_INTFRCH_INTFRC55 (0x00800000) +#define MCF_INTC_INTFRCH_INTFRC56 (0x01000000) +#define MCF_INTC_INTFRCH_INTFRC57 (0x02000000) +#define MCF_INTC_INTFRCH_INTFRC58 (0x04000000) +#define MCF_INTC_INTFRCH_INTFRC59 (0x08000000) +#define MCF_INTC_INTFRCH_INTFRC60 (0x10000000) +#define MCF_INTC_INTFRCH_INTFRC61 (0x20000000) +#define MCF_INTC_INTFRCH_INTFRC62 (0x40000000) +#define MCF_INTC_INTFRCH_INTFRC63 (0x80000000) + +/* Bit definitions and macros for MCF_INTC_INTFRCL */ +#define MCF_INTC_INTFRCL_INTFRC0 (0x00000001) +#define MCF_INTC_INTFRCL_INTFRC1 (0x00000002) +#define MCF_INTC_INTFRCL_INTFRC2 (0x00000004) +#define MCF_INTC_INTFRCL_INTFRC3 (0x00000008) +#define MCF_INTC_INTFRCL_INTFRC4 (0x00000010) +#define MCF_INTC_INTFRCL_INTFRC5 (0x00000020) +#define MCF_INTC_INTFRCL_INTFRC6 (0x00000040) +#define MCF_INTC_INTFRCL_INTFRC7 (0x00000080) +#define MCF_INTC_INTFRCL_INTFRC8 (0x00000100) +#define MCF_INTC_INTFRCL_INTFRC9 (0x00000200) +#define MCF_INTC_INTFRCL_INTFRC10 (0x00000400) +#define MCF_INTC_INTFRCL_INTFRC11 (0x00000800) +#define MCF_INTC_INTFRCL_INTFRC12 (0x00001000) +#define MCF_INTC_INTFRCL_INTFRC13 (0x00002000) +#define MCF_INTC_INTFRCL_INTFRC14 (0x00004000) +#define MCF_INTC_INTFRCL_INTFRC15 (0x00008000) +#define MCF_INTC_INTFRCL_INTFRC16 (0x00010000) +#define MCF_INTC_INTFRCL_INTFRC17 (0x00020000) +#define MCF_INTC_INTFRCL_INTFRC18 (0x00040000) +#define MCF_INTC_INTFRCL_INTFRC19 (0x00080000) +#define MCF_INTC_INTFRCL_INTFRC20 (0x00100000) +#define MCF_INTC_INTFRCL_INTFRC21 (0x00200000) +#define MCF_INTC_INTFRCL_INTFRC22 (0x00400000) +#define MCF_INTC_INTFRCL_INTFRC23 (0x00800000) +#define MCF_INTC_INTFRCL_INTFRC24 (0x01000000) +#define MCF_INTC_INTFRCL_INTFRC25 (0x02000000) +#define MCF_INTC_INTFRCL_INTFRC26 (0x04000000) +#define MCF_INTC_INTFRCL_INTFRC27 (0x08000000) +#define MCF_INTC_INTFRCL_INTFRC28 (0x10000000) +#define MCF_INTC_INTFRCL_INTFRC29 (0x20000000) +#define MCF_INTC_INTFRCL_INTFRC30 (0x40000000) +#define MCF_INTC_INTFRCL_INTFRC31 (0x80000000) + +/* Bit definitions and macros for MCF_INTC_ICONFIG */ +#define MCF_INTC_ICONFIG_EMASK (0x0020) +#define MCF_INTC_ICONFIG_ELVLPRI1 (0x0200) +#define MCF_INTC_ICONFIG_ELVLPRI2 (0x0400) +#define MCF_INTC_ICONFIG_ELVLPRI3 (0x0800) +#define MCF_INTC_ICONFIG_ELVLPRI4 (0x1000) +#define MCF_INTC_ICONFIG_ELVLPRI5 (0x2000) +#define MCF_INTC_ICONFIG_ELVLPRI6 (0x4000) +#define MCF_INTC_ICONFIG_ELVLPRI7 (0x8000) + +/* Bit definitions and macros for MCF_INTC_SIMR */ +#define MCF_INTC_SIMR_SIMR(x) (((x)&0x7F)<<0) + +/* Bit definitions and macros for MCF_INTC_CIMR */ +#define MCF_INTC_CIMR_CIMR(x) (((x)&0x7F)<<0) + +/* Bit definitions and macros for MCF_INTC_CLMASK */ +#define MCF_INTC_CLMASK_CLMASK(x) (((x)&0x0F)<<0) + +/* Bit definitions and macros for MCF_INTC_SLMASK */ +#define MCF_INTC_SLMASK_SLMASK(x) (((x)&0x0F)<<0) + +/* Bit definitions and macros for MCF_INTC_ICR */ +#define MCF_INTC_ICR_IL(x) (((x)&0x07)<<0) + +/* Bit definitions and macros for MCF_INTC_SWIACK */ +#define MCF_INTC_SWIACK_VECTOR(x) (((x)&0xFF)<<0) + +/* Bit definitions and macros for MCF_INTC_LIACK */ +#define MCF_INTC_LIACK_VECTOR(x) (((x)&0xFF)<<0) + +/********************************************************************/ +/********************************************************************* +* +* LCD Controller (LCDC) +* +*********************************************************************/ + +/* Register read/write macros */ +#define MCF_LCDC_LSSAR MCF_REG32(0xFC0AC000) +#define MCF_LCDC_LSR MCF_REG32(0xFC0AC004) +#define MCF_LCDC_LVPWR MCF_REG32(0xFC0AC008) +#define MCF_LCDC_LCPR MCF_REG32(0xFC0AC00C) +#define MCF_LCDC_LCWHBR MCF_REG32(0xFC0AC010) +#define MCF_LCDC_LCCMR MCF_REG32(0xFC0AC014) +#define MCF_LCDC_LPCR MCF_REG32(0xFC0AC018) +#define MCF_LCDC_LHCR MCF_REG32(0xFC0AC01C) +#define MCF_LCDC_LVCR MCF_REG32(0xFC0AC020) +#define MCF_LCDC_LPOR MCF_REG32(0xFC0AC024) +#define MCF_LCDC_LSCR MCF_REG32(0xFC0AC028) +#define MCF_LCDC_LPCCR MCF_REG32(0xFC0AC02C) +#define MCF_LCDC_LDCR MCF_REG32(0xFC0AC030) +#define MCF_LCDC_LRMCR MCF_REG32(0xFC0AC034) +#define MCF_LCDC_LICR MCF_REG32(0xFC0AC038) +#define MCF_LCDC_LIER MCF_REG32(0xFC0AC03C) +#define MCF_LCDC_LISR MCF_REG32(0xFC0AC040) +#define MCF_LCDC_LGWSAR MCF_REG32(0xFC0AC050) +#define MCF_LCDC_LGWSR MCF_REG32(0xFC0AC054) +#define MCF_LCDC_LGWVPWR MCF_REG32(0xFC0AC058) +#define MCF_LCDC_LGWPOR MCF_REG32(0xFC0AC05C) +#define MCF_LCDC_LGWPR MCF_REG32(0xFC0AC060) +#define MCF_LCDC_LGWCR MCF_REG32(0xFC0AC064) +#define MCF_LCDC_LGWDCR MCF_REG32(0xFC0AC068) +#define MCF_LCDC_BPLUT_BASE MCF_REG32(0xFC0AC800) +#define MCF_LCDC_GWLUT_BASE MCF_REG32(0xFC0ACC00) + +/* Bit definitions and macros for MCF_LCDC_LSSAR */ +#define MCF_LCDC_LSSAR_SSA(x) (((x)&0x3FFFFFFF)<<2) + +/* Bit definitions and macros for MCF_LCDC_LSR */ +#define MCF_LCDC_LSR_YMAX(x) (((x)&0x000003FF)<<0) +#define MCF_LCDC_LSR_XMAX(x) (((x)&0x0000003F)<<20) + +/* Bit definitions and macros for MCF_LCDC_LVPWR */ +#define MCF_LCDC_LVPWR_VPW(x) (((x)&0x000003FF)<<0) + +/* Bit definitions and macros for MCF_LCDC_LCPR */ +#define MCF_LCDC_LCPR_CYP(x) (((x)&0x000003FF)<<0) +#define MCF_LCDC_LCPR_CXP(x) (((x)&0x000003FF)<<16) +#define MCF_LCDC_LCPR_OP (0x10000000) +#define MCF_LCDC_LCPR_CC(x) (((x)&0x00000003)<<30) +#define MCF_LCDC_LCPR_CC_TRANSPARENT (0x00000000) +#define MCF_LCDC_LCPR_CC_OR (0x40000000) +#define MCF_LCDC_LCPR_CC_XOR (0x80000000) +#define MCF_LCDC_LCPR_CC_AND (0xC0000000) +#define MCF_LCDC_LCPR_OP_ON (0x10000000) +#define MCF_LCDC_LCPR_OP_OFF (0x00000000) + +/* Bit definitions and macros for MCF_LCDC_LCWHBR */ +#define MCF_LCDC_LCWHBR_BD(x) (((x)&0x000000FF)<<0) +#define MCF_LCDC_LCWHBR_CH(x) (((x)&0x0000001F)<<16) +#define MCF_LCDC_LCWHBR_CW(x) (((x)&0x0000001F)<<24) +#define MCF_LCDC_LCWHBR_BK_EN (0x80000000) +#define MCF_LCDC_LCWHBR_BK_EN_ON (0x80000000) +#define MCF_LCDC_LCWHBR_BK_EN_OFF (0x00000000) + +/* Bit definitions and macros for MCF_LCDC_LCCMR */ +#define MCF_LCDC_LCCMR_CUR_COL_B(x) (((x)&0x0000003F)<<0) +#define MCF_LCDC_LCCMR_CUR_COL_G(x) (((x)&0x0000003F)<<6) +#define MCF_LCDC_LCCMR_CUR_COL_R(x) (((x)&0x0000003F)<<12) + +/* Bit definitions and macros for MCF_LCDC_LPCR */ +#define MCF_LCDC_LPCR_PCD(x) (((x)&0x0000003F)<<0) +#define MCF_LCDC_LPCR_SHARP (0x00000040) +#define MCF_LCDC_LPCR_SCLKSEL (0x00000080) +#define MCF_LCDC_LPCR_ACD(x) (((x)&0x0000007F)<<8) +#define MCF_LCDC_LPCR_ACDSEL (0x00008000) +#define MCF_LCDC_LPCR_REV_VS (0x00010000) +#define MCF_LCDC_LPCR_SWAP_SEL (0x00020000) +#define MCF_LCDC_LPCR_ENDSEL (0x00040000) +#define MCF_LCDC_LPCR_SCLKIDLE (0x00080000) +#define MCF_LCDC_LPCR_OEPOL (0x00100000) +#define MCF_LCDC_LPCR_CLKPOL (0x00200000) +#define MCF_LCDC_LPCR_LPPOL (0x00400000) +#define MCF_LCDC_LPCR_FLM (0x00800000) +#define MCF_LCDC_LPCR_PIXPOL (0x01000000) +#define MCF_LCDC_LPCR_BPIX(x) (((x)&0x00000007)<<25) +#define MCF_LCDC_LPCR_PBSIZ(x) (((x)&0x00000003)<<28) +#define MCF_LCDC_LPCR_COLOR (0x40000000) +#define MCF_LCDC_LPCR_TFT (0x80000000) +#define MCF_LCDC_LPCR_MODE_MONOCGROME (0x00000000) +#define MCF_LCDC_LPCR_MODE_CSTN (0x40000000) +#define MCF_LCDC_LPCR_MODE_TFT (0xC0000000) +#define MCF_LCDC_LPCR_PBSIZ_1 (0x00000000) +#define MCF_LCDC_LPCR_PBSIZ_2 (0x10000000) +#define MCF_LCDC_LPCR_PBSIZ_4 (0x20000000) +#define MCF_LCDC_LPCR_PBSIZ_8 (0x30000000) +#define MCF_LCDC_LPCR_BPIX_1bpp (0x00000000) +#define MCF_LCDC_LPCR_BPIX_2bpp (0x02000000) +#define MCF_LCDC_LPCR_BPIX_4bpp (0x04000000) +#define MCF_LCDC_LPCR_BPIX_8bpp (0x06000000) +#define MCF_LCDC_LPCR_BPIX_12bpp (0x08000000) +#define MCF_LCDC_LPCR_BPIX_16bpp (0x0A000000) +#define MCF_LCDC_LPCR_BPIX_18bpp (0x0C000000) + +#define MCF_LCDC_LPCR_PANEL_TYPE(x) (((x)&0x00000003)<<30) + +/* Bit definitions and macros for MCF_LCDC_LHCR */ +#define MCF_LCDC_LHCR_H_WAIT_2(x) (((x)&0x000000FF)<<0) +#define MCF_LCDC_LHCR_H_WAIT_1(x) (((x)&0x000000FF)<<8) +#define MCF_LCDC_LHCR_H_WIDTH(x) (((x)&0x0000003F)<<26) + +/* Bit definitions and macros for MCF_LCDC_LVCR */ +#define MCF_LCDC_LVCR_V_WAIT_2(x) (((x)&0x000000FF)<<0) +#define MCF_LCDC_LVCR_V_WAIT_1(x) (((x)&0x000000FF)<<8) +#define MCF_LCDC_LVCR_V_WIDTH(x) (((x)&0x0000003F)<<26) + +/* Bit definitions and macros for MCF_LCDC_LPOR */ +#define MCF_LCDC_LPOR_POS(x) (((x)&0x0000001F)<<0) + +/* Bit definitions and macros for MCF_LCDC_LPCCR */ +#define MCF_LCDC_LPCCR_PW(x) (((x)&0x000000FF)<<0) +#define MCF_LCDC_LPCCR_CC_EN (0x00000100) +#define MCF_LCDC_LPCCR_SCR(x) (((x)&0x00000003)<<9) +#define MCF_LCDC_LPCCR_LDMSK (0x00008000) +#define MCF_LCDC_LPCCR_CLS_HI_WIDTH(x) (((x)&0x000001FF)<<16) +#define MCF_LCDC_LPCCR_SCR_LINEPULSE (0x00000000) +#define MCF_LCDC_LPCCR_SCR_PIXELCLK (0x00002000) +#define MCF_LCDC_LPCCR_SCR_LCDCLOCK (0x00004000) + +/* Bit definitions and macros for MCF_LCDC_LDCR */ +#define MCF_LCDC_LDCR_TM(x) (((x)&0x0000001F)<<0) +#define MCF_LCDC_LDCR_HM(x) (((x)&0x0000001F)<<16) +#define MCF_LCDC_LDCR_BURST (0x80000000) + +/* Bit definitions and macros for MCF_LCDC_LRMCR */ +#define MCF_LCDC_LRMCR_SEL_REF (0x00000001) + +/* Bit definitions and macros for MCF_LCDC_LICR */ +#define MCF_LCDC_LICR_INTCON (0x00000001) +#define MCF_LCDC_LICR_INTSYN (0x00000004) +#define MCF_LCDC_LICR_GW_INT_CON (0x00000010) + +/* Bit definitions and macros for MCF_LCDC_LIER */ +#define MCF_LCDC_LIER_BOF_EN (0x00000001) +#define MCF_LCDC_LIER_EOF_EN (0x00000002) +#define MCF_LCDC_LIER_ERR_RES_EN (0x00000004) +#define MCF_LCDC_LIER_UDR_ERR_EN (0x00000008) +#define MCF_LCDC_LIER_GW_BOF_EN (0x00000010) +#define MCF_LCDC_LIER_GW_EOF_EN (0x00000020) +#define MCF_LCDC_LIER_GW_ERR_RES_EN (0x00000040) +#define MCF_LCDC_LIER_GW_UDR_ERR_EN (0x00000080) + +/* Bit definitions and macros for MCF_LCDC_LISR */ +#define MCF_LCDC_LISR_BOF (0x00000001) +#define MCF_LCDC_LISR_EOF (0x00000002) +#define MCF_LCDC_LISR_ERR_RES (0x00000004) +#define MCF_LCDC_LISR_UDR_ERR (0x00000008) +#define MCF_LCDC_LISR_GW_BOF (0x00000010) +#define MCF_LCDC_LISR_GW_EOF (0x00000020) +#define MCF_LCDC_LISR_GW_ERR_RES (0x00000040) +#define MCF_LCDC_LISR_GW_UDR_ERR (0x00000080) + +/* Bit definitions and macros for MCF_LCDC_LGWSAR */ +#define MCF_LCDC_LGWSAR_GWSA(x) (((x)&0x3FFFFFFF)<<2) + +/* Bit definitions and macros for MCF_LCDC_LGWSR */ +#define MCF_LCDC_LGWSR_GWH(x) (((x)&0x000003FF)<<0) +#define MCF_LCDC_LGWSR_GWW(x) (((x)&0x0000003F)<<20) + +/* Bit definitions and macros for MCF_LCDC_LGWVPWR */ +#define MCF_LCDC_LGWVPWR_GWVPW(x) (((x)&0x000003FF)<<0) + +/* Bit definitions and macros for MCF_LCDC_LGWPOR */ +#define MCF_LCDC_LGWPOR_GWPO(x) (((x)&0x0000001F)<<0) + +/* Bit definitions and macros for MCF_LCDC_LGWPR */ +#define MCF_LCDC_LGWPR_GWYP(x) (((x)&0x000003FF)<<0) +#define MCF_LCDC_LGWPR_GWXP(x) (((x)&0x000003FF)<<16) + +/* Bit definitions and macros for MCF_LCDC_LGWCR */ +#define MCF_LCDC_LGWCR_GWCKB(x) (((x)&0x0000003F)<<0) +#define MCF_LCDC_LGWCR_GWCKG(x) (((x)&0x0000003F)<<6) +#define MCF_LCDC_LGWCR_GWCKR(x) (((x)&0x0000003F)<<12) +#define MCF_LCDC_LGWCR_GW_RVS (0x00200000) +#define MCF_LCDC_LGWCR_GWE (0x00400000) +#define MCF_LCDC_LGWCR_GWCKE (0x00800000) +#define MCF_LCDC_LGWCR_GWAV(x) (((x)&0x000000FF)<<24) + +/* Bit definitions and macros for MCF_LCDC_LGWDCR */ +#define MCF_LCDC_LGWDCR_GWTM(x) (((x)&0x0000001F)<<0) +#define MCF_LCDC_LGWDCR_GWHM(x) (((x)&0x0000001F)<<16) +#define MCF_LCDC_LGWDCR_GWBT (0x80000000) + +/* Bit definitions and macros for MCF_LCDC_LSCR */ +#define MCF_LCDC_LSCR_PS_RISE_DELAY(x) (((x)&0x0000003F)<<26) +#define MCF_LCDC_LSCR_CLS_RISE_DELAY(x) (((x)&0x000000FF)<<16) +#define MCF_LCDC_LSCR_REV_TOGGLE_DELAY(x) (((x)&0x0000000F)<<8) +#define MCF_LCDC_LSCR_GRAY_2(x) (((x)&0x0000000F)<<4) +#define MCF_LCDC_LSCR_GRAY_1(x) (((x)&0x0000000F)<<0) + +/* Bit definitions and macros for MCF_LCDC_BPLUT_BASE */ +#define MCF_LCDC_BPLUT_BASE_BASE(x) (((x)&0xFFFFFFFF)<<0) + +/* Bit definitions and macros for MCF_LCDC_GWLUT_BASE */ +#define MCF_LCDC_GWLUT_BASE_BASE(x) (((x)&0xFFFFFFFF)<<0) + +/********************************************************************* + * + * Phase Locked Loop (PLL) + * + *********************************************************************/ + +/* Register read/write macros */ +#define MCF_PLL_PODR MCF_REG08(0xFC0C0000) +#define MCF_PLL_PLLCR MCF_REG08(0xFC0C0004) +#define MCF_PLL_PMDR MCF_REG08(0xFC0C0008) +#define MCF_PLL_PFDR MCF_REG08(0xFC0C000C) + +/* Bit definitions and macros for MCF_PLL_PODR */ +#define MCF_PLL_PODR_BUSDIV(x) (((x)&0x0F)<<0) +#define MCF_PLL_PODR_CPUDIV(x) (((x)&0x0F)<<4) + +/* Bit definitions and macros for MCF_PLL_PLLCR */ +#define MCF_PLL_PLLCR_DITHDEV(x) (((x)&0x07)<<0) +#define MCF_PLL_PLLCR_DITHEN (0x80) + +/* Bit definitions and macros for MCF_PLL_PMDR */ +#define MCF_PLL_PMDR_MODDIV(x) (((x)&0xFF)<<0) + +/* Bit definitions and macros for MCF_PLL_PFDR */ +#define MCF_PLL_PFDR_MFD(x) (((x)&0xFF)<<0) + +/********************************************************************* + * + * System Control Module Registers (SCM) + * + *********************************************************************/ + +/* Register read/write macros */ +#define MCF_SCM_MPR MCF_REG32(0xFC000000) +#define MCF_SCM_PACRA MCF_REG32(0xFC000020) +#define MCF_SCM_PACRB MCF_REG32(0xFC000024) +#define MCF_SCM_PACRC MCF_REG32(0xFC000028) +#define MCF_SCM_PACRD MCF_REG32(0xFC00002C) +#define MCF_SCM_PACRE MCF_REG32(0xFC000040) +#define MCF_SCM_PACRF MCF_REG32(0xFC000044) + +#define MCF_SCM_BCR MCF_REG32(0xFC040024) + +/********************************************************************* + * + * SDRAM Controller (SDRAMC) + * + *********************************************************************/ + +/* Register read/write macros */ +#define MCF_SDRAMC_SDMR MCF_REG32(0xFC0B8000) +#define MCF_SDRAMC_SDCR MCF_REG32(0xFC0B8004) +#define MCF_SDRAMC_SDCFG1 MCF_REG32(0xFC0B8008) +#define MCF_SDRAMC_SDCFG2 MCF_REG32(0xFC0B800C) +#define MCF_SDRAMC_LIMP_FIX MCF_REG32(0xFC0B8080) +#define MCF_SDRAMC_SDDS MCF_REG32(0xFC0B8100) +#define MCF_SDRAMC_SDCS0 MCF_REG32(0xFC0B8110) +#define MCF_SDRAMC_SDCS1 MCF_REG32(0xFC0B8114) +#define MCF_SDRAMC_SDCS2 MCF_REG32(0xFC0B8118) +#define MCF_SDRAMC_SDCS3 MCF_REG32(0xFC0B811C) +#define MCF_SDRAMC_SDCS(x) MCF_REG32(0xFC0B8110+((x)*0x004)) + +/* Bit definitions and macros for MCF_SDRAMC_SDMR */ +#define MCF_SDRAMC_SDMR_CMD (0x00010000) +#define MCF_SDRAMC_SDMR_AD(x) (((x)&0x00000FFF)<<18) +#define MCF_SDRAMC_SDMR_BNKAD(x) (((x)&0x00000003)<<30) +#define MCF_SDRAMC_SDMR_BNKAD_LMR (0x00000000) +#define MCF_SDRAMC_SDMR_BNKAD_LEMR (0x40000000) + +/* Bit definitions and macros for MCF_SDRAMC_SDCR */ +#define MCF_SDRAMC_SDCR_IPALL (0x00000002) +#define MCF_SDRAMC_SDCR_IREF (0x00000004) +#define MCF_SDRAMC_SDCR_DQS_OE(x) (((x)&0x0000000F)<<8) +#define MCF_SDRAMC_SDCR_PS(x) (((x)&0x00000003)<<12) +#define MCF_SDRAMC_SDCR_RCNT(x) (((x)&0x0000003F)<<16) +#define MCF_SDRAMC_SDCR_OE_RULE (0x00400000) +#define MCF_SDRAMC_SDCR_MUX(x) (((x)&0x00000003)<<24) +#define MCF_SDRAMC_SDCR_REF (0x10000000) +#define MCF_SDRAMC_SDCR_DDR (0x20000000) +#define MCF_SDRAMC_SDCR_CKE (0x40000000) +#define MCF_SDRAMC_SDCR_MODE_EN (0x80000000) +#define MCF_SDRAMC_SDCR_PS_16 (0x00002000) +#define MCF_SDRAMC_SDCR_PS_32 (0x00000000) + +/* Bit definitions and macros for MCF_SDRAMC_SDCFG1 */ +#define MCF_SDRAMC_SDCFG1_WTLAT(x) (((x)&0x00000007)<<4) +#define MCF_SDRAMC_SDCFG1_REF2ACT(x) (((x)&0x0000000F)<<8) +#define MCF_SDRAMC_SDCFG1_PRE2ACT(x) (((x)&0x00000007)<<12) +#define MCF_SDRAMC_SDCFG1_ACT2RW(x) (((x)&0x00000007)<<16) +#define MCF_SDRAMC_SDCFG1_RDLAT(x) (((x)&0x0000000F)<<20) +#define MCF_SDRAMC_SDCFG1_SWT2RD(x) (((x)&0x00000007)<<24) +#define MCF_SDRAMC_SDCFG1_SRD2RW(x) (((x)&0x0000000F)<<28) + +/* Bit definitions and macros for MCF_SDRAMC_SDCFG2 */ +#define MCF_SDRAMC_SDCFG2_BL(x) (((x)&0x0000000F)<<16) +#define MCF_SDRAMC_SDCFG2_BRD2WT(x) (((x)&0x0000000F)<<20) +#define MCF_SDRAMC_SDCFG2_BWT2RW(x) (((x)&0x0000000F)<<24) +#define MCF_SDRAMC_SDCFG2_BRD2PRE(x) (((x)&0x0000000F)<<28) + +/* Device Errata - LIMP mode work around */ +#define MCF_SDRAMC_REFRESH (0x40000000) + +/* Bit definitions and macros for MCF_SDRAMC_SDDS */ +#define MCF_SDRAMC_SDDS_SB_D(x) (((x)&0x00000003)<<0) +#define MCF_SDRAMC_SDDS_SB_S(x) (((x)&0x00000003)<<2) +#define MCF_SDRAMC_SDDS_SB_A(x) (((x)&0x00000003)<<4) +#define MCF_SDRAMC_SDDS_SB_C(x) (((x)&0x00000003)<<6) +#define MCF_SDRAMC_SDDS_SB_E(x) (((x)&0x00000003)<<8) + +/* Bit definitions and macros for MCF_SDRAMC_SDCS */ +#define MCF_SDRAMC_SDCS_CSSZ(x) (((x)&0x0000001F)<<0) +#define MCF_SDRAMC_SDCS_BASE(x) (((x)&0x00000FFF)<<20) +#define MCF_SDRAMC_SDCS_BA(x) ((x)&0xFFF00000) +#define MCF_SDRAMC_SDCS_CSSZ_DIABLE (0x00000000) +#define MCF_SDRAMC_SDCS_CSSZ_1MBYTE (0x00000013) +#define MCF_SDRAMC_SDCS_CSSZ_2MBYTE (0x00000014) +#define MCF_SDRAMC_SDCS_CSSZ_4MBYTE (0x00000015) +#define MCF_SDRAMC_SDCS_CSSZ_8MBYTE (0x00000016) +#define MCF_SDRAMC_SDCS_CSSZ_16MBYTE (0x00000017) +#define MCF_SDRAMC_SDCS_CSSZ_32MBYTE (0x00000018) +#define MCF_SDRAMC_SDCS_CSSZ_64MBYTE (0x00000019) +#define MCF_SDRAMC_SDCS_CSSZ_128MBYTE (0x0000001A) +#define MCF_SDRAMC_SDCS_CSSZ_256MBYTE (0x0000001B) +#define MCF_SDRAMC_SDCS_CSSZ_512MBYTE (0x0000001C) +#define MCF_SDRAMC_SDCS_CSSZ_1GBYTE (0x0000001D) +#define MCF_SDRAMC_SDCS_CSSZ_2GBYTE (0x0000001E) +#define MCF_SDRAMC_SDCS_CSSZ_4GBYTE (0x0000001F) + +/********************************************************************* + * + * FlexCAN module registers + * + *********************************************************************/ +#define MCF_FLEXCAN_BASEADDR(x) (0xFC020000+(x)*0x0800) +#define MCF_FLEXCAN_CANMCR(x) MCF_REG32(0xFC020000+(x)*0x0800+0x00) +#define MCF_FLEXCAN_CANCTRL(x) MCF_REG32(0xFC020000+(x)*0x0800+0x04) +#define MCF_FLEXCAN_TIMER(x) MCF_REG32(0xFC020000+(x)*0x0800+0x08) +#define MCF_FLEXCAN_RXGMASK(x) MCF_REG32(0xFC020000+(x)*0x0800+0x10) +#define MCF_FLEXCAN_RX14MASK(x) MCF_REG32(0xFC020000+(x)*0x0800+0x14) +#define MCF_FLEXCAN_RX15MASK(x) MCF_REG32(0xFC020000+(x)*0x0800+0x18) +#define MCF_FLEXCAN_ERRCNT(x) MCF_REG32(0xFC020000+(x)*0x0800+0x1C) +#define MCF_FLEXCAN_ERRSTAT(x) MCF_REG32(0xFC020000+(x)*0x0800+0x20) +#define MCF_FLEXCAN_IMASK(x) MCF_REG32(0xFC020000+(x)*0x0800+0x28) +#define MCF_FLEXCAN_IFLAG(x) MCF_REG32(0xFC020000+(x)*0x0800+0x30) + +#define MCF_FLEXCAN_MB_CNT(x,y) MCF_REG32(0xFC020080+(x)*0x0800+(y)*0x10+0x0) +#define MCF_FLEXCAN_MB_ID(x,y) MCF_REG32(0xFC020080+(x)*0x0800+(y)*0x10+0x4) +#define MCF_FLEXCAN_MB_DB(x,y,z) MCF_REG08(0xFC020080+(x)*0x0800+(y)*0x10+0x8+(z)*0x1) + +/* + * FlexCAN Module Configuration Register + */ +#define CANMCR_MDIS (0x80000000) +#define CANMCR_FRZ (0x40000000) +#define CANMCR_HALT (0x10000000) +#define CANMCR_SOFTRST (0x02000000) +#define CANMCR_FRZACK (0x01000000) +#define CANMCR_SUPV (0x00800000) +#define CANMCR_MAXMB(x) ((x)&0x0F) + +/* + * FlexCAN Control Register + */ +#define CANCTRL_PRESDIV(x) (((x)&0xFF)<<24) +#define CANCTRL_RJW(x) (((x)&0x03)<<22) +#define CANCTRL_PSEG1(x) (((x)&0x07)<<19) +#define CANCTRL_PSEG2(x) (((x)&0x07)<<16) +#define CANCTRL_BOFFMSK (0x00008000) +#define CANCTRL_ERRMSK (0x00004000) +#define CANCTRL_CLKSRC (0x00002000) +#define CANCTRL_LPB (0x00001000) +#define CANCTRL_SAMP (0x00000080) +#define CANCTRL_BOFFREC (0x00000040) +#define CANCTRL_TSYNC (0x00000020) +#define CANCTRL_LBUF (0x00000010) +#define CANCTRL_LOM (0x00000008) +#define CANCTRL_PROPSEG(x) ((x)&0x07) + +/* + * FlexCAN Error Counter Register + */ +#define ERRCNT_RXECTR(x) (((x)&0xFF)<<8) +#define ERRCNT_TXECTR(x) ((x)&0xFF) + +/* + * FlexCAN Error and Status Register + */ +#define ERRSTAT_BITERR(x) (((x)&0x03)<<14) +#define ERRSTAT_ACKERR (0x00002000) +#define ERRSTAT_CRCERR (0x00001000) +#define ERRSTAT_FRMERR (0x00000800) +#define ERRSTAT_STFERR (0x00000400) +#define ERRSTAT_TXWRN (0x00000200) +#define ERRSTAT_RXWRN (0x00000100) +#define ERRSTAT_IDLE (0x00000080) +#define ERRSTAT_TXRX (0x00000040) +#define ERRSTAT_FLTCONF(x) (((x)&0x03)<<4) +#define ERRSTAT_BOFFINT (0x00000004) +#define ERRSTAT_ERRINT (0x00000002) + +/* + * Interrupt Mask Register + */ +#define IMASK_BUF15M (0x8000) +#define IMASK_BUF14M (0x4000) +#define IMASK_BUF13M (0x2000) +#define IMASK_BUF12M (0x1000) +#define IMASK_BUF11M (0x0800) +#define IMASK_BUF10M (0x0400) +#define IMASK_BUF9M (0x0200) +#define IMASK_BUF8M (0x0100) +#define IMASK_BUF7M (0x0080) +#define IMASK_BUF6M (0x0040) +#define IMASK_BUF5M (0x0020) +#define IMASK_BUF4M (0x0010) +#define IMASK_BUF3M (0x0008) +#define IMASK_BUF2M (0x0004) +#define IMASK_BUF1M (0x0002) +#define IMASK_BUF0M (0x0001) +#define IMASK_BUFnM(x) (0x1<<(x)) +#define IMASK_BUFF_ENABLE_ALL (0x1111) +#define IMASK_BUFF_DISABLE_ALL (0x0000) + +/* + * Interrupt Flag Register + */ +#define IFLAG_BUF15M (0x8000) +#define IFLAG_BUF14M (0x4000) +#define IFLAG_BUF13M (0x2000) +#define IFLAG_BUF12M (0x1000) +#define IFLAG_BUF11M (0x0800) +#define IFLAG_BUF10M (0x0400) +#define IFLAG_BUF9M (0x0200) +#define IFLAG_BUF8M (0x0100) +#define IFLAG_BUF7M (0x0080) +#define IFLAG_BUF6M (0x0040) +#define IFLAG_BUF5M (0x0020) +#define IFLAG_BUF4M (0x0010) +#define IFLAG_BUF3M (0x0008) +#define IFLAG_BUF2M (0x0004) +#define IFLAG_BUF1M (0x0002) +#define IFLAG_BUF0M (0x0001) +#define IFLAG_BUFF_SET_ALL (0xFFFF) +#define IFLAG_BUFF_CLEAR_ALL (0x0000) +#define IFLAG_BUFnM(x) (0x1<<(x)) + +/* + * Message Buffers + */ +#define MB_CNT_CODE(x) (((x)&0x0F)<<24) +#define MB_CNT_SRR (0x00400000) +#define MB_CNT_IDE (0x00200000) +#define MB_CNT_RTR (0x00100000) +#define MB_CNT_LENGTH(x) (((x)&0x0F)<<16) +#define MB_CNT_TIMESTAMP(x) ((x)&0xFFFF) +#define MB_ID_STD(x) (((x)&0x07FF)<<18) +#define MB_ID_EXT(x) ((x)&0x3FFFF) + +/********************************************************************* + * + * Edge Port Module (EPORT) + * + *********************************************************************/ + +/* Register read/write macros */ +#define MCF_EPORT_EPPAR MCF_REG16(0xFC094000) +#define MCF_EPORT_EPDDR MCF_REG08(0xFC094002) +#define MCF_EPORT_EPIER MCF_REG08(0xFC094003) +#define MCF_EPORT_EPDR MCF_REG08(0xFC094004) +#define MCF_EPORT_EPPDR MCF_REG08(0xFC094005) +#define MCF_EPORT_EPFR MCF_REG08(0xFC094006) + +/* Bit definitions and macros for MCF_EPORT_EPPAR */ +#define MCF_EPORT_EPPAR_EPPA1(x) (((x)&0x0003)<<2) +#define MCF_EPORT_EPPAR_EPPA2(x) (((x)&0x0003)<<4) +#define MCF_EPORT_EPPAR_EPPA3(x) (((x)&0x0003)<<6) +#define MCF_EPORT_EPPAR_EPPA4(x) (((x)&0x0003)<<8) +#define MCF_EPORT_EPPAR_EPPA5(x) (((x)&0x0003)<<10) +#define MCF_EPORT_EPPAR_EPPA6(x) (((x)&0x0003)<<12) +#define MCF_EPORT_EPPAR_EPPA7(x) (((x)&0x0003)<<14) +#define MCF_EPORT_EPPAR_LEVEL (0) +#define MCF_EPORT_EPPAR_RISING (1) +#define MCF_EPORT_EPPAR_FALLING (2) +#define MCF_EPORT_EPPAR_BOTH (3) +#define MCF_EPORT_EPPAR_EPPA7_LEVEL (0x0000) +#define MCF_EPORT_EPPAR_EPPA7_RISING (0x4000) +#define MCF_EPORT_EPPAR_EPPA7_FALLING (0x8000) +#define MCF_EPORT_EPPAR_EPPA7_BOTH (0xC000) +#define MCF_EPORT_EPPAR_EPPA6_LEVEL (0x0000) +#define MCF_EPORT_EPPAR_EPPA6_RISING (0x1000) +#define MCF_EPORT_EPPAR_EPPA6_FALLING (0x2000) +#define MCF_EPORT_EPPAR_EPPA6_BOTH (0x3000) +#define MCF_EPORT_EPPAR_EPPA5_LEVEL (0x0000) +#define MCF_EPORT_EPPAR_EPPA5_RISING (0x0400) +#define MCF_EPORT_EPPAR_EPPA5_FALLING (0x0800) +#define MCF_EPORT_EPPAR_EPPA5_BOTH (0x0C00) +#define MCF_EPORT_EPPAR_EPPA4_LEVEL (0x0000) +#define MCF_EPORT_EPPAR_EPPA4_RISING (0x0100) +#define MCF_EPORT_EPPAR_EPPA4_FALLING (0x0200) +#define MCF_EPORT_EPPAR_EPPA4_BOTH (0x0300) +#define MCF_EPORT_EPPAR_EPPA3_LEVEL (0x0000) +#define MCF_EPORT_EPPAR_EPPA3_RISING (0x0040) +#define MCF_EPORT_EPPAR_EPPA3_FALLING (0x0080) +#define MCF_EPORT_EPPAR_EPPA3_BOTH (0x00C0) +#define MCF_EPORT_EPPAR_EPPA2_LEVEL (0x0000) +#define MCF_EPORT_EPPAR_EPPA2_RISING (0x0010) +#define MCF_EPORT_EPPAR_EPPA2_FALLING (0x0020) +#define MCF_EPORT_EPPAR_EPPA2_BOTH (0x0030) +#define MCF_EPORT_EPPAR_EPPA1_LEVEL (0x0000) +#define MCF_EPORT_EPPAR_EPPA1_RISING (0x0004) +#define MCF_EPORT_EPPAR_EPPA1_FALLING (0x0008) +#define MCF_EPORT_EPPAR_EPPA1_BOTH (0x000C) + +/* Bit definitions and macros for MCF_EPORT_EPDDR */ +#define MCF_EPORT_EPDDR_EPDD1 (0x02) +#define MCF_EPORT_EPDDR_EPDD2 (0x04) +#define MCF_EPORT_EPDDR_EPDD3 (0x08) +#define MCF_EPORT_EPDDR_EPDD4 (0x10) +#define MCF_EPORT_EPDDR_EPDD5 (0x20) +#define MCF_EPORT_EPDDR_EPDD6 (0x40) +#define MCF_EPORT_EPDDR_EPDD7 (0x80) + +/* Bit definitions and macros for MCF_EPORT_EPIER */ +#define MCF_EPORT_EPIER_EPIE1 (0x02) +#define MCF_EPORT_EPIER_EPIE2 (0x04) +#define MCF_EPORT_EPIER_EPIE3 (0x08) +#define MCF_EPORT_EPIER_EPIE4 (0x10) +#define MCF_EPORT_EPIER_EPIE5 (0x20) +#define MCF_EPORT_EPIER_EPIE6 (0x40) +#define MCF_EPORT_EPIER_EPIE7 (0x80) + +/* Bit definitions and macros for MCF_EPORT_EPDR */ +#define MCF_EPORT_EPDR_EPD1 (0x02) +#define MCF_EPORT_EPDR_EPD2 (0x04) +#define MCF_EPORT_EPDR_EPD3 (0x08) +#define MCF_EPORT_EPDR_EPD4 (0x10) +#define MCF_EPORT_EPDR_EPD5 (0x20) +#define MCF_EPORT_EPDR_EPD6 (0x40) +#define MCF_EPORT_EPDR_EPD7 (0x80) + +/* Bit definitions and macros for MCF_EPORT_EPPDR */ +#define MCF_EPORT_EPPDR_EPPD1 (0x02) +#define MCF_EPORT_EPPDR_EPPD2 (0x04) +#define MCF_EPORT_EPPDR_EPPD3 (0x08) +#define MCF_EPORT_EPPDR_EPPD4 (0x10) +#define MCF_EPORT_EPPDR_EPPD5 (0x20) +#define MCF_EPORT_EPPDR_EPPD6 (0x40) +#define MCF_EPORT_EPPDR_EPPD7 (0x80) + +/* Bit definitions and macros for MCF_EPORT_EPFR */ +#define MCF_EPORT_EPFR_EPF1 (0x02) +#define MCF_EPORT_EPFR_EPF2 (0x04) +#define MCF_EPORT_EPFR_EPF3 (0x08) +#define MCF_EPORT_EPFR_EPF4 (0x10) +#define MCF_EPORT_EPFR_EPF5 (0x20) +#define MCF_EPORT_EPFR_EPF6 (0x40) +#define MCF_EPORT_EPFR_EPF7 (0x80) + +/********************************************************************/ +#endif /* m532xsim_h */ diff --git a/include/asm-mips/Kbuild b/include/asm-mips/Kbuild new file mode 100644 index 000000000..c68e1680d --- /dev/null +++ b/include/asm-mips/Kbuild @@ -0,0 +1 @@ +include include/asm-generic/Kbuild.asm diff --git a/include/asm-mips/apm.h b/include/asm-mips/apm.h new file mode 100644 index 000000000..4b99ffc11 --- /dev/null +++ b/include/asm-mips/apm.h @@ -0,0 +1,64 @@ +/* -*- linux-c -*- + * + * (C) 2003 zecke@handhelds.org + * + * GPL version 2 + * + * based on arch/arm/kernel/apm.c + * factor out the information needed by architectures to provide + * apm status + * + * + */ +#ifndef MIPS_ASM_SA1100_APM_H +#define MIPS_ASM_SA1100_APM_H + +#include <linux/apm_bios.h> + +/* + * This structure gets filled in by the machine specific 'get_power_status' + * implementation. Any fields which are not set default to a safe value. + */ +struct apm_power_info { + unsigned char ac_line_status; +#define APM_AC_OFFLINE 0 +#define APM_AC_ONLINE 1 +#define APM_AC_BACKUP 2 +#define APM_AC_UNKNOWN 0xff + + unsigned char battery_status; +#define APM_BATTERY_STATUS_HIGH 0 +#define APM_BATTERY_STATUS_LOW 1 +#define APM_BATTERY_STATUS_CRITICAL 2 +#define APM_BATTERY_STATUS_CHARGING 3 +#define APM_BATTERY_STATUS_NOT_PRESENT 4 +#define APM_BATTERY_STATUS_UNKNOWN 0xff + + unsigned char battery_flag; +#define APM_BATTERY_FLAG_HIGH (1 << 0) +#define APM_BATTERY_FLAG_LOW (1 << 1) +#define APM_BATTERY_FLAG_CRITICAL (1 << 2) +#define APM_BATTERY_FLAG_CHARGING (1 << 3) +#define APM_BATTERY_FLAG_NOT_PRESENT (1 << 7) +#define APM_BATTERY_FLAG_UNKNOWN 0xff + + int battery_life; + int time; + int units; +#define APM_UNITS_MINS 0 +#define APM_UNITS_SECS 1 +#define APM_UNITS_UNKNOWN -1 + +}; + +/* + * This allows machines to provide their own "apm get power status" function. + */ +extern void (*apm_get_power_status)(struct apm_power_info *); + +/* + * Queue an event (APM_SYS_SUSPEND or APM_CRITICAL_SUSPEND) + */ +void apm_queue_event(apm_event_t event); + +#endif diff --git a/include/asm-mips/emma2rh/emma2rh.h b/include/asm-mips/emma2rh/emma2rh.h new file mode 100644 index 000000000..4fb8df71c --- /dev/null +++ b/include/asm-mips/emma2rh/emma2rh.h @@ -0,0 +1,330 @@ +/* + * include/asm-mips/emma2rh/emma2rh.h + * This file is EMMA2RH common header. + * + * Copyright (C) NEC Electronics Corporation 2005-2006 + * + * This file based on include/asm-mips/ddb5xxx/ddb5xxx.h + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __ASM_EMMA2RH_EMMA2RH_H +#define __ASM_EMMA2RH_EMMA2RH_H + +/* + * EMMA2RH registers + */ +#define REGBASE 0x10000000 + +#define EMMA2RH_BHIF_STRAP_0 (0x000010+REGBASE) +#define EMMA2RH_BHIF_INT_ST_0 (0x000030+REGBASE) +#define EMMA2RH_BHIF_INT_ST_1 (0x000034+REGBASE) +#define EMMA2RH_BHIF_INT_ST_2 (0x000038+REGBASE) +#define EMMA2RH_BHIF_INT_EN_0 (0x000040+REGBASE) +#define EMMA2RH_BHIF_INT_EN_1 (0x000044+REGBASE) +#define EMMA2RH_BHIF_INT_EN_2 (0x000048+REGBASE) +#define EMMA2RH_BHIF_INT1_EN_0 (0x000050+REGBASE) +#define EMMA2RH_BHIF_INT1_EN_1 (0x000054+REGBASE) +#define EMMA2RH_BHIF_INT1_EN_2 (0x000058+REGBASE) +#define EMMA2RH_BHIF_SW_INT (0x000070+REGBASE) +#define EMMA2RH_BHIF_SW_INT_EN (0x000080+REGBASE) +#define EMMA2RH_BHIF_SW_INT_CLR (0x000090+REGBASE) +#define EMMA2RH_BHIF_MAIN_CTRL (0x0000b4+REGBASE) +#define EMMA2RH_BHIF_EXCEPT_VECT_BASE_ADDRESS (0x0000c0+REGBASE) +#define EMMA2RH_GPIO_DIR (0x110d20+REGBASE) +#define EMMA2RH_GPIO_INT_ST (0x110d30+REGBASE) +#define EMMA2RH_GPIO_INT_MASK (0x110d3c+REGBASE) +#define EMMA2RH_GPIO_INT_MODE (0x110d48+REGBASE) +#define EMMA2RH_GPIO_INT_CND_A (0x110d54+REGBASE) +#define EMMA2RH_GPIO_INT_CND_B (0x110d60+REGBASE) +#define EMMA2RH_PBRD_INT_EN (0x100010+REGBASE) +#define EMMA2RH_PBRD_CLKSEL (0x100028+REGBASE) +#define EMMA2RH_PFUR0_BASE (0x101000+REGBASE) +#define EMMA2RH_PFUR1_BASE (0x102000+REGBASE) +#define EMMA2RH_PFUR2_BASE (0x103000+REGBASE) +#define EMMA2RH_PIIC0_BASE (0x107000+REGBASE) +#define EMMA2RH_PIIC1_BASE (0x108000+REGBASE) +#define EMMA2RH_PIIC2_BASE (0x109000+REGBASE) +#define EMMA2RH_PCI_CONTROL (0x200000+REGBASE) +#define EMMA2RH_PCI_ARBIT_CTR (0x200004+REGBASE) +#define EMMA2RH_PCI_IWIN0_CTR (0x200010+REGBASE) +#define EMMA2RH_PCI_IWIN1_CTR (0x200014+REGBASE) +#define EMMA2RH_PCI_INIT_ESWP (0x200018+REGBASE) +#define EMMA2RH_PCI_INT (0x200020+REGBASE) +#define EMMA2RH_PCI_INT_EN (0x200024+REGBASE) +#define EMMA2RH_PCI_TWIN_CTR (0x200030+REGBASE) +#define EMMA2RH_PCI_TWIN_BADR (0x200034+REGBASE) +#define EMMA2RH_PCI_TWIN0_DADR (0x200038+REGBASE) +#define EMMA2RH_PCI_TWIN1_DADR (0x20003c+REGBASE) + +/* + * Memory map (physical address) + * + * Note most of the following address must be properly aligned by the + * corresponding size. For example, if PCI_IO_SIZE is 16MB, then + * PCI_IO_BASE must be aligned along 16MB boundary. + */ + +/* the actual ram size is detected at run-time */ +#define EMMA2RH_RAM_BASE 0x00000000 +#define EMMA2RH_RAM_SIZE 0x10000000 /* less than 256MB */ + +#define EMMA2RH_IO_BASE 0x10000000 +#define EMMA2RH_IO_SIZE 0x01000000 /* 16 MB */ + +#define EMMA2RH_GENERALIO_BASE 0x11000000 +#define EMMA2RH_GENERALIO_SIZE 0x01000000 /* 16 MB */ + +#define EMMA2RH_PCI_IO_BASE 0x12000000 +#define EMMA2RH_PCI_IO_SIZE 0x02000000 /* 32 MB */ + +#define EMMA2RH_PCI_MEM_BASE 0x14000000 +#define EMMA2RH_PCI_MEM_SIZE 0x08000000 /* 128 MB */ + +#define EMMA2RH_ROM_BASE 0x1c000000 +#define EMMA2RH_ROM_SIZE 0x04000000 /* 64 MB */ + +#define EMMA2RH_PCI_CONFIG_BASE EMMA2RH_PCI_IO_BASE +#define EMMA2RH_PCI_CONFIG_SIZE EMMA2RH_PCI_IO_SIZE + +#define NUM_CPU_IRQ 8 +#define NUM_EMMA2RH_IRQ 96 + +#define CPU_EMMA2RH_CASCADE 2 +#define EMMA2RH_IRQ_BASE 0 + +/* + * emma2rh irq defs + */ + +#define EMMA2RH_IRQ_INT0 (0 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT1 (1 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT2 (2 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT3 (3 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT4 (4 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT5 (5 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT6 (6 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT7 (7 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT8 (8 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT9 (9 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT10 (10 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT11 (11 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT12 (12 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT13 (13 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT14 (14 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT15 (15 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT16 (16 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT17 (17 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT18 (18 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT19 (19 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT20 (20 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT21 (21 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT22 (22 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT23 (23 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT24 (24 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT25 (25 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT26 (26 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT27 (27 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT28 (28 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT29 (29 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT30 (30 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT31 (31 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT32 (32 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT33 (33 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT34 (34 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT35 (35 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT36 (36 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT37 (37 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT38 (38 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT39 (39 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT40 (40 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT41 (41 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT42 (42 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT43 (43 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT44 (44 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT45 (45 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT46 (46 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT47 (47 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT48 (48 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT49 (49 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT50 (50 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT51 (51 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT52 (52 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT53 (53 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT54 (54 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT55 (55 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT56 (56 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT57 (57 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT58 (58 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT59 (59 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT60 (60 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT61 (61 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT62 (62 + EMMA2RH_IRQ_BASE) +#define EMMA2RH_IRQ_INT63 (63 + EMMA2RH_IRQ_BASE) + +#define EMMA2RH_IRQ_PFUR0 EMMA2RH_IRQ_INT49 +#define EMMA2RH_IRQ_PFUR1 EMMA2RH_IRQ_INT50 +#define EMMA2RH_IRQ_PFUR2 EMMA2RH_IRQ_INT51 +#define EMMA2RH_IRQ_PIIC0 EMMA2RH_IRQ_INT56 +#define EMMA2RH_IRQ_PIIC1 EMMA2RH_IRQ_INT57 +#define EMMA2RH_IRQ_PIIC2 EMMA2RH_IRQ_INT58 + +/* + * EMMA2RH Register Access + */ + +#define EMMA2RH_BASE (0xa0000000) + +static inline void emma2rh_sync(void) +{ + volatile u32 *p = (volatile u32 *)0xbfc00000; + (void)(*p); +} + +static inline void emma2rh_out32(u32 offset, u32 val) +{ + *(volatile u32 *)(EMMA2RH_BASE | offset) = val; + emma2rh_sync(); +} + +static inline u32 emma2rh_in32(u32 offset) +{ + u32 val = *(volatile u32 *)(EMMA2RH_BASE | offset); + emma2rh_sync(); + return val; +} + +static inline void emma2rh_out16(u32 offset, u16 val) +{ + *(volatile u16 *)(EMMA2RH_BASE | offset) = val; + emma2rh_sync(); +} + +static inline u16 emma2rh_in16(u32 offset) +{ + u16 val = *(volatile u16 *)(EMMA2RH_BASE | offset); + emma2rh_sync(); + return val; +} + +static inline void emma2rh_out8(u32 offset, u8 val) +{ + *(volatile u8 *)(EMMA2RH_BASE | offset) = val; + emma2rh_sync(); +} + +static inline u8 emma2rh_in8(u32 offset) +{ + u8 val = *(volatile u8 *)(EMMA2RH_BASE | offset); + emma2rh_sync(); + return val; +} + +/** + * IIC registers map + **/ + +/*---------------------------------------------------------------------------*/ +/* CNT - Control register (00H R/W) */ +/*---------------------------------------------------------------------------*/ +#define SPT 0x00000001 +#define STT 0x00000002 +#define ACKE 0x00000004 +#define WTIM 0x00000008 +#define SPIE 0x00000010 +#define WREL 0x00000020 +#define LREL 0x00000040 +#define IICE 0x00000080 +#define CNT_RESERVED 0x000000ff /* reserved bit 0 */ + +#define I2C_EMMA_START (IICE | STT) +#define I2C_EMMA_STOP (IICE | SPT) +#define I2C_EMMA_REPSTART I2C_EMMA_START + +/*---------------------------------------------------------------------------*/ +/* STA - Status register (10H Read) */ +/*---------------------------------------------------------------------------*/ +#define MSTS 0x00000080 +#define ALD 0x00000040 +#define EXC 0x00000020 +#define COI 0x00000010 +#define TRC 0x00000008 +#define ACKD 0x00000004 +#define STD 0x00000002 +#define SPD 0x00000001 + +/*---------------------------------------------------------------------------*/ +/* CSEL - Clock select register (20H R/W) */ +/*---------------------------------------------------------------------------*/ +#define FCL 0x00000080 +#define ND50 0x00000040 +#define CLD 0x00000020 +#define DAD 0x00000010 +#define SMC 0x00000008 +#define DFC 0x00000004 +#define CL 0x00000003 +#define CSEL_RESERVED 0x000000ff /* reserved bit 0 */ + +#define FAST397 0x0000008b +#define FAST297 0x0000008a +#define FAST347 0x0000000b +#define FAST260 0x0000000a +#define FAST130 0x00000008 +#define STANDARD108 0x00000083 +#define STANDARD83 0x00000082 +#define STANDARD95 0x00000003 +#define STANDARD73 0x00000002 +#define STANDARD36 0x00000001 +#define STANDARD71 0x00000000 + +/*---------------------------------------------------------------------------*/ +/* SVA - Slave address register (30H R/W) */ +/*---------------------------------------------------------------------------*/ +#define SVA 0x000000fe + +/*---------------------------------------------------------------------------*/ +/* SHR - Shift register (40H R/W) */ +/*---------------------------------------------------------------------------*/ +#define SR 0x000000ff + +/*---------------------------------------------------------------------------*/ +/* INT - Interrupt register (50H R/W) */ +/* INTM - Interrupt mask register (60H R/W) */ +/*---------------------------------------------------------------------------*/ +#define INTE0 0x00000001 + +/*********************************************************************** + * I2C registers + *********************************************************************** + */ +#define I2C_EMMA_CNT 0x00 +#define I2C_EMMA_STA 0x10 +#define I2C_EMMA_CSEL 0x20 +#define I2C_EMMA_SVA 0x30 +#define I2C_EMMA_SHR 0x40 +#define I2C_EMMA_INT 0x50 +#define I2C_EMMA_INTM 0x60 + +/* + * include the board dependent part + */ +#if defined(CONFIG_MARKEINS) +#include <asm/emma2rh/markeins.h> +#else +#error "Unknown EMMA2RH board!" +#endif + +#endif /* __ASM_EMMA2RH_EMMA2RH_H */ diff --git a/include/asm-mips/emma2rh/markeins.h b/include/asm-mips/emma2rh/markeins.h new file mode 100644 index 000000000..8fa766795 --- /dev/null +++ b/include/asm-mips/emma2rh/markeins.h @@ -0,0 +1,76 @@ +/* + * include/asm-mips/emma2rh/markeins.h + * This file is EMMA2RH board depended header. + * + * Copyright (C) NEC Electronics Corporation 2005-2006 + * + * This file based on include/asm-mips/ddb5xxx/ddb5xxx.h + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MARKEINS_H +#define MARKEINS_H + +#define NUM_EMMA2RH_IRQ_SW 32 +#define NUM_EMMA2RH_IRQ_GPIO 32 + +#define EMMA2RH_SW_CASCADE (EMMA2RH_IRQ_INT7 - EMMA2RH_IRQ_INT0) +#define EMMA2RH_GPIO_CASCADE (EMMA2RH_IRQ_INT46 - EMMA2RH_IRQ_INT0) + +#define EMMA2RH_SW_IRQ_BASE (EMMA2RH_IRQ_BASE + NUM_EMMA2RH_IRQ) +#define EMMA2RH_GPIO_IRQ_BASE (EMMA2RH_SW_IRQ_BASE + NUM_EMMA2RH_IRQ_SW) +#define CPU_IRQ_BASE (EMMA2RH_GPIO_IRQ_BASE + NUM_EMMA2RH_IRQ_GPIO) + +#define EMMA2RH_SW_IRQ_INT0 (0+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT1 (1+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT2 (2+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT3 (3+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT4 (4+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT5 (5+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT6 (6+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT7 (7+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT8 (8+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT9 (9+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT10 (10+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT11 (11+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT12 (12+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT13 (13+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT14 (14+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT15 (15+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT16 (16+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT17 (17+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT18 (18+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT19 (19+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT20 (20+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT21 (21+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT22 (22+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT23 (23+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT24 (24+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT25 (25+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT26 (26+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT27 (27+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT28 (28+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT29 (29+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT30 (30+EMMA2RH_SW_IRQ_BASE) +#define EMMA2RH_SW_IRQ_INT31 (31+EMMA2RH_SW_IRQ_BASE) + +#define MARKEINS_PCI_IRQ_INTA EMMA2RH_GPIO_IRQ_BASE+15 +#define MARKEINS_PCI_IRQ_INTB EMMA2RH_GPIO_IRQ_BASE+16 +#define MARKEINS_PCI_IRQ_INTC EMMA2RH_GPIO_IRQ_BASE+17 +#define MARKEINS_PCI_IRQ_INTD EMMA2RH_GPIO_IRQ_BASE+18 + +#endif /* CONFIG_MARKEINS */ diff --git a/include/asm-mips/irqflags.h b/include/asm-mips/irqflags.h new file mode 100644 index 000000000..43ca09a3a --- /dev/null +++ b/include/asm-mips/irqflags.h @@ -0,0 +1,225 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 by Ralf Baechle + * Copyright (C) 1996 by Paul M. Antoine + * Copyright (C) 1999 Silicon Graphics + * Copyright (C) 2000 MIPS Technologies, Inc. + */ +#ifndef _ASM_IRQFLAGS_H +#define _ASM_IRQFLAGS_H + +#ifndef __ASSEMBLY__ + +#include <asm/hazards.h> + +__asm__ ( + " .macro raw_local_irq_enable \n" + " .set push \n" + " .set reorder \n" + " .set noat \n" +#ifdef CONFIG_MIPS_MT_SMTC + " mfc0 $1, $2, 1 # SMTC - clear TCStatus.IXMT \n" + " ori $1, 0x400 \n" + " xori $1, 0x400 \n" + " mtc0 $1, $2, 1 \n" +#elif defined(CONFIG_CPU_MIPSR2) + " ei \n" +#else + " mfc0 $1,$12 \n" + " ori $1,0x1f \n" + " xori $1,0x1e \n" + " mtc0 $1,$12 \n" +#endif + " irq_enable_hazard \n" + " .set pop \n" + " .endm"); + +static inline void raw_local_irq_enable(void) +{ + __asm__ __volatile__( + "raw_local_irq_enable" + : /* no outputs */ + : /* no inputs */ + : "memory"); +} + +/* + * For cli() we have to insert nops to make sure that the new value + * has actually arrived in the status register before the end of this + * macro. + * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs + * no nops at all. + */ +/* + * For TX49, operating only IE bit is not enough. + * + * If mfc0 $12 follows store and the mfc0 is last instruction of a + * page and fetching the next instruction causes TLB miss, the result + * of the mfc0 might wrongly contain EXL bit. + * + * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008 + * + * Workaround: mask EXL bit of the result or place a nop before mfc0. + */ +__asm__ ( + " .macro raw_local_irq_disable\n" + " .set push \n" + " .set noat \n" +#ifdef CONFIG_MIPS_MT_SMTC + " mfc0 $1, $2, 1 \n" + " ori $1, 0x400 \n" + " .set noreorder \n" + " mtc0 $1, $2, 1 \n" +#elif defined(CONFIG_CPU_MIPSR2) + " di \n" +#else + " mfc0 $1,$12 \n" + " ori $1,0x1f \n" + " xori $1,0x1f \n" + " .set noreorder \n" + " mtc0 $1,$12 \n" +#endif + " irq_disable_hazard \n" + " .set pop \n" + " .endm \n"); + +static inline void raw_local_irq_disable(void) +{ + __asm__ __volatile__( + "raw_local_irq_disable" + : /* no outputs */ + : /* no inputs */ + : "memory"); +} + +__asm__ ( + " .macro raw_local_save_flags flags \n" + " .set push \n" + " .set reorder \n" +#ifdef CONFIG_MIPS_MT_SMTC + " mfc0 \\flags, $2, 1 \n" +#else + " mfc0 \\flags, $12 \n" +#endif + " .set pop \n" + " .endm \n"); + +#define raw_local_save_flags(x) \ +__asm__ __volatile__( \ + "raw_local_save_flags %0" \ + : "=r" (x)) + +__asm__ ( + " .macro raw_local_irq_save result \n" + " .set push \n" + " .set reorder \n" + " .set noat \n" +#ifdef CONFIG_MIPS_MT_SMTC + " mfc0 \\result, $2, 1 \n" + " ori $1, \\result, 0x400 \n" + " .set noreorder \n" + " mtc0 $1, $2, 1 \n" + " andi \\result, \\result, 0x400 \n" +#elif defined(CONFIG_CPU_MIPSR2) + " di \\result \n" + " andi \\result, 1 \n" +#else + " mfc0 \\result, $12 \n" + " ori $1, \\result, 0x1f \n" + " xori $1, 0x1f \n" + " .set noreorder \n" + " mtc0 $1, $12 \n" +#endif + " irq_disable_hazard \n" + " .set pop \n" + " .endm \n"); + +#define raw_local_irq_save(x) \ +__asm__ __volatile__( \ + "raw_local_irq_save\t%0" \ + : "=r" (x) \ + : /* no inputs */ \ + : "memory") + +__asm__ ( + " .macro raw_local_irq_restore flags \n" + " .set push \n" + " .set noreorder \n" + " .set noat \n" +#ifdef CONFIG_MIPS_MT_SMTC + "mfc0 $1, $2, 1 \n" + "andi \\flags, 0x400 \n" + "ori $1, 0x400 \n" + "xori $1, 0x400 \n" + "or \\flags, $1 \n" + "mtc0 \\flags, $2, 1 \n" +#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU) + /* + * Slow, but doesn't suffer from a relativly unlikely race + * condition we're having since days 1. + */ + " beqz \\flags, 1f \n" + " di \n" + " ei \n" + "1: \n" +#elif defined(CONFIG_CPU_MIPSR2) + /* + * Fast, dangerous. Life is fun, life is good. + */ + " mfc0 $1, $12 \n" + " ins $1, \\flags, 0, 1 \n" + " mtc0 $1, $12 \n" +#else + " mfc0 $1, $12 \n" + " andi \\flags, 1 \n" + " ori $1, 0x1f \n" + " xori $1, 0x1f \n" + " or \\flags, $1 \n" + " mtc0 \\flags, $12 \n" +#endif + " irq_disable_hazard \n" + " .set pop \n" + " .endm \n"); + +#define raw_local_irq_restore(flags) \ +do { \ + unsigned long __tmp1; \ + \ + __asm__ __volatile__( \ + "raw_local_irq_restore\t%0" \ + : "=r" (__tmp1) \ + : "0" (flags) \ + : "memory"); \ +} while(0) + +static inline int raw_irqs_disabled_flags(unsigned long flags) +{ +#ifdef CONFIG_MIPS_MT_SMTC + /* + * SMTC model uses TCStatus.IXMT to disable interrupts for a thread/CPU + */ + return flags & 0x400; +#else + return !(flags & 1); +#endif +} + +#endif + +/* + * Do the CPU's IRQ-state tracing from assembly code. + */ +#ifdef CONFIG_TRACE_IRQFLAGS +# define TRACE_IRQS_ON \ + jal trace_hardirqs_on +# define TRACE_IRQS_OFF \ + jal trace_hardirqs_off +#else +# define TRACE_IRQS_ON +# define TRACE_IRQS_OFF +#endif + +#endif /* _ASM_IRQFLAGS_H */ diff --git a/include/asm-mips/mach-emma2rh/irq.h b/include/asm-mips/mach-emma2rh/irq.h new file mode 100644 index 000000000..bce64244b --- /dev/null +++ b/include/asm-mips/mach-emma2rh/irq.h @@ -0,0 +1,13 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003 by Ralf Baechle + */ +#ifndef __ASM_MACH_EMMA2RH_IRQ_H +#define __ASM_MACH_EMMA2RH_IRQ_H + +#define NR_IRQS 256 + +#endif /* __ASM_MACH_EMMA2RH_IRQ_H */ diff --git a/include/asm-mips/mach-excite/cpu-feature-overrides.h b/include/asm-mips/mach-excite/cpu-feature-overrides.h new file mode 100644 index 000000000..0d3185422 --- /dev/null +++ b/include/asm-mips/mach-excite/cpu-feature-overrides.h @@ -0,0 +1,40 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2004 Thomas Koeller <thomas.koeller@baslerweb.com> + */ +#ifndef __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H + +/* + * Basler eXcite has an RM9122 processor. + */ +#define cpu_has_watch 1 +#define cpu_has_mips16 0 +#define cpu_has_divec 0 +#define cpu_has_vce 0 +#define cpu_has_cache_cdex_p 0 +#define cpu_has_cache_cdex_s 0 +#define cpu_has_prefetch 1 +#define cpu_has_mcheck 0 +#define cpu_has_ejtag 0 + +#define cpu_has_llsc 1 +#define cpu_has_vtag_icache 0 +#define cpu_has_dc_aliases 0 +#define cpu_has_ic_fills_f_dc 0 +#define cpu_has_dsp 0 +#define cpu_icache_snoops_remote_store 0 + +#define cpu_has_nofpuex 0 +#define cpu_has_64bits 1 + +#define cpu_has_inclusive_pcaches 0 + +#define cpu_dcache_line_size() 32 +#define cpu_icache_line_size() 32 +#define cpu_scache_line_size() 32 + +#endif /* __ASM_MACH_EXCITE_CPU_FEATURE_OVERRIDES_H */ diff --git a/include/asm-mips/mach-excite/excite.h b/include/asm-mips/mach-excite/excite.h new file mode 100644 index 000000000..130bd4b8e --- /dev/null +++ b/include/asm-mips/mach-excite/excite.h @@ -0,0 +1,154 @@ +#ifndef __EXCITE_H__ +#define __EXCITE_H__ + +#include <linux/init.h> +#include <asm/addrspace.h> +#include <asm/types.h> + +#define EXCITE_CPU_EXT_CLOCK 100000000 + +#if !defined(__ASSEMBLER__) +void __init excite_kgdb_init(void); +void excite_procfs_init(void); +extern unsigned long memsize; +extern char modetty[]; +extern u32 unit_id; +#endif + +/* Base name for XICAP devices */ +#define XICAP_NAME "xicap_gpi" + +/* OCD register offsets */ +#define LKB0 0x0038 +#define LKB5 0x0128 +#define LKM5 0x012C +#define LKB7 0x0138 +#define LKM7 0x013c +#define LKB8 0x0140 +#define LKM8 0x0144 +#define LKB9 0x0148 +#define LKM9 0x014c +#define LKB10 0x0150 +#define LKM10 0x0154 +#define LKB11 0x0158 +#define LKM11 0x015c +#define LKB12 0x0160 +#define LKM12 0x0164 +#define LKB13 0x0168 +#define LKM13 0x016c +#define LDP0 0x0200 +#define LDP1 0x0210 +#define LDP2 0x0220 +#define LDP3 0x0230 +#define INTPIN0 0x0A40 +#define INTPIN1 0x0A44 +#define INTPIN2 0x0A48 +#define INTPIN3 0x0A4C +#define INTPIN4 0x0A50 +#define INTPIN5 0x0A54 +#define INTPIN6 0x0A58 +#define INTPIN7 0x0A5C + + + + +/* TITAN register offsets */ +#define CPRR 0x0004 +#define CPDSR 0x0008 +#define CPTC0R 0x000c +#define CPTC1R 0x0010 +#define CPCFG0 0x0020 +#define CPCFG1 0x0024 +#define CPDST0A 0x0028 +#define CPDST0B 0x002c +#define CPDST1A 0x0030 +#define CPDST1B 0x0034 +#define CPXDSTA 0x0038 +#define CPXDSTB 0x003c +#define CPXCISRA 0x0048 +#define CPXCISRB 0x004c +#define CPGIG0ER 0x0050 +#define CPGIG1ER 0x0054 +#define CPGRWL 0x0068 +#define CPURSLMT 0x00f8 +#define UACFG 0x0200 +#define UAINTS 0x0204 +#define SDRXFCIE 0x4828 +#define SDTXFCIE 0x4928 +#define INTP0Status0 0x1B00 +#define INTP0Mask0 0x1B04 +#define INTP0Set0 0x1B08 +#define INTP0Clear0 0x1B0C +#define GXCFG 0x5000 +#define GXDMADRPFX 0x5018 +#define GXDMA_DESCADR 0x501c +#define GXCH0TDESSTRT 0x5054 + +/* IRQ definitions */ +#define NMICONFIG 0xac0 +#define TITAN_MSGINT 0xc4 +#define TITAN_IRQ ((TITAN_MSGINT / 0x20) + 2) +#define FPGA0_MSGINT 0x5a +#define FPGA0_IRQ ((FPGA0_MSGINT / 0x20) + 2) +#define FPGA1_MSGINT 0x7b +#define FPGA1_IRQ ((FPGA1_MSGINT / 0x20) + 2) +#define PHY_MSGINT 0x9c +#define PHY_IRQ ((PHY_MSGINT / 0x20) + 2) + +#if defined(CONFIG_BASLER_EXCITE_PROTOTYPE) +/* Pre-release units used interrupt pin #9 */ +#define USB_IRQ 11 +#else +/* Re-designed units use interrupt pin #1 */ +#define USB_MSGINT 0x39 +#define USB_IRQ ((USB_MSGINT / 0x20) + 2) +#endif +#define TIMER_IRQ 12 + + +/* Device address ranges */ +#define EXCITE_OFFS_OCD 0x1fffc000 +#define EXCITE_SIZE_OCD (16 * 1024) +#define EXCITE_PHYS_OCD CPHYSADDR(EXCITE_OFFS_OCD) +#define EXCITE_ADDR_OCD CKSEG1ADDR(EXCITE_OFFS_OCD) + +#define EXCITE_OFFS_SCRAM 0x1fffa000 +#define EXCITE_SIZE_SCRAM (8 << 10) +#define EXCITE_PHYS_SCRAM CPHYSADDR(EXCITE_OFFS_SCRAM) +#define EXCITE_ADDR_SCRAM CKSEG1ADDR(EXCITE_OFFS_SCRAM) + +#define EXCITE_OFFS_PCI_IO 0x1fff8000 +#define EXCITE_SIZE_PCI_IO (8 << 10) +#define EXCITE_PHYS_PCI_IO CPHYSADDR(EXCITE_OFFS_PCI_IO) +#define EXCITE_ADDR_PCI_IO CKSEG1ADDR(EXCITE_OFFS_PCI_IO) + +#define EXCITE_OFFS_TITAN 0x1fff0000 +#define EXCITE_SIZE_TITAN (32 << 10) +#define EXCITE_PHYS_TITAN CPHYSADDR(EXCITE_OFFS_TITAN) +#define EXCITE_ADDR_TITAN CKSEG1ADDR(EXCITE_OFFS_TITAN) + +#define EXCITE_OFFS_PCI_MEM 0x1ffe0000 +#define EXCITE_SIZE_PCI_MEM (64 << 10) +#define EXCITE_PHYS_PCI_MEM CPHYSADDR(EXCITE_OFFS_PCI_MEM) +#define EXCITE_ADDR_PCI_MEM CKSEG1ADDR(EXCITE_OFFS_PCI_MEM) + +#define EXCITE_OFFS_FPGA 0x1ffdc000 +#define EXCITE_SIZE_FPGA (16 << 10) +#define EXCITE_PHYS_FPGA CPHYSADDR(EXCITE_OFFS_FPGA) +#define EXCITE_ADDR_FPGA CKSEG1ADDR(EXCITE_OFFS_FPGA) + +#define EXCITE_OFFS_NAND 0x1ffd8000 +#define EXCITE_SIZE_NAND (16 << 10) +#define EXCITE_PHYS_NAND CPHYSADDR(EXCITE_OFFS_NAND) +#define EXCITE_ADDR_NAND CKSEG1ADDR(EXCITE_OFFS_NAND) + +#define EXCITE_OFFS_BOOTROM 0x1f000000 +#define EXCITE_SIZE_BOOTROM (8 << 20) +#define EXCITE_PHYS_BOOTROM CPHYSADDR(EXCITE_OFFS_BOOTROM) +#define EXCITE_ADDR_BOOTROM CKSEG1ADDR(EXCITE_OFFS_BOOTROM) + +/* FPGA address offsets */ +#define EXCITE_FPGA_DPR 0x0104 /* dual-ported ram */ +#define EXCITE_FPGA_SYSCTL 0x0200 /* system control register block */ + +#endif /* __EXCITE_H__ */ diff --git a/include/asm-mips/mach-excite/excite_nandflash.h b/include/asm-mips/mach-excite/excite_nandflash.h new file mode 100644 index 000000000..c4cf61406 --- /dev/null +++ b/include/asm-mips/mach-excite/excite_nandflash.h @@ -0,0 +1,7 @@ +#ifndef __EXCITE_NANDFLASH_H__ +#define __EXCITE_NANDFLASH_H__ + +/* Resource names */ +#define EXCITE_NANDFLASH_RESOURCE_REGS "excite_nandflash_regs" + +#endif /* __EXCITE_NANDFLASH_H__ */ diff --git a/include/asm-mips/mach-excite/rm9k_eth.h b/include/asm-mips/mach-excite/rm9k_eth.h new file mode 100644 index 000000000..94705a46f --- /dev/null +++ b/include/asm-mips/mach-excite/rm9k_eth.h @@ -0,0 +1,23 @@ +#if !defined(__RM9K_ETH_H__) +#define __RM9K_ETH_H__ + +#define RM9K_GE_NAME "rm9k_ge" + +/* Resource names */ +#define RM9K_GE_RESOURCE_MAC "rm9k_ge_mac" +#define RM9K_GE_RESOURCE_MSTAT "rm9k_ge_mstat" +#define RM9K_GE_RESOURCE_PKTPROC "rm9k_ge_pktproc" +#define RM9K_GE_RESOURCE_XDMA "rm9k_ge_xdma" +#define RM9K_GE_RESOURCE_FIFO_RX "rm9k_ge_fifo_rx" +#define RM9K_GE_RESOURCE_FIFO_TX "rm9k_ge_fifo_tx" +#define RM9K_GE_RESOURCE_FIFOMEM_RX "rm9k_ge_fifo_memory_rx" +#define RM9K_GE_RESOURCE_FIFOMEM_TX "rm9k_ge_fifo_memory_tx" +#define RM9K_GE_RESOURCE_PHY "rm9k_ge_phy" +#define RM9K_GE_RESOURCE_DMADESC_RX "rm9k_ge_dmadesc_rx" +#define RM9K_GE_RESOURCE_DMADESC_TX "rm9k_ge_dmadesc_tx" +#define RM9K_GE_RESOURCE_IRQ_MAIN "rm9k_ge_irq_main" +#define RM9K_GE_RESOURCE_IRQ_PHY "rm9k_ge_irq_phy" +#define RM9K_GE_RESOURCE_GPI_SLICE "rm9k_ge_gpi_slice" +#define RM9K_GE_RESOURCE_MDIO_CHANNEL "rm9k_ge_mdio_channel" + +#endif /* !defined(__RM9K_ETH_H__) */ diff --git a/include/asm-mips/mach-excite/rm9k_wdt.h b/include/asm-mips/mach-excite/rm9k_wdt.h new file mode 100644 index 000000000..3fa3c08d2 --- /dev/null +++ b/include/asm-mips/mach-excite/rm9k_wdt.h @@ -0,0 +1,12 @@ +#ifndef __RM9K_WDT_H__ +#define __RM9K_WDT_H__ + +/* Device name */ +#define WDT_NAME "wdt_gpi" + +/* Resource names */ +#define WDT_RESOURCE_REGS "excite_watchdog_regs" +#define WDT_RESOURCE_IRQ "excite_watchdog_irq" +#define WDT_RESOURCE_COUNTER "excite_watchdog_counter" + +#endif /* __RM9K_WDT_H__ */ diff --git a/include/asm-mips/mach-excite/rm9k_xicap.h b/include/asm-mips/mach-excite/rm9k_xicap.h new file mode 100644 index 000000000..009577734 --- /dev/null +++ b/include/asm-mips/mach-excite/rm9k_xicap.h @@ -0,0 +1,16 @@ +#ifndef __EXCITE_XICAP_H__ +#define __EXCITE_XICAP_H__ + + +/* Resource names */ +#define XICAP_RESOURCE_FIFO_RX "xicap_fifo_rx" +#define XICAP_RESOURCE_FIFO_TX "xicap_fifo_tx" +#define XICAP_RESOURCE_XDMA "xicap_xdma" +#define XICAP_RESOURCE_DMADESC "xicap_dmadesc" +#define XICAP_RESOURCE_PKTPROC "xicap_pktproc" +#define XICAP_RESOURCE_IRQ "xicap_irq" +#define XICAP_RESOURCE_GPI_SLICE "xicap_gpi_slice" +#define XICAP_RESOURCE_FIFO_BLK "xicap_fifo_blocks" +#define XICAP_RESOURCE_PKT_STREAM "xicap_pkt_stream" + +#endif /* __EXCITE_XICAP_H__ */ diff --git a/include/asm-mips/mach-wrppmc/mach-gt64120.h b/include/asm-mips/mach-wrppmc/mach-gt64120.h new file mode 100644 index 000000000..ba9205a04 --- /dev/null +++ b/include/asm-mips/mach-wrppmc/mach-gt64120.h @@ -0,0 +1,84 @@ +/* + * This is a direct copy of the ev96100.h file, with a global + * search and replace. The numbers are the same. + * + * The reason I'm duplicating this is so that the 64120/96100 + * defines won't be confusing in the source code. + */ +#ifndef __ASM_MIPS_GT64120_H +#define __ASM_MIPS_GT64120_H + +/* + * This is the CPU physical memory map of PPMC Board: + * + * 0x00000000-0x03FFFFFF - 64MB SDRAM (SCS[0]#) + * 0x1C000000-0x1C000000 - LED (CS0) + * 0x1C800000-0x1C800007 - UART 16550 port (CS1) + * 0x1F000000-0x1F000000 - MailBox (CS3) + * 0x1FC00000-0x20000000 - 4MB Flash (BOOT CS) + */ + +#define WRPPMC_SDRAM_SCS0_BASE 0x00000000 +#define WRPPMC_SDRAM_SCS0_SIZE 0x04000000 + +#define WRPPMC_UART16550_BASE 0x1C800000 +#define WRPPMC_UART16550_CLOCK 3686400 /* 3.68MHZ */ + +#define WRPPMC_LED_BASE 0x1C000000 +#define WRPPMC_MBOX_BASE 0x1F000000 + +#define WRPPMC_BOOTROM_BASE 0x1FC00000 +#define WRPPMC_BOOTROM_SIZE 0x00400000 /* 4M Flash */ + +#define WRPPMC_MIPS_TIMER_IRQ 7 /* MIPS compare/count timer interrupt */ +#define WRPPMC_UART16550_IRQ 6 +#define WRPPMC_PCI_INTA_IRQ 3 + +/* + * PCI Bus I/O and Memory resources allocation + * + * NOTE: We only have PCI_0 hose interface + */ +#define GT_PCI_MEM_BASE 0x13000000UL +#define GT_PCI_MEM_SIZE 0x02000000UL +#define GT_PCI_IO_BASE 0x11000000UL +#define GT_PCI_IO_SIZE 0x02000000UL +#define GT_ISA_IO_BASE PCI_IO_BASE + +/* + * PCI interrupts will come in on either the INTA or INTD interrups lines, + * which are mapped to the #2 and #5 interrupt pins of the MIPS. On our + * boards, they all either come in on IntD or they all come in on IntA, they + * aren't mixed. There can be numerous PCI interrupts, so we keep a list of the + * "requested" interrupt numbers and go through the list whenever we get an + * IntA/D. + * + * Interrupts < 8 are directly wired to the processor; PCI INTA is 8 and + * INTD is 11. + */ +#define GT_TIMER 4 +#define GT_INTA 2 +#define GT_INTD 5 + +#ifndef __ASSEMBLY__ + +/* + * GT64120 internal register space base address + */ +extern unsigned long gt64120_base; + +#define GT64120_BASE (gt64120_base) + +/* define WRPPMC_EARLY_DEBUG to enable early output something to UART */ +#undef WRPPMC_EARLY_DEBUG + +#ifdef WRPPMC_EARLY_DEBUG +extern void wrppmc_led_on(int mask); +extern void wrppmc_led_off(int mask); +extern void wrppmc_early_printk(const char *fmt, ...); +#else +#define wrppmc_early_printk(fmt, ...) do {} while (0) +#endif /* WRPPMC_EARLY_DEBUG */ + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_MIPS_GT64120_H */ diff --git a/include/asm-mips/rm9k-ocd.h b/include/asm-mips/rm9k-ocd.h new file mode 100644 index 000000000..b0b80d9ec --- /dev/null +++ b/include/asm-mips/rm9k-ocd.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2004 by Basler Vision Technologies AG + * Author: Thomas Koeller <thomas.koeller@baslerweb.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined(_ASM_RM9K_OCD_H) +#define _ASM_RM9K_OCD_H + +#include <linux/types.h> +#include <linux/spinlock.h> +#include <asm/io.h> + +extern volatile void __iomem * const ocd_base; +extern volatile void __iomem * const titan_base; + +#define ocd_addr(__x__) (ocd_base + (__x__)) +#define titan_addr(__x__) (titan_base + (__x__)) +#define scram_addr(__x__) (scram_base + (__x__)) + +/* OCD register access */ +#define ocd_readl(__offs__) __raw_readl(ocd_addr(__offs__)) +#define ocd_readw(__offs__) __raw_readw(ocd_addr(__offs__)) +#define ocd_readb(__offs__) __raw_readb(ocd_addr(__offs__)) +#define ocd_writel(__val__, __offs__) \ + __raw_writel((__val__), ocd_addr(__offs__)) +#define ocd_writew(__val__, __offs__) \ + __raw_writew((__val__), ocd_addr(__offs__)) +#define ocd_writeb(__val__, __offs__) \ + __raw_writeb((__val__), ocd_addr(__offs__)) + +/* TITAN register access - 32 bit-wide only */ +#define titan_readl(__offs__) __raw_readl(titan_addr(__offs__)) +#define titan_writel(__val__, __offs__) \ + __raw_writel((__val__), titan_addr(__offs__)) + +/* Protect access to shared TITAN registers */ +extern spinlock_t titan_lock; +extern int titan_irqflags; +#define lock_titan_regs() spin_lock_irqsave(&titan_lock, titan_irqflags) +#define unlock_titan_regs() spin_unlock_irqrestore(&titan_lock, titan_irqflags) + +#endif /* !defined(_ASM_RM9K_OCD_H) */ diff --git a/include/asm-mips/sn/fru.h b/include/asm-mips/sn/fru.h new file mode 100644 index 000000000..b3e360672 --- /dev/null +++ b/include/asm-mips/sn/fru.h @@ -0,0 +1,44 @@ +/* + * 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. + * + * Derived from IRIX <sys/SN/SN0/sn0_fru.h> + * + * Copyright (C) 1992 - 1997, 1999 Silcon Graphics, Inc. + * Copyright (C) 1999, 2006 Ralf Baechle (ralf@linux-mips) + */ +#ifndef __ASM_SN_FRU_H +#define __ASM_SN_FRU_H + +#define MAX_DIMMS 8 /* max # of dimm banks */ +#define MAX_PCIDEV 8 /* max # of pci devices on a pci bus */ + +typedef unsigned char confidence_t; + +typedef struct kf_mem_s { + confidence_t km_confidence; /* confidence level that the memory is bad + * is this necessary ? + */ + confidence_t km_dimm[MAX_DIMMS]; + /* confidence level that dimm[i] is bad + *I think this is the right number + */ + +} kf_mem_t; + +typedef struct kf_cpu_s { + confidence_t kc_confidence; /* confidence level that cpu is bad */ + confidence_t kc_icache; /* confidence level that instr. cache is bad */ + confidence_t kc_dcache; /* confidence level that data cache is bad */ + confidence_t kc_scache; /* confidence level that sec. cache is bad */ + confidence_t kc_sysbus; /* confidence level that sysad/cmd/state bus is bad */ +} kf_cpu_t; + +typedef struct kf_pci_bus_s { + confidence_t kpb_belief; /* confidence level that the pci bus is bad */ + confidence_t kpb_pcidev_belief[MAX_PCIDEV]; + /* confidence level that the pci dev is bad */ +} kf_pci_bus_t; + +#endif /* __ASM_SN_FRU_H */ diff --git a/include/asm-mips/vr41xx/irq.h b/include/asm-mips/vr41xx/irq.h new file mode 100644 index 000000000..d315dfbc0 --- /dev/null +++ b/include/asm-mips/vr41xx/irq.h @@ -0,0 +1,101 @@ +/* + * include/asm-mips/vr41xx/irq.h + * + * Interrupt numbers for NEC VR4100 series. + * + * Copyright (C) 1999 Michael Klar + * Copyright (C) 2001, 2002 Paul Mundt + * Copyright (C) 2002 MontaVista Software, Inc. + * Copyright (C) 2002 TimeSys Corp. + * Copyright (C) 2003-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#ifndef __NEC_VR41XX_IRQ_H +#define __NEC_VR41XX_IRQ_H + +/* + * CPU core Interrupt Numbers + */ +#define MIPS_CPU_IRQ_BASE 0 +#define MIPS_CPU_IRQ(x) (MIPS_CPU_IRQ_BASE + (x)) +#define MIPS_SOFTINT0_IRQ MIPS_CPU_IRQ(0) +#define MIPS_SOFTINT1_IRQ MIPS_CPU_IRQ(1) +#define INT0_IRQ MIPS_CPU_IRQ(2) +#define INT1_IRQ MIPS_CPU_IRQ(3) +#define INT2_IRQ MIPS_CPU_IRQ(4) +#define INT3_IRQ MIPS_CPU_IRQ(5) +#define INT4_IRQ MIPS_CPU_IRQ(6) +#define TIMER_IRQ MIPS_CPU_IRQ(7) + +/* + * SYINT1 Interrupt Numbers + */ +#define SYSINT1_IRQ_BASE 8 +#define SYSINT1_IRQ(x) (SYSINT1_IRQ_BASE + (x)) +#define BATTRY_IRQ SYSINT1_IRQ(0) +#define POWER_IRQ SYSINT1_IRQ(1) +#define RTCLONG1_IRQ SYSINT1_IRQ(2) +#define ELAPSEDTIME_IRQ SYSINT1_IRQ(3) +/* RFU */ +#define PIU_IRQ SYSINT1_IRQ(5) +#define AIU_IRQ SYSINT1_IRQ(6) +#define KIU_IRQ SYSINT1_IRQ(7) +#define GIUINT_IRQ SYSINT1_IRQ(8) +#define SIU_IRQ SYSINT1_IRQ(9) +#define BUSERR_IRQ SYSINT1_IRQ(10) +#define SOFTINT_IRQ SYSINT1_IRQ(11) +#define CLKRUN_IRQ SYSINT1_IRQ(12) +#define DOZEPIU_IRQ SYSINT1_IRQ(13) +#define SYSINT1_IRQ_LAST DOZEPIU_IRQ + +/* + * SYSINT2 Interrupt Numbers + */ +#define SYSINT2_IRQ_BASE 24 +#define SYSINT2_IRQ(x) (SYSINT2_IRQ_BASE + (x)) +#define RTCLONG2_IRQ SYSINT2_IRQ(0) +#define LED_IRQ SYSINT2_IRQ(1) +#define HSP_IRQ SYSINT2_IRQ(2) +#define TCLOCK_IRQ SYSINT2_IRQ(3) +#define FIR_IRQ SYSINT2_IRQ(4) +#define CEU_IRQ SYSINT2_IRQ(4) /* same number as FIR_IRQ */ +#define DSIU_IRQ SYSINT2_IRQ(5) +#define PCI_IRQ SYSINT2_IRQ(6) +#define SCU_IRQ SYSINT2_IRQ(7) +#define CSI_IRQ SYSINT2_IRQ(8) +#define BCU_IRQ SYSINT2_IRQ(9) +#define ETHERNET_IRQ SYSINT2_IRQ(10) +#define SYSINT2_IRQ_LAST ETHERNET_IRQ + +/* + * GIU Interrupt Numbers + */ +#define GIU_IRQ_BASE 40 +#define GIU_IRQ(x) (GIU_IRQ_BASE + (x)) /* IRQ 40-71 */ +#define GIU_IRQ_LAST GIU_IRQ(31) + +/* + * VRC4173 Interrupt Numbers + */ +#define VRC4173_IRQ_BASE 72 +#define VRC4173_IRQ(x) (VRC4173_IRQ_BASE + (x)) +#define VRC4173_USB_IRQ VRC4173_IRQ(0) +#define VRC4173_PCMCIA2_IRQ VRC4173_IRQ(1) +#define VRC4173_PCMCIA1_IRQ VRC4173_IRQ(2) +#define VRC4173_PS2CH2_IRQ VRC4173_IRQ(3) +#define VRC4173_PS2CH1_IRQ VRC4173_IRQ(4) +#define VRC4173_PIU_IRQ VRC4173_IRQ(5) +#define VRC4173_AIU_IRQ VRC4173_IRQ(6) +#define VRC4173_KIU_IRQ VRC4173_IRQ(7) +#define VRC4173_GIU_IRQ VRC4173_IRQ(8) +#define VRC4173_AC97_IRQ VRC4173_IRQ(9) +#define VRC4173_AC97INT1_IRQ VRC4173_IRQ(10) +/* RFU */ +#define VRC4173_DOZEPIU_IRQ VRC4173_IRQ(13) +#define VRC4173_IRQ_LAST VRC4173_DOZEPIU_IRQ + +#endif /* __NEC_VR41XX_IRQ_H */ diff --git a/include/asm-parisc/Kbuild b/include/asm-parisc/Kbuild new file mode 100644 index 000000000..c68e1680d --- /dev/null +++ b/include/asm-parisc/Kbuild @@ -0,0 +1 @@ +include include/asm-generic/Kbuild.asm diff --git a/include/asm-powerpc/Kbuild b/include/asm-powerpc/Kbuild new file mode 100644 index 000000000..982784995 --- /dev/null +++ b/include/asm-powerpc/Kbuild @@ -0,0 +1,41 @@ +include include/asm-generic/Kbuild.asm + +header-y += auxvec.h +header-y += ioctls.h +header-y += mman.h +header-y += sembuf.h +header-y += siginfo.h +header-y += stat.h +header-y += errno.h +header-y += ipcbuf.h +header-y += msgbuf.h +header-y += shmbuf.h +header-y += socket.h +header-y += termbits.h +header-y += fcntl.h +header-y += ipc.h +header-y += poll.h +header-y += shmparam.h +header-y += sockios.h +header-y += ucontext.h +header-y += ioctl.h +header-y += linkage.h +header-y += resource.h +header-y += sigcontext.h +header-y += statfs.h + +unifdef-y += a.out.h +unifdef-y += asm-compat.h +unifdef-y += bootx.h +unifdef-y += byteorder.h +unifdef-y += cputable.h +unifdef-y += elf.h +unifdef-y += nvram.h +unifdef-y += param.h +unifdef-y += posix_types.h +unifdef-y += ptrace.h +unifdef-y += seccomp.h +unifdef-y += signal.h +unifdef-y += termios.h +unifdef-y += types.h +unifdef-y += unistd.h diff --git a/include/asm-powerpc/immap_86xx.h b/include/asm-powerpc/immap_86xx.h new file mode 100644 index 000000000..d905b6622 --- /dev/null +++ b/include/asm-powerpc/immap_86xx.h @@ -0,0 +1,199 @@ +/* + * MPC86xx Internal Memory Map + * + * Author: Jeff Brown + * + * Copyright 2004 Freescale Semiconductor, Inc + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __ASM_POWERPC_IMMAP_86XX_H__ +#define __ASM_POWERPC_IMMAP_86XX_H__ +#ifdef __KERNEL__ + +/* Eventually this should define all the IO block registers in 86xx */ + +/* PCI Registers */ +typedef struct ccsr_pci { + uint cfg_addr; /* 0x.000 - PCI Configuration Address Register */ + uint cfg_data; /* 0x.004 - PCI Configuration Data Register */ + uint int_ack; /* 0x.008 - PCI Interrupt Acknowledge Register */ + char res1[3060]; + uint potar0; /* 0x.c00 - PCI Outbound Transaction Address Register 0 */ + uint potear0; /* 0x.c04 - PCI Outbound Translation Extended Address Register 0 */ + uint powbar0; /* 0x.c08 - PCI Outbound Window Base Address Register 0 */ + char res2[4]; + uint powar0; /* 0x.c10 - PCI Outbound Window Attributes Register 0 */ + char res3[12]; + uint potar1; /* 0x.c20 - PCI Outbound Transaction Address Register 1 */ + uint potear1; /* 0x.c24 - PCI Outbound Translation Extended Address Register 1 */ + uint powbar1; /* 0x.c28 - PCI Outbound Window Base Address Register 1 */ + char res4[4]; + uint powar1; /* 0x.c30 - PCI Outbound Window Attributes Register 1 */ + char res5[12]; + uint potar2; /* 0x.c40 - PCI Outbound Transaction Address Register 2 */ + uint potear2; /* 0x.c44 - PCI Outbound Translation Extended Address Register 2 */ + uint powbar2; /* 0x.c48 - PCI Outbound Window Base Address Register 2 */ + char res6[4]; + uint powar2; /* 0x.c50 - PCI Outbound Window Attributes Register 2 */ + char res7[12]; + uint potar3; /* 0x.c60 - PCI Outbound Transaction Address Register 3 */ + uint potear3; /* 0x.c64 - PCI Outbound Translation Extended Address Register 3 */ + uint powbar3; /* 0x.c68 - PCI Outbound Window Base Address Register 3 */ + char res8[4]; + uint powar3; /* 0x.c70 - PCI Outbound Window Attributes Register 3 */ + char res9[12]; + uint potar4; /* 0x.c80 - PCI Outbound Transaction Address Register 4 */ + uint potear4; /* 0x.c84 - PCI Outbound Translation Extended Address Register 4 */ + uint powbar4; /* 0x.c88 - PCI Outbound Window Base Address Register 4 */ + char res10[4]; + uint powar4; /* 0x.c90 - PCI Outbound Window Attributes Register 4 */ + char res11[268]; + uint pitar3; /* 0x.da0 - PCI Inbound Translation Address Register 3 */ + char res12[4]; + uint piwbar3; /* 0x.da8 - PCI Inbound Window Base Address Register 3 */ + uint piwbear3; /* 0x.dac - PCI Inbound Window Base Extended Address Register 3 */ + uint piwar3; /* 0x.db0 - PCI Inbound Window Attributes Register 3 */ + char res13[12]; + uint pitar2; /* 0x.dc0 - PCI Inbound Translation Address Register 2 */ + char res14[4]; + uint piwbar2; /* 0x.dc8 - PCI Inbound Window Base Address Register 2 */ + uint piwbear2; /* 0x.dcc - PCI Inbound Window Base Extended Address Register 2 */ + uint piwar2; /* 0x.dd0 - PCI Inbound Window Attributes Register 2 */ + char res15[12]; + uint pitar1; /* 0x.de0 - PCI Inbound Translation Address Register 1 */ + char res16[4]; + uint piwbar1; /* 0x.de8 - PCI Inbound Window Base Address Register 1 */ + char res17[4]; + uint piwar1; /* 0x.df0 - PCI Inbound Window Attributes Register 1 */ + char res18[12]; + uint err_dr; /* 0x.e00 - PCI Error Detect Register */ + uint err_cap_dr; /* 0x.e04 - PCI Error Capture Disable Register */ + uint err_en; /* 0x.e08 - PCI Error Enable Register */ + uint err_attrib; /* 0x.e0c - PCI Error Attributes Capture Register */ + uint err_addr; /* 0x.e10 - PCI Error Address Capture Register */ + uint err_ext_addr; /* 0x.e14 - PCI Error Extended Address Capture Register */ + uint err_dl; /* 0x.e18 - PCI Error Data Low Capture Register */ + uint err_dh; /* 0x.e1c - PCI Error Data High Capture Register */ + uint gas_timr; /* 0x.e20 - PCI Gasket Timer Register */ + uint pci_timr; /* 0x.e24 - PCI Timer Register */ + char res19[472]; +} ccsr_pci_t; + +/* PCI Express Registers */ +typedef struct ccsr_pex { + uint pex_config_addr; /* 0x.000 - PCI Express Configuration Address Register */ + uint pex_config_data; /* 0x.004 - PCI Express Configuration Data Register */ + char res1[4]; + uint pex_otb_cpl_tor; /* 0x.00c - PCI Express Outbound completion timeout register */ + uint pex_conf_tor; /* 0x.010 - PCI Express configuration timeout register */ + char res2[12]; + uint pex_pme_mes_dr; /* 0x.020 - PCI Express PME and message detect register */ + uint pex_pme_mes_disr; /* 0x.024 - PCI Express PME and message disable register */ + uint pex_pme_mes_ier; /* 0x.028 - PCI Express PME and message interrupt enable register */ + uint pex_pmcr; /* 0x.02c - PCI Express power management command register */ + char res3[3024]; + uint pexotar0; /* 0x.c00 - PCI Express outbound translation address register 0 */ + uint pexotear0; /* 0x.c04 - PCI Express outbound translation extended address register 0*/ + char res4[8]; + uint pexowar0; /* 0x.c10 - PCI Express outbound window attributes register 0*/ + char res5[12]; + uint pexotar1; /* 0x.c20 - PCI Express outbound translation address register 1 */ + uint pexotear1; /* 0x.c24 - PCI Express outbound translation extended address register 1*/ + uint pexowbar1; /* 0x.c28 - PCI Express outbound window base address register 1*/ + char res6[4]; + uint pexowar1; /* 0x.c30 - PCI Express outbound window attributes register 1*/ + char res7[12]; + uint pexotar2; /* 0x.c40 - PCI Express outbound translation address register 2 */ + uint pexotear2; /* 0x.c44 - PCI Express outbound translation extended address register 2*/ + uint pexowbar2; /* 0x.c48 - PCI Express outbound window base address register 2*/ + char res8[4]; + uint pexowar2; /* 0x.c50 - PCI Express outbound window attributes register 2*/ + char res9[12]; + uint pexotar3; /* 0x.c60 - PCI Express outbound translation address register 3 */ + uint pexotear3; /* 0x.c64 - PCI Express outbound translation extended address register 3*/ + uint pexowbar3; /* 0x.c68 - PCI Express outbound window base address register 3*/ + char res10[4]; + uint pexowar3; /* 0x.c70 - PCI Express outbound window attributes register 3*/ + char res11[12]; + uint pexotar4; /* 0x.c80 - PCI Express outbound translation address register 4 */ + uint pexotear4; /* 0x.c84 - PCI Express outbound translation extended address register 4*/ + uint pexowbar4; /* 0x.c88 - PCI Express outbound window base address register 4*/ + char res12[4]; + uint pexowar4; /* 0x.c90 - PCI Express outbound window attributes register 4*/ + char res13[12]; + char res14[256]; + uint pexitar3; /* 0x.da0 - PCI Express inbound translation address register 3 */ + char res15[4]; + uint pexiwbar3; /* 0x.da8 - PCI Express inbound window base address register 3 */ + uint pexiwbear3; /* 0x.dac - PCI Express inbound window base extended address register 3 */ + uint pexiwar3; /* 0x.db0 - PCI Express inbound window attributes register 3 */ + char res16[12]; + uint pexitar2; /* 0x.dc0 - PCI Express inbound translation address register 2 */ + char res17[4]; + uint pexiwbar2; /* 0x.dc8 - PCI Express inbound window base address register 2 */ + uint pexiwbear2; /* 0x.dcc - PCI Express inbound window base extended address register 2 */ + uint pexiwar2; /* 0x.dd0 - PCI Express inbound window attributes register 2 */ + char res18[12]; + uint pexitar1; /* 0x.de0 - PCI Express inbound translation address register 2 */ + char res19[4]; + uint pexiwbar1; /* 0x.de8 - PCI Express inbound window base address register 2 */ + uint pexiwbear1; /* 0x.dec - PCI Express inbound window base extended address register 2 */ + uint pexiwar1; /* 0x.df0 - PCI Express inbound window attributes register 2 */ + char res20[12]; + uint pex_err_dr; /* 0x.e00 - PCI Express error detect register */ + char res21[4]; + uint pex_err_en; /* 0x.e08 - PCI Express error interrupt enable register */ + char res22[4]; + uint pex_err_disr; /* 0x.e10 - PCI Express error disable register */ + char res23[12]; + uint pex_err_cap_stat; /* 0x.e20 - PCI Express error capture status register */ + char res24[4]; + uint pex_err_cap_r0; /* 0x.e28 - PCI Express error capture register 0 */ + uint pex_err_cap_r1; /* 0x.e2c - PCI Express error capture register 0 */ + uint pex_err_cap_r2; /* 0x.e30 - PCI Express error capture register 0 */ + uint pex_err_cap_r3; /* 0x.e34 - PCI Express error capture register 0 */ +} ccsr_pex_t; + +/* Global Utility Registers */ +typedef struct ccsr_guts { + uint porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */ + uint porbmsr; /* 0x.0004 - POR Boot Mode Status Register */ + uint porimpscr; /* 0x.0008 - POR I/O Impedance Status and Control Register */ + uint pordevsr; /* 0x.000c - POR I/O Device Status Register */ + uint pordbgmsr; /* 0x.0010 - POR Debug Mode Status Register */ + char res1[12]; + uint gpporcr; /* 0x.0020 - General-Purpose POR Configuration Register */ + char res2[12]; + uint gpiocr; /* 0x.0030 - GPIO Control Register */ + char res3[12]; + uint gpoutdr; /* 0x.0040 - General-Purpose Output Data Register */ + char res4[12]; + uint gpindr; /* 0x.0050 - General-Purpose Input Data Register */ + char res5[12]; + uint pmuxcr; /* 0x.0060 - Alternate Function Signal Multiplex Control */ + char res6[12]; + uint devdisr; /* 0x.0070 - Device Disable Control */ + char res7[12]; + uint powmgtcsr; /* 0x.0080 - Power Management Status and Control Register */ + char res8[12]; + uint mcpsumr; /* 0x.0090 - Machine Check Summary Register */ + char res9[12]; + uint pvr; /* 0x.00a0 - Processor Version Register */ + uint svr; /* 0x.00a4 - System Version Register */ + char res10[3416]; + uint clkocr; /* 0x.0e00 - Clock Out Select Register */ + char res11[12]; + uint ddrdllcr; /* 0x.0e10 - DDR DLL Control Register */ + char res12[12]; + uint lbcdllcr; /* 0x.0e20 - LBC DLL Control Register */ + char res13[61916]; +} ccsr_guts_t; + +#endif /* __ASM_POWERPC_IMMAP_86XX_H__ */ +#endif /* __KERNEL__ */ diff --git a/include/asm-powerpc/irqflags.h b/include/asm-powerpc/irqflags.h new file mode 100644 index 000000000..7970cbaea --- /dev/null +++ b/include/asm-powerpc/irqflags.h @@ -0,0 +1,31 @@ +/* + * include/asm-powerpc/irqflags.h + * + * IRQ flags handling + * + * This file gets included from lowlevel asm headers too, to provide + * wrapped versions of the local_irq_*() APIs, based on the + * raw_local_irq_*() macros from the lowlevel headers. + */ +#ifndef _ASM_IRQFLAGS_H +#define _ASM_IRQFLAGS_H + +/* + * Get definitions for raw_local_save_flags(x), etc. + */ +#include <asm-powerpc/hw_irq.h> + +/* + * Do the CPU's IRQ-state tracing from assembly code. We call a + * C function, so save all the C-clobbered registers: + */ +#ifdef CONFIG_TRACE_IRQFLAGS + +#error No support on PowerPC yet for CONFIG_TRACE_IRQFLAGS + +#else +# define TRACE_IRQS_ON +# define TRACE_IRQS_OFF +#endif + +#endif diff --git a/include/asm-powerpc/iseries/iommu.h b/include/asm-powerpc/iseries/iommu.h new file mode 100644 index 000000000..0edbfe10c --- /dev/null +++ b/include/asm-powerpc/iseries/iommu.h @@ -0,0 +1,35 @@ +#ifndef _ASM_POWERPC_ISERIES_IOMMU_H +#define _ASM_POWERPC_ISERIES_IOMMU_H + +/* + * Copyright (C) 2005 Stephen Rothwell, IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the: + * Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA + */ + +struct device_node; +struct iommu_table; + +/* Creates table for an individual device node */ +extern void iommu_devnode_init_iSeries(struct device_node *dn); + +/* Get table parameters from HV */ +extern void iommu_table_getparms_iSeries(unsigned long busno, + unsigned char slotno, unsigned char virtbus, + struct iommu_table *tbl); + +#endif /* _ASM_POWERPC_ISERIES_IOMMU_H */ diff --git a/include/asm-powerpc/mpc86xx.h b/include/asm-powerpc/mpc86xx.h new file mode 100644 index 000000000..b85df45b1 --- /dev/null +++ b/include/asm-powerpc/mpc86xx.h @@ -0,0 +1,39 @@ +/* + * MPC86xx definitions + * + * Author: Jeff Brown + * + * Copyright 2004 Freescale Semiconductor, Inc + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifdef __KERNEL__ +#ifndef __ASM_POWERPC_MPC86xx_H__ +#define __ASM_POWERPC_MPC86xx_H__ + +#include <asm/mmu.h> + +#ifdef CONFIG_PPC_86xx + +#define _IO_BASE isa_io_base +#define _ISA_MEM_BASE isa_mem_base +#ifdef CONFIG_PCI +#define PCI_DRAM_OFFSET pci_dram_offset +#endif + +#define CPU0_BOOT_RELEASE 0x01000000 +#define CPU1_BOOT_RELEASE 0x02000000 +#define CPU_ALL_RELEASED (CPU0_BOOT_RELEASE | CPU1_BOOT_RELEASE) +#define MCM_PORT_CONFIG_OFFSET 0x1010 + +/* Offset from CCSRBAR */ +#define MPC86xx_MCM_OFFSET (0x00000) +#define MPC86xx_MCM_SIZE (0x02000) + +#endif /* CONFIG_PPC_86xx */ +#endif /* __ASM_POWERPC_MPC86xx_H__ */ +#endif /* __KERNEL__ */ diff --git a/include/asm-powerpc/spu_priv1.h b/include/asm-powerpc/spu_priv1.h new file mode 100644 index 000000000..300c458b6 --- /dev/null +++ b/include/asm-powerpc/spu_priv1.h @@ -0,0 +1,182 @@ +/* + * Defines an spu hypervisor abstraction layer. + * + * Copyright 2006 Sony Corp. + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#if !defined(_SPU_PRIV1_H) +#define _SPU_PRIV1_H +#if defined(__KERNEL__) + +struct spu; + +/* access to priv1 registers */ + +struct spu_priv1_ops +{ + void (*int_mask_and) (struct spu *spu, int class, u64 mask); + void (*int_mask_or) (struct spu *spu, int class, u64 mask); + void (*int_mask_set) (struct spu *spu, int class, u64 mask); + u64 (*int_mask_get) (struct spu *spu, int class); + void (*int_stat_clear) (struct spu *spu, int class, u64 stat); + u64 (*int_stat_get) (struct spu *spu, int class); + void (*cpu_affinity_set) (struct spu *spu, int cpu); + u64 (*mfc_dar_get) (struct spu *spu); + u64 (*mfc_dsisr_get) (struct spu *spu); + void (*mfc_dsisr_set) (struct spu *spu, u64 dsisr); + void (*mfc_sdr_set) (struct spu *spu, u64 sdr); + void (*mfc_sr1_set) (struct spu *spu, u64 sr1); + u64 (*mfc_sr1_get) (struct spu *spu); + void (*mfc_tclass_id_set) (struct spu *spu, u64 tclass_id); + u64 (*mfc_tclass_id_get) (struct spu *spu); + void (*tlb_invalidate) (struct spu *spu); + void (*resource_allocation_groupID_set) (struct spu *spu, u64 id); + u64 (*resource_allocation_groupID_get) (struct spu *spu); + void (*resource_allocation_enable_set) (struct spu *spu, u64 enable); + u64 (*resource_allocation_enable_get) (struct spu *spu); +}; + +extern const struct spu_priv1_ops* spu_priv1_ops; + +static inline void +spu_int_mask_and (struct spu *spu, int class, u64 mask) +{ + spu_priv1_ops->int_mask_and(spu, class, mask); +} + +static inline void +spu_int_mask_or (struct spu *spu, int class, u64 mask) +{ + spu_priv1_ops->int_mask_or(spu, class, mask); +} + +static inline void +spu_int_mask_set (struct spu *spu, int class, u64 mask) +{ + spu_priv1_ops->int_mask_set(spu, class, mask); +} + +static inline u64 +spu_int_mask_get (struct spu *spu, int class) +{ + return spu_priv1_ops->int_mask_get(spu, class); +} + +static inline void +spu_int_stat_clear (struct spu *spu, int class, u64 stat) +{ + spu_priv1_ops->int_stat_clear(spu, class, stat); +} + +static inline u64 +spu_int_stat_get (struct spu *spu, int class) +{ + return spu_priv1_ops->int_stat_get (spu, class); +} + +static inline void +spu_cpu_affinity_set (struct spu *spu, int cpu) +{ + spu_priv1_ops->cpu_affinity_set(spu, cpu); +} + +static inline u64 +spu_mfc_dar_get (struct spu *spu) +{ + return spu_priv1_ops->mfc_dar_get(spu); +} + +static inline u64 +spu_mfc_dsisr_get (struct spu *spu) +{ + return spu_priv1_ops->mfc_dsisr_get(spu); +} + +static inline void +spu_mfc_dsisr_set (struct spu *spu, u64 dsisr) +{ + spu_priv1_ops->mfc_dsisr_set(spu, dsisr); +} + +static inline void +spu_mfc_sdr_set (struct spu *spu, u64 sdr) +{ + spu_priv1_ops->mfc_sdr_set(spu, sdr); +} + +static inline void +spu_mfc_sr1_set (struct spu *spu, u64 sr1) +{ + spu_priv1_ops->mfc_sr1_set(spu, sr1); +} + +static inline u64 +spu_mfc_sr1_get (struct spu *spu) +{ + return spu_priv1_ops->mfc_sr1_get(spu); +} + +static inline void +spu_mfc_tclass_id_set (struct spu *spu, u64 tclass_id) +{ + spu_priv1_ops->mfc_tclass_id_set(spu, tclass_id); +} + +static inline u64 +spu_mfc_tclass_id_get (struct spu *spu) +{ + return spu_priv1_ops->mfc_tclass_id_get(spu); +} + +static inline void +spu_tlb_invalidate (struct spu *spu) +{ + spu_priv1_ops->tlb_invalidate(spu); +} + +static inline void +spu_resource_allocation_groupID_set (struct spu *spu, u64 id) +{ + spu_priv1_ops->resource_allocation_groupID_set(spu, id); +} + +static inline u64 +spu_resource_allocation_groupID_get (struct spu *spu) +{ + return spu_priv1_ops->resource_allocation_groupID_get(spu); +} + +static inline void +spu_resource_allocation_enable_set (struct spu *spu, u64 enable) +{ + spu_priv1_ops->resource_allocation_enable_set(spu, enable); +} + +static inline u64 +spu_resource_allocation_enable_get (struct spu *spu) +{ + return spu_priv1_ops->resource_allocation_enable_get(spu); +} + +/* The declarations folowing are put here for convenience + * and only intended to be used by the platform setup code + * for initializing spu_priv1_ops. + */ + +extern const struct spu_priv1_ops spu_priv1_mmio_ops; + +#endif /* __KERNEL__ */ +#endif diff --git a/include/asm-powerpc/systbl.h b/include/asm-powerpc/systbl.h new file mode 100644 index 000000000..607c1e0a6 --- /dev/null +++ b/include/asm-powerpc/systbl.h @@ -0,0 +1,306 @@ +/* + * List of powerpc syscalls. For the meaning of the _SPU suffix see + * arch/powerpc/platforms/cell/spu_callbacks.c + */ + +SYSCALL(restart_syscall) +SYSCALL(exit) +PPC_SYS(fork) +SYSCALL_SPU(read) +SYSCALL_SPU(write) +COMPAT_SYS_SPU(open) +SYSCALL_SPU(close) +COMPAT_SYS_SPU(waitpid) +COMPAT_SYS_SPU(creat) +SYSCALL_SPU(link) +SYSCALL_SPU(unlink) +COMPAT_SYS(execve) +SYSCALL_SPU(chdir) +COMPAT_SYS_SPU(time) +SYSCALL_SPU(mknod) +SYSCALL_SPU(chmod) +SYSCALL_SPU(lchown) +SYSCALL(ni_syscall) +OLDSYS(stat) +SYSX_SPU(sys_lseek,ppc32_lseek,sys_lseek) +SYSCALL_SPU(getpid) +COMPAT_SYS(mount) +SYSX(sys_ni_syscall,sys_oldumount,sys_oldumount) +SYSCALL_SPU(setuid) +SYSCALL_SPU(getuid) +COMPAT_SYS_SPU(stime) +COMPAT_SYS(ptrace) +SYSCALL_SPU(alarm) +OLDSYS(fstat) +COMPAT_SYS(pause) +COMPAT_SYS(utime) +SYSCALL(ni_syscall) +SYSCALL(ni_syscall) +COMPAT_SYS_SPU(access) +COMPAT_SYS_SPU(nice) +SYSCALL(ni_syscall) +SYSCALL_SPU(sync) +COMPAT_SYS_SPU(kill) +SYSCALL_SPU(rename) +COMPAT_SYS_SPU(mkdir) +SYSCALL_SPU(rmdir) +SYSCALL_SPU(dup) +SYSCALL_SPU(pipe) +COMPAT_SYS_SPU(times) +SYSCALL(ni_syscall) +SYSCALL_SPU(brk) +SYSCALL_SPU(setgid) +SYSCALL_SPU(getgid) +SYSCALL(signal) +SYSCALL_SPU(geteuid) +SYSCALL_SPU(getegid) +SYSCALL(acct) +SYSCALL(umount) +SYSCALL(ni_syscall) +COMPAT_SYS_SPU(ioctl) +COMPAT_SYS_SPU(fcntl) +SYSCALL(ni_syscall) +COMPAT_SYS_SPU(setpgid) +SYSCALL(ni_syscall) +SYSX(sys_ni_syscall,sys_olduname, sys_olduname) +COMPAT_SYS_SPU(umask) +SYSCALL_SPU(chroot) +SYSCALL(ustat) +SYSCALL_SPU(dup2) +SYSCALL_SPU(getppid) +SYSCALL_SPU(getpgrp) +SYSCALL_SPU(setsid) +SYS32ONLY(sigaction) +SYSCALL_SPU(sgetmask) +COMPAT_SYS_SPU(ssetmask) +SYSCALL_SPU(setreuid) +SYSCALL_SPU(setregid) +SYS32ONLY(sigsuspend) +COMPAT_SYS(sigpending) +COMPAT_SYS_SPU(sethostname) +COMPAT_SYS_SPU(setrlimit) +COMPAT_SYS(old_getrlimit) +COMPAT_SYS_SPU(getrusage) +COMPAT_SYS_SPU(gettimeofday) +COMPAT_SYS_SPU(settimeofday) +COMPAT_SYS_SPU(getgroups) +COMPAT_SYS_SPU(setgroups) +SYSX(sys_ni_syscall,sys_ni_syscall,ppc_select) +SYSCALL_SPU(symlink) +OLDSYS(lstat) +COMPAT_SYS_SPU(readlink) +SYSCALL(uselib) +SYSCALL(swapon) +SYSCALL(reboot) +SYSX(sys_ni_syscall,old32_readdir,old_readdir) +SYSCALL_SPU(mmap) +SYSCALL_SPU(munmap) +SYSCALL_SPU(truncate) +SYSCALL_SPU(ftruncate) +SYSCALL_SPU(fchmod) +SYSCALL_SPU(fchown) +COMPAT_SYS_SPU(getpriority) +COMPAT_SYS_SPU(setpriority) +SYSCALL(ni_syscall) +COMPAT_SYS(statfs) +COMPAT_SYS(fstatfs) +SYSCALL(ni_syscall) +COMPAT_SYS_SPU(socketcall) +COMPAT_SYS_SPU(syslog) +COMPAT_SYS_SPU(setitimer) +COMPAT_SYS_SPU(getitimer) +COMPAT_SYS_SPU(newstat) +COMPAT_SYS_SPU(newlstat) +COMPAT_SYS_SPU(newfstat) +SYSX(sys_ni_syscall,sys_uname,sys_uname) +SYSCALL(ni_syscall) +SYSCALL_SPU(vhangup) +SYSCALL(ni_syscall) +SYSCALL(ni_syscall) +COMPAT_SYS_SPU(wait4) +SYSCALL(swapoff) +COMPAT_SYS_SPU(sysinfo) +COMPAT_SYS(ipc) +SYSCALL_SPU(fsync) +SYS32ONLY(sigreturn) +PPC_SYS(clone) +COMPAT_SYS_SPU(setdomainname) +PPC_SYS_SPU(newuname) +SYSCALL(ni_syscall) +COMPAT_SYS_SPU(adjtimex) +SYSCALL_SPU(mprotect) +SYSX(sys_ni_syscall,compat_sys_sigprocmask,sys_sigprocmask) +SYSCALL(ni_syscall) +SYSCALL(init_module) +SYSCALL(delete_module) +SYSCALL(ni_syscall) +SYSCALL(quotactl) +COMPAT_SYS_SPU(getpgid) +SYSCALL_SPU(fchdir) +SYSCALL_SPU(bdflush) +COMPAT_SYS(sysfs) +SYSX_SPU(ppc64_personality,ppc64_personality,sys_personality) +SYSCALL(ni_syscall) +SYSCALL_SPU(setfsuid) +SYSCALL_SPU(setfsgid) +SYSCALL_SPU(llseek) +COMPAT_SYS_SPU(getdents) +SYSX_SPU(sys_select,ppc32_select,ppc_select) +SYSCALL_SPU(flock) +SYSCALL_SPU(msync) +COMPAT_SYS_SPU(readv) +COMPAT_SYS_SPU(writev) +COMPAT_SYS_SPU(getsid) +SYSCALL_SPU(fdatasync) +COMPAT_SYS(sysctl) +SYSCALL_SPU(mlock) +SYSCALL_SPU(munlock) +SYSCALL_SPU(mlockall) +SYSCALL_SPU(munlockall) +COMPAT_SYS_SPU(sched_setparam) +COMPAT_SYS_SPU(sched_getparam) +COMPAT_SYS_SPU(sched_setscheduler) +COMPAT_SYS_SPU(sched_getscheduler) +SYSCALL_SPU(sched_yield) +COMPAT_SYS_SPU(sched_get_priority_max) +COMPAT_SYS_SPU(sched_get_priority_min) +COMPAT_SYS_SPU(sched_rr_get_interval) +COMPAT_SYS_SPU(nanosleep) +SYSCALL_SPU(mremap) +SYSCALL_SPU(setresuid) +SYSCALL_SPU(getresuid) +SYSCALL(ni_syscall) +SYSCALL_SPU(poll) +COMPAT_SYS(nfsservctl) +SYSCALL_SPU(setresgid) +SYSCALL_SPU(getresgid) +COMPAT_SYS_SPU(prctl) +COMPAT_SYS(rt_sigreturn) +COMPAT_SYS(rt_sigaction) +COMPAT_SYS(rt_sigprocmask) +COMPAT_SYS(rt_sigpending) +COMPAT_SYS(rt_sigtimedwait) +COMPAT_SYS(rt_sigqueueinfo) +COMPAT_SYS(rt_sigsuspend) +COMPAT_SYS_SPU(pread64) +COMPAT_SYS_SPU(pwrite64) +SYSCALL_SPU(chown) +SYSCALL_SPU(getcwd) +SYSCALL_SPU(capget) +SYSCALL_SPU(capset) +COMPAT_SYS(sigaltstack) +SYSX_SPU(sys_sendfile64,compat_sys_sendfile,sys_sendfile) +SYSCALL(ni_syscall) +SYSCALL(ni_syscall) +PPC_SYS(vfork) +COMPAT_SYS_SPU(getrlimit) +COMPAT_SYS_SPU(readahead) +SYS32ONLY(mmap2) +SYS32ONLY(truncate64) +SYS32ONLY(ftruncate64) +SYSX(sys_ni_syscall,sys_stat64,sys_stat64) +SYSX(sys_ni_syscall,sys_lstat64,sys_lstat64) +SYSX(sys_ni_syscall,sys_fstat64,sys_fstat64) +SYSCALL(pciconfig_read) +SYSCALL(pciconfig_write) +SYSCALL(pciconfig_iobase) +SYSCALL(ni_syscall) +SYSCALL_SPU(getdents64) +SYSCALL_SPU(pivot_root) +SYSX(sys_ni_syscall,compat_sys_fcntl64,sys_fcntl64) +SYSCALL_SPU(madvise) +SYSCALL_SPU(mincore) +SYSCALL_SPU(gettid) +SYSCALL_SPU(tkill) +SYSCALL_SPU(setxattr) +SYSCALL_SPU(lsetxattr) +SYSCALL_SPU(fsetxattr) +SYSCALL_SPU(getxattr) +SYSCALL_SPU(lgetxattr) +SYSCALL_SPU(fgetxattr) +SYSCALL_SPU(listxattr) +SYSCALL_SPU(llistxattr) +SYSCALL_SPU(flistxattr) +SYSCALL_SPU(removexattr) +SYSCALL_SPU(lremovexattr) +SYSCALL_SPU(fremovexattr) +COMPAT_SYS_SPU(futex) +COMPAT_SYS_SPU(sched_setaffinity) +COMPAT_SYS_SPU(sched_getaffinity) +SYSCALL(ni_syscall) +SYSCALL(ni_syscall) +SYS32ONLY(sendfile64) +COMPAT_SYS_SPU(io_setup) +SYSCALL_SPU(io_destroy) +COMPAT_SYS_SPU(io_getevents) +COMPAT_SYS_SPU(io_submit) +SYSCALL_SPU(io_cancel) +SYSCALL(set_tid_address) +SYSX_SPU(sys_fadvise64,ppc32_fadvise64,sys_fadvise64) +SYSCALL(exit_group) +SYSX(sys_lookup_dcookie,ppc32_lookup_dcookie,sys_lookup_dcookie) +SYSCALL_SPU(epoll_create) +SYSCALL_SPU(epoll_ctl) +SYSCALL_SPU(epoll_wait) +SYSCALL_SPU(remap_file_pages) +SYSX_SPU(sys_timer_create,compat_sys_timer_create,sys_timer_create) +COMPAT_SYS_SPU(timer_settime) +COMPAT_SYS_SPU(timer_gettime) +SYSCALL_SPU(timer_getoverrun) +SYSCALL_SPU(timer_delete) +COMPAT_SYS_SPU(clock_settime) +COMPAT_SYS_SPU(clock_gettime) +COMPAT_SYS_SPU(clock_getres) +COMPAT_SYS_SPU(clock_nanosleep) +SYSX(ppc64_swapcontext,ppc32_swapcontext,ppc_swapcontext) +COMPAT_SYS_SPU(tgkill) +COMPAT_SYS_SPU(utimes) +COMPAT_SYS_SPU(statfs64) +COMPAT_SYS_SPU(fstatfs64) +SYSX(sys_ni_syscall, ppc_fadvise64_64, ppc_fadvise64_64) +PPC_SYS_SPU(rtas) +OLDSYS(debug_setcontext) +SYSX(sys_vserver, sys32_vserver, sys_vserver) +SYSCALL(ni_syscall) +COMPAT_SYS(mbind) +COMPAT_SYS(get_mempolicy) +COMPAT_SYS(set_mempolicy) +COMPAT_SYS(mq_open) +SYSCALL(mq_unlink) +COMPAT_SYS(mq_timedsend) +COMPAT_SYS(mq_timedreceive) +COMPAT_SYS(mq_notify) +COMPAT_SYS(mq_getsetattr) +COMPAT_SYS(kexec_load) +COMPAT_SYS(add_key) +COMPAT_SYS(request_key) +COMPAT_SYS(keyctl) +COMPAT_SYS(waitid) +COMPAT_SYS(ioprio_set) +COMPAT_SYS(ioprio_get) +SYSCALL(inotify_init) +SYSCALL(inotify_add_watch) +SYSCALL(inotify_rm_watch) +SYSCALL(spu_run) +SYSCALL(spu_create) +COMPAT_SYS(pselect6) +COMPAT_SYS(ppoll) +SYSCALL_SPU(unshare) +SYSCALL_SPU(splice) +SYSCALL_SPU(tee) +SYSCALL_SPU(vmsplice) +COMPAT_SYS_SPU(openat) +SYSCALL_SPU(mkdirat) +SYSCALL_SPU(mknodat) +SYSCALL_SPU(fchownat) +COMPAT_SYS_SPU(futimesat) +SYSX_SPU(sys_newfstatat, sys_fstatat64, sys_fstatat64) +SYSCALL_SPU(unlinkat) +SYSCALL_SPU(renameat) +SYSCALL_SPU(linkat) +SYSCALL_SPU(symlinkat) +SYSCALL_SPU(readlinkat) +SYSCALL_SPU(fchmodat) +SYSCALL_SPU(faccessat) +COMPAT_SYS_SPU(get_robust_list) +COMPAT_SYS_SPU(set_robust_list) diff --git a/include/asm-powerpc/todc.h b/include/asm-powerpc/todc.h new file mode 100644 index 000000000..60a8c39b8 --- /dev/null +++ b/include/asm-powerpc/todc.h @@ -0,0 +1,487 @@ +/* + * Definitions for the M48Txx and mc146818 series of Time of day/Real Time + * Clock chips. + * + * Author: Mark A. Greer <mgreer@mvista.com> + * + * 2001 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +/* + * Support for the M48T37/M48T59/.../mc146818 Real Time Clock chips. + * Purpose is to make one generic file that handles all of these chips instead + * of every platform implementing the same code over & over again. + */ + +#ifndef __PPC_KERNEL_TODC_H +#define __PPC_KERNEL_TODC_H + +typedef struct { + uint rtc_type; /* your particular chip */ + + /* + * Following are the addresses of the AS0, AS1, and DATA registers + * of these chips. Note that these are board-specific. + */ + unsigned int nvram_as0; + unsigned int nvram_as1; + unsigned int nvram_data; + + /* + * Define bits to stop external set of regs from changing so + * the chip can be read/written reliably. + */ + unsigned char enable_read; + unsigned char enable_write; + + /* + * Following is the number of AS0 address bits. This is normally + * 8 but some bad hardware routes address lines incorrectly. + */ + int as0_bits; + + int nvram_size; /* Size of NVRAM on chip */ + int sw_flags; /* Software control flags */ + + /* Following are the register offsets for the particular chip */ + int year; + int month; + int day_of_month; + int day_of_week; + int hours; + int minutes; + int seconds; + int control_b; + int control_a; + int watchdog; + int interrupts; + int alarm_date; + int alarm_hour; + int alarm_minutes; + int alarm_seconds; + int century; + int flags; + + /* + * Some RTC chips have their NVRAM buried behind a addr/data pair of + * regs on the first level/clock registers. The following fields + * are the addresses for those addr/data regs. + */ + int nvram_addr_reg; + int nvram_data_reg; +} todc_info_t; + +/* + * Define the types of TODC/RTC variants that are supported in + * arch/ppc/kernel/todc_time.c + * Make a new one of these for any chip somehow differs from what's already + * defined. That way, if you ever need to put in code to touch those + * bits/registers in todc_time.c, you can put it inside an + * 'if (todc_info->rtc_type == TODC_TYPE_XXX)' so you won't break + * anyone else. + */ +#define TODC_TYPE_MK48T35 1 +#define TODC_TYPE_MK48T37 2 +#define TODC_TYPE_MK48T59 3 +#define TODC_TYPE_DS1693 4 /* Dallas DS1693 RTC */ +#define TODC_TYPE_DS1743 5 /* Dallas DS1743 RTC */ +#define TODC_TYPE_DS1746 6 /* Dallas DS1746 RTC */ +#define TODC_TYPE_DS1747 7 /* Dallas DS1747 RTC */ +#define TODC_TYPE_DS1501 8 /* Dallas DS1501 RTC */ +#define TODC_TYPE_DS1643 9 /* Dallas DS1643 RTC */ +#define TODC_TYPE_PC97307 10 /* PC97307 internal RTC */ +#define TODC_TYPE_DS1557 11 /* Dallas DS1557 RTC */ +#define TODC_TYPE_DS17285 12 /* Dallas DS17285 RTC */ +#define TODC_TYPE_DS1553 13 /* Dallas DS1553 RTC */ +#define TODC_TYPE_MC146818 100 /* Leave room for m48txx's */ + +/* + * Bit to clear/set to enable reads/writes to the chip + */ +#define TODC_MK48TXX_CNTL_A_R 0x40 +#define TODC_MK48TXX_CNTL_A_W 0x80 +#define TODC_MK48TXX_DAY_CB 0x80 + +#define TODC_DS1501_CNTL_B_TE 0x80 + +/* + * Define flag bits used by todc routines. + */ +#define TODC_FLAG_2_LEVEL_NVRAM 0x00000001 + +/* + * Define the values for the various RTC's that should to into the todc_info + * table. + * Note: The XXX_NVRAM_SIZE, XXX_NVRAM_ADDR_REG, and XXX_NVRAM_DATA_REG only + * matter if XXX_SW_FLAGS has TODC_FLAG_2_LEVEL_NVRAM set. + */ +#define TODC_TYPE_MK48T35_NVRAM_SIZE 0x7ff8 +#define TODC_TYPE_MK48T35_SW_FLAGS 0 +#define TODC_TYPE_MK48T35_YEAR 0x7fff +#define TODC_TYPE_MK48T35_MONTH 0x7ffe +#define TODC_TYPE_MK48T35_DOM 0x7ffd /* Day of Month */ +#define TODC_TYPE_MK48T35_DOW 0x7ffc /* Day of Week */ +#define TODC_TYPE_MK48T35_HOURS 0x7ffb +#define TODC_TYPE_MK48T35_MINUTES 0x7ffa +#define TODC_TYPE_MK48T35_SECONDS 0x7ff9 +#define TODC_TYPE_MK48T35_CNTL_B 0x7ff9 +#define TODC_TYPE_MK48T35_CNTL_A 0x7ff8 +#define TODC_TYPE_MK48T35_WATCHDOG 0x0000 +#define TODC_TYPE_MK48T35_INTERRUPTS 0x0000 +#define TODC_TYPE_MK48T35_ALARM_DATE 0x0000 +#define TODC_TYPE_MK48T35_ALARM_HOUR 0x0000 +#define TODC_TYPE_MK48T35_ALARM_MINUTES 0x0000 +#define TODC_TYPE_MK48T35_ALARM_SECONDS 0x0000 +#define TODC_TYPE_MK48T35_CENTURY 0x0000 +#define TODC_TYPE_MK48T35_FLAGS 0x0000 +#define TODC_TYPE_MK48T35_NVRAM_ADDR_REG 0 +#define TODC_TYPE_MK48T35_NVRAM_DATA_REG 0 + +#define TODC_TYPE_MK48T37_NVRAM_SIZE 0x7ff0 +#define TODC_TYPE_MK48T37_SW_FLAGS 0 +#define TODC_TYPE_MK48T37_YEAR 0x7fff +#define TODC_TYPE_MK48T37_MONTH 0x7ffe +#define TODC_TYPE_MK48T37_DOM 0x7ffd /* Day of Month */ +#define TODC_TYPE_MK48T37_DOW 0x7ffc /* Day of Week */ +#define TODC_TYPE_MK48T37_HOURS 0x7ffb +#define TODC_TYPE_MK48T37_MINUTES 0x7ffa +#define TODC_TYPE_MK48T37_SECONDS 0x7ff9 +#define TODC_TYPE_MK48T37_CNTL_B 0x7ff9 +#define TODC_TYPE_MK48T37_CNTL_A 0x7ff8 +#define TODC_TYPE_MK48T37_WATCHDOG 0x7ff7 +#define TODC_TYPE_MK48T37_INTERRUPTS 0x7ff6 +#define TODC_TYPE_MK48T37_ALARM_DATE 0x7ff5 +#define TODC_TYPE_MK48T37_ALARM_HOUR 0x7ff4 +#define TODC_TYPE_MK48T37_ALARM_MINUTES 0x7ff3 +#define TODC_TYPE_MK48T37_ALARM_SECONDS 0x7ff2 +#define TODC_TYPE_MK48T37_CENTURY 0x7ff1 +#define TODC_TYPE_MK48T37_FLAGS 0x7ff0 +#define TODC_TYPE_MK48T37_NVRAM_ADDR_REG 0 +#define TODC_TYPE_MK48T37_NVRAM_DATA_REG 0 + +#define TODC_TYPE_MK48T59_NVRAM_SIZE 0x1ff0 +#define TODC_TYPE_MK48T59_SW_FLAGS 0 +#define TODC_TYPE_MK48T59_YEAR 0x1fff +#define TODC_TYPE_MK48T59_MONTH 0x1ffe +#define TODC_TYPE_MK48T59_DOM 0x1ffd /* Day of Month */ +#define TODC_TYPE_MK48T59_DOW 0x1ffc /* Day of Week */ +#define TODC_TYPE_MK48T59_HOURS 0x1ffb +#define TODC_TYPE_MK48T59_MINUTES 0x1ffa +#define TODC_TYPE_MK48T59_SECONDS 0x1ff9 +#define TODC_TYPE_MK48T59_CNTL_B 0x1ff9 +#define TODC_TYPE_MK48T59_CNTL_A 0x1ff8 +#define TODC_TYPE_MK48T59_WATCHDOG 0x1fff +#define TODC_TYPE_MK48T59_INTERRUPTS 0x1fff +#define TODC_TYPE_MK48T59_ALARM_DATE 0x1fff +#define TODC_TYPE_MK48T59_ALARM_HOUR 0x1fff +#define TODC_TYPE_MK48T59_ALARM_MINUTES 0x1fff +#define TODC_TYPE_MK48T59_ALARM_SECONDS 0x1fff +#define TODC_TYPE_MK48T59_CENTURY 0x1fff +#define TODC_TYPE_MK48T59_FLAGS 0x1fff +#define TODC_TYPE_MK48T59_NVRAM_ADDR_REG 0 +#define TODC_TYPE_MK48T59_NVRAM_DATA_REG 0 + +#define TODC_TYPE_DS1501_NVRAM_SIZE 0x100 +#define TODC_TYPE_DS1501_SW_FLAGS TODC_FLAG_2_LEVEL_NVRAM +#define TODC_TYPE_DS1501_YEAR (TODC_TYPE_DS1501_NVRAM_SIZE + 0x06) +#define TODC_TYPE_DS1501_MONTH (TODC_TYPE_DS1501_NVRAM_SIZE + 0x05) +#define TODC_TYPE_DS1501_DOM (TODC_TYPE_DS1501_NVRAM_SIZE + 0x04) +#define TODC_TYPE_DS1501_DOW (TODC_TYPE_DS1501_NVRAM_SIZE + 0x03) +#define TODC_TYPE_DS1501_HOURS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x02) +#define TODC_TYPE_DS1501_MINUTES (TODC_TYPE_DS1501_NVRAM_SIZE + 0x01) +#define TODC_TYPE_DS1501_SECONDS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x00) +#define TODC_TYPE_DS1501_CNTL_B (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f) +#define TODC_TYPE_DS1501_CNTL_A (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0f) +#define TODC_TYPE_DS1501_WATCHDOG (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff) +#define TODC_TYPE_DS1501_INTERRUPTS (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff) +#define TODC_TYPE_DS1501_ALARM_DATE (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0b) +#define TODC_TYPE_DS1501_ALARM_HOUR (TODC_TYPE_DS1501_NVRAM_SIZE + 0x0a) +#define TODC_TYPE_DS1501_ALARM_MINUTES (TODC_TYPE_DS1501_NVRAM_SIZE + 0x09) +#define TODC_TYPE_DS1501_ALARM_SECONDS (TODC_TYPE_DS1501_NVRAM_SIZE + 0x08) +#define TODC_TYPE_DS1501_CENTURY (TODC_TYPE_DS1501_NVRAM_SIZE + 0x07) +#define TODC_TYPE_DS1501_FLAGS (TODC_TYPE_DS1501_NVRAM_SIZE + 0xff) +#define TODC_TYPE_DS1501_NVRAM_ADDR_REG 0x10 +#define TODC_TYPE_DS1501_NVRAM_DATA_REG 0x13 + +#define TODC_TYPE_DS1553_NVRAM_SIZE 0x1ff0 +#define TODC_TYPE_DS1553_SW_FLAGS 0 +#define TODC_TYPE_DS1553_YEAR 0x1fff +#define TODC_TYPE_DS1553_MONTH 0x1ffe +#define TODC_TYPE_DS1553_DOM 0x1ffd /* Day of Month */ +#define TODC_TYPE_DS1553_DOW 0x1ffc /* Day of Week */ +#define TODC_TYPE_DS1553_HOURS 0x1ffb +#define TODC_TYPE_DS1553_MINUTES 0x1ffa +#define TODC_TYPE_DS1553_SECONDS 0x1ff9 +#define TODC_TYPE_DS1553_CNTL_B 0x1ff9 +#define TODC_TYPE_DS1553_CNTL_A 0x1ff8 /* control_a R/W regs */ +#define TODC_TYPE_DS1553_WATCHDOG 0x1ff7 +#define TODC_TYPE_DS1553_INTERRUPTS 0x1ff6 +#define TODC_TYPE_DS1553_ALARM_DATE 0x1ff5 +#define TODC_TYPE_DS1553_ALARM_HOUR 0x1ff4 +#define TODC_TYPE_DS1553_ALARM_MINUTES 0x1ff3 +#define TODC_TYPE_DS1553_ALARM_SECONDS 0x1ff2 +#define TODC_TYPE_DS1553_CENTURY 0x1ff8 +#define TODC_TYPE_DS1553_FLAGS 0x1ff0 +#define TODC_TYPE_DS1553_NVRAM_ADDR_REG 0 +#define TODC_TYPE_DS1553_NVRAM_DATA_REG 0 + +#define TODC_TYPE_DS1557_NVRAM_SIZE 0x7fff0 +#define TODC_TYPE_DS1557_SW_FLAGS 0 +#define TODC_TYPE_DS1557_YEAR 0x7ffff +#define TODC_TYPE_DS1557_MONTH 0x7fffe +#define TODC_TYPE_DS1557_DOM 0x7fffd /* Day of Month */ +#define TODC_TYPE_DS1557_DOW 0x7fffc /* Day of Week */ +#define TODC_TYPE_DS1557_HOURS 0x7fffb +#define TODC_TYPE_DS1557_MINUTES 0x7fffa +#define TODC_TYPE_DS1557_SECONDS 0x7fff9 +#define TODC_TYPE_DS1557_CNTL_B 0x7fff9 +#define TODC_TYPE_DS1557_CNTL_A 0x7fff8 /* control_a R/W regs */ +#define TODC_TYPE_DS1557_WATCHDOG 0x7fff7 +#define TODC_TYPE_DS1557_INTERRUPTS 0x7fff6 +#define TODC_TYPE_DS1557_ALARM_DATE 0x7fff5 +#define TODC_TYPE_DS1557_ALARM_HOUR 0x7fff4 +#define TODC_TYPE_DS1557_ALARM_MINUTES 0x7fff3 +#define TODC_TYPE_DS1557_ALARM_SECONDS 0x7fff2 +#define TODC_TYPE_DS1557_CENTURY 0x7fff8 +#define TODC_TYPE_DS1557_FLAGS 0x7fff0 +#define TODC_TYPE_DS1557_NVRAM_ADDR_REG 0 +#define TODC_TYPE_DS1557_NVRAM_DATA_REG 0 + +#define TODC_TYPE_DS1643_NVRAM_SIZE 0x1ff8 +#define TODC_TYPE_DS1643_SW_FLAGS 0 +#define TODC_TYPE_DS1643_YEAR 0x1fff +#define TODC_TYPE_DS1643_MONTH 0x1ffe +#define TODC_TYPE_DS1643_DOM 0x1ffd /* Day of Month */ +#define TODC_TYPE_DS1643_DOW 0x1ffc /* Day of Week */ +#define TODC_TYPE_DS1643_HOURS 0x1ffb +#define TODC_TYPE_DS1643_MINUTES 0x1ffa +#define TODC_TYPE_DS1643_SECONDS 0x1ff9 +#define TODC_TYPE_DS1643_CNTL_B 0x1ff9 +#define TODC_TYPE_DS1643_CNTL_A 0x1ff8 /* control_a R/W regs */ +#define TODC_TYPE_DS1643_WATCHDOG 0x1fff +#define TODC_TYPE_DS1643_INTERRUPTS 0x1fff +#define TODC_TYPE_DS1643_ALARM_DATE 0x1fff +#define TODC_TYPE_DS1643_ALARM_HOUR 0x1fff +#define TODC_TYPE_DS1643_ALARM_MINUTES 0x1fff +#define TODC_TYPE_DS1643_ALARM_SECONDS 0x1fff +#define TODC_TYPE_DS1643_CENTURY 0x1ff8 +#define TODC_TYPE_DS1643_FLAGS 0x1fff +#define TODC_TYPE_DS1643_NVRAM_ADDR_REG 0 +#define TODC_TYPE_DS1643_NVRAM_DATA_REG 0 + +#define TODC_TYPE_DS1693_NVRAM_SIZE 0 /* Not handled yet */ +#define TODC_TYPE_DS1693_SW_FLAGS 0 +#define TODC_TYPE_DS1693_YEAR 0x09 +#define TODC_TYPE_DS1693_MONTH 0x08 +#define TODC_TYPE_DS1693_DOM 0x07 /* Day of Month */ +#define TODC_TYPE_DS1693_DOW 0x06 /* Day of Week */ +#define TODC_TYPE_DS1693_HOURS 0x04 +#define TODC_TYPE_DS1693_MINUTES 0x02 +#define TODC_TYPE_DS1693_SECONDS 0x00 +#define TODC_TYPE_DS1693_CNTL_B 0x0b +#define TODC_TYPE_DS1693_CNTL_A 0x0a +#define TODC_TYPE_DS1693_WATCHDOG 0xff +#define TODC_TYPE_DS1693_INTERRUPTS 0xff +#define TODC_TYPE_DS1693_ALARM_DATE 0x49 +#define TODC_TYPE_DS1693_ALARM_HOUR 0x05 +#define TODC_TYPE_DS1693_ALARM_MINUTES 0x03 +#define TODC_TYPE_DS1693_ALARM_SECONDS 0x01 +#define TODC_TYPE_DS1693_CENTURY 0x48 +#define TODC_TYPE_DS1693_FLAGS 0xff +#define TODC_TYPE_DS1693_NVRAM_ADDR_REG 0 +#define TODC_TYPE_DS1693_NVRAM_DATA_REG 0 + +#define TODC_TYPE_DS1743_NVRAM_SIZE 0x1ff8 +#define TODC_TYPE_DS1743_SW_FLAGS 0 +#define TODC_TYPE_DS1743_YEAR 0x1fff +#define TODC_TYPE_DS1743_MONTH 0x1ffe +#define TODC_TYPE_DS1743_DOM 0x1ffd /* Day of Month */ +#define TODC_TYPE_DS1743_DOW 0x1ffc /* Day of Week */ +#define TODC_TYPE_DS1743_HOURS 0x1ffb +#define TODC_TYPE_DS1743_MINUTES 0x1ffa +#define TODC_TYPE_DS1743_SECONDS 0x1ff9 +#define TODC_TYPE_DS1743_CNTL_B 0x1ff9 +#define TODC_TYPE_DS1743_CNTL_A 0x1ff8 /* control_a R/W regs */ +#define TODC_TYPE_DS1743_WATCHDOG 0x1fff +#define TODC_TYPE_DS1743_INTERRUPTS 0x1fff +#define TODC_TYPE_DS1743_ALARM_DATE 0x1fff +#define TODC_TYPE_DS1743_ALARM_HOUR 0x1fff +#define TODC_TYPE_DS1743_ALARM_MINUTES 0x1fff +#define TODC_TYPE_DS1743_ALARM_SECONDS 0x1fff +#define TODC_TYPE_DS1743_CENTURY 0x1ff8 +#define TODC_TYPE_DS1743_FLAGS 0x1fff +#define TODC_TYPE_DS1743_NVRAM_ADDR_REG 0 +#define TODC_TYPE_DS1743_NVRAM_DATA_REG 0 + +#define TODC_TYPE_DS1746_NVRAM_SIZE 0x1fff8 +#define TODC_TYPE_DS1746_SW_FLAGS 0 +#define TODC_TYPE_DS1746_YEAR 0x1ffff +#define TODC_TYPE_DS1746_MONTH 0x1fffe +#define TODC_TYPE_DS1746_DOM 0x1fffd /* Day of Month */ +#define TODC_TYPE_DS1746_DOW 0x1fffc /* Day of Week */ +#define TODC_TYPE_DS1746_HOURS 0x1fffb +#define TODC_TYPE_DS1746_MINUTES 0x1fffa +#define TODC_TYPE_DS1746_SECONDS 0x1fff9 +#define TODC_TYPE_DS1746_CNTL_B 0x1fff9 +#define TODC_TYPE_DS1746_CNTL_A 0x1fff8 /* control_a R/W regs */ +#define TODC_TYPE_DS1746_WATCHDOG 0x00000 +#define TODC_TYPE_DS1746_INTERRUPTS 0x00000 +#define TODC_TYPE_DS1746_ALARM_DATE 0x00000 +#define TODC_TYPE_DS1746_ALARM_HOUR 0x00000 +#define TODC_TYPE_DS1746_ALARM_MINUTES 0x00000 +#define TODC_TYPE_DS1746_ALARM_SECONDS 0x00000 +#define TODC_TYPE_DS1746_CENTURY 0x00000 +#define TODC_TYPE_DS1746_FLAGS 0x00000 +#define TODC_TYPE_DS1746_NVRAM_ADDR_REG 0 +#define TODC_TYPE_DS1746_NVRAM_DATA_REG 0 + +#define TODC_TYPE_DS1747_NVRAM_SIZE 0x7fff8 +#define TODC_TYPE_DS1747_SW_FLAGS 0 +#define TODC_TYPE_DS1747_YEAR 0x7ffff +#define TODC_TYPE_DS1747_MONTH 0x7fffe +#define TODC_TYPE_DS1747_DOM 0x7fffd /* Day of Month */ +#define TODC_TYPE_DS1747_DOW 0x7fffc /* Day of Week */ +#define TODC_TYPE_DS1747_HOURS 0x7fffb +#define TODC_TYPE_DS1747_MINUTES 0x7fffa +#define TODC_TYPE_DS1747_SECONDS 0x7fff9 +#define TODC_TYPE_DS1747_CNTL_B 0x7fff9 +#define TODC_TYPE_DS1747_CNTL_A 0x7fff8 /* control_a R/W regs */ +#define TODC_TYPE_DS1747_WATCHDOG 0x00000 +#define TODC_TYPE_DS1747_INTERRUPTS 0x00000 +#define TODC_TYPE_DS1747_ALARM_DATE 0x00000 +#define TODC_TYPE_DS1747_ALARM_HOUR 0x00000 +#define TODC_TYPE_DS1747_ALARM_MINUTES 0x00000 +#define TODC_TYPE_DS1747_ALARM_SECONDS 0x00000 +#define TODC_TYPE_DS1747_CENTURY 0x00000 +#define TODC_TYPE_DS1747_FLAGS 0x00000 +#define TODC_TYPE_DS1747_NVRAM_ADDR_REG 0 +#define TODC_TYPE_DS1747_NVRAM_DATA_REG 0 + +#define TODC_TYPE_DS17285_NVRAM_SIZE (0x1000-0x80) /* 4Kx8 NVRAM (minus RTC regs) */ +#define TODC_TYPE_DS17285_SW_FLAGS TODC_FLAG_2_LEVEL_NVRAM +#define TODC_TYPE_DS17285_SECONDS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x00) +#define TODC_TYPE_DS17285_ALARM_SECONDS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x01) +#define TODC_TYPE_DS17285_MINUTES (TODC_TYPE_DS17285_NVRAM_SIZE + 0x02) +#define TODC_TYPE_DS17285_ALARM_MINUTES (TODC_TYPE_DS17285_NVRAM_SIZE + 0x03) +#define TODC_TYPE_DS17285_HOURS (TODC_TYPE_DS17285_NVRAM_SIZE + 0x04) +#define TODC_TYPE_DS17285_ALARM_HOUR (TODC_TYPE_DS17285_NVRAM_SIZE + 0x05) +#define TODC_TYPE_DS17285_DOW (TODC_TYPE_DS17285_NVRAM_SIZE + 0x06) +#define TODC_TYPE_DS17285_DOM (TODC_TYPE_DS17285_NVRAM_SIZE + 0x07) +#define TODC_TYPE_DS17285_MONTH (TODC_TYPE_DS17285_NVRAM_SIZE + 0x08) +#define TODC_TYPE_DS17285_YEAR (TODC_TYPE_DS17285_NVRAM_SIZE + 0x09) +#define TODC_TYPE_DS17285_CNTL_A (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0A) +#define TODC_TYPE_DS17285_CNTL_B (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0B) +#define TODC_TYPE_DS17285_CNTL_C (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0C) +#define TODC_TYPE_DS17285_CNTL_D (TODC_TYPE_DS17285_NVRAM_SIZE + 0x0D) +#define TODC_TYPE_DS17285_WATCHDOG 0 +#define TODC_TYPE_DS17285_INTERRUPTS 0 +#define TODC_TYPE_DS17285_ALARM_DATE 0 +#define TODC_TYPE_DS17285_CENTURY 0 +#define TODC_TYPE_DS17285_FLAGS 0 +#define TODC_TYPE_DS17285_NVRAM_ADDR_REG 0x50 +#define TODC_TYPE_DS17285_NVRAM_DATA_REG 0x53 + +#define TODC_TYPE_MC146818_NVRAM_SIZE 0 /* XXXX */ +#define TODC_TYPE_MC146818_SW_FLAGS 0 +#define TODC_TYPE_MC146818_YEAR 0x09 +#define TODC_TYPE_MC146818_MONTH 0x08 +#define TODC_TYPE_MC146818_DOM 0x07 /* Day of Month */ +#define TODC_TYPE_MC146818_DOW 0x06 /* Day of Week */ +#define TODC_TYPE_MC146818_HOURS 0x04 +#define TODC_TYPE_MC146818_MINUTES 0x02 +#define TODC_TYPE_MC146818_SECONDS 0x00 +#define TODC_TYPE_MC146818_CNTL_B 0x0a +#define TODC_TYPE_MC146818_CNTL_A 0x0b /* control_a R/W regs */ +#define TODC_TYPE_MC146818_WATCHDOG 0 +#define TODC_TYPE_MC146818_INTERRUPTS 0x0c +#define TODC_TYPE_MC146818_ALARM_DATE 0xff +#define TODC_TYPE_MC146818_ALARM_HOUR 0x05 +#define TODC_TYPE_MC146818_ALARM_MINUTES 0x03 +#define TODC_TYPE_MC146818_ALARM_SECONDS 0x01 +#define TODC_TYPE_MC146818_CENTURY 0xff +#define TODC_TYPE_MC146818_FLAGS 0xff +#define TODC_TYPE_MC146818_NVRAM_ADDR_REG 0 +#define TODC_TYPE_MC146818_NVRAM_DATA_REG 0 + +#define TODC_TYPE_PC97307_NVRAM_SIZE 0 /* No NVRAM? */ +#define TODC_TYPE_PC97307_SW_FLAGS 0 +#define TODC_TYPE_PC97307_YEAR 0x09 +#define TODC_TYPE_PC97307_MONTH 0x08 +#define TODC_TYPE_PC97307_DOM 0x07 /* Day of Month */ +#define TODC_TYPE_PC97307_DOW 0x06 /* Day of Week */ +#define TODC_TYPE_PC97307_HOURS 0x04 +#define TODC_TYPE_PC97307_MINUTES 0x02 +#define TODC_TYPE_PC97307_SECONDS 0x00 +#define TODC_TYPE_PC97307_CNTL_B 0x0a +#define TODC_TYPE_PC97307_CNTL_A 0x0b /* control_a R/W regs */ +#define TODC_TYPE_PC97307_WATCHDOG 0x0c +#define TODC_TYPE_PC97307_INTERRUPTS 0x0d +#define TODC_TYPE_PC97307_ALARM_DATE 0xff +#define TODC_TYPE_PC97307_ALARM_HOUR 0x05 +#define TODC_TYPE_PC97307_ALARM_MINUTES 0x03 +#define TODC_TYPE_PC97307_ALARM_SECONDS 0x01 +#define TODC_TYPE_PC97307_CENTURY 0xff +#define TODC_TYPE_PC97307_FLAGS 0xff +#define TODC_TYPE_PC97307_NVRAM_ADDR_REG 0 +#define TODC_TYPE_PC97307_NVRAM_DATA_REG 0 + +/* + * Define macros to allocate and init the todc_info_t table that will + * be used by the todc_time.c routines. + */ +#define TODC_ALLOC() \ + static todc_info_t todc_info_alloc; \ + todc_info_t *todc_info = &todc_info_alloc; + +#define TODC_INIT(clock_type, as0, as1, data, bits) { \ + todc_info->rtc_type = clock_type; \ + \ + todc_info->nvram_as0 = (unsigned int)(as0); \ + todc_info->nvram_as1 = (unsigned int)(as1); \ + todc_info->nvram_data = (unsigned int)(data); \ + \ + todc_info->as0_bits = (bits); \ + \ + todc_info->nvram_size = clock_type ##_NVRAM_SIZE; \ + todc_info->sw_flags = clock_type ##_SW_FLAGS; \ + \ + todc_info->year = clock_type ##_YEAR; \ + todc_info->month = clock_type ##_MONTH; \ + todc_info->day_of_month = clock_type ##_DOM; \ + todc_info->day_of_week = clock_type ##_DOW; \ + todc_info->hours = clock_type ##_HOURS; \ + todc_info->minutes = clock_type ##_MINUTES; \ + todc_info->seconds = clock_type ##_SECONDS; \ + todc_info->control_b = clock_type ##_CNTL_B; \ + todc_info->control_a = clock_type ##_CNTL_A; \ + todc_info->watchdog = clock_type ##_WATCHDOG; \ + todc_info->interrupts = clock_type ##_INTERRUPTS; \ + todc_info->alarm_date = clock_type ##_ALARM_DATE; \ + todc_info->alarm_hour = clock_type ##_ALARM_HOUR; \ + todc_info->alarm_minutes = clock_type ##_ALARM_MINUTES; \ + todc_info->alarm_seconds = clock_type ##_ALARM_SECONDS; \ + todc_info->century = clock_type ##_CENTURY; \ + todc_info->flags = clock_type ##_FLAGS; \ + \ + todc_info->nvram_addr_reg = clock_type ##_NVRAM_ADDR_REG; \ + todc_info->nvram_data_reg = clock_type ##_NVRAM_DATA_REG; \ +} + +extern todc_info_t *todc_info; + +unsigned char todc_direct_read_val(int addr); +void todc_direct_write_val(int addr, unsigned char val); +unsigned char todc_m48txx_read_val(int addr); +void todc_m48txx_write_val(int addr, unsigned char val); +unsigned char todc_mc146818_read_val(int addr); +void todc_mc146818_write_val(int addr, unsigned char val); + +long todc_time_init(void); +void todc_get_rtc_time(struct rtc_time *); +int todc_set_rtc_time(struct rtc_time *); +void todc_calibrate_decr(void); + +#endif /* __PPC_KERNEL_TODC_H */ diff --git a/include/asm-powerpc/tracehook.h b/include/asm-powerpc/tracehook.h new file mode 100644 index 000000000..2cf5dc3bc --- /dev/null +++ b/include/asm-powerpc/tracehook.h @@ -0,0 +1,80 @@ +/* + * Tracing hooks, PowerPC CPU support + */ + +#ifndef _ASM_TRACEHOOK_H +#define _ASM_TRACEHOOK_H 1 + +#include <linux/sched.h> +#include <asm/ptrace.h> + +/* + * See linux/tracehook.h for the descriptions of what these need to do. + */ + +#define ARCH_HAS_SINGLE_STEP (1) + +static inline void tracehook_enable_single_step(struct task_struct *task) +{ + struct pt_regs *regs = task->thread.regs; + if (regs != NULL) { +#if defined(CONFIG_PPC32) && (defined(CONFIG_40x) || defined(CONFIG_BOOKE)) + task->thread.dbcr0 = DBCR0_IDM | DBCR0_IC; + regs->msr |= MSR_DE; +#else + regs->msr |= MSR_SE; +#endif + } + set_tsk_thread_flag(task, TIF_SINGLESTEP); +} + +static inline void tracehook_disable_single_step(struct task_struct *task) +{ + struct pt_regs *regs = task->thread.regs; + if (regs != NULL) { +#if defined(CONFIG_PPC32) && (defined(CONFIG_40x) || defined(CONFIG_BOOKE)) + task->thread.dbcr0 = 0; + regs->msr &= ~MSR_DE; +#else + regs->msr &= ~MSR_SE; +#endif + } + clear_tsk_thread_flag(task, TIF_SINGLESTEP); +} + +static inline int tracehook_single_step_enabled(struct task_struct *tsk) +{ + return test_tsk_thread_flag(tsk, TIF_SINGLESTEP); +} + +static inline void tracehook_enable_syscall_trace(struct task_struct *tsk) +{ + set_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE); +} + +static inline void tracehook_disable_syscall_trace(struct task_struct *tsk) +{ + clear_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE); +} + +static inline void tracehook_abort_syscall(struct pt_regs *regs) +{ + regs->orig_gpr3 = -1L; +} + + +extern const struct utrace_regset_view utrace_ppc_native_view; +static inline const struct utrace_regset_view * +utrace_native_view(struct task_struct *tsk) +{ +#ifdef CONFIG_PPC64 + extern const struct utrace_regset_view utrace_ppc32_view; + + if (test_tsk_thread_flag(tsk, TIF_32BIT)) + return &utrace_ppc32_view; +#endif + return &utrace_ppc_native_view; +} + + +#endif diff --git a/include/asm-powerpc/tsi108.h b/include/asm-powerpc/tsi108.h new file mode 100644 index 000000000..2c702d35a --- /dev/null +++ b/include/asm-powerpc/tsi108.h @@ -0,0 +1,111 @@ +/* + * common routine and memory layout for Tundra TSI108(Grendel) host bridge + * memory controller. + * + * Author: Jacob Pan (jacob.pan@freescale.com) + * Alex Bounine (alexandreb@tundra.com) + * + * Copyright 2004-2006 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef __PPC_KERNEL_TSI108_H +#define __PPC_KERNEL_TSI108_H + +#include <asm/pci-bridge.h> + +/* Size of entire register space */ +#define TSI108_REG_SIZE (0x10000) + +/* Sizes of register spaces for individual blocks */ +#define TSI108_HLP_SIZE 0x1000 +#define TSI108_PCI_SIZE 0x1000 +#define TSI108_CLK_SIZE 0x1000 +#define TSI108_PB_SIZE 0x1000 +#define TSI108_SD_SIZE 0x1000 +#define TSI108_DMA_SIZE 0x1000 +#define TSI108_ETH_SIZE 0x1000 +#define TSI108_I2C_SIZE 0x400 +#define TSI108_MPIC_SIZE 0x400 +#define TSI108_UART0_SIZE 0x200 +#define TSI108_GPIO_SIZE 0x200 +#define TSI108_UART1_SIZE 0x200 + +/* Offsets within Tsi108(A) CSR space for individual blocks */ +#define TSI108_HLP_OFFSET 0x0000 +#define TSI108_PCI_OFFSET 0x1000 +#define TSI108_CLK_OFFSET 0x2000 +#define TSI108_PB_OFFSET 0x3000 +#define TSI108_SD_OFFSET 0x4000 +#define TSI108_DMA_OFFSET 0x5000 +#define TSI108_ETH_OFFSET 0x6000 +#define TSI108_I2C_OFFSET 0x7000 +#define TSI108_MPIC_OFFSET 0x7400 +#define TSI108_UART0_OFFSET 0x7800 +#define TSI108_GPIO_OFFSET 0x7A00 +#define TSI108_UART1_OFFSET 0x7C00 + +/* Tsi108 registers used by common code components */ +#define TSI108_PCI_CSR (0x004) +#define TSI108_PCI_IRP_CFG_CTL (0x180) +#define TSI108_PCI_IRP_STAT (0x184) +#define TSI108_PCI_IRP_ENABLE (0x188) +#define TSI108_PCI_IRP_INTAD (0x18C) + +#define TSI108_PCI_IRP_STAT_P_INT (0x00400000) +#define TSI108_PCI_IRP_ENABLE_P_INT (0x00400000) + +#define TSI108_CG_PWRUP_STATUS (0x234) + +#define TSI108_PB_ISR (0x00C) +#define TSI108_PB_ERRCS (0x404) +#define TSI108_PB_AERR (0x408) + +#define TSI108_PB_ERRCS_ES (1 << 1) +#define TSI108_PB_ISR_PBS_RD_ERR (1 << 8) + +#define TSI108_PCI_CFG_BASE_PHYS (0xfb000000) +#define TSI108_PCI_CFG_SIZE (0x01000000) +/* Global variables */ + +extern u32 tsi108_pci_cfg_base; +/* Exported functions */ + +extern int tsi108_bridge_init(struct pci_controller *hose, uint phys_csr_base); +extern unsigned long tsi108_get_mem_size(void); +extern unsigned long tsi108_get_cpu_clk(void); +extern unsigned long tsi108_get_sdc_clk(void); +extern int tsi108_direct_write_config(struct pci_bus *bus, unsigned int devfn, + int offset, int len, u32 val); +extern int tsi108_direct_read_config(struct pci_bus *bus, unsigned int devfn, + int offset, int len, u32 * val); +extern void tsi108_clear_pci_error(u32 pci_cfg_base); + +extern phys_addr_t get_csrbase(void); + +typedef struct { + u32 regs; /* hw registers base address */ + u32 phyregs; /* phy registers base address */ + u16 phy; /* phy address */ + u16 irq_num; /* irq number */ + u8 mac_addr[6]; /* phy mac address */ +} hw_info; + +extern u32 get_vir_csrbase(void); +extern u32 tsi108_csr_vir_base; + +extern inline u32 tsi108_read_reg(u32 reg_offset) +{ + return in_be32((volatile u32 *)(tsi108_csr_vir_base + reg_offset)); +} + +extern inline void tsi108_write_reg(u32 reg_offset, u32 val) +{ + out_be32((volatile u32 *)(tsi108_csr_vir_base + reg_offset), val); +} + +#endif /* __PPC_KERNEL_TSI108_H */ diff --git a/include/asm-powerpc/tsi108_irq.h b/include/asm-powerpc/tsi108_irq.h new file mode 100644 index 000000000..3e4d04eff --- /dev/null +++ b/include/asm-powerpc/tsi108_irq.h @@ -0,0 +1,124 @@ +/* + * (C) Copyright 2005 Tundra Semiconductor Corp. + * Alex Bounine, <alexandreb at tundra.com). + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * definitions for interrupt controller initialization and external interrupt + * demultiplexing on TSI108EMU/SVB boards. + */ + +#ifndef _ASM_PPC_TSI108_IRQ_H +#define _ASM_PPC_TSI108_IRQ_H + +/* + * Tsi108 interrupts + */ +#ifndef TSI108_IRQ_REG_BASE +#define TSI108_IRQ_REG_BASE 0 +#endif + +#define TSI108_IRQ(x) (TSI108_IRQ_REG_BASE + (x)) + +#define TSI108_MAX_VECTORS (36 + 4) /* 36 sources + PCI INT demux */ +#define MAX_TASK_PRIO 0xF + +#define TSI108_IRQ_SPURIOUS (TSI108_MAX_VECTORS) + +#define DEFAULT_PRIO_LVL 10 /* initial priority level */ + +/* Interrupt vectors assignment to external and internal + * sources of requests. */ + +/* EXTERNAL INTERRUPT SOURCES */ + +#define IRQ_TSI108_EXT_INT0 TSI108_IRQ(0) /* External Source at INT[0] */ +#define IRQ_TSI108_EXT_INT1 TSI108_IRQ(1) /* External Source at INT[1] */ +#define IRQ_TSI108_EXT_INT2 TSI108_IRQ(2) /* External Source at INT[2] */ +#define IRQ_TSI108_EXT_INT3 TSI108_IRQ(3) /* External Source at INT[3] */ + +/* INTERNAL INTERRUPT SOURCES */ + +#define IRQ_TSI108_RESERVED0 TSI108_IRQ(4) /* Reserved IRQ */ +#define IRQ_TSI108_RESERVED1 TSI108_IRQ(5) /* Reserved IRQ */ +#define IRQ_TSI108_RESERVED2 TSI108_IRQ(6) /* Reserved IRQ */ +#define IRQ_TSI108_RESERVED3 TSI108_IRQ(7) /* Reserved IRQ */ +#define IRQ_TSI108_DMA0 TSI108_IRQ(8) /* DMA0 */ +#define IRQ_TSI108_DMA1 TSI108_IRQ(9) /* DMA1 */ +#define IRQ_TSI108_DMA2 TSI108_IRQ(10) /* DMA2 */ +#define IRQ_TSI108_DMA3 TSI108_IRQ(11) /* DMA3 */ +#define IRQ_TSI108_UART0 TSI108_IRQ(12) /* UART0 */ +#define IRQ_TSI108_UART1 TSI108_IRQ(13) /* UART1 */ +#define IRQ_TSI108_I2C TSI108_IRQ(14) /* I2C */ +#define IRQ_TSI108_GPIO TSI108_IRQ(15) /* GPIO */ +#define IRQ_TSI108_GIGE0 TSI108_IRQ(16) /* GIGE0 */ +#define IRQ_TSI108_GIGE1 TSI108_IRQ(17) /* GIGE1 */ +#define IRQ_TSI108_RESERVED4 TSI108_IRQ(18) /* Reserved IRQ */ +#define IRQ_TSI108_HLP TSI108_IRQ(19) /* HLP */ +#define IRQ_TSI108_SDRAM TSI108_IRQ(20) /* SDC */ +#define IRQ_TSI108_PROC_IF TSI108_IRQ(21) /* Processor IF */ +#define IRQ_TSI108_RESERVED5 TSI108_IRQ(22) /* Reserved IRQ */ +#define IRQ_TSI108_PCI TSI108_IRQ(23) /* PCI/X block */ + +#define IRQ_TSI108_MBOX0 TSI108_IRQ(24) /* Mailbox 0 register */ +#define IRQ_TSI108_MBOX1 TSI108_IRQ(25) /* Mailbox 1 register */ +#define IRQ_TSI108_MBOX2 TSI108_IRQ(26) /* Mailbox 2 register */ +#define IRQ_TSI108_MBOX3 TSI108_IRQ(27) /* Mailbox 3 register */ + +#define IRQ_TSI108_DBELL0 TSI108_IRQ(28) /* Doorbell 0 */ +#define IRQ_TSI108_DBELL1 TSI108_IRQ(29) /* Doorbell 1 */ +#define IRQ_TSI108_DBELL2 TSI108_IRQ(30) /* Doorbell 2 */ +#define IRQ_TSI108_DBELL3 TSI108_IRQ(31) /* Doorbell 3 */ + +#define IRQ_TSI108_TIMER0 TSI108_IRQ(32) /* Global Timer 0 */ +#define IRQ_TSI108_TIMER1 TSI108_IRQ(33) /* Global Timer 1 */ +#define IRQ_TSI108_TIMER2 TSI108_IRQ(34) /* Global Timer 2 */ +#define IRQ_TSI108_TIMER3 TSI108_IRQ(35) /* Global Timer 3 */ + +/* + * PCI bus INTA# - INTD# lines demultiplexor + */ +#define IRQ_PCI_INTAD_BASE TSI108_IRQ(36) +#define IRQ_PCI_INTA (IRQ_PCI_INTAD_BASE + 0) +#define IRQ_PCI_INTB (IRQ_PCI_INTAD_BASE + 1) +#define IRQ_PCI_INTC (IRQ_PCI_INTAD_BASE + 2) +#define IRQ_PCI_INTD (IRQ_PCI_INTAD_BASE + 3) +#define NUM_PCI_IRQS (4) + +/* number of entries in vector dispatch table */ +#define IRQ_TSI108_TAB_SIZE (TSI108_MAX_VECTORS + 1) + +/* Mapping of MPIC outputs to processors' interrupt pins */ + +#define IDIR_INT_OUT0 0x1 +#define IDIR_INT_OUT1 0x2 +#define IDIR_INT_OUT2 0x4 +#define IDIR_INT_OUT3 0x8 + +/*--------------------------------------------------------------- + * IRQ line configuration parameters */ + +/* Interrupt delivery modes */ +typedef enum { + TSI108_IRQ_DIRECTED, + TSI108_IRQ_DISTRIBUTED, +} TSI108_IRQ_MODE; +#endif /* _ASM_PPC_TSI108_IRQ_H */ diff --git a/include/asm-s390/Kbuild b/include/asm-s390/Kbuild new file mode 100644 index 000000000..14158a4a9 --- /dev/null +++ b/include/asm-s390/Kbuild @@ -0,0 +1,11 @@ +include include/asm-generic/Kbuild.asm + +header-y += dasd.h +header-y += qeth.h +header-y += tape390.h +header-y += ucontext.h +header-y += vtoc.h +header-y += z90crypt.h + +unifdef-y += cmb.h +unifdef-y += debug.h diff --git a/include/asm-s390/irqflags.h b/include/asm-s390/irqflags.h new file mode 100644 index 000000000..3b566a5b3 --- /dev/null +++ b/include/asm-s390/irqflags.h @@ -0,0 +1,56 @@ +/* + * include/asm-s390/irqflags.h + * + * Copyright (C) IBM Corp. 2006 + * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> + */ + +#ifndef __ASM_IRQFLAGS_H +#define __ASM_IRQFLAGS_H + +#ifdef __KERNEL__ + +/* interrupt control.. */ +#define raw_local_irq_enable() ({ \ + unsigned long __dummy; \ + __asm__ __volatile__ ( \ + "stosm 0(%1),0x03" \ + : "=m" (__dummy) : "a" (&__dummy) : "memory" ); \ + }) + +#define raw_local_irq_disable() ({ \ + unsigned long __flags; \ + __asm__ __volatile__ ( \ + "stnsm 0(%1),0xfc" : "=m" (__flags) : "a" (&__flags) ); \ + __flags; \ + }) + +#define raw_local_save_flags(x) \ +do { \ + typecheck(unsigned long, x); \ + __asm__ __volatile__("stosm 0(%1),0" : "=m" (x) : "a" (&x), "m" (x) ); \ +} while (0) + +#define raw_local_irq_restore(x) \ +do { \ + typecheck(unsigned long, x); \ + __asm__ __volatile__("ssm 0(%0)" : : "a" (&x), "m" (x) : "memory"); \ +} while (0) + +#define raw_irqs_disabled() \ +({ \ + unsigned long flags; \ + raw_local_save_flags(flags); \ + !((flags >> __FLAG_SHIFT) & 3); \ +}) + +static inline int raw_irqs_disabled_flags(unsigned long flags) +{ + return !((flags >> __FLAG_SHIFT) & 3); +} + +/* For spinlocks etc */ +#define raw_local_irq_save(x) ((x) = raw_local_irq_disable()) + +#endif /* __KERNEL__ */ +#endif /* __ASM_IRQFLAGS_H */ diff --git a/include/asm-s390/tracehook.h b/include/asm-s390/tracehook.h new file mode 100644 index 000000000..8fc8c3888 --- /dev/null +++ b/include/asm-s390/tracehook.h @@ -0,0 +1,53 @@ +/* + * Tracing hooks, s390/s390x support. + */ + +#ifndef _ASM_TRACEHOOK_H +#define _ASM_TRACEHOOK_H 1 + +#include <linux/sched.h> +#include <asm/ptrace.h> + +/* + * See linux/tracehook.h for the descriptions of what these need to do. + */ + +#define ARCH_HAS_SINGLE_STEP (1) + +/* These three are defined in arch/s390/kernel/ptrace.c. */ +void tracehook_enable_single_step(struct task_struct *tsk); +void tracehook_disable_single_step(struct task_struct *tsk); +int tracehook_single_step_enabled(struct task_struct *tsk); + + +static inline void tracehook_enable_syscall_trace(struct task_struct *tsk) +{ + set_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE); +} + +static inline void tracehook_disable_syscall_trace(struct task_struct *tsk) +{ + clear_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE); +} + +static inline void tracehook_abort_syscall(struct pt_regs *regs) +{ + regs->gprs[2] = -1L; +} + + +extern const struct utrace_regset_view utrace_s390_native_view; +static inline const struct utrace_regset_view * +utrace_native_view(struct task_struct *tsk) +{ +#ifdef CONFIG_COMPAT + extern const struct utrace_regset_view utrace_s390_compat_view; + + if (test_tsk_thread_flag(tsk, TIF_31BIT)) + return &utrace_s390_compat_view; +#endif + return &utrace_s390_native_view; +} + + +#endif diff --git a/include/asm-s390/z90crypt.h b/include/asm-s390/z90crypt.h new file mode 100644 index 000000000..31a2439b0 --- /dev/null +++ b/include/asm-s390/z90crypt.h @@ -0,0 +1,212 @@ +/* + * include/asm-s390/z90crypt.h + * + * z90crypt 1.3.3 (user-visible header) + * + * Copyright (C) 2001, 2005 IBM Corporation + * Author(s): Robert Burroughs + * Eric Rossman (edrossma@us.ibm.com) + * + * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ASM_S390_Z90CRYPT_H +#define __ASM_S390_Z90CRYPT_H +#include <linux/ioctl.h> + +#define z90crypt_VERSION 1 +#define z90crypt_RELEASE 3 // 2 = PCIXCC, 3 = rewrite for coding standards +#define z90crypt_VARIANT 3 // 3 = CEX2A support + +/** + * struct ica_rsa_modexpo + * + * Requirements: + * - outputdatalength is at least as large as inputdatalength. + * - All key parts are right justified in their fields, padded on + * the left with zeroes. + * - length(b_key) = inputdatalength + * - length(n_modulus) = inputdatalength + */ +struct ica_rsa_modexpo { + char __user * inputdata; + unsigned int inputdatalength; + char __user * outputdata; + unsigned int outputdatalength; + char __user * b_key; + char __user * n_modulus; +}; + +/** + * struct ica_rsa_modexpo_crt + * + * Requirements: + * - inputdatalength is even. + * - outputdatalength is at least as large as inputdatalength. + * - All key parts are right justified in their fields, padded on + * the left with zeroes. + * - length(bp_key) = inputdatalength/2 + 8 + * - length(bq_key) = inputdatalength/2 + * - length(np_key) = inputdatalength/2 + 8 + * - length(nq_key) = inputdatalength/2 + * - length(u_mult_inv) = inputdatalength/2 + 8 + */ +struct ica_rsa_modexpo_crt { + char __user * inputdata; + unsigned int inputdatalength; + char __user * outputdata; + unsigned int outputdatalength; + char __user * bp_key; + char __user * bq_key; + char __user * np_prime; + char __user * nq_prime; + char __user * u_mult_inv; +}; + +#define Z90_IOCTL_MAGIC 'z' // NOTE: Need to allocate from linux folks + +/** + * Interface notes: + * + * The ioctl()s which are implemented (along with relevant details) + * are: + * + * ICARSAMODEXPO + * Perform an RSA operation using a Modulus-Exponent pair + * This takes an ica_rsa_modexpo struct as its arg. + * + * NOTE: please refer to the comments preceding this structure + * for the implementation details for the contents of the + * block + * + * ICARSACRT + * Perform an RSA operation using a Chinese-Remainder Theorem key + * This takes an ica_rsa_modexpo_crt struct as its arg. + * + * NOTE: please refer to the comments preceding this structure + * for the implementation details for the contents of the + * block + * + * Z90STAT_TOTALCOUNT + * Return an integer count of all device types together. + * + * Z90STAT_PCICACOUNT + * Return an integer count of all PCICAs. + * + * Z90STAT_PCICCCOUNT + * Return an integer count of all PCICCs. + * + * Z90STAT_PCIXCCMCL2COUNT + * Return an integer count of all MCL2 PCIXCCs. + * + * Z90STAT_PCIXCCMCL3COUNT + * Return an integer count of all MCL3 PCIXCCs. + * + * Z90STAT_CEX2CCOUNT + * Return an integer count of all CEX2Cs. + * + * Z90STAT_CEX2ACOUNT + * Return an integer count of all CEX2As. + * + * Z90STAT_REQUESTQ_COUNT + * Return an integer count of the number of entries waiting to be + * sent to a device. + * + * Z90STAT_PENDINGQ_COUNT + * Return an integer count of the number of entries sent to a + * device awaiting the reply. + * + * Z90STAT_TOTALOPEN_COUNT + * Return an integer count of the number of open file handles. + * + * Z90STAT_DOMAIN_INDEX + * Return the integer value of the Cryptographic Domain. + * + * Z90STAT_STATUS_MASK + * Return an 64 element array of unsigned chars for the status of + * all devices. + * 0x01: PCICA + * 0x02: PCICC + * 0x03: PCIXCC_MCL2 + * 0x04: PCIXCC_MCL3 + * 0x05: CEX2C + * 0x06: CEX2A + * 0x0d: device is disabled via the proc filesystem + * + * Z90STAT_QDEPTH_MASK + * Return an 64 element array of unsigned chars for the queue + * depth of all devices. + * + * Z90STAT_PERDEV_REQCNT + * Return an 64 element array of unsigned integers for the number + * of successfully completed requests per device since the device + * was detected and made available. + * + * ICAZ90STATUS (deprecated) + * Return some device driver status in a ica_z90_status struct + * This takes an ica_z90_status struct as its arg. + * + * NOTE: this ioctl() is deprecated, and has been replaced with + * single ioctl()s for each type of status being requested + * + * Z90STAT_PCIXCCCOUNT (deprecated) + * Return an integer count of all PCIXCCs (MCL2 + MCL3). + * This is DEPRECATED now that MCL3 PCIXCCs are treated differently from + * MCL2 PCIXCCs. + * + * Z90QUIESCE (not recommended) + * Quiesce the driver. This is intended to stop all new + * requests from being processed. Its use is NOT recommended, + * except in circumstances where there is no other way to stop + * callers from accessing the driver. Its original use was to + * allow the driver to be "drained" of work in preparation for + * a system shutdown. + * + * NOTE: once issued, this ban on new work cannot be undone + * except by unloading and reloading the driver. + */ + +/** + * Supported ioctl calls + */ +#define ICARSAMODEXPO _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x05, 0) +#define ICARSACRT _IOC(_IOC_READ|_IOC_WRITE, Z90_IOCTL_MAGIC, 0x06, 0) + +/* DEPRECATED status calls (bound for removal at some point) */ +#define ICAZ90STATUS _IOR(Z90_IOCTL_MAGIC, 0x10, struct ica_z90_status) +#define Z90STAT_PCIXCCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x43, int) + +/* unrelated to ICA callers */ +#define Z90QUIESCE _IO(Z90_IOCTL_MAGIC, 0x11) + +/* New status calls */ +#define Z90STAT_TOTALCOUNT _IOR(Z90_IOCTL_MAGIC, 0x40, int) +#define Z90STAT_PCICACOUNT _IOR(Z90_IOCTL_MAGIC, 0x41, int) +#define Z90STAT_PCICCCOUNT _IOR(Z90_IOCTL_MAGIC, 0x42, int) +#define Z90STAT_PCIXCCMCL2COUNT _IOR(Z90_IOCTL_MAGIC, 0x4b, int) +#define Z90STAT_PCIXCCMCL3COUNT _IOR(Z90_IOCTL_MAGIC, 0x4c, int) +#define Z90STAT_CEX2CCOUNT _IOR(Z90_IOCTL_MAGIC, 0x4d, int) +#define Z90STAT_CEX2ACOUNT _IOR(Z90_IOCTL_MAGIC, 0x4e, int) +#define Z90STAT_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int) +#define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int) +#define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int) +#define Z90STAT_DOMAIN_INDEX _IOR(Z90_IOCTL_MAGIC, 0x47, int) +#define Z90STAT_STATUS_MASK _IOR(Z90_IOCTL_MAGIC, 0x48, char[64]) +#define Z90STAT_QDEPTH_MASK _IOR(Z90_IOCTL_MAGIC, 0x49, char[64]) +#define Z90STAT_PERDEV_REQCNT _IOR(Z90_IOCTL_MAGIC, 0x4a, int[64]) + +#endif /* __ASM_S390_Z90CRYPT_H */ diff --git a/include/asm-sh/Kbuild b/include/asm-sh/Kbuild new file mode 100644 index 000000000..c68e1680d --- /dev/null +++ b/include/asm-sh/Kbuild @@ -0,0 +1 @@ +include include/asm-generic/Kbuild.asm diff --git a/include/asm-sh64/Kbuild b/include/asm-sh64/Kbuild new file mode 100644 index 000000000..c68e1680d --- /dev/null +++ b/include/asm-sh64/Kbuild @@ -0,0 +1 @@ +include include/asm-generic/Kbuild.asm diff --git a/include/asm-sparc/Kbuild b/include/asm-sparc/Kbuild new file mode 100644 index 000000000..c6a55cf0d --- /dev/null +++ b/include/asm-sparc/Kbuild @@ -0,0 +1,15 @@ +include include/asm-generic/Kbuild.asm + +header-y += apc.h +header-y += asi.h +header-y += bpp.h +header-y += jsflash.h +header-y += openpromio.h +header-y += pconf.h +header-y += reg.h +header-y += traps.h +header-y += vfc_ioctls.h + +unifdef-y += fbio.h +unifdef-y += perfctr.h +unifdef-y += psr.h diff --git a/include/asm-sparc/of_device.h b/include/asm-sparc/of_device.h new file mode 100644 index 000000000..80ea31f6e --- /dev/null +++ b/include/asm-sparc/of_device.h @@ -0,0 +1,79 @@ +#ifndef _ASM_SPARC_OF_DEVICE_H +#define _ASM_SPARC_OF_DEVICE_H +#ifdef __KERNEL__ + +#include <linux/device.h> +#include <linux/mod_devicetable.h> +#include <asm/openprom.h> +#include <asm/prom.h> + +extern struct bus_type ebus_bus_type; +extern struct bus_type sbus_bus_type; +extern struct bus_type of_bus_type; + +/* + * The of_device is a kind of "base class" that is a superset of + * struct device for use by devices attached to an OF node and + * probed using OF properties. + */ +struct of_device +{ + struct device_node *node; + struct device dev; + struct resource resource[PROMREG_MAX]; + unsigned int irqs[PROMINTR_MAX]; + int num_irqs; + + void *sysdata; + + int slot; + int portid; + int clock_freq; +}; +#define to_of_device(d) container_of(d, struct of_device, dev) + +extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name); +extern void of_iounmap(void __iomem *base, unsigned long size); + +extern struct of_device *of_find_device_by_node(struct device_node *); + +extern const struct of_device_id *of_match_device( + const struct of_device_id *matches, const struct of_device *dev); + +extern struct of_device *of_dev_get(struct of_device *dev); +extern void of_dev_put(struct of_device *dev); + +/* + * An of_platform_driver driver is attached to a basic of_device on + * the ISA, EBUS, and SBUS busses on sparc64. + */ +struct of_platform_driver +{ + char *name; + struct of_device_id *match_table; + struct module *owner; + + int (*probe)(struct of_device* dev, const struct of_device_id *match); + int (*remove)(struct of_device* dev); + + int (*suspend)(struct of_device* dev, pm_message_t state); + int (*resume)(struct of_device* dev); + int (*shutdown)(struct of_device* dev); + + struct device_driver driver; +}; +#define to_of_platform_driver(drv) container_of(drv,struct of_platform_driver, driver) + +extern int of_register_driver(struct of_platform_driver *drv, + struct bus_type *bus); +extern void of_unregister_driver(struct of_platform_driver *drv); +extern int of_device_register(struct of_device *ofdev); +extern void of_device_unregister(struct of_device *ofdev); +extern struct of_device *of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent, + struct bus_type *bus); +extern void of_release_dev(struct device *dev); + +#endif /* __KERNEL__ */ +#endif /* _ASM_SPARC_OF_DEVICE_H */ diff --git a/include/asm-sparc/prom.h b/include/asm-sparc/prom.h new file mode 100644 index 000000000..86c13dcce --- /dev/null +++ b/include/asm-sparc/prom.h @@ -0,0 +1,104 @@ +#ifndef _SPARC_PROM_H +#define _SPARC_PROM_H +#ifdef __KERNEL__ + + +/* + * Definitions for talking to the Open Firmware PROM on + * Power Macintosh computers. + * + * Copyright (C) 1996-2005 Paul Mackerras. + * + * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp. + * Updates for SPARC32 by David S. Miller + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/types.h> +#include <linux/proc_fs.h> +#include <asm/atomic.h> + +typedef u32 phandle; +typedef u32 ihandle; + +struct property { + char *name; + int length; + void *value; + struct property *next; + unsigned long _flags; + unsigned int unique_id; +}; + +struct device_node { + char *name; + char *type; + phandle node; + char *path_component_name; + char *full_name; + + struct property *properties; + struct property *deadprops; /* removed properties */ + struct device_node *parent; + struct device_node *child; + struct device_node *sibling; + struct device_node *next; /* next device of same type */ + struct device_node *allnext; /* next in list of all nodes */ + struct proc_dir_entry *pde; /* this node's proc directory */ + struct kref kref; + unsigned long _flags; + void *data; + unsigned int unique_id; +}; + +/* flag descriptions */ +#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ + +#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags) +#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags) + +#define OF_BAD_ADDR ((u64)-1) + +static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de) +{ + dn->pde = de; +} + +extern struct device_node *of_find_node_by_name(struct device_node *from, + const char *name); +#define for_each_node_by_name(dn, name) \ + for (dn = of_find_node_by_name(NULL, name); dn; \ + dn = of_find_node_by_name(dn, name)) +extern struct device_node *of_find_node_by_type(struct device_node *from, + const char *type); +#define for_each_node_by_type(dn, type) \ + for (dn = of_find_node_by_type(NULL, type); dn; \ + dn = of_find_node_by_type(dn, type)) +extern struct device_node *of_find_compatible_node(struct device_node *from, + const char *type, const char *compat); +extern struct device_node *of_find_node_by_path(const char *path); +extern struct device_node *of_find_node_by_phandle(phandle handle); +extern struct device_node *of_get_parent(const struct device_node *node); +extern struct device_node *of_get_next_child(const struct device_node *node, + struct device_node *prev); +extern struct property *of_find_property(struct device_node *np, + const char *name, + int *lenp); +extern int of_device_is_compatible(struct device_node *device, const char *); +extern void *of_get_property(struct device_node *node, const char *name, + int *lenp); +extern int of_set_property(struct device_node *node, const char *name, void *val, int len); +extern int of_getintprop_default(struct device_node *np, + const char *name, + int def); +extern int of_n_addr_cells(struct device_node *np); +extern int of_n_size_cells(struct device_node *np); + +extern void prom_build_devicetree(void); + +#endif /* __KERNEL__ */ +#endif /* _SPARC_PROM_H */ diff --git a/include/asm-sparc64/Kbuild b/include/asm-sparc64/Kbuild new file mode 100644 index 000000000..a7f44408c --- /dev/null +++ b/include/asm-sparc64/Kbuild @@ -0,0 +1,26 @@ +include include/asm-generic/Kbuild.asm + +ALTARCH := sparc +ARCHDEF := defined __sparc__ && defined __arch64__ +ALTARCHDEF := defined __sparc__ && !defined __arch64__ + +header-y += apb.h +header-y += asi.h +header-y += bbc.h +header-y += bpp.h +header-y += const.h +header-y += display7seg.h +header-y += envctrl.h +header-y += ipc.h +header-y += openprom.h +header-y += openpromio.h +header-y += pconf.h +header-y += psrcompat.h +header-y += pstate.h +header-y += reg.h +header-y += uctx.h +header-y += utrap.h +header-y += watchdog.h + +unifdef-y += fbio.h +unifdef-y += perfctr.h diff --git a/include/asm-sparc64/of_device.h b/include/asm-sparc64/of_device.h new file mode 100644 index 000000000..a62c7b997 --- /dev/null +++ b/include/asm-sparc64/of_device.h @@ -0,0 +1,80 @@ +#ifndef _ASM_SPARC64_OF_DEVICE_H +#define _ASM_SPARC64_OF_DEVICE_H +#ifdef __KERNEL__ + +#include <linux/device.h> +#include <linux/mod_devicetable.h> +#include <asm/openprom.h> +#include <asm/prom.h> + +extern struct bus_type isa_bus_type; +extern struct bus_type ebus_bus_type; +extern struct bus_type sbus_bus_type; +extern struct bus_type of_bus_type; + +/* + * The of_device is a kind of "base class" that is a superset of + * struct device for use by devices attached to an OF node and + * probed using OF properties. + */ +struct of_device +{ + struct device_node *node; + struct device dev; + struct resource resource[PROMREG_MAX]; + unsigned int irqs[PROMINTR_MAX]; + int num_irqs; + + void *sysdata; + + int slot; + int portid; + int clock_freq; +}; +#define to_of_device(d) container_of(d, struct of_device, dev) + +extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name); +extern void of_iounmap(void __iomem *base, unsigned long size); + +extern struct of_device *of_find_device_by_node(struct device_node *); + +extern const struct of_device_id *of_match_device( + const struct of_device_id *matches, const struct of_device *dev); + +extern struct of_device *of_dev_get(struct of_device *dev); +extern void of_dev_put(struct of_device *dev); + +/* + * An of_platform_driver driver is attached to a basic of_device on + * the ISA, EBUS, and SBUS busses on sparc64. + */ +struct of_platform_driver +{ + char *name; + struct of_device_id *match_table; + struct module *owner; + + int (*probe)(struct of_device* dev, const struct of_device_id *match); + int (*remove)(struct of_device* dev); + + int (*suspend)(struct of_device* dev, pm_message_t state); + int (*resume)(struct of_device* dev); + int (*shutdown)(struct of_device* dev); + + struct device_driver driver; +}; +#define to_of_platform_driver(drv) container_of(drv,struct of_platform_driver, driver) + +extern int of_register_driver(struct of_platform_driver *drv, + struct bus_type *bus); +extern void of_unregister_driver(struct of_platform_driver *drv); +extern int of_device_register(struct of_device *ofdev); +extern void of_device_unregister(struct of_device *ofdev); +extern struct of_device *of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent, + struct bus_type *bus); +extern void of_release_dev(struct device *dev); + +#endif /* __KERNEL__ */ +#endif /* _ASM_SPARC64_OF_DEVICE_H */ diff --git a/include/asm-sparc64/prom.h b/include/asm-sparc64/prom.h new file mode 100644 index 000000000..99671ed66 --- /dev/null +++ b/include/asm-sparc64/prom.h @@ -0,0 +1,112 @@ +#ifndef _SPARC64_PROM_H +#define _SPARC64_PROM_H +#ifdef __KERNEL__ + + +/* + * Definitions for talking to the Open Firmware PROM on + * Power Macintosh computers. + * + * Copyright (C) 1996-2005 Paul Mackerras. + * + * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp. + * Updates for SPARC64 by David S. Miller + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/types.h> +#include <linux/proc_fs.h> +#include <asm/atomic.h> + +typedef u32 phandle; +typedef u32 ihandle; + +struct property { + char *name; + int length; + void *value; + struct property *next; + unsigned long _flags; + unsigned int unique_id; +}; + +struct of_irq_controller; +struct device_node { + char *name; + char *type; + phandle node; + char *path_component_name; + char *full_name; + + struct property *properties; + struct property *deadprops; /* removed properties */ + struct device_node *parent; + struct device_node *child; + struct device_node *sibling; + struct device_node *next; /* next device of same type */ + struct device_node *allnext; /* next in list of all nodes */ + struct proc_dir_entry *pde; /* this node's proc directory */ + struct kref kref; + unsigned long _flags; + void *data; + unsigned int unique_id; + + struct of_irq_controller *irq_trans; +}; + +struct of_irq_controller { + unsigned int (*irq_build)(struct device_node *, unsigned int, void *); + void *data; +}; + +/* flag descriptions */ +#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ + +#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags) +#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags) + +#define OF_BAD_ADDR ((u64)-1) + +static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de) +{ + dn->pde = de; +} + +extern struct device_node *of_find_node_by_name(struct device_node *from, + const char *name); +#define for_each_node_by_name(dn, name) \ + for (dn = of_find_node_by_name(NULL, name); dn; \ + dn = of_find_node_by_name(dn, name)) +extern struct device_node *of_find_node_by_type(struct device_node *from, + const char *type); +#define for_each_node_by_type(dn, type) \ + for (dn = of_find_node_by_type(NULL, type); dn; \ + dn = of_find_node_by_type(dn, type)) +extern struct device_node *of_find_compatible_node(struct device_node *from, + const char *type, const char *compat); +extern struct device_node *of_find_node_by_path(const char *path); +extern struct device_node *of_find_node_by_phandle(phandle handle); +extern struct device_node *of_get_parent(const struct device_node *node); +extern struct device_node *of_get_next_child(const struct device_node *node, + struct device_node *prev); +extern struct property *of_find_property(struct device_node *np, + const char *name, + int *lenp); +extern int of_device_is_compatible(struct device_node *device, const char *); +extern void *of_get_property(struct device_node *node, const char *name, + int *lenp); +extern int of_set_property(struct device_node *node, const char *name, void *val, int len); +extern int of_getintprop_default(struct device_node *np, + const char *name, + int def); +extern int of_n_addr_cells(struct device_node *np); +extern int of_n_size_cells(struct device_node *np); + +extern void prom_build_devicetree(void); + +#endif /* __KERNEL__ */ +#endif /* _SPARC64_PROM_H */ diff --git a/include/asm-sparc64/tracehook.h b/include/asm-sparc64/tracehook.h new file mode 100644 index 000000000..fbcdae196 --- /dev/null +++ b/include/asm-sparc64/tracehook.h @@ -0,0 +1,44 @@ +/* + * Tracing hooks, SPARC64 CPU support + */ + +#ifndef _ASM_TRACEHOOK_H +#define _ASM_TRACEHOOK_H 1 + + +#include <linux/sched.h> +#include <asm/ptrace.h> + +/* + * See linux/tracehook.h for the descriptions of what these need to do. + */ + + +static inline void tracehook_enable_syscall_trace(struct task_struct *tsk) +{ + set_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE); +} + +static inline void tracehook_disable_syscall_trace(struct task_struct *tsk) +{ + clear_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE); +} + +static inline void tracehook_abort_syscall(struct pt_regs *regs) +{ + regs->u_regs[UREG_G1] = -1L; +} + +extern const struct utrace_regset_view utrace_sparc64_native_view; +static inline const struct utrace_regset_view * +utrace_native_view(struct task_struct *tsk) +{ +#ifdef CONFIG_COMPAT + extern const struct utrace_regset_view utrace_sparc32_view; + if (test_tsk_thread_flag(tsk, TIF_32BIT)) + return &utrace_sparc32_view; +#endif + return &utrace_sparc64_native_view; +} + +#endif diff --git a/include/asm-v850/Kbuild b/include/asm-v850/Kbuild new file mode 100644 index 000000000..c68e1680d --- /dev/null +++ b/include/asm-v850/Kbuild @@ -0,0 +1 @@ +include include/asm-generic/Kbuild.asm diff --git a/include/asm-x86_64/Kbuild b/include/asm-x86_64/Kbuild new file mode 100644 index 000000000..40f2f13fe --- /dev/null +++ b/include/asm-x86_64/Kbuild @@ -0,0 +1,21 @@ +include include/asm-generic/Kbuild.asm + +ALTARCH := i386 +ARCHDEF := defined __x86_64__ +ALTARCHDEF := defined __i386__ + +header-y += boot.h +header-y += bootsetup.h +header-y += cpufeature.h +header-y += debugreg.h +header-y += ldt.h +header-y += msr.h +header-y += prctl.h +header-y += setup.h +header-y += sigcontext32.h +header-y += ucontext.h +header-y += vsyscall32.h + +unifdef-y += mce.h +unifdef-y += mtrr.h +unifdef-y += vsyscall.h diff --git a/include/asm-x86_64/alternative-asm.i b/include/asm-x86_64/alternative-asm.i new file mode 100644 index 000000000..0b3f1a2bb --- /dev/null +++ b/include/asm-x86_64/alternative-asm.i @@ -0,0 +1,12 @@ +#ifdef CONFIG_SMP + .macro LOCK_PREFIX +1: lock + .section .smp_locks,"a" + .align 8 + .quad 1b + .previous + .endm +#else + .macro LOCK_PREFIX + .endm +#endif diff --git a/include/asm-x86_64/alternative.h b/include/asm-x86_64/alternative.h new file mode 100644 index 000000000..a584826cc --- /dev/null +++ b/include/asm-x86_64/alternative.h @@ -0,0 +1,136 @@ +#ifndef _X86_64_ALTERNATIVE_H +#define _X86_64_ALTERNATIVE_H + +#ifdef __KERNEL__ + +#include <linux/types.h> +#include <asm/cpufeature.h> + +struct alt_instr { + u8 *instr; /* original instruction */ + u8 *replacement; + u8 cpuid; /* cpuid bit set for replacement */ + u8 instrlen; /* length of original instruction */ + u8 replacementlen; /* length of new instruction, <= instrlen */ + u8 pad[5]; +}; + +extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end); + +struct module; + +#ifdef CONFIG_SMP +extern void alternatives_smp_module_add(struct module *mod, char *name, + void *locks, void *locks_end, + void *text, void *text_end); +extern void alternatives_smp_module_del(struct module *mod); +extern void alternatives_smp_switch(int smp); +#else +static inline void alternatives_smp_module_add(struct module *mod, char *name, + void *locks, void *locks_end, + void *text, void *text_end) {} +static inline void alternatives_smp_module_del(struct module *mod) {} +static inline void alternatives_smp_switch(int smp) {} +#endif + +#endif + +/* + * Alternative instructions for different CPU types or capabilities. + * + * This allows to use optimized instructions even on generic binary + * kernels. + * + * length of oldinstr must be longer or equal the length of newinstr + * It can be padded with nops as needed. + * + * For non barrier like inlines please define new variants + * without volatile and memory clobber. + */ +#define alternative(oldinstr, newinstr, feature) \ + asm volatile ("661:\n\t" oldinstr "\n662:\n" \ + ".section .altinstructions,\"a\"\n" \ + " .align 8\n" \ + " .quad 661b\n" /* label */ \ + " .quad 663f\n" /* new instruction */ \ + " .byte %c0\n" /* feature bit */ \ + " .byte 662b-661b\n" /* sourcelen */ \ + " .byte 664f-663f\n" /* replacementlen */ \ + ".previous\n" \ + ".section .altinstr_replacement,\"ax\"\n" \ + "663:\n\t" newinstr "\n664:\n" /* replacement */ \ + ".previous" :: "i" (feature) : "memory") + +/* + * Alternative inline assembly with input. + * + * Pecularities: + * No memory clobber here. + * Argument numbers start with 1. + * Best is to use constraints that are fixed size (like (%1) ... "r") + * If you use variable sized constraints like "m" or "g" in the + * replacement make sure to pad to the worst case length. + */ +#define alternative_input(oldinstr, newinstr, feature, input...) \ + asm volatile ("661:\n\t" oldinstr "\n662:\n" \ + ".section .altinstructions,\"a\"\n" \ + " .align 8\n" \ + " .quad 661b\n" /* label */ \ + " .quad 663f\n" /* new instruction */ \ + " .byte %c0\n" /* feature bit */ \ + " .byte 662b-661b\n" /* sourcelen */ \ + " .byte 664f-663f\n" /* replacementlen */ \ + ".previous\n" \ + ".section .altinstr_replacement,\"ax\"\n" \ + "663:\n\t" newinstr "\n664:\n" /* replacement */ \ + ".previous" :: "i" (feature), ##input) + +/* Like alternative_input, but with a single output argument */ +#define alternative_io(oldinstr, newinstr, feature, output, input...) \ + asm volatile ("661:\n\t" oldinstr "\n662:\n" \ + ".section .altinstructions,\"a\"\n" \ + " .align 8\n" \ + " .quad 661b\n" /* label */ \ + " .quad 663f\n" /* new instruction */ \ + " .byte %c[feat]\n" /* feature bit */ \ + " .byte 662b-661b\n" /* sourcelen */ \ + " .byte 664f-663f\n" /* replacementlen */ \ + ".previous\n" \ + ".section .altinstr_replacement,\"ax\"\n" \ + "663:\n\t" newinstr "\n664:\n" /* replacement */ \ + ".previous" : output : [feat] "i" (feature), ##input) + +/* + * Alternative inline assembly for SMP. + * + * The LOCK_PREFIX macro defined here replaces the LOCK and + * LOCK_PREFIX macros used everywhere in the source tree. + * + * SMP alternatives use the same data structures as the other + * alternatives and the X86_FEATURE_UP flag to indicate the case of a + * UP system running a SMP kernel. The existing apply_alternatives() + * works fine for patching a SMP kernel for UP. + * + * The SMP alternative tables can be kept after boot and contain both + * UP and SMP versions of the instructions to allow switching back to + * SMP at runtime, when hotplugging in a new CPU, which is especially + * useful in virtualized environments. + * + * The very common lock prefix is handled as special case in a + * separate table which is a pure address list without replacement ptr + * and size information. That keeps the table sizes small. + */ + +#ifdef CONFIG_SMP +#define LOCK_PREFIX \ + ".section .smp_locks,\"a\"\n" \ + " .align 8\n" \ + " .quad 661f\n" /* address */ \ + ".previous\n" \ + "661:\n\tlock; " + +#else /* ! CONFIG_SMP */ +#define LOCK_PREFIX "" +#endif + +#endif /* _X86_64_ALTERNATIVE_H */ diff --git a/include/asm-x86_64/calgary.h b/include/asm-x86_64/calgary.h new file mode 100644 index 000000000..82d8de726 --- /dev/null +++ b/include/asm-x86_64/calgary.h @@ -0,0 +1,62 @@ +/* + * Derived from include/asm-powerpc/iommu.h + * + * Copyright (C) IBM Corporation, 2006 + * + * Author: Jon Mason <jdmason@us.ibm.com> + * Author: Muli Ben-Yehuda <muli@il.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ASM_X86_64_CALGARY_H +#define _ASM_X86_64_CALGARY_H + +#include <linux/spinlock.h> +#include <linux/device.h> +#include <linux/dma-mapping.h> +#include <asm/types.h> + +struct iommu_table { + unsigned long it_base; /* mapped address of tce table */ + unsigned long it_hint; /* Hint for next alloc */ + unsigned long *it_map; /* A simple allocation bitmap for now */ + spinlock_t it_lock; /* Protects it_map */ + unsigned int it_size; /* Size of iommu table in entries */ + unsigned char it_busno; /* Bus number this table belongs to */ + void __iomem *bbar; + u64 tar_val; + struct timer_list watchdog_timer; +}; + +#define TCE_TABLE_SIZE_UNSPECIFIED ~0 +#define TCE_TABLE_SIZE_64K 0 +#define TCE_TABLE_SIZE_128K 1 +#define TCE_TABLE_SIZE_256K 2 +#define TCE_TABLE_SIZE_512K 3 +#define TCE_TABLE_SIZE_1M 4 +#define TCE_TABLE_SIZE_2M 5 +#define TCE_TABLE_SIZE_4M 6 +#define TCE_TABLE_SIZE_8M 7 + +#ifdef CONFIG_CALGARY_IOMMU +extern int calgary_iommu_init(void); +extern void detect_calgary(void); +#else +static inline int calgary_iommu_init(void) { return 1; } +static inline void detect_calgary(void) { return; } +#endif + +#endif /* _ASM_X86_64_CALGARY_H */ diff --git a/include/asm-x86_64/intel_arch_perfmon.h b/include/asm-x86_64/intel_arch_perfmon.h new file mode 100644 index 000000000..59c396431 --- /dev/null +++ b/include/asm-x86_64/intel_arch_perfmon.h @@ -0,0 +1,19 @@ +#ifndef X86_64_INTEL_ARCH_PERFMON_H +#define X86_64_INTEL_ARCH_PERFMON_H 1 + +#define MSR_ARCH_PERFMON_PERFCTR0 0xc1 +#define MSR_ARCH_PERFMON_PERFCTR1 0xc2 + +#define MSR_ARCH_PERFMON_EVENTSEL0 0x186 +#define MSR_ARCH_PERFMON_EVENTSEL1 0x187 + +#define ARCH_PERFMON_EVENTSEL0_ENABLE (1 << 22) +#define ARCH_PERFMON_EVENTSEL_INT (1 << 20) +#define ARCH_PERFMON_EVENTSEL_OS (1 << 17) +#define ARCH_PERFMON_EVENTSEL_USR (1 << 16) + +#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL (0x3c) +#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK (0x00 << 8) +#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT (1 << 0) + +#endif /* X86_64_INTEL_ARCH_PERFMON_H */ diff --git a/include/asm-x86_64/irqflags.h b/include/asm-x86_64/irqflags.h new file mode 100644 index 000000000..cce6937e8 --- /dev/null +++ b/include/asm-x86_64/irqflags.h @@ -0,0 +1,141 @@ +/* + * include/asm-x86_64/irqflags.h + * + * IRQ flags handling + * + * This file gets included from lowlevel asm headers too, to provide + * wrapped versions of the local_irq_*() APIs, based on the + * raw_local_irq_*() functions from the lowlevel headers. + */ +#ifndef _ASM_IRQFLAGS_H +#define _ASM_IRQFLAGS_H + +#ifndef __ASSEMBLY__ +/* + * Interrupt control: + */ + +static inline unsigned long __raw_local_save_flags(void) +{ + unsigned long flags; + + __asm__ __volatile__( + "# __raw_save_flags\n\t" + "pushfq ; popq %q0" + : "=g" (flags) + : /* no input */ + : "memory" + ); + + return flags; +} + +#define raw_local_save_flags(flags) \ + do { (flags) = __raw_local_save_flags(); } while (0) + +static inline void raw_local_irq_restore(unsigned long flags) +{ + __asm__ __volatile__( + "pushq %0 ; popfq" + : /* no output */ + :"g" (flags) + :"memory", "cc" + ); +} + +#ifdef CONFIG_X86_VSMP + +/* + * Interrupt control for the VSMP architecture: + */ + +static inline void raw_local_irq_disable(void) +{ + unsigned long flags = __raw_local_save_flags(); + + raw_local_irq_restore((flags & ~(1 << 9)) | (1 << 18)); +} + +static inline void raw_local_irq_enable(void) +{ + unsigned long flags = __raw_local_save_flags(); + + raw_local_irq_restore((flags | (1 << 9)) & ~(1 << 18)); +} + +static inline int raw_irqs_disabled_flags(unsigned long flags) +{ + return !(flags & (1<<9)) || (flags & (1 << 18)); +} + +#else /* CONFIG_X86_VSMP */ + +static inline void raw_local_irq_disable(void) +{ + __asm__ __volatile__("cli" : : : "memory"); +} + +static inline void raw_local_irq_enable(void) +{ + __asm__ __volatile__("sti" : : : "memory"); +} + +static inline int raw_irqs_disabled_flags(unsigned long flags) +{ + return !(flags & (1 << 9)); +} + +#endif + +/* + * For spinlocks, etc.: + */ + +static inline unsigned long __raw_local_irq_save(void) +{ + unsigned long flags = __raw_local_save_flags(); + + raw_local_irq_disable(); + + return flags; +} + +#define raw_local_irq_save(flags) \ + do { (flags) = __raw_local_irq_save(); } while (0) + +static inline int raw_irqs_disabled(void) +{ + unsigned long flags = __raw_local_save_flags(); + + return raw_irqs_disabled_flags(flags); +} + +/* + * Used in the idle loop; sti takes one instruction cycle + * to complete: + */ +static inline void raw_safe_halt(void) +{ + __asm__ __volatile__("sti; hlt" : : : "memory"); +} + +/* + * Used when interrupts are already enabled or to + * shutdown the processor: + */ +static inline void halt(void) +{ + __asm__ __volatile__("hlt": : :"memory"); +} + +#else /* __ASSEMBLY__: */ +# ifdef CONFIG_TRACE_IRQFLAGS +# define TRACE_IRQS_ON call trace_hardirqs_on_thunk +# define TRACE_IRQS_OFF call trace_hardirqs_off_thunk +# else +# define TRACE_IRQS_ON +# define TRACE_IRQS_OFF +# endif +#endif + +#endif diff --git a/include/asm-x86_64/k8.h b/include/asm-x86_64/k8.h new file mode 100644 index 000000000..699dd6961 --- /dev/null +++ b/include/asm-x86_64/k8.h @@ -0,0 +1,14 @@ +#ifndef _ASM_K8_H +#define _ASM_K8_H 1 + +#include <linux/pci.h> + +extern struct pci_device_id k8_nb_ids[]; + +extern int early_is_k8_nb(u32 value); +extern struct pci_dev **k8_northbridges; +extern int num_k8_northbridges; +extern int cache_k8_northbridges(void); +extern void k8_flush_garts(void); + +#endif diff --git a/include/asm-x86_64/mach-xen/asm/irqflags.h b/include/asm-x86_64/mach-xen/asm/irqflags.h new file mode 100644 index 000000000..7b03e7a73 --- /dev/null +++ b/include/asm-x86_64/mach-xen/asm/irqflags.h @@ -0,0 +1,65 @@ +/* + * include/asm-x86_64/irqflags.h + * + * IRQ flags handling + * + * This file gets included from lowlevel asm headers too, to provide + * wrapped versions of the local_irq_*() APIs, based on the + * raw_local_irq_*() functions from the lowlevel headers. + */ +#ifndef _ASM_IRQFLAGS_H +#define _ASM_IRQFLAGS_H + +#ifndef __ASSEMBLY__ +/* + * Interrupt control: + */ + +unsigned long __raw_local_save_flags(void); +#define raw_local_save_flags(flags) \ + do { (flags) = __raw_local_save_flags(); } while (0) + +void raw_local_irq_restore(unsigned long flags); +void raw_local_irq_disable(void); +void raw_local_irq_enable(void); + +static inline int raw_irqs_disabled_flags(unsigned long flags) +{ + return flags != 0; +} + +/* + * For spinlocks, etc.: + */ + +unsigned long __raw_local_irq_save(void); + +#define raw_local_irq_save(flags) \ + do { (flags) = __raw_local_irq_save(); } while (0) + +int raw_irqs_disabled(void); + +/* + * Used in the idle loop; sti takes one instruction cycle + * to complete: + */ +void raw_safe_halt(void); + + +/* + * Used when interrupts are already enabled or to + * shutdown the processor: + */ +void halt(void); + +#else /* __ASSEMBLY__: */ +# ifdef CONFIG_TRACE_IRQFLAGS +# define TRACE_IRQS_ON call trace_hardirqs_on_thunk +# define TRACE_IRQS_OFF call trace_hardirqs_off_thunk +# else +# define TRACE_IRQS_ON +# define TRACE_IRQS_OFF +# endif +#endif + +#endif diff --git a/include/asm-x86_64/mach-xen/asm/maddr.h b/include/asm-x86_64/mach-xen/asm/maddr.h new file mode 100644 index 000000000..0104de808 --- /dev/null +++ b/include/asm-x86_64/mach-xen/asm/maddr.h @@ -0,0 +1,139 @@ +#ifndef _X86_64_MADDR_H +#define _X86_64_MADDR_H + +#include <xen/features.h> +#include <xen/interface/xen.h> + +/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/ +#define INVALID_P2M_ENTRY (~0UL) +#define FOREIGN_FRAME_BIT (1UL<<63) +#define FOREIGN_FRAME(m) ((m) | FOREIGN_FRAME_BIT) + +#ifdef CONFIG_XEN + +extern unsigned long *phys_to_machine_mapping; + +#undef machine_to_phys_mapping +extern unsigned long *machine_to_phys_mapping; +extern unsigned int machine_to_phys_order; + +static inline unsigned long pfn_to_mfn(unsigned long pfn) +{ + if (xen_feature(XENFEAT_auto_translated_physmap)) + return pfn; + return phys_to_machine_mapping[(unsigned int)(pfn)] & + ~FOREIGN_FRAME_BIT; +} + +static inline int phys_to_machine_mapping_valid(unsigned long pfn) +{ + if (xen_feature(XENFEAT_auto_translated_physmap)) + return 1; + return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY); +} + +static inline unsigned long mfn_to_pfn(unsigned long mfn) +{ + unsigned long pfn; + + if (xen_feature(XENFEAT_auto_translated_physmap)) + return mfn; + + if (unlikely((mfn >> machine_to_phys_order) != 0)) + return end_pfn; + + /* The array access can fail (e.g., device space beyond end of RAM). */ + asm ( + "1: movq %1,%0\n" + "2:\n" + ".section .fixup,\"ax\"\n" + "3: movq %2,%0\n" + " jmp 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 8\n" + " .quad 1b,3b\n" + ".previous" + : "=r" (pfn) + : "m" (machine_to_phys_mapping[mfn]), "m" (end_pfn) ); + + return pfn; +} + +/* + * We detect special mappings in one of two ways: + * 1. If the MFN is an I/O page then Xen will set the m2p entry + * to be outside our maximum possible pseudophys range. + * 2. If the MFN belongs to a different domain then we will certainly + * not have MFN in our p2m table. Conversely, if the page is ours, + * then we'll have p2m(m2p(MFN))==MFN. + * If we detect a special mapping then it doesn't have a 'struct page'. + * We force !pfn_valid() by returning an out-of-range pointer. + * + * NB. These checks require that, for any MFN that is not in our reservation, + * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if + * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN. + * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety. + * + * NB2. When deliberately mapping foreign pages into the p2m table, you *must* + * use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we + * require. In all the cases we care about, the FOREIGN_FRAME bit is + * masked (e.g., pfn_to_mfn()) so behaviour there is correct. + */ +static inline unsigned long mfn_to_local_pfn(unsigned long mfn) +{ + unsigned long pfn = mfn_to_pfn(mfn); + if ((pfn < end_pfn) + && !xen_feature(XENFEAT_auto_translated_physmap) + && (phys_to_machine_mapping[pfn] != mfn)) + return end_pfn; /* force !pfn_valid() */ + return pfn; +} + +static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn) +{ + if (xen_feature(XENFEAT_auto_translated_physmap)) { + BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY); + return; + } + phys_to_machine_mapping[pfn] = mfn; +} + +#else /* !CONFIG_XEN */ + +#define pfn_to_mfn(pfn) (pfn) +#define mfn_to_pfn(mfn) (mfn) +#define mfn_to_local_pfn(mfn) (mfn) +#define set_phys_to_machine(pfn, mfn) BUG_ON((pfn) != (mfn)) +#define phys_to_machine_mapping_valid(pfn) (1) + +#endif /* !CONFIG_XEN */ + +/* Definitions for machine and pseudophysical addresses. */ +typedef unsigned long paddr_t; +typedef unsigned long maddr_t; + +static inline maddr_t phys_to_machine(paddr_t phys) +{ + maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT); + machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK); + return machine; +} + +static inline paddr_t machine_to_phys(maddr_t machine) +{ + paddr_t phys = mfn_to_pfn(machine >> PAGE_SHIFT); + phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK); + return phys; +} + +/* VIRT <-> MACHINE conversion */ +#define virt_to_machine(v) (phys_to_machine(__pa(v))) +#define virt_to_mfn(v) (pfn_to_mfn(__pa(v) >> PAGE_SHIFT)) +#define mfn_to_virt(m) (__va(mfn_to_pfn(m) << PAGE_SHIFT)) + +#define __pte_ma(x) ((pte_t) { (x) } ) +#define pfn_pte_ma(pfn, prot) __pte_ma((((pfn) << PAGE_SHIFT) | pgprot_val(prot)) & __supported_pte_mask) + +#endif /* _X86_64_MADDR_H */ + diff --git a/include/asm-x86_64/mach-xen/asm/stacktrace.h b/include/asm-x86_64/mach-xen/asm/stacktrace.h new file mode 100644 index 000000000..5eb9799be --- /dev/null +++ b/include/asm-x86_64/mach-xen/asm/stacktrace.h @@ -0,0 +1,18 @@ +#ifndef _ASM_STACKTRACE_H +#define _ASM_STACKTRACE_H 1 + +/* Generic stack tracer with callbacks */ + +struct stacktrace_ops { + void (*warning)(void *data, char *msg); + /* msg must contain %s for the symbol */ + void (*warning_symbol)(void *data, char *msg, unsigned long symbol); + void (*address)(void *data, unsigned long address); + /* On negative return stop dumping */ + int (*stack)(void *data, char *name); +}; + +void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack, + struct stacktrace_ops *ops, void *data); + +#endif diff --git a/include/asm-x86_64/stacktrace.h b/include/asm-x86_64/stacktrace.h new file mode 100644 index 000000000..5eb9799be --- /dev/null +++ b/include/asm-x86_64/stacktrace.h @@ -0,0 +1,18 @@ +#ifndef _ASM_STACKTRACE_H +#define _ASM_STACKTRACE_H 1 + +/* Generic stack tracer with callbacks */ + +struct stacktrace_ops { + void (*warning)(void *data, char *msg); + /* msg must contain %s for the symbol */ + void (*warning_symbol)(void *data, char *msg, unsigned long symbol); + void (*address)(void *data, unsigned long address); + /* On negative return stop dumping */ + int (*stack)(void *data, char *name); +}; + +void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack, + struct stacktrace_ops *ops, void *data); + +#endif diff --git a/include/asm-x86_64/tce.h b/include/asm-x86_64/tce.h new file mode 100644 index 000000000..53e9a68b3 --- /dev/null +++ b/include/asm-x86_64/tce.h @@ -0,0 +1,49 @@ +/* + * This file is derived from asm-powerpc/tce.h. + * + * Copyright (C) IBM Corporation, 2006 + * + * Author: Muli Ben-Yehuda <muli@il.ibm.com> + * Author: Jon Mason <jdmason@us.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ASM_X86_64_TCE_H +#define _ASM_X86_64_TCE_H + +extern void* tce_table_kva[]; +extern unsigned int specified_table_size; +struct iommu_table; + +#define TCE_ENTRY_SIZE 8 /* in bytes */ + +#define TCE_READ_SHIFT 0 +#define TCE_WRITE_SHIFT 1 +#define TCE_HUBID_SHIFT 2 /* unused */ +#define TCE_RSVD_SHIFT 8 /* unused */ +#define TCE_RPN_SHIFT 12 +#define TCE_UNUSED_SHIFT 48 /* unused */ + +#define TCE_RPN_MASK 0x0000fffffffff000ULL + +extern void tce_build(struct iommu_table *tbl, unsigned long index, + unsigned int npages, unsigned long uaddr, int direction); +extern void tce_free(struct iommu_table *tbl, long index, unsigned int npages); +extern void* alloc_tce_table(void); +extern void free_tce_table(void *tbl); +extern int build_tce_table(struct pci_dev *dev, void __iomem *bbar); + +#endif /* _ASM_X86_64_TCE_H */ diff --git a/include/asm-x86_64/tracehook.h b/include/asm-x86_64/tracehook.h new file mode 100644 index 000000000..d7588bf94 --- /dev/null +++ b/include/asm-x86_64/tracehook.h @@ -0,0 +1,54 @@ +/* + * Tracing hooks, x86-64 CPU support + */ + +#ifndef _ASM_TRACEHOOK_H +#define _ASM_TRACEHOOK_H 1 + +#include <linux/sched.h> +#include <asm/ptrace.h> +#include <asm/proto.h> + +/* + * See linux/tracehook.h for the descriptions of what these need to do. + */ + +#define ARCH_HAS_SINGLE_STEP (1) + +/* These two are defined in arch/x86_64/kernel/ptrace.c. */ +void tracehook_enable_single_step(struct task_struct *tsk); +void tracehook_disable_single_step(struct task_struct *tsk); + +static inline int tracehook_single_step_enabled(struct task_struct *tsk) +{ + return test_tsk_thread_flag(tsk, TIF_SINGLESTEP); +} + +static inline void tracehook_enable_syscall_trace(struct task_struct *tsk) +{ + set_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE); +} + +static inline void tracehook_disable_syscall_trace(struct task_struct *tsk) +{ + clear_tsk_thread_flag(tsk, TIF_SYSCALL_TRACE); +} + +static inline void tracehook_abort_syscall(struct pt_regs *regs) +{ + regs->orig_rax = -1L; +} + +extern const struct utrace_regset_view utrace_x86_64_native, utrace_ia32_view; +static inline const struct utrace_regset_view * +utrace_native_view(struct task_struct *tsk) +{ +#ifdef CONFIG_IA32_EMULATION + if (test_tsk_thread_flag(tsk, TIF_IA32)) + return &utrace_ia32_view; +#endif + return &utrace_x86_64_native; +} + + +#endif diff --git a/include/asm-x86_64/unwind.h b/include/asm-x86_64/unwind.h new file mode 100644 index 000000000..3b450601a --- /dev/null +++ b/include/asm-x86_64/unwind.h @@ -0,0 +1,107 @@ +#ifndef _ASM_X86_64_UNWIND_H +#define _ASM_X86_64_UNWIND_H + +/* + * Copyright (C) 2002-2006 Novell, Inc. + * Jan Beulich <jbeulich@novell.com> + * This code is released under version 2 of the GNU GPL. + */ + +#ifdef CONFIG_STACK_UNWIND + +#include <linux/sched.h> +#include <asm/ptrace.h> +#include <asm/uaccess.h> +#include <asm/vsyscall.h> + +struct unwind_frame_info +{ + struct pt_regs regs; + struct task_struct *task; +}; + +#define UNW_PC(frame) (frame)->regs.rip +#define UNW_SP(frame) (frame)->regs.rsp +#ifdef CONFIG_FRAME_POINTER +#define UNW_FP(frame) (frame)->regs.rbp +#define FRAME_RETADDR_OFFSET 8 +#define FRAME_LINK_OFFSET 0 +#define STACK_BOTTOM(tsk) (((tsk)->thread.rsp0 - 1) & ~(THREAD_SIZE - 1)) +#define STACK_TOP(tsk) ((tsk)->thread.rsp0) +#endif +/* Might need to account for the special exception and interrupt handling + stacks here, since normally + EXCEPTION_STACK_ORDER < THREAD_ORDER < IRQSTACK_ORDER, + but the construct is needed only for getting across the stack switch to + the interrupt stack - thus considering the IRQ stack itself is unnecessary, + and the overhead of comparing against all exception handling stacks seems + not desirable. */ +#define STACK_LIMIT(ptr) (((ptr) - 1) & ~(THREAD_SIZE - 1)) + +#define UNW_REGISTER_INFO \ + PTREGS_INFO(rax), \ + PTREGS_INFO(rdx), \ + PTREGS_INFO(rcx), \ + PTREGS_INFO(rbx), \ + PTREGS_INFO(rsi), \ + PTREGS_INFO(rdi), \ + PTREGS_INFO(rbp), \ + PTREGS_INFO(rsp), \ + PTREGS_INFO(r8), \ + PTREGS_INFO(r9), \ + PTREGS_INFO(r10), \ + PTREGS_INFO(r11), \ + PTREGS_INFO(r12), \ + PTREGS_INFO(r13), \ + PTREGS_INFO(r14), \ + PTREGS_INFO(r15), \ + PTREGS_INFO(rip) + +static inline void arch_unw_init_frame_info(struct unwind_frame_info *info, + /*const*/ struct pt_regs *regs) +{ + info->regs = *regs; +} + +static inline void arch_unw_init_blocked(struct unwind_frame_info *info) +{ + extern const char thread_return[]; + + memset(&info->regs, 0, sizeof(info->regs)); + info->regs.rip = (unsigned long)thread_return; + info->regs.cs = __KERNEL_CS; + __get_user(info->regs.rbp, (unsigned long *)info->task->thread.rsp); + info->regs.rsp = info->task->thread.rsp; + info->regs.ss = __KERNEL_DS; +} + +extern int arch_unwind_init_running(struct unwind_frame_info *, + int (*callback)(struct unwind_frame_info *, + void *arg), + void *arg); + +static inline int arch_unw_user_mode(const struct unwind_frame_info *info) +{ +#if 0 /* This can only work when selector register saves/restores + are properly annotated (and tracked in UNW_REGISTER_INFO). */ + return user_mode(&info->regs); +#else + return (long)info->regs.rip >= 0 + || (info->regs.rip >= VSYSCALL_START && info->regs.rip < VSYSCALL_END) + || (long)info->regs.rsp >= 0; +#endif +} + +#else + +#define UNW_PC(frame) ((void)(frame), 0UL) +#define UNW_SP(frame) ((void)(frame), 0UL) + +static inline int arch_unw_user_mode(const void *info) +{ + return 0; +} + +#endif + +#endif /* _ASM_X86_64_UNWIND_H */ diff --git a/include/asm-xtensa/Kbuild b/include/asm-xtensa/Kbuild new file mode 100644 index 000000000..c68e1680d --- /dev/null +++ b/include/asm-xtensa/Kbuild @@ -0,0 +1 @@ +include include/asm-generic/Kbuild.asm diff --git a/include/linux/Kbuild b/include/linux/Kbuild new file mode 100644 index 000000000..10d2ca075 --- /dev/null +++ b/include/linux/Kbuild @@ -0,0 +1,343 @@ +header-y += byteorder/ +header-y += dvb/ +header-y += hdlc/ +header-y += isdn/ +header-y += nfsd/ +header-y += raid/ +header-y += sunrpc/ +header-y += tc_act/ +header-y += netfilter/ +header-y += netfilter_arp/ +header-y += netfilter_bridge/ +header-y += netfilter_ipv4/ +header-y += netfilter_ipv6/ + +header-y += affs_fs.h +header-y += affs_hardblocks.h +header-y += aio_abi.h +header-y += a.out.h +header-y += arcfb.h +header-y += atmapi.h +header-y += atmbr2684.h +header-y += atmclip.h +header-y += atm_eni.h +header-y += atm_he.h +header-y += atm_idt77105.h +header-y += atmioc.h +header-y += atmlec.h +header-y += atmmpc.h +header-y += atm_nicstar.h +header-y += atmppp.h +header-y += atmsap.h +header-y += atmsvc.h +header-y += atm_zatm.h +header-y += auto_fs4.h +header-y += auxvec.h +header-y += awe_voice.h +header-y += ax25.h +header-y += b1lli.h +header-y += baycom.h +header-y += bfs_fs.h +header-y += blkpg.h +header-y += bpqether.h +header-y += cdk.h +header-y += chio.h +header-y += coda_psdev.h +header-y += coff.h +header-y += comstats.h +header-y += consolemap.h +header-y += cycx_cfm.h +header-y += dm-ioctl.h +header-y += dn.h +header-y += dqblk_v1.h +header-y += dqblk_v2.h +header-y += dqblk_xfs.h +header-y += efs_fs_sb.h +header-y += elf-fdpic.h +header-y += elf.h +header-y += elf-em.h +header-y += fadvise.h +header-y += fd.h +header-y += fdreg.h +header-y += ftape-header-segment.h +header-y += ftape-vendors.h +header-y += fuse.h +header-y += futex.h +header-y += genetlink.h +header-y += gen_stats.h +header-y += gigaset_dev.h +header-y += hdsmart.h +header-y += hpfs_fs.h +header-y += hysdn_if.h +header-y += i2c-dev.h +header-y += i8k.h +header-y += icmp.h +header-y += if_arcnet.h +header-y += if_arp.h +header-y += if_bonding.h +header-y += if_cablemodem.h +header-y += if_fc.h +header-y += if_fddi.h +header-y += if.h +header-y += if_hippi.h +header-y += if_infiniband.h +header-y += if_packet.h +header-y += if_plip.h +header-y += if_ppp.h +header-y += if_slip.h +header-y += if_strip.h +header-y += if_tunnel.h +header-y += in6.h +header-y += in_route.h +header-y += ioctl.h +header-y += ip.h +header-y += ipmi_msgdefs.h +header-y += ip_mp_alg.h +header-y += ipsec.h +header-y += ipx.h +header-y += irda.h +header-y += isdn_divertif.h +header-y += iso_fs.h +header-y += ite_gpio.h +header-y += ixjuser.h +header-y += jffs2.h +header-y += keyctl.h +header-y += limits.h +header-y += major.h +header-y += matroxfb.h +header-y += meye.h +header-y += minix_fs.h +header-y += mmtimer.h +header-y += mqueue.h +header-y += mtio.h +header-y += ncp_no.h +header-y += netfilter_arp.h +header-y += netrom.h +header-y += nfs2.h +header-y += nfs4_mount.h +header-y += nfs_mount.h +header-y += openprom_fs.h +header-y += param.h +header-y += pci_ids.h +header-y += pci_regs.h +header-y += personality.h +header-y += pfkeyv2.h +header-y += pg.h +header-y += pkt_cls.h +header-y += pkt_sched.h +header-y += posix_types.h +header-y += ppdev.h +header-y += prctl.h +header-y += ps2esdi.h +header-y += qic117.h +header-y += qnxtypes.h +header-y += quotaio_v1.h +header-y += quotaio_v2.h +header-y += radeonfb.h +header-y += raw.h +header-y += resource.h +header-y += rose.h +header-y += sctp.h +header-y += smbno.h +header-y += snmp.h +header-y += sockios.h +header-y += som.h +header-y += sound.h +header-y += synclink.h +header-y += telephony.h +header-y += termios.h +header-y += ticable.h +header-y += times.h +header-y += tiocl.h +header-y += tipc.h +header-y += toshiba.h +header-y += ultrasound.h +header-y += un.h +header-y += utime.h +header-y += utsname.h +header-y += video_decoder.h +header-y += video_encoder.h +header-y += videotext.h +header-y += vt.h +header-y += wavefront.h +header-y += wireless.h +header-y += xattr.h +header-y += x25.h +header-y += zorro_ids.h + +unifdef-y += acct.h +unifdef-y += adb.h +unifdef-y += adfs_fs.h +unifdef-y += agpgart.h +unifdef-y += apm_bios.h +unifdef-y += atalk.h +unifdef-y += atmarp.h +unifdef-y += atmdev.h +unifdef-y += atm.h +unifdef-y += atm_tcp.h +unifdef-y += audit.h +unifdef-y += auto_fs.h +unifdef-y += binfmts.h +unifdef-y += capability.h +unifdef-y += capi.h +unifdef-y += cciss_ioctl.h +unifdef-y += cdrom.h +unifdef-y += cm4000_cs.h +unifdef-y += cn_proc.h +unifdef-y += coda.h +unifdef-y += connector.h +unifdef-y += cramfs_fs.h +unifdef-y += cuda.h +unifdef-y += cyclades.h +unifdef-y += dccp.h +unifdef-y += dirent.h +unifdef-y += divert.h +unifdef-y += elfcore.h +unifdef-y += errno.h +unifdef-y += errqueue.h +unifdef-y += ethtool.h +unifdef-y += eventpoll.h +unifdef-y += ext2_fs.h +unifdef-y += ext3_fs.h +unifdef-y += fb.h +unifdef-y += fcntl.h +unifdef-y += filter.h +unifdef-y += flat.h +unifdef-y += fs.h +unifdef-y += ftape.h +unifdef-y += gameport.h +unifdef-y += generic_serial.h +unifdef-y += genhd.h +unifdef-y += hayesesp.h +unifdef-y += hdlcdrv.h +unifdef-y += hdlc.h +unifdef-y += hdreg.h +unifdef-y += hiddev.h +unifdef-y += hpet.h +unifdef-y += i2c.h +unifdef-y += i2o-dev.h +unifdef-y += icmpv6.h +unifdef-y += if_bridge.h +unifdef-y += if_ec.h +unifdef-y += if_eql.h +unifdef-y += if_ether.h +unifdef-y += if_frad.h +unifdef-y += if_ltalk.h +unifdef-y += if_pppox.h +unifdef-y += if_shaper.h +unifdef-y += if_tr.h +unifdef-y += if_tun.h +unifdef-y += if_vlan.h +unifdef-y += if_wanpipe.h +unifdef-y += igmp.h +unifdef-y += inet_diag.h +unifdef-y += in.h +unifdef-y += inotify.h +unifdef-y += input.h +unifdef-y += ipc.h +unifdef-y += ipmi.h +unifdef-y += ipv6.h +unifdef-y += ipv6_route.h +unifdef-y += isdn.h +unifdef-y += isdnif.h +unifdef-y += isdn_ppp.h +unifdef-y += isicom.h +unifdef-y += jbd.h +unifdef-y += joystick.h +unifdef-y += kdev_t.h +unifdef-y += kd.h +unifdef-y += kernelcapi.h +unifdef-y += kernel.h +unifdef-y += keyboard.h +unifdef-y += llc.h +unifdef-y += loop.h +unifdef-y += lp.h +unifdef-y += mempolicy.h +unifdef-y += mii.h +unifdef-y += mman.h +unifdef-y += mroute.h +unifdef-y += msdos_fs.h +unifdef-y += msg.h +unifdef-y += nbd.h +unifdef-y += ncp_fs.h +unifdef-y += ncp.h +unifdef-y += ncp_mount.h +unifdef-y += netdevice.h +unifdef-y += netfilter_bridge.h +unifdef-y += netfilter_decnet.h +unifdef-y += netfilter.h +unifdef-y += netfilter_ipv4.h +unifdef-y += netfilter_ipv6.h +unifdef-y += netfilter_logging.h +unifdef-y += net.h +unifdef-y += netlink.h +unifdef-y += nfs3.h +unifdef-y += nfs4.h +unifdef-y += nfsacl.h +unifdef-y += nfs_fs.h +unifdef-y += nfs.h +unifdef-y += nfs_idmap.h +unifdef-y += n_r3964.h +unifdef-y += nubus.h +unifdef-y += nvram.h +unifdef-y += parport.h +unifdef-y += patchkey.h +unifdef-y += pci.h +unifdef-y += pktcdvd.h +unifdef-y += pmu.h +unifdef-y += poll.h +unifdef-y += ppp_defs.h +unifdef-y += ppp-comp.h +unifdef-y += ptrace.h +unifdef-y += qnx4_fs.h +unifdef-y += quota.h +unifdef-y += random.h +unifdef-y += reboot.h +unifdef-y += reiserfs_fs.h +unifdef-y += reiserfs_xattr.h +unifdef-y += romfs_fs.h +unifdef-y += route.h +unifdef-y += rtc.h +unifdef-y += rtnetlink.h +unifdef-y += scc.h +unifdef-y += sched.h +unifdef-y += sdla.h +unifdef-y += selinux_netlink.h +unifdef-y += sem.h +unifdef-y += serial_core.h +unifdef-y += serial.h +unifdef-y += serio.h +unifdef-y += shm.h +unifdef-y += signal.h +unifdef-y += smb_fs.h +unifdef-y += smb.h +unifdef-y += smb_mount.h +unifdef-y += socket.h +unifdef-y += sonet.h +unifdef-y += sonypi.h +unifdef-y += soundcard.h +unifdef-y += stat.h +unifdef-y += stddef.h +unifdef-y += sysctl.h +unifdef-y += tcp.h +unifdef-y += time.h +unifdef-y += timex.h +unifdef-y += tty.h +unifdef-y += types.h +unifdef-y += udf_fs_i.h +unifdef-y += udp.h +unifdef-y += uinput.h +unifdef-y += uio.h +unifdef-y += unistd.h +unifdef-y += usb_ch9.h +unifdef-y += usbdevice_fs.h +unifdef-y += user.h +unifdef-y += videodev2.h +unifdef-y += videodev.h +unifdef-y += wait.h +unifdef-y += wanrouter.h +unifdef-y += watchdog.h +unifdef-y += xfrm.h +unifdef-y += zftape.h + +objhdr-y += version.h diff --git a/include/linux/byteorder/Kbuild b/include/linux/byteorder/Kbuild new file mode 100644 index 000000000..56499ab9e --- /dev/null +++ b/include/linux/byteorder/Kbuild @@ -0,0 +1,7 @@ +header-y += big_endian.h +header-y += little_endian.h +header-y += pdp_endian.h + +unifdef-y += generic.h +unifdef-y += swabb.h +unifdef-y += swab.h diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h new file mode 100644 index 000000000..d852024ed --- /dev/null +++ b/include/linux/clocksource.h @@ -0,0 +1,185 @@ +/* linux/include/linux/clocksource.h + * + * This file contains the structure definitions for clocksources. + * + * If you are not a clocksource, or timekeeping code, you should + * not be including this file! + */ +#ifndef _LINUX_CLOCKSOURCE_H +#define _LINUX_CLOCKSOURCE_H + +#include <linux/types.h> +#include <linux/timex.h> +#include <linux/time.h> +#include <linux/list.h> +#include <asm/div64.h> +#include <asm/io.h> + +/* clocksource cycle base type */ +typedef u64 cycle_t; + +/** + * struct clocksource - hardware abstraction for a free running counter + * Provides mostly state-free accessors to the underlying hardware. + * + * @name: ptr to clocksource name + * @list: list head for registration + * @rating: rating value for selection (higher is better) + * To avoid rating inflation the following + * list should give you a guide as to how + * to assign your clocksource a rating + * 1-99: Unfit for real use + * Only available for bootup and testing purposes. + * 100-199: Base level usability. + * Functional for real use, but not desired. + * 200-299: Good. + * A correct and usable clocksource. + * 300-399: Desired. + * A reasonably fast and accurate clocksource. + * 400-499: Perfect + * The ideal clocksource. A must-use where + * available. + * @read: returns a cycle value + * @mask: bitmask for two's complement + * subtraction of non 64 bit counters + * @mult: cycle to nanosecond multiplier + * @shift: cycle to nanosecond divisor (power of two) + * @update_callback: called when safe to alter clocksource values + * @is_continuous: defines if clocksource is free-running. + * @cycle_interval: Used internally by timekeeping core, please ignore. + * @xtime_interval: Used internally by timekeeping core, please ignore. + */ +struct clocksource { + char *name; + struct list_head list; + int rating; + cycle_t (*read)(void); + cycle_t mask; + u32 mult; + u32 shift; + int (*update_callback)(void); + int is_continuous; + + /* timekeeping specific data, ignore */ + cycle_t cycle_last, cycle_interval; + u64 xtime_nsec, xtime_interval; + s64 error; +}; + +/* simplify initialization of mask field */ +#define CLOCKSOURCE_MASK(bits) (cycle_t)(bits<64 ? ((1ULL<<bits)-1) : -1) + +/** + * clocksource_khz2mult - calculates mult from khz and shift + * @khz: Clocksource frequency in KHz + * @shift_constant: Clocksource shift factor + * + * Helper functions that converts a khz counter frequency to a timsource + * multiplier, given the clocksource shift value + */ +static inline u32 clocksource_khz2mult(u32 khz, u32 shift_constant) +{ + /* khz = cyc/(Million ns) + * mult/2^shift = ns/cyc + * mult = ns/cyc * 2^shift + * mult = 1Million/khz * 2^shift + * mult = 1000000 * 2^shift / khz + * mult = (1000000<<shift) / khz + */ + u64 tmp = ((u64)1000000) << shift_constant; + + tmp += khz/2; /* round for do_div */ + do_div(tmp, khz); + + return (u32)tmp; +} + +/** + * clocksource_hz2mult - calculates mult from hz and shift + * @hz: Clocksource frequency in Hz + * @shift_constant: Clocksource shift factor + * + * Helper functions that converts a hz counter + * frequency to a timsource multiplier, given the + * clocksource shift value + */ +static inline u32 clocksource_hz2mult(u32 hz, u32 shift_constant) +{ + /* hz = cyc/(Billion ns) + * mult/2^shift = ns/cyc + * mult = ns/cyc * 2^shift + * mult = 1Billion/hz * 2^shift + * mult = 1000000000 * 2^shift / hz + * mult = (1000000000<<shift) / hz + */ + u64 tmp = ((u64)1000000000) << shift_constant; + + tmp += hz/2; /* round for do_div */ + do_div(tmp, hz); + + return (u32)tmp; +} + +/** + * clocksource_read: - Access the clocksource's current cycle value + * @cs: pointer to clocksource being read + * + * Uses the clocksource to return the current cycle_t value + */ +static inline cycle_t clocksource_read(struct clocksource *cs) +{ + return cs->read(); +} + +/** + * cyc2ns - converts clocksource cycles to nanoseconds + * @cs: Pointer to clocksource + * @cycles: Cycles + * + * Uses the clocksource and ntp ajdustment to convert cycle_ts to nanoseconds. + * + * XXX - This could use some mult_lxl_ll() asm optimization + */ +static inline s64 cyc2ns(struct clocksource *cs, cycle_t cycles) +{ + u64 ret = (u64)cycles; + ret = (ret * cs->mult) >> cs->shift; + return ret; +} + +/** + * clocksource_calculate_interval - Calculates a clocksource interval struct + * + * @c: Pointer to clocksource. + * @length_nsec: Desired interval length in nanoseconds. + * + * Calculates a fixed cycle/nsec interval for a given clocksource/adjustment + * pair and interval request. + * + * Unless you're the timekeeping code, you should not be using this! + */ +static inline void clocksource_calculate_interval(struct clocksource *c, + unsigned long length_nsec) +{ + u64 tmp; + + /* XXX - All of this could use a whole lot of optimization */ + tmp = length_nsec; + tmp <<= c->shift; + tmp += c->mult/2; + do_div(tmp, c->mult); + + c->cycle_interval = (cycle_t)tmp; + if (c->cycle_interval == 0) + c->cycle_interval = 1; + + c->xtime_interval = (u64)c->cycle_interval * c->mult; +} + + +/* used to install a new clocksource */ +int clocksource_register(struct clocksource*); +void clocksource_reselect(void); +struct clocksource* clocksource_get_next(void); + +#endif /* _LINUX_CLOCKSOURCE_H */ diff --git a/include/linux/debug_locks.h b/include/linux/debug_locks.h new file mode 100644 index 000000000..88dafa246 --- /dev/null +++ b/include/linux/debug_locks.h @@ -0,0 +1,71 @@ +#ifndef __LINUX_DEBUG_LOCKING_H +#define __LINUX_DEBUG_LOCKING_H + +struct task_struct; + +extern int debug_locks; +extern int debug_locks_silent; + +/* + * Generic 'turn off all lock debugging' function: + */ +extern int debug_locks_off(void); + +/* + * In the debug case we carry the caller's instruction pointer into + * other functions, but we dont want the function argument overhead + * in the nondebug case - hence these macros: + */ +#define _RET_IP_ (unsigned long)__builtin_return_address(0) +#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; }) + +#define DEBUG_LOCKS_WARN_ON(c) \ +({ \ + int __ret = 0; \ + \ + if (unlikely(c)) { \ + if (debug_locks_off()) \ + WARN_ON(1); \ + __ret = 1; \ + } \ + __ret; \ +}) + +#ifdef CONFIG_SMP +# define SMP_DEBUG_LOCKS_WARN_ON(c) DEBUG_LOCKS_WARN_ON(c) +#else +# define SMP_DEBUG_LOCKS_WARN_ON(c) do { } while (0) +#endif + +#ifdef CONFIG_DEBUG_LOCKING_API_SELFTESTS + extern void locking_selftest(void); +#else +# define locking_selftest() do { } while (0) +#endif + +#ifdef CONFIG_LOCKDEP +extern void debug_show_all_locks(void); +extern void debug_show_held_locks(struct task_struct *task); +extern void debug_check_no_locks_freed(const void *from, unsigned long len); +extern void debug_check_no_locks_held(struct task_struct *task); +#else +static inline void debug_show_all_locks(void) +{ +} + +static inline void debug_show_held_locks(struct task_struct *task) +{ +} + +static inline void +debug_check_no_locks_freed(const void *from, unsigned long len) +{ +} + +static inline void +debug_check_no_locks_held(struct task_struct *task) +{ +} +#endif + +#endif diff --git a/include/linux/delayacct.h b/include/linux/delayacct.h new file mode 100644 index 000000000..561e2a778 --- /dev/null +++ b/include/linux/delayacct.h @@ -0,0 +1,121 @@ +/* delayacct.h - per-task delay accounting + * + * Copyright (C) Shailabh Nagar, IBM Corp. 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + */ + +#ifndef _LINUX_DELAYACCT_H +#define _LINUX_DELAYACCT_H + +#include <linux/sched.h> +#include <linux/taskstats_kern.h> + +/* + * Per-task flags relevant to delay accounting + * maintained privately to avoid exhausting similar flags in sched.h:PF_* + * Used to set current->delays->flags + */ +#define DELAYACCT_PF_SWAPIN 0x00000001 /* I am doing a swapin */ + +#ifdef CONFIG_TASK_DELAY_ACCT + +extern int delayacct_on; /* Delay accounting turned on/off */ +extern kmem_cache_t *delayacct_cache; +extern void delayacct_init(void); +extern void __delayacct_tsk_init(struct task_struct *); +extern void __delayacct_tsk_exit(struct task_struct *); +extern void __delayacct_blkio_start(void); +extern void __delayacct_blkio_end(void); +extern int __delayacct_add_tsk(struct taskstats *, struct task_struct *); +extern __u64 __delayacct_blkio_ticks(struct task_struct *); + +static inline void delayacct_set_flag(int flag) +{ + if (current->delays) + current->delays->flags |= flag; +} + +static inline void delayacct_clear_flag(int flag) +{ + if (current->delays) + current->delays->flags &= ~flag; +} + +static inline void delayacct_tsk_init(struct task_struct *tsk) +{ + /* reinitialize in case parent's non-null pointer was dup'ed*/ + tsk->delays = NULL; + if (delayacct_on) + __delayacct_tsk_init(tsk); +} + +/* Free tsk->delays. Called from bad fork and __put_task_struct + * where there's no risk of tsk->delays being accessed elsewhere + */ +static inline void delayacct_tsk_free(struct task_struct *tsk) +{ + if (tsk->delays) + kmem_cache_free(delayacct_cache, tsk->delays); + tsk->delays = NULL; +} + +static inline void delayacct_blkio_start(void) +{ + if (current->delays) + __delayacct_blkio_start(); +} + +static inline void delayacct_blkio_end(void) +{ + if (current->delays) + __delayacct_blkio_end(); +} + +static inline int delayacct_add_tsk(struct taskstats *d, + struct task_struct *tsk) +{ + if (!delayacct_on || !tsk->delays) + return 0; + return __delayacct_add_tsk(d, tsk); +} + +static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk) +{ + if (tsk->delays) + return __delayacct_blkio_ticks(tsk); + return 0; +} + +#else +static inline void delayacct_set_flag(int flag) +{} +static inline void delayacct_clear_flag(int flag) +{} +static inline void delayacct_init(void) +{} +static inline void delayacct_tsk_init(struct task_struct *tsk) +{} +static inline void delayacct_tsk_free(struct task_struct *tsk) +{} +static inline void delayacct_blkio_start(void) +{} +static inline void delayacct_blkio_end(void) +{} +static inline int delayacct_add_tsk(struct taskstats *d, + struct task_struct *tsk) +{ return 0; } +static inline __u64 delayacct_blkio_ticks(struct task_struct *tsk) +{ return 0; } +#endif /* CONFIG_TASK_DELAY_ACCT */ + +#endif diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h new file mode 100644 index 000000000..c94d8f1d6 --- /dev/null +++ b/include/linux/dmaengine.h @@ -0,0 +1,366 @@ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ +#ifndef DMAENGINE_H +#define DMAENGINE_H + +#ifdef CONFIG_DMA_ENGINE + +#include <linux/device.h> +#include <linux/uio.h> +#include <linux/kref.h> +#include <linux/completion.h> +#include <linux/rcupdate.h> + +/** + * enum dma_event - resource PNP/power managment events + * @DMA_RESOURCE_SUSPEND: DMA device going into low power state + * @DMA_RESOURCE_RESUME: DMA device returning to full power + * @DMA_RESOURCE_ADDED: DMA device added to the system + * @DMA_RESOURCE_REMOVED: DMA device removed from the system + */ +enum dma_event { + DMA_RESOURCE_SUSPEND, + DMA_RESOURCE_RESUME, + DMA_RESOURCE_ADDED, + DMA_RESOURCE_REMOVED, +}; + +/** + * typedef dma_cookie_t - an opaque DMA cookie + * + * if dma_cookie_t is >0 it's a DMA request cookie, <0 it's an error code + */ +typedef s32 dma_cookie_t; + +#define dma_submit_error(cookie) ((cookie) < 0 ? 1 : 0) + +/** + * enum dma_status - DMA transaction status + * @DMA_SUCCESS: transaction completed successfully + * @DMA_IN_PROGRESS: transaction not yet processed + * @DMA_ERROR: transaction failed + */ +enum dma_status { + DMA_SUCCESS, + DMA_IN_PROGRESS, + DMA_ERROR, +}; + +/** + * struct dma_chan_percpu - the per-CPU part of struct dma_chan + * @refcount: local_t used for open-coded "bigref" counting + * @memcpy_count: transaction counter + * @bytes_transferred: byte counter + */ + +struct dma_chan_percpu { + local_t refcount; + /* stats */ + unsigned long memcpy_count; + unsigned long bytes_transferred; +}; + +/** + * struct dma_chan - devices supply DMA channels, clients use them + * @client: ptr to the client user of this chan, will be %NULL when unused + * @device: ptr to the dma device who supplies this channel, always !%NULL + * @cookie: last cookie value returned to client + * @chan_id: channel ID for sysfs + * @class_dev: class device for sysfs + * @refcount: kref, used in "bigref" slow-mode + * @slow_ref: indicates that the DMA channel is free + * @rcu: the DMA channel's RCU head + * @client_node: used to add this to the client chan list + * @device_node: used to add this to the device chan list + * @local: per-cpu pointer to a struct dma_chan_percpu + */ +struct dma_chan { + struct dma_client *client; + struct dma_device *device; + dma_cookie_t cookie; + + /* sysfs */ + int chan_id; + struct class_device class_dev; + + struct kref refcount; + int slow_ref; + struct rcu_head rcu; + + struct list_head client_node; + struct list_head device_node; + struct dma_chan_percpu *local; +}; + +void dma_chan_cleanup(struct kref *kref); + +static inline void dma_chan_get(struct dma_chan *chan) +{ + if (unlikely(chan->slow_ref)) + kref_get(&chan->refcount); + else { + local_inc(&(per_cpu_ptr(chan->local, get_cpu())->refcount)); + put_cpu(); + } +} + +static inline void dma_chan_put(struct dma_chan *chan) +{ + if (unlikely(chan->slow_ref)) + kref_put(&chan->refcount, dma_chan_cleanup); + else { + local_dec(&(per_cpu_ptr(chan->local, get_cpu())->refcount)); + put_cpu(); + } +} + +/* + * typedef dma_event_callback - function pointer to a DMA event callback + */ +typedef void (*dma_event_callback) (struct dma_client *client, + struct dma_chan *chan, enum dma_event event); + +/** + * struct dma_client - info on the entity making use of DMA services + * @event_callback: func ptr to call when something happens + * @chan_count: number of chans allocated + * @chans_desired: number of chans requested. Can be +/- chan_count + * @lock: protects access to the channels list + * @channels: the list of DMA channels allocated + * @global_node: list_head for global dma_client_list + */ +struct dma_client { + dma_event_callback event_callback; + unsigned int chan_count; + unsigned int chans_desired; + + spinlock_t lock; + struct list_head channels; + struct list_head global_node; +}; + +/** + * struct dma_device - info on the entity supplying DMA services + * @chancnt: how many DMA channels are supported + * @channels: the list of struct dma_chan + * @global_node: list_head for global dma_device_list + * @refcount: reference count + * @done: IO completion struct + * @dev_id: unique device ID + * @device_alloc_chan_resources: allocate resources and return the + * number of allocated descriptors + * @device_free_chan_resources: release DMA channel's resources + * @device_memcpy_buf_to_buf: memcpy buf pointer to buf pointer + * @device_memcpy_buf_to_pg: memcpy buf pointer to struct page + * @device_memcpy_pg_to_pg: memcpy struct page/offset to struct page/offset + * @device_memcpy_complete: poll the status of an IOAT DMA transaction + * @device_memcpy_issue_pending: push appended descriptors to hardware + */ +struct dma_device { + + unsigned int chancnt; + struct list_head channels; + struct list_head global_node; + + struct kref refcount; + struct completion done; + + int dev_id; + + int (*device_alloc_chan_resources)(struct dma_chan *chan); + void (*device_free_chan_resources)(struct dma_chan *chan); + dma_cookie_t (*device_memcpy_buf_to_buf)(struct dma_chan *chan, + void *dest, void *src, size_t len); + dma_cookie_t (*device_memcpy_buf_to_pg)(struct dma_chan *chan, + struct page *page, unsigned int offset, void *kdata, + size_t len); + dma_cookie_t (*device_memcpy_pg_to_pg)(struct dma_chan *chan, + struct page *dest_pg, unsigned int dest_off, + struct page *src_pg, unsigned int src_off, size_t len); + enum dma_status (*device_memcpy_complete)(struct dma_chan *chan, + dma_cookie_t cookie, dma_cookie_t *last, + dma_cookie_t *used); + void (*device_memcpy_issue_pending)(struct dma_chan *chan); +}; + +/* --- public DMA engine API --- */ + +struct dma_client *dma_async_client_register(dma_event_callback event_callback); +void dma_async_client_unregister(struct dma_client *client); +void dma_async_client_chan_request(struct dma_client *client, + unsigned int number); + +/** + * dma_async_memcpy_buf_to_buf - offloaded copy between virtual addresses + * @chan: DMA channel to offload copy to + * @dest: destination address (virtual) + * @src: source address (virtual) + * @len: length + * + * Both @dest and @src must be mappable to a bus address according to the + * DMA mapping API rules for streaming mappings. + * Both @dest and @src must stay memory resident (kernel memory or locked + * user space pages). + */ +static inline dma_cookie_t dma_async_memcpy_buf_to_buf(struct dma_chan *chan, + void *dest, void *src, size_t len) +{ + int cpu = get_cpu(); + per_cpu_ptr(chan->local, cpu)->bytes_transferred += len; + per_cpu_ptr(chan->local, cpu)->memcpy_count++; + put_cpu(); + + return chan->device->device_memcpy_buf_to_buf(chan, dest, src, len); +} + +/** + * dma_async_memcpy_buf_to_pg - offloaded copy from address to page + * @chan: DMA channel to offload copy to + * @page: destination page + * @offset: offset in page to copy to + * @kdata: source address (virtual) + * @len: length + * + * Both @page/@offset and @kdata must be mappable to a bus address according + * to the DMA mapping API rules for streaming mappings. + * Both @page/@offset and @kdata must stay memory resident (kernel memory or + * locked user space pages) + */ +static inline dma_cookie_t dma_async_memcpy_buf_to_pg(struct dma_chan *chan, + struct page *page, unsigned int offset, void *kdata, size_t len) +{ + int cpu = get_cpu(); + per_cpu_ptr(chan->local, cpu)->bytes_transferred += len; + per_cpu_ptr(chan->local, cpu)->memcpy_count++; + put_cpu(); + + return chan->device->device_memcpy_buf_to_pg(chan, page, offset, + kdata, len); +} + +/** + * dma_async_memcpy_pg_to_pg - offloaded copy from page to page + * @chan: DMA channel to offload copy to + * @dest_pg: destination page + * @dest_off: offset in page to copy to + * @src_pg: source page + * @src_off: offset in page to copy from + * @len: length + * + * Both @dest_page/@dest_off and @src_page/@src_off must be mappable to a bus + * address according to the DMA mapping API rules for streaming mappings. + * Both @dest_page/@dest_off and @src_page/@src_off must stay memory resident + * (kernel memory or locked user space pages). + */ +static inline dma_cookie_t dma_async_memcpy_pg_to_pg(struct dma_chan *chan, + struct page *dest_pg, unsigned int dest_off, struct page *src_pg, + unsigned int src_off, size_t len) +{ + int cpu = get_cpu(); + per_cpu_ptr(chan->local, cpu)->bytes_transferred += len; + per_cpu_ptr(chan->local, cpu)->memcpy_count++; + put_cpu(); + + return chan->device->device_memcpy_pg_to_pg(chan, dest_pg, dest_off, + src_pg, src_off, len); +} + +/** + * dma_async_memcpy_issue_pending - flush pending copies to HW + * @chan: target DMA channel + * + * This allows drivers to push copies to HW in batches, + * reducing MMIO writes where possible. + */ +static inline void dma_async_memcpy_issue_pending(struct dma_chan *chan) +{ + return chan->device->device_memcpy_issue_pending(chan); +} + +/** + * dma_async_memcpy_complete - poll for transaction completion + * @chan: DMA channel + * @cookie: transaction identifier to check status of + * @last: returns last completed cookie, can be NULL + * @used: returns last issued cookie, can be NULL + * + * If @last and @used are passed in, upon return they reflect the driver + * internal state and can be used with dma_async_is_complete() to check + * the status of multiple cookies without re-checking hardware state. + */ +static inline enum dma_status dma_async_memcpy_complete(struct dma_chan *chan, + dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used) +{ + return chan->device->device_memcpy_complete(chan, cookie, last, used); +} + +/** + * dma_async_is_complete - test a cookie against chan state + * @cookie: transaction identifier to test status of + * @last_complete: last know completed transaction + * @last_used: last cookie value handed out + * + * dma_async_is_complete() is used in dma_async_memcpy_complete() + * the test logic is seperated for lightweight testing of multiple cookies + */ +static inline enum dma_status dma_async_is_complete(dma_cookie_t cookie, + dma_cookie_t last_complete, dma_cookie_t last_used) +{ + if (last_complete <= last_used) { + if ((cookie <= last_complete) || (cookie > last_used)) + return DMA_SUCCESS; + } else { + if ((cookie <= last_complete) && (cookie > last_used)) + return DMA_SUCCESS; + } + return DMA_IN_PROGRESS; +} + + +/* --- DMA device --- */ + +int dma_async_device_register(struct dma_device *device); +void dma_async_device_unregister(struct dma_device *device); + +/* --- Helper iov-locking functions --- */ + +struct dma_page_list { + char *base_address; + int nr_pages; + struct page **pages; +}; + +struct dma_pinned_list { + int nr_iovecs; + struct dma_page_list page_list[0]; +}; + +struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len); +void dma_unpin_iovec_pages(struct dma_pinned_list* pinned_list); + +dma_cookie_t dma_memcpy_to_iovec(struct dma_chan *chan, struct iovec *iov, + struct dma_pinned_list *pinned_list, unsigned char *kdata, size_t len); +dma_cookie_t dma_memcpy_pg_to_iovec(struct dma_chan *chan, struct iovec *iov, + struct dma_pinned_list *pinned_list, struct page *page, + unsigned int offset, size_t len); + +#endif /* CONFIG_DMA_ENGINE */ +#endif /* DMAENGINE_H */ diff --git a/include/linux/dvb/Kbuild b/include/linux/dvb/Kbuild new file mode 100644 index 000000000..d97b3a51e --- /dev/null +++ b/include/linux/dvb/Kbuild @@ -0,0 +1,9 @@ +header-y += ca.h +header-y += frontend.h +header-y += net.h +header-y += osd.h +header-y += version.h + +unifdef-y += audio.h +unifdef-y += dmx.h +unifdef-y += video.h diff --git a/include/linux/elf-em.h b/include/linux/elf-em.h new file mode 100644 index 000000000..6a5796c81 --- /dev/null +++ b/include/linux/elf-em.h @@ -0,0 +1,49 @@ +#ifndef _LINUX_ELF_EM_H +#define _LINUX_ELF_EM_H + +/* These constants define the various ELF target machines */ +#define EM_NONE 0 +#define EM_M32 1 +#define EM_SPARC 2 +#define EM_386 3 +#define EM_68K 4 +#define EM_88K 5 +#define EM_486 6 /* Perhaps disused */ +#define EM_860 7 +#define EM_MIPS 8 /* MIPS R3000 (officially, big-endian only) */ + /* Next two are historical and binaries and + modules of these types will be rejected by + Linux. */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */ + +#define EM_PARISC 15 /* HPPA */ +#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* PowerPC64 */ +#define EM_SH 42 /* SuperH */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit */ +#define EM_IA_64 50 /* HP/Intel IA-64 */ +#define EM_X86_64 62 /* AMD x86-64 */ +#define EM_S390 22 /* IBM S/390 */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Renesas M32R */ +#define EM_H8_300 46 /* Renesas H8/300,300H,H8S */ +#define EM_FRV 0x5441 /* Fujitsu FR-V */ + +/* + * This is an interim value that we will use until the committee comes + * up with a final number. + */ +#define EM_ALPHA 0x9026 + +/* Bogus old v850 magic number, used by old tools. */ +#define EM_CYGNUS_V850 0x9080 +/* Bogus old m32r magic number, used by old tools. */ +#define EM_CYGNUS_M32R 0x9041 +/* This is the old interim value for S/390 architecture */ +#define EM_S390_OLD 0xA390 + + +#endif /* _LINUX_ELF_EM_H */ diff --git a/include/linux/elfnote.h b/include/linux/elfnote.h new file mode 100644 index 000000000..67396db14 --- /dev/null +++ b/include/linux/elfnote.h @@ -0,0 +1,90 @@ +#ifndef _LINUX_ELFNOTE_H +#define _LINUX_ELFNOTE_H +/* + * Helper macros to generate ELF Note structures, which are put into a + * PT_NOTE segment of the final vmlinux image. These are useful for + * including name-value pairs of metadata into the kernel binary (or + * modules?) for use by external programs. + * + * Each note has three parts: a name, a type and a desc. The name is + * intended to distinguish the note's originator, so it would be a + * company, project, subsystem, etc; it must be in a suitable form for + * use in a section name. The type is an integer which is used to tag + * the data, and is considered to be within the "name" namespace (so + * "FooCo"'s type 42 is distinct from "BarProj"'s type 42). The + * "desc" field is the actual data. There are no constraints on the + * desc field's contents, though typically they're fairly small. + * + * All notes from a given NAME are put into a section named + * .note.NAME. When the kernel image is finally linked, all the notes + * are packed into a single .notes section, which is mapped into the + * PT_NOTE segment. Because notes for a given name are grouped into + * the same section, they'll all be adjacent the output file. + * + * This file defines macros for both C and assembler use. Their + * syntax is slightly different, but they're semantically similar. + * + * See the ELF specification for more detail about ELF notes. + */ + +#ifdef __ASSEMBLER__ +/* + * Generate a structure with the same shape as Elf{32,64}_Nhdr (which + * turn out to be the same size and shape), followed by the name and + * desc data with appropriate padding. The 'desctype' argument is the + * assembler pseudo op defining the type of the data e.g. .asciz while + * 'descdata' is the data itself e.g. "hello, world". + * + * e.g. ELFNOTE(XYZCo, 42, .asciz, "forty-two") + * ELFNOTE(XYZCo, 12, .long, 0xdeadbeef) + */ +#define ELFNOTE(name, type, desctype, descdata) \ +.pushsection .note.name ; \ + .align 4 ; \ + .long 2f - 1f /* namesz */ ; \ + .long 4f - 3f /* descsz */ ; \ + .long type ; \ +1:.asciz "name" ; \ +2:.align 4 ; \ +3:desctype descdata ; \ +4:.align 4 ; \ +.popsection ; +#else /* !__ASSEMBLER__ */ +#include <linux/elf.h> +/* + * Use an anonymous structure which matches the shape of + * Elf{32,64}_Nhdr, but includes the name and desc data. The size and + * type of name and desc depend on the macro arguments. "name" must + * be a literal string, and "desc" must be passed by value. You may + * only define one note per line, since __LINE__ is used to generate + * unique symbols. + */ +#define _ELFNOTE_PASTE(a,b) a##b +#define _ELFNOTE(size, name, unique, type, desc) \ + static const struct { \ + struct elf##size##_note _nhdr; \ + unsigned char _name[sizeof(name)] \ + __attribute__((aligned(sizeof(Elf##size##_Word)))); \ + typeof(desc) _desc \ + __attribute__((aligned(sizeof(Elf##size##_Word)))); \ + } _ELFNOTE_PASTE(_note_, unique) \ + __attribute_used__ \ + __attribute__((section(".note." name), \ + aligned(sizeof(Elf##size##_Word)), \ + unused)) = { \ + { \ + sizeof(name), \ + sizeof(desc), \ + type, \ + }, \ + name, \ + desc \ + } +#define ELFNOTE(size, name, type, desc) \ + _ELFNOTE(size, name, __LINE__, type, desc) + +#define ELFNOTE32(name, type, desc) ELFNOTE(32, name, type, desc) +#define ELFNOTE64(name, type, desc) ELFNOTE(64, name, type, desc) +#endif /* __ASSEMBLER__ */ + +#endif /* _LINUX_ELFNOTE_H */ diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h new file mode 100644 index 000000000..e229fed00 --- /dev/null +++ b/include/linux/fscache-cache.h @@ -0,0 +1,243 @@ +/* fscache-cache.h: general filesystem caching backing cache interface + * + * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * NOTE!!! See: + * + * Documentation/filesystems/caching/backend-api.txt + * + * for a description of the cache backend interface declared here. + */ + +#ifndef _LINUX_FSCACHE_CACHE_H +#define _LINUX_FSCACHE_CACHE_H + +#include <linux/fscache.h> + +#define NR_MAXCACHES BITS_PER_LONG + +struct fscache_cache; +struct fscache_cache_ops; +struct fscache_object; + +/* + * cache tag definition + */ +struct fscache_cache_tag { + struct list_head link; + struct fscache_cache *cache; /* cache referred to by this tag */ + atomic_t usage; + char name[0]; /* tag name */ +}; + +/* + * cache definition + */ +struct fscache_cache { + struct fscache_cache_ops *ops; + struct fscache_cache_tag *tag; /* tag representing this cache */ + struct list_head link; /* link in list of caches */ + struct rw_semaphore withdrawal_sem; /* withdrawal control sem */ + size_t max_index_size; /* maximum size of index data */ + char identifier[32]; /* cache label */ + + /* node management */ + struct list_head object_list; /* list of data/index objects */ + spinlock_t object_list_lock; + struct fscache_object *fsdef; /* object for the fsdef index */ + unsigned long flags; +#define FSCACHE_IOERROR 0 /* cache stopped on I/O error */ +}; + +extern void fscache_init_cache(struct fscache_cache *cache, + struct fscache_cache_ops *ops, + const char *idfmt, + ...) __attribute__ ((format (printf,3,4))); + +extern int fscache_add_cache(struct fscache_cache *cache, + struct fscache_object *fsdef, + const char *tagname); +extern void fscache_withdraw_cache(struct fscache_cache *cache); + +extern void fscache_io_error(struct fscache_cache *cache); + +/*****************************************************************************/ +/* + * cache operations + */ +struct fscache_cache_ops { + /* name of cache provider */ + const char *name; + + /* look up the object for a cookie, creating it on disc if necessary */ + struct fscache_object *(*lookup_object)(struct fscache_cache *cache, + struct fscache_object *parent, + struct fscache_cookie *cookie); + + /* increment the usage count on this object (may fail if unmounting) */ + struct fscache_object *(*grab_object)(struct fscache_object *object); + + /* lock a semaphore on an object */ + void (*lock_object)(struct fscache_object *object); + + /* unlock a semaphore on an object */ + void (*unlock_object)(struct fscache_object *object); + + /* pin an object in the cache */ + int (*pin_object)(struct fscache_object *object); + + /* unpin an object in the cache */ + void (*unpin_object)(struct fscache_object *object); + + /* store the updated auxilliary data on an object */ + void (*update_object)(struct fscache_object *object); + + /* dispose of a reference to an object */ + void (*put_object)(struct fscache_object *object); + + /* sync a cache */ + void (*sync_cache)(struct fscache_cache *cache); + + /* set the data size of an object */ + int (*set_i_size)(struct fscache_object *object, loff_t i_size); + + /* reserve space for an object's data and associated metadata */ + int (*reserve_space)(struct fscache_object *object, loff_t i_size); + + /* request a backing block for a page be read or allocated in the + * cache */ + int (*read_or_alloc_page)(struct fscache_object *object, + struct page *page, + fscache_rw_complete_t end_io_func, + void *context, + unsigned long gfp); + + /* request backing blocks for a list of pages be read or allocated in + * the cache */ + int (*read_or_alloc_pages)(struct fscache_object *object, + struct address_space *mapping, + struct list_head *pages, + unsigned *nr_pages, + fscache_rw_complete_t end_io_func, + void *context, + unsigned long gfp); + + /* request a backing block for a page be allocated in the cache so that + * it can be written directly */ + int (*allocate_page)(struct fscache_object *object, + struct page *page, + unsigned long gfp); + + /* write a page to its backing block in the cache */ + int (*write_page)(struct fscache_object *object, + struct page *page, + fscache_rw_complete_t end_io_func, + void *context, + unsigned long gfp); + + /* write several pages to their backing blocks in the cache */ + int (*write_pages)(struct fscache_object *object, + struct pagevec *pagevec, + fscache_rw_complete_t end_io_func, + void *context, + unsigned long gfp); + + /* detach backing block from a bunch of pages */ + void (*uncache_pages)(struct fscache_object *object, + struct pagevec *pagevec); + + /* dissociate a cache from all the pages it was backing */ + void (*dissociate_pages)(struct fscache_cache *cache); +}; + +/*****************************************************************************/ +/* + * data file or index object cookie + * - a file will only appear in one cache + * - a request to cache a file may or may not be honoured, subject to + * constraints such as disc space + * - indexes files are created on disc just-in-time + */ +struct fscache_cookie { + atomic_t usage; /* number of users of this cookie */ + atomic_t children; /* number of children of this cookie */ + struct rw_semaphore sem; /* list creation vs scan lock */ + struct hlist_head backing_objects; /* object(s) backing this file/index */ + struct fscache_cookie_def *def; /* definition */ + struct fscache_cookie *parent; /* parent of this entry */ + struct fscache_netfs *netfs; /* owner network fs definition */ + void *netfs_data; /* back pointer to netfs */ +}; + +extern struct fscache_cookie fscache_fsdef_index; + +/*****************************************************************************/ +/* + * on-disc cache file or index handle + */ +struct fscache_object { + unsigned long flags; +#define FSCACHE_OBJECT_RELEASING 0 /* T if object is being released */ +#define FSCACHE_OBJECT_RECYCLING 1 /* T if object is being retired */ +#define FSCACHE_OBJECT_WITHDRAWN 2 /* T if object has been withdrawn */ + + struct list_head cache_link; /* link in cache->object_list */ + struct hlist_node cookie_link; /* link in cookie->backing_objects */ + struct fscache_cache *cache; /* cache that supplied this object */ + struct fscache_cookie *cookie; /* netfs's file/index object */ +}; + +static inline +void fscache_object_init(struct fscache_object *object) +{ + object->flags = 0; + INIT_LIST_HEAD(&object->cache_link); + INIT_HLIST_NODE(&object->cookie_link); + object->cache = NULL; + object->cookie = NULL; +} + +/* find the parent index object for a object */ +static inline +struct fscache_object *fscache_find_parent_object(struct fscache_object *object) +{ + struct fscache_object *parent; + struct fscache_cookie *cookie = object->cookie; + struct fscache_cache *cache = object->cache; + struct hlist_node *_p; + + hlist_for_each_entry(parent, _p, + &cookie->parent->backing_objects, + cookie_link + ) { + if (parent->cache == cache) + return parent; + } + + return NULL; +} + +/* get an extra reference to a context */ +static inline +void *fscache_get_context(struct fscache_cookie *cookie, void *context) +{ + if (cookie->def->get_context) + cookie->def->get_context(cookie->netfs_data, context); + return context; +} + +/* release an extra reference to a context */ +static inline +void fscache_put_context(struct fscache_cookie *cookie, void *context) +{ + if (cookie->def->put_context) + cookie->def->put_context(cookie->netfs_data, context); +} + +#endif /* _LINUX_FSCACHE_CACHE_H */ diff --git a/include/linux/fscache.h b/include/linux/fscache.h new file mode 100644 index 000000000..867ab9e9d --- /dev/null +++ b/include/linux/fscache.h @@ -0,0 +1,495 @@ +/* fscache.h: general filesystem caching interface + * + * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * NOTE!!! See: + * + * Documentation/filesystems/caching/netfs-api.txt + * + * for a description of the network filesystem interface declared here. + */ + +#ifndef _LINUX_FSCACHE_H +#define _LINUX_FSCACHE_H + +#include <linux/fs.h> +#include <linux/list.h> +#include <linux/pagemap.h> +#include <linux/pagevec.h> + +struct pagevec; +struct fscache_cache_tag; +struct fscache_cookie; +struct fscache_netfs; +struct fscache_netfs_operations; + +typedef void (*fscache_rw_complete_t)(struct page *page, + void *context, + int error); + +/* result of index entry consultation */ +typedef enum { + FSCACHE_CHECKAUX_OKAY, /* entry okay as is */ + FSCACHE_CHECKAUX_NEEDS_UPDATE, /* entry requires update */ + FSCACHE_CHECKAUX_OBSOLETE, /* entry requires deletion */ +} fscache_checkaux_t; + +/*****************************************************************************/ +/* + * fscache cookie definition + */ +struct fscache_cookie_def +{ + /* name of cookie type */ + char name[16]; + + /* cookie type */ + uint8_t type; +#define FSCACHE_COOKIE_TYPE_INDEX 0 +#define FSCACHE_COOKIE_TYPE_DATAFILE 1 + + /* select the cache into which to insert an entry in this index + * - optional + * - should return a cache identifier or NULL to cause the cache to be + * inherited from the parent if possible or the first cache picked + * for a non-index file if not + */ + struct fscache_cache_tag *(*select_cache)(const void *parent_netfs_data, + const void *cookie_netfs_data); + + /* get an index key + * - should store the key data in the buffer + * - should return the amount of amount stored + * - not permitted to return an error + * - the netfs data from the cookie being used as the source is + * presented + */ + uint16_t (*get_key)(const void *cookie_netfs_data, + void *buffer, + uint16_t bufmax); + + /* get certain file attributes from the netfs data + * - this function can be absent for an index + * - not permitted to return an error + * - the netfs data from the cookie being used as the source is + * presented + */ + void (*get_attr)(const void *cookie_netfs_data, uint64_t *size); + + /* get the auxilliary data from netfs data + * - this function can be absent if the index carries no state data + * - should store the auxilliary data in the buffer + * - should return the amount of amount stored + * - not permitted to return an error + * - the netfs data from the cookie being used as the source is + * presented + */ + uint16_t (*get_aux)(const void *cookie_netfs_data, + void *buffer, + uint16_t bufmax); + + /* consult the netfs about the state of an object + * - this function can be absent if the index carries no state data + * - the netfs data from the cookie being used as the target is + * presented, as is the auxilliary data + */ + fscache_checkaux_t (*check_aux)(void *cookie_netfs_data, + const void *data, + uint16_t datalen); + + /* get an extra reference on a read context + * - this function can be absent if the completion function doesn't + * require a context + */ + void (*get_context)(void *cookie_netfs_data, void *context); + + /* release an extra reference on a read context + * - this function can be absent if the completion function doesn't + * require a context + */ + void (*put_context)(void *cookie_netfs_data, void *context); + + /* indicate pages that now have cache metadata retained + * - this function should mark the specified pages as now being cached + */ + void (*mark_pages_cached)(void *cookie_netfs_data, + struct address_space *mapping, + struct pagevec *cached_pvec); + + /* indicate the cookie is no longer cached + * - this function is called when the backing store currently caching + * a cookie is removed + * - the netfs should use this to clean up any markers indicating + * cached pages + * - this is mandatory for any object that may have data + */ + void (*now_uncached)(void *cookie_netfs_data); +}; + +/* pattern used to fill dead space in an index entry */ +#define FSCACHE_INDEX_DEADFILL_PATTERN 0x79 + +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) +extern struct fscache_cookie *__fscache_acquire_cookie(struct fscache_cookie *parent, + struct fscache_cookie_def *def, + void *netfs_data); + +extern void __fscache_relinquish_cookie(struct fscache_cookie *cookie, + int retire); + +extern void __fscache_update_cookie(struct fscache_cookie *cookie); +#endif + +static inline +struct fscache_cookie *fscache_acquire_cookie(struct fscache_cookie *parent, + struct fscache_cookie_def *def, + void *netfs_data) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + if (parent) + return __fscache_acquire_cookie(parent, def, netfs_data); +#endif + return NULL; +} + +static inline +void fscache_relinquish_cookie(struct fscache_cookie *cookie, + int retire) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + if (cookie) + __fscache_relinquish_cookie(cookie, retire); +#endif +} + +static inline +void fscache_update_cookie(struct fscache_cookie *cookie) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + if (cookie) + __fscache_update_cookie(cookie); +#endif +} + +/*****************************************************************************/ +/* + * pin or unpin a cookie in a cache + * - only available for data cookies + */ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) +extern int __fscache_pin_cookie(struct fscache_cookie *cookie); +extern void __fscache_unpin_cookie(struct fscache_cookie *cookie); +#endif + +static inline +int fscache_pin_cookie(struct fscache_cookie *cookie) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + if (cookie) + return __fscache_pin_cookie(cookie); +#endif + return -ENOBUFS; +} + +static inline +void fscache_unpin_cookie(struct fscache_cookie *cookie) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + if (cookie) + __fscache_unpin_cookie(cookie); +#endif +} + +/*****************************************************************************/ +/* + * fscache cached network filesystem type + * - name, version and ops must be filled in before registration + * - all other fields will be set during registration + */ +struct fscache_netfs +{ + uint32_t version; /* indexing version */ + const char *name; /* filesystem name */ + struct fscache_cookie *primary_index; + struct fscache_netfs_operations *ops; + struct list_head link; /* internal link */ +}; + +struct fscache_netfs_operations +{ +}; + +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) +extern int __fscache_register_netfs(struct fscache_netfs *netfs); +extern void __fscache_unregister_netfs(struct fscache_netfs *netfs); +#endif + +static inline +int fscache_register_netfs(struct fscache_netfs *netfs) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + return __fscache_register_netfs(netfs); +#else + return 0; +#endif +} + +static inline +void fscache_unregister_netfs(struct fscache_netfs *netfs) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + __fscache_unregister_netfs(netfs); +#endif +} + +/*****************************************************************************/ +/* + * look up a cache tag + * - cache tags are used to select specific caches in which to cache indexes + */ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) +extern struct fscache_cache_tag *__fscache_lookup_cache_tag(const char *name); +extern void __fscache_release_cache_tag(struct fscache_cache_tag *tag); +#endif + +static inline +struct fscache_cache_tag *fscache_lookup_cache_tag(const char *name) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + return __fscache_lookup_cache_tag(name); +#else + return NULL; +#endif +} + +static inline +void fscache_release_cache_tag(struct fscache_cache_tag *tag) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + __fscache_release_cache_tag(tag); +#endif +} + +/*****************************************************************************/ +/* + * set the data size on a cached object + * - no pages beyond the end of the object will be accessible + * - returns -ENOBUFS if the file is not backed + * - returns -ENOSPC if a pinned file of that size can't be stored + * - returns 0 if okay + */ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) +extern int __fscache_set_i_size(struct fscache_cookie *cookie, loff_t i_size); +#endif + +static inline +int fscache_set_i_size(struct fscache_cookie *cookie, loff_t i_size) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + if (cookie) + return __fscache_set_i_size(cookie, i_size); +#endif + return -ENOBUFS; +} + +/*****************************************************************************/ +/* + * reserve data space for a cached object + * - returns -ENOBUFS if the file is not backed + * - returns -ENOSPC if there isn't enough space to honour the reservation + * - returns 0 if okay + */ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) +extern int __fscache_reserve_space(struct fscache_cookie *cookie, loff_t size); +#endif + +static inline +int fscache_reserve_space(struct fscache_cookie *cookie, loff_t size) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + if (cookie) + return __fscache_reserve_space(cookie, size); +#endif + return -ENOBUFS; +} + +/*****************************************************************************/ +/* + * read a page from the cache or allocate a block in which to store it + * - if the page is not backed by a file: + * - -ENOBUFS will be returned and nothing more will be done + * - else if the page is backed by a block in the cache: + * - a read will be started which will call end_io_func on completion + * - else if the page is unbacked: + * - a block will be allocated + * - -ENODATA will be returned + */ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) +extern int __fscache_read_or_alloc_page(struct fscache_cookie *cookie, + struct page *page, + fscache_rw_complete_t end_io_func, + void *context, + gfp_t gfp); +#endif + +static inline +int fscache_read_or_alloc_page(struct fscache_cookie *cookie, + struct page *page, + fscache_rw_complete_t end_io_func, + void *context, + gfp_t gfp) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + if (cookie) + return __fscache_read_or_alloc_page(cookie, page, end_io_func, + context, gfp); +#endif + return -ENOBUFS; +} + +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) +extern int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie, + struct address_space *mapping, + struct list_head *pages, + unsigned *nr_pages, + fscache_rw_complete_t end_io_func, + void *context, + gfp_t gfp); +#endif + +static inline +int fscache_read_or_alloc_pages(struct fscache_cookie *cookie, + struct address_space *mapping, + struct list_head *pages, + unsigned *nr_pages, + fscache_rw_complete_t end_io_func, + void *context, + gfp_t gfp) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + if (cookie) + return __fscache_read_or_alloc_pages(cookie, mapping, pages, + nr_pages, end_io_func, + context, gfp); +#endif + return -ENOBUFS; +} + +/* + * allocate a block in which to store a page + * - if the page is not backed by a file: + * - -ENOBUFS will be returned and nothing more will be done + * - else + * - a block will be allocated if there isn't one + * - 0 will be returned + */ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) +extern int __fscache_alloc_page(struct fscache_cookie *cookie, + struct page *page, + gfp_t gfp); +#endif + +static inline +int fscache_alloc_page(struct fscache_cookie *cookie, + struct page *page, + gfp_t gfp) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + if (cookie) + return __fscache_alloc_page(cookie, page, gfp); +#endif + return -ENOBUFS; +} + +/* + * request a page be stored in the cache + * - this request may be ignored if no cache block is currently allocated, in + * which case it: + * - returns -ENOBUFS + * - if a cache block was already allocated: + * - a BIO will be dispatched to write the page (end_io_func will be called + * from the completion function) + * - returns 0 + */ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) +extern int __fscache_write_page(struct fscache_cookie *cookie, + struct page *page, + fscache_rw_complete_t end_io_func, + void *context, + gfp_t gfp); + +extern int __fscache_write_pages(struct fscache_cookie *cookie, + struct pagevec *pagevec, + fscache_rw_complete_t end_io_func, + void *context, + gfp_t gfp); +#endif + +static inline +int fscache_write_page(struct fscache_cookie *cookie, + struct page *page, + fscache_rw_complete_t end_io_func, + void *context, + gfp_t gfp) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + if (cookie) + return __fscache_write_page(cookie, page, end_io_func, + context, gfp); +#endif + return -ENOBUFS; +} + +static inline +int fscache_write_pages(struct fscache_cookie *cookie, + struct pagevec *pagevec, + fscache_rw_complete_t end_io_func, + void *context, + gfp_t gfp) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + if (cookie) + return __fscache_write_pages(cookie, pagevec, end_io_func, + context, gfp); +#endif + return -ENOBUFS; +} + +/* + * indicate that caching is no longer required on a page + * - note: cannot cancel any outstanding BIOs between this page and the cache + */ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) +extern void __fscache_uncache_page(struct fscache_cookie *cookie, + struct page *page); +extern void __fscache_uncache_pages(struct fscache_cookie *cookie, + struct pagevec *pagevec); +#endif + +static inline +void fscache_uncache_page(struct fscache_cookie *cookie, + struct page *page) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + if (cookie) + __fscache_uncache_page(cookie, page); +#endif +} + +static inline +void fscache_uncache_pagevec(struct fscache_cookie *cookie, + struct pagevec *pagevec) +{ +#if defined(CONFIG_FSCACHE) || defined(CONFIG_FSCACHE_MODULE) + if (cookie) + __fscache_uncache_pages(cookie, pagevec); +#endif +} + +#endif /* _LINUX_FSCACHE_H */ diff --git a/include/linux/hdlc/Kbuild b/include/linux/hdlc/Kbuild new file mode 100644 index 000000000..1fb26448f --- /dev/null +++ b/include/linux/hdlc/Kbuild @@ -0,0 +1 @@ +header-y += ioctl.h diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h new file mode 100644 index 000000000..21ea7610e --- /dev/null +++ b/include/linux/hw_random.h @@ -0,0 +1,50 @@ +/* + Hardware Random Number Generator + + Please read Documentation/hw_random.txt for details on use. + + ---------------------------------------------------------- + This software may be used and distributed according to the terms + of the GNU General Public License, incorporated herein by reference. + + */ + +#ifndef LINUX_HWRANDOM_H_ +#define LINUX_HWRANDOM_H_ +#ifdef __KERNEL__ + +#include <linux/types.h> +#include <linux/list.h> + +/** + * struct hwrng - Hardware Random Number Generator driver + * @name: Unique RNG name. + * @init: Initialization callback (can be NULL). + * @cleanup: Cleanup callback (can be NULL). + * @data_present: Callback to determine if data is available + * on the RNG. If NULL, it is assumed that + * there is always data available. + * @data_read: Read data from the RNG device. + * Returns the number of lower random bytes in "data". + * Must not be NULL. + * @priv: Private data, for use by the RNG driver. + */ +struct hwrng { + const char *name; + int (*init)(struct hwrng *rng); + void (*cleanup)(struct hwrng *rng); + int (*data_present)(struct hwrng *rng); + int (*data_read)(struct hwrng *rng, u32 *data); + unsigned long priv; + + /* internal. */ + struct list_head list; +}; + +/** Register a new Hardware Random Number Generator driver. */ +extern int hwrng_register(struct hwrng *rng); +/** Unregister a Hardware Random Number Generator driver. */ +extern void hwrng_unregister(struct hwrng *rng); + +#endif /* __KERNEL__ */ +#endif /* LINUX_HWRANDOM_H_ */ diff --git a/include/linux/i2c-ocores.h b/include/linux/i2c-ocores.h new file mode 100644 index 000000000..8ed591b08 --- /dev/null +++ b/include/linux/i2c-ocores.h @@ -0,0 +1,19 @@ +/* + * i2c-ocores.h - definitions for the i2c-ocores interface + * + * Peter Korsgaard <jacmet@sunsite.dk> + * + * This file is licensed under the terms of the GNU General Public License + * version 2. This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#ifndef _LINUX_I2C_OCORES_H +#define _LINUX_I2C_OCORES_H + +struct ocores_i2c_platform_data { + u32 regstep; /* distance between registers */ + u32 clock_khz; /* input clock in kHz */ +}; + +#endif /* _LINUX_I2C_OCORES_H */ diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h new file mode 100644 index 000000000..412e025bc --- /dev/null +++ b/include/linux/irqflags.h @@ -0,0 +1,96 @@ +/* + * include/linux/irqflags.h + * + * IRQ flags tracing: follow the state of the hardirq and softirq flags and + * provide callbacks for transitions between ON and OFF states. + * + * This file gets included from lowlevel asm headers too, to provide + * wrapped versions of the local_irq_*() APIs, based on the + * raw_local_irq_*() macros from the lowlevel headers. + */ +#ifndef _LINUX_TRACE_IRQFLAGS_H +#define _LINUX_TRACE_IRQFLAGS_H + +#ifdef CONFIG_TRACE_IRQFLAGS + extern void trace_hardirqs_on(void); + extern void trace_hardirqs_off(void); + extern void trace_softirqs_on(unsigned long ip); + extern void trace_softirqs_off(unsigned long ip); +# define trace_hardirq_context(p) ((p)->hardirq_context) +# define trace_softirq_context(p) ((p)->softirq_context) +# define trace_hardirqs_enabled(p) ((p)->hardirqs_enabled) +# define trace_softirqs_enabled(p) ((p)->softirqs_enabled) +# define trace_hardirq_enter() do { current->hardirq_context++; } while (0) +# define trace_hardirq_exit() do { current->hardirq_context--; } while (0) +# define trace_softirq_enter() do { current->softirq_context++; } while (0) +# define trace_softirq_exit() do { current->softirq_context--; } while (0) +# define INIT_TRACE_IRQFLAGS .softirqs_enabled = 1, +#else +# define trace_hardirqs_on() do { } while (0) +# define trace_hardirqs_off() do { } while (0) +# define trace_softirqs_on(ip) do { } while (0) +# define trace_softirqs_off(ip) do { } while (0) +# define trace_hardirq_context(p) 0 +# define trace_softirq_context(p) 0 +# define trace_hardirqs_enabled(p) 0 +# define trace_softirqs_enabled(p) 0 +# define trace_hardirq_enter() do { } while (0) +# define trace_hardirq_exit() do { } while (0) +# define trace_softirq_enter() do { } while (0) +# define trace_softirq_exit() do { } while (0) +# define INIT_TRACE_IRQFLAGS +#endif + +#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT + +#include <asm/irqflags.h> + +#define local_irq_enable() \ + do { trace_hardirqs_on(); raw_local_irq_enable(); } while (0) +#define local_irq_disable() \ + do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0) +#define local_irq_save(flags) \ + do { raw_local_irq_save(flags); trace_hardirqs_off(); } while (0) + +#define local_irq_restore(flags) \ + do { \ + if (raw_irqs_disabled_flags(flags)) { \ + raw_local_irq_restore(flags); \ + trace_hardirqs_off(); \ + } else { \ + trace_hardirqs_on(); \ + raw_local_irq_restore(flags); \ + } \ + } while (0) +#else /* !CONFIG_TRACE_IRQFLAGS_SUPPORT */ +/* + * The local_irq_*() APIs are equal to the raw_local_irq*() + * if !TRACE_IRQFLAGS. + */ +# define raw_local_irq_disable() local_irq_disable() +# define raw_local_irq_enable() local_irq_enable() +# define raw_local_irq_save(flags) local_irq_save(flags) +# define raw_local_irq_restore(flags) local_irq_restore(flags) +#endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */ + +#ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT +#define safe_halt() \ + do { \ + trace_hardirqs_on(); \ + raw_safe_halt(); \ + } while (0) + +#define local_save_flags(flags) raw_local_save_flags(flags) + +#define irqs_disabled() \ +({ \ + unsigned long flags; \ + \ + raw_local_save_flags(flags); \ + raw_irqs_disabled_flags(flags); \ +}) + +#define irqs_disabled_flags(flags) raw_irqs_disabled_flags(flags) +#endif /* CONFIG_X86 */ + +#endif diff --git a/include/linux/irqreturn.h b/include/linux/irqreturn.h new file mode 100644 index 000000000..881883c20 --- /dev/null +++ b/include/linux/irqreturn.h @@ -0,0 +1,25 @@ +/* irqreturn.h */ +#ifndef _LINUX_IRQRETURN_H +#define _LINUX_IRQRETURN_H + +/* + * For 2.4.x compatibility, 2.4.x can use + * + * typedef void irqreturn_t; + * #define IRQ_NONE + * #define IRQ_HANDLED + * #define IRQ_RETVAL(x) + * + * To mix old-style and new-style irq handler returns. + * + * IRQ_NONE means we didn't handle it. + * IRQ_HANDLED means that we did have a valid interrupt and handled it. + * IRQ_RETVAL(x) selects on the two depending on x being non-zero (for handled) + */ +typedef int irqreturn_t; + +#define IRQ_NONE (0) +#define IRQ_HANDLED (1) +#define IRQ_RETVAL(x) ((x) != 0) + +#endif diff --git a/include/linux/isa.h b/include/linux/isa.h new file mode 100644 index 000000000..1b855335c --- /dev/null +++ b/include/linux/isa.h @@ -0,0 +1,28 @@ +/* + * ISA bus. + */ + +#ifndef __LINUX_ISA_H +#define __LINUX_ISA_H + +#include <linux/device.h> +#include <linux/kernel.h> + +struct isa_driver { + int (*match)(struct device *, unsigned int); + int (*probe)(struct device *, unsigned int); + int (*remove)(struct device *, unsigned int); + void (*shutdown)(struct device *, unsigned int); + int (*suspend)(struct device *, unsigned int, pm_message_t); + int (*resume)(struct device *, unsigned int); + + struct device_driver driver; + struct device *devices; +}; + +#define to_isa_driver(x) container_of((x), struct isa_driver, driver) + +int isa_register_driver(struct isa_driver *, unsigned int); +void isa_unregister_driver(struct isa_driver *); + +#endif /* __LINUX_ISA_H */ diff --git a/include/linux/isdn/Kbuild b/include/linux/isdn/Kbuild new file mode 100644 index 000000000..991cdb29a --- /dev/null +++ b/include/linux/isdn/Kbuild @@ -0,0 +1 @@ +header-y += capicmd.h diff --git a/include/linux/license.h b/include/linux/license.h new file mode 100644 index 000000000..decdbf43c --- /dev/null +++ b/include/linux/license.h @@ -0,0 +1,14 @@ +#ifndef __LICENSE_H +#define __LICENSE_H + +static inline int license_is_gpl_compatible(const char *license) +{ + return (strcmp(license, "GPL") == 0 + || strcmp(license, "GPL v2") == 0 + || strcmp(license, "GPL and additional rights") == 0 + || strcmp(license, "Dual BSD/GPL") == 0 + || strcmp(license, "Dual MIT/GPL") == 0 + || strcmp(license, "Dual MPL/GPL") == 0); +} + +#endif diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h new file mode 100644 index 000000000..716787278 --- /dev/null +++ b/include/linux/lockdep.h @@ -0,0 +1,357 @@ +/* + * Runtime locking correctness validator + * + * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + * + * see Documentation/lockdep-design.txt for more details. + */ +#ifndef __LINUX_LOCKDEP_H +#define __LINUX_LOCKDEP_H + +#include <linux/linkage.h> +#include <linux/list.h> +#include <linux/debug_locks.h> +#include <linux/stacktrace.h> + +#ifdef CONFIG_LOCKDEP + +/* + * Lock-class usage-state bits: + */ +enum lock_usage_bit +{ + LOCK_USED = 0, + LOCK_USED_IN_HARDIRQ, + LOCK_USED_IN_SOFTIRQ, + LOCK_ENABLED_SOFTIRQS, + LOCK_ENABLED_HARDIRQS, + LOCK_USED_IN_HARDIRQ_READ, + LOCK_USED_IN_SOFTIRQ_READ, + LOCK_ENABLED_SOFTIRQS_READ, + LOCK_ENABLED_HARDIRQS_READ, + LOCK_USAGE_STATES +}; + +/* + * Usage-state bitmasks: + */ +#define LOCKF_USED (1 << LOCK_USED) +#define LOCKF_USED_IN_HARDIRQ (1 << LOCK_USED_IN_HARDIRQ) +#define LOCKF_USED_IN_SOFTIRQ (1 << LOCK_USED_IN_SOFTIRQ) +#define LOCKF_ENABLED_HARDIRQS (1 << LOCK_ENABLED_HARDIRQS) +#define LOCKF_ENABLED_SOFTIRQS (1 << LOCK_ENABLED_SOFTIRQS) + +#define LOCKF_ENABLED_IRQS (LOCKF_ENABLED_HARDIRQS | LOCKF_ENABLED_SOFTIRQS) +#define LOCKF_USED_IN_IRQ (LOCKF_USED_IN_HARDIRQ | LOCKF_USED_IN_SOFTIRQ) + +#define LOCKF_USED_IN_HARDIRQ_READ (1 << LOCK_USED_IN_HARDIRQ_READ) +#define LOCKF_USED_IN_SOFTIRQ_READ (1 << LOCK_USED_IN_SOFTIRQ_READ) +#define LOCKF_ENABLED_HARDIRQS_READ (1 << LOCK_ENABLED_HARDIRQS_READ) +#define LOCKF_ENABLED_SOFTIRQS_READ (1 << LOCK_ENABLED_SOFTIRQS_READ) + +#define LOCKF_ENABLED_IRQS_READ \ + (LOCKF_ENABLED_HARDIRQS_READ | LOCKF_ENABLED_SOFTIRQS_READ) +#define LOCKF_USED_IN_IRQ_READ \ + (LOCKF_USED_IN_HARDIRQ_READ | LOCKF_USED_IN_SOFTIRQ_READ) + +#define MAX_LOCKDEP_SUBCLASSES 8UL + +/* + * Lock-classes are keyed via unique addresses, by embedding the + * lockclass-key into the kernel (or module) .data section. (For + * static locks we use the lock address itself as the key.) + */ +struct lockdep_subclass_key { + char __one_byte; +} __attribute__ ((__packed__)); + +struct lock_class_key { + struct lockdep_subclass_key subkeys[MAX_LOCKDEP_SUBCLASSES]; +}; + +/* + * The lock-class itself: + */ +struct lock_class { + /* + * class-hash: + */ + struct list_head hash_entry; + + /* + * global list of all lock-classes: + */ + struct list_head lock_entry; + + struct lockdep_subclass_key *key; + unsigned int subclass; + + /* + * IRQ/softirq usage tracking bits: + */ + unsigned long usage_mask; + struct stack_trace usage_traces[LOCK_USAGE_STATES]; + + /* + * These fields represent a directed graph of lock dependencies, + * to every node we attach a list of "forward" and a list of + * "backward" graph nodes. + */ + struct list_head locks_after, locks_before; + + /* + * Generation counter, when doing certain classes of graph walking, + * to ensure that we check one node only once: + */ + unsigned int version; + + /* + * Statistics counter: + */ + unsigned long ops; + + const char *name; + int name_version; +}; + +/* + * Map the lock object (the lock instance) to the lock-class object. + * This is embedded into specific lock instances: + */ +struct lockdep_map { + struct lock_class_key *key; + struct lock_class *class_cache; + const char *name; +}; + +/* + * Every lock has a list of other locks that were taken after it. + * We only grow the list, never remove from it: + */ +struct lock_list { + struct list_head entry; + struct lock_class *class; + struct stack_trace trace; +}; + +/* + * We record lock dependency chains, so that we can cache them: + */ +struct lock_chain { + struct list_head entry; + u64 chain_key; +}; + +struct held_lock { + /* + * One-way hash of the dependency chain up to this point. We + * hash the hashes step by step as the dependency chain grows. + * + * We use it for dependency-caching and we skip detection + * passes and dependency-updates if there is a cache-hit, so + * it is absolutely critical for 100% coverage of the validator + * to have a unique key value for every unique dependency path + * that can occur in the system, to make a unique hash value + * as likely as possible - hence the 64-bit width. + * + * The task struct holds the current hash value (initialized + * with zero), here we store the previous hash value: + */ + u64 prev_chain_key; + struct lock_class *class; + unsigned long acquire_ip; + struct lockdep_map *instance; + + /* + * The lock-stack is unified in that the lock chains of interrupt + * contexts nest ontop of process context chains, but we 'separate' + * the hashes by starting with 0 if we cross into an interrupt + * context, and we also keep do not add cross-context lock + * dependencies - the lock usage graph walking covers that area + * anyway, and we'd just unnecessarily increase the number of + * dependencies otherwise. [Note: hardirq and softirq contexts + * are separated from each other too.] + * + * The following field is used to detect when we cross into an + * interrupt context: + */ + int irq_context; + int trylock; + int read; + int check; + int hardirqs_off; +}; + +/* + * Initialization, self-test and debugging-output methods: + */ +extern void lockdep_init(void); +extern void lockdep_info(void); +extern void lockdep_reset(void); +extern void lockdep_reset_lock(struct lockdep_map *lock); +extern void lockdep_free_key_range(void *start, unsigned long size); + +extern void lockdep_off(void); +extern void lockdep_on(void); +extern int lockdep_internal(void); + +/* + * These methods are used by specific locking variants (spinlocks, + * rwlocks, mutexes and rwsems) to pass init/acquire/release events + * to lockdep: + */ + +extern void lockdep_init_map(struct lockdep_map *lock, const char *name, + struct lock_class_key *key, int subclass); + +/* + * Reinitialize a lock key - for cases where there is special locking or + * special initialization of locks so that the validator gets the scope + * of dependencies wrong: they are either too broad (they need a class-split) + * or they are too narrow (they suffer from a false class-split): + */ +#define lockdep_set_class(lock, key) \ + lockdep_init_map(&(lock)->dep_map, #key, key, 0) +#define lockdep_set_class_and_name(lock, key, name) \ + lockdep_init_map(&(lock)->dep_map, name, key, 0) +#define lockdep_set_class_and_subclass(lock, key, sub) \ + lockdep_init_map(&(lock)->dep_map, #key, key, sub) + +/* + * Acquire a lock. + * + * Values for "read": + * + * 0: exclusive (write) acquire + * 1: read-acquire (no recursion allowed) + * 2: read-acquire with same-instance recursion allowed + * + * Values for check: + * + * 0: disabled + * 1: simple checks (freeing, held-at-exit-time, etc.) + * 2: full validation + */ +extern void lock_acquire(struct lockdep_map *lock, unsigned int subclass, + int trylock, int read, int check, unsigned long ip); + +extern void lock_release(struct lockdep_map *lock, int nested, + unsigned long ip); + +# define INIT_LOCKDEP .lockdep_recursion = 0, + +#else /* !LOCKDEP */ + +static inline void lockdep_off(void) +{ +} + +static inline void lockdep_on(void) +{ +} + +static inline int lockdep_internal(void) +{ + return 0; +} + +# define lock_acquire(l, s, t, r, c, i) do { } while (0) +# define lock_release(l, n, i) do { } while (0) +# define lockdep_init() do { } while (0) +# define lockdep_info() do { } while (0) +# define lockdep_init_map(lock, name, key, sub) do { (void)(key); } while (0) +# define lockdep_set_class(lock, key) do { (void)(key); } while (0) +# define lockdep_set_class_and_name(lock, key, name) \ + do { (void)(key); } while (0) +#define lockdep_set_class_and_subclass(lock, key, sub) \ + do { (void)(key); } while (0) +# define INIT_LOCKDEP +# define lockdep_reset() do { debug_locks = 1; } while (0) +# define lockdep_free_key_range(start, size) do { } while (0) +/* + * The class key takes no space if lockdep is disabled: + */ +struct lock_class_key { }; +#endif /* !LOCKDEP */ + +#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_GENERIC_HARDIRQS) +extern void early_init_irq_lock_class(void); +#else +# define early_init_irq_lock_class() do { } while (0) +#endif + +#ifdef CONFIG_TRACE_IRQFLAGS +extern void early_boot_irqs_off(void); +extern void early_boot_irqs_on(void); +#else +# define early_boot_irqs_off() do { } while (0) +# define early_boot_irqs_on() do { } while (0) +#endif + +/* + * For trivial one-depth nesting of a lock-class, the following + * global define can be used. (Subsystems with multiple levels + * of nesting should define their own lock-nesting subclasses.) + */ +#define SINGLE_DEPTH_NESTING 1 + +/* + * Map the dependency ops to NOP or to real lockdep ops, depending + * on the per lock-class debug mode: + */ + +#ifdef CONFIG_DEBUG_LOCK_ALLOC +# ifdef CONFIG_PROVE_LOCKING +# define spin_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, i) +# else +# define spin_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, i) +# endif +# define spin_release(l, n, i) lock_release(l, n, i) +#else +# define spin_acquire(l, s, t, i) do { } while (0) +# define spin_release(l, n, i) do { } while (0) +#endif + +#ifdef CONFIG_DEBUG_LOCK_ALLOC +# ifdef CONFIG_PROVE_LOCKING +# define rwlock_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, i) +# define rwlock_acquire_read(l, s, t, i) lock_acquire(l, s, t, 2, 2, i) +# else +# define rwlock_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, i) +# define rwlock_acquire_read(l, s, t, i) lock_acquire(l, s, t, 2, 1, i) +# endif +# define rwlock_release(l, n, i) lock_release(l, n, i) +#else +# define rwlock_acquire(l, s, t, i) do { } while (0) +# define rwlock_acquire_read(l, s, t, i) do { } while (0) +# define rwlock_release(l, n, i) do { } while (0) +#endif + +#ifdef CONFIG_DEBUG_LOCK_ALLOC +# ifdef CONFIG_PROVE_LOCKING +# define mutex_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, i) +# else +# define mutex_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, i) +# endif +# define mutex_release(l, n, i) lock_release(l, n, i) +#else +# define mutex_acquire(l, s, t, i) do { } while (0) +# define mutex_release(l, n, i) do { } while (0) +#endif + +#ifdef CONFIG_DEBUG_LOCK_ALLOC +# ifdef CONFIG_PROVE_LOCKING +# define rwsem_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, i) +# define rwsem_acquire_read(l, s, t, i) lock_acquire(l, s, t, 1, 2, i) +# else +# define rwsem_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, i) +# define rwsem_acquire_read(l, s, t, i) lock_acquire(l, s, t, 1, 1, i) +# endif +# define rwsem_release(l, n, i) lock_release(l, n, i) +#else +# define rwsem_acquire(l, s, t, i) do { } while (0) +# define rwsem_acquire_read(l, s, t, i) do { } while (0) +# define rwsem_release(l, n, i) do { } while (0) +#endif + +#endif /* __LINUX_LOCKDEP_H */ diff --git a/include/linux/m41t00.h b/include/linux/m41t00.h new file mode 100644 index 000000000..b423360ca --- /dev/null +++ b/include/linux/m41t00.h @@ -0,0 +1,50 @@ +/* + * Definitions for the ST M41T00 family of i2c rtc chips. + * + * Author: Mark A. Greer <mgreer@mvista.com> + * + * 2005, 2006 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#ifndef _M41T00_H +#define _M41T00_H + +#define M41T00_DRV_NAME "m41t00" +#define M41T00_I2C_ADDR 0x68 + +#define M41T00_TYPE_M41T00 0 +#define M41T00_TYPE_M41T81 81 +#define M41T00_TYPE_M41T85 85 + +struct m41t00_platform_data { + u8 type; + u8 i2c_addr; + u8 sqw_freq; +}; + +/* SQW output disabled, this is default value by power on */ +#define M41T00_SQW_DISABLE (0) + +#define M41T00_SQW_32KHZ (1<<4) /* 32.768 KHz */ +#define M41T00_SQW_8KHZ (2<<4) /* 8.192 KHz */ +#define M41T00_SQW_4KHZ (3<<4) /* 4.096 KHz */ +#define M41T00_SQW_2KHZ (4<<4) /* 2.048 KHz */ +#define M41T00_SQW_1KHZ (5<<4) /* 1.024 KHz */ +#define M41T00_SQW_512HZ (6<<4) /* 512 Hz */ +#define M41T00_SQW_256HZ (7<<4) /* 256 Hz */ +#define M41T00_SQW_128HZ (8<<4) /* 128 Hz */ +#define M41T00_SQW_64HZ (9<<4) /* 64 Hz */ +#define M41T00_SQW_32HZ (10<<4) /* 32 Hz */ +#define M41T00_SQW_16HZ (11<<4) /* 16 Hz */ +#define M41T00_SQW_8HZ (12<<4) /* 8 Hz */ +#define M41T00_SQW_4HZ (13<<4) /* 4 Hz */ +#define M41T00_SQW_2HZ (14<<4) /* 2 Hz */ +#define M41T00_SQW_1HZ (15<<4) /* 1 Hz */ + +extern ulong m41t00_get_rtc_time(void); +extern int m41t00_set_rtc_time(ulong nowtime); + +#endif /* _M41T00_H */ diff --git a/include/linux/mtd/ndfc.h b/include/linux/mtd/ndfc.h new file mode 100644 index 000000000..d0558a982 --- /dev/null +++ b/include/linux/mtd/ndfc.h @@ -0,0 +1,67 @@ +/* + * linux/include/linux/mtd/ndfc.h + * + * Copyright (c) 2006 Thomas Gleixner <tglx@linutronix.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Info: + * Contains defines, datastructures for ndfc nand controller + * + */ +#ifndef __LINUX_MTD_NDFC_H +#define __LINUX_MTD_NDFC_H + +/* NDFC Register definitions */ +#define NDFC_CMD 0x00 +#define NDFC_ALE 0x04 +#define NDFC_DATA 0x08 +#define NDFC_ECC 0x10 +#define NDFC_BCFG0 0x30 +#define NDFC_BCFG1 0x34 +#define NDFC_BCFG2 0x38 +#define NDFC_BCFG3 0x3c +#define NDFC_CCR 0x40 +#define NDFC_STAT 0x44 +#define NDFC_HWCTL 0x48 +#define NDFC_REVID 0x50 + +#define NDFC_STAT_IS_READY 0x01000000 + +#define NDFC_CCR_RESET_CE 0x80000000 /* CE Reset */ +#define NDFC_CCR_RESET_ECC 0x40000000 /* ECC Reset */ +#define NDFC_CCR_RIE 0x20000000 /* Interrupt Enable on Device Rdy */ +#define NDFC_CCR_REN 0x10000000 /* Enable wait for Rdy in LinearR */ +#define NDFC_CCR_ROMEN 0x08000000 /* Enable ROM In LinearR */ +#define NDFC_CCR_ARE 0x04000000 /* Auto-Read Enable */ +#define NDFC_CCR_BS(x) (((x) & 0x3) << 24) /* Select Bank on CE[x] */ +#define NDFC_CCR_BS_MASK 0x03000000 /* Select Bank */ +#define NDFC_CCR_ARAC0 0x00000000 /* 3 Addr, 1 Col 2 Row 512b page */ +#define NDFC_CCR_ARAC1 0x00001000 /* 4 Addr, 1 Col 3 Row 512b page */ +#define NDFC_CCR_ARAC2 0x00002000 /* 4 Addr, 2 Col 2 Row 2K page */ +#define NDFC_CCR_ARAC3 0x00003000 /* 5 Addr, 2 Col 3 Row 2K page */ +#define NDFC_CCR_ARAC_MASK 0x00003000 /* Auto-Read mode Addr Cycles */ +#define NDFC_CCR_RPG 0x0000C000 /* Auto-Read Page */ +#define NDFC_CCR_EBCC 0x00000004 /* EBC Configuration Completed */ +#define NDFC_CCR_DHC 0x00000002 /* Direct Hardware Control Enable */ + +#define NDFC_BxCFG_EN 0x80000000 /* Bank Enable */ +#define NDFC_BxCFG_CED 0x40000000 /* nCE Style */ +#define NDFC_BxCFG_SZ_MASK 0x08000000 /* Bank Size */ +#define NDFC_BxCFG_SZ_8BIT 0x00000000 /* 8bit */ +#define NDFC_BxCFG_SZ_16BIT 0x08000000 /* 16bit */ + +#define NDFC_MAX_BANKS 4 + +struct ndfc_controller_settings { + uint32_t ccr_settings; + uint64_t ndfc_erpn; +}; + +struct ndfc_chip_settings { + uint32_t bank_settings; +}; + +#endif diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild new file mode 100644 index 000000000..9a285cecf --- /dev/null +++ b/include/linux/netfilter/Kbuild @@ -0,0 +1,38 @@ +header-y += nf_conntrack_sctp.h +header-y += nf_conntrack_tuple_common.h +header-y += nfnetlink_conntrack.h +header-y += nfnetlink_log.h +header-y += nfnetlink_queue.h +header-y += xt_CLASSIFY.h +header-y += xt_comment.h +header-y += xt_connbytes.h +header-y += xt_connmark.h +header-y += xt_CONNMARK.h +header-y += xt_conntrack.h +header-y += xt_dccp.h +header-y += xt_esp.h +header-y += xt_helper.h +header-y += xt_length.h +header-y += xt_limit.h +header-y += xt_mac.h +header-y += xt_mark.h +header-y += xt_MARK.h +header-y += xt_multiport.h +header-y += xt_NFQUEUE.h +header-y += xt_pkttype.h +header-y += xt_policy.h +header-y += xt_realm.h +header-y += xt_sctp.h +header-y += xt_state.h +header-y += xt_string.h +header-y += xt_tcpmss.h +header-y += xt_tcpudp.h +header-y += xt_SECMARK.h +header-y += xt_CONNSECMARK.h + +unifdef-y += nf_conntrack_common.h +unifdef-y += nf_conntrack_ftp.h +unifdef-y += nf_conntrack_tcp.h +unifdef-y += nfnetlink.h +unifdef-y += x_tables.h +unifdef-y += xt_physdev.h diff --git a/include/linux/netfilter/xt_CONNSECMARK.h b/include/linux/netfilter/xt_CONNSECMARK.h new file mode 100644 index 000000000..c6bd75469 --- /dev/null +++ b/include/linux/netfilter/xt_CONNSECMARK.h @@ -0,0 +1,13 @@ +#ifndef _XT_CONNSECMARK_H_target +#define _XT_CONNSECMARK_H_target + +enum { + CONNSECMARK_SAVE = 1, + CONNSECMARK_RESTORE, +}; + +struct xt_connsecmark_target_info { + u_int8_t mode; +}; + +#endif /*_XT_CONNSECMARK_H_target */ diff --git a/include/linux/netfilter/xt_SECMARK.h b/include/linux/netfilter/xt_SECMARK.h new file mode 100644 index 000000000..c53fbffa9 --- /dev/null +++ b/include/linux/netfilter/xt_SECMARK.h @@ -0,0 +1,26 @@ +#ifndef _XT_SECMARK_H_target +#define _XT_SECMARK_H_target + +/* + * This is intended for use by various security subsystems (but not + * at the same time). + * + * 'mode' refers to the specific security subsystem which the + * packets are being marked for. + */ +#define SECMARK_MODE_SEL 0x01 /* SELinux */ +#define SECMARK_SELCTX_MAX 256 + +struct xt_secmark_target_selinux_info { + u_int32_t selsid; + char selctx[SECMARK_SELCTX_MAX]; +}; + +struct xt_secmark_target_info { + u_int8_t mode; + union { + struct xt_secmark_target_selinux_info sel; + } u; +}; + +#endif /*_XT_SECMARK_H_target */ diff --git a/include/linux/netfilter/xt_quota.h b/include/linux/netfilter/xt_quota.h new file mode 100644 index 000000000..acd7fd77b --- /dev/null +++ b/include/linux/netfilter/xt_quota.h @@ -0,0 +1,16 @@ +#ifndef _XT_QUOTA_H +#define _XT_QUOTA_H + +enum xt_quota_flags { + XT_QUOTA_INVERT = 0x1, +}; +#define XT_QUOTA_MASK 0x1 + +struct xt_quota_info { + u_int32_t flags; + u_int32_t pad; + aligned_u64 quota; + struct xt_quota_info *master; +}; + +#endif /* _XT_QUOTA_H */ diff --git a/include/linux/netfilter/xt_statistic.h b/include/linux/netfilter/xt_statistic.h new file mode 100644 index 000000000..c344e9916 --- /dev/null +++ b/include/linux/netfilter/xt_statistic.h @@ -0,0 +1,32 @@ +#ifndef _XT_STATISTIC_H +#define _XT_STATISTIC_H + +enum xt_statistic_mode { + XT_STATISTIC_MODE_RANDOM, + XT_STATISTIC_MODE_NTH, + __XT_STATISTIC_MODE_MAX +}; +#define XT_STATISTIC_MODE_MAX (__XT_STATISTIC_MODE_MAX - 1) + +enum xt_statistic_flags { + XT_STATISTIC_INVERT = 0x1, +}; +#define XT_STATISTIC_MASK 0x1 + +struct xt_statistic_info { + u_int16_t mode; + u_int16_t flags; + union { + struct { + u_int32_t probability; + } random; + struct { + u_int32_t every; + u_int32_t packet; + u_int32_t count; + } nth; + } u; + struct xt_statistic_info *master __attribute__((aligned(8))); +}; + +#endif /* _XT_STATISTIC_H */ diff --git a/include/linux/netfilter_arp/Kbuild b/include/linux/netfilter_arp/Kbuild new file mode 100644 index 000000000..4f13dfcb9 --- /dev/null +++ b/include/linux/netfilter_arp/Kbuild @@ -0,0 +1,3 @@ +header-y += arpt_mangle.h + +unifdef-y += arp_tables.h diff --git a/include/linux/netfilter_bridge/Kbuild b/include/linux/netfilter_bridge/Kbuild new file mode 100644 index 000000000..76ff4c47d --- /dev/null +++ b/include/linux/netfilter_bridge/Kbuild @@ -0,0 +1,17 @@ +header-y += ebt_among.h +header-y += ebt_arp.h +header-y += ebt_arpreply.h +header-y += ebt_ip.h +header-y += ebt_limit.h +header-y += ebt_log.h +header-y += ebt_mark_m.h +header-y += ebt_mark_t.h +header-y += ebt_nat.h +header-y += ebt_pkttype.h +header-y += ebt_redirect.h +header-y += ebt_stp.h +header-y += ebt_ulog.h +header-y += ebt_vlan.h + +unifdef-y += ebtables.h +unifdef-y += ebt_802_3.h diff --git a/include/linux/netfilter_ipv4/Kbuild b/include/linux/netfilter_ipv4/Kbuild new file mode 100644 index 000000000..591c1a809 --- /dev/null +++ b/include/linux/netfilter_ipv4/Kbuild @@ -0,0 +1,63 @@ +header-y += ip_conntrack_helper.h +header-y += ip_conntrack_helper_h323_asn1.h +header-y += ip_conntrack_helper_h323_types.h +header-y += ip_conntrack_protocol.h +header-y += ip_conntrack_sctp.h +header-y += ip_conntrack_tcp.h +header-y += ip_conntrack_tftp.h +header-y += ip_nat_pptp.h +header-y += ipt_addrtype.h +header-y += ipt_ah.h +header-y += ipt_CLASSIFY.h +header-y += ipt_CLUSTERIP.h +header-y += ipt_comment.h +header-y += ipt_connbytes.h +header-y += ipt_connmark.h +header-y += ipt_CONNMARK.h +header-y += ipt_conntrack.h +header-y += ipt_dccp.h +header-y += ipt_dscp.h +header-y += ipt_DSCP.h +header-y += ipt_ecn.h +header-y += ipt_ECN.h +header-y += ipt_esp.h +header-y += ipt_hashlimit.h +header-y += ipt_helper.h +header-y += ipt_iprange.h +header-y += ipt_length.h +header-y += ipt_limit.h +header-y += ipt_LOG.h +header-y += ipt_mac.h +header-y += ipt_mark.h +header-y += ipt_MARK.h +header-y += ipt_multiport.h +header-y += ipt_NFQUEUE.h +header-y += ipt_owner.h +header-y += ipt_physdev.h +header-y += ipt_pkttype.h +header-y += ipt_policy.h +header-y += ipt_realm.h +header-y += ipt_recent.h +header-y += ipt_REJECT.h +header-y += ipt_SAME.h +header-y += ipt_sctp.h +header-y += ipt_state.h +header-y += ipt_string.h +header-y += ipt_tcpmss.h +header-y += ipt_TCPMSS.h +header-y += ipt_tos.h +header-y += ipt_TOS.h +header-y += ipt_ttl.h +header-y += ipt_TTL.h +header-y += ipt_ULOG.h + +unifdef-y += ip_conntrack.h +unifdef-y += ip_conntrack_h323.h +unifdef-y += ip_conntrack_irc.h +unifdef-y += ip_conntrack_pptp.h +unifdef-y += ip_conntrack_proto_gre.h +unifdef-y += ip_conntrack_tuple.h +unifdef-y += ip_nat.h +unifdef-y += ip_nat_rule.h +unifdef-y += ip_queue.h +unifdef-y += ip_tables.h diff --git a/include/linux/netfilter_ipv4/ip_conntrack_sip.h b/include/linux/netfilter_ipv4/ip_conntrack_sip.h new file mode 100644 index 000000000..913dad66c --- /dev/null +++ b/include/linux/netfilter_ipv4/ip_conntrack_sip.h @@ -0,0 +1,44 @@ +#ifndef __IP_CONNTRACK_SIP_H__ +#define __IP_CONNTRACK_SIP_H__ +#ifdef __KERNEL__ + +#define SIP_PORT 5060 +#define SIP_TIMEOUT 3600 + +#define POS_VIA 0 +#define POS_CONTACT 1 +#define POS_CONTENT 2 +#define POS_MEDIA 3 +#define POS_OWNER 4 +#define POS_CONNECTION 5 +#define POS_REQ_HEADER 6 +#define POS_SDP_HEADER 7 + +struct sip_header_nfo { + const char *lname; + const char *sname; + const char *ln_str; + size_t lnlen; + size_t snlen; + size_t ln_strlen; + int (*match_len)(const char *, const char *, int *); +}; + +extern unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct ip_conntrack *ct, + const char **dptr); +extern unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct ip_conntrack_expect *exp, + const char *dptr); + +extern int ct_sip_get_info(const char *dptr, size_t dlen, + unsigned int *matchoff, + unsigned int *matchlen, + struct sip_header_nfo *hnfo); +extern int ct_sip_lnlen(const char *line, const char *limit); +extern const char *ct_sip_search(const char *needle, const char *haystack, + size_t needle_len, size_t haystack_len); +#endif /* __KERNEL__ */ +#endif /* __IP_CONNTRACK_SIP_H__ */ diff --git a/include/linux/netfilter_ipv6/Kbuild b/include/linux/netfilter_ipv6/Kbuild new file mode 100644 index 000000000..9dd978d14 --- /dev/null +++ b/include/linux/netfilter_ipv6/Kbuild @@ -0,0 +1,21 @@ +header-y += ip6t_HL.h +header-y += ip6t_LOG.h +header-y += ip6t_MARK.h +header-y += ip6t_REJECT.h +header-y += ip6t_ah.h +header-y += ip6t_esp.h +header-y += ip6t_frag.h +header-y += ip6t_hl.h +header-y += ip6t_ipv6header.h +header-y += ip6t_length.h +header-y += ip6t_limit.h +header-y += ip6t_mac.h +header-y += ip6t_mark.h +header-y += ip6t_multiport.h +header-y += ip6t_opts.h +header-y += ip6t_owner.h +header-y += ip6t_policy.h +header-y += ip6t_physdev.h +header-y += ip6t_rt.h + +unifdef-y += ip6_tables.h diff --git a/include/linux/nfsd/Kbuild b/include/linux/nfsd/Kbuild new file mode 100644 index 000000000..d9c545580 --- /dev/null +++ b/include/linux/nfsd/Kbuild @@ -0,0 +1,7 @@ +unifdef-y += const.h +unifdef-y += export.h +unifdef-y += stats.h +unifdef-y += syscall.h +unifdef-y += nfsfh.h +unifdef-y += debug.h +unifdef-y += auth.h diff --git a/include/linux/nsc_gpio.h b/include/linux/nsc_gpio.h new file mode 100644 index 000000000..7da0cf370 --- /dev/null +++ b/include/linux/nsc_gpio.h @@ -0,0 +1,40 @@ +/** + nsc_gpio.c + + National Semiconductor GPIO common access methods. + + struct nsc_gpio_ops abstracts the low-level access + operations for the GPIO units on 2 NSC chip families; the GEODE + integrated CPU, and the PC-8736[03456] integrated PC-peripheral + chips. + + The GPIO units on these chips have the same pin architecture, but + the access methods differ. Thus, scx200_gpio and pc8736x_gpio + implement their own versions of these routines; and use the common + file-operations routines implemented in nsc_gpio module. + + Copyright (c) 2005 Jim Cromie <jim.cromie@gmail.com> + + NB: this work was tested on the Geode SC-1100 and PC-87366 chips. + NSC sold the GEODE line to AMD, and the PC-8736x line to Winbond. +*/ + +struct nsc_gpio_ops { + struct module* owner; + u32 (*gpio_config) (unsigned iminor, u32 mask, u32 bits); + void (*gpio_dump) (struct nsc_gpio_ops *amp, unsigned iminor); + int (*gpio_get) (unsigned iminor); + void (*gpio_set) (unsigned iminor, int state); + void (*gpio_change) (unsigned iminor); + int (*gpio_current) (unsigned iminor); + struct device* dev; /* for dev_dbg() support, set in init */ +}; + +extern ssize_t nsc_gpio_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos); + +extern ssize_t nsc_gpio_read(struct file *file, char __user *buf, + size_t len, loff_t *ppos); + +extern void nsc_gpio_dump(struct nsc_gpio_ops *amp, unsigned index); + diff --git a/include/linux/plist.h b/include/linux/plist.h new file mode 100644 index 000000000..b95818a03 --- /dev/null +++ b/include/linux/plist.h @@ -0,0 +1,248 @@ +/* + * Descending-priority-sorted double-linked list + * + * (C) 2002-2003 Intel Corp + * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>. + * + * 2001-2005 (c) MontaVista Software, Inc. + * Daniel Walker <dwalker@mvista.com> + * + * (C) 2005 Thomas Gleixner <tglx@linutronix.de> + * + * Simplifications of the original code by + * Oleg Nesterov <oleg@tv-sign.ru> + * + * Licensed under the FSF's GNU Public License v2 or later. + * + * Based on simple lists (include/linux/list.h). + * + * This is a priority-sorted list of nodes; each node has a + * priority from INT_MIN (highest) to INT_MAX (lowest). + * + * Addition is O(K), removal is O(1), change of priority of a node is + * O(K) and K is the number of RT priority levels used in the system. + * (1 <= K <= 99) + * + * This list is really a list of lists: + * + * - The tier 1 list is the prio_list, different priority nodes. + * + * - The tier 2 list is the node_list, serialized nodes. + * + * Simple ASCII art explanation: + * + * |HEAD | + * | | + * |prio_list.prev|<------------------------------------| + * |prio_list.next|<->|pl|<->|pl|<--------------->|pl|<-| + * |10 | |10| |21| |21| |21| |40| (prio) + * | | | | | | | | | | | | + * | | | | | | | | | | | | + * |node_list.next|<->|nl|<->|nl|<->|nl|<->|nl|<->|nl|<-| + * |node_list.prev|<------------------------------------| + * + * The nodes on the prio_list list are sorted by priority to simplify + * the insertion of new nodes. There are no nodes with duplicate + * priorites on the list. + * + * The nodes on the node_list is ordered by priority and can contain + * entries which have the same priority. Those entries are ordered + * FIFO + * + * Addition means: look for the prio_list node in the prio_list + * for the priority of the node and insert it before the node_list + * entry of the next prio_list node. If it is the first node of + * that priority, add it to the prio_list in the right position and + * insert it into the serialized node_list list + * + * Removal means remove it from the node_list and remove it from + * the prio_list if the node_list list_head is non empty. In case + * of removal from the prio_list it must be checked whether other + * entries of the same priority are on the list or not. If there + * is another entry of the same priority then this entry has to + * replace the removed entry on the prio_list. If the entry which + * is removed is the only entry of this priority then a simple + * remove from both list is sufficient. + * + * INT_MIN is the highest priority, 0 is the medium highest, INT_MAX + * is lowest priority. + * + * No locking is done, up to the caller. + * + */ +#ifndef _LINUX_PLIST_H_ +#define _LINUX_PLIST_H_ + +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/spinlock_types.h> + +struct plist_head { + struct list_head prio_list; + struct list_head node_list; +#ifdef CONFIG_DEBUG_PI_LIST + spinlock_t *lock; +#endif +}; + +struct plist_node { + int prio; + struct plist_head plist; +}; + +#ifdef CONFIG_DEBUG_PI_LIST +# define PLIST_HEAD_LOCK_INIT(_lock) .lock = _lock +#else +# define PLIST_HEAD_LOCK_INIT(_lock) +#endif + +/** + * #PLIST_HEAD_INIT - static struct plist_head initializer + * + * @head: struct plist_head variable name + */ +#define PLIST_HEAD_INIT(head, _lock) \ +{ \ + .prio_list = LIST_HEAD_INIT((head).prio_list), \ + .node_list = LIST_HEAD_INIT((head).node_list), \ + PLIST_HEAD_LOCK_INIT(&(_lock)) \ +} + +/** + * #PLIST_NODE_INIT - static struct plist_node initializer + * + * @node: struct plist_node variable name + * @__prio: initial node priority + */ +#define PLIST_NODE_INIT(node, __prio) \ +{ \ + .prio = (__prio), \ + .plist = PLIST_HEAD_INIT((node).plist, NULL), \ +} + +/** + * plist_head_init - dynamic struct plist_head initializer + * + * @head: &struct plist_head pointer + */ +static inline void +plist_head_init(struct plist_head *head, spinlock_t *lock) +{ + INIT_LIST_HEAD(&head->prio_list); + INIT_LIST_HEAD(&head->node_list); +#ifdef CONFIG_DEBUG_PI_LIST + head->lock = lock; +#endif +} + +/** + * plist_node_init - Dynamic struct plist_node initializer + * + * @node: &struct plist_node pointer + * @prio: initial node priority + */ +static inline void plist_node_init(struct plist_node *node, int prio) +{ + node->prio = prio; + plist_head_init(&node->plist, NULL); +} + +extern void plist_add(struct plist_node *node, struct plist_head *head); +extern void plist_del(struct plist_node *node, struct plist_head *head); + +/** + * plist_for_each - iterate over the plist + * + * @pos1: the type * to use as a loop counter. + * @head: the head for your list. + */ +#define plist_for_each(pos, head) \ + list_for_each_entry(pos, &(head)->node_list, plist.node_list) + +/** + * plist_for_each_entry_safe - iterate over a plist of given type safe + * against removal of list entry + * + * @pos1: the type * to use as a loop counter. + * @n1: another type * to use as temporary storage + * @head: the head for your list. + */ +#define plist_for_each_safe(pos, n, head) \ + list_for_each_entry_safe(pos, n, &(head)->node_list, plist.node_list) + +/** + * plist_for_each_entry - iterate over list of given type + * + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define plist_for_each_entry(pos, head, mem) \ + list_for_each_entry(pos, &(head)->node_list, mem.plist.node_list) + +/** + * plist_for_each_entry_safe - iterate over list of given type safe against + * removal of list entry + * + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @m: the name of the list_struct within the struct. + */ +#define plist_for_each_entry_safe(pos, n, head, m) \ + list_for_each_entry_safe(pos, n, &(head)->node_list, m.plist.node_list) + +/** + * plist_head_empty - return !0 if a plist_head is empty + * + * @head: &struct plist_head pointer + */ +static inline int plist_head_empty(const struct plist_head *head) +{ + return list_empty(&head->node_list); +} + +/** + * plist_node_empty - return !0 if plist_node is not on a list + * + * @node: &struct plist_node pointer + */ +static inline int plist_node_empty(const struct plist_node *node) +{ + return plist_head_empty(&node->plist); +} + +/* All functions below assume the plist_head is not empty. */ + +/** + * plist_first_entry - get the struct for the first entry + * + * @ptr: the &struct plist_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#ifdef CONFIG_DEBUG_PI_LIST +# define plist_first_entry(head, type, member) \ +({ \ + WARN_ON(plist_head_empty(head)); \ + container_of(plist_first(head), type, member); \ +}) +#else +# define plist_first_entry(head, type, member) \ + container_of(plist_first(head), type, member) +#endif + +/** + * plist_first - return the first node (and thus, highest priority) + * + * @head: the &struct plist_head pointer + * + * Assumes the plist is _not_ empty. + */ +static inline struct plist_node* plist_first(const struct plist_head *head) +{ + return list_entry(head->node_list.next, + struct plist_node, plist.node_list); +} + +#endif diff --git a/include/linux/poison.h b/include/linux/poison.h new file mode 100644 index 000000000..3e628f990 --- /dev/null +++ b/include/linux/poison.h @@ -0,0 +1,63 @@ +#ifndef _LINUX_POISON_H +#define _LINUX_POISON_H + +/********** include/linux/list.h **********/ +/* + * These are non-NULL pointers that will result in page faults + * under normal circumstances, used to verify that nobody uses + * non-initialized list entries. + */ +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) + +/********** mm/slab.c **********/ +/* + * Magic nums for obj red zoning. + * Placed in the first word before and the first word after an obj. + */ +#define RED_INACTIVE 0x5A2CF071UL /* when obj is inactive */ +#define RED_ACTIVE 0x170FC2A5UL /* when obj is active */ + +/* ...and for poisoning */ +#define POISON_INUSE 0x5a /* for use-uninitialised poisoning */ +#define POISON_FREE 0x6b /* for use-after-free poisoning */ +#define POISON_END 0xa5 /* end-byte of poisoning */ + +/********** arch/$ARCH/mm/init.c **********/ +#define POISON_FREE_INITMEM 0xcc + +/********** arch/x86_64/mm/init.c **********/ +#define POISON_FREE_INITDATA 0xba + +/********** arch/ia64/hp/common/sba_iommu.c **********/ +/* + * arch/ia64/hp/common/sba_iommu.c uses a 16-byte poison string with a + * value of "SBAIOMMU POISON\0" for spill-over poisoning. + */ + +/********** fs/jbd/journal.c **********/ +#define JBD_POISON_FREE 0x5b + +/********** drivers/base/dmapool.c **********/ +#define POOL_POISON_FREED 0xa7 /* !inuse */ +#define POOL_POISON_ALLOCATED 0xa9 /* !initted */ + +/********** drivers/atm/ **********/ +#define ATM_POISON_FREE 0x12 +#define ATM_POISON 0xdeadbeef + +/********** net/ **********/ +#define NEIGHBOR_DEAD 0xdeadbeef +#define NETFILTER_LINK_POISON 0xdead57ac + +/********** kernel/mutexes **********/ +#define MUTEX_DEBUG_INIT 0x11 +#define MUTEX_DEBUG_FREE 0x22 + +/********** security/ **********/ +#define KEY_DESTROY 0xbd + +/********** sound/oss/ **********/ +#define OSS_POISON_FREE 0xAB + +#endif diff --git a/include/linux/raid/Kbuild b/include/linux/raid/Kbuild new file mode 100644 index 000000000..2415a64c5 --- /dev/null +++ b/include/linux/raid/Kbuild @@ -0,0 +1,2 @@ +header-y += md_p.h +header-y += md_u.h diff --git a/include/linux/resume-trace.h b/include/linux/resume-trace.h new file mode 100644 index 000000000..a376bd4ad --- /dev/null +++ b/include/linux/resume-trace.h @@ -0,0 +1,30 @@ +#ifndef RESUME_TRACE_H +#define RESUME_TRACE_H + +#ifdef CONFIG_PM_TRACE + +struct device; +extern void set_trace_device(struct device *); +extern void generate_resume_trace(void *tracedata, unsigned int user); + +#define TRACE_DEVICE(dev) set_trace_device(dev) +#define TRACE_RESUME(user) do { \ + void *tracedata; \ + asm volatile("movl $1f,%0\n" \ + ".section .tracedata,\"a\"\n" \ + "1:\t.word %c1\n" \ + "\t.long %c2\n" \ + ".previous" \ + :"=r" (tracedata) \ + : "i" (__LINE__), "i" (__FILE__)); \ + generate_resume_trace(tracedata, user); \ +} while (0) + +#else + +#define TRACE_DEVICE(dev) do { } while (0) +#define TRACE_RESUME(dev) do { } while (0) + +#endif + +#endif diff --git a/include/linux/rtc-v3020.h b/include/linux/rtc-v3020.h new file mode 100644 index 000000000..bf74e63c9 --- /dev/null +++ b/include/linux/rtc-v3020.h @@ -0,0 +1,35 @@ +/* + * v3020.h - Registers definition and platform data structure for the v3020 RTC. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2006, 8D Technologies inc. + */ +#ifndef __LINUX_V3020_H +#define __LINUX_V3020_H + +/* The v3020 has only one data pin but which one + * is used depends on the board. */ +struct v3020_platform_data { + int leftshift; /* (1<<(leftshift)) & readl() */ +}; + +#define V3020_STATUS_0 0x00 +#define V3020_STATUS_1 0x01 +#define V3020_SECONDS 0x02 +#define V3020_MINUTES 0x03 +#define V3020_HOURS 0x04 +#define V3020_MONTH_DAY 0x05 +#define V3020_MONTH 0x06 +#define V3020_YEAR 0x07 +#define V3020_WEEK_DAY 0x08 +#define V3020_WEEK 0x09 + +#define V3020_IS_COMMAND(val) ((val)>=0x0E) + +#define V3020_CMD_RAM2CLOCK 0x0E +#define V3020_CMD_CLOCK2RAM 0x0F + +#endif /* __LINUX_V3020_H */ diff --git a/include/linux/rtmutex.h b/include/linux/rtmutex.h new file mode 100644 index 000000000..5d41dee82 --- /dev/null +++ b/include/linux/rtmutex.h @@ -0,0 +1,107 @@ +/* + * RT Mutexes: blocking mutual exclusion locks with PI support + * + * started by Ingo Molnar and Thomas Gleixner: + * + * Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + * Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com> + * + * This file contains the public data structure and API definitions. + */ + +#ifndef __LINUX_RT_MUTEX_H +#define __LINUX_RT_MUTEX_H + +#include <linux/linkage.h> +#include <linux/plist.h> +#include <linux/spinlock_types.h> + +/* + * The rt_mutex structure + * + * @wait_lock: spinlock to protect the structure + * @wait_list: pilist head to enqueue waiters in priority order + * @owner: the mutex owner + */ +struct rt_mutex { + spinlock_t wait_lock; + struct plist_head wait_list; + struct task_struct *owner; +#ifdef CONFIG_DEBUG_RT_MUTEXES + int save_state; + const char *name, *file; + int line; + void *magic; +#endif +}; + +struct rt_mutex_waiter; +struct hrtimer_sleeper; + +#ifdef CONFIG_DEBUG_RT_MUTEXES + extern int rt_mutex_debug_check_no_locks_freed(const void *from, + unsigned long len); + extern void rt_mutex_debug_check_no_locks_held(struct task_struct *task); +#else + static inline int rt_mutex_debug_check_no_locks_freed(const void *from, + unsigned long len) + { + return 0; + } +# define rt_mutex_debug_check_no_locks_held(task) do { } while (0) +#endif + +#ifdef CONFIG_DEBUG_RT_MUTEXES +# define __DEBUG_RT_MUTEX_INITIALIZER(mutexname) \ + , .name = #mutexname, .file = __FILE__, .line = __LINE__ +# define rt_mutex_init(mutex) __rt_mutex_init(mutex, __FUNCTION__) + extern void rt_mutex_debug_task_free(struct task_struct *tsk); +#else +# define __DEBUG_RT_MUTEX_INITIALIZER(mutexname) +# define rt_mutex_init(mutex) __rt_mutex_init(mutex, NULL) +# define rt_mutex_debug_task_free(t) do { } while (0) +#endif + +#define __RT_MUTEX_INITIALIZER(mutexname) \ + { .wait_lock = SPIN_LOCK_UNLOCKED \ + , .wait_list = PLIST_HEAD_INIT(mutexname.wait_list, mutexname.wait_lock) \ + , .owner = NULL \ + __DEBUG_RT_MUTEX_INITIALIZER(mutexname)} + +#define DEFINE_RT_MUTEX(mutexname) \ + struct rt_mutex mutexname = __RT_MUTEX_INITIALIZER(mutexname) + +/*** + * rt_mutex_is_locked - is the mutex locked + * @lock: the mutex to be queried + * + * Returns 1 if the mutex is locked, 0 if unlocked. + */ +static inline int rt_mutex_is_locked(struct rt_mutex *lock) +{ + return lock->owner != NULL; +} + +extern void __rt_mutex_init(struct rt_mutex *lock, const char *name); +extern void rt_mutex_destroy(struct rt_mutex *lock); + +extern void rt_mutex_lock(struct rt_mutex *lock); +extern int rt_mutex_lock_interruptible(struct rt_mutex *lock, + int detect_deadlock); +extern int rt_mutex_timed_lock(struct rt_mutex *lock, + struct hrtimer_sleeper *timeout, + int detect_deadlock); + +extern int rt_mutex_trylock(struct rt_mutex *lock); + +extern void rt_mutex_unlock(struct rt_mutex *lock); + +#ifdef CONFIG_RT_MUTEXES +# define INIT_RT_MUTEXES(tsk) \ + .pi_waiters = PLIST_HEAD_INIT(tsk.pi_waiters, tsk.pi_lock), \ + INIT_RT_MUTEX_DEBUG(tsk) +#else +# define INIT_RT_MUTEXES(tsk) +#endif + +#endif diff --git a/include/linux/stacktrace.h b/include/linux/stacktrace.h new file mode 100644 index 000000000..50e2b01e5 --- /dev/null +++ b/include/linux/stacktrace.h @@ -0,0 +1,21 @@ +#ifndef __LINUX_STACKTRACE_H +#define __LINUX_STACKTRACE_H + +#ifdef CONFIG_STACKTRACE +struct stack_trace { + unsigned int nr_entries, max_entries; + unsigned long *entries; + int skip; /* input argument: How many entries to skip */ + int all_contexts; /* input argument: if true do than one stack */ +}; + +extern void save_stack_trace(struct stack_trace *trace, + struct task_struct *task); + +extern void print_stack_trace(struct stack_trace *trace, int spaces); +#else +# define save_stack_trace(trace, task) do { } while (0) +# define print_stack_trace(trace) do { } while (0) +#endif + +#endif diff --git a/include/linux/sunrpc/Kbuild b/include/linux/sunrpc/Kbuild new file mode 100644 index 000000000..fb438f158 --- /dev/null +++ b/include/linux/sunrpc/Kbuild @@ -0,0 +1 @@ +unifdef-y += debug.h diff --git a/include/linux/taskstats.h b/include/linux/taskstats.h new file mode 100644 index 000000000..f1cb6cddd --- /dev/null +++ b/include/linux/taskstats.h @@ -0,0 +1,137 @@ +/* taskstats.h - exporting per-task statistics + * + * Copyright (C) Shailabh Nagar, IBM Corp. 2006 + * (C) Balbir Singh, IBM Corp. 2006 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef _LINUX_TASKSTATS_H +#define _LINUX_TASKSTATS_H + +/* Format for per-task data returned to userland when + * - a task exits + * - listener requests stats for a task + * + * The struct is versioned. Newer versions should only add fields to + * the bottom of the struct to maintain backward compatibility. + * + * + * To add new fields + * a) bump up TASKSTATS_VERSION + * b) add comment indicating new version number at end of struct + * c) add new fields after version comment; maintain 64-bit alignment + */ + +#define TASKSTATS_VERSION 1 + +struct taskstats { + + /* Version 1 */ + __u16 version; + __u16 padding[3]; /* Userspace should not interpret the padding + * field which can be replaced by useful + * fields if struct taskstats is extended. + */ + + /* Delay accounting fields start + * + * All values, until comment "Delay accounting fields end" are + * available only if delay accounting is enabled, even though the last + * few fields are not delays + * + * xxx_count is the number of delay values recorded + * xxx_delay_total is the corresponding cumulative delay in nanoseconds + * + * xxx_delay_total wraps around to zero on overflow + * xxx_count incremented regardless of overflow + */ + + /* Delay waiting for cpu, while runnable + * count, delay_total NOT updated atomically + */ + __u64 cpu_count; + __u64 cpu_delay_total; + + /* Following four fields atomically updated using task->delays->lock */ + + /* Delay waiting for synchronous block I/O to complete + * does not account for delays in I/O submission + */ + __u64 blkio_count; + __u64 blkio_delay_total; + + /* Delay waiting for page fault I/O (swap in only) */ + __u64 swapin_count; + __u64 swapin_delay_total; + + /* cpu "wall-clock" running time + * On some architectures, value will adjust for cpu time stolen + * from the kernel in involuntary waits due to virtualization. + * Value is cumulative, in nanoseconds, without a corresponding count + * and wraps around to zero silently on overflow + */ + __u64 cpu_run_real_total; + + /* cpu "virtual" running time + * Uses time intervals seen by the kernel i.e. no adjustment + * for kernel's involuntary waits due to virtualization. + * Value is cumulative, in nanoseconds, without a corresponding count + * and wraps around to zero silently on overflow + */ + __u64 cpu_run_virtual_total; + /* Delay accounting fields end */ + /* version 1 ends here */ +}; + + +/* + * Commands sent from userspace + * Not versioned. New commands should only be inserted at the enum's end + * prior to __TASKSTATS_CMD_MAX + */ + +enum { + TASKSTATS_CMD_UNSPEC = 0, /* Reserved */ + TASKSTATS_CMD_GET, /* user->kernel request/get-response */ + TASKSTATS_CMD_NEW, /* kernel->user event */ + __TASKSTATS_CMD_MAX, +}; + +#define TASKSTATS_CMD_MAX (__TASKSTATS_CMD_MAX - 1) + +enum { + TASKSTATS_TYPE_UNSPEC = 0, /* Reserved */ + TASKSTATS_TYPE_PID, /* Process id */ + TASKSTATS_TYPE_TGID, /* Thread group id */ + TASKSTATS_TYPE_STATS, /* taskstats structure */ + TASKSTATS_TYPE_AGGR_PID, /* contains pid + stats */ + TASKSTATS_TYPE_AGGR_TGID, /* contains tgid + stats */ + __TASKSTATS_TYPE_MAX, +}; + +#define TASKSTATS_TYPE_MAX (__TASKSTATS_TYPE_MAX - 1) + +enum { + TASKSTATS_CMD_ATTR_UNSPEC = 0, + TASKSTATS_CMD_ATTR_PID, + TASKSTATS_CMD_ATTR_TGID, + TASKSTATS_CMD_ATTR_REGISTER_CPUMASK, + TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK, + __TASKSTATS_CMD_ATTR_MAX, +}; + +#define TASKSTATS_CMD_ATTR_MAX (__TASKSTATS_CMD_ATTR_MAX - 1) + +/* NETLINK_GENERIC related info */ + +#define TASKSTATS_GENL_NAME "TASKSTATS" +#define TASKSTATS_GENL_VERSION 0x1 + +#endif /* _LINUX_TASKSTATS_H */ diff --git a/include/linux/taskstats_kern.h b/include/linux/taskstats_kern.h new file mode 100644 index 000000000..16894b7ed --- /dev/null +++ b/include/linux/taskstats_kern.h @@ -0,0 +1,89 @@ +/* taskstats_kern.h - kernel header for per-task statistics interface + * + * Copyright (C) Shailabh Nagar, IBM Corp. 2006 + * (C) Balbir Singh, IBM Corp. 2006 + */ + +#ifndef _LINUX_TASKSTATS_KERN_H +#define _LINUX_TASKSTATS_KERN_H + +#include <linux/taskstats.h> +#include <linux/sched.h> +#include <net/genetlink.h> + +#ifdef CONFIG_TASKSTATS +extern kmem_cache_t *taskstats_cache; +extern struct mutex taskstats_exit_mutex; + +static inline void taskstats_exit_free(struct taskstats *tidstats) +{ + if (tidstats) + kmem_cache_free(taskstats_cache, tidstats); +} + +static inline void taskstats_tgid_init(struct signal_struct *sig) +{ + spin_lock_init(&sig->stats_lock); + sig->stats = NULL; +} + +static inline void taskstats_tgid_alloc(struct signal_struct *sig) +{ + struct taskstats *stats; + unsigned long flags; + + stats = kmem_cache_zalloc(taskstats_cache, SLAB_KERNEL); + if (!stats) + return; + + spin_lock_irqsave(&sig->stats_lock, flags); + if (!sig->stats) { + sig->stats = stats; + stats = NULL; + } + spin_unlock_irqrestore(&sig->stats_lock, flags); + + if (stats) + kmem_cache_free(taskstats_cache, stats); +} + +static inline void taskstats_tgid_free(struct signal_struct *sig) +{ + struct taskstats *stats = NULL; + unsigned long flags; + + spin_lock_irqsave(&sig->stats_lock, flags); + if (sig->stats) { + stats = sig->stats; + sig->stats = NULL; + } + spin_unlock_irqrestore(&sig->stats_lock, flags); + if (stats) + kmem_cache_free(taskstats_cache, stats); +} + +extern void taskstats_exit_alloc(struct taskstats **, unsigned int *); +extern void taskstats_exit_send(struct task_struct *, struct taskstats *, int, unsigned int); +extern void taskstats_init_early(void); +extern void taskstats_tgid_alloc(struct signal_struct *); +#else +static inline void taskstats_exit_alloc(struct taskstats **ptidstats, unsigned int *mycpu) +{} +static inline void taskstats_exit_free(struct taskstats *ptidstats) +{} +static inline void taskstats_exit_send(struct task_struct *tsk, + struct taskstats *tidstats, + int group_dead, unsigned int cpu) +{} +static inline void taskstats_tgid_init(struct signal_struct *sig) +{} +static inline void taskstats_tgid_alloc(struct signal_struct *sig) +{} +static inline void taskstats_tgid_free(struct signal_struct *sig) +{} +static inline void taskstats_init_early(void) +{} +#endif /* CONFIG_TASKSTATS */ + +#endif + diff --git a/include/linux/tc_act/Kbuild b/include/linux/tc_act/Kbuild new file mode 100644 index 000000000..78dfbac36 --- /dev/null +++ b/include/linux/tc_act/Kbuild @@ -0,0 +1,4 @@ +header-y += tc_gact.h +header-y += tc_ipt.h +header-y += tc_mirred.h +header-y += tc_pedit.h diff --git a/include/linux/tc_ematch/Kbuild b/include/linux/tc_ematch/Kbuild new file mode 100644 index 000000000..4a58a1c32 --- /dev/null +++ b/include/linux/tc_ematch/Kbuild @@ -0,0 +1,4 @@ +header-y += tc_em_cmp.h +header-y += tc_em_meta.h +header-y += tc_em_nbyte.h +header-y += tc_em_text.h diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h new file mode 100644 index 000000000..3cadfa5a6 --- /dev/null +++ b/include/linux/tracehook.h @@ -0,0 +1,707 @@ +/* + * Tracing hooks + * + * This file defines hook entry points called by core code where + * user tracing/debugging support might need to do something. + * These entry points are called tracehook_*. Each hook declared below + * has a detailed comment giving the context (locking et al) from + * which it is called, and the meaning of its return value (if any). + * + * We also declare here tracehook_* functions providing access to low-level + * interrogation and control of threads. These functions must be called + * on either the current thread or on a quiescent thread. We say a + * thread is "quiescent" if it is in TASK_STOPPED or TASK_TRACED state, + * we are guaranteed it will not be woken up and return to user mode, and + * we have called wait_task_inactive on it. + */ + +#ifndef _LINUX_TRACEHOOK_H +#define _LINUX_TRACEHOOK_H 1 + +#include <linux/sched.h> +#include <linux/uaccess.h> +struct linux_binprm; +struct pt_regs; + + +/* + * The machine-specific asm/tracehook.h file is responsible for declaring + * the following entry points. These can be called only on a quiescent thread, + * or the current thread when it is about to return to user mode. + * + * Single-step control. When enabled, the next instruction or syscall exit + * produces a SIGTRAP. Enabling or disabling redundantly is harmless. + * + * void tracehook_enable_single_step(struct task_struct *tsk); + * void tracehook_disable_single_step(struct task_struct *tsk); + * int tracehook_single_step_enabled(struct task_struct *tsk); + * + * If those calls are defined, #define ARCH_HAS_SINGLE_STEP to nonzero. + * Do not #define it if these calls are never available in this kernel config. + * If defined, the value of ARCH_HAS_SINGLE_STEP can be constant or variable. + * It should evaluate to nonzero if the hardware is able to support + * tracehook_enable_single_step. If it's a variable expression, it + * should be one that can be evaluated in modules, i.e. uses exported symbols. + * + * Block-step control (trap on control transfer), when available. + * tracehook_disable_block_step will be called after tracehook_enable_single_step. + * When enabled, the next jump, or other control transfer or syscall exit, + * produces a SIGTRAP. Enabling or disabling redundantly is harmless. + * + * void tracehook_enable_block_step(struct task_struct *tsk); + * void tracehook_disable_block_step(struct task_struct *tsk); + * int tracehook_block_step_enabled(struct task_struct *tsk); + * + * If those calls are defined, #define ARCH_HAS_BLOCK_STEP to nonzero. + * Do not #define it if these calls are never available in this kernel config. + * If defined, the value of ARCH_HAS_BLOCK_STEP can be constant or variable. + * It should evaluate to nonzero if the hardware is able to support + * tracehook_enable_block_step. If it's a variable expression, it + * should be one that can be evaluated in modules, i.e. uses exported symbols. + * + * Control system call tracing. When enabled a syscall entry or exit + * produces a call to tracehook_report_syscall, below. + * + * void tracehook_enable_syscall_trace(struct task_struct *tsk); + * void tracehook_disable_syscall_trace(struct task_struct *tsk); + * + * When stopped in tracehook_report_syscall for syscall entry, + * abort the syscall so no kernel function is called. + * If the register state was not otherwise updated before, + * this produces an -ENOSYS error return as for an invalid syscall number. + * + * void tracehook_abort_syscall(struct pt_regs *regs); + * + * Return the regset view (see below) that is native for the given process. + * For example, what it would access when it called ptrace. + * Throughout the life of the process, this only changes at exec. + * + * const struct utrace_regset_view *utrace_native_view(struct task_struct *); + * + ***/ + + +/* + * This data structure describes a machine resource we call a register set. + * This is part of the state of an individual thread, not necessarily + * actual CPU registers per se. A register set consists of a number of + * similar slots, given by ->n. Each slot is ->size bytes, and aligned to + * ->align bytes (which is at least ->size). + * + * As described above, these entry points can be called on the current + * thread or on a quiescent thread. The pos argument must be aligned + * according to ->align; the count argument must be a multiple of ->size. + * These functions are not responsible for checking for invalid arguments. + * + * When there is a natural value to use as an index, ->bias gives the + * difference between the natural index and the slot index for the + * register set. For example, x86 GDT segment descriptors form a regset; + * the segment selector produces a natural index, but only a subset of + * that index space is available as a regset (the TLS slots); subtracting + * ->bias from a segment selector index value computes the regset slot. + */ +struct utrace_regset { + unsigned int n; /* Number of slots (registers). */ + unsigned int size; /* Size in bytes of a slot (register). */ + unsigned int align; /* Required alignment, in bytes. */ + unsigned int bias; /* Bias from natural indexing. */ + + /* + * Return -ENODEV if not available on the hardware found. + * Return 0 if no interesting state in this thread. + * Return >0 number of ->size units of interesting state. + * Any get call fetching state beyond that number will + * see the default initialization state for this data, + * so a caller that knows that the default state is need + * not copy it all out. + * This call is optional; the pointer is NULL if there + * so no inexpensive check to yield a value < .n. + */ + int (*active)(struct task_struct *, const struct utrace_regset *); + + /* + * Fetch and store register values. Return 0 on success; -EIO or + * -ENODEV are usual failure returns. The pos and count values are + * in bytes, but must be properly aligned. If kbuf is non-null, + * that buffer is used and ubuf is ignored. If kbuf is NULL, then + * ubuf gives a userland pointer to access directly, and an -EFAULT + * return value is possible. + */ + int (*get)(struct task_struct *, const struct utrace_regset *, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf); + int (*set)(struct task_struct *, const struct utrace_regset *, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf); + + /* + * This call is optional; usually the pointer is NULL. + * When provided, there is some user memory associated + * with this regset's hardware, such as memory backing + * cached register data on register window machines; the + * regset's data controls what user memory is used + * (e.g. via the stack pointer value). + * + * Write register data back to user memory. If the + * immediate flag is nonzero, it must be written to the + * user memory so uaccess/access_process_vm can see it + * when this call returns; if zero, then it must be + * written back by the time the task completes a context + * switch (as synchronized with wait_task_inactive). + * Return 0 on success or if there was nothing to do, + * -EFAULT for a memory problem (bad stack pointer or + * whatever), or -EIO for a hardware problem. + */ + int (*writeback)(struct task_struct *, const struct utrace_regset *, + int immediate); +}; + +/* + * A regset view is a collection of regsets (struct utrace_regset, above). + * This describes all the state of a thread that can be seen from a given + * architecture/ABI environment. More than one view might refer to the + * same utrace_regset, or more than one regset might refer to the same + * machine-specific state in the thread. For example, a 32-bit thread's + * state could be examined from the 32-bit view or from the 64-bit view. + * Either method reaches the same thread register state, doing appropriate + * widening or truncation. + */ +struct utrace_regset_view { + const char *name; /* Identifier, e.g. ELF_PLATFORM string. */ + + const struct utrace_regset *regsets; + unsigned int n; + + /* + * EM_* value for which this is the native view, if any. + */ + u16 e_machine; +}; + + +/* + * These two are helpers for writing regset get/set functions in arch code. + * Use one or more calls sequentially for each chunk of regset data stored + * contiguously in memory. Call with constants for start_pos and end_pos, + * giving the range of byte positions in the regset that data corresponds + * to; end_pos can be -1 if this chunk is at the end of the regset layout. + * Each call updates the arguments to point past its chunk. + */ + +static inline int +utrace_regset_copyout(unsigned int *pos, unsigned int *count, + void **kbuf, void __user **ubuf, + const void *data, int start_pos, int end_pos) +{ + if (*count == 0) + return 0; + BUG_ON(*pos < start_pos); + if (end_pos < 0 || *pos < end_pos) { + unsigned int copy = (end_pos < 0 ? *count + : min(*count, end_pos - *pos)); + data += *pos - start_pos; + if (*kbuf) { + memcpy(*kbuf, data, copy); + *kbuf += copy; + } + else if (copy_to_user(*ubuf, data, copy)) + return -EFAULT; + else + *ubuf += copy; + *pos += copy; + *count -= copy; + } + return 0; +} + +static inline int +utrace_regset_copyin(unsigned int *pos, unsigned int *count, + const void **kbuf, const void __user **ubuf, + void *data, int start_pos, int end_pos) +{ + if (*count == 0) + return 0; + BUG_ON(*pos < start_pos); + if (end_pos < 0 || *pos < end_pos) { + unsigned int copy = (end_pos < 0 ? *count + : min(*count, end_pos - *pos)); + data += *pos - start_pos; + if (*kbuf) { + memcpy(data, *kbuf, copy); + *kbuf += copy; + } + else if (copy_from_user(data, *ubuf, copy)) + return -EFAULT; + else + *ubuf += copy; + *pos += copy; + *count -= copy; + } + return 0; +} + +/* + * These two parallel the two above, but for portions of a regset layout + * that always read as all-zero or for which writes are ignored. + */ +static inline int +utrace_regset_copyout_zero(unsigned int *pos, unsigned int *count, + void **kbuf, void __user **ubuf, + int start_pos, int end_pos) +{ + if (*count == 0) + return 0; + BUG_ON(*pos < start_pos); + if (end_pos < 0 || *pos < end_pos) { + unsigned int copy = (end_pos < 0 ? *count + : min(*count, end_pos - *pos)); + if (*kbuf) { + memset(*kbuf, 0, copy); + *kbuf += copy; + } + else if (clear_user(*ubuf, copy)) + return -EFAULT; + else + *ubuf += copy; + *pos += copy; + *count -= copy; + } + return 0; +} + +static inline int +utrace_regset_copyin_ignore(unsigned int *pos, unsigned int *count, + const void **kbuf, const void __user **ubuf, + int start_pos, int end_pos) +{ + if (*count == 0) + return 0; + BUG_ON(*pos < start_pos); + if (end_pos < 0 || *pos < end_pos) { + unsigned int copy = (end_pos < 0 ? *count + : min(*count, end_pos - *pos)); + if (*kbuf) + *kbuf += copy; + else + *ubuf += copy; + *pos += copy; + *count -= copy; + } + return 0; +} + +/**/ + + +/*** + *** + *** Following are entry points from core code, where the user debugging + *** support can affect the normal behavior. The locking situation is + *** described for each call. + *** + ***/ + +#ifdef CONFIG_UTRACE +#include <linux/utrace.h> +#endif + + +/* + * Called in copy_process when setting up the copied task_struct, + * with tasklist_lock held for writing. + */ +static inline void tracehook_init_task(struct task_struct *child) +{ +#ifdef CONFIG_UTRACE + child->utrace_flags = 0; + child->utrace = NULL; +#endif +} + +/* + * Called from release_task, no locks held. + * After this, there should be no tracing entanglements. + */ +static inline void tracehook_release_task(struct task_struct *p) +{ +#ifdef CONFIG_UTRACE + smp_mb(); + if (p->utrace != NULL) + utrace_release_task(p); +#endif +} + +/* + * Return nonzero to trigger a BUG_ON crash in release_task. + * This should verify that there is no tracing-related state + * still affecting the task_struct about to be released. + * Called with tasklist_lock held for writing. + */ +static inline int tracehook_check_released(struct task_struct *p) +{ +#ifdef CONFIG_UTRACE + return unlikely(p->utrace != NULL); +#endif + return 0; +} + +/* + * do_notify_parent_cldstop calls this when it's about to generate a SIGCHLD + * for a job control stop. Return nonzero to prevent that signal generation. + * Called with tasklist_lock held for reading, sometimes with irqs disabled. + */ +static inline int tracehook_notify_cldstop(struct task_struct *tsk, + const siginfo_t *info) +{ +#ifdef CONFIG_UTRACE + if (tsk->utrace_flags & UTRACE_ACTION_NOREAP) + return 1; +#endif + return 0; +} + +/* + * exit_notify calls this with tasklist_lock held for writing. + * Return nonzero to prevent any normal SIGCHLD generation for this + * thread's death (i.e. when it is not ignored and its thread group is + * empty). This call must set *noreap to 0, or to 1 to force this thread + * to become a zombie when it would normally reap itself. + * The *death_cookie is passed to tracehook_report_death (below). + */ +static inline int tracehook_notify_death(struct task_struct *tsk, + int *noreap, void **death_cookie) +{ + *death_cookie = NULL; +#ifdef CONFIG_UTRACE + *death_cookie = tsk->utrace; + if (tsk->utrace_flags & UTRACE_ACTION_NOREAP) { + *noreap = 1; + return 1; + } +#endif + *noreap = 0; + return 0; +} + +/* + * Return zero iff tracing doesn't care to examine this fatal signal, + * so it can short-circuit normal delivery directly to a group exit. + * Called with tsk->sighand->siglock held. + */ +static inline int tracehook_consider_fatal_signal(struct task_struct *tsk, + int sig) +{ +#ifdef CONFIG_UTRACE + return (tsk->utrace_flags & (UTRACE_EVENT(SIGNAL_TERM) + | UTRACE_EVENT(SIGNAL_CORE))); +#endif + return 0; +} + +/* + * Return zero iff tracing doesn't care to examine this ignored signal, + * so it can short-circuit normal delivery and never even get queued. + * Either the handler is SIG_DFL and sig's default is ignore, or it's SIG_IGN. + * Called with tsk->sighand->siglock held. + */ +static inline int tracehook_consider_ignored_signal(struct task_struct *tsk, + int sig, void *handler) +{ +#ifdef CONFIG_UTRACE + return (tsk->utrace_flags & UTRACE_EVENT(SIGNAL_IGN)); +#endif + return 0; +} + + +/* + * Called with the siglock held when computing tsk's signal_pending flag. + * Return nonzero to force the signal_pending flag on, so that + * tracehook_induce_signal will be called before the next return to user mode. + */ +static inline int tracehook_induce_sigpending(struct task_struct *tsk) +{ +#ifdef CONFIG_UTRACE + return unlikely(tsk->utrace_flags & UTRACE_ACTION_QUIESCE); +#endif + return 0; +} + +/* + * Called with the siglock held before dequeuing pending signals. + * Return zero to check for a real pending signal normally. + * Return -1 after releasing the siglock to repeat the check. + * Return a signal number to induce an artifical signal delivery, + * setting *info and *return_ka to specify its details and behavior. + */ +static inline int tracehook_get_signal(struct task_struct *tsk, + struct pt_regs *regs, + siginfo_t *info, + struct k_sigaction *return_ka) +{ +#ifdef CONFIG_UTRACE + if (unlikely(tsk->utrace_flags)) + return utrace_get_signal(tsk, regs, info, return_ka); +#endif + return 0; +} + +/* + * Called with no locks held when about to stop for job control; + * we are already in TASK_STOPPED state, about to call schedule. + * Return zero if the normal SIGCHLD should be generated, which + * will happen if last_one is true meaning this is the last thread + * in the thread group to stop. + */ +static inline int tracehook_finish_stop(int last_one) +{ +#ifdef CONFIG_UTRACE + if (current->utrace_flags & UTRACE_EVENT(JCTL)) + return utrace_report_jctl(CLD_STOPPED); +#endif + + return 0; +} + +/* + * Called with tasklist_lock held for reading, for an event notification stop. + * We are already in TASK_TRACED. Return zero to go back to running, + * or nonzero to actually stop until resumed. + */ +static inline int tracehook_stop_now(void) +{ + return 0; +} + + +/* + * Return nonzero if the child's parent (current) should be prevented + * from seeing its child in TASK_STOPPED state when it waits with WSTOPPED. + * Called with tasklist_lock held for reading. + */ +static inline int tracehook_inhibit_wait_stopped(struct task_struct *child) +{ +#ifdef CONFIG_UTRACE + return (child->utrace_flags & UTRACE_ACTION_NOREAP); +#endif + return 0; +} + +/* + * Return nonzero if the child's parent (current) should be prevented + * from seeing its child in TASK_ZOMBIE state when it waits with WEXITED. + * Called with tasklist_lock held for reading. + */ +static inline int tracehook_inhibit_wait_zombie(struct task_struct *child) +{ +#ifdef CONFIG_UTRACE + return (child->utrace_flags & UTRACE_ACTION_NOREAP); +#endif + return 0; +} + +/* + * Return nonzero if the child's parent (current) should be prevented + * from seeing its child resuming after job stop when it waits with WCONTINUED. + * Called with tasklist_lock held for reading. + */ +static inline int tracehook_inhibit_wait_continued(struct task_struct *child) +{ +#ifdef CONFIG_UTRACE + return (child->utrace_flags & UTRACE_ACTION_NOREAP); +#endif + return 0; +} + + +/* + * Return LSM_UNSAFE_* bits applied to an exec because of tracing. + * Called with task_lock(tsk) held. + */ +static inline int tracehook_unsafe_exec(struct task_struct *tsk) +{ +#ifdef CONFIG_UTRACE + if (tsk->utrace_flags) + return utrace_unsafe_exec(tsk); +#endif + return 0; +} + +/* + * Return the task_struct for the task using ptrace on this one, or NULL. + * Must be called with rcu_read_lock held to keep the returned struct alive. + * + * At exec time, this may be called with task_lock(p) still held from when + * tracehook_unsafe_exec was just called. + * + * The value is also used to display after "TracerPid:" in /proc/PID/status, + * where it is called with only rcu_read_lock held. + */ +static inline struct task_struct *tracehook_tracer_task(struct task_struct *p) +{ +#ifdef CONFIG_UTRACE + if (p->utrace_flags) + return utrace_tracer_task(p); +#endif + return NULL; +} + +/* + * Return nonzero if the current task should be allowed to use + * access_process_vm on the given task. + */ +static inline int tracehook_allow_access_process_vm(struct task_struct *tsk) +{ + if (tsk == current) + return 1; +#ifdef CONFIG_UTRACE + if (tsk->utrace_flags) + return utrace_allow_access_process_vm(tsk); +#endif + return 0; +} + + +/*** + *** + *** Following decelarations are hook stubs where core code reports + *** events. These are called without locks, from the thread having the + *** event. In all tracehook_report_* calls, no locks are held and the thread + *** is in a state close to returning to user mode with little baggage to + *** unwind, except as noted below for tracehook_report_clone. It is generally + *** OK to block in these places if you want the user thread to be suspended. + *** + ***/ + +/* + * Thread has just become a zombie (exit_state==TASK_ZOMBIE) or is about to + * self-reap (exit_state==EXIT_DEAD). If normal reaping is not inhibited, + * tsk->exit_state might be changing in parallel. The death_cookie was + * passed back by tracehook_notify_death (above). + */ +static inline void tracehook_report_death(struct task_struct *tsk, + int exit_state, void *death_cookie) +{ +#ifdef CONFIG_UTRACE + smp_mb(); + if (tsk->utrace_flags & (UTRACE_EVENT(DEATH) | UTRACE_ACTION_QUIESCE)) + utrace_report_death(tsk, death_cookie); +#endif +} + +/* + * exec completed, we are shortly going to return to user mode. + * The freshly initialized register state can be seen and changed here. + */ +static inline void tracehook_report_exec(struct linux_binprm *bprm, + struct pt_regs *regs) +{ +#ifdef CONFIG_UTRACE + if (current->utrace_flags & UTRACE_EVENT(EXEC)) + utrace_report_exec(bprm, regs); +#endif +} + +/* + * Called from do_exit, we are about to exit. The code returned to the + * parent for wait can be changed here. + */ +static inline void tracehook_report_exit(long *exit_code) +{ +#ifdef CONFIG_UTRACE + if (current->utrace_flags & UTRACE_EVENT(EXIT)) + utrace_report_exit(exit_code); +#endif +} + +/* + * Called after a child is set up, but before it has been started or + * been given its CLONE_STOPPED initial stop. (See also tracehook_init_task.) + * This is not a good place to block, because the child has not started yet. + * Suspend the child here if desired, and block in clone_complete (below). + * This must prevent the child from self-reaping if clone_complete uses + * the task_struct pointer; otherwise it might have died and been released + * by the time tracehook_report_clone_complete is called. + */ +static inline void tracehook_report_clone(unsigned long clone_flags, + struct task_struct *child) +{ +#ifdef CONFIG_UTRACE + if (current->utrace_flags & UTRACE_EVENT(CLONE)) + utrace_report_clone(clone_flags, child); +#endif +} + +/* + * Called after the child has started running, shortly after + * tracehook_report_clone. This is just before the clone/fork syscall + * returns, or blocks for vfork child completion if (clone_flags & + * CLONE_VFORK). The child pointer may be invalid if a self-reaping + * child died and tracehook_report_clone took no action to prevent it + * from self-reaping. + */ +static inline void tracehook_report_clone_complete(unsigned long clone_flags, + pid_t pid, + struct task_struct *child) +{ +#ifdef CONFIG_UTRACE + if (current->utrace_flags & UTRACE_ACTION_QUIESCE) + utrace_quiescent(current); +#endif +} + +/* + * Called after a CLONE_VFORK parent has waited for the child to complete. + * The clone/vfork system call will return immediately after this. + * The child pointer may be invalid if a self-reaping child died and + * tracehook_report_clone took no action to prevent it from self-reaping. + */ +static inline void tracehook_report_vfork_done(struct task_struct *child, + pid_t child_pid) +{ +#ifdef CONFIG_UTRACE + if (current->utrace_flags & UTRACE_EVENT(VFORK_DONE)) + utrace_report_vfork_done(child_pid); +#endif +} + +/* + * Called for system call entry or exit. + */ +static inline void tracehook_report_syscall(struct pt_regs *regs, int is_exit) +{ +#ifdef CONFIG_UTRACE + if (current->utrace_flags & (is_exit ? UTRACE_EVENT(SYSCALL_EXIT) + : UTRACE_EVENT(SYSCALL_ENTRY))) + utrace_report_syscall(regs, is_exit); +#endif +} + +/* + * Called after system call exit if single/block-stepped into the syscall. + */ +static inline void tracehook_report_syscall_step(struct pt_regs *regs) +{ +} + +/* + * Called when a signal handler has been set up. + * Register and stack state reflects the user handler about to run. + * Signal mask changes have already been made. + */ +static inline void tracehook_report_handle_signal(int sig, + const struct k_sigaction *ka, + const sigset_t *oldset, + struct pt_regs *regs) +{ +#ifdef CONFIG_UTRACE + struct task_struct *tsk = current; + if ((tsk->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) + && (tsk->utrace_flags & (UTRACE_ACTION_SINGLESTEP + | UTRACE_ACTION_BLOCKSTEP))) + utrace_signal_handler_singlestep(tsk, regs); +#endif +} + + +#endif /* <linux/tracehook.h> */ diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h new file mode 100644 index 000000000..391e7ed1e --- /dev/null +++ b/include/linux/uaccess.h @@ -0,0 +1,22 @@ +#ifndef __LINUX_UACCESS_H__ +#define __LINUX_UACCESS_H__ + +#include <asm/uaccess.h> + +#ifndef ARCH_HAS_NOCACHE_UACCESS + +static inline unsigned long __copy_from_user_inatomic_nocache(void *to, + const void __user *from, unsigned long n) +{ + return __copy_from_user_inatomic(to, from, n); +} + +static inline unsigned long __copy_from_user_nocache(void *to, + const void __user *from, unsigned long n) +{ + return __copy_from_user(to, from, n); +} + +#endif /* ARCH_HAS_NOCACHE_UACCESS */ + +#endif /* __LINUX_UACCESS_H__ */ diff --git a/include/linux/unwind.h b/include/linux/unwind.h new file mode 100644 index 000000000..73e1751d0 --- /dev/null +++ b/include/linux/unwind.h @@ -0,0 +1,125 @@ +#ifndef _LINUX_UNWIND_H +#define _LINUX_UNWIND_H + +/* + * Copyright (C) 2002-2006 Novell, Inc. + * Jan Beulich <jbeulich@novell.com> + * This code is released under version 2 of the GNU GPL. + * + * A simple API for unwinding kernel stacks. This is used for + * debugging and error reporting purposes. The kernel doesn't need + * full-blown stack unwinding with all the bells and whistles, so there + * is not much point in implementing the full Dwarf2 unwind API. + */ + +struct module; + +#ifdef CONFIG_STACK_UNWIND + +#include <asm/unwind.h> + +#ifndef ARCH_UNWIND_SECTION_NAME +#define ARCH_UNWIND_SECTION_NAME ".eh_frame" +#endif + +/* + * Initialize unwind support. + */ +extern void unwind_init(void); + +#ifdef CONFIG_MODULES + +extern void *unwind_add_table(struct module *, + const void *table_start, + unsigned long table_size); + +extern void unwind_remove_table(void *handle, int init_only); + +#endif + +extern int unwind_init_frame_info(struct unwind_frame_info *, + struct task_struct *, + /*const*/ struct pt_regs *); + +/* + * Prepare to unwind a blocked task. + */ +extern int unwind_init_blocked(struct unwind_frame_info *, + struct task_struct *); + +/* + * Prepare to unwind the currently running thread. + */ +extern int unwind_init_running(struct unwind_frame_info *, + asmlinkage int (*callback)(struct unwind_frame_info *, + void *arg), + void *arg); + +/* + * Unwind to previous to frame. Returns 0 if successful, negative + * number in case of an error. + */ +extern int unwind(struct unwind_frame_info *); + +/* + * Unwind until the return pointer is in user-land (or until an error + * occurs). Returns 0 if successful, negative number in case of + * error. + */ +extern int unwind_to_user(struct unwind_frame_info *); + +#else + +struct unwind_frame_info {}; + +static inline void unwind_init(void) {} + +#ifdef CONFIG_MODULES + +static inline void *unwind_add_table(struct module *mod, + const void *table_start, + unsigned long table_size) +{ + return NULL; +} + +#endif + +static inline void unwind_remove_table(void *handle, int init_only) +{ +} + +static inline int unwind_init_frame_info(struct unwind_frame_info *info, + struct task_struct *tsk, + const struct pt_regs *regs) +{ + return -ENOSYS; +} + +static inline int unwind_init_blocked(struct unwind_frame_info *info, + struct task_struct *tsk) +{ + return -ENOSYS; +} + +static inline int unwind_init_running(struct unwind_frame_info *info, + asmlinkage int (*cb)(struct unwind_frame_info *, + void *arg), + void *arg) +{ + return -ENOSYS; +} + +static inline int unwind(struct unwind_frame_info *info) +{ + return -ENOSYS; +} + +static inline int unwind_to_user(struct unwind_frame_info *info) +{ + return -ENOSYS; +} + +#endif + +#endif /* _LINUX_UNWIND_H */ diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h new file mode 100644 index 000000000..ba617c372 --- /dev/null +++ b/include/linux/usb/cdc.h @@ -0,0 +1,205 @@ +/* + * USB Communications Device Class (CDC) definitions + * + * CDC says how to talk to lots of different types of network adapters, + * notably ethernet adapters and various modems. It's used mostly with + * firmware based USB peripherals. + */ + +#define USB_CDC_SUBCLASS_ACM 0x02 +#define USB_CDC_SUBCLASS_ETHERNET 0x06 +#define USB_CDC_SUBCLASS_WHCM 0x08 +#define USB_CDC_SUBCLASS_DMM 0x09 +#define USB_CDC_SUBCLASS_MDLM 0x0a +#define USB_CDC_SUBCLASS_OBEX 0x0b + +#define USB_CDC_PROTO_NONE 0 + +#define USB_CDC_ACM_PROTO_AT_V25TER 1 +#define USB_CDC_ACM_PROTO_AT_PCCA101 2 +#define USB_CDC_ACM_PROTO_AT_PCCA101_WAKE 3 +#define USB_CDC_ACM_PROTO_AT_GSM 4 +#define USB_CDC_ACM_PROTO_AT_3G 5 +#define USB_CDC_ACM_PROTO_AT_CDMA 6 +#define USB_CDC_ACM_PROTO_VENDOR 0xff + +/*-------------------------------------------------------------------------*/ + +/* + * Class-Specific descriptors ... there are a couple dozen of them + */ + +#define USB_CDC_HEADER_TYPE 0x00 /* header_desc */ +#define USB_CDC_CALL_MANAGEMENT_TYPE 0x01 /* call_mgmt_descriptor */ +#define USB_CDC_ACM_TYPE 0x02 /* acm_descriptor */ +#define USB_CDC_UNION_TYPE 0x06 /* union_desc */ +#define USB_CDC_COUNTRY_TYPE 0x07 +#define USB_CDC_NETWORK_TERMINAL_TYPE 0x0a /* network_terminal_desc */ +#define USB_CDC_ETHERNET_TYPE 0x0f /* ether_desc */ +#define USB_CDC_WHCM_TYPE 0x11 +#define USB_CDC_MDLM_TYPE 0x12 /* mdlm_desc */ +#define USB_CDC_MDLM_DETAIL_TYPE 0x13 /* mdlm_detail_desc */ +#define USB_CDC_DMM_TYPE 0x14 +#define USB_CDC_OBEX_TYPE 0x15 + +/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */ +struct usb_cdc_header_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __le16 bcdCDC; +} __attribute__ ((packed)); + +/* "Call Management Descriptor" from CDC spec 5.2.3.2 */ +struct usb_cdc_call_mgmt_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 bmCapabilities; +#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT 0x01 +#define USB_CDC_CALL_MGMT_CAP_DATA_INTF 0x02 + + __u8 bDataInterface; +} __attribute__ ((packed)); + +/* "Abstract Control Management Descriptor" from CDC spec 5.2.3.3 */ +struct usb_cdc_acm_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 bmCapabilities; +} __attribute__ ((packed)); + +/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */ +struct usb_cdc_union_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 bMasterInterface0; + __u8 bSlaveInterface0; + /* ... and there could be other slave interfaces */ +} __attribute__ ((packed)); + +/* "Network Channel Terminal Functional Descriptor" from CDC spec 5.2.3.11 */ +struct usb_cdc_network_terminal_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 bEntityId; + __u8 iName; + __u8 bChannelIndex; + __u8 bPhysicalInterface; +} __attribute__ ((packed)); + +/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */ +struct usb_cdc_ether_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 iMACAddress; + __le32 bmEthernetStatistics; + __le16 wMaxSegmentSize; + __le16 wNumberMCFilters; + __u8 bNumberPowerFilters; +} __attribute__ ((packed)); + +/* "MDLM Functional Descriptor" from CDC WMC spec 6.7.2.3 */ +struct usb_cdc_mdlm_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __le16 bcdVersion; + __u8 bGUID[16]; +} __attribute__ ((packed)); + +/* "MDLM Detail Functional Descriptor" from CDC WMC spec 6.7.2.4 */ +struct usb_cdc_mdlm_detail_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + /* type is associated with mdlm_desc.bGUID */ + __u8 bGuidDescriptorType; + __u8 bDetailData[0]; +} __attribute__ ((packed)); + +/*-------------------------------------------------------------------------*/ + +/* + * Class-Specific Control Requests (6.2) + * + * section 3.6.2.1 table 4 has the ACM profile, for modems. + * section 3.8.2 table 10 has the ethernet profile. + * + * Microsoft's RNDIS stack for Ethernet is a vendor-specific CDC ACM variant, + * heavily dependent on the encapsulated (proprietary) command mechanism. + */ + +#define USB_CDC_SEND_ENCAPSULATED_COMMAND 0x00 +#define USB_CDC_GET_ENCAPSULATED_RESPONSE 0x01 +#define USB_CDC_REQ_SET_LINE_CODING 0x20 +#define USB_CDC_REQ_GET_LINE_CODING 0x21 +#define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22 +#define USB_CDC_REQ_SEND_BREAK 0x23 +#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40 +#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER 0x41 +#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER 0x42 +#define USB_CDC_SET_ETHERNET_PACKET_FILTER 0x43 +#define USB_CDC_GET_ETHERNET_STATISTIC 0x44 + +/* Line Coding Structure from CDC spec 6.2.13 */ +struct usb_cdc_line_coding { + __le32 dwDTERate; + __u8 bCharFormat; +#define USB_CDC_1_STOP_BITS 0 +#define USB_CDC_1_5_STOP_BITS 1 +#define USB_CDC_2_STOP_BITS 2 + + __u8 bParityType; +#define USB_CDC_NO_PARITY 0 +#define USB_CDC_ODD_PARITY 1 +#define USB_CDC_EVEN_PARITY 2 +#define USB_CDC_MARK_PARITY 3 +#define USB_CDC_SPACE_PARITY 4 + + __u8 bDataBits; +} __attribute__ ((packed)); + +/* table 62; bits in multicast filter */ +#define USB_CDC_PACKET_TYPE_PROMISCUOUS (1 << 0) +#define USB_CDC_PACKET_TYPE_ALL_MULTICAST (1 << 1) /* no filter */ +#define USB_CDC_PACKET_TYPE_DIRECTED (1 << 2) +#define USB_CDC_PACKET_TYPE_BROADCAST (1 << 3) +#define USB_CDC_PACKET_TYPE_MULTICAST (1 << 4) /* filtered */ + + +/*-------------------------------------------------------------------------*/ + +/* + * Class-Specific Notifications (6.3) sent by interrupt transfers + * + * section 3.8.2 table 11 of the CDC spec lists Ethernet notifications + * section 3.6.2.1 table 5 specifies ACM notifications, accepted by RNDIS + * RNDIS also defines its own bit-incompatible notifications + */ + +#define USB_CDC_NOTIFY_NETWORK_CONNECTION 0x00 +#define USB_CDC_NOTIFY_RESPONSE_AVAILABLE 0x01 +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20 +#define USB_CDC_NOTIFY_SPEED_CHANGE 0x2a + +struct usb_cdc_notification { + __u8 bmRequestType; + __u8 bNotificationType; + __le16 wValue; + __le16 wIndex; + __le16 wLength; +} __attribute__ ((packed)); + diff --git a/include/linux/usb/input.h b/include/linux/usb/input.h new file mode 100644 index 000000000..716e0cc16 --- /dev/null +++ b/include/linux/usb/input.h @@ -0,0 +1,25 @@ +#ifndef __USB_INPUT_H +#define __USB_INPUT_H + +/* + * Copyright (C) 2005 Dmitry Torokhov + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include <linux/usb.h> +#include <linux/input.h> +#include <asm/byteorder.h> + +static inline void +usb_to_input_id(const struct usb_device *dev, struct input_id *id) +{ + id->bustype = BUS_USB; + id->vendor = le16_to_cpu(dev->descriptor.idVendor); + id->product = le16_to_cpu(dev->descriptor.idProduct); + id->version = le16_to_cpu(dev->descriptor.bcdDevice); +} + +#endif diff --git a/include/linux/usb/isp116x.h b/include/linux/usb/isp116x.h new file mode 100644 index 000000000..436dd8a2b --- /dev/null +++ b/include/linux/usb/isp116x.h @@ -0,0 +1,29 @@ + +/* + * Board initialization code should put one of these into dev->platform_data + * and place the isp116x onto platform_bus. + */ + +struct isp116x_platform_data { + /* Enable internal resistors on downstream ports */ + unsigned sel15Kres:1; + /* On-chip overcurrent detection */ + unsigned oc_enable:1; + /* INT output polarity */ + unsigned int_act_high:1; + /* INT edge or level triggered */ + unsigned int_edge_triggered:1; + /* Enable wakeup by devices on usb bus (e.g. wakeup + by attachment/detachment or by device activity + such as moving a mouse). When chosen, this option + prevents stopping internal clock, increasing + thereby power consumption in suspended state. */ + unsigned remote_wakeup_enable:1; + /* Inter-io delay (ns). The chip is picky about access timings; it + expects at least: + 150ns delay between consecutive accesses to DATA_REG, + 300ns delay between access to ADDR_REG and DATA_REG + OE, WE MUST NOT be changed during these intervals + */ + void (*delay) (struct device * dev, int delay); +}; diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h new file mode 100644 index 000000000..91c983eef --- /dev/null +++ b/include/linux/usb/serial.h @@ -0,0 +1,300 @@ +/* + * USB Serial Converter stuff + * + * Copyright (C) 1999 - 2005 + * Greg Kroah-Hartman (greg@kroah.com) + * + * 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; version 2 of the License. + * + */ + + +#ifndef __LINUX_USB_SERIAL_H +#define __LINUX_USB_SERIAL_H + +#include <linux/kref.h> +#include <linux/mutex.h> + +#define SERIAL_TTY_MAJOR 188 /* Nice legal number now */ +#define SERIAL_TTY_MINORS 255 /* loads of devices :) */ + +#define MAX_NUM_PORTS 8 /* The maximum number of ports one device can grab at once */ + +/* parity check flag */ +#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) + +/** + * usb_serial_port: structure for the specific ports of a device. + * @serial: pointer back to the struct usb_serial owner of this port. + * @tty: pointer to the corresponding tty for this port. + * @lock: spinlock to grab when updating portions of this structure. + * @mutex: mutex used to synchronize serial_open() and serial_close() + * access for this port. + * @number: the number of the port (the minor number). + * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. + * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. + * @interrupt_in_endpointAddress: endpoint address for the interrupt in pipe + * for this port. + * @interrupt_out_buffer: pointer to the interrupt out buffer for this port. + * @interrupt_out_size: the size of the interrupt_out_buffer, in bytes. + * @interrupt_out_urb: pointer to the interrupt out struct urb for this port. + * @interrupt_out_endpointAddress: endpoint address for the interrupt out pipe + * for this port. + * @bulk_in_buffer: pointer to the bulk in buffer for this port. + * @read_urb: pointer to the bulk in struct urb for this port. + * @bulk_in_endpointAddress: endpoint address for the bulk in pipe for this + * port. + * @bulk_out_buffer: pointer to the bulk out buffer for this port. + * @bulk_out_size: the size of the bulk_out_buffer, in bytes. + * @write_urb: pointer to the bulk out struct urb for this port. + * @bulk_out_endpointAddress: endpoint address for the bulk out pipe for this + * port. + * @write_wait: a wait_queue_head_t used by the port. + * @work: work queue entry for the line discipline waking up. + * @open_count: number of times this port has been opened. + * + * This structure is used by the usb-serial core and drivers for the specific + * ports of a device. + */ +struct usb_serial_port { + struct usb_serial * serial; + struct tty_struct * tty; + spinlock_t lock; + struct mutex mutex; + unsigned char number; + + unsigned char * interrupt_in_buffer; + struct urb * interrupt_in_urb; + __u8 interrupt_in_endpointAddress; + + unsigned char * interrupt_out_buffer; + int interrupt_out_size; + struct urb * interrupt_out_urb; + __u8 interrupt_out_endpointAddress; + + unsigned char * bulk_in_buffer; + int bulk_in_size; + struct urb * read_urb; + __u8 bulk_in_endpointAddress; + + unsigned char * bulk_out_buffer; + int bulk_out_size; + struct urb * write_urb; + int write_urb_busy; + __u8 bulk_out_endpointAddress; + + wait_queue_head_t write_wait; + struct work_struct work; + int open_count; + struct device dev; +}; +#define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev) + +/* get and set the port private data pointer helper functions */ +static inline void *usb_get_serial_port_data (struct usb_serial_port *port) +{ + return dev_get_drvdata(&port->dev); +} + +static inline void usb_set_serial_port_data (struct usb_serial_port *port, void *data) +{ + dev_set_drvdata(&port->dev, data); +} + +/** + * usb_serial - structure used by the usb-serial core for a device + * @dev: pointer to the struct usb_device for this device + * @type: pointer to the struct usb_serial_driver for this device + * @interface: pointer to the struct usb_interface for this device + * @minor: the starting minor number for this device + * @num_ports: the number of ports this device has + * @num_interrupt_in: number of interrupt in endpoints we have + * @num_interrupt_out: number of interrupt out endpoints we have + * @num_bulk_in: number of bulk in endpoints we have + * @num_bulk_out: number of bulk out endpoints we have + * @port: array of struct usb_serial_port structures for the different ports. + * @private: place to put any driver specific information that is needed. The + * usb-serial driver is required to manage this data, the usb-serial core + * will not touch this. Use usb_get_serial_data() and + * usb_set_serial_data() to access this. + */ +struct usb_serial { + struct usb_device * dev; + struct usb_serial_driver * type; + struct usb_interface * interface; + unsigned char minor; + unsigned char num_ports; + unsigned char num_port_pointers; + char num_interrupt_in; + char num_interrupt_out; + char num_bulk_in; + char num_bulk_out; + struct usb_serial_port * port[MAX_NUM_PORTS]; + struct kref kref; + void * private; +}; +#define to_usb_serial(d) container_of(d, struct usb_serial, kref) + +#define NUM_DONT_CARE (-1) + +/* get and set the serial private data pointer helper functions */ +static inline void *usb_get_serial_data (struct usb_serial *serial) +{ + return serial->private; +} + +static inline void usb_set_serial_data (struct usb_serial *serial, void *data) +{ + serial->private = data; +} + +/** + * usb_serial_driver - describes a usb serial driver + * @description: pointer to a string that describes this driver. This string used + * in the syslog messages when a device is inserted or removed. + * @id_table: pointer to a list of usb_device_id structures that define all + * of the devices this structure can support. + * @num_interrupt_in: the number of interrupt in endpoints this device will + * have. + * @num_interrupt_out: the number of interrupt out endpoints this device will + * have. + * @num_bulk_in: the number of bulk in endpoints this device will have. + * @num_bulk_out: the number of bulk out endpoints this device will have. + * @num_ports: the number of different ports this device will have. + * @calc_num_ports: pointer to a function to determine how many ports this + * device has dynamically. It will be called after the probe() + * callback is called, but before attach() + * @probe: pointer to the driver's probe function. + * This will be called when the device is inserted into the system, + * but before the device has been fully initialized by the usb_serial + * subsystem. Use this function to download any firmware to the device, + * or any other early initialization that might be needed. + * Return 0 to continue on with the initialization sequence. Anything + * else will abort it. + * @attach: pointer to the driver's attach function. + * This will be called when the struct usb_serial structure is fully set + * set up. Do any local initialization of the device, or any private + * memory structure allocation at this point in time. + * @shutdown: pointer to the driver's shutdown function. This will be + * called when the device is removed from the system. + * + * This structure is defines a USB Serial driver. It provides all of + * the information that the USB serial core code needs. If the function + * pointers are defined, then the USB serial core code will call them when + * the corresponding tty port functions are called. If they are not + * called, the generic serial function will be used instead. + * + * The driver.owner field should be set to the module owner of this driver. + * The driver.name field should be set to the name of this driver (remember + * it will show up in sysfs, so it needs to be short and to the point. + * Useing the module name is a good idea.) + */ +struct usb_serial_driver { + const char *description; + const struct usb_device_id *id_table; + char num_interrupt_in; + char num_interrupt_out; + char num_bulk_in; + char num_bulk_out; + char num_ports; + + struct list_head driver_list; + struct device_driver driver; + + int (*probe) (struct usb_serial *serial, const struct usb_device_id *id); + int (*attach) (struct usb_serial *serial); + int (*calc_num_ports) (struct usb_serial *serial); + + void (*shutdown) (struct usb_serial *serial); + + int (*port_probe) (struct usb_serial_port *port); + int (*port_remove) (struct usb_serial_port *port); + + /* serial function calls */ + int (*open) (struct usb_serial_port *port, struct file * filp); + void (*close) (struct usb_serial_port *port, struct file * filp); + int (*write) (struct usb_serial_port *port, const unsigned char *buf, int count); + int (*write_room) (struct usb_serial_port *port); + int (*ioctl) (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); + void (*set_termios) (struct usb_serial_port *port, struct termios * old); + void (*break_ctl) (struct usb_serial_port *port, int break_state); + int (*chars_in_buffer) (struct usb_serial_port *port); + void (*throttle) (struct usb_serial_port *port); + void (*unthrottle) (struct usb_serial_port *port); + int (*tiocmget) (struct usb_serial_port *port, struct file *file); + int (*tiocmset) (struct usb_serial_port *port, struct file *file, unsigned int set, unsigned int clear); + + void (*read_int_callback)(struct urb *urb, struct pt_regs *regs); + void (*write_int_callback)(struct urb *urb, struct pt_regs *regs); + void (*read_bulk_callback)(struct urb *urb, struct pt_regs *regs); + void (*write_bulk_callback)(struct urb *urb, struct pt_regs *regs); +}; +#define to_usb_serial_driver(d) container_of(d, struct usb_serial_driver, driver) + +extern int usb_serial_register(struct usb_serial_driver *driver); +extern void usb_serial_deregister(struct usb_serial_driver *driver); +extern void usb_serial_port_softint(struct usb_serial_port *port); + +extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id); +extern void usb_serial_disconnect(struct usb_interface *iface); + +extern int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest); +extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit); + +/* USB Serial console functions */ +#ifdef CONFIG_USB_SERIAL_CONSOLE +extern void usb_serial_console_init (int debug, int minor); +extern void usb_serial_console_exit (void); +extern void usb_serial_console_disconnect(struct usb_serial *serial); +#else +static inline void usb_serial_console_init (int debug, int minor) { } +static inline void usb_serial_console_exit (void) { } +static inline void usb_serial_console_disconnect(struct usb_serial *serial) {} +#endif + +/* Functions needed by other parts of the usbserial core */ +extern struct usb_serial *usb_serial_get_by_index (unsigned int minor); +extern void usb_serial_put(struct usb_serial *serial); +extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp); +extern int usb_serial_generic_write (struct usb_serial_port *port, const unsigned char *buf, int count); +extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp); +extern int usb_serial_generic_write_room (struct usb_serial_port *port); +extern int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port); +extern void usb_serial_generic_read_bulk_callback (struct urb *urb, struct pt_regs *regs); +extern void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *regs); +extern void usb_serial_generic_shutdown (struct usb_serial *serial); +extern int usb_serial_generic_register (int debug); +extern void usb_serial_generic_deregister (void); + +extern int usb_serial_bus_register (struct usb_serial_driver *device); +extern void usb_serial_bus_deregister (struct usb_serial_driver *device); + +extern struct usb_serial_driver usb_serial_generic_device; +extern struct bus_type usb_serial_bus_type; +extern struct tty_driver *usb_serial_tty_driver; + +static inline void usb_serial_debug_data(int debug, + struct device *dev, + const char *function, int size, + const unsigned char *data) +{ + int i; + + if (debug) { + dev_printk(KERN_DEBUG, dev, "%s - length = %d, data = ", function, size); + for (i = 0; i < size; ++i) + printk ("%.2x ", data[i]); + printk ("\n"); + } +} + +/* Use our own dbg macro */ +#undef dbg +#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg); } while (0) + + + +#endif /* ifdef __LINUX_USB_SERIAL_H */ + diff --git a/include/linux/usb/sl811.h b/include/linux/usb/sl811.h new file mode 100644 index 000000000..397ee3b3d --- /dev/null +++ b/include/linux/usb/sl811.h @@ -0,0 +1,26 @@ + +/* + * board initialization should put one of these into dev->platform_data + * and place the sl811hs onto platform_bus named "sl811-hcd". + */ + +struct sl811_platform_data { + unsigned can_wakeup:1; + + /* given port_power, msec/2 after power on till power good */ + u8 potpg; + + /* mA/2 power supplied on this port (max = default = 250) */ + u8 power; + + /* sl811 relies on an external source of VBUS current */ + void (*port_power)(struct device *dev, int is_on); + + /* pulse sl811 nRST (probably with a GPIO) */ + void (*reset)(struct device *dev); + + // some boards need something like these: + // int (*check_overcurrent)(struct device *dev); + // void (*clock_enable)(struct device *dev, int is_on); +}; + diff --git a/include/linux/utrace.h b/include/linux/utrace.h new file mode 100644 index 000000000..e0f8ae1cd --- /dev/null +++ b/include/linux/utrace.h @@ -0,0 +1,484 @@ +/* + * User Debugging Data & Event Rendezvous + * + * This interface allows for notification of interesting events in a thread. + * It also mediates access to thread state such as registers. + * Multiple unrelated users can be associated with a single thread. + * We call each of these a tracing engine. + * + * A tracing engine starts by calling utrace_attach on the chosen thread, + * passing in a set of hooks (struct utrace_engine_ops), and some associated + * data. This produces a struct utrace_attached_engine, which is the handle + * used for all other operations. An attached engine has its ops vector, + * its data, and a flags word controlled by utrace_set_flags. + * + * Each engine's flags word contains two kinds of flags: events of + * interest, and action state flags. + * + * For each event flag that is set, that engine will get the + * appropriate ops->report_* callback when the event occurs. The + * struct utrace_engine_ops need not provide callbacks for an event + * unless the engine sets one of the associated event flags. + * + * Action state flags change the normal behavior of the thread. + * These bits are in UTRACE_ACTION_STATE_MASK; these can be OR'd into + * flags set with utrace_set_flags. Also, every callback that return + * an action value can reset these bits for the engine (see below). + * + * The bits UTRACE_ACTION_STATE_MASK of all attached engines are OR'd + * together, so each action is in force as long as any engine requests it. + * As long as some engine sets the UTRACE_ACTION_QUIESCE flag, the thread + * will block and not resume running user code. When the last engine + * clears its UTRACE_ACTION_QUIESCE flag, the thread will resume running. + */ + +#ifndef _LINUX_UTRACE_H +#define _LINUX_UTRACE_H 1 + +#include <linux/list.h> +#include <linux/rcupdate.h> +#include <linux/signal.h> + +struct linux_binprm; +struct pt_regs; +struct utrace_regset; +struct utrace_regset_view; + + +/* + * Flags in task_struct.utrace_flags and utrace_attached_engine.flags. + * Low four bits are UTRACE_ACTION_STATE_MASK bits (below). + * Higher bits are events of interest. + */ + +#define UTRACE_FIRST_EVENT 4 +#define UTRACE_EVENT_BITS (BITS_PER_LONG - UTRACE_FIRST_EVENT) +#define UTRACE_EVENT_MASK (-1UL &~ UTRACE_ACTION_STATE_MASK) + +enum utrace_events { + _UTRACE_EVENT_QUIESCE, /* Tracing requests stop. */ + _UTRACE_EVENT_REAP, /* Zombie reaped, no more tracing possible. */ + _UTRACE_EVENT_CLONE, /* Successful clone/fork/vfork just done. */ + _UTRACE_EVENT_VFORK_DONE, /* vfork woke from waiting for child. */ + _UTRACE_EVENT_EXEC, /* Successful execve just completed. */ + _UTRACE_EVENT_EXIT, /* Thread exit in progress. */ + _UTRACE_EVENT_DEATH, /* Thread has died. */ + _UTRACE_EVENT_SYSCALL_ENTRY, /* User entered kernel for system call. */ + _UTRACE_EVENT_SYSCALL_EXIT, /* Returning to user after system call. */ + _UTRACE_EVENT_SIGNAL, /* Signal delivery will run a user handler. */ + _UTRACE_EVENT_SIGNAL_IGN, /* No-op signal to be delivered. */ + _UTRACE_EVENT_SIGNAL_STOP, /* Signal delivery will suspend. */ + _UTRACE_EVENT_SIGNAL_TERM, /* Signal delivery will terminate. */ + _UTRACE_EVENT_SIGNAL_CORE, /* Signal delivery will dump core. */ + _UTRACE_EVENT_JCTL, /* Job control stop or continue completed. */ + _UTRACE_NEVENTS +}; +#define UTRACE_EVENT_BIT(type) (UTRACE_FIRST_EVENT + _UTRACE_EVENT_##type) +#define UTRACE_EVENT(type) (1UL << UTRACE_EVENT_BIT(type)) + +/* + * All the kinds of signal events. These all use the report_signal callback. + */ +#define UTRACE_EVENT_SIGNAL_ALL (UTRACE_EVENT(SIGNAL) \ + | UTRACE_EVENT(SIGNAL_IGN) \ + | UTRACE_EVENT(SIGNAL_STOP) \ + | UTRACE_EVENT(SIGNAL_TERM) \ + | UTRACE_EVENT(SIGNAL_CORE)) +/* + * Both kinds of syscall events; these call the report_syscall_entry and + * report_syscall_exit callbacks, respectively. + */ +#define UTRACE_EVENT_SYSCALL \ + (UTRACE_EVENT(SYSCALL_ENTRY) | UTRACE_EVENT(SYSCALL_EXIT)) + + +/* + * Action flags, in return value of callbacks. + * + * UTRACE_ACTION_RESUME (zero) is the return value to do nothing special. + * For each particular callback, some bits in UTRACE_ACTION_OP_MASK can + * be set in the return value to change the thread's behavior (see below). + * + * If UTRACE_ACTION_NEWSTATE is set, then the UTRACE_ACTION_STATE_MASK + * bits in the return value replace the engine's flags as in utrace_set_flags + * (but the event flags remained unchanged). + * + * If UTRACE_ACTION_HIDE is set, then the callbacks to other engines + * should be suppressed for this event. This is appropriate only when + * the event was artificially provoked by something this engine did, + * such as setting a breakpoint. + * + * If UTRACE_ACTION_DETACH is set, this engine is detached as by utrace_detach. + * The action bits in UTRACE_ACTION_OP_MASK work as normal, but the engine's + * UTRACE_ACTION_STATE_MASK bits will no longer affect the thread. + */ +#define UTRACE_ACTION_RESUME 0x0000 /* Continue normally after event. */ +#define UTRACE_ACTION_HIDE 0x0010 /* Hide event from other tracing. */ +#define UTRACE_ACTION_DETACH 0x0020 /* Detach me, state flags ignored. */ +#define UTRACE_ACTION_NEWSTATE 0x0040 /* Replace state bits. */ + +/* + * These flags affect the state of the thread until they are changed via + * utrace_set_flags or by the next callback to the same engine that uses + * UTRACE_ACTION_NEWSTATE. + */ +#define UTRACE_ACTION_QUIESCE 0x0001 /* Stay quiescent after callbacks. */ +#define UTRACE_ACTION_SINGLESTEP 0x0002 /* Resume for one instruction. */ +#define UTRACE_ACTION_BLOCKSTEP 0x0004 /* Resume until next branch. */ +#define UTRACE_ACTION_NOREAP 0x0008 /* Inhibit parent SIGCHLD and wait. */ +#define UTRACE_ACTION_STATE_MASK 0x000f /* Lasting state bits. */ + +/* These flags have meanings specific to the particular event report hook. */ +#define UTRACE_ACTION_OP_MASK 0xff00 + +/* + * Action flags in return value and argument of report_signal callback. + */ +#define UTRACE_SIGNAL_DELIVER 0x0100 /* Deliver according to sigaction. */ +#define UTRACE_SIGNAL_IGN 0x0200 /* Ignore the signal. */ +#define UTRACE_SIGNAL_TERM 0x0300 /* Terminate the process. */ +#define UTRACE_SIGNAL_CORE 0x0400 /* Terminate with core dump. */ +#define UTRACE_SIGNAL_STOP 0x0500 /* Deliver as absolute stop. */ +#define UTRACE_SIGNAL_TSTP 0x0600 /* Deliver as job control stop. */ +#define UTRACE_SIGNAL_HOLD 0x1000 /* Flag, push signal back on queue. */ +/* + * This value is passed to a report_signal callback after a signal + * handler is entered while UTRACE_ACTION_SINGLESTEP is in force. + * For this callback, no signal will never actually be delivered regardless + * of the return value, and the other callback parameters are null. + */ +#define UTRACE_SIGNAL_HANDLER 0x0700 + +/* Action flag in return value of report_jctl. */ +#define UTRACE_JCTL_NOSIGCHLD 0x0100 /* Do not notify the parent. */ + + +/* + * Flags for utrace_attach. If UTRACE_ATTACH_CREATE is not specified, + * you only look up an existing engine already attached to the + * thread. If UTRACE_ATTACH_MATCH_* bits are set, only consider + * matching engines. If UTRACE_ATTACH_EXCLUSIVE is set, attempting to + * attach a second (matching) engine fails with -EEXIST. + */ +#define UTRACE_ATTACH_CREATE 0x0010 /* Attach a new engine. */ +#define UTRACE_ATTACH_EXCLUSIVE 0x0020 /* Refuse if existing match. */ +#define UTRACE_ATTACH_MATCH_OPS 0x0001 /* Match engines on ops. */ +#define UTRACE_ATTACH_MATCH_DATA 0x0002 /* Match engines on data. */ +#define UTRACE_ATTACH_MATCH_MASK 0x000f + + +/* + * Per-thread structure task_struct.utrace points to. + * + * The task itself never has to worry about this going away after + * some event is found set in task_struct.utrace_flags. + * Once created, this pointer is changed only when the task is quiescent + * (TASK_TRACED or TASK_STOPPED with the siglock held, or dead). + * + * For other parties, the pointer to this is protected by RCU and + * task_lock. Since call_rcu is never used while the thread is alive and + * using this struct utrace, we can overlay the RCU data structure used + * only for a dead struct with some local state used only for a live utrace + * on an active thread. + */ +struct utrace +{ + union { + struct rcu_head dead; + struct { + struct task_struct *cloning; + struct utrace_signal *signal; + } live; + struct { + int notified; + int reap; + } exit; + } u; + + struct list_head engines; + spinlock_t lock; +}; +#define utrace_lock(utrace) spin_lock(&(utrace)->lock) +#define utrace_unlock(utrace) spin_unlock(&(utrace)->lock) + + +/* + * Per-engine per-thread structure. + * + * The task itself never has to worry about engines detaching while + * it's doing event callbacks. These structures are freed only when + * the task is quiescent. For other parties, the list is protected + * by RCU and utrace_lock. + */ +struct utrace_attached_engine +{ + struct list_head entry; /* Entry on thread's utrace.engines list. */ + struct rcu_head rhead; + + const struct utrace_engine_ops *ops; + unsigned long data; + + unsigned long flags; +}; + + +struct utrace_engine_ops +{ + /* + * Event reporting hooks. + * + * Return values contain UTRACE_ACTION_* flag bits. + * The UTRACE_ACTION_OP_MASK bits are specific to each kind of event. + * + * All report_* hooks are called with no locks held, in a generally + * safe environment when we will be returning to user mode soon. + * It is fine to block for memory allocation and the like, but all + * hooks are *asynchronous* and must not block on external events. + * If you want the thread to block, request UTRACE_ACTION_QUIESCE in + * your hook; then later wake it up with utrace_set_flags. + * + */ + + /* + * Event reported for parent, before child might run. + * The PF_STARTING flag prevents other engines from attaching + * before this one has its chance. + */ + u32 (*report_clone)(struct utrace_attached_engine *engine, + struct task_struct *parent, + unsigned long clone_flags, + struct task_struct *child); + + /* + * Event reported for parent using CLONE_VFORK or vfork system call. + * The child has died or exec'd, so the vfork parent has unblocked + * and is about to return child_pid. + */ + u32 (*report_vfork_done)(struct utrace_attached_engine *engine, + struct task_struct *parent, pid_t child_pid); + + /* + * Event reported after UTRACE_ACTION_QUIESCE is set, when the target + * thread is quiescent. Either it's the current thread, or it's in + * TASK_TRACED or TASK_STOPPED and will not resume running until the + * UTRACE_ACTION_QUIESCE flag is no longer asserted by any engine. + */ + u32 (*report_quiesce)(struct utrace_attached_engine *engine, + struct task_struct *tsk); + + /* + * Thread dequeuing a signal to be delivered. + * The action and *return_ka values say what UTRACE_ACTION_RESUME + * will do (possibly already influenced by another tracing engine). + * An UTRACE_SIGNAL_* return value overrides the signal disposition. + * The *info data (including info->si_signo) can be changed at will. + * Changing *return_ka affects the sigaction that be used. + * The *orig_ka value is the one in force before other tracing + * engines intervened. + */ + u32 (*report_signal)(struct utrace_attached_engine *engine, + struct task_struct *tsk, + struct pt_regs *regs, + u32 action, siginfo_t *info, + const struct k_sigaction *orig_ka, + struct k_sigaction *return_ka); + + /* + * Job control event completing, about to send SIGCHLD to parent + * with CLD_STOPPED or CLD_CONTINUED as given in type. + * UTRACE_JOBSTOP_NOSIGCHLD in the return value inhibits that. + */ + u32 (*report_jctl)(struct utrace_attached_engine *engine, + struct task_struct *tsk, + int type); + + /* + * Thread has just completed an exec. + * The initial user register state is handy to be tweaked directly. + */ + u32 (*report_exec)(struct utrace_attached_engine *engine, + struct task_struct *tsk, + const struct linux_binprm *bprm, + struct pt_regs *regs); + + /* + * Thread has entered the kernel to request a system call. + * The user register state is handy to be tweaked directly. + */ + u32 (*report_syscall_entry)(struct utrace_attached_engine *engine, + struct task_struct *tsk, + struct pt_regs *regs); + + /* + * Thread is about to leave the kernel after a system call request. + * The user register state is handy to be tweaked directly. + */ + u32 (*report_syscall_exit)(struct utrace_attached_engine *engine, + struct task_struct *tsk, + struct pt_regs *regs); + + /* + * Thread is exiting and cannot be prevented from doing so, + * but all its state is still live. The *code value will be + * the wait result seen by the parent, and can be changed by + * this engine or others. The orig_code value is the real + * status, not changed by any tracing engine. + */ + u32 (*report_exit)(struct utrace_attached_engine *engine, + struct task_struct *tsk, + long orig_code, long *code); + + /* + * Thread is really dead now. If UTRACE_ACTION_NOREAP is in force, + * it remains an unreported zombie. Otherwise, it might be reaped + * by its parent, or self-reap immediately. Though the actual + * reaping may happen in parallel, a report_reap callback will + * always be ordered after a report_death callback. + */ + u32 (*report_death)(struct utrace_attached_engine *engine, + struct task_struct *tsk); + + /* + * Called when someone reaps the dead task (parent, init, or self). + * No more callbacks are made after this one. + * The engine is always detached. + * There is nothing more a tracing engine can do about this thread. + */ + void (*report_reap)(struct utrace_attached_engine *engine, + struct task_struct *tsk); + + /* + * Miscellaneous hooks. These are not associated with event reports. + * Any of these may be null if the engine has nothing to say. + * These hooks are called in more constrained environments and should + * not block or do very much. + */ + + /* + * Return nonzero iff the caller task should be allowed to access + * the memory of the target task via /proc/PID/mem and so forth, + * by dint of this engine's attachment to the target. + */ + int (*allow_access_process_vm)(struct utrace_attached_engine *engine, + struct task_struct *target, + struct task_struct *caller); + + /* + * Return LSM_UNSAFE_* bits that apply to the exec in progress + * due to tracing done by this engine. These bits indicate that + * someone is able to examine the process and so a set-UID or similar + * privilege escalation may not be safe to permit. + * + * Called with task_lock held. + */ + int (*unsafe_exec)(struct utrace_attached_engine *engine, + struct task_struct *target); + + /* + * Return the task_struct for the task using ptrace on this one, or + * NULL. Always called with rcu_read_lock held to keep the + * returned struct alive. + * + * At exec time, this may be called with task_lock(target) still + * held from when unsafe_exec was just called. In that case it + * must give results consistent with those unsafe_exec results, + * i.e. non-NULL if any LSM_UNSAFE_PTRACE_* bits were set. + * + * The value is also used to display after "TracerPid:" in + * /proc/PID/status, where it is called with only rcu_read_lock held. + * + * If this engine returns NULL, another engine may supply the result. + */ + struct task_struct *(*tracer_task)(struct utrace_attached_engine *, + struct task_struct *target); +}; + + +/*** + *** These are the exported entry points for tracing engines to use. + ***/ + +/* + * Attach a new tracing engine to a thread, or look up attached engines. + * See UTRACE_ATTACH_* flags, above. The caller must ensure that the + * target thread does not get freed, i.e. hold a ref or be its parent. + */ +struct utrace_attached_engine *utrace_attach(struct task_struct *target, + int flags, + const struct utrace_engine_ops *, + unsigned long data); + +/* + * Detach a tracing engine from a thread. After this, the engine + * data structure is no longer accessible, and the thread might be reaped. + * The thread will start running again if it was being kept quiescent + * and no longer has any attached engines asserting UTRACE_ACTION_QUIESCE. + * + * If the target thread is not already quiescent, then a callback to this + * engine might be in progress or about to start on another CPU. If it's + * quiescent when utrace_detach is called, then after return it's guaranteed + * that no more callbacks to the ops vector will be done. + */ +void utrace_detach(struct task_struct *target, + struct utrace_attached_engine *engine); + +/* + * Change the flags for a tracing engine. + * This resets the event flags and the action state flags. + * If UTRACE_ACTION_QUIESCE and UTRACE_EVENT(QUIESCE) are set, + * this will cause a report_quiesce callback soon, maybe immediately. + * If UTRACE_ACTION_QUIESCE was set before and is no longer set by + * any engine, this will wake the thread up. + */ +void utrace_set_flags(struct task_struct *target, + struct utrace_attached_engine *engine, + unsigned long flags); + +/* + * Cause a specified signal delivery in the target thread, which must be + * quiescent (or the current thread). The action has UTRACE_SIGNAL_* bits + * as returned from a report_signal callback. If ka is non-null, it gives + * the sigaction to follow for UTRACE_SIGNAL_DELIVER; otherwise, the + * installed sigaction at the time of delivery is used. + */ +int utrace_inject_signal(struct task_struct *target, + struct utrace_attached_engine *engine, + u32 action, siginfo_t *info, + const struct k_sigaction *ka); + +/* + * Prepare to access thread's machine state, see <linux/tracehook.h>. + * The given thread must be quiescent (or the current thread). + * When this returns, the struct utrace_regset calls may be used to + * interrogate or change the thread's state. Do not cache the returned + * pointer when the thread can resume. You must call utrace_regset to + * ensure that context switching has completed and consistent state is + * available. + */ +const struct utrace_regset *utrace_regset(struct task_struct *target, + struct utrace_attached_engine *, + const struct utrace_regset_view *, + int which); + + +/* + * Hooks in <linux/tracehook.h> call these entry points to the utrace dispatch. + */ +void utrace_quiescent(struct task_struct *); +void utrace_release_task(struct task_struct *); +int utrace_get_signal(struct task_struct *, struct pt_regs *, + siginfo_t *, struct k_sigaction *); +void utrace_report_clone(unsigned long clone_flags, struct task_struct *child); +void utrace_report_vfork_done(pid_t child_pid); +void utrace_report_exit(long *exit_code); +void utrace_report_death(struct task_struct *, struct utrace *); +int utrace_report_jctl(int type); +void utrace_report_exec(struct linux_binprm *bprm, struct pt_regs *regs); +void utrace_report_syscall(struct pt_regs *regs, int is_exit); +struct task_struct *utrace_tracer_task(struct task_struct *); +int utrace_allow_access_process_vm(struct task_struct *); +int utrace_unsafe_exec(struct task_struct *); +void utrace_signal_handler_singlestep(struct task_struct *, struct pt_regs *); + + +#endif /* linux/utrace.h */ diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h new file mode 100644 index 000000000..198372624 --- /dev/null +++ b/include/linux/vmstat.h @@ -0,0 +1,219 @@ +#ifndef _LINUX_VMSTAT_H +#define _LINUX_VMSTAT_H + +#include <linux/types.h> +#include <linux/percpu.h> +#include <linux/mmzone.h> +#include <asm/atomic.h> + +#ifdef CONFIG_VM_EVENT_COUNTERS +/* + * Light weight per cpu counter implementation. + * + * Counters should only be incremented and no critical kernel component + * should rely on the counter values. + * + * Counters are handled completely inline. On many platforms the code + * generated will simply be the increment of a global address. + */ + +#define FOR_ALL_ZONES(x) x##_DMA, x##_DMA32, x##_NORMAL, x##_HIGH + +enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT, + FOR_ALL_ZONES(PGALLOC), + PGFREE, PGACTIVATE, PGDEACTIVATE, + PGFAULT, PGMAJFAULT, + FOR_ALL_ZONES(PGREFILL), + FOR_ALL_ZONES(PGSTEAL), + FOR_ALL_ZONES(PGSCAN_KSWAPD), + FOR_ALL_ZONES(PGSCAN_DIRECT), + PGINODESTEAL, SLABS_SCANNED, KSWAPD_STEAL, KSWAPD_INODESTEAL, + PAGEOUTRUN, ALLOCSTALL, PGROTATED, + NR_VM_EVENT_ITEMS +}; + +struct vm_event_state { + unsigned long event[NR_VM_EVENT_ITEMS]; +}; + +DECLARE_PER_CPU(struct vm_event_state, vm_event_states); + +static inline void __count_vm_event(enum vm_event_item item) +{ + __get_cpu_var(vm_event_states).event[item]++; +} + +static inline void count_vm_event(enum vm_event_item item) +{ + get_cpu_var(vm_event_states).event[item]++; + put_cpu(); +} + +static inline void __count_vm_events(enum vm_event_item item, long delta) +{ + __get_cpu_var(vm_event_states).event[item] += delta; +} + +static inline void count_vm_events(enum vm_event_item item, long delta) +{ + get_cpu_var(vm_event_states).event[item] += delta; + put_cpu(); +} + +extern void all_vm_events(unsigned long *); +extern void vm_events_fold_cpu(int cpu); + +#else + +/* Disable counters */ +#define get_cpu_vm_events(e) 0L +#define count_vm_event(e) do { } while (0) +#define count_vm_events(e,d) do { } while (0) +#define __count_vm_event(e) do { } while (0) +#define __count_vm_events(e,d) do { } while (0) +#define vm_events_fold_cpu(x) do { } while (0) + +#endif /* CONFIG_VM_EVENT_COUNTERS */ + +#define __count_zone_vm_events(item, zone, delta) \ + __count_vm_events(item##_DMA + zone_idx(zone), delta) + +/* + * Zone based page accounting with per cpu differentials. + */ +extern atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS]; + +static inline void zone_page_state_add(long x, struct zone *zone, + enum zone_stat_item item) +{ + atomic_long_add(x, &zone->vm_stat[item]); + atomic_long_add(x, &vm_stat[item]); +} + +static inline unsigned long global_page_state(enum zone_stat_item item) +{ + long x = atomic_long_read(&vm_stat[item]); +#ifdef CONFIG_SMP + if (x < 0) + x = 0; +#endif + return x; +} + +static inline unsigned long zone_page_state(struct zone *zone, + enum zone_stat_item item) +{ + long x = atomic_long_read(&zone->vm_stat[item]); +#ifdef CONFIG_SMP + if (x < 0) + x = 0; +#endif + return x; +} + +#ifdef CONFIG_NUMA +/* + * Determine the per node value of a stat item. This function + * is called frequently in a NUMA machine, so try to be as + * frugal as possible. + */ +static inline unsigned long node_page_state(int node, + enum zone_stat_item item) +{ + struct zone *zones = NODE_DATA(node)->node_zones; + + return +#ifndef CONFIG_DMA_IS_NORMAL +#if !defined(CONFIG_DMA_IS_DMA32) && BITS_PER_LONG >= 64 + zone_page_state(&zones[ZONE_DMA32], item) + +#endif + zone_page_state(&zones[ZONE_NORMAL], item) + +#endif +#ifdef CONFIG_HIGHMEM + zone_page_state(&zones[ZONE_HIGHMEM], item) + +#endif + zone_page_state(&zones[ZONE_DMA], item); +} + +extern void zone_statistics(struct zonelist *, struct zone *); + +#else + +#define node_page_state(node, item) global_page_state(item) +#define zone_statistics(_zl,_z) do { } while (0) + +#endif /* CONFIG_NUMA */ + +#define __add_zone_page_state(__z, __i, __d) \ + __mod_zone_page_state(__z, __i, __d) +#define __sub_zone_page_state(__z, __i, __d) \ + __mod_zone_page_state(__z, __i,-(__d)) + +#define add_zone_page_state(__z, __i, __d) mod_zone_page_state(__z, __i, __d) +#define sub_zone_page_state(__z, __i, __d) mod_zone_page_state(__z, __i, -(__d)) + +static inline void zap_zone_vm_stats(struct zone *zone) +{ + memset(zone->vm_stat, 0, sizeof(zone->vm_stat)); +} + +extern void inc_zone_state(struct zone *, enum zone_stat_item); + +#ifdef CONFIG_SMP +void __mod_zone_page_state(struct zone *, enum zone_stat_item item, int); +void __inc_zone_page_state(struct page *, enum zone_stat_item); +void __dec_zone_page_state(struct page *, enum zone_stat_item); + +void mod_zone_page_state(struct zone *, enum zone_stat_item, int); +void inc_zone_page_state(struct page *, enum zone_stat_item); +void dec_zone_page_state(struct page *, enum zone_stat_item); + +extern void inc_zone_state(struct zone *, enum zone_stat_item); + +void refresh_cpu_vm_stats(int); +void refresh_vm_stats(void); + +#else /* CONFIG_SMP */ + +/* + * We do not maintain differentials in a single processor configuration. + * The functions directly modify the zone and global counters. + */ +static inline void __mod_zone_page_state(struct zone *zone, + enum zone_stat_item item, int delta) +{ + zone_page_state_add(delta, zone, item); +} + +static inline void __inc_zone_state(struct zone *zone, enum zone_stat_item item) +{ + atomic_long_inc(&zone->vm_stat[item]); + atomic_long_inc(&vm_stat[item]); +} + +static inline void __inc_zone_page_state(struct page *page, + enum zone_stat_item item) +{ + __inc_zone_state(page_zone(page), item); +} + +static inline void __dec_zone_page_state(struct page *page, + enum zone_stat_item item) +{ + atomic_long_dec(&page_zone(page)->vm_stat[item]); + atomic_long_dec(&vm_stat[item]); +} + +/* + * We only use atomic operations to update counters. So there is no need to + * disable interrupts. + */ +#define inc_zone_page_state __inc_zone_page_state +#define dec_zone_page_state __dec_zone_page_state +#define mod_zone_page_state __mod_zone_page_state + +static inline void refresh_cpu_vm_stats(int cpu) { } +static inline void refresh_vm_stats(void) { } +#endif + +#endif /* _LINUX_VMSTAT_H */ diff --git a/include/linux/vs_cvirt.h.orig b/include/linux/vs_cvirt.h.orig new file mode 100644 index 000000000..c6aa9d3cf --- /dev/null +++ b/include/linux/vs_cvirt.h.orig @@ -0,0 +1,157 @@ +#ifndef _VX_VS_CVIRT_H +#define _VX_VS_CVIRT_H + +#include "vserver/cvirt.h" +#include "vserver/debug.h" + + +/* utsname virtualization */ + +static inline struct new_utsname *vx_new_utsname(void) +{ + if (current->vx_info) + return ¤t->vx_info->cvirt.utsname; + return &system_utsname; +} + +#define vx_new_uts(x) ((vx_new_utsname())->x) + + +/* pid faking stuff */ + + +#define vx_info_map_pid(v,p) \ + __vx_info_map_pid((v), (p), __FUNC__, __FILE__, __LINE__) +#define vx_info_map_tgid(v,p) vx_info_map_pid(v,p) +#define vx_map_pid(p) vx_info_map_pid(current->vx_info, p) +#define vx_map_tgid(p) vx_map_pid(p) + +static inline int __vx_info_map_pid(struct vx_info *vxi, int pid, + const char *func, const char *file, int line) +{ + if (vx_info_flags(vxi, VXF_INFO_INIT, 0)) { + vxfprintk(VXD_CBIT(cvirt, 2), + "vx_map_tgid: %p/%llx: %d -> %d", + vxi, (long long)vxi->vx_flags, pid, + (pid && pid == vxi->vx_initpid)?1:pid, + func, file, line); + if (pid == 0) + return 0; + if (pid == vxi->vx_initpid) + return 1; + } + return pid; +} + +#define vx_info_rmap_pid(v,p) \ + __vx_info_rmap_pid((v), (p), __FUNC__, __FILE__, __LINE__) +#define vx_rmap_pid(p) vx_info_rmap_pid(current->vx_info, p) +#define vx_rmap_tgid(p) vx_rmap_pid(p) + +static inline int __vx_info_rmap_pid(struct vx_info *vxi, int pid, + const char *func, const char *file, int line) +{ + if (vx_info_flags(vxi, VXF_INFO_INIT, 0)) { + vxfprintk(VXD_CBIT(cvirt, 2), + "vx_rmap_tgid: %p/%llx: %d -> %d", + vxi, (long long)vxi->vx_flags, pid, + (pid == 1)?vxi->vx_initpid:pid, + func, file, line); + if ((pid == 1) && vxi->vx_initpid) + return vxi->vx_initpid; + if (pid == vxi->vx_initpid) + return ~0U; + } + return pid; +} + + +static inline void vx_activate_task(struct task_struct *p) +{ + struct vx_info *vxi; + + if ((vxi = p->vx_info)) { + vx_update_load(vxi); + atomic_inc(&vxi->cvirt.nr_running); + } +} + +static inline void vx_deactivate_task(struct task_struct *p) +{ + struct vx_info *vxi; + + if ((vxi = p->vx_info)) { + vx_update_load(vxi); + atomic_dec(&vxi->cvirt.nr_running); + } +} + +static inline void vx_uninterruptible_inc(struct task_struct *p) +{ + struct vx_info *vxi; + + if ((vxi = p->vx_info)) + atomic_inc(&vxi->cvirt.nr_uninterruptible); +} + +static inline void vx_uninterruptible_dec(struct task_struct *p) +{ + struct vx_info *vxi; + + if ((vxi = p->vx_info)) + atomic_dec(&vxi->cvirt.nr_uninterruptible); +} + + +struct inode; + +#define VXF_FAKE_INIT (VXF_INFO_INIT|VXF_STATE_INIT) + +static inline +int proc_pid_visible(struct task_struct *task, int pid) +{ + if ((pid == 1) && + !vx_flags(VXF_FAKE_INIT, VXF_FAKE_INIT)) + /* show a blend through init */ + goto visible; + if (vx_check(vx_task_xid(task), VX_WATCH|VX_IDENT)) + goto visible; + return 0; +visible: + return 1; +} + +static inline +struct task_struct *find_proc_task_by_pid(int pid) +{ + struct task_struct *task = find_task_by_pid(pid); + + if (task && !proc_pid_visible(task, pid)) { + vxdprintk(VXD_CBIT(misc, 6), + "dropping task %p[#%u,%u] for %p[#%u,%u]", + task, task->xid, task->pid, + current, current->xid, current->pid); + task = NULL; + } + return task; +} + +static inline +struct task_struct *vx_get_proc_task(struct inode *inode, struct pid *pid) +{ + struct task_struct *task = get_pid_task(pid, PIDTYPE_PID); + + if (task && !proc_pid_visible(task, pid->nr)) { + vxdprintk(VXD_CBIT(misc, 6), + "dropping task %p[#%u,%u] for %p[#%u,%u]", + task, task->xid, task->pid, + current, current->xid, current->pid); + put_task_struct(task); + task = NULL; + } + return task; +} + +#else +#warning duplicate inclusion +#endif diff --git a/include/linux/xenfb.h b/include/linux/xenfb.h new file mode 100644 index 000000000..3653c57f6 --- /dev/null +++ b/include/linux/xenfb.h @@ -0,0 +1,108 @@ +/* + * linux/include/linux/xenfb.h -- Xen virtual frame buffer device + * + * Copyright (C) 2005 + * + * Anthony Liguori <aliguori@us.ibm.com> + * + * 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. + */ + +#ifndef _LINUX_XENFB_H +#define _LINUX_XENFB_H + +#include <asm/types.h> + +/* out events */ + +#define XENFB_OUT_EVENT_SIZE 40 + +#define XENFB_TYPE_MOTION 1 +#define XENFB_TYPE_UPDATE 2 + +struct xenfb_motion /* currently unused */ +{ + __u8 type; /* XENFB_TYPE_MOTION */ + __u16 x; /* The new x coordinate */ + __u16 y; /* The new y coordinate */ +}; + +struct xenfb_update +{ + __u8 type; /* XENFB_TYPE_UPDATE */ + __u16 x; /* source x */ + __u16 y; /* source y */ + __u16 width; /* rect width */ + __u16 height; /* rect height */ +}; + +union xenfb_out_event +{ + __u8 type; + struct xenfb_motion motion; + struct xenfb_update update; + char _[XENFB_OUT_EVENT_SIZE]; +}; + +/* in events */ + +#define XENFB_IN_EVENT_SIZE 40 + +#define XENFB_TYPE_SET_EVENTS 1 + +#define XENFB_FLAG_MOTION 1 +#define XENFB_FLAG_UPDATE 2 +#define XENFB_FLAG_COPY 4 +#define XENFB_FLAG_FILL 8 + +struct xenfb_set_events +{ + __u8 type; /* XENFB_TYPE_SET_EVENTS */ + __u32 flags; /* combination of XENFB_FLAG_* */ +}; + +union xenfb_in_event +{ + __u8 type; + struct xenfb_set_events set_events; + char _[XENFB_OUT_EVENT_SIZE]; +}; + +/* shared page */ + +#define XENFB_IN_RING_SIZE 1024 +#define XENFB_IN_RING_LEN (XENFB_IN_RING_SIZE / XENFB_IN_EVENT_SIZE) +#define XENFB_IN_RING_OFFS 1024 +#define XENFB_IN_RING(page) \ + ((union xenfb_in_event *)((char *)(page) + XENFB_IN_RING_OFFS)) +#define XENFB_IN_RING_REF(page, idx) \ + (XENFB_IN_RING((page))[(idx) % XENFB_IN_RING_LEN]) + +#define XENFB_OUT_RING_SIZE 2048 +#define XENFB_OUT_RING_LEN (XENFB_OUT_RING_SIZE / XENFB_OUT_EVENT_SIZE) +#define XENFB_OUT_RING_OFFS (XENFB_IN_RING_OFFS + XENFB_IN_RING_SIZE) +#define XENFB_OUT_RING(page) \ + ((union xenfb_out_event *)((char *)(page) + XENFB_OUT_RING_OFFS)) +#define XENFB_OUT_RING_REF(page, idx) \ + (XENFB_OUT_RING((page))[(idx) % XENFB_OUT_RING_LEN]) + +struct xenfb_page +{ + __u16 width; /* the width of the framebuffer (in pixels) */ + __u16 height; /* the height of the framebuffer (in pixels) */ + __u32 line_length; /* the length of a row of pixels (in bytes) */ + __u32 mem_length; /* the length of the framebuffer (in bytes) */ + __u8 depth; /* the depth of a pixel (in bits) */ + + unsigned long pd[2]; /* FIXME rename to pgdir? */ + /* FIXME pd[1] unused at this time, shrink? */ + + __u32 in_cons, in_prod; + __u32 out_cons, out_prod; +}; + +void xenfb_resume(void); + +#endif diff --git a/include/linux/xenkbd.h b/include/linux/xenkbd.h new file mode 100644 index 000000000..c023c123d --- /dev/null +++ b/include/linux/xenkbd.h @@ -0,0 +1,92 @@ +/* + * linux/include/linux/xenkbd.h -- Xen virtual keyboard/mouse + * + * Copyright (C) 2005 + * + * Anthony Liguori <aliguori@us.ibm.com> + * + * 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. + */ + +#ifndef _LINUX_XENKBD_H +#define _LINUX_XENKBD_H + +#include <asm/types.h> + +/* in events */ + +#define XENKBD_IN_EVENT_SIZE 40 + +#define XENKBD_TYPE_MOTION 1 /* mouse movement event */ +#define XENKBD_TYPE_BUTTON 2 /* mouse button event */ +#define XENKBD_TYPE_KEY 3 /* keyboard event */ + +struct xenkbd_motion +{ + __u8 type; /* XENKBD_TYPE_MOTION */ + __s16 rel_x; /* relative X motion */ + __s16 rel_y; /* relative Y motion */ +}; + +struct xenkbd_button +{ + __u8 type; /* XENKBD_TYPE_BUTTON */ + __u8 pressed; /* 1 if pressed; 0 otherwise */ + __u8 button; /* the button (0, 1, 2 is right, middle, left) */ +}; + +struct xenkbd_key +{ + __u8 type; /* XENKBD_TYPE_KEY */ + __u8 pressed; /* 1 if pressed; 0 otherwise */ + __u16 keycode; /* KEY_* from linux/input.h */ +}; + +union xenkbd_in_event +{ + __u8 type; + struct xenkbd_motion motion; + struct xenkbd_button button; + struct xenkbd_key key; + char _[XENKBD_IN_EVENT_SIZE]; +}; + +/* out events */ + +#define XENKBD_OUT_EVENT_SIZE 40 + +union xenkbd_out_event +{ + __u8 type; + char _[XENKBD_OUT_EVENT_SIZE]; +}; + +/* shared page */ + +#define XENKBD_IN_RING_SIZE 2048 +#define XENKBD_IN_RING_LEN (XENKBD_IN_RING_SIZE / XENKBD_IN_EVENT_SIZE) +#define XENKBD_IN_RING_OFFS 1024 +#define XENKBD_IN_RING(page) \ + ((union xenkbd_in_event *)((char *)(page) + XENKBD_IN_RING_OFFS)) +#define XENKBD_IN_RING_REF(page, idx) \ + (XENKBD_IN_RING((page))[(idx) % XENKBD_IN_RING_LEN]) + +#define XENKBD_OUT_RING_SIZE 1024 +#define XENKBD_OUT_RING_LEN (XENKBD_OUT_RING_SIZE / XENKBD_OUT_EVENT_SIZE) +#define XENKBD_OUT_RING_OFFS (XENKBD_IN_RING_OFFS + XENKBD_IN_RING_SIZE) +#define XENKBD_OUT_RING(page) \ + ((union xenkbd_out_event *)((char *)(page) + XENKBD_OUT_RING_OFFS)) +#define XENKBD_OUT_RING_REF(page, idx) \ + (XENKBD_OUT_RING((page))[(idx) % XENKBD_OUT_RING_LEN]) + +struct xenkbd_info +{ + __u32 in_cons, in_prod; + __u32 out_cons, out_prod; +}; + +void xenkbd_resume(void); + +#endif diff --git a/include/media/cx2341x.h b/include/media/cx2341x.h new file mode 100644 index 000000000..d91d88f93 --- /dev/null +++ b/include/media/cx2341x.h @@ -0,0 +1,195 @@ +/* + cx23415/6 header containing common defines. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef CX2341X_H +#define CX2341X_H + +enum cx2341x_port { + CX2341X_PORT_MEMORY = 0, + CX2341X_PORT_STREAMING = 1, + CX2341X_PORT_SERIAL = 2 +}; + +enum cx2341x_cap { + CX2341X_CAP_HAS_SLICED_VBI = 1 << 0, +}; + +struct cx2341x_mpeg_params { + /* misc */ + u32 capabilities; + enum cx2341x_port port; + u16 width; + u16 height; + u16 is_50hz; + + /* stream */ + enum v4l2_mpeg_stream_type stream_type; + enum v4l2_mpeg_stream_vbi_fmt stream_vbi_fmt; + + /* audio */ + enum v4l2_mpeg_audio_sampling_freq audio_sampling_freq; + enum v4l2_mpeg_audio_encoding audio_encoding; + enum v4l2_mpeg_audio_l2_bitrate audio_l2_bitrate; + enum v4l2_mpeg_audio_mode audio_mode; + enum v4l2_mpeg_audio_mode_extension audio_mode_extension; + enum v4l2_mpeg_audio_emphasis audio_emphasis; + enum v4l2_mpeg_audio_crc audio_crc; + u8 audio_properties; + + /* video */ + enum v4l2_mpeg_video_encoding video_encoding; + enum v4l2_mpeg_video_aspect video_aspect; + u16 video_b_frames; + u16 video_gop_size; + u16 video_gop_closure; + u16 video_pulldown; + enum v4l2_mpeg_video_bitrate_mode video_bitrate_mode; + u32 video_bitrate; + u32 video_bitrate_peak; + u16 video_temporal_decimation; + + /* encoding filters */ + enum v4l2_mpeg_cx2341x_video_spatial_filter_mode video_spatial_filter_mode; + u16 video_spatial_filter; + enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type video_luma_spatial_filter_type; + enum v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type video_chroma_spatial_filter_type; + enum v4l2_mpeg_cx2341x_video_temporal_filter_mode video_temporal_filter_mode; + u16 video_temporal_filter; + enum v4l2_mpeg_cx2341x_video_median_filter_type video_median_filter_type; + u16 video_luma_median_filter_top; + u16 video_luma_median_filter_bottom; + u16 video_chroma_median_filter_top; + u16 video_chroma_median_filter_bottom; +}; + +#define CX2341X_MBOX_MAX_DATA 16 + +extern const u32 cx2341x_mpeg_ctrls[]; +typedef int (*cx2341x_mbox_func)(void *priv, int cmd, int in, int out, + u32 data[CX2341X_MBOX_MAX_DATA]); +int cx2341x_update(void *priv, cx2341x_mbox_func func, + const struct cx2341x_mpeg_params *old, + const struct cx2341x_mpeg_params *new); +int cx2341x_ctrl_query(struct cx2341x_mpeg_params *params, + struct v4l2_queryctrl *qctrl); +const char **cx2341x_ctrl_get_menu(u32 id); +int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, + struct v4l2_ext_controls *ctrls, unsigned int cmd); +void cx2341x_fill_defaults(struct cx2341x_mpeg_params *p); +void cx2341x_log_status(struct cx2341x_mpeg_params *p, const char *prefix); + +/* Firmware names */ +#define CX2341X_FIRM_ENC_FILENAME "v4l-cx2341x-enc.fw" +/* Decoder firmware for the cx23415 only */ +#define CX2341X_FIRM_DEC_FILENAME "v4l-cx2341x-dec.fw" + +/* Firmware API commands */ + +/* MPEG decoder API, specific to the cx23415 */ +#define CX2341X_DEC_PING_FW 0x00 +#define CX2341X_DEC_START_PLAYBACK 0x01 +#define CX2341X_DEC_STOP_PLAYBACK 0x02 +#define CX2341X_DEC_SET_PLAYBACK_SPEED 0x03 +#define CX2341X_DEC_STEP_VIDEO 0x05 +#define CX2341X_DEC_SET_DMA_BLOCK_SIZE 0x08 +#define CX2341X_DEC_GET_XFER_INFO 0x09 +#define CX2341X_DEC_GET_DMA_STATUS 0x0a +#define CX2341X_DEC_SCHED_DMA_FROM_HOST 0x0b +#define CX2341X_DEC_PAUSE_PLAYBACK 0x0d +#define CX2341X_DEC_HALT_FW 0x0e +#define CX2341X_DEC_SET_STANDARD 0x10 +#define CX2341X_DEC_GET_VERSION 0x11 +#define CX2341X_DEC_SET_STREAM_INPUT 0x14 +#define CX2341X_DEC_GET_TIMING_INFO 0x15 +#define CX2341X_DEC_SET_AUDIO_MODE 0x16 +#define CX2341X_DEC_SET_EVENT_NOTIFICATION 0x17 +#define CX2341X_DEC_SET_DISPLAY_BUFFERS 0x18 +#define CX2341X_DEC_EXTRACT_VBI 0x19 +#define CX2341X_DEC_SET_DECODER_SOURCE 0x1a +#define CX2341X_DEC_SET_AUDIO_OUTPUT 0x1b +#define CX2341X_DEC_SET_AV_DELAY 0x1c +#define CX2341X_DEC_SET_PREBUFFERING 0x1e + +/* MPEG encoder API */ +#define CX2341X_ENC_PING_FW 0x80 +#define CX2341X_ENC_START_CAPTURE 0x81 +#define CX2341X_ENC_STOP_CAPTURE 0x82 +#define CX2341X_ENC_SET_AUDIO_ID 0x89 +#define CX2341X_ENC_SET_VIDEO_ID 0x8b +#define CX2341X_ENC_SET_PCR_ID 0x8d +#define CX2341X_ENC_SET_FRAME_RATE 0x8f +#define CX2341X_ENC_SET_FRAME_SIZE 0x91 +#define CX2341X_ENC_SET_BIT_RATE 0x95 +#define CX2341X_ENC_SET_GOP_PROPERTIES 0x97 +#define CX2341X_ENC_SET_ASPECT_RATIO 0x99 +#define CX2341X_ENC_SET_DNR_FILTER_MODE 0x9b +#define CX2341X_ENC_SET_DNR_FILTER_PROPS 0x9d +#define CX2341X_ENC_SET_CORING_LEVELS 0x9f +#define CX2341X_ENC_SET_SPATIAL_FILTER_TYPE 0xa1 +#define CX2341X_ENC_SET_3_2_PULLDOWN 0xb1 +#define CX2341X_ENC_SET_VBI_LINE 0xb7 +#define CX2341X_ENC_SET_STREAM_TYPE 0xb9 +#define CX2341X_ENC_SET_OUTPUT_PORT 0xbb +#define CX2341X_ENC_SET_AUDIO_PROPERTIES 0xbd +#define CX2341X_ENC_HALT_FW 0xc3 +#define CX2341X_ENC_GET_VERSION 0xc4 +#define CX2341X_ENC_SET_GOP_CLOSURE 0xc5 +#define CX2341X_ENC_GET_SEQ_END 0xc6 +#define CX2341X_ENC_SET_PGM_INDEX_INFO 0xc7 +#define CX2341X_ENC_SET_VBI_CONFIG 0xc8 +#define CX2341X_ENC_SET_DMA_BLOCK_SIZE 0xc9 +#define CX2341X_ENC_GET_PREV_DMA_INFO_MB_10 0xca +#define CX2341X_ENC_GET_PREV_DMA_INFO_MB_9 0xcb +#define CX2341X_ENC_SCHED_DMA_TO_HOST 0xcc +#define CX2341X_ENC_INITIALIZE_INPUT 0xcd +#define CX2341X_ENC_SET_FRAME_DROP_RATE 0xd0 +#define CX2341X_ENC_PAUSE_ENCODER 0xd2 +#define CX2341X_ENC_REFRESH_INPUT 0xd3 +#define CX2341X_ENC_SET_COPYRIGHT 0xd4 +#define CX2341X_ENC_SET_EVENT_NOTIFICATION 0xd5 +#define CX2341X_ENC_SET_NUM_VSYNC_LINES 0xd6 +#define CX2341X_ENC_SET_PLACEHOLDER 0xd7 +#define CX2341X_ENC_MUTE_VIDEO 0xd9 +#define CX2341X_ENC_MUTE_AUDIO 0xda +#define CX2341X_ENC_UNKNOWN 0xdb +#define CX2341X_ENC_MISC 0xdc + +/* OSD API, specific to the cx23415 */ +#define CX2341X_OSD_GET_FRAMEBUFFER 0x41 +#define CX2341X_OSD_GET_PIXEL_FORMAT 0x42 +#define CX2341X_OSD_SET_PIXEL_FORMAT 0x43 +#define CX2341X_OSD_GET_STATE 0x44 +#define CX2341X_OSD_SET_STATE 0x45 +#define CX2341X_OSD_GET_OSD_COORDS 0x46 +#define CX2341X_OSD_SET_OSD_COORDS 0x47 +#define CX2341X_OSD_GET_SCREEN_COORDS 0x48 +#define CX2341X_OSD_SET_SCREEN_COORDS 0x49 +#define CX2341X_OSD_GET_GLOBAL_ALPHA 0x4a +#define CX2341X_OSD_SET_GLOBAL_ALPHA 0x4b +#define CX2341X_OSD_SET_BLEND_COORDS 0x4c +#define CX2341X_OSD_GET_FLICKER_STATE 0x4f +#define CX2341X_OSD_SET_FLICKER_STATE 0x50 +#define CX2341X_OSD_BLT_COPY 0x52 +#define CX2341X_OSD_BLT_FILL 0x53 +#define CX2341X_OSD_BLT_TEXT 0x54 +#define CX2341X_OSD_SET_FRAMEBUFFER_WINDOW 0x56 +#define CX2341X_OSD_SET_CHROMA_KEY 0x60 +#define CX2341X_OSD_GET_ALPHA_CONTENT_INDEX 0x61 +#define CX2341X_OSD_SET_ALPHA_CONTENT_INDEX 0x62 + +#endif /* CX2341X_H */ diff --git a/include/media/pwc-ioctl.h b/include/media/pwc-ioctl.h new file mode 100644 index 000000000..adc1254e8 --- /dev/null +++ b/include/media/pwc-ioctl.h @@ -0,0 +1,325 @@ +#ifndef PWC_IOCTL_H +#define PWC_IOCTL_H + +/* (C) 2001-2004 Nemosoft Unv. + (C) 2004-2006 Luc Saillard (luc@saillard.org) + + NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx + driver and thus may have bugs that are not present in the original version. + Please send bug reports and support requests to <luc@saillard.org>. + The decompression routines have been implemented by reverse-engineering the + Nemosoft binary pwcx module. Caveat emptor. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* This is pwc-ioctl.h belonging to PWC 10.0.10 + It contains structures and defines to communicate from user space + directly to the driver. + */ + +/* + Changes + 2001/08/03 Alvarado Added ioctl constants to access methods for + changing white balance and red/blue gains + 2002/12/15 G. H. Fernandez-Toribio VIDIOCGREALSIZE + 2003/12/13 Nemosft Unv. Some modifications to make interfacing to + PWCX easier + 2006/01/01 Luc Saillard Add raw format definition + */ + +/* These are private ioctl() commands, specific for the Philips webcams. + They contain functions not found in other webcams, and settings not + specified in the Video4Linux API. + + The #define names are built up like follows: + VIDIOC VIDeo IOCtl prefix + PWC Philps WebCam + G optional: Get + S optional: Set + ... the function + */ + +#include <linux/types.h> +#include <linux/version.h> + + + /* Enumeration of image sizes */ +#define PSZ_SQCIF 0x00 +#define PSZ_QSIF 0x01 +#define PSZ_QCIF 0x02 +#define PSZ_SIF 0x03 +#define PSZ_CIF 0x04 +#define PSZ_VGA 0x05 +#define PSZ_MAX 6 + + +/* The frame rate is encoded in the video_window.flags parameter using + the upper 16 bits, since some flags are defined nowadays. The following + defines provide a mask and shift to filter out this value. + This value can also be passing using the private flag when using v4l2 and + VIDIOC_S_FMT ioctl. + + In 'Snapshot' mode the camera freezes its automatic exposure and colour + balance controls. + */ +#define PWC_FPS_SHIFT 16 +#define PWC_FPS_MASK 0x00FF0000 +#define PWC_FPS_FRMASK 0x003F0000 +#define PWC_FPS_SNAPSHOT 0x00400000 +#define PWC_QLT_MASK 0x03000000 +#define PWC_QLT_SHIFT 24 + + +/* structure for transferring x & y coordinates */ +struct pwc_coord +{ + int x, y; /* guess what */ + int size; /* size, or offset */ +}; + + +/* Used with VIDIOCPWCPROBE */ +struct pwc_probe +{ + char name[32]; + int type; +}; + +struct pwc_serial +{ + char serial[30]; /* String with serial number. Contains terminating 0 */ +}; + +/* pwc_whitebalance.mode values */ +#define PWC_WB_INDOOR 0 +#define PWC_WB_OUTDOOR 1 +#define PWC_WB_FL 2 +#define PWC_WB_MANUAL 3 +#define PWC_WB_AUTO 4 + +/* Used with VIDIOCPWC[SG]AWB (Auto White Balance). + Set mode to one of the PWC_WB_* values above. + *red and *blue are the respective gains of these colour components inside + the camera; range 0..65535 + When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read; + otherwise undefined. + 'read_red' and 'read_blue' are read-only. +*/ +struct pwc_whitebalance +{ + int mode; + int manual_red, manual_blue; /* R/W */ + int read_red, read_blue; /* R/O */ +}; + +/* + 'control_speed' and 'control_delay' are used in automatic whitebalance mode, + and tell the camera how fast it should react to changes in lighting, and + with how much delay. Valid values are 0..65535. +*/ +struct pwc_wb_speed +{ + int control_speed; + int control_delay; + +}; + +/* Used with VIDIOCPWC[SG]LED */ +struct pwc_leds +{ + int led_on; /* Led on-time; range = 0..25000 */ + int led_off; /* Led off-time; range = 0..25000 */ +}; + +/* Image size (used with GREALSIZE) */ +struct pwc_imagesize +{ + int width; + int height; +}; + +/* Defines and structures for Motorized Pan & Tilt */ +#define PWC_MPT_PAN 0x01 +#define PWC_MPT_TILT 0x02 +#define PWC_MPT_TIMEOUT 0x04 /* for status */ + +/* Set angles; when absolute != 0, the angle is absolute and the + driver calculates the relative offset for you. This can only + be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns + absolute angles. + */ +struct pwc_mpt_angles +{ + int absolute; /* write-only */ + int pan; /* degrees * 100 */ + int tilt; /* degress * 100 */ +}; + +/* Range of angles of the camera, both horizontally and vertically. + */ +struct pwc_mpt_range +{ + int pan_min, pan_max; /* degrees * 100 */ + int tilt_min, tilt_max; +}; + +struct pwc_mpt_status +{ + int status; + int time_pan; + int time_tilt; +}; + + +/* This is used for out-of-kernel decompression. With it, you can get + all the necessary information to initialize and use the decompressor + routines in standalone applications. + */ +struct pwc_video_command +{ + int type; /* camera type (645, 675, 730, etc.) */ + int release; /* release number */ + + int size; /* one of PSZ_* */ + int alternate; + int command_len; /* length of USB video command */ + unsigned char command_buf[13]; /* Actual USB video command */ + int bandlength; /* >0 = compressed */ + int frame_size; /* Size of one (un)compressed frame */ +}; + +/* Flags for PWCX subroutines. Not all modules honour all flags. */ +#define PWCX_FLAG_PLANAR 0x0001 +#define PWCX_FLAG_BAYER 0x0008 + + +/* IOCTL definitions */ + + /* Restore user settings */ +#define VIDIOCPWCRUSER _IO('v', 192) + /* Save user settings */ +#define VIDIOCPWCSUSER _IO('v', 193) + /* Restore factory settings */ +#define VIDIOCPWCFACTORY _IO('v', 194) + + /* You can manipulate the compression factor. A compression preference of 0 + means use uncompressed modes when available; 1 is low compression, 2 is + medium and 3 is high compression preferred. Of course, the higher the + compression, the lower the bandwidth used but more chance of artefacts + in the image. The driver automatically chooses a higher compression when + the preferred mode is not available. + */ + /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */ +#define VIDIOCPWCSCQUAL _IOW('v', 195, int) + /* Get preferred compression quality */ +#define VIDIOCPWCGCQUAL _IOR('v', 195, int) + + +/* Retrieve serial number of camera */ +#define VIDIOCPWCGSERIAL _IOR('v', 198, struct pwc_serial) + + /* This is a probe function; since so many devices are supported, it + becomes difficult to include all the names in programs that want to + check for the enhanced Philips stuff. So in stead, try this PROBE; + it returns a structure with the original name, and the corresponding + Philips type. + To use, fill the structure with zeroes, call PROBE and if that succeeds, + compare the name with that returned from VIDIOCGCAP; they should be the + same. If so, you can be assured it is a Philips (OEM) cam and the type + is valid. + */ +#define VIDIOCPWCPROBE _IOR('v', 199, struct pwc_probe) + + /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */ +#define VIDIOCPWCSAGC _IOW('v', 200, int) + /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */ +#define VIDIOCPWCGAGC _IOR('v', 200, int) + /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */ +#define VIDIOCPWCSSHUTTER _IOW('v', 201, int) + + /* Color compensation (Auto White Balance) */ +#define VIDIOCPWCSAWB _IOW('v', 202, struct pwc_whitebalance) +#define VIDIOCPWCGAWB _IOR('v', 202, struct pwc_whitebalance) + + /* Auto WB speed */ +#define VIDIOCPWCSAWBSPEED _IOW('v', 203, struct pwc_wb_speed) +#define VIDIOCPWCGAWBSPEED _IOR('v', 203, struct pwc_wb_speed) + + /* LEDs on/off/blink; int range 0..65535 */ +#define VIDIOCPWCSLED _IOW('v', 205, struct pwc_leds) +#define VIDIOCPWCGLED _IOR('v', 205, struct pwc_leds) + + /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */ +#define VIDIOCPWCSCONTOUR _IOW('v', 206, int) +#define VIDIOCPWCGCONTOUR _IOR('v', 206, int) + + /* Backlight compensation; 0 = off, otherwise on */ +#define VIDIOCPWCSBACKLIGHT _IOW('v', 207, int) +#define VIDIOCPWCGBACKLIGHT _IOR('v', 207, int) + + /* Flickerless mode; = 0 off, otherwise on */ +#define VIDIOCPWCSFLICKER _IOW('v', 208, int) +#define VIDIOCPWCGFLICKER _IOR('v', 208, int) + + /* Dynamic noise reduction; 0 off, 3 = high noise reduction */ +#define VIDIOCPWCSDYNNOISE _IOW('v', 209, int) +#define VIDIOCPWCGDYNNOISE _IOR('v', 209, int) + + /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */ +#define VIDIOCPWCGREALSIZE _IOR('v', 210, struct pwc_imagesize) + + /* Motorized pan & tilt functions */ +#define VIDIOCPWCMPTRESET _IOW('v', 211, int) +#define VIDIOCPWCMPTGRANGE _IOR('v', 211, struct pwc_mpt_range) +#define VIDIOCPWCMPTSANGLE _IOW('v', 212, struct pwc_mpt_angles) +#define VIDIOCPWCMPTGANGLE _IOR('v', 212, struct pwc_mpt_angles) +#define VIDIOCPWCMPTSTATUS _IOR('v', 213, struct pwc_mpt_status) + + /* Get the USB set-video command; needed for initializing libpwcx */ +#define VIDIOCPWCGVIDCMD _IOR('v', 215, struct pwc_video_command) +struct pwc_table_init_buffer { + int len; + char *buffer; + +}; +#define VIDIOCPWCGVIDTABLE _IOR('v', 216, struct pwc_table_init_buffer) + +/* + * This is private command used when communicating with v4l2. + * In the future all private ioctl will be remove/replace to + * use interface offer by v4l2. + */ + +#define V4L2_CID_PRIVATE_SAVE_USER (V4L2_CID_PRIVATE_BASE + 0) +#define V4L2_CID_PRIVATE_RESTORE_USER (V4L2_CID_PRIVATE_BASE + 1) +#define V4L2_CID_PRIVATE_RESTORE_FACTORY (V4L2_CID_PRIVATE_BASE + 2) +#define V4L2_CID_PRIVATE_COLOUR_MODE (V4L2_CID_PRIVATE_BASE + 3) +#define V4L2_CID_PRIVATE_AUTOCONTOUR (V4L2_CID_PRIVATE_BASE + 4) +#define V4L2_CID_PRIVATE_CONTOUR (V4L2_CID_PRIVATE_BASE + 5) +#define V4L2_CID_PRIVATE_BACKLIGHT (V4L2_CID_PRIVATE_BASE + 6) +#define V4L2_CID_PRIVATE_FLICKERLESS (V4L2_CID_PRIVATE_BASE + 7) +#define V4L2_CID_PRIVATE_NOISE_REDUCTION (V4L2_CID_PRIVATE_BASE + 8) + +struct pwc_raw_frame { + __le16 type; /* type of the webcam */ + __le16 vbandlength; /* Size of 4lines compressed (used by the decompressor) */ + __u8 cmd[4]; /* the four byte of the command (in case of nala, + only the first 3 bytes is filled) */ + __u8 rawframe[0]; /* frame_size = H/4*vbandlength */ +} __attribute__ ((packed)); + + +#endif diff --git a/include/media/tvp5150.h b/include/media/tvp5150.h new file mode 100644 index 000000000..72bd2a2b8 --- /dev/null +++ b/include/media/tvp5150.h @@ -0,0 +1,34 @@ +/* + tvp5150.h - definition for tvp5150 inputs + + Copyright (C) 2006 Hans Verkuil (hverkuil@xs4all.nl) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _TVP5150_H_ +#define _TVP5150_H_ + +/* TVP5150 HW inputs */ +#define TVP5150_COMPOSITE0 0 +#define TVP5150_COMPOSITE1 1 +#define TVP5150_SVIDEO 2 + +/* TVP5150 HW outputs */ +#define TVP5150_NORMAL 0 +#define TVP5150_BLACK_SCREEN 1 + +#endif + diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h new file mode 100644 index 000000000..810462f8a --- /dev/null +++ b/include/media/v4l2-dev.h @@ -0,0 +1,378 @@ +/* + * + * V 4 L 2 D R I V E R H E L P E R A P I + * + * Moved from videodev2.h + * + * Some commonly needed functions for drivers (v4l2-common.o module) + */ +#ifndef _V4L2_DEV_H +#define _V4L2_DEV_H + +#define OBSOLETE_OWNER 1 /* to be removed soon */ + +#include <linux/poll.h> +#include <linux/fs.h> +#include <linux/device.h> +#include <linux/mutex.h> +#include <linux/compiler.h> /* need __user */ +#ifdef CONFIG_VIDEO_V4L1_COMPAT +#include <linux/videodev.h> +#else +#include <linux/videodev2.h> +#endif + +#include <linux/fs.h> + +#define VIDEO_MAJOR 81 +/* Minor device allocation */ +#define MINOR_VFL_TYPE_GRABBER_MIN 0 +#define MINOR_VFL_TYPE_GRABBER_MAX 63 +#define MINOR_VFL_TYPE_RADIO_MIN 64 +#define MINOR_VFL_TYPE_RADIO_MAX 127 +#define MINOR_VFL_TYPE_VTX_MIN 192 +#define MINOR_VFL_TYPE_VTX_MAX 223 +#define MINOR_VFL_TYPE_VBI_MIN 224 +#define MINOR_VFL_TYPE_VBI_MAX 255 + +#define VFL_TYPE_GRABBER 0 +#define VFL_TYPE_VBI 1 +#define VFL_TYPE_RADIO 2 +#define VFL_TYPE_VTX 3 + +/* Video standard functions */ +extern unsigned int v4l2_video_std_fps(struct v4l2_standard *vs); +extern int v4l2_video_std_construct(struct v4l2_standard *vs, + int id, char *name); + +/* prority handling */ +struct v4l2_prio_state { + atomic_t prios[4]; +}; +int v4l2_prio_init(struct v4l2_prio_state *global); +int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, + enum v4l2_priority new); +int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local); +int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local); +enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global); +int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local); + +/* names for fancy debug output */ +extern char *v4l2_field_names[]; +extern char *v4l2_type_names[]; + +/* Compatibility layer interface -- v4l1-compat module */ +typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file, + unsigned int cmd, void *arg); +#ifdef CONFIG_VIDEO_V4L1_COMPAT +int v4l_compat_translate_ioctl(struct inode *inode, struct file *file, + int cmd, void *arg, v4l2_kioctl driver_ioctl); +#else +#define v4l_compat_translate_ioctl(inode,file,cmd,arg,ioctl) -EINVAL +#endif + +/* 32 Bits compatibility layer for 64 bits processors */ +extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd, + unsigned long arg); + +/* + * Newer version of video_device, handled by videodev2.c + * This version moves redundant code from video device code to + * the common handler + */ +struct v4l2_tvnorm { + char *name; + v4l2_std_id id; + + void *priv_data; +}; + +struct video_device +{ + /* device ops */ + const struct file_operations *fops; + + /* device info */ + struct device *dev; + char name[32]; + int type; /* v4l1 */ + int type2; /* v4l2 */ + int hardware; + int minor; + + int debug; /* Activates debug level*/ + + /* Video standard vars */ + int tvnormsize; /* Size of tvnorm array */ + v4l2_std_id current_norm; /* Current tvnorm */ + struct v4l2_tvnorm *tvnorms; + + /* callbacks */ + void (*release)(struct video_device *vfd); + + /* ioctl callbacks */ + + /* VIDIOC_QUERYCAP handler */ + int (*vidioc_querycap)(struct file *file, void *fh, struct v4l2_capability *cap); + + /* Priority handling */ + int (*vidioc_g_priority) (struct file *file, void *fh, + enum v4l2_priority *p); + int (*vidioc_s_priority) (struct file *file, void *fh, + enum v4l2_priority p); + + /* VIDIOC_ENUM_FMT handlers */ + int (*vidioc_enum_fmt_cap) (struct file *file, void *fh, + struct v4l2_fmtdesc *f); + int (*vidioc_enum_fmt_overlay) (struct file *file, void *fh, + struct v4l2_fmtdesc *f); + int (*vidioc_enum_fmt_vbi) (struct file *file, void *fh, + struct v4l2_fmtdesc *f); + int (*vidioc_enum_fmt_vbi_capture) (struct file *file, void *fh, + struct v4l2_fmtdesc *f); + int (*vidioc_enum_fmt_video_output)(struct file *file, void *fh, + struct v4l2_fmtdesc *f); + int (*vidioc_enum_fmt_vbi_output) (struct file *file, void *fh, + struct v4l2_fmtdesc *f); + int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh, + struct v4l2_fmtdesc *f); + + /* VIDIOC_G_FMT handlers */ + int (*vidioc_g_fmt_cap) (struct file *file, void *fh, + struct v4l2_format *f); + int (*vidioc_g_fmt_overlay) (struct file *file, void *fh, + struct v4l2_format *f); + int (*vidioc_g_fmt_vbi) (struct file *file, void *fh, + struct v4l2_format *f); + int (*vidioc_g_fmt_vbi_output) (struct file *file, void *fh, + struct v4l2_format *f); + int (*vidioc_g_fmt_vbi_capture)(struct file *file, void *fh, + struct v4l2_format *f); + int (*vidioc_g_fmt_video_output)(struct file *file, void *fh, + struct v4l2_format *f); + int (*vidioc_g_fmt_type_private)(struct file *file, void *fh, + struct v4l2_format *f); + + /* VIDIOC_S_FMT handlers */ + int (*vidioc_s_fmt_cap) (struct file *file, void *fh, + struct v4l2_format *f); + + int (*vidioc_s_fmt_overlay) (struct file *file, void *fh, + struct v4l2_format *f); + int (*vidioc_s_fmt_vbi) (struct file *file, void *fh, + struct v4l2_format *f); + int (*vidioc_s_fmt_vbi_output) (struct file *file, void *fh, + struct v4l2_format *f); + int (*vidioc_s_fmt_vbi_capture)(struct file *file, void *fh, + struct v4l2_format *f); + int (*vidioc_s_fmt_video_output)(struct file *file, void *fh, + struct v4l2_format *f); + int (*vidioc_s_fmt_type_private)(struct file *file, void *fh, + struct v4l2_format *f); + + /* VIDIOC_TRY_FMT handlers */ + int (*vidioc_try_fmt_cap) (struct file *file, void *fh, + struct v4l2_format *f); + int (*vidioc_try_fmt_overlay) (struct file *file, void *fh, + struct v4l2_format *f); + int (*vidioc_try_fmt_vbi) (struct file *file, void *fh, + struct v4l2_format *f); + int (*vidioc_try_fmt_vbi_output) (struct file *file, void *fh, + struct v4l2_format *f); + int (*vidioc_try_fmt_vbi_capture)(struct file *file, void *fh, + struct v4l2_format *f); + int (*vidioc_try_fmt_video_output)(struct file *file, void *fh, + struct v4l2_format *f); + int (*vidioc_try_fmt_type_private)(struct file *file, void *fh, + struct v4l2_format *f); + + /* Buffer handlers */ + int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b); + int (*vidioc_querybuf)(struct file *file, void *fh, struct v4l2_buffer *b); + int (*vidioc_qbuf) (struct file *file, void *fh, struct v4l2_buffer *b); + int (*vidioc_dqbuf) (struct file *file, void *fh, struct v4l2_buffer *b); + + + int (*vidioc_overlay) (struct file *file, void *fh, unsigned int i); +#ifdef CONFIG_VIDEO_V4L1_COMPAT + /* buffer type is struct vidio_mbuf * */ + int (*vidiocgmbuf) (struct file *file, void *fh, struct video_mbuf *p); +#endif + int (*vidioc_g_fbuf) (struct file *file, void *fh, + struct v4l2_framebuffer *a); + int (*vidioc_s_fbuf) (struct file *file, void *fh, + struct v4l2_framebuffer *a); + + /* Stream on/off */ + int (*vidioc_streamon) (struct file *file, void *fh, enum v4l2_buf_type i); + int (*vidioc_streamoff)(struct file *file, void *fh, enum v4l2_buf_type i); + + /* Standard handling + G_STD and ENUMSTD are handled by videodev.c + */ + int (*vidioc_s_std) (struct file *file, void *fh, v4l2_std_id a); + int (*vidioc_querystd) (struct file *file, void *fh, v4l2_std_id *a); + + /* Input handling */ + int (*vidioc_enum_input)(struct file *file, void *fh, + struct v4l2_input *inp); + int (*vidioc_g_input) (struct file *file, void *fh, unsigned int *i); + int (*vidioc_s_input) (struct file *file, void *fh, unsigned int i); + + /* Output handling */ + int (*vidioc_enumoutput) (struct file *file, void *fh, + struct v4l2_output *a); + int (*vidioc_g_output) (struct file *file, void *fh, unsigned int *i); + int (*vidioc_s_output) (struct file *file, void *fh, unsigned int i); + + /* Control handling */ + int (*vidioc_queryctrl) (struct file *file, void *fh, + struct v4l2_queryctrl *a); + int (*vidioc_g_ctrl) (struct file *file, void *fh, + struct v4l2_control *a); + int (*vidioc_s_ctrl) (struct file *file, void *fh, + struct v4l2_control *a); + int (*vidioc_g_ext_ctrls) (struct file *file, void *fh, + struct v4l2_ext_controls *a); + int (*vidioc_s_ext_ctrls) (struct file *file, void *fh, + struct v4l2_ext_controls *a); + int (*vidioc_try_ext_ctrls) (struct file *file, void *fh, + struct v4l2_ext_controls *a); + int (*vidioc_querymenu) (struct file *file, void *fh, + struct v4l2_querymenu *a); + + /* Audio ioctls */ + int (*vidioc_enumaudio) (struct file *file, void *fh, + struct v4l2_audio *a); + int (*vidioc_g_audio) (struct file *file, void *fh, + struct v4l2_audio *a); + int (*vidioc_s_audio) (struct file *file, void *fh, + struct v4l2_audio *a); + + /* Audio out ioctls */ + int (*vidioc_enumaudout) (struct file *file, void *fh, + struct v4l2_audioout *a); + int (*vidioc_g_audout) (struct file *file, void *fh, + struct v4l2_audioout *a); + int (*vidioc_s_audout) (struct file *file, void *fh, + struct v4l2_audioout *a); + int (*vidioc_g_modulator) (struct file *file, void *fh, + struct v4l2_modulator *a); + int (*vidioc_s_modulator) (struct file *file, void *fh, + struct v4l2_modulator *a); + /* Crop ioctls */ + int (*vidioc_cropcap) (struct file *file, void *fh, + struct v4l2_cropcap *a); + int (*vidioc_g_crop) (struct file *file, void *fh, + struct v4l2_crop *a); + int (*vidioc_s_crop) (struct file *file, void *fh, + struct v4l2_crop *a); + /* Compression ioctls */ + int (*vidioc_g_mpegcomp) (struct file *file, void *fh, + struct v4l2_mpeg_compression *a); + int (*vidioc_s_mpegcomp) (struct file *file, void *fh, + struct v4l2_mpeg_compression *a); + int (*vidioc_g_jpegcomp) (struct file *file, void *fh, + struct v4l2_jpegcompression *a); + int (*vidioc_s_jpegcomp) (struct file *file, void *fh, + struct v4l2_jpegcompression *a); + + /* Stream type-dependent parameter ioctls */ + int (*vidioc_g_parm) (struct file *file, void *fh, + struct v4l2_streamparm *a); + int (*vidioc_s_parm) (struct file *file, void *fh, + struct v4l2_streamparm *a); + + /* Tuner ioctls */ + int (*vidioc_g_tuner) (struct file *file, void *fh, + struct v4l2_tuner *a); + int (*vidioc_s_tuner) (struct file *file, void *fh, + struct v4l2_tuner *a); + int (*vidioc_g_frequency) (struct file *file, void *fh, + struct v4l2_frequency *a); + int (*vidioc_s_frequency) (struct file *file, void *fh, + struct v4l2_frequency *a); + + /* Sliced VBI cap */ + int (*vidioc_g_sliced_vbi_cap) (struct file *file, void *fh, + struct v4l2_sliced_vbi_cap *a); + + /* Log status ioctl */ + int (*vidioc_log_status) (struct file *file, void *fh); + + +#ifdef OBSOLETE_OWNER /* to be removed soon */ +/* obsolete -- fops->owner is used instead */ +struct module *owner; +/* dev->driver_data will be used instead some day. + * Use the video_{get|set}_drvdata() helper functions, + * so the switch over will be transparent for you. + * Or use {pci|usb}_{get|set}_drvdata() directly. */ +void *priv; +#endif + + /* for videodev.c intenal usage -- please don't touch */ + int users; /* video_exclusive_{open|close} ... */ + struct mutex lock; /* ... helper function uses these */ + struct class_device class_dev; /* sysfs */ +}; + +/* Version 2 functions */ +extern int video_register_device(struct video_device *vfd, int type, int nr); +void video_unregister_device(struct video_device *); +extern int video_ioctl2(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg); + +/* helper functions to alloc / release struct video_device, the + later can be used for video_device->release() */ +struct video_device *video_device_alloc(void); +void video_device_release(struct video_device *vfd); + +/* Include support for obsoleted stuff */ +extern int video_usercopy(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct inode *inode, struct file *file, + unsigned int cmd, void *arg)); + + +#ifdef CONFIG_VIDEO_V4L1_COMPAT +#include <linux/mm.h> + +extern struct video_device* video_devdata(struct file*); + +#define to_video_device(cd) container_of(cd, struct video_device, class_dev) +static inline int +video_device_create_file(struct video_device *vfd, + struct class_device_attribute *attr) +{ + int ret = class_device_create_file(&vfd->class_dev, attr); + if (ret < 0) + printk(KERN_WARNING "%s error: %d\n", __FUNCTION__, ret); + return ret; +} +static inline void +video_device_remove_file(struct video_device *vfd, + struct class_device_attribute *attr) +{ + class_device_remove_file(&vfd->class_dev, attr); +} + +#endif /* CONFIG_VIDEO_V4L1_COMPAT */ + +#ifdef OBSOLETE_OWNER /* to be removed soon */ +/* helper functions to access driver private data. */ +static inline void *video_get_drvdata(struct video_device *dev) +{ + return dev->priv; +} + +static inline void video_set_drvdata(struct video_device *dev, void *data) +{ + dev->priv = data; +} +#endif + +extern int video_exclusive_open(struct inode *inode, struct file *file); +extern int video_exclusive_release(struct inode *inode, struct file *file); + +#endif /* _V4L2_DEV_H */ diff --git a/include/mtd/Kbuild b/include/mtd/Kbuild new file mode 100644 index 000000000..13e7a3c6d --- /dev/null +++ b/include/mtd/Kbuild @@ -0,0 +1,6 @@ +header-y += inftl-user.h +header-y += jffs2-user.h +header-y += mtd-user.h +header-y += nftl-user.h + +unifdef-y += mtd-abi.h diff --git a/include/net/netdma.h b/include/net/netdma.h new file mode 100644 index 000000000..f28c6e064 --- /dev/null +++ b/include/net/netdma.h @@ -0,0 +1,43 @@ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ +#ifndef NETDMA_H +#define NETDMA_H +#ifdef CONFIG_NET_DMA +#include <linux/dmaengine.h> +#include <linux/skbuff.h> + +static inline struct dma_chan *get_softnet_dma(void) +{ + struct dma_chan *chan; + rcu_read_lock(); + chan = rcu_dereference(__get_cpu_var(softnet_data).net_dma); + if (chan) + dma_chan_get(chan); + rcu_read_unlock(); + return chan; +} + +int dma_skb_copy_datagram_iovec(struct dma_chan* chan, + struct sk_buff *skb, int offset, struct iovec *to, + size_t len, struct dma_pinned_list *pinned_list); + +#endif /* CONFIG_NET_DMA */ +#endif /* NETDMA_H */ diff --git a/include/net/netevent.h b/include/net/netevent.h new file mode 100644 index 000000000..e5d216241 --- /dev/null +++ b/include/net/netevent.h @@ -0,0 +1,33 @@ +#ifndef _NET_EVENT_H +#define _NET_EVENT_H + +/* + * Generic netevent notifiers + * + * Authors: + * Tom Tucker <tom@opengridcomputing.com> + * Steve Wise <swise@opengridcomputing.com> + * + * Changes: + */ +#ifdef __KERNEL__ + +#include <net/dst.h> + +struct netevent_redirect { + struct dst_entry *old; + struct dst_entry *new; +}; + +enum netevent_notif_type { + NETEVENT_NEIGH_UPDATE = 1, /* arg is struct neighbour ptr */ + NETEVENT_PMTU_UPDATE, /* arg is struct dst_entry ptr */ + NETEVENT_REDIRECT, /* arg is struct netevent_redirect ptr */ +}; + +extern int register_netevent_notifier(struct notifier_block *nb); +extern int unregister_netevent_notifier(struct notifier_block *nb); +extern int call_netevent_notifiers(unsigned long val, void *v); + +#endif +#endif diff --git a/include/rdma/Kbuild b/include/rdma/Kbuild new file mode 100644 index 000000000..e7c043216 --- /dev/null +++ b/include/rdma/Kbuild @@ -0,0 +1 @@ +header-y += ib_user_mad.h diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h new file mode 100644 index 000000000..0ff673989 --- /dev/null +++ b/include/rdma/ib_addr.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2005 Voltaire Inc. All rights reserved. + * Copyright (c) 2005 Intel Corporation. All rights reserved. + * + * This Software is licensed under one of the following licenses: + * + * 1) under the terms of the "Common Public License 1.0" a copy of which is + * available from the Open Source Initiative, see + * http://www.opensource.org/licenses/cpl.php. + * + * 2) under the terms of the "The BSD License" a copy of which is + * available from the Open Source Initiative, see + * http://www.opensource.org/licenses/bsd-license.php. + * + * 3) under the terms of the "GNU General Public License (GPL) Version 2" a + * copy of which is available from the Open Source Initiative, see + * http://www.opensource.org/licenses/gpl-license.php. + * + * Licensee has the right to choose one of the above licenses. + * + * Redistributions of source code must retain the above copyright + * notice and one of the license notices. + * + * Redistributions in binary form must reproduce both the above copyright + * notice, one of the license notices in the documentation + * and/or other materials provided with the distribution. + * + */ + +#if !defined(IB_ADDR_H) +#define IB_ADDR_H + +#include <linux/in.h> +#include <linux/in6.h> +#include <linux/netdevice.h> +#include <linux/socket.h> +#include <rdma/ib_verbs.h> + +struct rdma_dev_addr { + unsigned char src_dev_addr[MAX_ADDR_LEN]; + unsigned char dst_dev_addr[MAX_ADDR_LEN]; + unsigned char broadcast[MAX_ADDR_LEN]; + enum ib_node_type dev_type; +}; + +/** + * rdma_translate_ip - Translate a local IP address to an RDMA hardware + * address. + */ +int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr); + +/** + * rdma_resolve_ip - Resolve source and destination IP addresses to + * RDMA hardware addresses. + * @src_addr: An optional source address to use in the resolution. If a + * source address is not provided, a usable address will be returned via + * the callback. + * @dst_addr: The destination address to resolve. + * @addr: A reference to a data location that will receive the resolved + * addresses. The data location must remain valid until the callback has + * been invoked. + * @timeout_ms: Amount of time to wait for the address resolution to complete. + * @callback: Call invoked once address resolution has completed, timed out, + * or been canceled. A status of 0 indicates success. + * @context: User-specified context associated with the call. + */ +int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr, + struct rdma_dev_addr *addr, int timeout_ms, + void (*callback)(int status, struct sockaddr *src_addr, + struct rdma_dev_addr *addr, void *context), + void *context); + +void rdma_addr_cancel(struct rdma_dev_addr *addr); + +static inline int ip_addr_size(struct sockaddr *addr) +{ + return addr->sa_family == AF_INET6 ? + sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); +} + +static inline u16 ib_addr_get_pkey(struct rdma_dev_addr *dev_addr) +{ + return ((u16)dev_addr->broadcast[8] << 8) | (u16)dev_addr->broadcast[9]; +} + +static inline void ib_addr_set_pkey(struct rdma_dev_addr *dev_addr, u16 pkey) +{ + dev_addr->broadcast[8] = pkey >> 8; + dev_addr->broadcast[9] = (unsigned char) pkey; +} + +static inline void ib_addr_get_sgid(struct rdma_dev_addr *dev_addr, + union ib_gid *gid) +{ + memcpy(gid, dev_addr->src_dev_addr + 4, sizeof *gid); +} + +static inline void ib_addr_set_sgid(struct rdma_dev_addr *dev_addr, + union ib_gid *gid) +{ + memcpy(dev_addr->src_dev_addr + 4, gid, sizeof *gid); +} + +static inline void ib_addr_get_dgid(struct rdma_dev_addr *dev_addr, + union ib_gid *gid) +{ + memcpy(gid, dev_addr->dst_dev_addr + 4, sizeof *gid); +} + +static inline void ib_addr_set_dgid(struct rdma_dev_addr *dev_addr, + union ib_gid *gid) +{ + memcpy(dev_addr->dst_dev_addr + 4, gid, sizeof *gid); +} + +#endif /* IB_ADDR_H */ diff --git a/include/rdma/ib_marshall.h b/include/rdma/ib_marshall.h new file mode 100644 index 000000000..66bf4d7d0 --- /dev/null +++ b/include/rdma/ib_marshall.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2005 Intel Corporation. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#if !defined(IB_USER_MARSHALL_H) +#define IB_USER_MARSHALL_H + +#include <rdma/ib_verbs.h> +#include <rdma/ib_sa.h> +#include <rdma/ib_user_verbs.h> +#include <rdma/ib_user_sa.h> + +void ib_copy_qp_attr_to_user(struct ib_uverbs_qp_attr *dst, + struct ib_qp_attr *src); + +void ib_copy_path_rec_to_user(struct ib_user_path_rec *dst, + struct ib_sa_path_rec *src); + +void ib_copy_path_rec_from_user(struct ib_sa_path_rec *dst, + struct ib_user_path_rec *src); + +#endif /* IB_USER_MARSHALL_H */ diff --git a/include/rdma/ib_user_sa.h b/include/rdma/ib_user_sa.h new file mode 100644 index 000000000..659120157 --- /dev/null +++ b/include/rdma/ib_user_sa.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2005 Intel Corporation. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef IB_USER_SA_H +#define IB_USER_SA_H + +#include <linux/types.h> + +struct ib_user_path_rec { + __u8 dgid[16]; + __u8 sgid[16]; + __be16 dlid; + __be16 slid; + __u32 raw_traffic; + __be32 flow_label; + __u32 reversible; + __u32 mtu; + __be16 pkey; + __u8 hop_limit; + __u8 traffic_class; + __u8 numb_path; + __u8 sl; + __u8 mtu_selector; + __u8 rate_selector; + __u8 rate; + __u8 packet_life_time_selector; + __u8 packet_life_time; + __u8 preference; +}; + +#endif /* IB_USER_SA_H */ diff --git a/include/rdma/rdma_cm.h b/include/rdma/rdma_cm.h new file mode 100644 index 000000000..402c63d72 --- /dev/null +++ b/include/rdma/rdma_cm.h @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2005 Voltaire Inc. All rights reserved. + * Copyright (c) 2005 Intel Corporation. All rights reserved. + * + * This Software is licensed under one of the following licenses: + * + * 1) under the terms of the "Common Public License 1.0" a copy of which is + * available from the Open Source Initiative, see + * http://www.opensource.org/licenses/cpl.php. + * + * 2) under the terms of the "The BSD License" a copy of which is + * available from the Open Source Initiative, see + * http://www.opensource.org/licenses/bsd-license.php. + * + * 3) under the terms of the "GNU General Public License (GPL) Version 2" a + * copy of which is available from the Open Source Initiative, see + * http://www.opensource.org/licenses/gpl-license.php. + * + * Licensee has the right to choose one of the above licenses. + * + * Redistributions of source code must retain the above copyright + * notice and one of the license notices. + * + * Redistributions in binary form must reproduce both the above copyright + * notice, one of the license notices in the documentation + * and/or other materials provided with the distribution. + * + */ + +#if !defined(RDMA_CM_H) +#define RDMA_CM_H + +#include <linux/socket.h> +#include <linux/in6.h> +#include <rdma/ib_addr.h> +#include <rdma/ib_sa.h> + +/* + * Upon receiving a device removal event, users must destroy the associated + * RDMA identifier and release all resources allocated with the device. + */ +enum rdma_cm_event_type { + RDMA_CM_EVENT_ADDR_RESOLVED, + RDMA_CM_EVENT_ADDR_ERROR, + RDMA_CM_EVENT_ROUTE_RESOLVED, + RDMA_CM_EVENT_ROUTE_ERROR, + RDMA_CM_EVENT_CONNECT_REQUEST, + RDMA_CM_EVENT_CONNECT_RESPONSE, + RDMA_CM_EVENT_CONNECT_ERROR, + RDMA_CM_EVENT_UNREACHABLE, + RDMA_CM_EVENT_REJECTED, + RDMA_CM_EVENT_ESTABLISHED, + RDMA_CM_EVENT_DISCONNECTED, + RDMA_CM_EVENT_DEVICE_REMOVAL, +}; + +enum rdma_port_space { + RDMA_PS_SDP = 0x0001, + RDMA_PS_TCP = 0x0106, + RDMA_PS_UDP = 0x0111, + RDMA_PS_SCTP = 0x0183 +}; + +struct rdma_addr { + struct sockaddr src_addr; + u8 src_pad[sizeof(struct sockaddr_in6) - + sizeof(struct sockaddr)]; + struct sockaddr dst_addr; + u8 dst_pad[sizeof(struct sockaddr_in6) - + sizeof(struct sockaddr)]; + struct rdma_dev_addr dev_addr; +}; + +struct rdma_route { + struct rdma_addr addr; + struct ib_sa_path_rec *path_rec; + int num_paths; +}; + +struct rdma_cm_event { + enum rdma_cm_event_type event; + int status; + void *private_data; + u8 private_data_len; +}; + +struct rdma_cm_id; + +/** + * rdma_cm_event_handler - Callback used to report user events. + * + * Notes: Users may not call rdma_destroy_id from this callback to destroy + * the passed in id, or a corresponding listen id. Returning a + * non-zero value from the callback will destroy the passed in id. + */ +typedef int (*rdma_cm_event_handler)(struct rdma_cm_id *id, + struct rdma_cm_event *event); + +struct rdma_cm_id { + struct ib_device *device; + void *context; + struct ib_qp *qp; + rdma_cm_event_handler event_handler; + struct rdma_route route; + enum rdma_port_space ps; + u8 port_num; +}; + +/** + * rdma_create_id - Create an RDMA identifier. + * + * @event_handler: User callback invoked to report events associated with the + * returned rdma_id. + * @context: User specified context associated with the id. + * @ps: RDMA port space. + */ +struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler, + void *context, enum rdma_port_space ps); + +void rdma_destroy_id(struct rdma_cm_id *id); + +/** + * rdma_bind_addr - Bind an RDMA identifier to a source address and + * associated RDMA device, if needed. + * + * @id: RDMA identifier. + * @addr: Local address information. Wildcard values are permitted. + * + * This associates a source address with the RDMA identifier before calling + * rdma_listen. If a specific local address is given, the RDMA identifier will + * be bound to a local RDMA device. + */ +int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr); + +/** + * rdma_resolve_addr - Resolve destination and optional source addresses + * from IP addresses to an RDMA address. If successful, the specified + * rdma_cm_id will be bound to a local device. + * + * @id: RDMA identifier. + * @src_addr: Source address information. This parameter may be NULL. + * @dst_addr: Destination address information. + * @timeout_ms: Time to wait for resolution to complete. + */ +int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, + struct sockaddr *dst_addr, int timeout_ms); + +/** + * rdma_resolve_route - Resolve the RDMA address bound to the RDMA identifier + * into route information needed to establish a connection. + * + * This is called on the client side of a connection. + * Users must have first called rdma_resolve_addr to resolve a dst_addr + * into an RDMA address before calling this routine. + */ +int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms); + +/** + * rdma_create_qp - Allocate a QP and associate it with the specified RDMA + * identifier. + * + * QPs allocated to an rdma_cm_id will automatically be transitioned by the CMA + * through their states. + */ +int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd, + struct ib_qp_init_attr *qp_init_attr); + +/** + * rdma_destroy_qp - Deallocate the QP associated with the specified RDMA + * identifier. + * + * Users must destroy any QP associated with an RDMA identifier before + * destroying the RDMA ID. + */ +void rdma_destroy_qp(struct rdma_cm_id *id); + +/** + * rdma_init_qp_attr - Initializes the QP attributes for use in transitioning + * to a specified QP state. + * @id: Communication identifier associated with the QP attributes to + * initialize. + * @qp_attr: On input, specifies the desired QP state. On output, the + * mandatory and desired optional attributes will be set in order to + * modify the QP to the specified state. + * @qp_attr_mask: The QP attribute mask that may be used to transition the + * QP to the specified state. + * + * Users must set the @qp_attr->qp_state to the desired QP state. This call + * will set all required attributes for the given transition, along with + * known optional attributes. Users may override the attributes returned from + * this call before calling ib_modify_qp. + * + * Users that wish to have their QP automatically transitioned through its + * states can associate a QP with the rdma_cm_id by calling rdma_create_qp(). + */ +int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr, + int *qp_attr_mask); + +struct rdma_conn_param { + const void *private_data; + u8 private_data_len; + u8 responder_resources; + u8 initiator_depth; + u8 flow_control; + u8 retry_count; /* ignored when accepting */ + u8 rnr_retry_count; + /* Fields below ignored if a QP is created on the rdma_cm_id. */ + u8 srq; + u32 qp_num; + enum ib_qp_type qp_type; +}; + +/** + * rdma_connect - Initiate an active connection request. + * + * Users must have resolved a route for the rdma_cm_id to connect with + * by having called rdma_resolve_route before calling this routine. + */ +int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param); + +/** + * rdma_listen - This function is called by the passive side to + * listen for incoming connection requests. + * + * Users must have bound the rdma_cm_id to a local address by calling + * rdma_bind_addr before calling this routine. + */ +int rdma_listen(struct rdma_cm_id *id, int backlog); + +/** + * rdma_accept - Called to accept a connection request or response. + * @id: Connection identifier associated with the request. + * @conn_param: Information needed to establish the connection. This must be + * provided if accepting a connection request. If accepting a connection + * response, this parameter must be NULL. + * + * Typically, this routine is only called by the listener to accept a connection + * request. It must also be called on the active side of a connection if the + * user is performing their own QP transitions. + */ +int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param); + +/** + * rdma_reject - Called to reject a connection request or response. + */ +int rdma_reject(struct rdma_cm_id *id, const void *private_data, + u8 private_data_len); + +/** + * rdma_disconnect - This function disconnects the associated QP and + * transitions it into the error state. + */ +int rdma_disconnect(struct rdma_cm_id *id); + +#endif /* RDMA_CM_H */ + diff --git a/include/rdma/rdma_cm_ib.h b/include/rdma/rdma_cm_ib.h new file mode 100644 index 000000000..e8c3af180 --- /dev/null +++ b/include/rdma/rdma_cm_ib.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006 Intel Corporation. All rights reserved. + * + * This Software is licensed under one of the following licenses: + * + * 1) under the terms of the "Common Public License 1.0" a copy of which is + * available from the Open Source Initiative, see + * http://www.opensource.org/licenses/cpl.php. + * + * 2) under the terms of the "The BSD License" a copy of which is + * available from the Open Source Initiative, see + * http://www.opensource.org/licenses/bsd-license.php. + * + * 3) under the terms of the "GNU General Public License (GPL) Version 2" a + * copy of which is available from the Open Source Initiative, see + * http://www.opensource.org/licenses/gpl-license.php. + * + * Licensee has the right to choose one of the above licenses. + * + * Redistributions of source code must retain the above copyright + * notice and one of the license notices. + * + * Redistributions in binary form must reproduce both the above copyright + * notice, one of the license notices in the documentation + * and/or other materials provided with the distribution. + * + */ + +#if !defined(RDMA_CM_IB_H) +#define RDMA_CM_IB_H + +#include <rdma/rdma_cm.h> + +/** + * rdma_set_ib_paths - Manually sets the path records used to establish a + * connection. + * @id: Connection identifier associated with the request. + * @path_rec: Reference to the path record + * + * This call permits a user to specify routing information for rdma_cm_id's + * bound to Infiniband devices. It is called on the client side of a + * connection and replaces the call to rdma_resolve_route. + */ +int rdma_set_ib_paths(struct rdma_cm_id *id, + struct ib_sa_path_rec *path_rec, int num_paths); + +#endif /* RDMA_CM_IB_H */ diff --git a/include/scsi/Kbuild b/include/scsi/Kbuild new file mode 100644 index 000000000..744f85011 --- /dev/null +++ b/include/scsi/Kbuild @@ -0,0 +1,4 @@ +header-y += scsi.h + +unifdef-y += scsi_ioctl.h +unifdef-y += sg.h diff --git a/include/sound/Kbuild b/include/sound/Kbuild new file mode 100644 index 000000000..fd054a344 --- /dev/null +++ b/include/sound/Kbuild @@ -0,0 +1,10 @@ +header-y += asound_fm.h +header-y += hdsp.h +header-y += hdspm.h +header-y += sfnt_info.h +header-y += sscape_ioctl.h + +unifdef-y += asequencer.h +unifdef-y += asound.h +unifdef-y += emu10k1.h +unifdef-y += sb16_csp.h diff --git a/include/video/Kbuild b/include/video/Kbuild new file mode 100644 index 000000000..a14f9c045 --- /dev/null +++ b/include/video/Kbuild @@ -0,0 +1 @@ +unifdef-y += sisfb.h diff --git a/include/video/mbxfb.h b/include/video/mbxfb.h new file mode 100644 index 000000000..3bde0f5cd --- /dev/null +++ b/include/video/mbxfb.h @@ -0,0 +1,28 @@ +#ifndef __MBX_FB_H +#define __MBX_FB_H + +struct mbxfb_val { + unsigned int defval; + unsigned int min; + unsigned int max; +}; + +struct fb_info; + +struct mbxfb_platform_data { + /* Screen info */ + struct mbxfb_val xres; + struct mbxfb_val yres; + struct mbxfb_val bpp; + + /* Memory info */ + unsigned long memsize; /* if 0 use ODFB? */ + unsigned long timings1; + unsigned long timings2; + unsigned long timings3; + + int (*probe)(struct fb_info *fb); + int (*remove)(struct fb_info *fb); +}; + +#endif /* __MBX_FB_H */ diff --git a/include/xen/hvm.h b/include/xen/hvm.h new file mode 100644 index 000000000..97bb68a32 --- /dev/null +++ b/include/xen/hvm.h @@ -0,0 +1,24 @@ +/* Simple wrappers around HVM functions */ +#ifndef XEN_HVM_H__ +#define XEN_HVM_H__ + +#include <xen/interface/hvm/params.h> +#include <asm/hypercall.h> + +static inline unsigned long hvm_get_parameter(int idx) +{ + struct xen_hvm_param xhv; + int r; + + xhv.domid = DOMID_SELF; + xhv.index = idx; + r = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv); + if (r < 0) { + printk(KERN_ERR "cannot get hvm parameter %d: %d.\n", + idx, r); + return 0; + } + return xhv.value; +} + +#endif /* XEN_HVM_H__ */ diff --git a/include/xen/interface/arch-ia64.h b/include/xen/interface/arch-ia64.h new file mode 100644 index 000000000..98bda1d24 --- /dev/null +++ b/include/xen/interface/arch-ia64.h @@ -0,0 +1,448 @@ +/****************************************************************************** + * arch-ia64/hypervisor-if.h + * + * Guest OS interface to IA64 Xen. + */ + +#ifndef __HYPERVISOR_IF_IA64_H__ +#define __HYPERVISOR_IF_IA64_H__ + +/* Structural guest handles introduced in 0x00030201. */ +#if __XEN_INTERFACE_VERSION__ >= 0x00030201 +#define __DEFINE_XEN_GUEST_HANDLE(name, type) \ + typedef struct { type *p; } __guest_handle_ ## name +#else +#define __DEFINE_XEN_GUEST_HANDLE(name, type) \ + typedef type * __guest_handle_ ## name +#endif + +#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name) +#define XEN_GUEST_HANDLE(name) __guest_handle_ ## name +#define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0) +#ifdef __XEN_TOOLS__ +#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0) +#endif + +#ifndef __ASSEMBLY__ +/* Guest handles for primitive C types. */ +__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char); +__DEFINE_XEN_GUEST_HANDLE(uint, unsigned int); +__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long); +DEFINE_XEN_GUEST_HANDLE(char); +DEFINE_XEN_GUEST_HANDLE(int); +DEFINE_XEN_GUEST_HANDLE(long); +DEFINE_XEN_GUEST_HANDLE(void); + +typedef unsigned long xen_pfn_t; +DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); +#endif + +/* Arch specific VIRQs definition */ +#define VIRQ_ITC VIRQ_ARCH_0 /* V. Virtual itc timer */ + +/* Maximum number of virtual CPUs in multi-processor guests. */ +/* WARNING: before changing this, check that shared_info fits on a page */ +#define MAX_VIRT_CPUS 64 + +#ifndef __ASSEMBLY__ + +typedef unsigned long xen_ulong_t; + +#define GPFN_MEM (0UL << 56) /* Guest pfn is normal mem */ +#define GPFN_FRAME_BUFFER (1UL << 56) /* VGA framebuffer */ +#define GPFN_LOW_MMIO (2UL << 56) /* Low MMIO range */ +#define GPFN_PIB (3UL << 56) /* PIB base */ +#define GPFN_IOSAPIC (4UL << 56) /* IOSAPIC base */ +#define GPFN_LEGACY_IO (5UL << 56) /* Legacy I/O base */ +#define GPFN_GFW (6UL << 56) /* Guest Firmware */ +#define GPFN_HIGH_MMIO (7UL << 56) /* High MMIO range */ + +#define GPFN_IO_MASK (7UL << 56) /* Guest pfn is I/O type */ +#define GPFN_INV_MASK (31UL << 59) /* Guest pfn is invalid */ + +#define INVALID_MFN (~0UL) + +#define MEM_G (1UL << 30) +#define MEM_M (1UL << 20) + +#define MMIO_START (3 * MEM_G) +#define MMIO_SIZE (512 * MEM_M) + +#define VGA_IO_START 0xA0000UL +#define VGA_IO_SIZE 0x20000 + +#define LEGACY_IO_START (MMIO_START + MMIO_SIZE) +#define LEGACY_IO_SIZE (64*MEM_M) + +#define IO_PAGE_START (LEGACY_IO_START + LEGACY_IO_SIZE) +#define IO_PAGE_SIZE PAGE_SIZE + +#define STORE_PAGE_START (IO_PAGE_START + IO_PAGE_SIZE) +#define STORE_PAGE_SIZE PAGE_SIZE + +#define IO_SAPIC_START 0xfec00000UL +#define IO_SAPIC_SIZE 0x100000 + +#define PIB_START 0xfee00000UL +#define PIB_SIZE 0x200000 + +#define GFW_START (4*MEM_G -16*MEM_M) +#define GFW_SIZE (16*MEM_M) + +struct pt_fpreg { + union { + unsigned long bits[2]; + long double __dummy; /* force 16-byte alignment */ + } u; +}; + +struct cpu_user_regs { + /* The following registers are saved by SAVE_MIN: */ + unsigned long b6; /* scratch */ + unsigned long b7; /* scratch */ + + unsigned long ar_csd; /* used by cmp8xchg16 (scratch) */ + unsigned long ar_ssd; /* reserved for future use (scratch) */ + + unsigned long r8; /* scratch (return value register 0) */ + unsigned long r9; /* scratch (return value register 1) */ + unsigned long r10; /* scratch (return value register 2) */ + unsigned long r11; /* scratch (return value register 3) */ + + unsigned long cr_ipsr; /* interrupted task's psr */ + unsigned long cr_iip; /* interrupted task's instruction pointer */ + unsigned long cr_ifs; /* interrupted task's function state */ + + unsigned long ar_unat; /* interrupted task's NaT register (preserved) */ + unsigned long ar_pfs; /* prev function state */ + unsigned long ar_rsc; /* RSE configuration */ + /* The following two are valid only if cr_ipsr.cpl > 0: */ + unsigned long ar_rnat; /* RSE NaT */ + unsigned long ar_bspstore; /* RSE bspstore */ + + unsigned long pr; /* 64 predicate registers (1 bit each) */ + unsigned long b0; /* return pointer (bp) */ + unsigned long loadrs; /* size of dirty partition << 16 */ + + unsigned long r1; /* the gp pointer */ + unsigned long r12; /* interrupted task's memory stack pointer */ + unsigned long r13; /* thread pointer */ + + unsigned long ar_fpsr; /* floating point status (preserved) */ + unsigned long r15; /* scratch */ + + /* The remaining registers are NOT saved for system calls. */ + + unsigned long r14; /* scratch */ + unsigned long r2; /* scratch */ + unsigned long r3; /* scratch */ + unsigned long r16; /* scratch */ + unsigned long r17; /* scratch */ + unsigned long r18; /* scratch */ + unsigned long r19; /* scratch */ + unsigned long r20; /* scratch */ + unsigned long r21; /* scratch */ + unsigned long r22; /* scratch */ + unsigned long r23; /* scratch */ + unsigned long r24; /* scratch */ + unsigned long r25; /* scratch */ + unsigned long r26; /* scratch */ + unsigned long r27; /* scratch */ + unsigned long r28; /* scratch */ + unsigned long r29; /* scratch */ + unsigned long r30; /* scratch */ + unsigned long r31; /* scratch */ + unsigned long ar_ccv; /* compare/exchange value (scratch) */ + + /* + * Floating point registers that the kernel considers scratch: + */ + struct pt_fpreg f6; /* scratch */ + struct pt_fpreg f7; /* scratch */ + struct pt_fpreg f8; /* scratch */ + struct pt_fpreg f9; /* scratch */ + struct pt_fpreg f10; /* scratch */ + struct pt_fpreg f11; /* scratch */ + unsigned long r4; /* preserved */ + unsigned long r5; /* preserved */ + unsigned long r6; /* preserved */ + unsigned long r7; /* preserved */ + unsigned long eml_unat; /* used for emulating instruction */ + unsigned long pad0; /* alignment pad */ + +}; +typedef struct cpu_user_regs cpu_user_regs_t; + +union vac { + unsigned long value; + struct { + int a_int:1; + int a_from_int_cr:1; + int a_to_int_cr:1; + int a_from_psr:1; + int a_from_cpuid:1; + int a_cover:1; + int a_bsw:1; + long reserved:57; + }; +}; +typedef union vac vac_t; + +union vdc { + unsigned long value; + struct { + int d_vmsw:1; + int d_extint:1; + int d_ibr_dbr:1; + int d_pmc:1; + int d_to_pmd:1; + int d_itm:1; + long reserved:58; + }; +}; +typedef union vdc vdc_t; + +struct mapped_regs { + union vac vac; + union vdc vdc; + unsigned long virt_env_vaddr; + unsigned long reserved1[29]; + unsigned long vhpi; + unsigned long reserved2[95]; + union { + unsigned long vgr[16]; + unsigned long bank1_regs[16]; // bank1 regs (r16-r31) when bank0 active + }; + union { + unsigned long vbgr[16]; + unsigned long bank0_regs[16]; // bank0 regs (r16-r31) when bank1 active + }; + unsigned long vnat; + unsigned long vbnat; + unsigned long vcpuid[5]; + unsigned long reserved3[11]; + unsigned long vpsr; + unsigned long vpr; + unsigned long reserved4[76]; + union { + unsigned long vcr[128]; + struct { + unsigned long dcr; // CR0 + unsigned long itm; + unsigned long iva; + unsigned long rsv1[5]; + unsigned long pta; // CR8 + unsigned long rsv2[7]; + unsigned long ipsr; // CR16 + unsigned long isr; + unsigned long rsv3; + unsigned long iip; + unsigned long ifa; + unsigned long itir; + unsigned long iipa; + unsigned long ifs; + unsigned long iim; // CR24 + unsigned long iha; + unsigned long rsv4[38]; + unsigned long lid; // CR64 + unsigned long ivr; + unsigned long tpr; + unsigned long eoi; + unsigned long irr[4]; + unsigned long itv; // CR72 + unsigned long pmv; + unsigned long cmcv; + unsigned long rsv5[5]; + unsigned long lrr0; // CR80 + unsigned long lrr1; + unsigned long rsv6[46]; + }; + }; + union { + unsigned long reserved5[128]; + struct { + unsigned long precover_ifs; + unsigned long unat; // not sure if this is needed until NaT arch is done + int interrupt_collection_enabled; // virtual psr.ic + /* virtual interrupt deliverable flag is evtchn_upcall_mask in + * shared info area now. interrupt_mask_addr is the address + * of evtchn_upcall_mask for current vcpu + */ + unsigned char *interrupt_mask_addr; + int pending_interruption; + int incomplete_regframe; // see SDM vol2 6.8 + unsigned char vpsr_pp; + unsigned char reserved5_2[7]; + unsigned long reserved5_1[3]; + int metaphysical_mode; // 1 = use metaphys mapping, 0 = use virtual + int banknum; // 0 or 1, which virtual register bank is active + unsigned long rrs[8]; // region registers + unsigned long krs[8]; // kernel registers + unsigned long pkrs[8]; // protection key registers + unsigned long tmp[8]; // temp registers (e.g. for hyperprivops) + }; + }; +}; +typedef struct mapped_regs mapped_regs_t; + +struct vpd { + struct mapped_regs vpd_low; + unsigned long reserved6[3456]; + unsigned long vmm_avail[128]; + unsigned long reserved7[4096]; +}; +typedef struct vpd vpd_t; + +struct arch_vcpu_info { +}; +typedef struct arch_vcpu_info arch_vcpu_info_t; + +struct arch_shared_info { + /* PFN of the start_info page. */ + unsigned long start_info_pfn; + + /* Interrupt vector for event channel. */ + int evtchn_vector; + + uint64_t pad[32]; +}; +typedef struct arch_shared_info arch_shared_info_t; + +typedef unsigned long xen_callback_t; + +struct ia64_tr_entry { + unsigned long pte; + unsigned long itir; + unsigned long vadr; + unsigned long rid; +}; + +struct vcpu_extra_regs { + struct ia64_tr_entry itrs[8]; + struct ia64_tr_entry dtrs[8]; + unsigned long iva; + unsigned long dcr; + unsigned long event_callback_ip; +}; + +struct vcpu_guest_context { +#define VGCF_EXTRA_REGS (1<<1) /* Get/Set extra regs. */ + unsigned long flags; /* VGCF_* flags */ + + struct cpu_user_regs user_regs; + struct vcpu_extra_regs extra_regs; + unsigned long privregs_pfn; +}; +typedef struct vcpu_guest_context vcpu_guest_context_t; +DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); + +// dom0 vp op +#define __HYPERVISOR_ia64_dom0vp_op __HYPERVISOR_arch_0 +#define IA64_DOM0VP_ioremap 0 // map io space in machine + // address to dom0 physical + // address space. + // currently physical + // assignedg address equals to + // machine address +#define IA64_DOM0VP_phystomach 1 // convert a pseudo physical + // page frame number + // to the corresponding + // machine page frame number. + // if no page is assigned, + // INVALID_MFN or GPFN_INV_MASK + // is returned depending on + // domain's non-vti/vti mode. +#define IA64_DOM0VP_machtophys 3 // convert a machine page + // frame number + // to the corresponding + // pseudo physical page frame + // number of the caller domain +#define IA64_DOM0VP_zap_physmap 17 // unmap and free pages + // contained in the specified + // pseudo physical region +#define IA64_DOM0VP_add_physmap 18 // assigne machine page frane + // to dom0's pseudo physical + // address space. +// flags for page assignement to pseudo physical address space +#define _ASSIGN_readonly 0 +#define ASSIGN_readonly (1UL << _ASSIGN_readonly) +#define ASSIGN_writable (0UL << _ASSIGN_readonly) // dummy flag +/* Internal only: memory attribute must be WC/UC/UCE. */ +#define _ASSIGN_nocache 1 +#define ASSIGN_nocache (1UL << _ASSIGN_nocache) + +/* This structure has the same layout of struct ia64_boot_param, defined in + <asm/system.h>. It is redefined here to ease use. */ +struct xen_ia64_boot_param { + unsigned long command_line; /* physical address of cmd line args */ + unsigned long efi_systab; /* physical address of EFI system table */ + unsigned long efi_memmap; /* physical address of EFI memory map */ + unsigned long efi_memmap_size; /* size of EFI memory map */ + unsigned long efi_memdesc_size; /* size of an EFI memory map descriptor */ + unsigned int efi_memdesc_version; /* memory descriptor version */ + struct { + unsigned short num_cols; /* number of columns on console. */ + unsigned short num_rows; /* number of rows on console. */ + unsigned short orig_x; /* cursor's x position */ + unsigned short orig_y; /* cursor's y position */ + } console_info; + unsigned long fpswa; /* physical address of the fpswa interface */ + unsigned long initrd_start; + unsigned long initrd_size; + unsigned long domain_start; /* va where the boot time domain begins */ + unsigned long domain_size; /* how big is the boot domain */ +}; + +#endif /* !__ASSEMBLY__ */ + +/* Address of shared_info in domain virtual space. + This is the default address, for compatibility only. */ +#define XSI_BASE 0xf100000000000000 + +/* Size of the shared_info area (this is not related to page size). */ +#define XSI_SHIFT 14 +#define XSI_SIZE (1 << XSI_SHIFT) +/* Log size of mapped_regs area (64 KB - only 4KB is used). */ +#define XMAPPEDREGS_SHIFT 12 +/* Offset of XASI (Xen arch shared info) wrt XSI_BASE. */ +#define XMAPPEDREGS_OFS XSI_SIZE + +/* Hyperprivops. */ +#define HYPERPRIVOP_RFI 0x1 +#define HYPERPRIVOP_RSM_DT 0x2 +#define HYPERPRIVOP_SSM_DT 0x3 +#define HYPERPRIVOP_COVER 0x4 +#define HYPERPRIVOP_ITC_D 0x5 +#define HYPERPRIVOP_ITC_I 0x6 +#define HYPERPRIVOP_SSM_I 0x7 +#define HYPERPRIVOP_GET_IVR 0x8 +#define HYPERPRIVOP_GET_TPR 0x9 +#define HYPERPRIVOP_SET_TPR 0xa +#define HYPERPRIVOP_EOI 0xb +#define HYPERPRIVOP_SET_ITM 0xc +#define HYPERPRIVOP_THASH 0xd +#define HYPERPRIVOP_PTC_GA 0xe +#define HYPERPRIVOP_ITR_D 0xf +#define HYPERPRIVOP_GET_RR 0x10 +#define HYPERPRIVOP_SET_RR 0x11 +#define HYPERPRIVOP_SET_KR 0x12 +#define HYPERPRIVOP_FC 0x13 +#define HYPERPRIVOP_GET_CPUID 0x14 +#define HYPERPRIVOP_GET_PMD 0x15 +#define HYPERPRIVOP_GET_EFLAG 0x16 +#define HYPERPRIVOP_SET_EFLAG 0x17 +#define HYPERPRIVOP_RSM_BE 0x18 +#define HYPERPRIVOP_GET_PSR 0x19 +#define HYPERPRIVOP_MAX 0x19 + +#endif /* __HYPERVISOR_IF_IA64_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/include/xen/interface/domctl.h b/include/xen/interface/domctl.h new file mode 100644 index 000000000..6ad891875 --- /dev/null +++ b/include/xen/interface/domctl.h @@ -0,0 +1,392 @@ +/****************************************************************************** + * domctl.h + * + * Domain management operations. For use by node control stack. + * + * Copyright (c) 2002-2003, B Dragovic + * Copyright (c) 2002-2006, K Fraser + */ + +#ifndef __XEN_PUBLIC_DOMCTL_H__ +#define __XEN_PUBLIC_DOMCTL_H__ + +#if !defined(__XEN__) && !defined(__XEN_TOOLS__) +#error "domctl operations are intended for use by node control tools only" +#endif + +#include "xen.h" + +#define XEN_DOMCTL_INTERFACE_VERSION 0x00000003 + +struct xenctl_cpumap { + XEN_GUEST_HANDLE(uint8_t) bitmap; + uint32_t nr_cpus; +}; + +/* + * NB. xen_domctl.domain is an IN/OUT parameter for this operation. + * If it is specified as zero, an id is auto-allocated and returned. + */ +#define XEN_DOMCTL_createdomain 1 +struct xen_domctl_createdomain { + /* IN parameters */ + uint32_t ssidref; + xen_domain_handle_t handle; +}; +typedef struct xen_domctl_createdomain xen_domctl_createdomain_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_createdomain_t); + +#define XEN_DOMCTL_destroydomain 2 +#define XEN_DOMCTL_pausedomain 3 +#define XEN_DOMCTL_unpausedomain 4 + +#define XEN_DOMCTL_getdomaininfo 5 +struct xen_domctl_getdomaininfo { + /* OUT variables. */ + domid_t domain; /* Also echoed in domctl.domain */ +#define DOMFLAGS_DYING (1<<0) /* Domain is scheduled to die. */ +#define DOMFLAGS_SHUTDOWN (1<<2) /* The guest OS has shut down. */ +#define DOMFLAGS_PAUSED (1<<3) /* Currently paused by control software. */ +#define DOMFLAGS_BLOCKED (1<<4) /* Currently blocked pending an event. */ +#define DOMFLAGS_RUNNING (1<<5) /* Domain is currently running. */ +#define DOMFLAGS_CPUMASK 255 /* CPU to which this domain is bound. */ +#define DOMFLAGS_CPUSHIFT 8 +#define DOMFLAGS_SHUTDOWNMASK 255 /* DOMFLAGS_SHUTDOWN guest-supplied code. */ +#define DOMFLAGS_SHUTDOWNSHIFT 16 + uint32_t flags; + uint64_t tot_pages; + uint64_t max_pages; + uint64_t shared_info_frame; /* MFN of shared_info struct */ + uint64_t cpu_time; + uint32_t nr_online_vcpus; /* Number of VCPUs currently online. */ + uint32_t max_vcpu_id; /* Maximum VCPUID in use by this domain. */ + uint32_t ssidref; + xen_domain_handle_t handle; +}; +typedef struct xen_domctl_getdomaininfo xen_domctl_getdomaininfo_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_getdomaininfo_t); + + +#define XEN_DOMCTL_getmemlist 6 +struct xen_domctl_getmemlist { + /* IN variables. */ + /* Max entries to write to output buffer. */ + uint64_t max_pfns; + /* Start index in guest's page list. */ + uint64_t start_pfn; + XEN_GUEST_HANDLE(xen_pfn_t) buffer; + /* OUT variables. */ + uint64_t num_pfns; +}; +typedef struct xen_domctl_getmemlist xen_domctl_getmemlist_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_getmemlist_t); + + +#define XEN_DOMCTL_getpageframeinfo 7 + +#define XEN_DOMCTL_PFINFO_LTAB_SHIFT 28 +#define XEN_DOMCTL_PFINFO_NOTAB (0x0<<28) +#define XEN_DOMCTL_PFINFO_L1TAB (0x1<<28) +#define XEN_DOMCTL_PFINFO_L2TAB (0x2<<28) +#define XEN_DOMCTL_PFINFO_L3TAB (0x3<<28) +#define XEN_DOMCTL_PFINFO_L4TAB (0x4<<28) +#define XEN_DOMCTL_PFINFO_LTABTYPE_MASK (0x7<<28) +#define XEN_DOMCTL_PFINFO_LPINTAB (0x1<<31) +#define XEN_DOMCTL_PFINFO_XTAB (0xf<<28) /* invalid page */ +#define XEN_DOMCTL_PFINFO_LTAB_MASK (0xf<<28) + +struct xen_domctl_getpageframeinfo { + /* IN variables. */ + uint64_t gmfn; /* GMFN to query */ + /* OUT variables. */ + /* Is the page PINNED to a type? */ + uint32_t type; /* see above type defs */ +}; +typedef struct xen_domctl_getpageframeinfo xen_domctl_getpageframeinfo_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_getpageframeinfo_t); + + +#define XEN_DOMCTL_getpageframeinfo2 8 +struct xen_domctl_getpageframeinfo2 { + /* IN variables. */ + uint64_t num; + /* IN/OUT variables. */ + XEN_GUEST_HANDLE(ulong) array; +}; +typedef struct xen_domctl_getpageframeinfo2 xen_domctl_getpageframeinfo2_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_getpageframeinfo2_t); + + +/* + * Control shadow pagetables operation + */ +#define XEN_DOMCTL_shadow_op 10 + +/* Disable shadow mode. */ +#define XEN_DOMCTL_SHADOW_OP_OFF 0 + +/* Enable shadow mode (mode contains ORed XEN_DOMCTL_SHADOW_ENABLE_* flags). */ +#define XEN_DOMCTL_SHADOW_OP_ENABLE 32 + +/* Log-dirty bitmap operations. */ + /* Return the bitmap and clean internal copy for next round. */ +#define XEN_DOMCTL_SHADOW_OP_CLEAN 11 + /* Return the bitmap but do not modify internal copy. */ +#define XEN_DOMCTL_SHADOW_OP_PEEK 12 + +/* Memory allocation accessors. */ +#define XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION 30 +#define XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION 31 + +/* Legacy enable operations. */ + /* Equiv. to ENABLE with no mode flags. */ +#define XEN_DOMCTL_SHADOW_OP_ENABLE_TEST 1 + /* Equiv. to ENABLE with mode flag ENABLE_LOG_DIRTY. */ +#define XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY 2 + /* Equiv. to ENABLE with mode flags ENABLE_REFCOUNT and ENABLE_TRANSLATE. */ +#define XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE 3 + +/* Mode flags for XEN_DOMCTL_SHADOW_OP_ENABLE. */ + /* + * Shadow pagetables are refcounted: guest does not use explicit mmu + * operations nor write-protect its pagetables. + */ +#define XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT (1 << 1) + /* + * Log pages in a bitmap as they are dirtied. + * Used for live relocation to determine which pages must be re-sent. + */ +#define XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY (1 << 2) + /* + * Automatically translate GPFNs into MFNs. + */ +#define XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE (1 << 3) + /* + * Xen does not steal virtual address space from the guest. + * Requires HVM support. + */ +#define XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL (1 << 4) + +struct xen_domctl_shadow_op_stats { + uint32_t fault_count; + uint32_t dirty_count; +}; +typedef struct xen_domctl_shadow_op_stats xen_domctl_shadow_op_stats_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_shadow_op_stats_t); + +struct xen_domctl_shadow_op { + /* IN variables. */ + uint32_t op; /* XEN_DOMCTL_SHADOW_OP_* */ + + /* OP_ENABLE */ + uint32_t mode; /* XEN_DOMCTL_SHADOW_ENABLE_* */ + + /* OP_GET_ALLOCATION / OP_SET_ALLOCATION */ + uint32_t mb; /* Shadow memory allocation in MB */ + + /* OP_PEEK / OP_CLEAN */ + XEN_GUEST_HANDLE(ulong) dirty_bitmap; + uint64_t pages; /* Size of buffer. Updated with actual size. */ + struct xen_domctl_shadow_op_stats stats; +}; +typedef struct xen_domctl_shadow_op xen_domctl_shadow_op_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_shadow_op_t); + + +#define XEN_DOMCTL_max_mem 11 +struct xen_domctl_max_mem { + /* IN variables. */ + uint64_t max_memkb; +}; +typedef struct xen_domctl_max_mem xen_domctl_max_mem_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_mem_t); + + +#define XEN_DOMCTL_setvcpucontext 12 +#define XEN_DOMCTL_getvcpucontext 13 +struct xen_domctl_vcpucontext { + uint32_t vcpu; /* IN */ + XEN_GUEST_HANDLE(vcpu_guest_context_t) ctxt; /* IN/OUT */ +}; +typedef struct xen_domctl_vcpucontext xen_domctl_vcpucontext_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpucontext_t); + + +#define XEN_DOMCTL_getvcpuinfo 14 +struct xen_domctl_getvcpuinfo { + /* IN variables. */ + uint32_t vcpu; + /* OUT variables. */ + uint8_t online; /* currently online (not hotplugged)? */ + uint8_t blocked; /* blocked waiting for an event? */ + uint8_t running; /* currently scheduled on its CPU? */ + uint64_t cpu_time; /* total cpu time consumed (ns) */ + uint32_t cpu; /* current mapping */ +}; +typedef struct xen_domctl_getvcpuinfo xen_domctl_getvcpuinfo_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_getvcpuinfo_t); + + +/* Get/set which physical cpus a vcpu can execute on. */ +#define XEN_DOMCTL_setvcpuaffinity 9 +#define XEN_DOMCTL_getvcpuaffinity 25 +struct xen_domctl_vcpuaffinity { + uint32_t vcpu; /* IN */ + struct xenctl_cpumap cpumap; /* IN/OUT */ +}; +typedef struct xen_domctl_vcpuaffinity xen_domctl_vcpuaffinity_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_vcpuaffinity_t); + + +#define XEN_DOMCTL_max_vcpus 15 +struct xen_domctl_max_vcpus { + uint32_t max; /* maximum number of vcpus */ +}; +typedef struct xen_domctl_max_vcpus xen_domctl_max_vcpus_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_max_vcpus_t); + + +#define XEN_DOMCTL_scheduler_op 16 +/* Scheduler types. */ +#define XEN_SCHEDULER_SEDF 4 +#define XEN_SCHEDULER_CREDIT 5 +/* Set or get info? */ +#define XEN_DOMCTL_SCHEDOP_putinfo 0 +#define XEN_DOMCTL_SCHEDOP_getinfo 1 +struct xen_domctl_scheduler_op { + uint32_t sched_id; /* XEN_SCHEDULER_* */ + uint32_t cmd; /* XEN_DOMCTL_SCHEDOP_* */ + union { + struct xen_domctl_sched_sedf { + uint64_t period; + uint64_t slice; + uint64_t latency; + uint32_t extratime; + uint32_t weight; + } sedf; + struct xen_domctl_sched_credit { + uint16_t weight; + uint16_t cap; + } credit; + } u; +}; +typedef struct xen_domctl_scheduler_op xen_domctl_scheduler_op_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_scheduler_op_t); + + +#define XEN_DOMCTL_setdomainhandle 17 +struct xen_domctl_setdomainhandle { + xen_domain_handle_t handle; +}; +typedef struct xen_domctl_setdomainhandle xen_domctl_setdomainhandle_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_setdomainhandle_t); + + +#define XEN_DOMCTL_setdebugging 18 +struct xen_domctl_setdebugging { + uint8_t enable; +}; +typedef struct xen_domctl_setdebugging xen_domctl_setdebugging_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_setdebugging_t); + + +#define XEN_DOMCTL_irq_permission 19 +struct xen_domctl_irq_permission { + uint8_t pirq; + uint8_t allow_access; /* flag to specify enable/disable of IRQ access */ +}; +typedef struct xen_domctl_irq_permission xen_domctl_irq_permission_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_irq_permission_t); + + +#define XEN_DOMCTL_iomem_permission 20 +struct xen_domctl_iomem_permission { + uint64_t first_mfn; /* first page (physical page number) in range */ + uint64_t nr_mfns; /* number of pages in range (>0) */ + uint8_t allow_access; /* allow (!0) or deny (0) access to range? */ +}; +typedef struct xen_domctl_iomem_permission xen_domctl_iomem_permission_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_iomem_permission_t); + + +#define XEN_DOMCTL_ioport_permission 21 +struct xen_domctl_ioport_permission { + uint32_t first_port; /* first port int range */ + uint32_t nr_ports; /* size of port range */ + uint8_t allow_access; /* allow or deny access to range? */ +}; +typedef struct xen_domctl_ioport_permission xen_domctl_ioport_permission_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_ioport_permission_t); + +#define XEN_DOMCTL_hypercall_init 22 +struct xen_domctl_hypercall_init { + uint64_t gmfn; /* GMFN to be initialised */ +}; +typedef struct xen_domctl_hypercall_init xen_domctl_hypercall_init_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_hypercall_init_t); + +#define XEN_DOMCTL_arch_setup 23 +#define _XEN_DOMAINSETUP_hvm_guest 0 +#define XEN_DOMAINSETUP_hvm_guest (1UL<<_XEN_DOMAINSETUP_hvm_guest) +#define _XEN_DOMAINSETUP_query 1 /* Get parameters (for save) */ +#define XEN_DOMAINSETUP_query (1UL<<_XEN_DOMAINSETUP_query) +typedef struct xen_domctl_arch_setup { + uint64_t flags; /* XEN_DOMAINSETUP_* */ +#ifdef __ia64__ + uint64_t bp; /* mpaddr of boot param area */ + uint64_t maxmem; /* Highest memory address for MDT. */ + uint64_t xsi_va; /* Xen shared_info area virtual address. */ + uint32_t hypercall_imm; /* Break imm for Xen hypercalls. */ +#endif +} xen_domctl_arch_setup_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_arch_setup_t); + +#define XEN_DOMCTL_settimeoffset 24 +struct xen_domctl_settimeoffset { + int32_t time_offset_seconds; /* applied to domain wallclock time */ +}; +typedef struct xen_domctl_settimeoffset xen_domctl_settimeoffset_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t); + +struct xen_domctl { + uint32_t cmd; + uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */ + domid_t domain; + union { + struct xen_domctl_createdomain createdomain; + struct xen_domctl_getdomaininfo getdomaininfo; + struct xen_domctl_getmemlist getmemlist; + struct xen_domctl_getpageframeinfo getpageframeinfo; + struct xen_domctl_getpageframeinfo2 getpageframeinfo2; + struct xen_domctl_vcpuaffinity vcpuaffinity; + struct xen_domctl_shadow_op shadow_op; + struct xen_domctl_max_mem max_mem; + struct xen_domctl_vcpucontext vcpucontext; + struct xen_domctl_getvcpuinfo getvcpuinfo; + struct xen_domctl_max_vcpus max_vcpus; + struct xen_domctl_scheduler_op scheduler_op; + struct xen_domctl_setdomainhandle setdomainhandle; + struct xen_domctl_setdebugging setdebugging; + struct xen_domctl_irq_permission irq_permission; + struct xen_domctl_iomem_permission iomem_permission; + struct xen_domctl_ioport_permission ioport_permission; + struct xen_domctl_hypercall_init hypercall_init; + struct xen_domctl_arch_setup arch_setup; + struct xen_domctl_settimeoffset settimeoffset; + uint8_t pad[128]; + } u; +}; +typedef struct xen_domctl xen_domctl_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_t); + +#endif /* __XEN_PUBLIC_DOMCTL_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/include/xen/interface/elfnote.h b/include/xen/interface/elfnote.h new file mode 100644 index 000000000..a64d3df5b --- /dev/null +++ b/include/xen/interface/elfnote.h @@ -0,0 +1,133 @@ +/****************************************************************************** + * elfnote.h + * + * Definitions used for the Xen ELF notes. + * + * Copyright (c) 2006, Ian Campbell, XenSource Ltd. + */ + +#ifndef __XEN_PUBLIC_ELFNOTE_H__ +#define __XEN_PUBLIC_ELFNOTE_H__ + +/* + * The notes should live in a SHT_NOTE segment and have "Xen" in the + * name field. + * + * Numeric types are either 4 or 8 bytes depending on the content of + * the desc field. + * + * LEGACY indicated the fields in the legacy __xen_guest string which + * this a note type replaces. + */ + +/* + * NAME=VALUE pair (string). + * + * LEGACY: FEATURES and PAE + */ +#define XEN_ELFNOTE_INFO 0 + +/* + * The virtual address of the entry point (numeric). + * + * LEGACY: VIRT_ENTRY + */ +#define XEN_ELFNOTE_ENTRY 1 + +/* The virtual address of the hypercall transfer page (numeric). + * + * LEGACY: HYPERCALL_PAGE. (n.b. legacy value is a physical page + * number not a virtual address) + */ +#define XEN_ELFNOTE_HYPERCALL_PAGE 2 + +/* The virtual address where the kernel image should be mapped (numeric). + * + * Defaults to 0. + * + * LEGACY: VIRT_BASE + */ +#define XEN_ELFNOTE_VIRT_BASE 3 + +/* + * The offset of the ELF paddr field from the acutal required + * psuedo-physical address (numeric). + * + * This is used to maintain backwards compatibility with older kernels + * which wrote __PAGE_OFFSET into that field. This field defaults to 0 + * if not present. + * + * LEGACY: ELF_PADDR_OFFSET. (n.b. legacy default is VIRT_BASE) + */ +#define XEN_ELFNOTE_PADDR_OFFSET 4 + +/* + * The version of Xen that we work with (string). + * + * LEGACY: XEN_VER + */ +#define XEN_ELFNOTE_XEN_VERSION 5 + +/* + * The name of the guest operating system (string). + * + * LEGACY: GUEST_OS + */ +#define XEN_ELFNOTE_GUEST_OS 6 + +/* + * The version of the guest operating system (string). + * + * LEGACY: GUEST_VER + */ +#define XEN_ELFNOTE_GUEST_VERSION 7 + +/* + * The loader type (string). + * + * LEGACY: LOADER + */ +#define XEN_ELFNOTE_LOADER 8 + +/* + * The kernel supports PAE (x86/32 only, string = "yes" or "no"). + * + * LEGACY: PAE (n.b. The legacy interface included a provision to + * indicate 'extended-cr3' support allowing L3 page tables to be + * placed above 4G. It is assumed that any kernel new enough to use + * these ELF notes will include this and therefore "yes" here is + * equivalent to "yes[entended-cr3]" in the __xen_guest interface. + */ +#define XEN_ELFNOTE_PAE_MODE 9 + +/* + * The features supported/required by this kernel (string). + * + * The string must consist of a list of feature names (as given in + * features.h, without the "XENFEAT_" prefix) separated by '|' + * characters. If a feature is required for the kernel to function + * then the feature name must be preceded by a '!' character. + * + * LEGACY: FEATURES + */ +#define XEN_ELFNOTE_FEATURES 10 + +/* + * The kernel requires the symbol table to be loaded (string = "yes" or "no") + * LEGACY: BSD_SYMTAB (n.b. The legacy treated the presence or absence + * of this string as a boolean flag rather than requiring "yes" or + * "no". + */ +#define XEN_ELFNOTE_BSD_SYMTAB 11 + +#endif /* __XEN_PUBLIC_ELFNOTE_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/include/xen/interface/hvm/e820.h b/include/xen/interface/hvm/e820.h new file mode 100644 index 000000000..8190c767d --- /dev/null +++ b/include/xen/interface/hvm/e820.h @@ -0,0 +1,32 @@ +#ifndef __XEN_PUBLIC_HVM_E820_H__ +#define __XEN_PUBLIC_HVM_E820_H__ + +/* PC BIOS standard E820 types. */ +#define E820_RAM 1 +#define E820_RESERVED 2 +#define E820_ACPI 3 +#define E820_NVS 4 + +/* Xen HVM extended E820 types. */ +#define E820_IO 16 +#define E820_SHARED_PAGE 17 +#define E820_XENSTORE 18 +#define E820_BUFFERED_IO 19 + +/* E820 location in HVM virtual address space. */ +#define E820_MAP_PAGE 0x00090000 +#define E820_MAP_NR_OFFSET 0x000001E8 +#define E820_MAP_OFFSET 0x000002D0 + +struct e820entry { + uint64_t addr; + uint64_t size; + uint32_t type; +} __attribute__((packed)); + +#define HVM_BELOW_4G_RAM_END 0xF0000000 + +#define HVM_BELOW_4G_MMIO_START HVM_BELOW_4G_RAM_END +#define HVM_BELOW_4G_MMIO_LENGTH ((1ULL << 32) - HVM_BELOW_4G_MMIO_START) + +#endif /* __XEN_PUBLIC_HVM_E820_H__ */ diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h new file mode 100644 index 000000000..46e916091 --- /dev/null +++ b/include/xen/interface/platform.h @@ -0,0 +1,125 @@ +/****************************************************************************** + * platform.h + * + * Hardware platform operations. Intended for use by domain-0 kernel. + * + * Copyright (c) 2002-2006, K Fraser + */ + +#ifndef __XEN_PUBLIC_PLATFORM_H__ +#define __XEN_PUBLIC_PLATFORM_H__ + +#include "xen.h" + +#define XENPF_INTERFACE_VERSION 0x03000001 + +/* + * Set clock such that it would read <secs,nsecs> after 00:00:00 UTC, + * 1 January, 1970 if the current system time was <system_time>. + */ +#define XENPF_settime 17 +struct xenpf_settime { + /* IN variables. */ + uint32_t secs; + uint32_t nsecs; + uint64_t system_time; +}; +typedef struct xenpf_settime xenpf_settime_t; +DEFINE_XEN_GUEST_HANDLE(xenpf_settime_t); + +/* + * Request memory range (@mfn, @mfn+@nr_mfns-1) to have type @type. + * On x86, @type is an architecture-defined MTRR memory type. + * On success, returns the MTRR that was used (@reg) and a handle that can + * be passed to XENPF_DEL_MEMTYPE to accurately tear down the new setting. + * (x86-specific). + */ +#define XENPF_add_memtype 31 +struct xenpf_add_memtype { + /* IN variables. */ + xen_pfn_t mfn; + uint64_t nr_mfns; + uint32_t type; + /* OUT variables. */ + uint32_t handle; + uint32_t reg; +}; +typedef struct xenpf_add_memtype xenpf_add_memtype_t; +DEFINE_XEN_GUEST_HANDLE(xenpf_add_memtype_t); + +/* + * Tear down an existing memory-range type. If @handle is remembered then it + * should be passed in to accurately tear down the correct setting (in case + * of overlapping memory regions with differing types). If it is not known + * then @handle should be set to zero. In all cases @reg must be set. + * (x86-specific). + */ +#define XENPF_del_memtype 32 +struct xenpf_del_memtype { + /* IN variables. */ + uint32_t handle; + uint32_t reg; +}; +typedef struct xenpf_del_memtype xenpf_del_memtype_t; +DEFINE_XEN_GUEST_HANDLE(xenpf_del_memtype_t); + +/* Read current type of an MTRR (x86-specific). */ +#define XENPF_read_memtype 33 +struct xenpf_read_memtype { + /* IN variables. */ + uint32_t reg; + /* OUT variables. */ + xen_pfn_t mfn; + uint64_t nr_mfns; + uint32_t type; +}; +typedef struct xenpf_read_memtype xenpf_read_memtype_t; +DEFINE_XEN_GUEST_HANDLE(xenpf_read_memtype_t); + +#define XENPF_microcode_update 35 +struct xenpf_microcode_update { + /* IN variables. */ + XEN_GUEST_HANDLE(void) data; /* Pointer to microcode data */ + uint32_t length; /* Length of microcode data. */ +}; +typedef struct xenpf_microcode_update xenpf_microcode_update_t; +DEFINE_XEN_GUEST_HANDLE(xenpf_microcode_update_t); + +#define XENPF_platform_quirk 39 +#define QUIRK_NOIRQBALANCING 1 /* Do not restrict IO-APIC RTE targets */ +#define QUIRK_IOAPIC_BAD_REGSEL 2 /* IO-APIC REGSEL forgets its value */ +#define QUIRK_IOAPIC_GOOD_REGSEL 3 /* IO-APIC REGSEL behaves properly */ +struct xenpf_platform_quirk { + /* IN variables. */ + uint32_t quirk_id; +}; +typedef struct xenpf_platform_quirk xenpf_platform_quirk_t; +DEFINE_XEN_GUEST_HANDLE(xenpf_platform_quirk_t); + +struct xen_platform_op { + uint32_t cmd; + uint32_t interface_version; /* XENPF_INTERFACE_VERSION */ + union { + struct xenpf_settime settime; + struct xenpf_add_memtype add_memtype; + struct xenpf_del_memtype del_memtype; + struct xenpf_read_memtype read_memtype; + struct xenpf_microcode_update microcode; + struct xenpf_platform_quirk platform_quirk; + uint8_t pad[128]; + } u; +}; +typedef struct xen_platform_op xen_platform_op_t; +DEFINE_XEN_GUEST_HANDLE(xen_platform_op_t); + +#endif /* __XEN_PUBLIC_PLATFORM_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/include/xen/interface/sysctl.h b/include/xen/interface/sysctl.h new file mode 100644 index 000000000..d556270a0 --- /dev/null +++ b/include/xen/interface/sysctl.h @@ -0,0 +1,151 @@ +/****************************************************************************** + * sysctl.h + * + * System management operations. For use by node control stack. + * + * Copyright (c) 2002-2006, K Fraser + */ + +#ifndef __XEN_PUBLIC_SYSCTL_H__ +#define __XEN_PUBLIC_SYSCTL_H__ + +#if !defined(__XEN__) && !defined(__XEN_TOOLS__) +#error "sysctl operations are intended for use by node control tools only" +#endif + +#include "xen.h" +#include "domctl.h" + +#define XEN_SYSCTL_INTERFACE_VERSION 0x00000002 + +/* + * Read console content from Xen buffer ring. + */ +#define XEN_SYSCTL_readconsole 1 +struct xen_sysctl_readconsole { + /* IN variables. */ + uint32_t clear; /* Non-zero -> clear after reading. */ + XEN_GUEST_HANDLE(char) buffer; /* Buffer start */ + /* IN/OUT variables. */ + uint32_t count; /* In: Buffer size; Out: Used buffer size */ +}; +typedef struct xen_sysctl_readconsole xen_sysctl_readconsole_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_readconsole_t); + +/* Get trace buffers machine base address */ +#define XEN_SYSCTL_tbuf_op 2 +struct xen_sysctl_tbuf_op { + /* IN variables */ +#define XEN_SYSCTL_TBUFOP_get_info 0 +#define XEN_SYSCTL_TBUFOP_set_cpu_mask 1 +#define XEN_SYSCTL_TBUFOP_set_evt_mask 2 +#define XEN_SYSCTL_TBUFOP_set_size 3 +#define XEN_SYSCTL_TBUFOP_enable 4 +#define XEN_SYSCTL_TBUFOP_disable 5 + uint32_t cmd; + /* IN/OUT variables */ + struct xenctl_cpumap cpu_mask; + uint32_t evt_mask; + /* OUT variables */ + uint64_t buffer_mfn; + uint32_t size; +}; +typedef struct xen_sysctl_tbuf_op xen_sysctl_tbuf_op_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_tbuf_op_t); + +/* + * Get physical information about the host machine + */ +#define XEN_SYSCTL_physinfo 3 +struct xen_sysctl_physinfo { + uint32_t threads_per_core; + uint32_t cores_per_socket; + uint32_t sockets_per_node; + uint32_t nr_nodes; + uint32_t cpu_khz; + uint64_t total_pages; + uint64_t free_pages; + uint64_t scrub_pages; + uint32_t hw_cap[8]; +}; +typedef struct xen_sysctl_physinfo xen_sysctl_physinfo_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_physinfo_t); + +/* + * Get the ID of the current scheduler. + */ +#define XEN_SYSCTL_sched_id 4 +struct xen_sysctl_sched_id { + /* OUT variable */ + uint32_t sched_id; +}; +typedef struct xen_sysctl_sched_id xen_sysctl_sched_id_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_sched_id_t); + +/* Interface for controlling Xen software performance counters. */ +#define XEN_SYSCTL_perfc_op 5 +/* Sub-operations: */ +#define XEN_SYSCTL_PERFCOP_reset 1 /* Reset all counters to zero. */ +#define XEN_SYSCTL_PERFCOP_query 2 /* Get perfctr information. */ +struct xen_sysctl_perfc_desc { + char name[80]; /* name of perf counter */ + uint32_t nr_vals; /* number of values for this counter */ +}; +typedef struct xen_sysctl_perfc_desc xen_sysctl_perfc_desc_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t); +typedef uint32_t xen_sysctl_perfc_val_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t); + +struct xen_sysctl_perfc_op { + /* IN variables. */ + uint32_t cmd; /* XEN_SYSCTL_PERFCOP_??? */ + /* OUT variables. */ + uint32_t nr_counters; /* number of counters description */ + uint32_t nr_vals; /* number of values */ + /* counter information (or NULL) */ + XEN_GUEST_HANDLE(xen_sysctl_perfc_desc_t) desc; + /* counter values (or NULL) */ + XEN_GUEST_HANDLE(xen_sysctl_perfc_val_t) val; +}; +typedef struct xen_sysctl_perfc_op xen_sysctl_perfc_op_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_perfc_op_t); + +#define XEN_SYSCTL_getdomaininfolist 6 +struct xen_sysctl_getdomaininfolist { + /* IN variables. */ + domid_t first_domain; + uint32_t max_domains; + XEN_GUEST_HANDLE(xen_domctl_getdomaininfo_t) buffer; + /* OUT variables. */ + uint32_t num_domains; +}; +typedef struct xen_sysctl_getdomaininfolist xen_sysctl_getdomaininfolist_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_getdomaininfolist_t); + +struct xen_sysctl { + uint32_t cmd; + uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */ + union { + struct xen_sysctl_readconsole readconsole; + struct xen_sysctl_tbuf_op tbuf_op; + struct xen_sysctl_physinfo physinfo; + struct xen_sysctl_sched_id sched_id; + struct xen_sysctl_perfc_op perfc_op; + struct xen_sysctl_getdomaininfolist getdomaininfolist; + uint8_t pad[128]; + } u; +}; +typedef struct xen_sysctl xen_sysctl_t; +DEFINE_XEN_GUEST_HANDLE(xen_sysctl_t); + +#endif /* __XEN_PUBLIC_SYSCTL_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/kernel/delayacct.c b/kernel/delayacct.c new file mode 100644 index 000000000..36752f124 --- /dev/null +++ b/kernel/delayacct.c @@ -0,0 +1,162 @@ +/* delayacct.c - per-task delay accounting + * + * Copyright (C) Shailabh Nagar, IBM Corp. 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + */ + +#include <linux/sched.h> +#include <linux/slab.h> +#include <linux/time.h> +#include <linux/sysctl.h> +#include <linux/delayacct.h> + +int delayacct_on __read_mostly = 1; /* Delay accounting turned on/off */ +kmem_cache_t *delayacct_cache; + +static int __init delayacct_setup_disable(char *str) +{ + delayacct_on = 0; + return 1; +} +__setup("nodelayacct", delayacct_setup_disable); + +void delayacct_init(void) +{ + delayacct_cache = kmem_cache_create("delayacct_cache", + sizeof(struct task_delay_info), + 0, + SLAB_PANIC, + NULL, NULL); + delayacct_tsk_init(&init_task); +} + +void __delayacct_tsk_init(struct task_struct *tsk) +{ + tsk->delays = kmem_cache_zalloc(delayacct_cache, SLAB_KERNEL); + if (tsk->delays) + spin_lock_init(&tsk->delays->lock); +} + +/* + * Start accounting for a delay statistic using + * its starting timestamp (@start) + */ + +static inline void delayacct_start(struct timespec *start) +{ + do_posix_clock_monotonic_gettime(start); +} + +/* + * Finish delay accounting for a statistic using + * its timestamps (@start, @end), accumalator (@total) and @count + */ + +static void delayacct_end(struct timespec *start, struct timespec *end, + u64 *total, u32 *count) +{ + struct timespec ts; + s64 ns; + + do_posix_clock_monotonic_gettime(end); + ts = timespec_sub(*end, *start); + ns = timespec_to_ns(&ts); + if (ns < 0) + return; + + spin_lock(¤t->delays->lock); + *total += ns; + (*count)++; + spin_unlock(¤t->delays->lock); +} + +void __delayacct_blkio_start(void) +{ + delayacct_start(¤t->delays->blkio_start); +} + +void __delayacct_blkio_end(void) +{ + if (current->delays->flags & DELAYACCT_PF_SWAPIN) + /* Swapin block I/O */ + delayacct_end(¤t->delays->blkio_start, + ¤t->delays->blkio_end, + ¤t->delays->swapin_delay, + ¤t->delays->swapin_count); + else /* Other block I/O */ + delayacct_end(¤t->delays->blkio_start, + ¤t->delays->blkio_end, + ¤t->delays->blkio_delay, + ¤t->delays->blkio_count); +} + +int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk) +{ + s64 tmp; + struct timespec ts; + unsigned long t1,t2,t3; + + /* Though tsk->delays accessed later, early exit avoids + * unnecessary returning of other data + */ + if (!tsk->delays) + goto done; + + tmp = (s64)d->cpu_run_real_total; + cputime_to_timespec(tsk->utime + tsk->stime, &ts); + tmp += timespec_to_ns(&ts); + d->cpu_run_real_total = (tmp < (s64)d->cpu_run_real_total) ? 0 : tmp; + + /* + * No locking available for sched_info (and too expensive to add one) + * Mitigate by taking snapshot of values + */ + t1 = tsk->sched_info.pcnt; + t2 = tsk->sched_info.run_delay; + t3 = tsk->sched_info.cpu_time; + + d->cpu_count += t1; + + jiffies_to_timespec(t2, &ts); + tmp = (s64)d->cpu_delay_total + timespec_to_ns(&ts); + d->cpu_delay_total = (tmp < (s64)d->cpu_delay_total) ? 0 : tmp; + + tmp = (s64)d->cpu_run_virtual_total + (s64)jiffies_to_usecs(t3) * 1000; + d->cpu_run_virtual_total = + (tmp < (s64)d->cpu_run_virtual_total) ? 0 : tmp; + + /* zero XXX_total, non-zero XXX_count implies XXX stat overflowed */ + + spin_lock(&tsk->delays->lock); + tmp = d->blkio_delay_total + tsk->delays->blkio_delay; + d->blkio_delay_total = (tmp < d->blkio_delay_total) ? 0 : tmp; + tmp = d->swapin_delay_total + tsk->delays->swapin_delay; + d->swapin_delay_total = (tmp < d->swapin_delay_total) ? 0 : tmp; + d->blkio_count += tsk->delays->blkio_count; + d->swapin_count += tsk->delays->swapin_count; + spin_unlock(&tsk->delays->lock); + +done: + return 0; +} + +__u64 __delayacct_blkio_ticks(struct task_struct *tsk) +{ + __u64 ret; + + spin_lock(&tsk->delays->lock); + ret = nsec_to_clock_t(tsk->delays->blkio_delay + + tsk->delays->swapin_delay); + spin_unlock(&tsk->delays->lock); + return ret; +} + diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c new file mode 100644 index 000000000..ac1f850d4 --- /dev/null +++ b/kernel/irq/chip.c @@ -0,0 +1,537 @@ +/* + * linux/kernel/irq/chip.c + * + * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar + * Copyright (C) 2005-2006, Thomas Gleixner, Russell King + * + * This file contains the core interrupt handling code, for irq-chip + * based architectures. + * + * Detailed information is available in Documentation/DocBook/genericirq + */ + +#include <linux/irq.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/kernel_stat.h> + +#include "internals.h" + +/** + * set_irq_chip - set the irq chip for an irq + * @irq: irq number + * @chip: pointer to irq chip description structure + */ +int set_irq_chip(unsigned int irq, struct irq_chip *chip) +{ + struct irq_desc *desc; + unsigned long flags; + + if (irq >= NR_IRQS) { + printk(KERN_ERR "Trying to install chip for IRQ%d\n", irq); + WARN_ON(1); + return -EINVAL; + } + + if (!chip) + chip = &no_irq_chip; + + desc = irq_desc + irq; + spin_lock_irqsave(&desc->lock, flags); + irq_chip_set_defaults(chip); + desc->chip = chip; + /* + * For compatibility only: + */ + desc->chip = chip; + spin_unlock_irqrestore(&desc->lock, flags); + + return 0; +} +EXPORT_SYMBOL(set_irq_chip); + +/** + * set_irq_type - set the irq type for an irq + * @irq: irq number + * @type: interrupt type - see include/linux/interrupt.h + */ +int set_irq_type(unsigned int irq, unsigned int type) +{ + struct irq_desc *desc; + unsigned long flags; + int ret = -ENXIO; + + if (irq >= NR_IRQS) { + printk(KERN_ERR "Trying to set irq type for IRQ%d\n", irq); + return -ENODEV; + } + + desc = irq_desc + irq; + if (desc->chip->set_type) { + spin_lock_irqsave(&desc->lock, flags); + ret = desc->chip->set_type(irq, type); + spin_unlock_irqrestore(&desc->lock, flags); + } + return ret; +} +EXPORT_SYMBOL(set_irq_type); + +/** + * set_irq_data - set irq type data for an irq + * @irq: Interrupt number + * @data: Pointer to interrupt specific data + * + * Set the hardware irq controller data for an irq + */ +int set_irq_data(unsigned int irq, void *data) +{ + struct irq_desc *desc; + unsigned long flags; + + if (irq >= NR_IRQS) { + printk(KERN_ERR + "Trying to install controller data for IRQ%d\n", irq); + return -EINVAL; + } + + desc = irq_desc + irq; + spin_lock_irqsave(&desc->lock, flags); + desc->handler_data = data; + spin_unlock_irqrestore(&desc->lock, flags); + return 0; +} +EXPORT_SYMBOL(set_irq_data); + +/** + * set_irq_chip_data - set irq chip data for an irq + * @irq: Interrupt number + * @data: Pointer to chip specific data + * + * Set the hardware irq chip data for an irq + */ +int set_irq_chip_data(unsigned int irq, void *data) +{ + struct irq_desc *desc = irq_desc + irq; + unsigned long flags; + + if (irq >= NR_IRQS || !desc->chip) { + printk(KERN_ERR "BUG: bad set_irq_chip_data(IRQ#%d)\n", irq); + return -EINVAL; + } + + spin_lock_irqsave(&desc->lock, flags); + desc->chip_data = data; + spin_unlock_irqrestore(&desc->lock, flags); + + return 0; +} +EXPORT_SYMBOL(set_irq_chip_data); + +/* + * default enable function + */ +static void default_enable(unsigned int irq) +{ + struct irq_desc *desc = irq_desc + irq; + + desc->chip->unmask(irq); + desc->status &= ~IRQ_MASKED; +} + +/* + * default disable function + */ +static void default_disable(unsigned int irq) +{ + struct irq_desc *desc = irq_desc + irq; + + if (!(desc->status & IRQ_DELAYED_DISABLE)) + irq_desc[irq].chip->mask(irq); +} + +/* + * default startup function + */ +static unsigned int default_startup(unsigned int irq) +{ + irq_desc[irq].chip->enable(irq); + + return 0; +} + +/* + * Fixup enable/disable function pointers + */ +void irq_chip_set_defaults(struct irq_chip *chip) +{ + if (!chip->enable) + chip->enable = default_enable; + if (!chip->disable) + chip->disable = default_disable; + if (!chip->startup) + chip->startup = default_startup; + if (!chip->shutdown) + chip->shutdown = chip->disable; + if (!chip->name) + chip->name = chip->typename; +} + +static inline void mask_ack_irq(struct irq_desc *desc, int irq) +{ + if (desc->chip->mask_ack) + desc->chip->mask_ack(irq); + else { + desc->chip->mask(irq); + desc->chip->ack(irq); + } +} + +/** + * handle_simple_irq - Simple and software-decoded IRQs. + * @irq: the interrupt number + * @desc: the interrupt description structure for this irq + * @regs: pointer to a register structure + * + * Simple interrupts are either sent from a demultiplexing interrupt + * handler or come from hardware, where no interrupt hardware control + * is necessary. + * + * Note: The caller is expected to handle the ack, clear, mask and + * unmask issues if necessary. + */ +void fastcall +handle_simple_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) +{ + struct irqaction *action; + irqreturn_t action_ret; + const unsigned int cpu = smp_processor_id(); + + spin_lock(&desc->lock); + + if (unlikely(desc->status & IRQ_INPROGRESS)) + goto out_unlock; + desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); + kstat_cpu(cpu).irqs[irq]++; + + action = desc->action; + if (unlikely(!action || (desc->status & IRQ_DISABLED))) + goto out_unlock; + + desc->status |= IRQ_INPROGRESS; + spin_unlock(&desc->lock); + + action_ret = handle_IRQ_event(irq, regs, action); + if (!noirqdebug) + note_interrupt(irq, desc, action_ret, regs); + + spin_lock(&desc->lock); + desc->status &= ~IRQ_INPROGRESS; +out_unlock: + spin_unlock(&desc->lock); +} + +/** + * handle_level_irq - Level type irq handler + * @irq: the interrupt number + * @desc: the interrupt description structure for this irq + * @regs: pointer to a register structure + * + * Level type interrupts are active as long as the hardware line has + * the active level. This may require to mask the interrupt and unmask + * it after the associated handler has acknowledged the device, so the + * interrupt line is back to inactive. + */ +void fastcall +handle_level_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) +{ + unsigned int cpu = smp_processor_id(); + struct irqaction *action; + irqreturn_t action_ret; + + spin_lock(&desc->lock); + mask_ack_irq(desc, irq); + + if (unlikely(desc->status & IRQ_INPROGRESS)) + goto out_unlock; + desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); + kstat_cpu(cpu).irqs[irq]++; + + /* + * If its disabled or no action available + * keep it masked and get out of here + */ + action = desc->action; + if (unlikely(!action || (desc->status & IRQ_DISABLED))) { + desc->status |= IRQ_PENDING; + goto out_unlock; + } + + desc->status |= IRQ_INPROGRESS; + desc->status &= ~IRQ_PENDING; + spin_unlock(&desc->lock); + + action_ret = handle_IRQ_event(irq, regs, action); + if (!noirqdebug) + note_interrupt(irq, desc, action_ret, regs); + + spin_lock(&desc->lock); + desc->status &= ~IRQ_INPROGRESS; + if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) + desc->chip->unmask(irq); +out_unlock: + spin_unlock(&desc->lock); +} + +/** + * handle_fasteoi_irq - irq handler for transparent controllers + * @irq: the interrupt number + * @desc: the interrupt description structure for this irq + * @regs: pointer to a register structure + * + * Only a single callback will be issued to the chip: an ->eoi() + * call when the interrupt has been serviced. This enables support + * for modern forms of interrupt handlers, which handle the flow + * details in hardware, transparently. + */ +void fastcall +handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc, + struct pt_regs *regs) +{ + unsigned int cpu = smp_processor_id(); + struct irqaction *action; + irqreturn_t action_ret; + + spin_lock(&desc->lock); + + if (unlikely(desc->status & IRQ_INPROGRESS)) + goto out; + + desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); + kstat_cpu(cpu).irqs[irq]++; + + /* + * If its disabled or no action available + * keep it masked and get out of here + */ + action = desc->action; + if (unlikely(!action || (desc->status & IRQ_DISABLED))) { + desc->status |= IRQ_PENDING; + goto out; + } + + desc->status |= IRQ_INPROGRESS; + desc->status &= ~IRQ_PENDING; + spin_unlock(&desc->lock); + + action_ret = handle_IRQ_event(irq, regs, action); + if (!noirqdebug) + note_interrupt(irq, desc, action_ret, regs); + + spin_lock(&desc->lock); + desc->status &= ~IRQ_INPROGRESS; +out: + desc->chip->eoi(irq); + + spin_unlock(&desc->lock); +} + +/** + * handle_edge_irq - edge type IRQ handler + * @irq: the interrupt number + * @desc: the interrupt description structure for this irq + * @regs: pointer to a register structure + * + * Interrupt occures on the falling and/or rising edge of a hardware + * signal. The occurence is latched into the irq controller hardware + * and must be acked in order to be reenabled. After the ack another + * interrupt can happen on the same source even before the first one + * is handled by the assosiacted event handler. If this happens it + * might be necessary to disable (mask) the interrupt depending on the + * controller hardware. This requires to reenable the interrupt inside + * of the loop which handles the interrupts which have arrived while + * the handler was running. If all pending interrupts are handled, the + * loop is left. + */ +void fastcall +handle_edge_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) +{ + const unsigned int cpu = smp_processor_id(); + + spin_lock(&desc->lock); + + desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); + + /* + * If we're currently running this IRQ, or its disabled, + * we shouldn't process the IRQ. Mark it pending, handle + * the necessary masking and go out + */ + if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) || + !desc->action)) { + desc->status |= (IRQ_PENDING | IRQ_MASKED); + mask_ack_irq(desc, irq); + goto out_unlock; + } + + kstat_cpu(cpu).irqs[irq]++; + + /* Start handling the irq */ + desc->chip->ack(irq); + + /* Mark the IRQ currently in progress.*/ + desc->status |= IRQ_INPROGRESS; + + do { + struct irqaction *action = desc->action; + irqreturn_t action_ret; + + if (unlikely(!action)) { + desc->chip->mask(irq); + goto out_unlock; + } + + /* + * When another irq arrived while we were handling + * one, we could have masked the irq. + * Renable it, if it was not disabled in meantime. + */ + if (unlikely((desc->status & + (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) == + (IRQ_PENDING | IRQ_MASKED))) { + desc->chip->unmask(irq); + desc->status &= ~IRQ_MASKED; + } + + desc->status &= ~IRQ_PENDING; + spin_unlock(&desc->lock); + action_ret = handle_IRQ_event(irq, regs, action); + if (!noirqdebug) + note_interrupt(irq, desc, action_ret, regs); + spin_lock(&desc->lock); + + } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING); + + desc->status &= ~IRQ_INPROGRESS; +out_unlock: + spin_unlock(&desc->lock); +} + +#ifdef CONFIG_SMP +/** + * handle_percpu_IRQ - Per CPU local irq handler + * @irq: the interrupt number + * @desc: the interrupt description structure for this irq + * @regs: pointer to a register structure + * + * Per CPU interrupts on SMP machines without locking requirements + */ +void fastcall +handle_percpu_irq(unsigned int irq, struct irq_desc *desc, struct pt_regs *regs) +{ + irqreturn_t action_ret; + + kstat_this_cpu.irqs[irq]++; + + if (desc->chip->ack) + desc->chip->ack(irq); + + action_ret = handle_IRQ_event(irq, regs, desc->action); + if (!noirqdebug) + note_interrupt(irq, desc, action_ret, regs); + + if (desc->chip->eoi) + desc->chip->eoi(irq); +} + +#endif /* CONFIG_SMP */ + +void +__set_irq_handler(unsigned int irq, + void fastcall (*handle)(unsigned int, irq_desc_t *, + struct pt_regs *), + int is_chained) +{ + struct irq_desc *desc; + unsigned long flags; + + if (irq >= NR_IRQS) { + printk(KERN_ERR + "Trying to install type control for IRQ%d\n", irq); + return; + } + + desc = irq_desc + irq; + + if (!handle) + handle = handle_bad_irq; + + if (desc->chip == &no_irq_chip) { + printk(KERN_WARNING "Trying to install %sinterrupt handler " + "for IRQ%d\n", is_chained ? "chained " : " ", irq); + /* + * Some ARM implementations install a handler for really dumb + * interrupt hardware without setting an irq_chip. This worked + * with the ARM no_irq_chip but the check in setup_irq would + * prevent us to setup the interrupt at all. Switch it to + * dummy_irq_chip for easy transition. + */ + desc->chip = &dummy_irq_chip; + } + + spin_lock_irqsave(&desc->lock, flags); + + /* Uninstall? */ + if (handle == handle_bad_irq) { + if (desc->chip != &no_irq_chip) { + desc->chip->mask(irq); + desc->chip->ack(irq); + } + desc->status |= IRQ_DISABLED; + desc->depth = 1; + } + desc->handle_irq = handle; + + if (handle != handle_bad_irq && is_chained) { + desc->status &= ~IRQ_DISABLED; + desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE; + desc->depth = 0; + desc->chip->unmask(irq); + } + spin_unlock_irqrestore(&desc->lock, flags); +} + +void +set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip, + void fastcall (*handle)(unsigned int, + struct irq_desc *, + struct pt_regs *)) +{ + set_irq_chip(irq, chip); + __set_irq_handler(irq, handle, 0); +} + +/* + * Get a descriptive string for the highlevel handler, for + * /proc/interrupts output: + */ +const char * +handle_irq_name(void fastcall (*handle)(unsigned int, struct irq_desc *, + struct pt_regs *)) +{ + if (handle == handle_level_irq) + return "level "; + if (handle == handle_fasteoi_irq) + return "fasteoi"; + if (handle == handle_edge_irq) + return "edge "; + if (handle == handle_simple_irq) + return "simple "; +#ifdef CONFIG_SMP + if (handle == handle_percpu_irq) + return "percpu "; +#endif + if (handle == handle_bad_irq) + return "bad "; + + return NULL; +} diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c new file mode 100644 index 000000000..35f10f7ff --- /dev/null +++ b/kernel/irq/resend.c @@ -0,0 +1,77 @@ +/* + * linux/kernel/irq/resend.c + * + * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar + * Copyright (C) 2005-2006, Thomas Gleixner + * + * This file contains the IRQ-resend code + * + * If the interrupt is waiting to be processed, we try to re-run it. + * We can't directly run it from here since the caller might be in an + * interrupt-protected region. Not all irq controller chips can + * retrigger interrupts at the hardware level, so in those cases + * we allow the resending of IRQs via a tasklet. + */ + +#include <linux/irq.h> +#include <linux/module.h> +#include <linux/random.h> +#include <linux/interrupt.h> + +#include "internals.h" + +#ifdef CONFIG_HARDIRQS_SW_RESEND + +/* Bitmap to handle software resend of interrupts: */ +static DECLARE_BITMAP(irqs_resend, NR_IRQS); + +/* + * Run software resends of IRQ's + */ +static void resend_irqs(unsigned long arg) +{ + struct irq_desc *desc; + int irq; + + while (!bitmap_empty(irqs_resend, NR_IRQS)) { + irq = find_first_bit(irqs_resend, NR_IRQS); + clear_bit(irq, irqs_resend); + desc = irq_desc + irq; + local_irq_disable(); + desc->handle_irq(irq, desc, NULL); + local_irq_enable(); + } +} + +/* Tasklet to handle resend: */ +static DECLARE_TASKLET(resend_tasklet, resend_irqs, 0); + +#endif + +/* + * IRQ resend + * + * Is called with interrupts disabled and desc->lock held. + */ +void check_irq_resend(struct irq_desc *desc, unsigned int irq) +{ + unsigned int status = desc->status; + + /* + * Make sure the interrupt is enabled, before resending it: + */ + desc->chip->enable(irq); + + if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { + desc->status = (status & ~IRQ_PENDING) | IRQ_REPLAY; + + if (!desc->chip || !desc->chip->retrigger || + !desc->chip->retrigger(irq)) { +#ifdef CONFIG_HARDIRQS_SW_RESEND + /* Set it pending and activate the softirq: */ + set_bit(irq, irqs_resend); + tasklet_schedule(&resend_tasklet); +#endif + } + } +} diff --git a/kernel/lockdep.c b/kernel/lockdep.c new file mode 100644 index 000000000..3a0c44c60 --- /dev/null +++ b/kernel/lockdep.c @@ -0,0 +1,2727 @@ +/* + * kernel/lockdep.c + * + * Runtime locking correctness validator + * + * Started by Ingo Molnar: + * + * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + * + * this code maps all the lock dependencies as they occur in a live kernel + * and will warn about the following classes of locking bugs: + * + * - lock inversion scenarios + * - circular lock dependencies + * - hardirq/softirq safe/unsafe locking bugs + * + * Bugs are reported even if the current locking scenario does not cause + * any deadlock at this point. + * + * I.e. if anytime in the past two locks were taken in a different order, + * even if it happened for another task, even if those were different + * locks (but of the same class as this lock), this code will detect it. + * + * Thanks to Arjan van de Ven for coming up with the initial idea of + * mapping lock dependencies runtime. + */ +#include <linux/mutex.h> +#include <linux/sched.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#include <linux/spinlock.h> +#include <linux/kallsyms.h> +#include <linux/interrupt.h> +#include <linux/stacktrace.h> +#include <linux/debug_locks.h> +#include <linux/irqflags.h> +#include <linux/utsname.h> + +#include <asm/sections.h> + +#include "lockdep_internals.h" + +/* + * hash_lock: protects the lockdep hashes and class/list/hash allocators. + * + * This is one of the rare exceptions where it's justified + * to use a raw spinlock - we really dont want the spinlock + * code to recurse back into the lockdep code. + */ +static raw_spinlock_t hash_lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; + +static int lockdep_initialized; + +unsigned long nr_list_entries; +static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES]; + +/* + * Allocate a lockdep entry. (assumes hash_lock held, returns + * with NULL on failure) + */ +static struct lock_list *alloc_list_entry(void) +{ + if (nr_list_entries >= MAX_LOCKDEP_ENTRIES) { + __raw_spin_unlock(&hash_lock); + debug_locks_off(); + printk("BUG: MAX_LOCKDEP_ENTRIES too low!\n"); + printk("turning off the locking correctness validator.\n"); + return NULL; + } + return list_entries + nr_list_entries++; +} + +/* + * All data structures here are protected by the global debug_lock. + * + * Mutex key structs only get allocated, once during bootup, and never + * get freed - this significantly simplifies the debugging code. + */ +unsigned long nr_lock_classes; +static struct lock_class lock_classes[MAX_LOCKDEP_KEYS]; + +/* + * We keep a global list of all lock classes. The list only grows, + * never shrinks. The list is only accessed with the lockdep + * spinlock lock held. + */ +LIST_HEAD(all_lock_classes); + +/* + * The lockdep classes are in a hash-table as well, for fast lookup: + */ +#define CLASSHASH_BITS (MAX_LOCKDEP_KEYS_BITS - 1) +#define CLASSHASH_SIZE (1UL << CLASSHASH_BITS) +#define CLASSHASH_MASK (CLASSHASH_SIZE - 1) +#define __classhashfn(key) ((((unsigned long)key >> CLASSHASH_BITS) + (unsigned long)key) & CLASSHASH_MASK) +#define classhashentry(key) (classhash_table + __classhashfn((key))) + +static struct list_head classhash_table[CLASSHASH_SIZE]; + +unsigned long nr_lock_chains; +static struct lock_chain lock_chains[MAX_LOCKDEP_CHAINS]; + +/* + * We put the lock dependency chains into a hash-table as well, to cache + * their existence: + */ +#define CHAINHASH_BITS (MAX_LOCKDEP_CHAINS_BITS-1) +#define CHAINHASH_SIZE (1UL << CHAINHASH_BITS) +#define CHAINHASH_MASK (CHAINHASH_SIZE - 1) +#define __chainhashfn(chain) \ + (((chain >> CHAINHASH_BITS) + chain) & CHAINHASH_MASK) +#define chainhashentry(chain) (chainhash_table + __chainhashfn((chain))) + +static struct list_head chainhash_table[CHAINHASH_SIZE]; + +/* + * The hash key of the lock dependency chains is a hash itself too: + * it's a hash of all locks taken up to that lock, including that lock. + * It's a 64-bit hash, because it's important for the keys to be + * unique. + */ +#define iterate_chain_key(key1, key2) \ + (((key1) << MAX_LOCKDEP_KEYS_BITS/2) ^ \ + ((key1) >> (64-MAX_LOCKDEP_KEYS_BITS/2)) ^ \ + (key2)) + +void lockdep_off(void) +{ + current->lockdep_recursion++; +} + +EXPORT_SYMBOL(lockdep_off); + +void lockdep_on(void) +{ + current->lockdep_recursion--; +} + +EXPORT_SYMBOL(lockdep_on); + +int lockdep_internal(void) +{ + return current->lockdep_recursion != 0; +} + +EXPORT_SYMBOL(lockdep_internal); + +/* + * Debugging switches: + */ + +#define VERBOSE 0 +#ifdef VERBOSE +# define VERY_VERBOSE 0 +#endif + +#if VERBOSE +# define HARDIRQ_VERBOSE 1 +# define SOFTIRQ_VERBOSE 1 +#else +# define HARDIRQ_VERBOSE 0 +# define SOFTIRQ_VERBOSE 0 +#endif + +#if VERBOSE || HARDIRQ_VERBOSE || SOFTIRQ_VERBOSE +/* + * Quick filtering for interesting events: + */ +static int class_filter(struct lock_class *class) +{ +#if 0 + /* Example */ + if (class->name_version == 1 && + !strcmp(class->name, "lockname")) + return 1; + if (class->name_version == 1 && + !strcmp(class->name, "&struct->lockfield")) + return 1; +#endif + /* Allow everything else. 0 would be filter everything else */ + return 1; +} +#endif + +static int verbose(struct lock_class *class) +{ +#if VERBOSE + return class_filter(class); +#endif + return 0; +} + +#ifdef CONFIG_TRACE_IRQFLAGS + +static int hardirq_verbose(struct lock_class *class) +{ +#if HARDIRQ_VERBOSE + return class_filter(class); +#endif + return 0; +} + +static int softirq_verbose(struct lock_class *class) +{ +#if SOFTIRQ_VERBOSE + return class_filter(class); +#endif + return 0; +} + +#endif + +/* + * Stack-trace: tightly packed array of stack backtrace + * addresses. Protected by the hash_lock. + */ +unsigned long nr_stack_trace_entries; +static unsigned long stack_trace[MAX_STACK_TRACE_ENTRIES]; + +static int save_trace(struct stack_trace *trace) +{ + trace->nr_entries = 0; + trace->max_entries = MAX_STACK_TRACE_ENTRIES - nr_stack_trace_entries; + trace->entries = stack_trace + nr_stack_trace_entries; + + trace->skip = 3; + trace->all_contexts = 0; + + /* Make sure to not recurse in case the the unwinder needs to tak +e locks. */ + lockdep_off(); + save_stack_trace(trace, NULL); + lockdep_on(); + + trace->max_entries = trace->nr_entries; + + nr_stack_trace_entries += trace->nr_entries; + if (DEBUG_LOCKS_WARN_ON(nr_stack_trace_entries > MAX_STACK_TRACE_ENTRIES)) + return 0; + + if (nr_stack_trace_entries == MAX_STACK_TRACE_ENTRIES) { + __raw_spin_unlock(&hash_lock); + if (debug_locks_off()) { + printk("BUG: MAX_STACK_TRACE_ENTRIES too low!\n"); + printk("turning off the locking correctness validator.\n"); + dump_stack(); + } + return 0; + } + + return 1; +} + +unsigned int nr_hardirq_chains; +unsigned int nr_softirq_chains; +unsigned int nr_process_chains; +unsigned int max_lockdep_depth; +unsigned int max_recursion_depth; + +#ifdef CONFIG_DEBUG_LOCKDEP +/* + * We cannot printk in early bootup code. Not even early_printk() + * might work. So we mark any initialization errors and printk + * about it later on, in lockdep_info(). + */ +static int lockdep_init_error; + +/* + * Various lockdep statistics: + */ +atomic_t chain_lookup_hits; +atomic_t chain_lookup_misses; +atomic_t hardirqs_on_events; +atomic_t hardirqs_off_events; +atomic_t redundant_hardirqs_on; +atomic_t redundant_hardirqs_off; +atomic_t softirqs_on_events; +atomic_t softirqs_off_events; +atomic_t redundant_softirqs_on; +atomic_t redundant_softirqs_off; +atomic_t nr_unused_locks; +atomic_t nr_cyclic_checks; +atomic_t nr_cyclic_check_recursions; +atomic_t nr_find_usage_forwards_checks; +atomic_t nr_find_usage_forwards_recursions; +atomic_t nr_find_usage_backwards_checks; +atomic_t nr_find_usage_backwards_recursions; +# define debug_atomic_inc(ptr) atomic_inc(ptr) +# define debug_atomic_dec(ptr) atomic_dec(ptr) +# define debug_atomic_read(ptr) atomic_read(ptr) +#else +# define debug_atomic_inc(ptr) do { } while (0) +# define debug_atomic_dec(ptr) do { } while (0) +# define debug_atomic_read(ptr) 0 +#endif + +/* + * Locking printouts: + */ + +static const char *usage_str[] = +{ + [LOCK_USED] = "initial-use ", + [LOCK_USED_IN_HARDIRQ] = "in-hardirq-W", + [LOCK_USED_IN_SOFTIRQ] = "in-softirq-W", + [LOCK_ENABLED_SOFTIRQS] = "softirq-on-W", + [LOCK_ENABLED_HARDIRQS] = "hardirq-on-W", + [LOCK_USED_IN_HARDIRQ_READ] = "in-hardirq-R", + [LOCK_USED_IN_SOFTIRQ_READ] = "in-softirq-R", + [LOCK_ENABLED_SOFTIRQS_READ] = "softirq-on-R", + [LOCK_ENABLED_HARDIRQS_READ] = "hardirq-on-R", +}; + +const char * __get_key_name(struct lockdep_subclass_key *key, char *str) +{ + unsigned long offs, size; + char *modname; + + return kallsyms_lookup((unsigned long)key, &size, &offs, &modname, str); +} + +void +get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4) +{ + *c1 = '.', *c2 = '.', *c3 = '.', *c4 = '.'; + + if (class->usage_mask & LOCKF_USED_IN_HARDIRQ) + *c1 = '+'; + else + if (class->usage_mask & LOCKF_ENABLED_HARDIRQS) + *c1 = '-'; + + if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ) + *c2 = '+'; + else + if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS) + *c2 = '-'; + + if (class->usage_mask & LOCKF_ENABLED_HARDIRQS_READ) + *c3 = '-'; + if (class->usage_mask & LOCKF_USED_IN_HARDIRQ_READ) { + *c3 = '+'; + if (class->usage_mask & LOCKF_ENABLED_HARDIRQS_READ) + *c3 = '?'; + } + + if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS_READ) + *c4 = '-'; + if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ_READ) { + *c4 = '+'; + if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS_READ) + *c4 = '?'; + } +} + +static void print_lock_name(struct lock_class *class) +{ + char str[128], c1, c2, c3, c4; + const char *name; + + get_usage_chars(class, &c1, &c2, &c3, &c4); + + name = class->name; + if (!name) { + name = __get_key_name(class->key, str); + printk(" (%s", name); + } else { + printk(" (%s", name); + if (class->name_version > 1) + printk("#%d", class->name_version); + if (class->subclass) + printk("/%d", class->subclass); + } + printk("){%c%c%c%c}", c1, c2, c3, c4); +} + +static void print_lockdep_cache(struct lockdep_map *lock) +{ + const char *name; + char str[128]; + + name = lock->name; + if (!name) + name = __get_key_name(lock->key->subkeys, str); + + printk("%s", name); +} + +static void print_lock(struct held_lock *hlock) +{ + print_lock_name(hlock->class); + printk(", at: "); + print_ip_sym(hlock->acquire_ip); +} + +static void lockdep_print_held_locks(struct task_struct *curr) +{ + int i, depth = curr->lockdep_depth; + + if (!depth) { + printk("no locks held by %s/%d.\n", curr->comm, curr->pid); + return; + } + printk("%d lock%s held by %s/%d:\n", + depth, depth > 1 ? "s" : "", curr->comm, curr->pid); + + for (i = 0; i < depth; i++) { + printk(" #%d: ", i); + print_lock(curr->held_locks + i); + } +} + +static void print_lock_class_header(struct lock_class *class, int depth) +{ + int bit; + + printk("%*s->", depth, ""); + print_lock_name(class); + printk(" ops: %lu", class->ops); + printk(" {\n"); + + for (bit = 0; bit < LOCK_USAGE_STATES; bit++) { + if (class->usage_mask & (1 << bit)) { + int len = depth; + + len += printk("%*s %s", depth, "", usage_str[bit]); + len += printk(" at:\n"); + print_stack_trace(class->usage_traces + bit, len); + } + } + printk("%*s }\n", depth, ""); + + printk("%*s ... key at: ",depth,""); + print_ip_sym((unsigned long)class->key); +} + +/* + * printk all lock dependencies starting at <entry>: + */ +static void print_lock_dependencies(struct lock_class *class, int depth) +{ + struct lock_list *entry; + + if (DEBUG_LOCKS_WARN_ON(depth >= 20)) + return; + + print_lock_class_header(class, depth); + + list_for_each_entry(entry, &class->locks_after, entry) { + DEBUG_LOCKS_WARN_ON(!entry->class); + print_lock_dependencies(entry->class, depth + 1); + + printk("%*s ... acquired at:\n",depth,""); + print_stack_trace(&entry->trace, 2); + printk("\n"); + } +} + +/* + * Add a new dependency to the head of the list: + */ +static int add_lock_to_list(struct lock_class *class, struct lock_class *this, + struct list_head *head, unsigned long ip) +{ + struct lock_list *entry; + /* + * Lock not present yet - get a new dependency struct and + * add it to the list: + */ + entry = alloc_list_entry(); + if (!entry) + return 0; + + entry->class = this; + save_trace(&entry->trace); + + /* + * Since we never remove from the dependency list, the list can + * be walked lockless by other CPUs, it's only allocation + * that must be protected by the spinlock. But this also means + * we must make new entries visible only once writes to the + * entry become visible - hence the RCU op: + */ + list_add_tail_rcu(&entry->entry, head); + + return 1; +} + +/* + * Recursive, forwards-direction lock-dependency checking, used for + * both noncyclic checking and for hardirq-unsafe/softirq-unsafe + * checking. + * + * (to keep the stackframe of the recursive functions small we + * use these global variables, and we also mark various helper + * functions as noinline.) + */ +static struct held_lock *check_source, *check_target; + +/* + * Print a dependency chain entry (this is only done when a deadlock + * has been detected): + */ +static noinline int +print_circular_bug_entry(struct lock_list *target, unsigned int depth) +{ + if (debug_locks_silent) + return 0; + printk("\n-> #%u", depth); + print_lock_name(target->class); + printk(":\n"); + print_stack_trace(&target->trace, 6); + + return 0; +} + +static void print_kernel_version(void) +{ + printk("%s %.*s\n", system_utsname.release, + (int)strcspn(system_utsname.version, " "), + system_utsname.version); +} + +/* + * When a circular dependency is detected, print the + * header first: + */ +static noinline int +print_circular_bug_header(struct lock_list *entry, unsigned int depth) +{ + struct task_struct *curr = current; + + __raw_spin_unlock(&hash_lock); + debug_locks_off(); + if (debug_locks_silent) + return 0; + + printk("\n=======================================================\n"); + printk( "[ INFO: possible circular locking dependency detected ]\n"); + print_kernel_version(); + printk( "-------------------------------------------------------\n"); + printk("%s/%d is trying to acquire lock:\n", + curr->comm, curr->pid); + print_lock(check_source); + printk("\nbut task is already holding lock:\n"); + print_lock(check_target); + printk("\nwhich lock already depends on the new lock.\n\n"); + printk("\nthe existing dependency chain (in reverse order) is:\n"); + + print_circular_bug_entry(entry, depth); + + return 0; +} + +static noinline int print_circular_bug_tail(void) +{ + struct task_struct *curr = current; + struct lock_list this; + + if (debug_locks_silent) + return 0; + + this.class = check_source->class; + save_trace(&this.trace); + print_circular_bug_entry(&this, 0); + + printk("\nother info that might help us debug this:\n\n"); + lockdep_print_held_locks(curr); + + printk("\nstack backtrace:\n"); + dump_stack(); + + return 0; +} + +static int noinline print_infinite_recursion_bug(void) +{ + __raw_spin_unlock(&hash_lock); + DEBUG_LOCKS_WARN_ON(1); + + return 0; +} + +/* + * Prove that the dependency graph starting at <entry> can not + * lead to <target>. Print an error and return 0 if it does. + */ +static noinline int +check_noncircular(struct lock_class *source, unsigned int depth) +{ + struct lock_list *entry; + + debug_atomic_inc(&nr_cyclic_check_recursions); + if (depth > max_recursion_depth) + max_recursion_depth = depth; + if (depth >= 20) + return print_infinite_recursion_bug(); + /* + * Check this lock's dependency list: + */ + list_for_each_entry(entry, &source->locks_after, entry) { + if (entry->class == check_target->class) + return print_circular_bug_header(entry, depth+1); + debug_atomic_inc(&nr_cyclic_checks); + if (!check_noncircular(entry->class, depth+1)) + return print_circular_bug_entry(entry, depth+1); + } + return 1; +} + +static int very_verbose(struct lock_class *class) +{ +#if VERY_VERBOSE + return class_filter(class); +#endif + return 0; +} +#ifdef CONFIG_TRACE_IRQFLAGS + +/* + * Forwards and backwards subgraph searching, for the purposes of + * proving that two subgraphs can be connected by a new dependency + * without creating any illegal irq-safe -> irq-unsafe lock dependency. + */ +static enum lock_usage_bit find_usage_bit; +static struct lock_class *forwards_match, *backwards_match; + +/* + * Find a node in the forwards-direction dependency sub-graph starting + * at <source> that matches <find_usage_bit>. + * + * Return 2 if such a node exists in the subgraph, and put that node + * into <forwards_match>. + * + * Return 1 otherwise and keep <forwards_match> unchanged. + * Return 0 on error. + */ +static noinline int +find_usage_forwards(struct lock_class *source, unsigned int depth) +{ + struct lock_list *entry; + int ret; + + if (depth > max_recursion_depth) + max_recursion_depth = depth; + if (depth >= 20) + return print_infinite_recursion_bug(); + + debug_atomic_inc(&nr_find_usage_forwards_checks); + if (source->usage_mask & (1 << find_usage_bit)) { + forwards_match = source; + return 2; + } + + /* + * Check this lock's dependency list: + */ + list_for_each_entry(entry, &source->locks_after, entry) { + debug_atomic_inc(&nr_find_usage_forwards_recursions); + ret = find_usage_forwards(entry->class, depth+1); + if (ret == 2 || ret == 0) + return ret; + } + return 1; +} + +/* + * Find a node in the backwards-direction dependency sub-graph starting + * at <source> that matches <find_usage_bit>. + * + * Return 2 if such a node exists in the subgraph, and put that node + * into <backwards_match>. + * + * Return 1 otherwise and keep <backwards_match> unchanged. + * Return 0 on error. + */ +static noinline int +find_usage_backwards(struct lock_class *source, unsigned int depth) +{ + struct lock_list *entry; + int ret; + + if (depth > max_recursion_depth) + max_recursion_depth = depth; + if (depth >= 20) + return print_infinite_recursion_bug(); + + debug_atomic_inc(&nr_find_usage_backwards_checks); + if (source->usage_mask & (1 << find_usage_bit)) { + backwards_match = source; + return 2; + } + + /* + * Check this lock's dependency list: + */ + list_for_each_entry(entry, &source->locks_before, entry) { + debug_atomic_inc(&nr_find_usage_backwards_recursions); + ret = find_usage_backwards(entry->class, depth+1); + if (ret == 2 || ret == 0) + return ret; + } + return 1; +} + +static int +print_bad_irq_dependency(struct task_struct *curr, + struct held_lock *prev, + struct held_lock *next, + enum lock_usage_bit bit1, + enum lock_usage_bit bit2, + const char *irqclass) +{ + __raw_spin_unlock(&hash_lock); + debug_locks_off(); + if (debug_locks_silent) + return 0; + + printk("\n======================================================\n"); + printk( "[ INFO: %s-safe -> %s-unsafe lock order detected ]\n", + irqclass, irqclass); + print_kernel_version(); + printk( "------------------------------------------------------\n"); + printk("%s/%d [HC%u[%lu]:SC%u[%lu]:HE%u:SE%u] is trying to acquire:\n", + curr->comm, curr->pid, + curr->hardirq_context, hardirq_count() >> HARDIRQ_SHIFT, + curr->softirq_context, softirq_count() >> SOFTIRQ_SHIFT, + curr->hardirqs_enabled, + curr->softirqs_enabled); + print_lock(next); + + printk("\nand this task is already holding:\n"); + print_lock(prev); + printk("which would create a new lock dependency:\n"); + print_lock_name(prev->class); + printk(" ->"); + print_lock_name(next->class); + printk("\n"); + + printk("\nbut this new dependency connects a %s-irq-safe lock:\n", + irqclass); + print_lock_name(backwards_match); + printk("\n... which became %s-irq-safe at:\n", irqclass); + + print_stack_trace(backwards_match->usage_traces + bit1, 1); + + printk("\nto a %s-irq-unsafe lock:\n", irqclass); + print_lock_name(forwards_match); + printk("\n... which became %s-irq-unsafe at:\n", irqclass); + printk("..."); + + print_stack_trace(forwards_match->usage_traces + bit2, 1); + + printk("\nother info that might help us debug this:\n\n"); + lockdep_print_held_locks(curr); + + printk("\nthe %s-irq-safe lock's dependencies:\n", irqclass); + print_lock_dependencies(backwards_match, 0); + + printk("\nthe %s-irq-unsafe lock's dependencies:\n", irqclass); + print_lock_dependencies(forwards_match, 0); + + printk("\nstack backtrace:\n"); + dump_stack(); + + return 0; +} + +static int +check_usage(struct task_struct *curr, struct held_lock *prev, + struct held_lock *next, enum lock_usage_bit bit_backwards, + enum lock_usage_bit bit_forwards, const char *irqclass) +{ + int ret; + + find_usage_bit = bit_backwards; + /* fills in <backwards_match> */ + ret = find_usage_backwards(prev->class, 0); + if (!ret || ret == 1) + return ret; + + find_usage_bit = bit_forwards; + ret = find_usage_forwards(next->class, 0); + if (!ret || ret == 1) + return ret; + /* ret == 2 */ + return print_bad_irq_dependency(curr, prev, next, + bit_backwards, bit_forwards, irqclass); +} + +#endif + +static int +print_deadlock_bug(struct task_struct *curr, struct held_lock *prev, + struct held_lock *next) +{ + debug_locks_off(); + __raw_spin_unlock(&hash_lock); + if (debug_locks_silent) + return 0; + + printk("\n=============================================\n"); + printk( "[ INFO: possible recursive locking detected ]\n"); + print_kernel_version(); + printk( "---------------------------------------------\n"); + printk("%s/%d is trying to acquire lock:\n", + curr->comm, curr->pid); + print_lock(next); + printk("\nbut task is already holding lock:\n"); + print_lock(prev); + + printk("\nother info that might help us debug this:\n"); + lockdep_print_held_locks(curr); + + printk("\nstack backtrace:\n"); + dump_stack(); + + return 0; +} + +/* + * Check whether we are holding such a class already. + * + * (Note that this has to be done separately, because the graph cannot + * detect such classes of deadlocks.) + * + * Returns: 0 on deadlock detected, 1 on OK, 2 on recursive read + */ +static int +check_deadlock(struct task_struct *curr, struct held_lock *next, + struct lockdep_map *next_instance, int read) +{ + struct held_lock *prev; + int i; + + for (i = 0; i < curr->lockdep_depth; i++) { + prev = curr->held_locks + i; + if (prev->class != next->class) + continue; + /* + * Allow read-after-read recursion of the same + * lock class (i.e. read_lock(lock)+read_lock(lock)): + */ + if ((read == 2) && prev->read) + return 2; + return print_deadlock_bug(curr, prev, next); + } + return 1; +} + +/* + * There was a chain-cache miss, and we are about to add a new dependency + * to a previous lock. We recursively validate the following rules: + * + * - would the adding of the <prev> -> <next> dependency create a + * circular dependency in the graph? [== circular deadlock] + * + * - does the new prev->next dependency connect any hardirq-safe lock + * (in the full backwards-subgraph starting at <prev>) with any + * hardirq-unsafe lock (in the full forwards-subgraph starting at + * <next>)? [== illegal lock inversion with hardirq contexts] + * + * - does the new prev->next dependency connect any softirq-safe lock + * (in the full backwards-subgraph starting at <prev>) with any + * softirq-unsafe lock (in the full forwards-subgraph starting at + * <next>)? [== illegal lock inversion with softirq contexts] + * + * any of these scenarios could lead to a deadlock. + * + * Then if all the validations pass, we add the forwards and backwards + * dependency. + */ +static int +check_prev_add(struct task_struct *curr, struct held_lock *prev, + struct held_lock *next) +{ + struct lock_list *entry; + int ret; + + /* + * Prove that the new <prev> -> <next> dependency would not + * create a circular dependency in the graph. (We do this by + * forward-recursing into the graph starting at <next>, and + * checking whether we can reach <prev>.) + * + * We are using global variables to control the recursion, to + * keep the stackframe size of the recursive functions low: + */ + check_source = next; + check_target = prev; + if (!(check_noncircular(next->class, 0))) + return print_circular_bug_tail(); + +#ifdef CONFIG_TRACE_IRQFLAGS + /* + * Prove that the new dependency does not connect a hardirq-safe + * lock with a hardirq-unsafe lock - to achieve this we search + * the backwards-subgraph starting at <prev>, and the + * forwards-subgraph starting at <next>: + */ + if (!check_usage(curr, prev, next, LOCK_USED_IN_HARDIRQ, + LOCK_ENABLED_HARDIRQS, "hard")) + return 0; + + /* + * Prove that the new dependency does not connect a hardirq-safe-read + * lock with a hardirq-unsafe lock - to achieve this we search + * the backwards-subgraph starting at <prev>, and the + * forwards-subgraph starting at <next>: + */ + if (!check_usage(curr, prev, next, LOCK_USED_IN_HARDIRQ_READ, + LOCK_ENABLED_HARDIRQS, "hard-read")) + return 0; + + /* + * Prove that the new dependency does not connect a softirq-safe + * lock with a softirq-unsafe lock - to achieve this we search + * the backwards-subgraph starting at <prev>, and the + * forwards-subgraph starting at <next>: + */ + if (!check_usage(curr, prev, next, LOCK_USED_IN_SOFTIRQ, + LOCK_ENABLED_SOFTIRQS, "soft")) + return 0; + /* + * Prove that the new dependency does not connect a softirq-safe-read + * lock with a softirq-unsafe lock - to achieve this we search + * the backwards-subgraph starting at <prev>, and the + * forwards-subgraph starting at <next>: + */ + if (!check_usage(curr, prev, next, LOCK_USED_IN_SOFTIRQ_READ, + LOCK_ENABLED_SOFTIRQS, "soft")) + return 0; +#endif + /* + * For recursive read-locks we do all the dependency checks, + * but we dont store read-triggered dependencies (only + * write-triggered dependencies). This ensures that only the + * write-side dependencies matter, and that if for example a + * write-lock never takes any other locks, then the reads are + * equivalent to a NOP. + */ + if (next->read == 2 || prev->read == 2) + return 1; + /* + * Is the <prev> -> <next> dependency already present? + * + * (this may occur even though this is a new chain: consider + * e.g. the L1 -> L2 -> L3 -> L4 and the L5 -> L1 -> L2 -> L3 + * chains - the second one will be new, but L1 already has + * L2 added to its dependency list, due to the first chain.) + */ + list_for_each_entry(entry, &prev->class->locks_after, entry) { + if (entry->class == next->class) + return 2; + } + + /* + * Ok, all validations passed, add the new lock + * to the previous lock's dependency list: + */ + ret = add_lock_to_list(prev->class, next->class, + &prev->class->locks_after, next->acquire_ip); + if (!ret) + return 0; + /* + * Return value of 2 signals 'dependency already added', + * in that case we dont have to add the backlink either. + */ + if (ret == 2) + return 2; + ret = add_lock_to_list(next->class, prev->class, + &next->class->locks_before, next->acquire_ip); + + /* + * Debugging printouts: + */ + if (verbose(prev->class) || verbose(next->class)) { + __raw_spin_unlock(&hash_lock); + printk("\n new dependency: "); + print_lock_name(prev->class); + printk(" => "); + print_lock_name(next->class); + printk("\n"); + dump_stack(); + __raw_spin_lock(&hash_lock); + } + return 1; +} + +/* + * Add the dependency to all directly-previous locks that are 'relevant'. + * The ones that are relevant are (in increasing distance from curr): + * all consecutive trylock entries and the final non-trylock entry - or + * the end of this context's lock-chain - whichever comes first. + */ +static int +check_prevs_add(struct task_struct *curr, struct held_lock *next) +{ + int depth = curr->lockdep_depth; + struct held_lock *hlock; + + /* + * Debugging checks. + * + * Depth must not be zero for a non-head lock: + */ + if (!depth) + goto out_bug; + /* + * At least two relevant locks must exist for this + * to be a head: + */ + if (curr->held_locks[depth].irq_context != + curr->held_locks[depth-1].irq_context) + goto out_bug; + + for (;;) { + hlock = curr->held_locks + depth-1; + /* + * Only non-recursive-read entries get new dependencies + * added: + */ + if (hlock->read != 2) { + check_prev_add(curr, hlock, next); + /* + * Stop after the first non-trylock entry, + * as non-trylock entries have added their + * own direct dependencies already, so this + * lock is connected to them indirectly: + */ + if (!hlock->trylock) + break; + } + depth--; + /* + * End of lock-stack? + */ + if (!depth) + break; + /* + * Stop the search if we cross into another context: + */ + if (curr->held_locks[depth].irq_context != + curr->held_locks[depth-1].irq_context) + break; + } + return 1; +out_bug: + __raw_spin_unlock(&hash_lock); + DEBUG_LOCKS_WARN_ON(1); + + return 0; +} + + +/* + * Is this the address of a static object: + */ +static int static_obj(void *obj) +{ + unsigned long start = (unsigned long) &_stext, + end = (unsigned long) &_end, + addr = (unsigned long) obj; +#ifdef CONFIG_SMP + int i; +#endif + + /* + * static variable? + */ + if ((addr >= start) && (addr < end)) + return 1; + +#ifdef CONFIG_SMP + /* + * percpu var? + */ + for_each_possible_cpu(i) { + start = (unsigned long) &__per_cpu_start + per_cpu_offset(i); + end = (unsigned long) &__per_cpu_end + per_cpu_offset(i); + + if ((addr >= start) && (addr < end)) + return 1; + } +#endif + + /* + * module var? + */ + return is_module_address(addr); +} + +/* + * To make lock name printouts unique, we calculate a unique + * class->name_version generation counter: + */ +static int count_matching_names(struct lock_class *new_class) +{ + struct lock_class *class; + int count = 0; + + if (!new_class->name) + return 0; + + list_for_each_entry(class, &all_lock_classes, lock_entry) { + if (new_class->key - new_class->subclass == class->key) + return class->name_version; + if (class->name && !strcmp(class->name, new_class->name)) + count = max(count, class->name_version); + } + + return count + 1; +} + +extern void __error_too_big_MAX_LOCKDEP_SUBCLASSES(void); + +/* + * Register a lock's class in the hash-table, if the class is not present + * yet. Otherwise we look it up. We cache the result in the lock object + * itself, so actual lookup of the hash should be once per lock object. + */ +static inline struct lock_class * +look_up_lock_class(struct lockdep_map *lock, unsigned int subclass) +{ + struct lockdep_subclass_key *key; + struct list_head *hash_head; + struct lock_class *class; + +#ifdef CONFIG_DEBUG_LOCKDEP + /* + * If the architecture calls into lockdep before initializing + * the hashes then we'll warn about it later. (we cannot printk + * right now) + */ + if (unlikely(!lockdep_initialized)) { + lockdep_init(); + lockdep_init_error = 1; + } +#endif + + /* + * Static locks do not have their class-keys yet - for them the key + * is the lock object itself: + */ + if (unlikely(!lock->key)) + lock->key = (void *)lock; + + /* + * NOTE: the class-key must be unique. For dynamic locks, a static + * lock_class_key variable is passed in through the mutex_init() + * (or spin_lock_init()) call - which acts as the key. For static + * locks we use the lock object itself as the key. + */ + if (sizeof(struct lock_class_key) > sizeof(struct lock_class)) + __error_too_big_MAX_LOCKDEP_SUBCLASSES(); + + key = lock->key->subkeys + subclass; + + hash_head = classhashentry(key); + + /* + * We can walk the hash lockfree, because the hash only + * grows, and we are careful when adding entries to the end: + */ + list_for_each_entry(class, hash_head, hash_entry) + if (class->key == key) + return class; + + return NULL; +} + +/* + * Register a lock's class in the hash-table, if the class is not present + * yet. Otherwise we look it up. We cache the result in the lock object + * itself, so actual lookup of the hash should be once per lock object. + */ +static inline struct lock_class * +register_lock_class(struct lockdep_map *lock, unsigned int subclass, int force) +{ + struct lockdep_subclass_key *key; + struct list_head *hash_head; + struct lock_class *class; + + class = look_up_lock_class(lock, subclass); + if (likely(class)) + return class; + + /* + * Debug-check: all keys must be persistent! + */ + if (!static_obj(lock->key)) { + debug_locks_off(); + printk("INFO: trying to register non-static key.\n"); + printk("the code is fine but needs lockdep annotation.\n"); + printk("turning off the locking correctness validator.\n"); + dump_stack(); + + return NULL; + } + + key = lock->key->subkeys + subclass; + hash_head = classhashentry(key); + + __raw_spin_lock(&hash_lock); + /* + * We have to do the hash-walk again, to avoid races + * with another CPU: + */ + list_for_each_entry(class, hash_head, hash_entry) + if (class->key == key) + goto out_unlock_set; + /* + * Allocate a new key from the static array, and add it to + * the hash: + */ + if (nr_lock_classes >= MAX_LOCKDEP_KEYS) { + __raw_spin_unlock(&hash_lock); + debug_locks_off(); + printk("BUG: MAX_LOCKDEP_KEYS too low!\n"); + printk("turning off the locking correctness validator.\n"); + return NULL; + } + class = lock_classes + nr_lock_classes++; + debug_atomic_inc(&nr_unused_locks); + class->key = key; + class->name = lock->name; + class->subclass = subclass; + INIT_LIST_HEAD(&class->lock_entry); + INIT_LIST_HEAD(&class->locks_before); + INIT_LIST_HEAD(&class->locks_after); + class->name_version = count_matching_names(class); + /* + * We use RCU's safe list-add method to make + * parallel walking of the hash-list safe: + */ + list_add_tail_rcu(&class->hash_entry, hash_head); + + if (verbose(class)) { + __raw_spin_unlock(&hash_lock); + printk("\nnew class %p: %s", class->key, class->name); + if (class->name_version > 1) + printk("#%d", class->name_version); + printk("\n"); + dump_stack(); + __raw_spin_lock(&hash_lock); + } +out_unlock_set: + __raw_spin_unlock(&hash_lock); + + if (!subclass || force) + lock->class_cache = class; + + DEBUG_LOCKS_WARN_ON(class->subclass != subclass); + + return class; +} + +/* + * Look up a dependency chain. If the key is not present yet then + * add it and return 0 - in this case the new dependency chain is + * validated. If the key is already hashed, return 1. + */ +static inline int lookup_chain_cache(u64 chain_key) +{ + struct list_head *hash_head = chainhashentry(chain_key); + struct lock_chain *chain; + + DEBUG_LOCKS_WARN_ON(!irqs_disabled()); + /* + * We can walk it lock-free, because entries only get added + * to the hash: + */ + list_for_each_entry(chain, hash_head, entry) { + if (chain->chain_key == chain_key) { +cache_hit: + debug_atomic_inc(&chain_lookup_hits); + /* + * In the debugging case, force redundant checking + * by returning 1: + */ +#ifdef CONFIG_DEBUG_LOCKDEP + __raw_spin_lock(&hash_lock); + return 1; +#endif + return 0; + } + } + /* + * Allocate a new chain entry from the static array, and add + * it to the hash: + */ + __raw_spin_lock(&hash_lock); + /* + * We have to walk the chain again locked - to avoid duplicates: + */ + list_for_each_entry(chain, hash_head, entry) { + if (chain->chain_key == chain_key) { + __raw_spin_unlock(&hash_lock); + goto cache_hit; + } + } + if (unlikely(nr_lock_chains >= MAX_LOCKDEP_CHAINS)) { + __raw_spin_unlock(&hash_lock); + debug_locks_off(); + printk("BUG: MAX_LOCKDEP_CHAINS too low!\n"); + printk("turning off the locking correctness validator.\n"); + return 0; + } + chain = lock_chains + nr_lock_chains++; + chain->chain_key = chain_key; + list_add_tail_rcu(&chain->entry, hash_head); + debug_atomic_inc(&chain_lookup_misses); +#ifdef CONFIG_TRACE_IRQFLAGS + if (current->hardirq_context) + nr_hardirq_chains++; + else { + if (current->softirq_context) + nr_softirq_chains++; + else + nr_process_chains++; + } +#else + nr_process_chains++; +#endif + + return 1; +} + +/* + * We are building curr_chain_key incrementally, so double-check + * it from scratch, to make sure that it's done correctly: + */ +static void check_chain_key(struct task_struct *curr) +{ +#ifdef CONFIG_DEBUG_LOCKDEP + struct held_lock *hlock, *prev_hlock = NULL; + unsigned int i, id; + u64 chain_key = 0; + + for (i = 0; i < curr->lockdep_depth; i++) { + hlock = curr->held_locks + i; + if (chain_key != hlock->prev_chain_key) { + debug_locks_off(); + printk("hm#1, depth: %u [%u], %016Lx != %016Lx\n", + curr->lockdep_depth, i, + (unsigned long long)chain_key, + (unsigned long long)hlock->prev_chain_key); + WARN_ON(1); + return; + } + id = hlock->class - lock_classes; + DEBUG_LOCKS_WARN_ON(id >= MAX_LOCKDEP_KEYS); + if (prev_hlock && (prev_hlock->irq_context != + hlock->irq_context)) + chain_key = 0; + chain_key = iterate_chain_key(chain_key, id); + prev_hlock = hlock; + } + if (chain_key != curr->curr_chain_key) { + debug_locks_off(); + printk("hm#2, depth: %u [%u], %016Lx != %016Lx\n", + curr->lockdep_depth, i, + (unsigned long long)chain_key, + (unsigned long long)curr->curr_chain_key); + WARN_ON(1); + } +#endif +} + +#ifdef CONFIG_TRACE_IRQFLAGS + +/* + * print irq inversion bug: + */ +static int +print_irq_inversion_bug(struct task_struct *curr, struct lock_class *other, + struct held_lock *this, int forwards, + const char *irqclass) +{ + __raw_spin_unlock(&hash_lock); + debug_locks_off(); + if (debug_locks_silent) + return 0; + + printk("\n=========================================================\n"); + printk( "[ INFO: possible irq lock inversion dependency detected ]\n"); + print_kernel_version(); + printk( "---------------------------------------------------------\n"); + printk("%s/%d just changed the state of lock:\n", + curr->comm, curr->pid); + print_lock(this); + if (forwards) + printk("but this lock took another, %s-irq-unsafe lock in the past:\n", irqclass); + else + printk("but this lock was taken by another, %s-irq-safe lock in the past:\n", irqclass); + print_lock_name(other); + printk("\n\nand interrupts could create inverse lock ordering between them.\n\n"); + + printk("\nother info that might help us debug this:\n"); + lockdep_print_held_locks(curr); + + printk("\nthe first lock's dependencies:\n"); + print_lock_dependencies(this->class, 0); + + printk("\nthe second lock's dependencies:\n"); + print_lock_dependencies(other, 0); + + printk("\nstack backtrace:\n"); + dump_stack(); + + return 0; +} + +/* + * Prove that in the forwards-direction subgraph starting at <this> + * there is no lock matching <mask>: + */ +static int +check_usage_forwards(struct task_struct *curr, struct held_lock *this, + enum lock_usage_bit bit, const char *irqclass) +{ + int ret; + + find_usage_bit = bit; + /* fills in <forwards_match> */ + ret = find_usage_forwards(this->class, 0); + if (!ret || ret == 1) + return ret; + + return print_irq_inversion_bug(curr, forwards_match, this, 1, irqclass); +} + +/* + * Prove that in the backwards-direction subgraph starting at <this> + * there is no lock matching <mask>: + */ +static int +check_usage_backwards(struct task_struct *curr, struct held_lock *this, + enum lock_usage_bit bit, const char *irqclass) +{ + int ret; + + find_usage_bit = bit; + /* fills in <backwards_match> */ + ret = find_usage_backwards(this->class, 0); + if (!ret || ret == 1) + return ret; + + return print_irq_inversion_bug(curr, backwards_match, this, 0, irqclass); +} + +static inline void print_irqtrace_events(struct task_struct *curr) +{ + printk("irq event stamp: %u\n", curr->irq_events); + printk("hardirqs last enabled at (%u): ", curr->hardirq_enable_event); + print_ip_sym(curr->hardirq_enable_ip); + printk("hardirqs last disabled at (%u): ", curr->hardirq_disable_event); + print_ip_sym(curr->hardirq_disable_ip); + printk("softirqs last enabled at (%u): ", curr->softirq_enable_event); + print_ip_sym(curr->softirq_enable_ip); + printk("softirqs last disabled at (%u): ", curr->softirq_disable_event); + print_ip_sym(curr->softirq_disable_ip); +} + +#else +static inline void print_irqtrace_events(struct task_struct *curr) +{ +} +#endif + +static int +print_usage_bug(struct task_struct *curr, struct held_lock *this, + enum lock_usage_bit prev_bit, enum lock_usage_bit new_bit) +{ + __raw_spin_unlock(&hash_lock); + debug_locks_off(); + if (debug_locks_silent) + return 0; + + printk("\n=================================\n"); + printk( "[ INFO: inconsistent lock state ]\n"); + print_kernel_version(); + printk( "---------------------------------\n"); + + printk("inconsistent {%s} -> {%s} usage.\n", + usage_str[prev_bit], usage_str[new_bit]); + + printk("%s/%d [HC%u[%lu]:SC%u[%lu]:HE%u:SE%u] takes:\n", + curr->comm, curr->pid, + trace_hardirq_context(curr), hardirq_count() >> HARDIRQ_SHIFT, + trace_softirq_context(curr), softirq_count() >> SOFTIRQ_SHIFT, + trace_hardirqs_enabled(curr), + trace_softirqs_enabled(curr)); + print_lock(this); + + printk("{%s} state was registered at:\n", usage_str[prev_bit]); + print_stack_trace(this->class->usage_traces + prev_bit, 1); + + print_irqtrace_events(curr); + printk("\nother info that might help us debug this:\n"); + lockdep_print_held_locks(curr); + + printk("\nstack backtrace:\n"); + dump_stack(); + + return 0; +} + +/* + * Print out an error if an invalid bit is set: + */ +static inline int +valid_state(struct task_struct *curr, struct held_lock *this, + enum lock_usage_bit new_bit, enum lock_usage_bit bad_bit) +{ + if (unlikely(this->class->usage_mask & (1 << bad_bit))) + return print_usage_bug(curr, this, bad_bit, new_bit); + return 1; +} + +#define STRICT_READ_CHECKS 1 + +/* + * Mark a lock with a usage bit, and validate the state transition: + */ +static int mark_lock(struct task_struct *curr, struct held_lock *this, + enum lock_usage_bit new_bit, unsigned long ip) +{ + unsigned int new_mask = 1 << new_bit, ret = 1; + + /* + * If already set then do not dirty the cacheline, + * nor do any checks: + */ + if (likely(this->class->usage_mask & new_mask)) + return 1; + + __raw_spin_lock(&hash_lock); + /* + * Make sure we didnt race: + */ + if (unlikely(this->class->usage_mask & new_mask)) { + __raw_spin_unlock(&hash_lock); + return 1; + } + + this->class->usage_mask |= new_mask; + +#ifdef CONFIG_TRACE_IRQFLAGS + if (new_bit == LOCK_ENABLED_HARDIRQS || + new_bit == LOCK_ENABLED_HARDIRQS_READ) + ip = curr->hardirq_enable_ip; + else if (new_bit == LOCK_ENABLED_SOFTIRQS || + new_bit == LOCK_ENABLED_SOFTIRQS_READ) + ip = curr->softirq_enable_ip; +#endif + if (!save_trace(this->class->usage_traces + new_bit)) + return 0; + + switch (new_bit) { +#ifdef CONFIG_TRACE_IRQFLAGS + case LOCK_USED_IN_HARDIRQ: + if (!valid_state(curr, this, new_bit, LOCK_ENABLED_HARDIRQS)) + return 0; + if (!valid_state(curr, this, new_bit, + LOCK_ENABLED_HARDIRQS_READ)) + return 0; + /* + * just marked it hardirq-safe, check that this lock + * took no hardirq-unsafe lock in the past: + */ + if (!check_usage_forwards(curr, this, + LOCK_ENABLED_HARDIRQS, "hard")) + return 0; +#if STRICT_READ_CHECKS + /* + * just marked it hardirq-safe, check that this lock + * took no hardirq-unsafe-read lock in the past: + */ + if (!check_usage_forwards(curr, this, + LOCK_ENABLED_HARDIRQS_READ, "hard-read")) + return 0; +#endif + if (hardirq_verbose(this->class)) + ret = 2; + break; + case LOCK_USED_IN_SOFTIRQ: + if (!valid_state(curr, this, new_bit, LOCK_ENABLED_SOFTIRQS)) + return 0; + if (!valid_state(curr, this, new_bit, + LOCK_ENABLED_SOFTIRQS_READ)) + return 0; + /* + * just marked it softirq-safe, check that this lock + * took no softirq-unsafe lock in the past: + */ + if (!check_usage_forwards(curr, this, + LOCK_ENABLED_SOFTIRQS, "soft")) + return 0; +#if STRICT_READ_CHECKS + /* + * just marked it softirq-safe, check that this lock + * took no softirq-unsafe-read lock in the past: + */ + if (!check_usage_forwards(curr, this, + LOCK_ENABLED_SOFTIRQS_READ, "soft-read")) + return 0; +#endif + if (softirq_verbose(this->class)) + ret = 2; + break; + case LOCK_USED_IN_HARDIRQ_READ: + if (!valid_state(curr, this, new_bit, LOCK_ENABLED_HARDIRQS)) + return 0; + /* + * just marked it hardirq-read-safe, check that this lock + * took no hardirq-unsafe lock in the past: + */ + if (!check_usage_forwards(curr, this, + LOCK_ENABLED_HARDIRQS, "hard")) + return 0; + if (hardirq_verbose(this->class)) + ret = 2; + break; + case LOCK_USED_IN_SOFTIRQ_READ: + if (!valid_state(curr, this, new_bit, LOCK_ENABLED_SOFTIRQS)) + return 0; + /* + * just marked it softirq-read-safe, check that this lock + * took no softirq-unsafe lock in the past: + */ + if (!check_usage_forwards(curr, this, + LOCK_ENABLED_SOFTIRQS, "soft")) + return 0; + if (softirq_verbose(this->class)) + ret = 2; + break; + case LOCK_ENABLED_HARDIRQS: + if (!valid_state(curr, this, new_bit, LOCK_USED_IN_HARDIRQ)) + return 0; + if (!valid_state(curr, this, new_bit, + LOCK_USED_IN_HARDIRQ_READ)) + return 0; + /* + * just marked it hardirq-unsafe, check that no hardirq-safe + * lock in the system ever took it in the past: + */ + if (!check_usage_backwards(curr, this, + LOCK_USED_IN_HARDIRQ, "hard")) + return 0; +#if STRICT_READ_CHECKS + /* + * just marked it hardirq-unsafe, check that no + * hardirq-safe-read lock in the system ever took + * it in the past: + */ + if (!check_usage_backwards(curr, this, + LOCK_USED_IN_HARDIRQ_READ, "hard-read")) + return 0; +#endif + if (hardirq_verbose(this->class)) + ret = 2; + break; + case LOCK_ENABLED_SOFTIRQS: + if (!valid_state(curr, this, new_bit, LOCK_USED_IN_SOFTIRQ)) + return 0; + if (!valid_state(curr, this, new_bit, + LOCK_USED_IN_SOFTIRQ_READ)) + return 0; + /* + * just marked it softirq-unsafe, check that no softirq-safe + * lock in the system ever took it in the past: + */ + if (!check_usage_backwards(curr, this, + LOCK_USED_IN_SOFTIRQ, "soft")) + return 0; +#if STRICT_READ_CHECKS + /* + * just marked it softirq-unsafe, check that no + * softirq-safe-read lock in the system ever took + * it in the past: + */ + if (!check_usage_backwards(curr, this, + LOCK_USED_IN_SOFTIRQ_READ, "soft-read")) + return 0; +#endif + if (softirq_verbose(this->class)) + ret = 2; + break; + case LOCK_ENABLED_HARDIRQS_READ: + if (!valid_state(curr, this, new_bit, LOCK_USED_IN_HARDIRQ)) + return 0; +#if STRICT_READ_CHECKS + /* + * just marked it hardirq-read-unsafe, check that no + * hardirq-safe lock in the system ever took it in the past: + */ + if (!check_usage_backwards(curr, this, + LOCK_USED_IN_HARDIRQ, "hard")) + return 0; +#endif + if (hardirq_verbose(this->class)) + ret = 2; + break; + case LOCK_ENABLED_SOFTIRQS_READ: + if (!valid_state(curr, this, new_bit, LOCK_USED_IN_SOFTIRQ)) + return 0; +#if STRICT_READ_CHECKS + /* + * just marked it softirq-read-unsafe, check that no + * softirq-safe lock in the system ever took it in the past: + */ + if (!check_usage_backwards(curr, this, + LOCK_USED_IN_SOFTIRQ, "soft")) + return 0; +#endif + if (softirq_verbose(this->class)) + ret = 2; + break; +#endif + case LOCK_USED: + /* + * Add it to the global list of classes: + */ + list_add_tail_rcu(&this->class->lock_entry, &all_lock_classes); + debug_atomic_dec(&nr_unused_locks); + break; + default: + debug_locks_off(); + WARN_ON(1); + return 0; + } + + __raw_spin_unlock(&hash_lock); + + /* + * We must printk outside of the hash_lock: + */ + if (ret == 2) { + printk("\nmarked lock as {%s}:\n", usage_str[new_bit]); + print_lock(this); + print_irqtrace_events(curr); + dump_stack(); + } + + return ret; +} + +#ifdef CONFIG_TRACE_IRQFLAGS +/* + * Mark all held locks with a usage bit: + */ +static int +mark_held_locks(struct task_struct *curr, int hardirq, unsigned long ip) +{ + enum lock_usage_bit usage_bit; + struct held_lock *hlock; + int i; + + for (i = 0; i < curr->lockdep_depth; i++) { + hlock = curr->held_locks + i; + + if (hardirq) { + if (hlock->read) + usage_bit = LOCK_ENABLED_HARDIRQS_READ; + else + usage_bit = LOCK_ENABLED_HARDIRQS; + } else { + if (hlock->read) + usage_bit = LOCK_ENABLED_SOFTIRQS_READ; + else + usage_bit = LOCK_ENABLED_SOFTIRQS; + } + if (!mark_lock(curr, hlock, usage_bit, ip)) + return 0; + } + + return 1; +} + +/* + * Debugging helper: via this flag we know that we are in + * 'early bootup code', and will warn about any invalid irqs-on event: + */ +static int early_boot_irqs_enabled; + +void early_boot_irqs_off(void) +{ + early_boot_irqs_enabled = 0; +} + +void early_boot_irqs_on(void) +{ + early_boot_irqs_enabled = 1; +} + +/* + * Hardirqs will be enabled: + */ +void trace_hardirqs_on(void) +{ + struct task_struct *curr = current; + unsigned long ip; + + if (unlikely(!debug_locks || current->lockdep_recursion)) + return; + + if (DEBUG_LOCKS_WARN_ON(unlikely(!early_boot_irqs_enabled))) + return; + + if (unlikely(curr->hardirqs_enabled)) { + debug_atomic_inc(&redundant_hardirqs_on); + return; + } + /* we'll do an OFF -> ON transition: */ + curr->hardirqs_enabled = 1; + ip = (unsigned long) __builtin_return_address(0); + + if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) + return; + if (DEBUG_LOCKS_WARN_ON(current->hardirq_context)) + return; + /* + * We are going to turn hardirqs on, so set the + * usage bit for all held locks: + */ + if (!mark_held_locks(curr, 1, ip)) + return; + /* + * If we have softirqs enabled, then set the usage + * bit for all held locks. (disabled hardirqs prevented + * this bit from being set before) + */ + if (curr->softirqs_enabled) + if (!mark_held_locks(curr, 0, ip)) + return; + + curr->hardirq_enable_ip = ip; + curr->hardirq_enable_event = ++curr->irq_events; + debug_atomic_inc(&hardirqs_on_events); +} + +EXPORT_SYMBOL(trace_hardirqs_on); + +/* + * Hardirqs were disabled: + */ +void trace_hardirqs_off(void) +{ + struct task_struct *curr = current; + + if (unlikely(!debug_locks || current->lockdep_recursion)) + return; + + if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) + return; + + if (curr->hardirqs_enabled) { + /* + * We have done an ON -> OFF transition: + */ + curr->hardirqs_enabled = 0; + curr->hardirq_disable_ip = _RET_IP_; + curr->hardirq_disable_event = ++curr->irq_events; + debug_atomic_inc(&hardirqs_off_events); + } else + debug_atomic_inc(&redundant_hardirqs_off); +} + +EXPORT_SYMBOL(trace_hardirqs_off); + +/* + * Softirqs will be enabled: + */ +void trace_softirqs_on(unsigned long ip) +{ + struct task_struct *curr = current; + + if (unlikely(!debug_locks)) + return; + + if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) + return; + + if (curr->softirqs_enabled) { + debug_atomic_inc(&redundant_softirqs_on); + return; + } + + /* + * We'll do an OFF -> ON transition: + */ + curr->softirqs_enabled = 1; + curr->softirq_enable_ip = ip; + curr->softirq_enable_event = ++curr->irq_events; + debug_atomic_inc(&softirqs_on_events); + /* + * We are going to turn softirqs on, so set the + * usage bit for all held locks, if hardirqs are + * enabled too: + */ + if (curr->hardirqs_enabled) + mark_held_locks(curr, 0, ip); +} + +/* + * Softirqs were disabled: + */ +void trace_softirqs_off(unsigned long ip) +{ + struct task_struct *curr = current; + + if (unlikely(!debug_locks)) + return; + + if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) + return; + + if (curr->softirqs_enabled) { + /* + * We have done an ON -> OFF transition: + */ + curr->softirqs_enabled = 0; + curr->softirq_disable_ip = ip; + curr->softirq_disable_event = ++curr->irq_events; + debug_atomic_inc(&softirqs_off_events); + DEBUG_LOCKS_WARN_ON(!softirq_count()); + } else + debug_atomic_inc(&redundant_softirqs_off); +} + +#endif + +/* + * Initialize a lock instance's lock-class mapping info: + */ +void lockdep_init_map(struct lockdep_map *lock, const char *name, + struct lock_class_key *key, int subclass) +{ + if (unlikely(!debug_locks)) + return; + + if (DEBUG_LOCKS_WARN_ON(!key)) + return; + if (DEBUG_LOCKS_WARN_ON(!name)) + return; + /* + * Sanity check, the lock-class key must be persistent: + */ + if (!static_obj(key)) { + printk("BUG: key %p not in .data!\n", key); + DEBUG_LOCKS_WARN_ON(1); + return; + } + lock->name = name; + lock->key = key; + lock->class_cache = NULL; + if (subclass) + register_lock_class(lock, subclass, 1); +} + +EXPORT_SYMBOL_GPL(lockdep_init_map); + +/* + * This gets called for every mutex_lock*()/spin_lock*() operation. + * We maintain the dependency maps and validate the locking attempt: + */ +static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, + int trylock, int read, int check, int hardirqs_off, + unsigned long ip) +{ + struct task_struct *curr = current; + struct lock_class *class = NULL; + struct held_lock *hlock; + unsigned int depth, id; + int chain_head = 0; + u64 chain_key; + + if (unlikely(!debug_locks)) + return 0; + + if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) + return 0; + + if (unlikely(subclass >= MAX_LOCKDEP_SUBCLASSES)) { + debug_locks_off(); + printk("BUG: MAX_LOCKDEP_SUBCLASSES too low!\n"); + printk("turning off the locking correctness validator.\n"); + return 0; + } + + if (!subclass) + class = lock->class_cache; + /* + * Not cached yet or subclass? + */ + if (unlikely(!class)) { + class = register_lock_class(lock, subclass, 0); + if (!class) + return 0; + } + debug_atomic_inc((atomic_t *)&class->ops); + if (very_verbose(class)) { + printk("\nacquire class [%p] %s", class->key, class->name); + if (class->name_version > 1) + printk("#%d", class->name_version); + printk("\n"); + dump_stack(); + } + + /* + * Add the lock to the list of currently held locks. + * (we dont increase the depth just yet, up until the + * dependency checks are done) + */ + depth = curr->lockdep_depth; + if (DEBUG_LOCKS_WARN_ON(depth >= MAX_LOCK_DEPTH)) + return 0; + + hlock = curr->held_locks + depth; + + hlock->class = class; + hlock->acquire_ip = ip; + hlock->instance = lock; + hlock->trylock = trylock; + hlock->read = read; + hlock->check = check; + hlock->hardirqs_off = hardirqs_off; + + if (check != 2) + goto out_calc_hash; +#ifdef CONFIG_TRACE_IRQFLAGS + /* + * If non-trylock use in a hardirq or softirq context, then + * mark the lock as used in these contexts: + */ + if (!trylock) { + if (read) { + if (curr->hardirq_context) + if (!mark_lock(curr, hlock, + LOCK_USED_IN_HARDIRQ_READ, ip)) + return 0; + if (curr->softirq_context) + if (!mark_lock(curr, hlock, + LOCK_USED_IN_SOFTIRQ_READ, ip)) + return 0; + } else { + if (curr->hardirq_context) + if (!mark_lock(curr, hlock, LOCK_USED_IN_HARDIRQ, ip)) + return 0; + if (curr->softirq_context) + if (!mark_lock(curr, hlock, LOCK_USED_IN_SOFTIRQ, ip)) + return 0; + } + } + if (!hardirqs_off) { + if (read) { + if (!mark_lock(curr, hlock, + LOCK_ENABLED_HARDIRQS_READ, ip)) + return 0; + if (curr->softirqs_enabled) + if (!mark_lock(curr, hlock, + LOCK_ENABLED_SOFTIRQS_READ, ip)) + return 0; + } else { + if (!mark_lock(curr, hlock, + LOCK_ENABLED_HARDIRQS, ip)) + return 0; + if (curr->softirqs_enabled) + if (!mark_lock(curr, hlock, + LOCK_ENABLED_SOFTIRQS, ip)) + return 0; + } + } +#endif + /* mark it as used: */ + if (!mark_lock(curr, hlock, LOCK_USED, ip)) + return 0; +out_calc_hash: + /* + * Calculate the chain hash: it's the combined has of all the + * lock keys along the dependency chain. We save the hash value + * at every step so that we can get the current hash easily + * after unlock. The chain hash is then used to cache dependency + * results. + * + * The 'key ID' is what is the most compact key value to drive + * the hash, not class->key. + */ + id = class - lock_classes; + if (DEBUG_LOCKS_WARN_ON(id >= MAX_LOCKDEP_KEYS)) + return 0; + + chain_key = curr->curr_chain_key; + if (!depth) { + if (DEBUG_LOCKS_WARN_ON(chain_key != 0)) + return 0; + chain_head = 1; + } + + hlock->prev_chain_key = chain_key; + +#ifdef CONFIG_TRACE_IRQFLAGS + /* + * Keep track of points where we cross into an interrupt context: + */ + hlock->irq_context = 2*(curr->hardirq_context ? 1 : 0) + + curr->softirq_context; + if (depth) { + struct held_lock *prev_hlock; + + prev_hlock = curr->held_locks + depth-1; + /* + * If we cross into another context, reset the + * hash key (this also prevents the checking and the + * adding of the dependency to 'prev'): + */ + if (prev_hlock->irq_context != hlock->irq_context) { + chain_key = 0; + chain_head = 1; + } + } +#endif + chain_key = iterate_chain_key(chain_key, id); + curr->curr_chain_key = chain_key; + + /* + * Trylock needs to maintain the stack of held locks, but it + * does not add new dependencies, because trylock can be done + * in any order. + * + * We look up the chain_key and do the O(N^2) check and update of + * the dependencies only if this is a new dependency chain. + * (If lookup_chain_cache() returns with 1 it acquires + * hash_lock for us) + */ + if (!trylock && (check == 2) && lookup_chain_cache(chain_key)) { + /* + * Check whether last held lock: + * + * - is irq-safe, if this lock is irq-unsafe + * - is softirq-safe, if this lock is hardirq-unsafe + * + * And check whether the new lock's dependency graph + * could lead back to the previous lock. + * + * any of these scenarios could lead to a deadlock. If + * All validations + */ + int ret = check_deadlock(curr, hlock, lock, read); + + if (!ret) + return 0; + /* + * Mark recursive read, as we jump over it when + * building dependencies (just like we jump over + * trylock entries): + */ + if (ret == 2) + hlock->read = 2; + /* + * Add dependency only if this lock is not the head + * of the chain, and if it's not a secondary read-lock: + */ + if (!chain_head && ret != 2) + if (!check_prevs_add(curr, hlock)) + return 0; + __raw_spin_unlock(&hash_lock); + } + curr->lockdep_depth++; + check_chain_key(curr); + if (unlikely(curr->lockdep_depth >= MAX_LOCK_DEPTH)) { + debug_locks_off(); + printk("BUG: MAX_LOCK_DEPTH too low!\n"); + printk("turning off the locking correctness validator.\n"); + return 0; + } + if (unlikely(curr->lockdep_depth > max_lockdep_depth)) + max_lockdep_depth = curr->lockdep_depth; + + return 1; +} + +static int +print_unlock_inbalance_bug(struct task_struct *curr, struct lockdep_map *lock, + unsigned long ip) +{ + if (!debug_locks_off()) + return 0; + if (debug_locks_silent) + return 0; + + printk("\n=====================================\n"); + printk( "[ BUG: bad unlock balance detected! ]\n"); + printk( "-------------------------------------\n"); + printk("%s/%d is trying to release lock (", + curr->comm, curr->pid); + print_lockdep_cache(lock); + printk(") at:\n"); + print_ip_sym(ip); + printk("but there are no more locks to release!\n"); + printk("\nother info that might help us debug this:\n"); + lockdep_print_held_locks(curr); + + printk("\nstack backtrace:\n"); + dump_stack(); + + return 0; +} + +/* + * Common debugging checks for both nested and non-nested unlock: + */ +static int check_unlock(struct task_struct *curr, struct lockdep_map *lock, + unsigned long ip) +{ + if (unlikely(!debug_locks)) + return 0; + if (DEBUG_LOCKS_WARN_ON(!irqs_disabled())) + return 0; + + if (curr->lockdep_depth <= 0) + return print_unlock_inbalance_bug(curr, lock, ip); + + return 1; +} + +/* + * Remove the lock to the list of currently held locks in a + * potentially non-nested (out of order) manner. This is a + * relatively rare operation, as all the unlock APIs default + * to nested mode (which uses lock_release()): + */ +static int +lock_release_non_nested(struct task_struct *curr, + struct lockdep_map *lock, unsigned long ip) +{ + struct held_lock *hlock, *prev_hlock; + unsigned int depth; + int i; + + /* + * Check whether the lock exists in the current stack + * of held locks: + */ + depth = curr->lockdep_depth; + if (DEBUG_LOCKS_WARN_ON(!depth)) + return 0; + + prev_hlock = NULL; + for (i = depth-1; i >= 0; i--) { + hlock = curr->held_locks + i; + /* + * We must not cross into another context: + */ + if (prev_hlock && prev_hlock->irq_context != hlock->irq_context) + break; + if (hlock->instance == lock) + goto found_it; + prev_hlock = hlock; + } + return print_unlock_inbalance_bug(curr, lock, ip); + +found_it: + /* + * We have the right lock to unlock, 'hlock' points to it. + * Now we remove it from the stack, and add back the other + * entries (if any), recalculating the hash along the way: + */ + curr->lockdep_depth = i; + curr->curr_chain_key = hlock->prev_chain_key; + + for (i++; i < depth; i++) { + hlock = curr->held_locks + i; + if (!__lock_acquire(hlock->instance, + hlock->class->subclass, hlock->trylock, + hlock->read, hlock->check, hlock->hardirqs_off, + hlock->acquire_ip)) + return 0; + } + + if (DEBUG_LOCKS_WARN_ON(curr->lockdep_depth != depth - 1)) + return 0; + return 1; +} + +/* + * Remove the lock to the list of currently held locks - this gets + * called on mutex_unlock()/spin_unlock*() (or on a failed + * mutex_lock_interruptible()). This is done for unlocks that nest + * perfectly. (i.e. the current top of the lock-stack is unlocked) + */ +static int lock_release_nested(struct task_struct *curr, + struct lockdep_map *lock, unsigned long ip) +{ + struct held_lock *hlock; + unsigned int depth; + + /* + * Pop off the top of the lock stack: + */ + depth = curr->lockdep_depth - 1; + hlock = curr->held_locks + depth; + + /* + * Is the unlock non-nested: + */ + if (hlock->instance != lock) + return lock_release_non_nested(curr, lock, ip); + curr->lockdep_depth--; + + if (DEBUG_LOCKS_WARN_ON(!depth && (hlock->prev_chain_key != 0))) + return 0; + + curr->curr_chain_key = hlock->prev_chain_key; + +#ifdef CONFIG_DEBUG_LOCKDEP + hlock->prev_chain_key = 0; + hlock->class = NULL; + hlock->acquire_ip = 0; + hlock->irq_context = 0; +#endif + return 1; +} + +/* + * Remove the lock to the list of currently held locks - this gets + * called on mutex_unlock()/spin_unlock*() (or on a failed + * mutex_lock_interruptible()). This is done for unlocks that nest + * perfectly. (i.e. the current top of the lock-stack is unlocked) + */ +static void +__lock_release(struct lockdep_map *lock, int nested, unsigned long ip) +{ + struct task_struct *curr = current; + + if (!check_unlock(curr, lock, ip)) + return; + + if (nested) { + if (!lock_release_nested(curr, lock, ip)) + return; + } else { + if (!lock_release_non_nested(curr, lock, ip)) + return; + } + + check_chain_key(curr); +} + +/* + * Check whether we follow the irq-flags state precisely: + */ +static void check_flags(unsigned long flags) +{ +#if defined(CONFIG_DEBUG_LOCKDEP) && defined(CONFIG_TRACE_IRQFLAGS) + if (!debug_locks) + return; + + if (irqs_disabled_flags(flags)) + DEBUG_LOCKS_WARN_ON(current->hardirqs_enabled); + else + DEBUG_LOCKS_WARN_ON(!current->hardirqs_enabled); + + /* + * We dont accurately track softirq state in e.g. + * hardirq contexts (such as on 4KSTACKS), so only + * check if not in hardirq contexts: + */ + if (!hardirq_count()) { + if (softirq_count()) + DEBUG_LOCKS_WARN_ON(current->softirqs_enabled); + else + DEBUG_LOCKS_WARN_ON(!current->softirqs_enabled); + } + + if (!debug_locks) + print_irqtrace_events(current); +#endif +} + +/* + * We are not always called with irqs disabled - do that here, + * and also avoid lockdep recursion: + */ +void lock_acquire(struct lockdep_map *lock, unsigned int subclass, + int trylock, int read, int check, unsigned long ip) +{ + unsigned long flags; + + if (unlikely(current->lockdep_recursion)) + return; + + raw_local_irq_save(flags); + check_flags(flags); + + current->lockdep_recursion = 1; + __lock_acquire(lock, subclass, trylock, read, check, + irqs_disabled_flags(flags), ip); + current->lockdep_recursion = 0; + raw_local_irq_restore(flags); +} + +EXPORT_SYMBOL_GPL(lock_acquire); + +void lock_release(struct lockdep_map *lock, int nested, unsigned long ip) +{ + unsigned long flags; + + if (unlikely(current->lockdep_recursion)) + return; + + raw_local_irq_save(flags); + check_flags(flags); + current->lockdep_recursion = 1; + __lock_release(lock, nested, ip); + current->lockdep_recursion = 0; + raw_local_irq_restore(flags); +} + +EXPORT_SYMBOL_GPL(lock_release); + +/* + * Used by the testsuite, sanitize the validator state + * after a simulated failure: + */ + +void lockdep_reset(void) +{ + unsigned long flags; + + raw_local_irq_save(flags); + current->curr_chain_key = 0; + current->lockdep_depth = 0; + current->lockdep_recursion = 0; + memset(current->held_locks, 0, MAX_LOCK_DEPTH*sizeof(struct held_lock)); + nr_hardirq_chains = 0; + nr_softirq_chains = 0; + nr_process_chains = 0; + debug_locks = 1; + raw_local_irq_restore(flags); +} + +static void zap_class(struct lock_class *class) +{ + int i; + + /* + * Remove all dependencies this lock is + * involved in: + */ + for (i = 0; i < nr_list_entries; i++) { + if (list_entries[i].class == class) + list_del_rcu(&list_entries[i].entry); + } + /* + * Unhash the class and remove it from the all_lock_classes list: + */ + list_del_rcu(&class->hash_entry); + list_del_rcu(&class->lock_entry); + +} + +static inline int within(void *addr, void *start, unsigned long size) +{ + return addr >= start && addr < start + size; +} + +void lockdep_free_key_range(void *start, unsigned long size) +{ + struct lock_class *class, *next; + struct list_head *head; + unsigned long flags; + int i; + + raw_local_irq_save(flags); + __raw_spin_lock(&hash_lock); + + /* + * Unhash all classes that were created by this module: + */ + for (i = 0; i < CLASSHASH_SIZE; i++) { + head = classhash_table + i; + if (list_empty(head)) + continue; + list_for_each_entry_safe(class, next, head, hash_entry) + if (within(class->key, start, size)) + zap_class(class); + } + + __raw_spin_unlock(&hash_lock); + raw_local_irq_restore(flags); +} + +void lockdep_reset_lock(struct lockdep_map *lock) +{ + struct lock_class *class, *next; + struct list_head *head; + unsigned long flags; + int i, j; + + raw_local_irq_save(flags); + + /* + * Remove all classes this lock might have: + */ + for (j = 0; j < MAX_LOCKDEP_SUBCLASSES; j++) { + /* + * If the class exists we look it up and zap it: + */ + class = look_up_lock_class(lock, j); + if (class) + zap_class(class); + } + /* + * Debug check: in the end all mapped classes should + * be gone. + */ + __raw_spin_lock(&hash_lock); + for (i = 0; i < CLASSHASH_SIZE; i++) { + head = classhash_table + i; + if (list_empty(head)) + continue; + list_for_each_entry_safe(class, next, head, hash_entry) { + if (unlikely(class == lock->class_cache)) { + __raw_spin_unlock(&hash_lock); + DEBUG_LOCKS_WARN_ON(1); + goto out_restore; + } + } + } + __raw_spin_unlock(&hash_lock); + +out_restore: + raw_local_irq_restore(flags); +} + +void __init lockdep_init(void) +{ + int i; + + /* + * Some architectures have their own start_kernel() + * code which calls lockdep_init(), while we also + * call lockdep_init() from the start_kernel() itself, + * and we want to initialize the hashes only once: + */ + if (lockdep_initialized) + return; + + for (i = 0; i < CLASSHASH_SIZE; i++) + INIT_LIST_HEAD(classhash_table + i); + + for (i = 0; i < CHAINHASH_SIZE; i++) + INIT_LIST_HEAD(chainhash_table + i); + + lockdep_initialized = 1; +} + +void __init lockdep_info(void) +{ + printk("Lock dependency validator: Copyright (c) 2006 Red Hat, Inc., Ingo Molnar\n"); + + printk("... MAX_LOCKDEP_SUBCLASSES: %lu\n", MAX_LOCKDEP_SUBCLASSES); + printk("... MAX_LOCK_DEPTH: %lu\n", MAX_LOCK_DEPTH); + printk("... MAX_LOCKDEP_KEYS: %lu\n", MAX_LOCKDEP_KEYS); + printk("... CLASSHASH_SIZE: %lu\n", CLASSHASH_SIZE); + printk("... MAX_LOCKDEP_ENTRIES: %lu\n", MAX_LOCKDEP_ENTRIES); + printk("... MAX_LOCKDEP_CHAINS: %lu\n", MAX_LOCKDEP_CHAINS); + printk("... CHAINHASH_SIZE: %lu\n", CHAINHASH_SIZE); + + printk(" memory used by lock dependency info: %lu kB\n", + (sizeof(struct lock_class) * MAX_LOCKDEP_KEYS + + sizeof(struct list_head) * CLASSHASH_SIZE + + sizeof(struct lock_list) * MAX_LOCKDEP_ENTRIES + + sizeof(struct lock_chain) * MAX_LOCKDEP_CHAINS + + sizeof(struct list_head) * CHAINHASH_SIZE) / 1024); + + printk(" per task-struct memory footprint: %lu bytes\n", + sizeof(struct held_lock) * MAX_LOCK_DEPTH); + +#ifdef CONFIG_DEBUG_LOCKDEP + if (lockdep_init_error) + printk("WARNING: lockdep init error! Arch code didnt call lockdep_init() early enough?\n"); +#endif +} + +static inline int in_range(const void *start, const void *addr, const void *end) +{ + return addr >= start && addr <= end; +} + +static void +print_freed_lock_bug(struct task_struct *curr, const void *mem_from, + const void *mem_to, struct held_lock *hlock) +{ + if (!debug_locks_off()) + return; + if (debug_locks_silent) + return; + + printk("\n=========================\n"); + printk( "[ BUG: held lock freed! ]\n"); + printk( "-------------------------\n"); + printk("%s/%d is freeing memory %p-%p, with a lock still held there!\n", + curr->comm, curr->pid, mem_from, mem_to-1); + print_lock(hlock); + lockdep_print_held_locks(curr); + + printk("\nstack backtrace:\n"); + dump_stack(); +} + +/* + * Called when kernel memory is freed (or unmapped), or if a lock + * is destroyed or reinitialized - this code checks whether there is + * any held lock in the memory range of <from> to <to>: + */ +void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len) +{ + const void *mem_to = mem_from + mem_len, *lock_from, *lock_to; + struct task_struct *curr = current; + struct held_lock *hlock; + unsigned long flags; + int i; + + if (unlikely(!debug_locks)) + return; + + local_irq_save(flags); + for (i = 0; i < curr->lockdep_depth; i++) { + hlock = curr->held_locks + i; + + lock_from = (void *)hlock->instance; + lock_to = (void *)(hlock->instance + 1); + + if (!in_range(mem_from, lock_from, mem_to) && + !in_range(mem_from, lock_to, mem_to)) + continue; + + print_freed_lock_bug(curr, mem_from, mem_to, hlock); + break; + } + local_irq_restore(flags); +} +EXPORT_SYMBOL_GPL(debug_check_no_locks_freed); + +static void print_held_locks_bug(struct task_struct *curr) +{ + if (!debug_locks_off()) + return; + if (debug_locks_silent) + return; + + printk("\n=====================================\n"); + printk( "[ BUG: lock held at task exit time! ]\n"); + printk( "-------------------------------------\n"); + printk("%s/%d is exiting with locks still held!\n", + curr->comm, curr->pid); + lockdep_print_held_locks(curr); + + printk("\nstack backtrace:\n"); + dump_stack(); +} + +void debug_check_no_locks_held(struct task_struct *task) +{ + if (unlikely(task->lockdep_depth > 0)) + print_held_locks_bug(task); +} + +void debug_show_all_locks(void) +{ + struct task_struct *g, *p; + int count = 10; + int unlock = 1; + + printk("\nShowing all locks held in the system:\n"); + + /* + * Here we try to get the tasklist_lock as hard as possible, + * if not successful after 2 seconds we ignore it (but keep + * trying). This is to enable a debug printout even if a + * tasklist_lock-holding task deadlocks or crashes. + */ +retry: + if (!read_trylock(&tasklist_lock)) { + if (count == 10) + printk("hm, tasklist_lock locked, retrying... "); + if (count) { + count--; + printk(" #%d", 10-count); + mdelay(200); + goto retry; + } + printk(" ignoring it.\n"); + unlock = 0; + } + if (count != 10) + printk(" locked it.\n"); + + do_each_thread(g, p) { + if (p->lockdep_depth) + lockdep_print_held_locks(p); + if (!unlock) + if (read_trylock(&tasklist_lock)) + unlock = 1; + } while_each_thread(g, p); + + printk("\n"); + printk("=============================================\n\n"); + + if (unlock) + read_unlock(&tasklist_lock); +} + +EXPORT_SYMBOL_GPL(debug_show_all_locks); + +void debug_show_held_locks(struct task_struct *task) +{ + lockdep_print_held_locks(task); +} + +EXPORT_SYMBOL_GPL(debug_show_held_locks); + diff --git a/kernel/lockdep_internals.h b/kernel/lockdep_internals.h new file mode 100644 index 000000000..eab043c83 --- /dev/null +++ b/kernel/lockdep_internals.h @@ -0,0 +1,78 @@ +/* + * kernel/lockdep_internals.h + * + * Runtime locking correctness validator + * + * lockdep subsystem internal functions and variables. + */ + +/* + * MAX_LOCKDEP_ENTRIES is the maximum number of lock dependencies + * we track. + * + * We use the per-lock dependency maps in two ways: we grow it by adding + * every to-be-taken lock to all currently held lock's own dependency + * table (if it's not there yet), and we check it for lock order + * conflicts and deadlocks. + */ +#define MAX_LOCKDEP_ENTRIES 8192UL + +#define MAX_LOCKDEP_KEYS_BITS 11 +#define MAX_LOCKDEP_KEYS (1UL << MAX_LOCKDEP_KEYS_BITS) + +#define MAX_LOCKDEP_CHAINS_BITS 13 +#define MAX_LOCKDEP_CHAINS (1UL << MAX_LOCKDEP_CHAINS_BITS) + +/* + * Stack-trace: tightly packed array of stack backtrace + * addresses. Protected by the hash_lock. + */ +#define MAX_STACK_TRACE_ENTRIES 262144UL + +extern struct list_head all_lock_classes; + +extern void +get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4); + +extern const char * __get_key_name(struct lockdep_subclass_key *key, char *str); + +extern unsigned long nr_lock_classes; +extern unsigned long nr_list_entries; +extern unsigned long nr_lock_chains; +extern unsigned long nr_stack_trace_entries; + +extern unsigned int nr_hardirq_chains; +extern unsigned int nr_softirq_chains; +extern unsigned int nr_process_chains; +extern unsigned int max_lockdep_depth; +extern unsigned int max_recursion_depth; + +#ifdef CONFIG_DEBUG_LOCKDEP +/* + * Various lockdep statistics: + */ +extern atomic_t chain_lookup_hits; +extern atomic_t chain_lookup_misses; +extern atomic_t hardirqs_on_events; +extern atomic_t hardirqs_off_events; +extern atomic_t redundant_hardirqs_on; +extern atomic_t redundant_hardirqs_off; +extern atomic_t softirqs_on_events; +extern atomic_t softirqs_off_events; +extern atomic_t redundant_softirqs_on; +extern atomic_t redundant_softirqs_off; +extern atomic_t nr_unused_locks; +extern atomic_t nr_cyclic_checks; +extern atomic_t nr_cyclic_check_recursions; +extern atomic_t nr_find_usage_forwards_checks; +extern atomic_t nr_find_usage_forwards_recursions; +extern atomic_t nr_find_usage_backwards_checks; +extern atomic_t nr_find_usage_backwards_recursions; +# define debug_atomic_inc(ptr) atomic_inc(ptr) +# define debug_atomic_dec(ptr) atomic_dec(ptr) +# define debug_atomic_read(ptr) atomic_read(ptr) +#else +# define debug_atomic_inc(ptr) do { } while (0) +# define debug_atomic_dec(ptr) do { } while (0) +# define debug_atomic_read(ptr) 0 +#endif diff --git a/kernel/lockdep_proc.c b/kernel/lockdep_proc.c new file mode 100644 index 000000000..f6e72eaab --- /dev/null +++ b/kernel/lockdep_proc.c @@ -0,0 +1,345 @@ +/* + * kernel/lockdep_proc.c + * + * Runtime locking correctness validator + * + * Started by Ingo Molnar: + * + * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + * + * Code for /proc/lockdep and /proc/lockdep_stats: + * + */ +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#include <linux/kallsyms.h> +#include <linux/debug_locks.h> + +#include "lockdep_internals.h" + +static void *l_next(struct seq_file *m, void *v, loff_t *pos) +{ + struct lock_class *class = v; + + (*pos)++; + + if (class->lock_entry.next != &all_lock_classes) + class = list_entry(class->lock_entry.next, struct lock_class, + lock_entry); + else + class = NULL; + m->private = class; + + return class; +} + +static void *l_start(struct seq_file *m, loff_t *pos) +{ + struct lock_class *class = m->private; + + if (&class->lock_entry == all_lock_classes.next) + seq_printf(m, "all lock classes:\n"); + + return class; +} + +static void l_stop(struct seq_file *m, void *v) +{ +} + +static unsigned long count_forward_deps(struct lock_class *class) +{ + struct lock_list *entry; + unsigned long ret = 1; + + /* + * Recurse this class's dependency list: + */ + list_for_each_entry(entry, &class->locks_after, entry) + ret += count_forward_deps(entry->class); + + return ret; +} + +static unsigned long count_backward_deps(struct lock_class *class) +{ + struct lock_list *entry; + unsigned long ret = 1; + + /* + * Recurse this class's dependency list: + */ + list_for_each_entry(entry, &class->locks_before, entry) + ret += count_backward_deps(entry->class); + + return ret; +} + +static int l_show(struct seq_file *m, void *v) +{ + unsigned long nr_forward_deps, nr_backward_deps; + struct lock_class *class = m->private; + char str[128], c1, c2, c3, c4; + const char *name; + + seq_printf(m, "%p", class->key); +#ifdef CONFIG_DEBUG_LOCKDEP + seq_printf(m, " OPS:%8ld", class->ops); +#endif + nr_forward_deps = count_forward_deps(class); + seq_printf(m, " FD:%5ld", nr_forward_deps); + + nr_backward_deps = count_backward_deps(class); + seq_printf(m, " BD:%5ld", nr_backward_deps); + + get_usage_chars(class, &c1, &c2, &c3, &c4); + seq_printf(m, " %c%c%c%c", c1, c2, c3, c4); + + name = class->name; + if (!name) { + name = __get_key_name(class->key, str); + seq_printf(m, ": %s", name); + } else{ + seq_printf(m, ": %s", name); + if (class->name_version > 1) + seq_printf(m, "#%d", class->name_version); + if (class->subclass) + seq_printf(m, "/%d", class->subclass); + } + seq_puts(m, "\n"); + + return 0; +} + +static struct seq_operations lockdep_ops = { + .start = l_start, + .next = l_next, + .stop = l_stop, + .show = l_show, +}; + +static int lockdep_open(struct inode *inode, struct file *file) +{ + int res = seq_open(file, &lockdep_ops); + if (!res) { + struct seq_file *m = file->private_data; + + if (!list_empty(&all_lock_classes)) + m->private = list_entry(all_lock_classes.next, + struct lock_class, lock_entry); + else + m->private = NULL; + } + return res; +} + +static struct file_operations proc_lockdep_operations = { + .open = lockdep_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static void lockdep_stats_debug_show(struct seq_file *m) +{ +#ifdef CONFIG_DEBUG_LOCKDEP + unsigned int hi1 = debug_atomic_read(&hardirqs_on_events), + hi2 = debug_atomic_read(&hardirqs_off_events), + hr1 = debug_atomic_read(&redundant_hardirqs_on), + hr2 = debug_atomic_read(&redundant_hardirqs_off), + si1 = debug_atomic_read(&softirqs_on_events), + si2 = debug_atomic_read(&softirqs_off_events), + sr1 = debug_atomic_read(&redundant_softirqs_on), + sr2 = debug_atomic_read(&redundant_softirqs_off); + + seq_printf(m, " chain lookup misses: %11u\n", + debug_atomic_read(&chain_lookup_misses)); + seq_printf(m, " chain lookup hits: %11u\n", + debug_atomic_read(&chain_lookup_hits)); + seq_printf(m, " cyclic checks: %11u\n", + debug_atomic_read(&nr_cyclic_checks)); + seq_printf(m, " cyclic-check recursions: %11u\n", + debug_atomic_read(&nr_cyclic_check_recursions)); + seq_printf(m, " find-mask forwards checks: %11u\n", + debug_atomic_read(&nr_find_usage_forwards_checks)); + seq_printf(m, " find-mask forwards recursions: %11u\n", + debug_atomic_read(&nr_find_usage_forwards_recursions)); + seq_printf(m, " find-mask backwards checks: %11u\n", + debug_atomic_read(&nr_find_usage_backwards_checks)); + seq_printf(m, " find-mask backwards recursions:%11u\n", + debug_atomic_read(&nr_find_usage_backwards_recursions)); + + seq_printf(m, " hardirq on events: %11u\n", hi1); + seq_printf(m, " hardirq off events: %11u\n", hi2); + seq_printf(m, " redundant hardirq ons: %11u\n", hr1); + seq_printf(m, " redundant hardirq offs: %11u\n", hr2); + seq_printf(m, " softirq on events: %11u\n", si1); + seq_printf(m, " softirq off events: %11u\n", si2); + seq_printf(m, " redundant softirq ons: %11u\n", sr1); + seq_printf(m, " redundant softirq offs: %11u\n", sr2); +#endif +} + +static int lockdep_stats_show(struct seq_file *m, void *v) +{ + struct lock_class *class; + unsigned long nr_unused = 0, nr_uncategorized = 0, + nr_irq_safe = 0, nr_irq_unsafe = 0, + nr_softirq_safe = 0, nr_softirq_unsafe = 0, + nr_hardirq_safe = 0, nr_hardirq_unsafe = 0, + nr_irq_read_safe = 0, nr_irq_read_unsafe = 0, + nr_softirq_read_safe = 0, nr_softirq_read_unsafe = 0, + nr_hardirq_read_safe = 0, nr_hardirq_read_unsafe = 0, + sum_forward_deps = 0, factor = 0; + + list_for_each_entry(class, &all_lock_classes, lock_entry) { + + if (class->usage_mask == 0) + nr_unused++; + if (class->usage_mask == LOCKF_USED) + nr_uncategorized++; + if (class->usage_mask & LOCKF_USED_IN_IRQ) + nr_irq_safe++; + if (class->usage_mask & LOCKF_ENABLED_IRQS) + nr_irq_unsafe++; + if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ) + nr_softirq_safe++; + if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS) + nr_softirq_unsafe++; + if (class->usage_mask & LOCKF_USED_IN_HARDIRQ) + nr_hardirq_safe++; + if (class->usage_mask & LOCKF_ENABLED_HARDIRQS) + nr_hardirq_unsafe++; + if (class->usage_mask & LOCKF_USED_IN_IRQ_READ) + nr_irq_read_safe++; + if (class->usage_mask & LOCKF_ENABLED_IRQS_READ) + nr_irq_read_unsafe++; + if (class->usage_mask & LOCKF_USED_IN_SOFTIRQ_READ) + nr_softirq_read_safe++; + if (class->usage_mask & LOCKF_ENABLED_SOFTIRQS_READ) + nr_softirq_read_unsafe++; + if (class->usage_mask & LOCKF_USED_IN_HARDIRQ_READ) + nr_hardirq_read_safe++; + if (class->usage_mask & LOCKF_ENABLED_HARDIRQS_READ) + nr_hardirq_read_unsafe++; + + sum_forward_deps += count_forward_deps(class); + } +#ifdef CONFIG_LOCKDEP_DEBUG + DEBUG_LOCKS_WARN_ON(debug_atomic_read(&nr_unused_locks) != nr_unused); +#endif + seq_printf(m, " lock-classes: %11lu [max: %lu]\n", + nr_lock_classes, MAX_LOCKDEP_KEYS); + seq_printf(m, " direct dependencies: %11lu [max: %lu]\n", + nr_list_entries, MAX_LOCKDEP_ENTRIES); + seq_printf(m, " indirect dependencies: %11lu\n", + sum_forward_deps); + + /* + * Total number of dependencies: + * + * All irq-safe locks may nest inside irq-unsafe locks, + * plus all the other known dependencies: + */ + seq_printf(m, " all direct dependencies: %11lu\n", + nr_irq_unsafe * nr_irq_safe + + nr_hardirq_unsafe * nr_hardirq_safe + + nr_list_entries); + + /* + * Estimated factor between direct and indirect + * dependencies: + */ + if (nr_list_entries) + factor = sum_forward_deps / nr_list_entries; + + seq_printf(m, " dependency chains: %11lu [max: %lu]\n", + nr_lock_chains, MAX_LOCKDEP_CHAINS); + +#ifdef CONFIG_TRACE_IRQFLAGS + seq_printf(m, " in-hardirq chains: %11u\n", + nr_hardirq_chains); + seq_printf(m, " in-softirq chains: %11u\n", + nr_softirq_chains); +#endif + seq_printf(m, " in-process chains: %11u\n", + nr_process_chains); + seq_printf(m, " stack-trace entries: %11lu [max: %lu]\n", + nr_stack_trace_entries, MAX_STACK_TRACE_ENTRIES); + seq_printf(m, " combined max dependencies: %11u\n", + (nr_hardirq_chains + 1) * + (nr_softirq_chains + 1) * + (nr_process_chains + 1) + ); + seq_printf(m, " hardirq-safe locks: %11lu\n", + nr_hardirq_safe); + seq_printf(m, " hardirq-unsafe locks: %11lu\n", + nr_hardirq_unsafe); + seq_printf(m, " softirq-safe locks: %11lu\n", + nr_softirq_safe); + seq_printf(m, " softirq-unsafe locks: %11lu\n", + nr_softirq_unsafe); + seq_printf(m, " irq-safe locks: %11lu\n", + nr_irq_safe); + seq_printf(m, " irq-unsafe locks: %11lu\n", + nr_irq_unsafe); + + seq_printf(m, " hardirq-read-safe locks: %11lu\n", + nr_hardirq_read_safe); + seq_printf(m, " hardirq-read-unsafe locks: %11lu\n", + nr_hardirq_read_unsafe); + seq_printf(m, " softirq-read-safe locks: %11lu\n", + nr_softirq_read_safe); + seq_printf(m, " softirq-read-unsafe locks: %11lu\n", + nr_softirq_read_unsafe); + seq_printf(m, " irq-read-safe locks: %11lu\n", + nr_irq_read_safe); + seq_printf(m, " irq-read-unsafe locks: %11lu\n", + nr_irq_read_unsafe); + + seq_printf(m, " uncategorized locks: %11lu\n", + nr_uncategorized); + seq_printf(m, " unused locks: %11lu\n", + nr_unused); + seq_printf(m, " max locking depth: %11u\n", + max_lockdep_depth); + seq_printf(m, " max recursion depth: %11u\n", + max_recursion_depth); + lockdep_stats_debug_show(m); + seq_printf(m, " debug_locks: %11u\n", + debug_locks); + + return 0; +} + +static int lockdep_stats_open(struct inode *inode, struct file *file) +{ + return single_open(file, lockdep_stats_show, NULL); +} + +static struct file_operations proc_lockdep_stats_operations = { + .open = lockdep_stats_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static int __init lockdep_proc_init(void) +{ + struct proc_dir_entry *entry; + + entry = create_proc_entry("lockdep", S_IRUSR, NULL); + if (entry) + entry->proc_fops = &proc_lockdep_operations; + + entry = create_proc_entry("lockdep_stats", S_IRUSR, NULL); + if (entry) + entry->proc_fops = &proc_lockdep_stats_operations; + + return 0; +} + +__initcall(lockdep_proc_init); + diff --git a/kernel/rtmutex-debug.c b/kernel/rtmutex-debug.c new file mode 100644 index 000000000..da8d6bf46 --- /dev/null +++ b/kernel/rtmutex-debug.c @@ -0,0 +1,241 @@ +/* + * RT-Mutexes: blocking mutual exclusion locks with PI support + * + * started by Ingo Molnar and Thomas Gleixner: + * + * Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + * Copyright (C) 2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com> + * + * This code is based on the rt.c implementation in the preempt-rt tree. + * Portions of said code are + * + * Copyright (C) 2004 LynuxWorks, Inc., Igor Manyilov, Bill Huey + * Copyright (C) 2006 Esben Nielsen + * Copyright (C) 2006 Kihon Technologies Inc., + * Steven Rostedt <rostedt@goodmis.org> + * + * See rt.c in preempt-rt for proper credits and further information + */ +#include <linux/sched.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/spinlock.h> +#include <linux/kallsyms.h> +#include <linux/syscalls.h> +#include <linux/interrupt.h> +#include <linux/plist.h> +#include <linux/fs.h> +#include <linux/debug_locks.h> + +#include "rtmutex_common.h" + +#ifdef CONFIG_DEBUG_RT_MUTEXES +# include "rtmutex-debug.h" +#else +# include "rtmutex.h" +#endif + +# define TRACE_WARN_ON(x) WARN_ON(x) +# define TRACE_BUG_ON(x) BUG_ON(x) + +# define TRACE_OFF() \ +do { \ + if (rt_trace_on) { \ + rt_trace_on = 0; \ + console_verbose(); \ + if (spin_is_locked(¤t->pi_lock)) \ + spin_unlock(¤t->pi_lock); \ + } \ +} while (0) + +# define TRACE_OFF_NOLOCK() \ +do { \ + if (rt_trace_on) { \ + rt_trace_on = 0; \ + console_verbose(); \ + } \ +} while (0) + +# define TRACE_BUG_LOCKED() \ +do { \ + TRACE_OFF(); \ + BUG(); \ +} while (0) + +# define TRACE_WARN_ON_LOCKED(c) \ +do { \ + if (unlikely(c)) { \ + TRACE_OFF(); \ + WARN_ON(1); \ + } \ +} while (0) + +# define TRACE_BUG_ON_LOCKED(c) \ +do { \ + if (unlikely(c)) \ + TRACE_BUG_LOCKED(); \ +} while (0) + +#ifdef CONFIG_SMP +# define SMP_TRACE_BUG_ON_LOCKED(c) TRACE_BUG_ON_LOCKED(c) +#else +# define SMP_TRACE_BUG_ON_LOCKED(c) do { } while (0) +#endif + +/* + * deadlock detection flag. We turn it off when we detect + * the first problem because we dont want to recurse back + * into the tracing code when doing error printk or + * executing a BUG(): + */ +int rt_trace_on = 1; + +void deadlock_trace_off(void) +{ + rt_trace_on = 0; +} + +static void printk_task(struct task_struct *p) +{ + if (p) + printk("%16s:%5d [%p, %3d]", p->comm, p->pid, p, p->prio); + else + printk("<none>"); +} + +static void printk_lock(struct rt_mutex *lock, int print_owner) +{ + if (lock->name) + printk(" [%p] {%s}\n", + lock, lock->name); + else + printk(" [%p] {%s:%d}\n", + lock, lock->file, lock->line); + + if (print_owner && rt_mutex_owner(lock)) { + printk(".. ->owner: %p\n", lock->owner); + printk(".. held by: "); + printk_task(rt_mutex_owner(lock)); + printk("\n"); + } +} + +void rt_mutex_debug_task_free(struct task_struct *task) +{ + WARN_ON(!plist_head_empty(&task->pi_waiters)); + WARN_ON(task->pi_blocked_on); +} + +/* + * We fill out the fields in the waiter to store the information about + * the deadlock. We print when we return. act_waiter can be NULL in + * case of a remove waiter operation. + */ +void debug_rt_mutex_deadlock(int detect, struct rt_mutex_waiter *act_waiter, + struct rt_mutex *lock) +{ + struct task_struct *task; + + if (!rt_trace_on || detect || !act_waiter) + return; + + task = rt_mutex_owner(act_waiter->lock); + if (task && task != current) { + act_waiter->deadlock_task_pid = task->pid; + act_waiter->deadlock_lock = lock; + } +} + +void debug_rt_mutex_print_deadlock(struct rt_mutex_waiter *waiter) +{ + struct task_struct *task; + + if (!waiter->deadlock_lock || !rt_trace_on) + return; + + task = find_task_by_pid(waiter->deadlock_task_pid); + if (!task) + return; + + TRACE_OFF_NOLOCK(); + + printk("\n============================================\n"); + printk( "[ BUG: circular locking deadlock detected! ]\n"); + printk( "--------------------------------------------\n"); + printk("%s/%d is deadlocking current task %s/%d\n\n", + task->comm, task->pid, current->comm, current->pid); + + printk("\n1) %s/%d is trying to acquire this lock:\n", + current->comm, current->pid); + printk_lock(waiter->lock, 1); + + printk("\n2) %s/%d is blocked on this lock:\n", task->comm, task->pid); + printk_lock(waiter->deadlock_lock, 1); + + debug_show_held_locks(current); + debug_show_held_locks(task); + + printk("\n%s/%d's [blocked] stackdump:\n\n", task->comm, task->pid); + show_stack(task, NULL); + printk("\n%s/%d's [current] stackdump:\n\n", + current->comm, current->pid); + dump_stack(); + debug_show_all_locks(); + + printk("[ turning off deadlock detection." + "Please report this trace. ]\n\n"); + local_irq_disable(); +} + +void debug_rt_mutex_lock(struct rt_mutex *lock) +{ +} + +void debug_rt_mutex_unlock(struct rt_mutex *lock) +{ + TRACE_WARN_ON_LOCKED(rt_mutex_owner(lock) != current); +} + +void +debug_rt_mutex_proxy_lock(struct rt_mutex *lock, struct task_struct *powner) +{ +} + +void debug_rt_mutex_proxy_unlock(struct rt_mutex *lock) +{ + TRACE_WARN_ON_LOCKED(!rt_mutex_owner(lock)); +} + +void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter) +{ + memset(waiter, 0x11, sizeof(*waiter)); + plist_node_init(&waiter->list_entry, MAX_PRIO); + plist_node_init(&waiter->pi_list_entry, MAX_PRIO); +} + +void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter) +{ + TRACE_WARN_ON(!plist_node_empty(&waiter->list_entry)); + TRACE_WARN_ON(!plist_node_empty(&waiter->pi_list_entry)); + TRACE_WARN_ON(waiter->task); + memset(waiter, 0x22, sizeof(*waiter)); +} + +void debug_rt_mutex_init(struct rt_mutex *lock, const char *name) +{ + /* + * Make sure we are not reinitializing a held lock: + */ + debug_check_no_locks_freed((void *)lock, sizeof(*lock)); + lock->name = name; +} + +void +rt_mutex_deadlock_account_lock(struct rt_mutex *lock, struct task_struct *task) +{ +} + +void rt_mutex_deadlock_account_unlock(struct task_struct *task) +{ +} + diff --git a/kernel/rtmutex-debug.h b/kernel/rtmutex-debug.h new file mode 100644 index 000000000..14193d596 --- /dev/null +++ b/kernel/rtmutex-debug.h @@ -0,0 +1,33 @@ +/* + * RT-Mutexes: blocking mutual exclusion locks with PI support + * + * started by Ingo Molnar and Thomas Gleixner: + * + * Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + * Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com> + * + * This file contains macros used solely by rtmutex.c. Debug version. + */ + +extern void +rt_mutex_deadlock_account_lock(struct rt_mutex *lock, struct task_struct *task); +extern void rt_mutex_deadlock_account_unlock(struct task_struct *task); +extern void debug_rt_mutex_init_waiter(struct rt_mutex_waiter *waiter); +extern void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter); +extern void debug_rt_mutex_init(struct rt_mutex *lock, const char *name); +extern void debug_rt_mutex_lock(struct rt_mutex *lock); +extern void debug_rt_mutex_unlock(struct rt_mutex *lock); +extern void debug_rt_mutex_proxy_lock(struct rt_mutex *lock, + struct task_struct *powner); +extern void debug_rt_mutex_proxy_unlock(struct rt_mutex *lock); +extern void debug_rt_mutex_deadlock(int detect, struct rt_mutex_waiter *waiter, + struct rt_mutex *lock); +extern void debug_rt_mutex_print_deadlock(struct rt_mutex_waiter *waiter); +# define debug_rt_mutex_reset_waiter(w) \ + do { (w)->deadlock_lock = NULL; } while (0) + +static inline int debug_rt_mutex_detect_deadlock(struct rt_mutex_waiter *waiter, + int detect) +{ + return (waiter != NULL); +} diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c new file mode 100644 index 000000000..6dcea9dd8 --- /dev/null +++ b/kernel/rtmutex-tester.c @@ -0,0 +1,440 @@ +/* + * RT-Mutex-tester: scriptable tester for rt mutexes + * + * started by Thomas Gleixner: + * + * Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com> + * + */ +#include <linux/kthread.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/smp_lock.h> +#include <linux/spinlock.h> +#include <linux/sysdev.h> +#include <linux/timer.h> + +#include "rtmutex.h" + +#define MAX_RT_TEST_THREADS 8 +#define MAX_RT_TEST_MUTEXES 8 + +static spinlock_t rttest_lock; +static atomic_t rttest_event; + +struct test_thread_data { + int opcode; + int opdata; + int mutexes[MAX_RT_TEST_MUTEXES]; + int bkl; + int event; + struct sys_device sysdev; +}; + +static struct test_thread_data thread_data[MAX_RT_TEST_THREADS]; +static struct task_struct *threads[MAX_RT_TEST_THREADS]; +static struct rt_mutex mutexes[MAX_RT_TEST_MUTEXES]; + +enum test_opcodes { + RTTEST_NOP = 0, + RTTEST_SCHEDOT, /* 1 Sched other, data = nice */ + RTTEST_SCHEDRT, /* 2 Sched fifo, data = prio */ + RTTEST_LOCK, /* 3 Lock uninterruptible, data = lockindex */ + RTTEST_LOCKNOWAIT, /* 4 Lock uninterruptible no wait in wakeup, data = lockindex */ + RTTEST_LOCKINT, /* 5 Lock interruptible, data = lockindex */ + RTTEST_LOCKINTNOWAIT, /* 6 Lock interruptible no wait in wakeup, data = lockindex */ + RTTEST_LOCKCONT, /* 7 Continue locking after the wakeup delay */ + RTTEST_UNLOCK, /* 8 Unlock, data = lockindex */ + RTTEST_LOCKBKL, /* 9 Lock BKL */ + RTTEST_UNLOCKBKL, /* 10 Unlock BKL */ + RTTEST_SIGNAL, /* 11 Signal other test thread, data = thread id */ + RTTEST_RESETEVENT = 98, /* 98 Reset event counter */ + RTTEST_RESET = 99, /* 99 Reset all pending operations */ +}; + +static int handle_op(struct test_thread_data *td, int lockwakeup) +{ + int i, id, ret = -EINVAL; + + switch(td->opcode) { + + case RTTEST_NOP: + return 0; + + case RTTEST_LOCKCONT: + td->mutexes[td->opdata] = 1; + td->event = atomic_add_return(1, &rttest_event); + return 0; + + case RTTEST_RESET: + for (i = 0; i < MAX_RT_TEST_MUTEXES; i++) { + if (td->mutexes[i] == 4) { + rt_mutex_unlock(&mutexes[i]); + td->mutexes[i] = 0; + } + } + + if (!lockwakeup && td->bkl == 4) { + unlock_kernel(); + td->bkl = 0; + } + return 0; + + case RTTEST_RESETEVENT: + atomic_set(&rttest_event, 0); + return 0; + + default: + if (lockwakeup) + return ret; + } + + switch(td->opcode) { + + case RTTEST_LOCK: + case RTTEST_LOCKNOWAIT: + id = td->opdata; + if (id < 0 || id >= MAX_RT_TEST_MUTEXES) + return ret; + + td->mutexes[id] = 1; + td->event = atomic_add_return(1, &rttest_event); + rt_mutex_lock(&mutexes[id]); + td->event = atomic_add_return(1, &rttest_event); + td->mutexes[id] = 4; + return 0; + + case RTTEST_LOCKINT: + case RTTEST_LOCKINTNOWAIT: + id = td->opdata; + if (id < 0 || id >= MAX_RT_TEST_MUTEXES) + return ret; + + td->mutexes[id] = 1; + td->event = atomic_add_return(1, &rttest_event); + ret = rt_mutex_lock_interruptible(&mutexes[id], 0); + td->event = atomic_add_return(1, &rttest_event); + td->mutexes[id] = ret ? 0 : 4; + return ret ? -EINTR : 0; + + case RTTEST_UNLOCK: + id = td->opdata; + if (id < 0 || id >= MAX_RT_TEST_MUTEXES || td->mutexes[id] != 4) + return ret; + + td->event = atomic_add_return(1, &rttest_event); + rt_mutex_unlock(&mutexes[id]); + td->event = atomic_add_return(1, &rttest_event); + td->mutexes[id] = 0; + return 0; + + case RTTEST_LOCKBKL: + if (td->bkl) + return 0; + td->bkl = 1; + lock_kernel(); + td->bkl = 4; + return 0; + + case RTTEST_UNLOCKBKL: + if (td->bkl != 4) + break; + unlock_kernel(); + td->bkl = 0; + return 0; + + default: + break; + } + return ret; +} + +/* + * Schedule replacement for rtsem_down(). Only called for threads with + * PF_MUTEX_TESTER set. + * + * This allows us to have finegrained control over the event flow. + * + */ +void schedule_rt_mutex_test(struct rt_mutex *mutex) +{ + int tid, op, dat; + struct test_thread_data *td; + + /* We have to lookup the task */ + for (tid = 0; tid < MAX_RT_TEST_THREADS; tid++) { + if (threads[tid] == current) + break; + } + + BUG_ON(tid == MAX_RT_TEST_THREADS); + + td = &thread_data[tid]; + + op = td->opcode; + dat = td->opdata; + + switch (op) { + case RTTEST_LOCK: + case RTTEST_LOCKINT: + case RTTEST_LOCKNOWAIT: + case RTTEST_LOCKINTNOWAIT: + if (mutex != &mutexes[dat]) + break; + + if (td->mutexes[dat] != 1) + break; + + td->mutexes[dat] = 2; + td->event = atomic_add_return(1, &rttest_event); + break; + + case RTTEST_LOCKBKL: + default: + break; + } + + schedule(); + + + switch (op) { + case RTTEST_LOCK: + case RTTEST_LOCKINT: + if (mutex != &mutexes[dat]) + return; + + if (td->mutexes[dat] != 2) + return; + + td->mutexes[dat] = 3; + td->event = atomic_add_return(1, &rttest_event); + break; + + case RTTEST_LOCKNOWAIT: + case RTTEST_LOCKINTNOWAIT: + if (mutex != &mutexes[dat]) + return; + + if (td->mutexes[dat] != 2) + return; + + td->mutexes[dat] = 1; + td->event = atomic_add_return(1, &rttest_event); + return; + + case RTTEST_LOCKBKL: + return; + default: + return; + } + + td->opcode = 0; + + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + + if (td->opcode > 0) { + int ret; + + set_current_state(TASK_RUNNING); + ret = handle_op(td, 1); + set_current_state(TASK_INTERRUPTIBLE); + if (td->opcode == RTTEST_LOCKCONT) + break; + td->opcode = ret; + } + + /* Wait for the next command to be executed */ + schedule(); + } + + /* Restore previous command and data */ + td->opcode = op; + td->opdata = dat; +} + +static int test_func(void *data) +{ + struct test_thread_data *td = data; + int ret; + + current->flags |= PF_MUTEX_TESTER; + allow_signal(SIGHUP); + + for(;;) { + + set_current_state(TASK_INTERRUPTIBLE); + + if (td->opcode > 0) { + set_current_state(TASK_RUNNING); + ret = handle_op(td, 0); + set_current_state(TASK_INTERRUPTIBLE); + td->opcode = ret; + } + + /* Wait for the next command to be executed */ + schedule(); + try_to_freeze(); + + if (signal_pending(current)) + flush_signals(current); + + if(kthread_should_stop()) + break; + } + return 0; +} + +/** + * sysfs_test_command - interface for test commands + * @dev: thread reference + * @buf: command for actual step + * @count: length of buffer + * + * command syntax: + * + * opcode:data + */ +static ssize_t sysfs_test_command(struct sys_device *dev, const char *buf, + size_t count) +{ + struct sched_param schedpar; + struct test_thread_data *td; + char cmdbuf[32]; + int op, dat, tid, ret; + + td = container_of(dev, struct test_thread_data, sysdev); + tid = td->sysdev.id; + + /* strings from sysfs write are not 0 terminated! */ + if (count >= sizeof(cmdbuf)) + return -EINVAL; + + /* strip of \n: */ + if (buf[count-1] == '\n') + count--; + if (count < 1) + return -EINVAL; + + memcpy(cmdbuf, buf, count); + cmdbuf[count] = 0; + + if (sscanf(cmdbuf, "%d:%d", &op, &dat) != 2) + return -EINVAL; + + switch (op) { + case RTTEST_SCHEDOT: + schedpar.sched_priority = 0; + ret = sched_setscheduler(threads[tid], SCHED_NORMAL, &schedpar); + if (ret) + return ret; + set_user_nice(current, 0); + break; + + case RTTEST_SCHEDRT: + schedpar.sched_priority = dat; + ret = sched_setscheduler(threads[tid], SCHED_FIFO, &schedpar); + if (ret) + return ret; + break; + + case RTTEST_SIGNAL: + send_sig(SIGHUP, threads[tid], 0); + break; + + default: + if (td->opcode > 0) + return -EBUSY; + td->opdata = dat; + td->opcode = op; + wake_up_process(threads[tid]); + } + + return count; +} + +/** + * sysfs_test_status - sysfs interface for rt tester + * @dev: thread to query + * @buf: char buffer to be filled with thread status info + */ +static ssize_t sysfs_test_status(struct sys_device *dev, char *buf) +{ + struct test_thread_data *td; + struct task_struct *tsk; + char *curr = buf; + int i; + + td = container_of(dev, struct test_thread_data, sysdev); + tsk = threads[td->sysdev.id]; + + spin_lock(&rttest_lock); + + curr += sprintf(curr, + "O: %4d, E:%8d, S: 0x%08lx, P: %4d, N: %4d, B: %p, K: %d, M:", + td->opcode, td->event, tsk->state, + (MAX_RT_PRIO - 1) - tsk->prio, + (MAX_RT_PRIO - 1) - tsk->normal_prio, + tsk->pi_blocked_on, td->bkl); + + for (i = MAX_RT_TEST_MUTEXES - 1; i >=0 ; i--) + curr += sprintf(curr, "%d", td->mutexes[i]); + + spin_unlock(&rttest_lock); + + curr += sprintf(curr, ", T: %p, R: %p\n", tsk, + mutexes[td->sysdev.id].owner); + + return curr - buf; +} + +static SYSDEV_ATTR(status, 0600, sysfs_test_status, NULL); +static SYSDEV_ATTR(command, 0600, NULL, sysfs_test_command); + +static struct sysdev_class rttest_sysclass = { + set_kset_name("rttest"), +}; + +static int init_test_thread(int id) +{ + thread_data[id].sysdev.cls = &rttest_sysclass; + thread_data[id].sysdev.id = id; + + threads[id] = kthread_run(test_func, &thread_data[id], "rt-test-%d", id); + if (IS_ERR(threads[id])) + return PTR_ERR(threads[id]); + + return sysdev_register(&thread_data[id].sysdev); +} + +static int init_rttest(void) +{ + int ret, i; + + spin_lock_init(&rttest_lock); + + for (i = 0; i < MAX_RT_TEST_MUTEXES; i++) + rt_mutex_init(&mutexes[i]); + + ret = sysdev_class_register(&rttest_sysclass); + if (ret) + return ret; + + for (i = 0; i < MAX_RT_TEST_THREADS; i++) { + ret = init_test_thread(i); + if (ret) + break; + ret = sysdev_create_file(&thread_data[i].sysdev, &attr_status); + if (ret) + break; + ret = sysdev_create_file(&thread_data[i].sysdev, &attr_command); + if (ret) + break; + } + + printk("Initializing RT-Tester: %s\n", ret ? "Failed" : "OK" ); + + return ret; +} + +device_initcall(init_rttest); diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c new file mode 100644 index 000000000..3e13a1e58 --- /dev/null +++ b/kernel/rtmutex.c @@ -0,0 +1,991 @@ +/* + * RT-Mutexes: simple blocking mutual exclusion locks with PI support + * + * started by Ingo Molnar and Thomas Gleixner. + * + * Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + * Copyright (C) 2005-2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com> + * Copyright (C) 2005 Kihon Technologies Inc., Steven Rostedt + * Copyright (C) 2006 Esben Nielsen + * + * See Documentation/rt-mutex-design.txt for details. + */ +#include <linux/spinlock.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/timer.h> + +#include "rtmutex_common.h" + +#ifdef CONFIG_DEBUG_RT_MUTEXES +# include "rtmutex-debug.h" +#else +# include "rtmutex.h" +#endif + +/* + * lock->owner state tracking: + * + * lock->owner holds the task_struct pointer of the owner. Bit 0 and 1 + * are used to keep track of the "owner is pending" and "lock has + * waiters" state. + * + * owner bit1 bit0 + * NULL 0 0 lock is free (fast acquire possible) + * NULL 0 1 invalid state + * NULL 1 0 Transitional State* + * NULL 1 1 invalid state + * taskpointer 0 0 lock is held (fast release possible) + * taskpointer 0 1 task is pending owner + * taskpointer 1 0 lock is held and has waiters + * taskpointer 1 1 task is pending owner and lock has more waiters + * + * Pending ownership is assigned to the top (highest priority) + * waiter of the lock, when the lock is released. The thread is woken + * up and can now take the lock. Until the lock is taken (bit 0 + * cleared) a competing higher priority thread can steal the lock + * which puts the woken up thread back on the waiters list. + * + * The fast atomic compare exchange based acquire and release is only + * possible when bit 0 and 1 of lock->owner are 0. + * + * (*) There's a small time where the owner can be NULL and the + * "lock has waiters" bit is set. This can happen when grabbing the lock. + * To prevent a cmpxchg of the owner releasing the lock, we need to set this + * bit before looking at the lock, hence the reason this is a transitional + * state. + */ + +static void +rt_mutex_set_owner(struct rt_mutex *lock, struct task_struct *owner, + unsigned long mask) +{ + unsigned long val = (unsigned long)owner | mask; + + if (rt_mutex_has_waiters(lock)) + val |= RT_MUTEX_HAS_WAITERS; + + lock->owner = (struct task_struct *)val; +} + +static inline void clear_rt_mutex_waiters(struct rt_mutex *lock) +{ + lock->owner = (struct task_struct *) + ((unsigned long)lock->owner & ~RT_MUTEX_HAS_WAITERS); +} + +static void fixup_rt_mutex_waiters(struct rt_mutex *lock) +{ + if (!rt_mutex_has_waiters(lock)) + clear_rt_mutex_waiters(lock); +} + +/* + * We can speed up the acquire/release, if the architecture + * supports cmpxchg and if there's no debugging state to be set up + */ +#if defined(__HAVE_ARCH_CMPXCHG) && !defined(CONFIG_DEBUG_RT_MUTEXES) +# define rt_mutex_cmpxchg(l,c,n) (cmpxchg(&l->owner, c, n) == c) +static inline void mark_rt_mutex_waiters(struct rt_mutex *lock) +{ + unsigned long owner, *p = (unsigned long *) &lock->owner; + + do { + owner = *p; + } while (cmpxchg(p, owner, owner | RT_MUTEX_HAS_WAITERS) != owner); +} +#else +# define rt_mutex_cmpxchg(l,c,n) (0) +static inline void mark_rt_mutex_waiters(struct rt_mutex *lock) +{ + lock->owner = (struct task_struct *) + ((unsigned long)lock->owner | RT_MUTEX_HAS_WAITERS); +} +#endif + +/* + * Calculate task priority from the waiter list priority + * + * Return task->normal_prio when the waiter list is empty or when + * the waiter is not allowed to do priority boosting + */ +int rt_mutex_getprio(struct task_struct *task) +{ + if (likely(!task_has_pi_waiters(task))) + return task->normal_prio; + + return min(task_top_pi_waiter(task)->pi_list_entry.prio, + task->normal_prio); +} + +/* + * Adjust the priority of a task, after its pi_waiters got modified. + * + * This can be both boosting and unboosting. task->pi_lock must be held. + */ +static void __rt_mutex_adjust_prio(struct task_struct *task) +{ + int prio = rt_mutex_getprio(task); + + if (task->prio != prio) + rt_mutex_setprio(task, prio); +} + +/* + * Adjust task priority (undo boosting). Called from the exit path of + * rt_mutex_slowunlock() and rt_mutex_slowlock(). + * + * (Note: We do this outside of the protection of lock->wait_lock to + * allow the lock to be taken while or before we readjust the priority + * of task. We do not use the spin_xx_mutex() variants here as we are + * outside of the debug path.) + */ +static void rt_mutex_adjust_prio(struct task_struct *task) +{ + unsigned long flags; + + spin_lock_irqsave(&task->pi_lock, flags); + __rt_mutex_adjust_prio(task); + spin_unlock_irqrestore(&task->pi_lock, flags); +} + +/* + * Max number of times we'll walk the boosting chain: + */ +int max_lock_depth = 1024; + +/* + * Adjust the priority chain. Also used for deadlock detection. + * Decreases task's usage by one - may thus free the task. + * Returns 0 or -EDEADLK. + */ +static int rt_mutex_adjust_prio_chain(struct task_struct *task, + int deadlock_detect, + struct rt_mutex *orig_lock, + struct rt_mutex_waiter *orig_waiter, + struct task_struct *top_task) +{ + struct rt_mutex *lock; + struct rt_mutex_waiter *waiter, *top_waiter = orig_waiter; + int detect_deadlock, ret = 0, depth = 0; + unsigned long flags; + + detect_deadlock = debug_rt_mutex_detect_deadlock(orig_waiter, + deadlock_detect); + + /* + * The (de)boosting is a step by step approach with a lot of + * pitfalls. We want this to be preemptible and we want hold a + * maximum of two locks per step. So we have to check + * carefully whether things change under us. + */ + again: + if (++depth > max_lock_depth) { + static int prev_max; + + /* + * Print this only once. If the admin changes the limit, + * print a new message when reaching the limit again. + */ + if (prev_max != max_lock_depth) { + prev_max = max_lock_depth; + printk(KERN_WARNING "Maximum lock depth %d reached " + "task: %s (%d)\n", max_lock_depth, + top_task->comm, top_task->pid); + } + put_task_struct(task); + + return deadlock_detect ? -EDEADLK : 0; + } + retry: + /* + * Task can not go away as we did a get_task() before ! + */ + spin_lock_irqsave(&task->pi_lock, flags); + + waiter = task->pi_blocked_on; + /* + * Check whether the end of the boosting chain has been + * reached or the state of the chain has changed while we + * dropped the locks. + */ + if (!waiter || !waiter->task) + goto out_unlock_pi; + + if (top_waiter && (!task_has_pi_waiters(task) || + top_waiter != task_top_pi_waiter(task))) + goto out_unlock_pi; + + /* + * When deadlock detection is off then we check, if further + * priority adjustment is necessary. + */ + if (!detect_deadlock && waiter->list_entry.prio == task->prio) + goto out_unlock_pi; + + lock = waiter->lock; + if (!spin_trylock(&lock->wait_lock)) { + spin_unlock_irqrestore(&task->pi_lock, flags); + cpu_relax(); + goto retry; + } + + /* Deadlock detection */ + if (lock == orig_lock || rt_mutex_owner(lock) == top_task) { + debug_rt_mutex_deadlock(deadlock_detect, orig_waiter, lock); + spin_unlock(&lock->wait_lock); + ret = deadlock_detect ? -EDEADLK : 0; + goto out_unlock_pi; + } + + top_waiter = rt_mutex_top_waiter(lock); + + /* Requeue the waiter */ + plist_del(&waiter->list_entry, &lock->wait_list); + waiter->list_entry.prio = task->prio; + plist_add(&waiter->list_entry, &lock->wait_list); + + /* Release the task */ + spin_unlock_irqrestore(&task->pi_lock, flags); + put_task_struct(task); + + /* Grab the next task */ + task = rt_mutex_owner(lock); + spin_lock_irqsave(&task->pi_lock, flags); + + if (waiter == rt_mutex_top_waiter(lock)) { + /* Boost the owner */ + plist_del(&top_waiter->pi_list_entry, &task->pi_waiters); + waiter->pi_list_entry.prio = waiter->list_entry.prio; + plist_add(&waiter->pi_list_entry, &task->pi_waiters); + __rt_mutex_adjust_prio(task); + + } else if (top_waiter == waiter) { + /* Deboost the owner */ + plist_del(&waiter->pi_list_entry, &task->pi_waiters); + waiter = rt_mutex_top_waiter(lock); + waiter->pi_list_entry.prio = waiter->list_entry.prio; + plist_add(&waiter->pi_list_entry, &task->pi_waiters); + __rt_mutex_adjust_prio(task); + } + + get_task_struct(task); + spin_unlock_irqrestore(&task->pi_lock, flags); + + top_waiter = rt_mutex_top_waiter(lock); + spin_unlock(&lock->wait_lock); + + if (!detect_deadlock && waiter != top_waiter) + goto out_put_task; + + goto again; + + out_unlock_pi: + spin_unlock_irqrestore(&task->pi_lock, flags); + out_put_task: + put_task_struct(task); + + return ret; +} + +/* + * Optimization: check if we can steal the lock from the + * assigned pending owner [which might not have taken the + * lock yet]: + */ +static inline int try_to_steal_lock(struct rt_mutex *lock) +{ + struct task_struct *pendowner = rt_mutex_owner(lock); + struct rt_mutex_waiter *next; + unsigned long flags; + + if (!rt_mutex_owner_pending(lock)) + return 0; + + if (pendowner == current) + return 1; + + spin_lock_irqsave(&pendowner->pi_lock, flags); + if (current->prio >= pendowner->prio) { + spin_unlock_irqrestore(&pendowner->pi_lock, flags); + return 0; + } + + /* + * Check if a waiter is enqueued on the pending owners + * pi_waiters list. Remove it and readjust pending owners + * priority. + */ + if (likely(!rt_mutex_has_waiters(lock))) { + spin_unlock_irqrestore(&pendowner->pi_lock, flags); + return 1; + } + + /* No chain handling, pending owner is not blocked on anything: */ + next = rt_mutex_top_waiter(lock); + plist_del(&next->pi_list_entry, &pendowner->pi_waiters); + __rt_mutex_adjust_prio(pendowner); + spin_unlock_irqrestore(&pendowner->pi_lock, flags); + + /* + * We are going to steal the lock and a waiter was + * enqueued on the pending owners pi_waiters queue. So + * we have to enqueue this waiter into + * current->pi_waiters list. This covers the case, + * where current is boosted because it holds another + * lock and gets unboosted because the booster is + * interrupted, so we would delay a waiter with higher + * priority as current->normal_prio. + * + * Note: in the rare case of a SCHED_OTHER task changing + * its priority and thus stealing the lock, next->task + * might be current: + */ + if (likely(next->task != current)) { + spin_lock_irqsave(¤t->pi_lock, flags); + plist_add(&next->pi_list_entry, ¤t->pi_waiters); + __rt_mutex_adjust_prio(current); + spin_unlock_irqrestore(¤t->pi_lock, flags); + } + return 1; +} + +/* + * Try to take an rt-mutex + * + * This fails + * - when the lock has a real owner + * - when a different pending owner exists and has higher priority than current + * + * Must be called with lock->wait_lock held. + */ +static int try_to_take_rt_mutex(struct rt_mutex *lock) +{ + /* + * We have to be careful here if the atomic speedups are + * enabled, such that, when + * - no other waiter is on the lock + * - the lock has been released since we did the cmpxchg + * the lock can be released or taken while we are doing the + * checks and marking the lock with RT_MUTEX_HAS_WAITERS. + * + * The atomic acquire/release aware variant of + * mark_rt_mutex_waiters uses a cmpxchg loop. After setting + * the WAITERS bit, the atomic release / acquire can not + * happen anymore and lock->wait_lock protects us from the + * non-atomic case. + * + * Note, that this might set lock->owner = + * RT_MUTEX_HAS_WAITERS in the case the lock is not contended + * any more. This is fixed up when we take the ownership. + * This is the transitional state explained at the top of this file. + */ + mark_rt_mutex_waiters(lock); + + if (rt_mutex_owner(lock) && !try_to_steal_lock(lock)) + return 0; + + /* We got the lock. */ + debug_rt_mutex_lock(lock); + + rt_mutex_set_owner(lock, current, 0); + + rt_mutex_deadlock_account_lock(lock, current); + + return 1; +} + +/* + * Task blocks on lock. + * + * Prepare waiter and propagate pi chain + * + * This must be called with lock->wait_lock held. + */ +static int task_blocks_on_rt_mutex(struct rt_mutex *lock, + struct rt_mutex_waiter *waiter, + int detect_deadlock) +{ + struct task_struct *owner = rt_mutex_owner(lock); + struct rt_mutex_waiter *top_waiter = waiter; + unsigned long flags; + int boost = 0, res; + + spin_lock_irqsave(¤t->pi_lock, flags); + __rt_mutex_adjust_prio(current); + waiter->task = current; + waiter->lock = lock; + plist_node_init(&waiter->list_entry, current->prio); + plist_node_init(&waiter->pi_list_entry, current->prio); + + /* Get the top priority waiter on the lock */ + if (rt_mutex_has_waiters(lock)) + top_waiter = rt_mutex_top_waiter(lock); + plist_add(&waiter->list_entry, &lock->wait_list); + + current->pi_blocked_on = waiter; + + spin_unlock_irqrestore(¤t->pi_lock, flags); + + if (waiter == rt_mutex_top_waiter(lock)) { + spin_lock_irqsave(&owner->pi_lock, flags); + plist_del(&top_waiter->pi_list_entry, &owner->pi_waiters); + plist_add(&waiter->pi_list_entry, &owner->pi_waiters); + + __rt_mutex_adjust_prio(owner); + if (owner->pi_blocked_on) { + boost = 1; + /* gets dropped in rt_mutex_adjust_prio_chain()! */ + get_task_struct(owner); + } + spin_unlock_irqrestore(&owner->pi_lock, flags); + } + else if (debug_rt_mutex_detect_deadlock(waiter, detect_deadlock)) { + spin_lock_irqsave(&owner->pi_lock, flags); + if (owner->pi_blocked_on) { + boost = 1; + /* gets dropped in rt_mutex_adjust_prio_chain()! */ + get_task_struct(owner); + } + spin_unlock_irqrestore(&owner->pi_lock, flags); + } + if (!boost) + return 0; + + spin_unlock(&lock->wait_lock); + + res = rt_mutex_adjust_prio_chain(owner, detect_deadlock, lock, waiter, + current); + + spin_lock(&lock->wait_lock); + + return res; +} + +/* + * Wake up the next waiter on the lock. + * + * Remove the top waiter from the current tasks waiter list and from + * the lock waiter list. Set it as pending owner. Then wake it up. + * + * Called with lock->wait_lock held. + */ +static void wakeup_next_waiter(struct rt_mutex *lock) +{ + struct rt_mutex_waiter *waiter; + struct task_struct *pendowner; + unsigned long flags; + + spin_lock_irqsave(¤t->pi_lock, flags); + + waiter = rt_mutex_top_waiter(lock); + plist_del(&waiter->list_entry, &lock->wait_list); + + /* + * Remove it from current->pi_waiters. We do not adjust a + * possible priority boost right now. We execute wakeup in the + * boosted mode and go back to normal after releasing + * lock->wait_lock. + */ + plist_del(&waiter->pi_list_entry, ¤t->pi_waiters); + pendowner = waiter->task; + waiter->task = NULL; + + rt_mutex_set_owner(lock, pendowner, RT_MUTEX_OWNER_PENDING); + + spin_unlock_irqrestore(¤t->pi_lock, flags); + + /* + * Clear the pi_blocked_on variable and enqueue a possible + * waiter into the pi_waiters list of the pending owner. This + * prevents that in case the pending owner gets unboosted a + * waiter with higher priority than pending-owner->normal_prio + * is blocked on the unboosted (pending) owner. + */ + spin_lock_irqsave(&pendowner->pi_lock, flags); + + WARN_ON(!pendowner->pi_blocked_on); + WARN_ON(pendowner->pi_blocked_on != waiter); + WARN_ON(pendowner->pi_blocked_on->lock != lock); + + pendowner->pi_blocked_on = NULL; + + if (rt_mutex_has_waiters(lock)) { + struct rt_mutex_waiter *next; + + next = rt_mutex_top_waiter(lock); + plist_add(&next->pi_list_entry, &pendowner->pi_waiters); + } + spin_unlock_irqrestore(&pendowner->pi_lock, flags); + + wake_up_process(pendowner); +} + +/* + * Remove a waiter from a lock + * + * Must be called with lock->wait_lock held + */ +static void remove_waiter(struct rt_mutex *lock, + struct rt_mutex_waiter *waiter) +{ + int first = (waiter == rt_mutex_top_waiter(lock)); + struct task_struct *owner = rt_mutex_owner(lock); + unsigned long flags; + int boost = 0; + + spin_lock_irqsave(¤t->pi_lock, flags); + plist_del(&waiter->list_entry, &lock->wait_list); + waiter->task = NULL; + current->pi_blocked_on = NULL; + spin_unlock_irqrestore(¤t->pi_lock, flags); + + if (first && owner != current) { + + spin_lock_irqsave(&owner->pi_lock, flags); + + plist_del(&waiter->pi_list_entry, &owner->pi_waiters); + + if (rt_mutex_has_waiters(lock)) { + struct rt_mutex_waiter *next; + + next = rt_mutex_top_waiter(lock); + plist_add(&next->pi_list_entry, &owner->pi_waiters); + } + __rt_mutex_adjust_prio(owner); + + if (owner->pi_blocked_on) { + boost = 1; + /* gets dropped in rt_mutex_adjust_prio_chain()! */ + get_task_struct(owner); + } + spin_unlock_irqrestore(&owner->pi_lock, flags); + } + + WARN_ON(!plist_node_empty(&waiter->pi_list_entry)); + + if (!boost) + return; + + spin_unlock(&lock->wait_lock); + + rt_mutex_adjust_prio_chain(owner, 0, lock, NULL, current); + + spin_lock(&lock->wait_lock); +} + +/* + * Recheck the pi chain, in case we got a priority setting + * + * Called from sched_setscheduler + */ +void rt_mutex_adjust_pi(struct task_struct *task) +{ + struct rt_mutex_waiter *waiter; + unsigned long flags; + + spin_lock_irqsave(&task->pi_lock, flags); + + waiter = task->pi_blocked_on; + if (!waiter || waiter->list_entry.prio == task->prio) { + spin_unlock_irqrestore(&task->pi_lock, flags); + return; + } + + /* gets dropped in rt_mutex_adjust_prio_chain()! */ + get_task_struct(task); + spin_unlock_irqrestore(&task->pi_lock, flags); + + rt_mutex_adjust_prio_chain(task, 0, NULL, NULL, task); +} + +/* + * Slow path lock function: + */ +static int __sched +rt_mutex_slowlock(struct rt_mutex *lock, int state, + struct hrtimer_sleeper *timeout, + int detect_deadlock) +{ + struct rt_mutex_waiter waiter; + int ret = 0; + + debug_rt_mutex_init_waiter(&waiter); + waiter.task = NULL; + + spin_lock(&lock->wait_lock); + + /* Try to acquire the lock again: */ + if (try_to_take_rt_mutex(lock)) { + spin_unlock(&lock->wait_lock); + return 0; + } + + set_current_state(state); + + /* Setup the timer, when timeout != NULL */ + if (unlikely(timeout)) + hrtimer_start(&timeout->timer, timeout->timer.expires, + HRTIMER_ABS); + + for (;;) { + /* Try to acquire the lock: */ + if (try_to_take_rt_mutex(lock)) + break; + + /* + * TASK_INTERRUPTIBLE checks for signals and + * timeout. Ignored otherwise. + */ + if (unlikely(state == TASK_INTERRUPTIBLE)) { + /* Signal pending? */ + if (signal_pending(current)) + ret = -EINTR; + if (timeout && !timeout->task) + ret = -ETIMEDOUT; + if (ret) + break; + } + + /* + * waiter.task is NULL the first time we come here and + * when we have been woken up by the previous owner + * but the lock got stolen by a higher prio task. + */ + if (!waiter.task) { + ret = task_blocks_on_rt_mutex(lock, &waiter, + detect_deadlock); + /* + * If we got woken up by the owner then start loop + * all over without going into schedule to try + * to get the lock now: + */ + if (unlikely(!waiter.task)) + continue; + + if (unlikely(ret)) + break; + } + + spin_unlock(&lock->wait_lock); + + debug_rt_mutex_print_deadlock(&waiter); + + if (waiter.task) + schedule_rt_mutex(lock); + + spin_lock(&lock->wait_lock); + set_current_state(state); + } + + set_current_state(TASK_RUNNING); + + if (unlikely(waiter.task)) + remove_waiter(lock, &waiter); + + /* + * try_to_take_rt_mutex() sets the waiter bit + * unconditionally. We might have to fix that up. + */ + fixup_rt_mutex_waiters(lock); + + spin_unlock(&lock->wait_lock); + + /* Remove pending timer: */ + if (unlikely(timeout)) + hrtimer_cancel(&timeout->timer); + + /* + * Readjust priority, when we did not get the lock. We might + * have been the pending owner and boosted. Since we did not + * take the lock, the PI boost has to go. + */ + if (unlikely(ret)) + rt_mutex_adjust_prio(current); + + debug_rt_mutex_free_waiter(&waiter); + + return ret; +} + +/* + * Slow path try-lock function: + */ +static inline int +rt_mutex_slowtrylock(struct rt_mutex *lock) +{ + int ret = 0; + + spin_lock(&lock->wait_lock); + + if (likely(rt_mutex_owner(lock) != current)) { + + ret = try_to_take_rt_mutex(lock); + /* + * try_to_take_rt_mutex() sets the lock waiters + * bit unconditionally. Clean this up. + */ + fixup_rt_mutex_waiters(lock); + } + + spin_unlock(&lock->wait_lock); + + return ret; +} + +/* + * Slow path to release a rt-mutex: + */ +static void __sched +rt_mutex_slowunlock(struct rt_mutex *lock) +{ + spin_lock(&lock->wait_lock); + + debug_rt_mutex_unlock(lock); + + rt_mutex_deadlock_account_unlock(current); + + if (!rt_mutex_has_waiters(lock)) { + lock->owner = NULL; + spin_unlock(&lock->wait_lock); + return; + } + + wakeup_next_waiter(lock); + + spin_unlock(&lock->wait_lock); + + /* Undo pi boosting if necessary: */ + rt_mutex_adjust_prio(current); +} + +/* + * debug aware fast / slowpath lock,trylock,unlock + * + * The atomic acquire/release ops are compiled away, when either the + * architecture does not support cmpxchg or when debugging is enabled. + */ +static inline int +rt_mutex_fastlock(struct rt_mutex *lock, int state, + int detect_deadlock, + int (*slowfn)(struct rt_mutex *lock, int state, + struct hrtimer_sleeper *timeout, + int detect_deadlock)) +{ + if (!detect_deadlock && likely(rt_mutex_cmpxchg(lock, NULL, current))) { + rt_mutex_deadlock_account_lock(lock, current); + return 0; + } else + return slowfn(lock, state, NULL, detect_deadlock); +} + +static inline int +rt_mutex_timed_fastlock(struct rt_mutex *lock, int state, + struct hrtimer_sleeper *timeout, int detect_deadlock, + int (*slowfn)(struct rt_mutex *lock, int state, + struct hrtimer_sleeper *timeout, + int detect_deadlock)) +{ + if (!detect_deadlock && likely(rt_mutex_cmpxchg(lock, NULL, current))) { + rt_mutex_deadlock_account_lock(lock, current); + return 0; + } else + return slowfn(lock, state, timeout, detect_deadlock); +} + +static inline int +rt_mutex_fasttrylock(struct rt_mutex *lock, + int (*slowfn)(struct rt_mutex *lock)) +{ + if (likely(rt_mutex_cmpxchg(lock, NULL, current))) { + rt_mutex_deadlock_account_lock(lock, current); + return 1; + } + return slowfn(lock); +} + +static inline void +rt_mutex_fastunlock(struct rt_mutex *lock, + void (*slowfn)(struct rt_mutex *lock)) +{ + if (likely(rt_mutex_cmpxchg(lock, current, NULL))) + rt_mutex_deadlock_account_unlock(current); + else + slowfn(lock); +} + +/** + * rt_mutex_lock - lock a rt_mutex + * + * @lock: the rt_mutex to be locked + */ +void __sched rt_mutex_lock(struct rt_mutex *lock) +{ + might_sleep(); + + rt_mutex_fastlock(lock, TASK_UNINTERRUPTIBLE, 0, rt_mutex_slowlock); +} +EXPORT_SYMBOL_GPL(rt_mutex_lock); + +/** + * rt_mutex_lock_interruptible - lock a rt_mutex interruptible + * + * @lock: the rt_mutex to be locked + * @detect_deadlock: deadlock detection on/off + * + * Returns: + * 0 on success + * -EINTR when interrupted by a signal + * -EDEADLK when the lock would deadlock (when deadlock detection is on) + */ +int __sched rt_mutex_lock_interruptible(struct rt_mutex *lock, + int detect_deadlock) +{ + might_sleep(); + + return rt_mutex_fastlock(lock, TASK_INTERRUPTIBLE, + detect_deadlock, rt_mutex_slowlock); +} +EXPORT_SYMBOL_GPL(rt_mutex_lock_interruptible); + +/** + * rt_mutex_lock_interruptible_ktime - lock a rt_mutex interruptible + * the timeout structure is provided + * by the caller + * + * @lock: the rt_mutex to be locked + * @timeout: timeout structure or NULL (no timeout) + * @detect_deadlock: deadlock detection on/off + * + * Returns: + * 0 on success + * -EINTR when interrupted by a signal + * -ETIMEOUT when the timeout expired + * -EDEADLK when the lock would deadlock (when deadlock detection is on) + */ +int +rt_mutex_timed_lock(struct rt_mutex *lock, struct hrtimer_sleeper *timeout, + int detect_deadlock) +{ + might_sleep(); + + return rt_mutex_timed_fastlock(lock, TASK_INTERRUPTIBLE, timeout, + detect_deadlock, rt_mutex_slowlock); +} +EXPORT_SYMBOL_GPL(rt_mutex_timed_lock); + +/** + * rt_mutex_trylock - try to lock a rt_mutex + * + * @lock: the rt_mutex to be locked + * + * Returns 1 on success and 0 on contention + */ +int __sched rt_mutex_trylock(struct rt_mutex *lock) +{ + return rt_mutex_fasttrylock(lock, rt_mutex_slowtrylock); +} +EXPORT_SYMBOL_GPL(rt_mutex_trylock); + +/** + * rt_mutex_unlock - unlock a rt_mutex + * + * @lock: the rt_mutex to be unlocked + */ +void __sched rt_mutex_unlock(struct rt_mutex *lock) +{ + rt_mutex_fastunlock(lock, rt_mutex_slowunlock); +} +EXPORT_SYMBOL_GPL(rt_mutex_unlock); + +/*** + * rt_mutex_destroy - mark a mutex unusable + * @lock: the mutex to be destroyed + * + * This function marks the mutex uninitialized, and any subsequent + * use of the mutex is forbidden. The mutex must not be locked when + * this function is called. + */ +void rt_mutex_destroy(struct rt_mutex *lock) +{ + WARN_ON(rt_mutex_is_locked(lock)); +#ifdef CONFIG_DEBUG_RT_MUTEXES + lock->magic = NULL; +#endif +} + +EXPORT_SYMBOL_GPL(rt_mutex_destroy); + +/** + * __rt_mutex_init - initialize the rt lock + * + * @lock: the rt lock to be initialized + * + * Initialize the rt lock to unlocked state. + * + * Initializing of a locked rt lock is not allowed + */ +void __rt_mutex_init(struct rt_mutex *lock, const char *name) +{ + lock->owner = NULL; + spin_lock_init(&lock->wait_lock); + plist_head_init(&lock->wait_list, &lock->wait_lock); + + debug_rt_mutex_init(lock, name); +} +EXPORT_SYMBOL_GPL(__rt_mutex_init); + +/** + * rt_mutex_init_proxy_locked - initialize and lock a rt_mutex on behalf of a + * proxy owner + * + * @lock: the rt_mutex to be locked + * @proxy_owner:the task to set as owner + * + * No locking. Caller has to do serializing itself + * Special API call for PI-futex support + */ +void rt_mutex_init_proxy_locked(struct rt_mutex *lock, + struct task_struct *proxy_owner) +{ + __rt_mutex_init(lock, NULL); + debug_rt_mutex_proxy_lock(lock, proxy_owner); + rt_mutex_set_owner(lock, proxy_owner, 0); + rt_mutex_deadlock_account_lock(lock, proxy_owner); +} + +/** + * rt_mutex_proxy_unlock - release a lock on behalf of owner + * + * @lock: the rt_mutex to be locked + * + * No locking. Caller has to do serializing itself + * Special API call for PI-futex support + */ +void rt_mutex_proxy_unlock(struct rt_mutex *lock, + struct task_struct *proxy_owner) +{ + debug_rt_mutex_proxy_unlock(lock); + rt_mutex_set_owner(lock, NULL, 0); + rt_mutex_deadlock_account_unlock(proxy_owner); +} + +/** + * rt_mutex_next_owner - return the next owner of the lock + * + * @lock: the rt lock query + * + * Returns the next owner of the lock or NULL + * + * Caller has to serialize against other accessors to the lock + * itself. + * + * Special API call for PI-futex support + */ +struct task_struct *rt_mutex_next_owner(struct rt_mutex *lock) +{ + if (!rt_mutex_has_waiters(lock)) + return NULL; + + return rt_mutex_top_waiter(lock)->task; +} diff --git a/kernel/rtmutex.h b/kernel/rtmutex.h new file mode 100644 index 000000000..a1a1dd064 --- /dev/null +++ b/kernel/rtmutex.h @@ -0,0 +1,26 @@ +/* + * RT-Mutexes: blocking mutual exclusion locks with PI support + * + * started by Ingo Molnar and Thomas Gleixner: + * + * Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + * Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com> + * + * This file contains macros used solely by rtmutex.c. + * Non-debug version. + */ + +#define rt_mutex_deadlock_check(l) (0) +#define rt_mutex_deadlock_account_lock(m, t) do { } while (0) +#define rt_mutex_deadlock_account_unlock(l) do { } while (0) +#define debug_rt_mutex_init_waiter(w) do { } while (0) +#define debug_rt_mutex_free_waiter(w) do { } while (0) +#define debug_rt_mutex_lock(l) do { } while (0) +#define debug_rt_mutex_proxy_lock(l,p) do { } while (0) +#define debug_rt_mutex_proxy_unlock(l) do { } while (0) +#define debug_rt_mutex_unlock(l) do { } while (0) +#define debug_rt_mutex_init(m, n) do { } while (0) +#define debug_rt_mutex_deadlock(d, a ,l) do { } while (0) +#define debug_rt_mutex_print_deadlock(w) do { } while (0) +#define debug_rt_mutex_detect_deadlock(w,d) (d) +#define debug_rt_mutex_reset_waiter(w) do { } while (0) diff --git a/kernel/rtmutex_common.h b/kernel/rtmutex_common.h new file mode 100644 index 000000000..9c75856e7 --- /dev/null +++ b/kernel/rtmutex_common.h @@ -0,0 +1,123 @@ +/* + * RT Mutexes: blocking mutual exclusion locks with PI support + * + * started by Ingo Molnar and Thomas Gleixner: + * + * Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + * Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com> + * + * This file contains the private data structure and API definitions. + */ + +#ifndef __KERNEL_RTMUTEX_COMMON_H +#define __KERNEL_RTMUTEX_COMMON_H + +#include <linux/rtmutex.h> + +/* + * The rtmutex in kernel tester is independent of rtmutex debugging. We + * call schedule_rt_mutex_test() instead of schedule() for the tasks which + * belong to the tester. That way we can delay the wakeup path of those + * threads to provoke lock stealing and testing of complex boosting scenarios. + */ +#ifdef CONFIG_RT_MUTEX_TESTER + +extern void schedule_rt_mutex_test(struct rt_mutex *lock); + +#define schedule_rt_mutex(_lock) \ + do { \ + if (!(current->flags & PF_MUTEX_TESTER)) \ + schedule(); \ + else \ + schedule_rt_mutex_test(_lock); \ + } while (0) + +#else +# define schedule_rt_mutex(_lock) schedule() +#endif + +/* + * This is the control structure for tasks blocked on a rt_mutex, + * which is allocated on the kernel stack on of the blocked task. + * + * @list_entry: pi node to enqueue into the mutex waiters list + * @pi_list_entry: pi node to enqueue into the mutex owner waiters list + * @task: task reference to the blocked task + */ +struct rt_mutex_waiter { + struct plist_node list_entry; + struct plist_node pi_list_entry; + struct task_struct *task; + struct rt_mutex *lock; +#ifdef CONFIG_DEBUG_RT_MUTEXES + unsigned long ip; + pid_t deadlock_task_pid; + struct rt_mutex *deadlock_lock; +#endif +}; + +/* + * Various helpers to access the waiters-plist: + */ +static inline int rt_mutex_has_waiters(struct rt_mutex *lock) +{ + return !plist_head_empty(&lock->wait_list); +} + +static inline struct rt_mutex_waiter * +rt_mutex_top_waiter(struct rt_mutex *lock) +{ + struct rt_mutex_waiter *w; + + w = plist_first_entry(&lock->wait_list, struct rt_mutex_waiter, + list_entry); + BUG_ON(w->lock != lock); + + return w; +} + +static inline int task_has_pi_waiters(struct task_struct *p) +{ + return !plist_head_empty(&p->pi_waiters); +} + +static inline struct rt_mutex_waiter * +task_top_pi_waiter(struct task_struct *p) +{ + return plist_first_entry(&p->pi_waiters, struct rt_mutex_waiter, + pi_list_entry); +} + +/* + * lock->owner state tracking: + */ +#define RT_MUTEX_OWNER_PENDING 1UL +#define RT_MUTEX_HAS_WAITERS 2UL +#define RT_MUTEX_OWNER_MASKALL 3UL + +static inline struct task_struct *rt_mutex_owner(struct rt_mutex *lock) +{ + return (struct task_struct *) + ((unsigned long)lock->owner & ~RT_MUTEX_OWNER_MASKALL); +} + +static inline struct task_struct *rt_mutex_real_owner(struct rt_mutex *lock) +{ + return (struct task_struct *) + ((unsigned long)lock->owner & ~RT_MUTEX_HAS_WAITERS); +} + +static inline unsigned long rt_mutex_owner_pending(struct rt_mutex *lock) +{ + return (unsigned long)lock->owner & RT_MUTEX_OWNER_PENDING; +} + +/* + * PI-futex support (proxy locking functions, etc.): + */ +extern struct task_struct *rt_mutex_next_owner(struct rt_mutex *lock); +extern void rt_mutex_init_proxy_locked(struct rt_mutex *lock, + struct task_struct *proxy_owner); +extern void rt_mutex_proxy_unlock(struct rt_mutex *lock, + struct task_struct *proxy_owner); +#endif diff --git a/kernel/rwsem.c b/kernel/rwsem.c new file mode 100644 index 000000000..291ded556 --- /dev/null +++ b/kernel/rwsem.c @@ -0,0 +1,147 @@ +/* kernel/rwsem.c: R/W semaphores, public implementation + * + * Written by David Howells (dhowells@redhat.com). + * Derived from asm-i386/semaphore.h + */ + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/rwsem.h> + +#include <asm/system.h> +#include <asm/atomic.h> + +/* + * lock for reading + */ +void down_read(struct rw_semaphore *sem) +{ + might_sleep(); + rwsem_acquire_read(&sem->dep_map, 0, 0, _RET_IP_); + + __down_read(sem); +} + +EXPORT_SYMBOL(down_read); + +/* + * trylock for reading -- returns 1 if successful, 0 if contention + */ +int down_read_trylock(struct rw_semaphore *sem) +{ + int ret = __down_read_trylock(sem); + + if (ret == 1) + rwsem_acquire_read(&sem->dep_map, 0, 1, _RET_IP_); + return ret; +} + +EXPORT_SYMBOL(down_read_trylock); + +/* + * lock for writing + */ +void down_write(struct rw_semaphore *sem) +{ + might_sleep(); + rwsem_acquire(&sem->dep_map, 0, 0, _RET_IP_); + + __down_write(sem); +} + +EXPORT_SYMBOL(down_write); + +/* + * trylock for writing -- returns 1 if successful, 0 if contention + */ +int down_write_trylock(struct rw_semaphore *sem) +{ + int ret = __down_write_trylock(sem); + + if (ret == 1) + rwsem_acquire(&sem->dep_map, 0, 0, _RET_IP_); + return ret; +} + +EXPORT_SYMBOL(down_write_trylock); + +/* + * release a read lock + */ +void up_read(struct rw_semaphore *sem) +{ + rwsem_release(&sem->dep_map, 1, _RET_IP_); + + __up_read(sem); +} + +EXPORT_SYMBOL(up_read); + +/* + * release a write lock + */ +void up_write(struct rw_semaphore *sem) +{ + rwsem_release(&sem->dep_map, 1, _RET_IP_); + + __up_write(sem); +} + +EXPORT_SYMBOL(up_write); + +/* + * downgrade write lock to read lock + */ +void downgrade_write(struct rw_semaphore *sem) +{ + /* + * lockdep: a downgraded write will live on as a write + * dependency. + */ + __downgrade_write(sem); +} + +EXPORT_SYMBOL(downgrade_write); + +#ifdef CONFIG_DEBUG_LOCK_ALLOC + +void down_read_nested(struct rw_semaphore *sem, int subclass) +{ + might_sleep(); + rwsem_acquire_read(&sem->dep_map, subclass, 0, _RET_IP_); + + __down_read(sem); +} + +EXPORT_SYMBOL(down_read_nested); + +void down_read_non_owner(struct rw_semaphore *sem) +{ + might_sleep(); + + __down_read(sem); +} + +EXPORT_SYMBOL(down_read_non_owner); + +void down_write_nested(struct rw_semaphore *sem, int subclass) +{ + might_sleep(); + rwsem_acquire(&sem->dep_map, subclass, 0, _RET_IP_); + + __down_write_nested(sem, subclass); +} + +EXPORT_SYMBOL(down_write_nested); + +void up_read_non_owner(struct rw_semaphore *sem) +{ + __up_read(sem); +} + +EXPORT_SYMBOL(up_read_non_owner); + +#endif + + diff --git a/kernel/stacktrace.c b/kernel/stacktrace.c new file mode 100644 index 000000000..b71816e47 --- /dev/null +++ b/kernel/stacktrace.c @@ -0,0 +1,24 @@ +/* + * kernel/stacktrace.c + * + * Stack trace management functions + * + * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + */ +#include <linux/sched.h> +#include <linux/kallsyms.h> +#include <linux/stacktrace.h> + +void print_stack_trace(struct stack_trace *trace, int spaces) +{ + int i, j; + + for (i = 0; i < trace->nr_entries; i++) { + unsigned long ip = trace->entries[i]; + + for (j = 0; j < spaces + 1; j++) + printk(" "); + print_ip_sym(ip); + } +} + diff --git a/kernel/taskstats.c b/kernel/taskstats.c new file mode 100644 index 000000000..b90b2a7ef --- /dev/null +++ b/kernel/taskstats.c @@ -0,0 +1,567 @@ +/* + * taskstats.c - Export per-task statistics to userland + * + * Copyright (C) Shailabh Nagar, IBM Corp. 2006 + * (C) Balbir Singh, IBM Corp. 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/kernel.h> +#include <linux/taskstats_kern.h> +#include <linux/delayacct.h> +#include <linux/cpumask.h> +#include <linux/percpu.h> +#include <net/genetlink.h> +#include <asm/atomic.h> + +/* + * Maximum length of a cpumask that can be specified in + * the TASKSTATS_CMD_ATTR_REGISTER/DEREGISTER_CPUMASK attribute + */ +#define TASKSTATS_CPUMASK_MAXLEN (100+6*NR_CPUS) + +static DEFINE_PER_CPU(__u32, taskstats_seqnum) = { 0 }; +static int family_registered; +kmem_cache_t *taskstats_cache; + +static struct genl_family family = { + .id = GENL_ID_GENERATE, + .name = TASKSTATS_GENL_NAME, + .version = TASKSTATS_GENL_VERSION, + .maxattr = TASKSTATS_CMD_ATTR_MAX, +}; + +static struct nla_policy taskstats_cmd_get_policy[TASKSTATS_CMD_ATTR_MAX+1] +__read_mostly = { + [TASKSTATS_CMD_ATTR_PID] = { .type = NLA_U32 }, + [TASKSTATS_CMD_ATTR_TGID] = { .type = NLA_U32 }, + [TASKSTATS_CMD_ATTR_REGISTER_CPUMASK] = { .type = NLA_STRING }, + [TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK] = { .type = NLA_STRING },}; + +struct listener { + struct list_head list; + pid_t pid; + char valid; +}; + +struct listener_list { + struct rw_semaphore sem; + struct list_head list; +}; +static DEFINE_PER_CPU(struct listener_list, listener_array); + +enum actions { + REGISTER, + DEREGISTER, + CPU_DONT_CARE +}; + +static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp, + void **replyp, size_t size) +{ + struct sk_buff *skb; + void *reply; + + /* + * If new attributes are added, please revisit this allocation + */ + skb = nlmsg_new(size); + if (!skb) + return -ENOMEM; + + if (!info) { + int seq = get_cpu_var(taskstats_seqnum)++; + put_cpu_var(taskstats_seqnum); + + reply = genlmsg_put(skb, 0, seq, + family.id, 0, 0, + cmd, family.version); + } else + reply = genlmsg_put(skb, info->snd_pid, info->snd_seq, + family.id, 0, 0, + cmd, family.version); + if (reply == NULL) { + nlmsg_free(skb); + return -EINVAL; + } + + *skbp = skb; + *replyp = reply; + return 0; +} + +/* + * Send taskstats data in @skb to listener with nl_pid @pid + */ +static int send_reply(struct sk_buff *skb, pid_t pid) +{ + struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data); + void *reply = genlmsg_data(genlhdr); + int rc; + + rc = genlmsg_end(skb, reply); + if (rc < 0) { + nlmsg_free(skb); + return rc; + } + + return genlmsg_unicast(skb, pid); +} + +/* + * Send taskstats data in @skb to listeners registered for @cpu's exit data + */ +static void send_cpu_listeners(struct sk_buff *skb, unsigned int cpu) +{ + struct genlmsghdr *genlhdr = nlmsg_data((struct nlmsghdr *)skb->data); + struct listener_list *listeners; + struct listener *s, *tmp; + struct sk_buff *skb_next, *skb_cur = skb; + void *reply = genlmsg_data(genlhdr); + int rc, delcount = 0; + + rc = genlmsg_end(skb, reply); + if (rc < 0) { + nlmsg_free(skb); + return; + } + + rc = 0; + listeners = &per_cpu(listener_array, cpu); + down_read(&listeners->sem); + list_for_each_entry(s, &listeners->list, list) { + skb_next = NULL; + if (!list_is_last(&s->list, &listeners->list)) { + skb_next = skb_clone(skb_cur, GFP_KERNEL); + if (!skb_next) + break; + } + rc = genlmsg_unicast(skb_cur, s->pid); + if (rc == -ECONNREFUSED) { + s->valid = 0; + delcount++; + } + skb_cur = skb_next; + } + up_read(&listeners->sem); + + if (skb_cur) + nlmsg_free(skb_cur); + + if (!delcount) + return; + + /* Delete invalidated entries */ + down_write(&listeners->sem); + list_for_each_entry_safe(s, tmp, &listeners->list, list) { + if (!s->valid) { + list_del(&s->list); + kfree(s); + } + } + up_write(&listeners->sem); +} + +static int fill_pid(pid_t pid, struct task_struct *pidtsk, + struct taskstats *stats) +{ + int rc = 0; + struct task_struct *tsk = pidtsk; + + if (!pidtsk) { + read_lock(&tasklist_lock); + tsk = find_task_by_pid(pid); + if (!tsk) { + read_unlock(&tasklist_lock); + return -ESRCH; + } + get_task_struct(tsk); + read_unlock(&tasklist_lock); + } else + get_task_struct(tsk); + + /* + * Each accounting subsystem adds calls to its functions to + * fill in relevant parts of struct taskstsats as follows + * + * per-task-foo(stats, tsk); + */ + + delayacct_add_tsk(stats, tsk); + stats->version = TASKSTATS_VERSION; + + /* Define err: label here if needed */ + put_task_struct(tsk); + return rc; + +} + +static int fill_tgid(pid_t tgid, struct task_struct *tgidtsk, + struct taskstats *stats) +{ + struct task_struct *tsk, *first; + unsigned long flags; + + /* + * Add additional stats from live tasks except zombie thread group + * leaders who are already counted with the dead tasks + */ + first = tgidtsk; + if (!first) { + read_lock(&tasklist_lock); + first = find_task_by_pid(tgid); + if (!first) { + read_unlock(&tasklist_lock); + return -ESRCH; + } + get_task_struct(first); + read_unlock(&tasklist_lock); + } else + get_task_struct(first); + + + tsk = first; + read_lock(&tasklist_lock); + /* Start with stats from dead tasks */ + if (first->signal) { + spin_lock_irqsave(&first->signal->stats_lock, flags); + if (first->signal->stats) + memcpy(stats, first->signal->stats, sizeof(*stats)); + spin_unlock_irqrestore(&first->signal->stats_lock, flags); + } + + do { + if (tsk->exit_state == EXIT_ZOMBIE && thread_group_leader(tsk)) + continue; + /* + * Accounting subsystem can call its functions here to + * fill in relevant parts of struct taskstsats as follows + * + * per-task-foo(stats, tsk); + */ + delayacct_add_tsk(stats, tsk); + + } while_each_thread(first, tsk); + read_unlock(&tasklist_lock); + stats->version = TASKSTATS_VERSION; + + /* + * Accounting subsytems can also add calls here to modify + * fields of taskstats. + */ + put_task_struct(first); + return 0; +} + + +static void fill_tgid_exit(struct task_struct *tsk) +{ + unsigned long flags; + + spin_lock_irqsave(&tsk->signal->stats_lock, flags); + if (!tsk->signal->stats) + goto ret; + + /* + * Each accounting subsystem calls its functions here to + * accumalate its per-task stats for tsk, into the per-tgid structure + * + * per-task-foo(tsk->signal->stats, tsk); + */ + delayacct_add_tsk(tsk->signal->stats, tsk); +ret: + spin_unlock_irqrestore(&tsk->signal->stats_lock, flags); + return; +} + +static int add_del_listener(pid_t pid, cpumask_t *maskp, int isadd) +{ + struct listener_list *listeners; + struct listener *s, *tmp; + unsigned int cpu; + cpumask_t mask = *maskp; + + if (!cpus_subset(mask, cpu_possible_map)) + return -EINVAL; + + if (isadd == REGISTER) { + for_each_cpu_mask(cpu, mask) { + s = kmalloc_node(sizeof(struct listener), GFP_KERNEL, + cpu_to_node(cpu)); + if (!s) + goto cleanup; + s->pid = pid; + INIT_LIST_HEAD(&s->list); + s->valid = 1; + + listeners = &per_cpu(listener_array, cpu); + down_write(&listeners->sem); + list_add(&s->list, &listeners->list); + up_write(&listeners->sem); + } + return 0; + } + + /* Deregister or cleanup */ +cleanup: + for_each_cpu_mask(cpu, mask) { + listeners = &per_cpu(listener_array, cpu); + down_write(&listeners->sem); + list_for_each_entry_safe(s, tmp, &listeners->list, list) { + if (s->pid == pid) { + list_del(&s->list); + kfree(s); + break; + } + } + up_write(&listeners->sem); + } + return 0; +} + +static int parse(struct nlattr *na, cpumask_t *mask) +{ + char *data; + int len; + int ret; + + if (na == NULL) + return 1; + len = nla_len(na); + if (len > TASKSTATS_CPUMASK_MAXLEN) + return -E2BIG; + if (len < 1) + return -EINVAL; + data = kmalloc(len, GFP_KERNEL); + if (!data) + return -ENOMEM; + nla_strlcpy(data, na, len); + ret = cpulist_parse(data, *mask); + kfree(data); + return ret; +} + +static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info) +{ + int rc = 0; + struct sk_buff *rep_skb; + struct taskstats stats; + void *reply; + size_t size; + struct nlattr *na; + cpumask_t mask; + + rc = parse(info->attrs[TASKSTATS_CMD_ATTR_REGISTER_CPUMASK], &mask); + if (rc < 0) + return rc; + if (rc == 0) + return add_del_listener(info->snd_pid, &mask, REGISTER); + + rc = parse(info->attrs[TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK], &mask); + if (rc < 0) + return rc; + if (rc == 0) + return add_del_listener(info->snd_pid, &mask, DEREGISTER); + + /* + * Size includes space for nested attributes + */ + size = nla_total_size(sizeof(u32)) + + nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); + + memset(&stats, 0, sizeof(stats)); + rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, &reply, size); + if (rc < 0) + return rc; + + if (info->attrs[TASKSTATS_CMD_ATTR_PID]) { + u32 pid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_PID]); + rc = fill_pid(pid, NULL, &stats); + if (rc < 0) + goto err; + + na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_PID); + NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_PID, pid); + NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS, + stats); + } else if (info->attrs[TASKSTATS_CMD_ATTR_TGID]) { + u32 tgid = nla_get_u32(info->attrs[TASKSTATS_CMD_ATTR_TGID]); + rc = fill_tgid(tgid, NULL, &stats); + if (rc < 0) + goto err; + + na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_TGID); + NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_TGID, tgid); + NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS, + stats); + } else { + rc = -EINVAL; + goto err; + } + + nla_nest_end(rep_skb, na); + + return send_reply(rep_skb, info->snd_pid); + +nla_put_failure: + return genlmsg_cancel(rep_skb, reply); +err: + nlmsg_free(rep_skb); + return rc; +} + +void taskstats_exit_alloc(struct taskstats **ptidstats, unsigned int *mycpu) +{ + struct listener_list *listeners; + struct taskstats *tmp; + /* + * This is the cpu on which the task is exiting currently and will + * be the one for which the exit event is sent, even if the cpu + * on which this function is running changes later. + */ + *mycpu = raw_smp_processor_id(); + + *ptidstats = NULL; + tmp = kmem_cache_zalloc(taskstats_cache, SLAB_KERNEL); + if (!tmp) + return; + + listeners = &per_cpu(listener_array, *mycpu); + down_read(&listeners->sem); + if (!list_empty(&listeners->list)) { + *ptidstats = tmp; + tmp = NULL; + } + up_read(&listeners->sem); + kfree(tmp); +} + +/* Send pid data out on exit */ +void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, + int group_dead, unsigned int mycpu) +{ + int rc; + struct sk_buff *rep_skb; + void *reply; + size_t size; + int is_thread_group; + struct nlattr *na; + unsigned long flags; + + if (!family_registered || !tidstats) + return; + + spin_lock_irqsave(&tsk->signal->stats_lock, flags); + is_thread_group = tsk->signal->stats ? 1 : 0; + spin_unlock_irqrestore(&tsk->signal->stats_lock, flags); + + rc = 0; + /* + * Size includes space for nested attributes + */ + size = nla_total_size(sizeof(u32)) + + nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); + + if (is_thread_group) + size = 2 * size; /* PID + STATS + TGID + STATS */ + + rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, &reply, size); + if (rc < 0) + goto ret; + + rc = fill_pid(tsk->pid, tsk, tidstats); + if (rc < 0) + goto err_skb; + + na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_PID); + NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_PID, (u32)tsk->pid); + NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS, + *tidstats); + nla_nest_end(rep_skb, na); + + if (!is_thread_group) + goto send; + + /* + * tsk has/had a thread group so fill the tsk->signal->stats structure + * Doesn't matter if tsk is the leader or the last group member leaving + */ + + fill_tgid_exit(tsk); + if (!group_dead) + goto send; + + na = nla_nest_start(rep_skb, TASKSTATS_TYPE_AGGR_TGID); + NLA_PUT_U32(rep_skb, TASKSTATS_TYPE_TGID, (u32)tsk->tgid); + /* No locking needed for tsk->signal->stats since group is dead */ + NLA_PUT_TYPE(rep_skb, struct taskstats, TASKSTATS_TYPE_STATS, + *tsk->signal->stats); + nla_nest_end(rep_skb, na); + +send: + send_cpu_listeners(rep_skb, mycpu); + return; + +nla_put_failure: + genlmsg_cancel(rep_skb, reply); + goto ret; +err_skb: + nlmsg_free(rep_skb); +ret: + return; +} + +static struct genl_ops taskstats_ops = { + .cmd = TASKSTATS_CMD_GET, + .doit = taskstats_user_cmd, + .policy = taskstats_cmd_get_policy, +}; + +/* Needed early in initialization */ +void __init taskstats_init_early(void) +{ + unsigned int i; + + taskstats_cache = kmem_cache_create("taskstats_cache", + sizeof(struct taskstats), + 0, SLAB_PANIC, NULL, NULL); + for_each_possible_cpu(i) { + INIT_LIST_HEAD(&(per_cpu(listener_array, i).list)); + init_rwsem(&(per_cpu(listener_array, i).sem)); + } +} + +static int __init taskstats_init(void) +{ + int rc; + + rc = genl_register_family(&family); + if (rc) + return rc; + + rc = genl_register_ops(&family, &taskstats_ops); + if (rc < 0) + goto err; + + family_registered = 1; + return 0; +err: + genl_unregister_family(&family); + return rc; +} + +/* + * late initcall ensures initialization of statistics collection + * mechanisms precedes initialization of the taskstats interface + */ +late_initcall(taskstats_init); diff --git a/kernel/time/Makefile b/kernel/time/Makefile new file mode 100644 index 000000000..e1dfd8e86 --- /dev/null +++ b/kernel/time/Makefile @@ -0,0 +1 @@ +obj-y += clocksource.o jiffies.o diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c new file mode 100644 index 000000000..74eca5939 --- /dev/null +++ b/kernel/time/clocksource.c @@ -0,0 +1,349 @@ +/* + * linux/kernel/time/clocksource.c + * + * This file contains the functions which manage clocksource drivers. + * + * Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * TODO WishList: + * o Allow clocksource drivers to be unregistered + * o get rid of clocksource_jiffies extern + */ + +#include <linux/clocksource.h> +#include <linux/sysdev.h> +#include <linux/init.h> +#include <linux/module.h> + +/* XXX - Would like a better way for initializing curr_clocksource */ +extern struct clocksource clocksource_jiffies; + +/*[Clocksource internal variables]--------- + * curr_clocksource: + * currently selected clocksource. Initialized to clocksource_jiffies. + * next_clocksource: + * pending next selected clocksource. + * clocksource_list: + * linked list with the registered clocksources + * clocksource_lock: + * protects manipulations to curr_clocksource and next_clocksource + * and the clocksource_list + * override_name: + * Name of the user-specified clocksource. + */ +static struct clocksource *curr_clocksource = &clocksource_jiffies; +static struct clocksource *next_clocksource; +static LIST_HEAD(clocksource_list); +static DEFINE_SPINLOCK(clocksource_lock); +static char override_name[32]; +static int finished_booting; + +/* clocksource_done_booting - Called near the end of bootup + * + * Hack to avoid lots of clocksource churn at boot time + */ +static int __init clocksource_done_booting(void) +{ + finished_booting = 1; + return 0; +} + +late_initcall(clocksource_done_booting); + +/** + * clocksource_get_next - Returns the selected clocksource + * + */ +struct clocksource *clocksource_get_next(void) +{ + unsigned long flags; + + spin_lock_irqsave(&clocksource_lock, flags); + if (next_clocksource && finished_booting) { + curr_clocksource = next_clocksource; + next_clocksource = NULL; + } + spin_unlock_irqrestore(&clocksource_lock, flags); + + return curr_clocksource; +} + +/** + * select_clocksource - Finds the best registered clocksource. + * + * Private function. Must hold clocksource_lock when called. + * + * Looks through the list of registered clocksources, returning + * the one with the highest rating value. If there is a clocksource + * name that matches the override string, it returns that clocksource. + */ +static struct clocksource *select_clocksource(void) +{ + struct clocksource *best = NULL; + struct list_head *tmp; + + list_for_each(tmp, &clocksource_list) { + struct clocksource *src; + + src = list_entry(tmp, struct clocksource, list); + if (!best) + best = src; + + /* check for override: */ + if (strlen(src->name) == strlen(override_name) && + !strcmp(src->name, override_name)) { + best = src; + break; + } + /* pick the highest rating: */ + if (src->rating > best->rating) + best = src; + } + + return best; +} + +/** + * is_registered_source - Checks if clocksource is registered + * @c: pointer to a clocksource + * + * Private helper function. Must hold clocksource_lock when called. + * + * Returns one if the clocksource is already registered, zero otherwise. + */ +static int is_registered_source(struct clocksource *c) +{ + int len = strlen(c->name); + struct list_head *tmp; + + list_for_each(tmp, &clocksource_list) { + struct clocksource *src; + + src = list_entry(tmp, struct clocksource, list); + if (strlen(src->name) == len && !strcmp(src->name, c->name)) + return 1; + } + + return 0; +} + +/** + * clocksource_register - Used to install new clocksources + * @t: clocksource to be registered + * + * Returns -EBUSY if registration fails, zero otherwise. + */ +int clocksource_register(struct clocksource *c) +{ + int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&clocksource_lock, flags); + /* check if clocksource is already registered */ + if (is_registered_source(c)) { + printk("register_clocksource: Cannot register %s. " + "Already registered!", c->name); + ret = -EBUSY; + } else { + /* register it */ + list_add(&c->list, &clocksource_list); + /* scan the registered clocksources, and pick the best one */ + next_clocksource = select_clocksource(); + } + spin_unlock_irqrestore(&clocksource_lock, flags); + return ret; +} +EXPORT_SYMBOL(clocksource_register); + +/** + * clocksource_reselect - Rescan list for next clocksource + * + * A quick helper function to be used if a clocksource changes its + * rating. Forces the clocksource list to be re-scanned for the best + * clocksource. + */ +void clocksource_reselect(void) +{ + unsigned long flags; + + spin_lock_irqsave(&clocksource_lock, flags); + next_clocksource = select_clocksource(); + spin_unlock_irqrestore(&clocksource_lock, flags); +} +EXPORT_SYMBOL(clocksource_reselect); + +/** + * sysfs_show_current_clocksources - sysfs interface for current clocksource + * @dev: unused + * @buf: char buffer to be filled with clocksource list + * + * Provides sysfs interface for listing current clocksource. + */ +static ssize_t +sysfs_show_current_clocksources(struct sys_device *dev, char *buf) +{ + char *curr = buf; + + spin_lock_irq(&clocksource_lock); + curr += sprintf(curr, "%s ", curr_clocksource->name); + spin_unlock_irq(&clocksource_lock); + + curr += sprintf(curr, "\n"); + + return curr - buf; +} + +/** + * sysfs_override_clocksource - interface for manually overriding clocksource + * @dev: unused + * @buf: name of override clocksource + * @count: length of buffer + * + * Takes input from sysfs interface for manually overriding the default + * clocksource selction. + */ +static ssize_t sysfs_override_clocksource(struct sys_device *dev, + const char *buf, size_t count) +{ + size_t ret = count; + /* strings from sysfs write are not 0 terminated! */ + if (count >= sizeof(override_name)) + return -EINVAL; + + /* strip of \n: */ + if (buf[count-1] == '\n') + count--; + if (count < 1) + return -EINVAL; + + spin_lock_irq(&clocksource_lock); + + /* copy the name given: */ + memcpy(override_name, buf, count); + override_name[count] = 0; + + /* try to select it: */ + next_clocksource = select_clocksource(); + + spin_unlock_irq(&clocksource_lock); + + return ret; +} + +/** + * sysfs_show_available_clocksources - sysfs interface for listing clocksource + * @dev: unused + * @buf: char buffer to be filled with clocksource list + * + * Provides sysfs interface for listing registered clocksources + */ +static ssize_t +sysfs_show_available_clocksources(struct sys_device *dev, char *buf) +{ + struct list_head *tmp; + char *curr = buf; + + spin_lock_irq(&clocksource_lock); + list_for_each(tmp, &clocksource_list) { + struct clocksource *src; + + src = list_entry(tmp, struct clocksource, list); + curr += sprintf(curr, "%s ", src->name); + } + spin_unlock_irq(&clocksource_lock); + + curr += sprintf(curr, "\n"); + + return curr - buf; +} + +/* + * Sysfs setup bits: + */ +static SYSDEV_ATTR(current_clocksource, 0600, sysfs_show_current_clocksources, + sysfs_override_clocksource); + +static SYSDEV_ATTR(available_clocksource, 0600, + sysfs_show_available_clocksources, NULL); + +static struct sysdev_class clocksource_sysclass = { + set_kset_name("clocksource"), +}; + +static struct sys_device device_clocksource = { + .id = 0, + .cls = &clocksource_sysclass, +}; + +static int __init init_clocksource_sysfs(void) +{ + int error = sysdev_class_register(&clocksource_sysclass); + + if (!error) + error = sysdev_register(&device_clocksource); + if (!error) + error = sysdev_create_file( + &device_clocksource, + &attr_current_clocksource); + if (!error) + error = sysdev_create_file( + &device_clocksource, + &attr_available_clocksource); + return error; +} + +device_initcall(init_clocksource_sysfs); + +/** + * boot_override_clocksource - boot clock override + * @str: override name + * + * Takes a clocksource= boot argument and uses it + * as the clocksource override name. + */ +static int __init boot_override_clocksource(char* str) +{ + unsigned long flags; + spin_lock_irqsave(&clocksource_lock, flags); + if (str) + strlcpy(override_name, str, sizeof(override_name)); + spin_unlock_irqrestore(&clocksource_lock, flags); + return 1; +} + +__setup("clocksource=", boot_override_clocksource); + +/** + * boot_override_clock - Compatibility layer for deprecated boot option + * @str: override name + * + * DEPRECATED! Takes a clock= boot argument and uses it + * as the clocksource override name + */ +static int __init boot_override_clock(char* str) +{ + if (!strcmp(str, "pmtmr")) { + printk("Warning: clock=pmtmr is deprecated. " + "Use clocksource=acpi_pm.\n"); + return boot_override_clocksource("acpi_pm"); + } + printk("Warning! clock= boot option is deprecated. " + "Use clocksource=xyz\n"); + return boot_override_clocksource(str); +} + +__setup("clock=", boot_override_clock); diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c new file mode 100644 index 000000000..126bb30c4 --- /dev/null +++ b/kernel/time/jiffies.c @@ -0,0 +1,73 @@ +/*********************************************************************** +* linux/kernel/time/jiffies.c +* +* This file contains the jiffies based clocksource. +* +* Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com) +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +************************************************************************/ +#include <linux/clocksource.h> +#include <linux/jiffies.h> +#include <linux/init.h> + +/* The Jiffies based clocksource is the lowest common + * denominator clock source which should function on + * all systems. It has the same coarse resolution as + * the timer interrupt frequency HZ and it suffers + * inaccuracies caused by missed or lost timer + * interrupts and the inability for the timer + * interrupt hardware to accuratly tick at the + * requested HZ value. It is also not reccomended + * for "tick-less" systems. + */ +#define NSEC_PER_JIFFY ((u32)((((u64)NSEC_PER_SEC)<<8)/ACTHZ)) + +/* Since jiffies uses a simple NSEC_PER_JIFFY multiplier + * conversion, the .shift value could be zero. However + * this would make NTP adjustments impossible as they are + * in units of 1/2^.shift. Thus we use JIFFIES_SHIFT to + * shift both the nominator and denominator the same + * amount, and give ntp adjustments in units of 1/2^8 + * + * The value 8 is somewhat carefully chosen, as anything + * larger can result in overflows. NSEC_PER_JIFFY grows as + * HZ shrinks, so values greater then 8 overflow 32bits when + * HZ=100. + */ +#define JIFFIES_SHIFT 8 + +static cycle_t jiffies_read(void) +{ + return (cycle_t) jiffies; +} + +struct clocksource clocksource_jiffies = { + .name = "jiffies", + .rating = 0, /* lowest rating*/ + .read = jiffies_read, + .mask = 0xffffffff, /*32bits*/ + .mult = NSEC_PER_JIFFY << JIFFIES_SHIFT, /* details above */ + .shift = JIFFIES_SHIFT, + .is_continuous = 0, /* tick based, not free running */ +}; + +static int __init init_jiffies_clocksource(void) +{ + return clocksource_register(&clocksource_jiffies); +} + +module_init(init_jiffies_clocksource); diff --git a/kernel/unwind.c b/kernel/unwind.c new file mode 100644 index 000000000..47281af3f --- /dev/null +++ b/kernel/unwind.c @@ -0,0 +1,920 @@ +/* + * Copyright (C) 2002-2006 Novell, Inc. + * Jan Beulich <jbeulich@novell.com> + * This code is released under version 2 of the GNU GPL. + * + * A simple API for unwinding kernel stacks. This is used for + * debugging and error reporting purposes. The kernel doesn't need + * full-blown stack unwinding with all the bells and whistles, so there + * is not much point in implementing the full Dwarf2 unwind API. + */ + +#include <linux/unwind.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/stop_machine.h> +#include <asm/sections.h> +#include <asm/uaccess.h> +#include <asm/unaligned.h> + +extern char __start_unwind[], __end_unwind[]; + +#define MAX_STACK_DEPTH 8 + +#define EXTRA_INFO(f) { \ + BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \ + % FIELD_SIZEOF(struct unwind_frame_info, f)) \ + + offsetof(struct unwind_frame_info, f) \ + / FIELD_SIZEOF(struct unwind_frame_info, f), \ + FIELD_SIZEOF(struct unwind_frame_info, f) \ + } +#define PTREGS_INFO(f) EXTRA_INFO(regs.f) + +static const struct { + unsigned offs:BITS_PER_LONG / 2; + unsigned width:BITS_PER_LONG / 2; +} reg_info[] = { + UNW_REGISTER_INFO +}; + +#undef PTREGS_INFO +#undef EXTRA_INFO + +#ifndef REG_INVALID +#define REG_INVALID(r) (reg_info[r].width == 0) +#endif + +#define DW_CFA_nop 0x00 +#define DW_CFA_set_loc 0x01 +#define DW_CFA_advance_loc1 0x02 +#define DW_CFA_advance_loc2 0x03 +#define DW_CFA_advance_loc4 0x04 +#define DW_CFA_offset_extended 0x05 +#define DW_CFA_restore_extended 0x06 +#define DW_CFA_undefined 0x07 +#define DW_CFA_same_value 0x08 +#define DW_CFA_register 0x09 +#define DW_CFA_remember_state 0x0a +#define DW_CFA_restore_state 0x0b +#define DW_CFA_def_cfa 0x0c +#define DW_CFA_def_cfa_register 0x0d +#define DW_CFA_def_cfa_offset 0x0e +#define DW_CFA_def_cfa_expression 0x0f +#define DW_CFA_expression 0x10 +#define DW_CFA_offset_extended_sf 0x11 +#define DW_CFA_def_cfa_sf 0x12 +#define DW_CFA_def_cfa_offset_sf 0x13 +#define DW_CFA_val_offset 0x14 +#define DW_CFA_val_offset_sf 0x15 +#define DW_CFA_val_expression 0x16 +#define DW_CFA_lo_user 0x1c +#define DW_CFA_GNU_window_save 0x2d +#define DW_CFA_GNU_args_size 0x2e +#define DW_CFA_GNU_negative_offset_extended 0x2f +#define DW_CFA_hi_user 0x3f + +#define DW_EH_PE_FORM 0x07 +#define DW_EH_PE_native 0x00 +#define DW_EH_PE_leb128 0x01 +#define DW_EH_PE_data2 0x02 +#define DW_EH_PE_data4 0x03 +#define DW_EH_PE_data8 0x04 +#define DW_EH_PE_signed 0x08 +#define DW_EH_PE_ADJUST 0x70 +#define DW_EH_PE_abs 0x00 +#define DW_EH_PE_pcrel 0x10 +#define DW_EH_PE_textrel 0x20 +#define DW_EH_PE_datarel 0x30 +#define DW_EH_PE_funcrel 0x40 +#define DW_EH_PE_aligned 0x50 +#define DW_EH_PE_indirect 0x80 +#define DW_EH_PE_omit 0xff + +typedef unsigned long uleb128_t; +typedef signed long sleb128_t; + +static struct unwind_table { + struct { + unsigned long pc; + unsigned long range; + } core, init; + const void *address; + unsigned long size; + struct unwind_table *link; + const char *name; +} root_table; + +struct unwind_item { + enum item_location { + Nowhere, + Memory, + Register, + Value + } where; + uleb128_t value; +}; + +struct unwind_state { + uleb128_t loc, org; + const u8 *cieStart, *cieEnd; + uleb128_t codeAlign; + sleb128_t dataAlign; + struct cfa { + uleb128_t reg, offs; + } cfa; + struct unwind_item regs[ARRAY_SIZE(reg_info)]; + unsigned stackDepth:8; + unsigned version:8; + const u8 *label; + const u8 *stack[MAX_STACK_DEPTH]; +}; + +static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 }; + +static struct unwind_table *find_table(unsigned long pc) +{ + struct unwind_table *table; + + for (table = &root_table; table; table = table->link) + if ((pc >= table->core.pc + && pc < table->core.pc + table->core.range) + || (pc >= table->init.pc + && pc < table->init.pc + table->init.range)) + break; + + return table; +} + +static void init_unwind_table(struct unwind_table *table, + const char *name, + const void *core_start, + unsigned long core_size, + const void *init_start, + unsigned long init_size, + const void *table_start, + unsigned long table_size) +{ + table->core.pc = (unsigned long)core_start; + table->core.range = core_size; + table->init.pc = (unsigned long)init_start; + table->init.range = init_size; + table->address = table_start; + table->size = table_size; + table->link = NULL; + table->name = name; +} + +void __init unwind_init(void) +{ + init_unwind_table(&root_table, "kernel", + _text, _end - _text, + NULL, 0, + __start_unwind, __end_unwind - __start_unwind); +} + +#ifdef CONFIG_MODULES + +static struct unwind_table *last_table; + +/* Must be called with module_mutex held. */ +void *unwind_add_table(struct module *module, + const void *table_start, + unsigned long table_size) +{ + struct unwind_table *table; + + if (table_size <= 0) + return NULL; + + table = kmalloc(sizeof(*table), GFP_KERNEL); + if (!table) + return NULL; + + init_unwind_table(table, module->name, + module->module_core, module->core_size, + module->module_init, module->init_size, + table_start, table_size); + + if (last_table) + last_table->link = table; + else + root_table.link = table; + last_table = table; + + return table; +} + +struct unlink_table_info +{ + struct unwind_table *table; + int init_only; +}; + +static int unlink_table(void *arg) +{ + struct unlink_table_info *info = arg; + struct unwind_table *table = info->table, *prev; + + for (prev = &root_table; prev->link && prev->link != table; prev = prev->link) + ; + + if (prev->link) { + if (info->init_only) { + table->init.pc = 0; + table->init.range = 0; + info->table = NULL; + } else { + prev->link = table->link; + if (!prev->link) + last_table = prev; + } + } else + info->table = NULL; + + return 0; +} + +/* Must be called with module_mutex held. */ +void unwind_remove_table(void *handle, int init_only) +{ + struct unwind_table *table = handle; + struct unlink_table_info info; + + if (!table || table == &root_table) + return; + + if (init_only && table == last_table) { + table->init.pc = 0; + table->init.range = 0; + return; + } + + info.table = table; + info.init_only = init_only; + stop_machine_run(unlink_table, &info, NR_CPUS); + + if (info.table) + kfree(table); +} + +#endif /* CONFIG_MODULES */ + +static uleb128_t get_uleb128(const u8 **pcur, const u8 *end) +{ + const u8 *cur = *pcur; + uleb128_t value; + unsigned shift; + + for (shift = 0, value = 0; cur < end; shift += 7) { + if (shift + 7 > 8 * sizeof(value) + && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) { + cur = end + 1; + break; + } + value |= (uleb128_t)(*cur & 0x7f) << shift; + if (!(*cur++ & 0x80)) + break; + } + *pcur = cur; + + return value; +} + +static sleb128_t get_sleb128(const u8 **pcur, const u8 *end) +{ + const u8 *cur = *pcur; + sleb128_t value; + unsigned shift; + + for (shift = 0, value = 0; cur < end; shift += 7) { + if (shift + 7 > 8 * sizeof(value) + && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) { + cur = end + 1; + break; + } + value |= (sleb128_t)(*cur & 0x7f) << shift; + if (!(*cur & 0x80)) { + value |= -(*cur++ & 0x40) << shift; + break; + } + } + *pcur = cur; + + return value; +} + +static unsigned long read_pointer(const u8 **pLoc, + const void *end, + signed ptrType) +{ + unsigned long value = 0; + union { + const u8 *p8; + const u16 *p16u; + const s16 *p16s; + const u32 *p32u; + const s32 *p32s; + const unsigned long *pul; + } ptr; + + if (ptrType < 0 || ptrType == DW_EH_PE_omit) + return 0; + ptr.p8 = *pLoc; + switch(ptrType & DW_EH_PE_FORM) { + case DW_EH_PE_data2: + if (end < (const void *)(ptr.p16u + 1)) + return 0; + if(ptrType & DW_EH_PE_signed) + value = get_unaligned(ptr.p16s++); + else + value = get_unaligned(ptr.p16u++); + break; + case DW_EH_PE_data4: +#ifdef CONFIG_64BIT + if (end < (const void *)(ptr.p32u + 1)) + return 0; + if(ptrType & DW_EH_PE_signed) + value = get_unaligned(ptr.p32s++); + else + value = get_unaligned(ptr.p32u++); + break; + case DW_EH_PE_data8: + BUILD_BUG_ON(sizeof(u64) != sizeof(value)); +#else + BUILD_BUG_ON(sizeof(u32) != sizeof(value)); +#endif + case DW_EH_PE_native: + if (end < (const void *)(ptr.pul + 1)) + return 0; + value = get_unaligned(ptr.pul++); + break; + case DW_EH_PE_leb128: + BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value)); + value = ptrType & DW_EH_PE_signed + ? get_sleb128(&ptr.p8, end) + : get_uleb128(&ptr.p8, end); + if ((const void *)ptr.p8 > end) + return 0; + break; + default: + return 0; + } + switch(ptrType & DW_EH_PE_ADJUST) { + case DW_EH_PE_abs: + break; + case DW_EH_PE_pcrel: + value += (unsigned long)*pLoc; + break; + default: + return 0; + } + if ((ptrType & DW_EH_PE_indirect) + && __get_user(value, (unsigned long *)value)) + return 0; + *pLoc = ptr.p8; + + return value; +} + +static signed fde_pointer_type(const u32 *cie) +{ + const u8 *ptr = (const u8 *)(cie + 2); + unsigned version = *ptr; + + if (version != 1) + return -1; /* unsupported */ + if (*++ptr) { + const char *aug; + const u8 *end = (const u8 *)(cie + 1) + *cie; + uleb128_t len; + + /* check if augmentation size is first (and thus present) */ + if (*ptr != 'z') + return -1; + /* check if augmentation string is nul-terminated */ + if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL) + return -1; + ++ptr; /* skip terminator */ + get_uleb128(&ptr, end); /* skip code alignment */ + get_sleb128(&ptr, end); /* skip data alignment */ + /* skip return address column */ + version <= 1 ? (void)++ptr : (void)get_uleb128(&ptr, end); + len = get_uleb128(&ptr, end); /* augmentation length */ + if (ptr + len < ptr || ptr + len > end) + return -1; + end = ptr + len; + while (*++aug) { + if (ptr >= end) + return -1; + switch(*aug) { + case 'L': + ++ptr; + break; + case 'P': { + signed ptrType = *ptr++; + + if (!read_pointer(&ptr, end, ptrType) || ptr > end) + return -1; + } + break; + case 'R': + return *ptr; + default: + return -1; + } + } + } + return DW_EH_PE_native|DW_EH_PE_abs; +} + +static int advance_loc(unsigned long delta, struct unwind_state *state) +{ + state->loc += delta * state->codeAlign; + + return delta > 0; +} + +static void set_rule(uleb128_t reg, + enum item_location where, + uleb128_t value, + struct unwind_state *state) +{ + if (reg < ARRAY_SIZE(state->regs)) { + state->regs[reg].where = where; + state->regs[reg].value = value; + } +} + +static int processCFI(const u8 *start, + const u8 *end, + unsigned long targetLoc, + signed ptrType, + struct unwind_state *state) +{ + union { + const u8 *p8; + const u16 *p16; + const u32 *p32; + } ptr; + int result = 1; + + if (start != state->cieStart) { + state->loc = state->org; + result = processCFI(state->cieStart, state->cieEnd, 0, ptrType, state); + if (targetLoc == 0 && state->label == NULL) + return result; + } + for (ptr.p8 = start; result && ptr.p8 < end; ) { + switch(*ptr.p8 >> 6) { + uleb128_t value; + + case 0: + switch(*ptr.p8++) { + case DW_CFA_nop: + break; + case DW_CFA_set_loc: + if ((state->loc = read_pointer(&ptr.p8, end, ptrType)) == 0) + result = 0; + break; + case DW_CFA_advance_loc1: + result = ptr.p8 < end && advance_loc(*ptr.p8++, state); + break; + case DW_CFA_advance_loc2: + result = ptr.p8 <= end + 2 + && advance_loc(*ptr.p16++, state); + break; + case DW_CFA_advance_loc4: + result = ptr.p8 <= end + 4 + && advance_loc(*ptr.p32++, state); + break; + case DW_CFA_offset_extended: + value = get_uleb128(&ptr.p8, end); + set_rule(value, Memory, get_uleb128(&ptr.p8, end), state); + break; + case DW_CFA_val_offset: + value = get_uleb128(&ptr.p8, end); + set_rule(value, Value, get_uleb128(&ptr.p8, end), state); + break; + case DW_CFA_offset_extended_sf: + value = get_uleb128(&ptr.p8, end); + set_rule(value, Memory, get_sleb128(&ptr.p8, end), state); + break; + case DW_CFA_val_offset_sf: + value = get_uleb128(&ptr.p8, end); + set_rule(value, Value, get_sleb128(&ptr.p8, end), state); + break; + case DW_CFA_restore_extended: + case DW_CFA_undefined: + case DW_CFA_same_value: + set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0, state); + break; + case DW_CFA_register: + value = get_uleb128(&ptr.p8, end); + set_rule(value, + Register, + get_uleb128(&ptr.p8, end), state); + break; + case DW_CFA_remember_state: + if (ptr.p8 == state->label) { + state->label = NULL; + return 1; + } + if (state->stackDepth >= MAX_STACK_DEPTH) + return 0; + state->stack[state->stackDepth++] = ptr.p8; + break; + case DW_CFA_restore_state: + if (state->stackDepth) { + const uleb128_t loc = state->loc; + const u8 *label = state->label; + + state->label = state->stack[state->stackDepth - 1]; + memcpy(&state->cfa, &badCFA, sizeof(state->cfa)); + memset(state->regs, 0, sizeof(state->regs)); + state->stackDepth = 0; + result = processCFI(start, end, 0, ptrType, state); + state->loc = loc; + state->label = label; + } else + return 0; + break; + case DW_CFA_def_cfa: + state->cfa.reg = get_uleb128(&ptr.p8, end); + /*nobreak*/ + case DW_CFA_def_cfa_offset: + state->cfa.offs = get_uleb128(&ptr.p8, end); + break; + case DW_CFA_def_cfa_sf: + state->cfa.reg = get_uleb128(&ptr.p8, end); + /*nobreak*/ + case DW_CFA_def_cfa_offset_sf: + state->cfa.offs = get_sleb128(&ptr.p8, end) + * state->dataAlign; + break; + case DW_CFA_def_cfa_register: + state->cfa.reg = get_uleb128(&ptr.p8, end); + break; + /*todo case DW_CFA_def_cfa_expression: */ + /*todo case DW_CFA_expression: */ + /*todo case DW_CFA_val_expression: */ + case DW_CFA_GNU_args_size: + get_uleb128(&ptr.p8, end); + break; + case DW_CFA_GNU_negative_offset_extended: + value = get_uleb128(&ptr.p8, end); + set_rule(value, + Memory, + (uleb128_t)0 - get_uleb128(&ptr.p8, end), state); + break; + case DW_CFA_GNU_window_save: + default: + result = 0; + break; + } + break; + case 1: + result = advance_loc(*ptr.p8++ & 0x3f, state); + break; + case 2: + value = *ptr.p8++ & 0x3f; + set_rule(value, Memory, get_uleb128(&ptr.p8, end), state); + break; + case 3: + set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state); + break; + } + if (ptr.p8 > end) + result = 0; + if (result && targetLoc != 0 && targetLoc < state->loc) + return 1; + } + + return result + && ptr.p8 == end + && (targetLoc == 0 + || (/*todo While in theory this should apply, gcc in practice omits + everything past the function prolog, and hence the location + never reaches the end of the function. + targetLoc < state->loc &&*/ state->label == NULL)); +} + +/* Unwind to previous to frame. Returns 0 if successful, negative + * number in case of an error. */ +int unwind(struct unwind_frame_info *frame) +{ +#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs]) + const u32 *fde = NULL, *cie = NULL; + const u8 *ptr = NULL, *end = NULL; + unsigned long startLoc = 0, endLoc = 0, cfa; + unsigned i; + signed ptrType = -1; + uleb128_t retAddrReg = 0; + struct unwind_table *table; + struct unwind_state state; + + if (UNW_PC(frame) == 0) + return -EINVAL; + if ((table = find_table(UNW_PC(frame))) != NULL + && !(table->size & (sizeof(*fde) - 1))) { + unsigned long tableSize = table->size; + + for (fde = table->address; + tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde; + tableSize -= sizeof(*fde) + *fde, + fde += 1 + *fde / sizeof(*fde)) { + if (!*fde || (*fde & (sizeof(*fde) - 1))) + break; + if (!fde[1]) + continue; /* this is a CIE */ + if ((fde[1] & (sizeof(*fde) - 1)) + || fde[1] > (unsigned long)(fde + 1) + - (unsigned long)table->address) + continue; /* this is not a valid FDE */ + cie = fde + 1 - fde[1] / sizeof(*fde); + if (*cie <= sizeof(*cie) + 4 + || *cie >= fde[1] - sizeof(*fde) + || (*cie & (sizeof(*cie) - 1)) + || cie[1] + || (ptrType = fde_pointer_type(cie)) < 0) { + cie = NULL; /* this is not a (valid) CIE */ + continue; + } + ptr = (const u8 *)(fde + 2); + startLoc = read_pointer(&ptr, + (const u8 *)(fde + 1) + *fde, + ptrType); + endLoc = startLoc + + read_pointer(&ptr, + (const u8 *)(fde + 1) + *fde, + ptrType & DW_EH_PE_indirect + ? ptrType + : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed)); + if (UNW_PC(frame) >= startLoc && UNW_PC(frame) < endLoc) + break; + cie = NULL; + } + } + if (cie != NULL) { + memset(&state, 0, sizeof(state)); + state.cieEnd = ptr; /* keep here temporarily */ + ptr = (const u8 *)(cie + 2); + end = (const u8 *)(cie + 1) + *cie; + if ((state.version = *ptr) != 1) + cie = NULL; /* unsupported version */ + else if (*++ptr) { + /* check if augmentation size is first (and thus present) */ + if (*ptr == 'z') { + /* check for ignorable (or already handled) + * nul-terminated augmentation string */ + while (++ptr < end && *ptr) + if (strchr("LPR", *ptr) == NULL) + break; + } + if (ptr >= end || *ptr) + cie = NULL; + } + ++ptr; + } + if (cie != NULL) { + /* get code aligment factor */ + state.codeAlign = get_uleb128(&ptr, end); + /* get data aligment factor */ + state.dataAlign = get_sleb128(&ptr, end); + if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end) + cie = NULL; + else { + retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end); + /* skip augmentation */ + if (((const char *)(cie + 2))[1] == 'z') + ptr += get_uleb128(&ptr, end); + if (ptr > end + || retAddrReg >= ARRAY_SIZE(reg_info) + || REG_INVALID(retAddrReg) + || reg_info[retAddrReg].width != sizeof(unsigned long)) + cie = NULL; + } + } + if (cie != NULL) { + state.cieStart = ptr; + ptr = state.cieEnd; + state.cieEnd = end; + end = (const u8 *)(fde + 1) + *fde; + /* skip augmentation */ + if (((const char *)(cie + 2))[1] == 'z') { + uleb128_t augSize = get_uleb128(&ptr, end); + + if ((ptr += augSize) > end) + fde = NULL; + } + } + if (cie == NULL || fde == NULL) { +#ifdef CONFIG_FRAME_POINTER + unsigned long top, bottom; +#endif + +#ifdef CONFIG_FRAME_POINTER + top = STACK_TOP(frame->task); + bottom = STACK_BOTTOM(frame->task); +# if FRAME_RETADDR_OFFSET < 0 + if (UNW_SP(frame) < top + && UNW_FP(frame) <= UNW_SP(frame) + && bottom < UNW_FP(frame) +# else + if (UNW_SP(frame) > top + && UNW_FP(frame) >= UNW_SP(frame) + && bottom > UNW_FP(frame) +# endif + && !((UNW_SP(frame) | UNW_FP(frame)) + & (sizeof(unsigned long) - 1))) { + unsigned long link; + + if (!__get_user(link, + (unsigned long *)(UNW_FP(frame) + + FRAME_LINK_OFFSET)) +# if FRAME_RETADDR_OFFSET < 0 + && link > bottom && link < UNW_FP(frame) +# else + && link > UNW_FP(frame) && link < bottom +# endif + && !(link & (sizeof(link) - 1)) + && !__get_user(UNW_PC(frame), + (unsigned long *)(UNW_FP(frame) + + FRAME_RETADDR_OFFSET))) { + UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET +# if FRAME_RETADDR_OFFSET < 0 + - +# else + + +# endif + sizeof(UNW_PC(frame)); + UNW_FP(frame) = link; + return 0; + } + } +#endif + return -ENXIO; + } + state.org = startLoc; + memcpy(&state.cfa, &badCFA, sizeof(state.cfa)); + /* process instructions */ + if (!processCFI(ptr, end, UNW_PC(frame), ptrType, &state) + || state.loc > endLoc + || state.regs[retAddrReg].where == Nowhere + || state.cfa.reg >= ARRAY_SIZE(reg_info) + || reg_info[state.cfa.reg].width != sizeof(unsigned long) + || state.cfa.offs % sizeof(unsigned long)) + return -EIO; + /* update frame */ + cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs; + startLoc = min((unsigned long)UNW_SP(frame), cfa); + endLoc = max((unsigned long)UNW_SP(frame), cfa); + if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) { + startLoc = min(STACK_LIMIT(cfa), cfa); + endLoc = max(STACK_LIMIT(cfa), cfa); + } +#ifndef CONFIG_64BIT +# define CASES CASE(8); CASE(16); CASE(32) +#else +# define CASES CASE(8); CASE(16); CASE(32); CASE(64) +#endif + for (i = 0; i < ARRAY_SIZE(state.regs); ++i) { + if (REG_INVALID(i)) { + if (state.regs[i].where == Nowhere) + continue; + return -EIO; + } + switch(state.regs[i].where) { + default: + break; + case Register: + if (state.regs[i].value >= ARRAY_SIZE(reg_info) + || REG_INVALID(state.regs[i].value) + || reg_info[i].width > reg_info[state.regs[i].value].width) + return -EIO; + switch(reg_info[state.regs[i].value].width) { +#define CASE(n) \ + case sizeof(u##n): \ + state.regs[i].value = FRAME_REG(state.regs[i].value, \ + const u##n); \ + break + CASES; +#undef CASE + default: + return -EIO; + } + break; + } + } + for (i = 0; i < ARRAY_SIZE(state.regs); ++i) { + if (REG_INVALID(i)) + continue; + switch(state.regs[i].where) { + case Nowhere: + if (reg_info[i].width != sizeof(UNW_SP(frame)) + || &FRAME_REG(i, __typeof__(UNW_SP(frame))) + != &UNW_SP(frame)) + continue; + UNW_SP(frame) = cfa; + break; + case Register: + switch(reg_info[i].width) { +#define CASE(n) case sizeof(u##n): \ + FRAME_REG(i, u##n) = state.regs[i].value; \ + break + CASES; +#undef CASE + default: + return -EIO; + } + break; + case Value: + if (reg_info[i].width != sizeof(unsigned long)) + return -EIO; + FRAME_REG(i, unsigned long) = cfa + state.regs[i].value + * state.dataAlign; + break; + case Memory: { + unsigned long addr = cfa + state.regs[i].value + * state.dataAlign; + + if ((state.regs[i].value * state.dataAlign) + % sizeof(unsigned long) + || addr < startLoc + || addr + sizeof(unsigned long) < addr + || addr + sizeof(unsigned long) > endLoc) + return -EIO; + switch(reg_info[i].width) { +#define CASE(n) case sizeof(u##n): \ + __get_user(FRAME_REG(i, u##n), (u##n *)addr); \ + break + CASES; +#undef CASE + default: + return -EIO; + } + } + break; + } + } + + return 0; +#undef CASES +#undef FRAME_REG +} +EXPORT_SYMBOL(unwind); + +int unwind_init_frame_info(struct unwind_frame_info *info, + struct task_struct *tsk, + /*const*/ struct pt_regs *regs) +{ + info->task = tsk; + arch_unw_init_frame_info(info, regs); + + return 0; +} +EXPORT_SYMBOL(unwind_init_frame_info); + +/* + * Prepare to unwind a blocked task. + */ +int unwind_init_blocked(struct unwind_frame_info *info, + struct task_struct *tsk) +{ + info->task = tsk; + arch_unw_init_blocked(info); + + return 0; +} +EXPORT_SYMBOL(unwind_init_blocked); + +/* + * Prepare to unwind the currently running thread. + */ +int unwind_init_running(struct unwind_frame_info *info, + asmlinkage int (*callback)(struct unwind_frame_info *, + void *arg), + void *arg) +{ + info->task = current; + + return arch_unwind_init_running(info, callback, arg); +} +EXPORT_SYMBOL(unwind_init_running); + +/* + * Unwind until the return pointer is in user-land (or until an error + * occurs). Returns 0 if successful, negative number in case of + * error. + */ +int unwind_to_user(struct unwind_frame_info *info) +{ + while (!arch_unw_user_mode(info)) { + int err = unwind(info); + + if (err < 0) + return err; + } + + return 0; +} +EXPORT_SYMBOL(unwind_to_user); diff --git a/kernel/utrace.c b/kernel/utrace.c new file mode 100644 index 000000000..52d9b0059 --- /dev/null +++ b/kernel/utrace.c @@ -0,0 +1,1598 @@ +#include <linux/utrace.h> +#include <linux/tracehook.h> +#include <linux/err.h> +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <asm/tracehook.h> + + +static kmem_cache_t *utrace_cachep; +static kmem_cache_t *utrace_engine_cachep; + +static int __init +utrace_init(void) +{ + utrace_cachep = + kmem_cache_create("utrace_cache", + sizeof(struct utrace), 0, + SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); + utrace_engine_cachep = + kmem_cache_create("utrace_engine_cache", + sizeof(struct utrace_attached_engine), 0, + SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); + return 0; +} +subsys_initcall(utrace_init); + + +/* + * Make sure target->utrace is allocated, and return with it locked on + * success. This function mediates startup races. The creating parent + * task has priority, and other callers will delay here to let its call + * succeed and take the new utrace lock first. + */ +static struct utrace * +utrace_first_engine(struct task_struct *target, + struct utrace_attached_engine *engine) +{ + struct utrace *utrace, *ret; + + /* + * If this is a newborn thread and we are not the creator, + * we have to wait for it. The creator gets the first chance + * to attach. The PF_STARTING flag is cleared after its + * report_clone hook has had a chance to run. + */ + if ((target->flags & PF_STARTING) + && (current->utrace == NULL + || current->utrace->u.live.cloning != target)) { + yield(); + return (signal_pending(current) + ? ERR_PTR(-ERESTARTNOINTR) : NULL); + } + + utrace = kmem_cache_alloc(utrace_cachep, SLAB_KERNEL); + if (unlikely(utrace == NULL)) + return ERR_PTR(-ENOMEM); + + utrace->u.live.cloning = NULL; + utrace->u.live.signal = NULL; + INIT_LIST_HEAD(&utrace->engines); + list_add(&engine->entry, &utrace->engines); + spin_lock_init(&utrace->lock); + + ret = utrace; + utrace_lock(utrace); + task_lock(target); + if (likely(target->utrace == NULL)) { + rcu_assign_pointer(target->utrace, utrace); + /* + * The task_lock protects us against another thread doing + * the same thing. We might still be racing against + * tracehook_release_task. It's called with ->exit_state + * set to EXIT_DEAD and then checks ->utrace with an + * smp_mb() in between. If EXIT_DEAD is set, then + * release_task might have checked ->utrace already and saw + * it NULL; we can't attach. If we see EXIT_DEAD not yet + * set after our barrier, then we know release_task will + * see our target->utrace pointer. + */ + smp_mb(); + if (target->exit_state == EXIT_DEAD) { + /* + * The target has already been through release_task. + */ + target->utrace = NULL; + goto cannot_attach; + } + task_unlock(target); + + /* + * If the thread is already dead when we attach, then its + * parent was notified already and we shouldn't repeat the + * notification later after a detach or NOREAP flag change. + */ + if (target->exit_state) + utrace->u.exit.notified = 1; + } + else { + /* + * Another engine attached first, so there is a struct already. + * A null return says to restart looking for the existing one. + */ + cannot_attach: + ret = NULL; + task_unlock(target); + utrace_unlock(utrace); + kmem_cache_free(utrace_cachep, utrace); + } + + return ret; +} + +static void +utrace_free(struct rcu_head *rhead) +{ + struct utrace *utrace = container_of(rhead, struct utrace, u.dead); + kmem_cache_free(utrace_cachep, utrace); +} + +static void +rcu_utrace_free(struct utrace *utrace) +{ + INIT_RCU_HEAD(&utrace->u.dead); + call_rcu(&utrace->u.dead, utrace_free); +} + +static void +utrace_engine_free(struct rcu_head *rhead) +{ + struct utrace_attached_engine *engine = + container_of(rhead, struct utrace_attached_engine, rhead); + kmem_cache_free(utrace_engine_cachep, engine); +} + +/* + * Called with utrace locked and the target quiescent (maybe current). + * If this was the last engine, utrace is left locked and not freed, + * but is removed from the task. + */ +static void +remove_engine(struct utrace_attached_engine *engine, + struct task_struct *tsk, struct utrace *utrace) +{ + list_del_rcu(&engine->entry); + if (list_empty(&utrace->engines)) { + task_lock(tsk); + if (likely(tsk->utrace != NULL)) { + rcu_assign_pointer(tsk->utrace, NULL); + tsk->utrace_flags = 0; + } + task_unlock(tsk); + } + call_rcu(&engine->rhead, utrace_engine_free); +} + +/* + * This is pointed to by the utrace struct, but it's really a private + * structure between utrace_get_signal and utrace_inject_signal. + */ +struct utrace_signal +{ + siginfo_t *const info; + struct k_sigaction *return_ka; + int signr; +}; + +/* + * Called with utrace locked, after remove_engine may have run. + * Passed the flags from all remaining engines, i.e. zero if none left. + * Install the flags in tsk->utrace_flags and return with utrace unlocked. + * If no engines are left, utrace is freed and we return NULL. + */ +static struct utrace * +check_dead_utrace(struct task_struct *tsk, struct utrace *utrace, + unsigned long flags) +{ + if (flags) { + tsk->utrace_flags = flags; + utrace_unlock(utrace); + return utrace; + } + + if (utrace->u.live.signal && utrace->u.live.signal->signr != 0) { + utrace_unlock(utrace); + return utrace; + } + + utrace_unlock(utrace); + rcu_utrace_free(utrace); + return NULL; +} + + + +/* + * Get the target thread to quiesce. Return nonzero if it's already quiescent. + * Return zero if it will report a QUIESCE event soon. + * If interrupt is nonzero, wake it like a signal would so it quiesces ASAP. + * If interrupt is zero, just make sure it quiesces before going to user mode. + */ +static int +quiesce(struct task_struct *target, int interrupt) +{ + int quiescent; + + target->utrace_flags |= UTRACE_ACTION_QUIESCE; + read_barrier_depends(); + + quiescent = (target->exit_state + || target->state & (TASK_TRACED | TASK_STOPPED)); + + if (!quiescent) { + spin_lock_irq(&target->sighand->siglock); + quiescent = (unlikely(target->exit_state) + || unlikely(target->state + & (TASK_TRACED | TASK_STOPPED))); + if (!quiescent) { + if (interrupt) + signal_wake_up(target, 0); + else { + set_tsk_thread_flag(target, TIF_SIGPENDING); + kick_process(target); + } + } + spin_unlock_irq(&target->sighand->siglock); + } + + return quiescent; +} + + +static struct utrace_attached_engine * +matching_engine(struct utrace *utrace, int flags, + const struct utrace_engine_ops *ops, unsigned long data) +{ + struct utrace_attached_engine *engine; + list_for_each_entry_rcu(engine, &utrace->engines, entry) { + if ((flags & UTRACE_ATTACH_MATCH_OPS) + && engine->ops != ops) + continue; + if ((flags & UTRACE_ATTACH_MATCH_DATA) + && engine->data != data) + continue; + if (flags & UTRACE_ATTACH_EXCLUSIVE) + engine = ERR_PTR(-EEXIST); + return engine; + } + return NULL; +} + +/* + option to stop it? + option to match existing on ops, ops+data, return it; nocreate:lookup only + */ +struct utrace_attached_engine * +utrace_attach(struct task_struct *target, int flags, + const struct utrace_engine_ops *ops, unsigned long data) +{ + struct utrace *utrace; + struct utrace_attached_engine *engine; + +restart: + rcu_read_lock(); + utrace = rcu_dereference(target->utrace); + smp_rmb(); + if (utrace == NULL) { + rcu_read_unlock(); + + if (!(flags & UTRACE_ATTACH_CREATE)) { + return ERR_PTR(-ENOENT); + } + + engine = kmem_cache_alloc(utrace_engine_cachep, SLAB_KERNEL); + if (unlikely(engine == NULL)) + return ERR_PTR(-ENOMEM); + engine->flags = 0; + + first: + utrace = utrace_first_engine(target, engine); + if (IS_ERR(utrace)) { + kmem_cache_free(utrace_engine_cachep, engine); + return ERR_PTR(PTR_ERR(utrace)); + } + if (unlikely(utrace == NULL)) /* Race condition. */ + goto restart; + } + else if (unlikely(target->exit_state == EXIT_DEAD)) { + /* + * The target has already been reaped. + */ + rcu_read_unlock(); + return ERR_PTR(-ESRCH); + } + else { + if (!(flags & UTRACE_ATTACH_CREATE)) { + engine = matching_engine(utrace, flags, ops, data); + rcu_read_unlock(); + return engine; + } + + engine = kmem_cache_alloc(utrace_engine_cachep, SLAB_KERNEL); + if (unlikely(engine == NULL)) + return ERR_PTR(-ENOMEM); + engine->flags = ops->report_reap ? UTRACE_EVENT(REAP) : 0; + + rcu_read_lock(); + utrace = rcu_dereference(target->utrace); + if (unlikely(utrace == NULL)) { /* Race with detach. */ + rcu_read_unlock(); + goto first; + } + + utrace_lock(utrace); + if (flags & UTRACE_ATTACH_EXCLUSIVE) { + struct utrace_attached_engine *old; + old = matching_engine(utrace, flags, ops, data); + if (old != NULL) { + utrace_unlock(utrace); + rcu_read_unlock(); + kmem_cache_free(utrace_engine_cachep, engine); + return ERR_PTR(-EEXIST); + } + } + + if (unlikely(rcu_dereference(target->utrace) != utrace)) { + /* + * We lost a race with other CPUs doing a sequence + * of detach and attach before we got in. + */ + utrace_unlock(utrace); + rcu_read_unlock(); + kmem_cache_free(utrace_engine_cachep, engine); + goto restart; + } + list_add_tail_rcu(&engine->entry, &utrace->engines); + } + + engine->ops = ops; + engine->data = data; + + utrace_unlock(utrace); + + return engine; +} +EXPORT_SYMBOL_GPL(utrace_attach); + +/* + * When an engine is detached, the target thread may still see it and make + * callbacks until it quiesces. We reset its event flags to just QUIESCE + * and install a special ops vector whose callback is dead_engine_delete. + * When the target thread quiesces, it can safely free the engine itself. + */ +static u32 +dead_engine_delete(struct utrace_attached_engine *engine, + struct task_struct *tsk) +{ + return UTRACE_ACTION_DETACH; +} + +static const struct utrace_engine_ops dead_engine_ops = +{ + .report_quiesce = &dead_engine_delete +}; + + +/* + * If tracing was preventing a SIGCHLD or self-reaping + * and is no longer, do that report or reaping right now. + */ +static void +check_noreap(struct task_struct *target, struct utrace *utrace, + u32 old_action, u32 action) +{ + if ((action | ~old_action) & UTRACE_ACTION_NOREAP) + return; + + if (utrace && xchg(&utrace->u.exit.notified, 1)) + return; + + if (target->exit_signal == -1) + release_task(target); + else if (thread_group_empty(target)) { + read_lock(&tasklist_lock); + do_notify_parent(target, target->exit_signal); + read_unlock(&tasklist_lock); + } +} + +/* + * We may have been the one keeping the target thread quiescent. + * Check if it should wake up now. + * Called with utrace locked, and unlocks it on return. + * If we were keeping it stopped, resume it. + * If we were keeping its zombie from reporting/self-reap, do it now. + */ +static void +wake_quiescent(unsigned long old_flags, + struct utrace *utrace, struct task_struct *target) +{ + unsigned long flags; + struct utrace_attached_engine *engine; + + if (target->exit_state) { + /* + * Update the set of events of interest from the union + * of the interests of the remaining tracing engines. + */ + flags = 0; + list_for_each_entry(engine, &utrace->engines, entry) + flags |= engine->flags | UTRACE_EVENT(REAP); + utrace = check_dead_utrace(target, utrace, flags); + + check_noreap(target, utrace, old_flags, flags); + return; + } + + /* + * Update the set of events of interest from the union + * of the interests of the remaining tracing engines. + */ + flags = 0; + list_for_each_entry(engine, &utrace->engines, entry) + flags |= engine->flags | UTRACE_EVENT(REAP); + utrace = check_dead_utrace(target, utrace, flags); + + if (flags & UTRACE_ACTION_QUIESCE) + return; + + read_lock(&tasklist_lock); + if (!target->exit_state) { + /* + * The target is not dead and should not be in tracing stop + * any more. Wake it unless it's in job control stop. + */ + spin_lock_irq(&target->sighand->siglock); + if (target->signal->flags & SIGNAL_STOP_STOPPED) { + int stop_count = target->signal->group_stop_count; + target->state = TASK_STOPPED; + spin_unlock_irq(&target->sighand->siglock); + + /* + * If tracing was preventing a CLD_STOPPED report + * and is no longer, do that report right now. + */ + if (stop_count == 0 + && 0 + /*&& (events &~ interest) & UTRACE_INHIBIT_CLDSTOP*/ + ) + do_notify_parent_cldstop(target, CLD_STOPPED); + } + else { + /* + * Wake the task up. + */ + recalc_sigpending_tsk(target); + wake_up_state(target, TASK_STOPPED | TASK_TRACED); + spin_unlock_irq(&target->sighand->siglock); + } + } + read_unlock(&tasklist_lock); +} + +void +utrace_detach(struct task_struct *target, + struct utrace_attached_engine *engine) +{ + struct utrace *utrace; + unsigned long flags; + + rcu_read_lock(); + utrace = rcu_dereference(target->utrace); + smp_rmb(); + if (unlikely(target->exit_state == EXIT_DEAD)) { + /* + * Called after utrace_release_task might have started. + * A call to this engine's report_reap callback might + * already be in progress or engine might even have been + * freed already. + */ + rcu_read_unlock(); + return; + } + utrace_lock(utrace); + rcu_read_unlock(); + + flags = engine->flags; + engine->flags = UTRACE_EVENT(QUIESCE) | UTRACE_ACTION_QUIESCE; + rcu_assign_pointer(engine->ops, &dead_engine_ops); + + if (quiesce(target, 1)) { + remove_engine(engine, target, utrace); + wake_quiescent(flags, utrace, target); + } + else + utrace_unlock(utrace); +} +EXPORT_SYMBOL_GPL(utrace_detach); + + +/* + * Called with utrace->lock held. + * Notify and clean up all engines, then free utrace. + */ +static void +utrace_reap(struct task_struct *target, struct utrace *utrace) +{ + struct utrace_attached_engine *engine, *next; + const struct utrace_engine_ops *ops; + +restart: + list_for_each_entry_safe(engine, next, &utrace->engines, entry) { + list_del_rcu(&engine->entry); + + /* + * Now nothing else refers to this engine. + */ + if (engine->flags & UTRACE_EVENT(REAP)) { + ops = rcu_dereference(engine->ops); + if (ops != &dead_engine_ops) { + utrace_unlock(utrace); + (*ops->report_reap)(engine, target); + call_rcu(&engine->rhead, utrace_engine_free); + utrace_lock(utrace); + goto restart; + } + } + call_rcu(&engine->rhead, utrace_engine_free); + } + utrace_unlock(utrace); + + rcu_utrace_free(utrace); +} + +/* + * Called by release_task. After this, target->utrace must be cleared. + */ +void +utrace_release_task(struct task_struct *target) +{ + struct utrace *utrace; + + task_lock(target); + utrace = target->utrace; + rcu_assign_pointer(target->utrace, NULL); + task_unlock(target); + + if (unlikely(utrace == NULL)) + return; + + utrace_lock(utrace); + + if (!utrace->u.exit.notified + && (target->utrace_flags & (UTRACE_EVENT(DEATH) + | UTRACE_EVENT(QUIESCE)))) { + /* + * The target will do some final callbacks but hasn't + * finished them yet. We know because it clears these + * event bits after it's done. Instead of cleaning up here + * and requiring utrace_report_death to cope with it, we + * delay the REAP report and the teardown until after the + * target finishes its death reports. + */ + utrace->u.exit.reap = 1; + utrace_unlock(utrace); + } + else + utrace_reap(target, utrace); /* Unlocks and frees. */ +} + + +void +utrace_set_flags(struct task_struct *target, + struct utrace_attached_engine *engine, + unsigned long flags) +{ + struct utrace *utrace; + int report = 0; + unsigned long old_flags, old_utrace_flags; + +#ifdef ARCH_HAS_SINGLE_STEP + if (! ARCH_HAS_SINGLE_STEP) +#endif + WARN_ON(flags & UTRACE_ACTION_SINGLESTEP); +#ifdef ARCH_HAS_BLOCK_STEP + if (! ARCH_HAS_BLOCK_STEP) +#endif + WARN_ON(flags & UTRACE_ACTION_BLOCKSTEP); + + rcu_read_lock(); + utrace = rcu_dereference(target->utrace); + smp_rmb(); + if (unlikely(target->exit_state == EXIT_DEAD)) { + /* + * Race with reaping. + */ + rcu_read_unlock(); + return; + } + + utrace_lock(utrace); + rcu_read_unlock(); + + old_utrace_flags = target->utrace_flags; + old_flags = engine->flags; + engine->flags = flags; + target->utrace_flags |= flags; + + if ((old_flags ^ flags) & UTRACE_ACTION_QUIESCE) { + if (flags & UTRACE_ACTION_QUIESCE) { + report = (quiesce(target, 1) + && (flags & UTRACE_EVENT(QUIESCE))); + utrace_unlock(utrace); + } + else + wake_quiescent(old_flags, utrace, target); + } + else { + /* + * If we're asking for single-stepping or syscall tracing, + * we need to pass through utrace_quiescent before resuming + * in user mode to get those effects, even if the target is + * not going to be quiescent right now. + */ + if (!(target->utrace_flags & UTRACE_ACTION_QUIESCE) + && ((flags &~ old_utrace_flags) + & (UTRACE_ACTION_SINGLESTEP | UTRACE_ACTION_BLOCKSTEP + | UTRACE_EVENT_SYSCALL))) + quiesce(target, 0); + utrace_unlock(utrace); + } + + if (report) /* Already quiescent, won't report itself. */ + (*engine->ops->report_quiesce)(engine, target); +} +EXPORT_SYMBOL_GPL(utrace_set_flags); + +/* + * While running an engine callback, no locks are held. + * If a callback updates its engine's action state, then + * we need to take the utrace lock to install the flags update. + */ +static inline u32 +update_action(struct task_struct *tsk, struct utrace *utrace, + struct utrace_attached_engine *engine, + u32 ret) +{ + if (ret & UTRACE_ACTION_DETACH) + rcu_assign_pointer(engine->ops, &dead_engine_ops); + else if ((ret & UTRACE_ACTION_NEWSTATE) + && ((ret ^ engine->flags) & UTRACE_ACTION_STATE_MASK)) { +#ifdef ARCH_HAS_SINGLE_STEP + if (! ARCH_HAS_SINGLE_STEP) +#endif + WARN_ON(ret & UTRACE_ACTION_SINGLESTEP); +#ifdef ARCH_HAS_BLOCK_STEP + if (! ARCH_HAS_BLOCK_STEP) +#endif + WARN_ON(ret & UTRACE_ACTION_BLOCKSTEP); + utrace_lock(utrace); + /* + * If we're changing something other than just QUIESCE, + * make sure we pass through utrace_quiescent before + * resuming even if we aren't going to stay quiescent. + * That's where we get the correct union of all engines' + * flags after they've finished changing, and apply changes. + */ + if (((ret ^ engine->flags) & (UTRACE_ACTION_STATE_MASK + & ~UTRACE_ACTION_QUIESCE))) + tsk->utrace_flags |= UTRACE_ACTION_QUIESCE; + engine->flags &= ~UTRACE_ACTION_STATE_MASK; + engine->flags |= ret & UTRACE_ACTION_STATE_MASK; + tsk->utrace_flags |= engine->flags; + utrace_unlock(utrace); + } + else + ret |= engine->flags & UTRACE_ACTION_STATE_MASK; + return ret; +} + +#define REPORT(callback, ...) do { \ + u32 ret = (*rcu_dereference(engine->ops)->callback) \ + (engine, tsk, ##__VA_ARGS__); \ + action = update_action(tsk, utrace, engine, ret); \ + } while (0) + + +/* + * Called with utrace->lock held, returns with it released. + */ +static u32 +remove_detached(struct task_struct *tsk, struct utrace *utrace, + struct utrace **utracep, u32 action) +{ + struct utrace_attached_engine *engine, *next; + unsigned long flags; + + flags = 0; + list_for_each_entry_safe(engine, next, &utrace->engines, entry) { + if (engine->ops == &dead_engine_ops) + remove_engine(engine, tsk, utrace); + else + flags |= engine->flags | UTRACE_EVENT(REAP); + } + utrace = check_dead_utrace(tsk, utrace, flags); + if (utracep) + *utracep = utrace; + + flags &= UTRACE_ACTION_STATE_MASK; + return flags | (action & UTRACE_ACTION_OP_MASK); +} + +/* + * Called after an event report loop. Remove any engines marked for detach. + */ +static inline u32 +check_detach(struct task_struct *tsk, u32 action) +{ + if (action & UTRACE_ACTION_DETACH) { + utrace_lock(tsk->utrace); + action = remove_detached(tsk, tsk->utrace, NULL, action); + } + return action; +} + +static inline void +check_quiescent(struct task_struct *tsk, u32 action) +{ + if (action & UTRACE_ACTION_STATE_MASK) + utrace_quiescent(tsk); +} + +/* + * Called iff UTRACE_EVENT(CLONE) flag is set. + * This notification call blocks the wake_up_new_task call on the child. + * So we must not quiesce here. tracehook_report_clone_complete will do + * a quiescence check momentarily. + */ +void +utrace_report_clone(unsigned long clone_flags, struct task_struct *child) +{ + struct task_struct *tsk = current; + struct utrace *utrace = tsk->utrace; + struct list_head *pos, *next; + struct utrace_attached_engine *engine; + unsigned long action; + + utrace->u.live.cloning = child; + + /* XXX must change for sharing */ + action = UTRACE_ACTION_RESUME; + list_for_each_safe_rcu(pos, next, &utrace->engines) { + engine = list_entry(pos, struct utrace_attached_engine, entry); + if (engine->flags & UTRACE_EVENT(CLONE)) + REPORT(report_clone, clone_flags, child); + if (action & UTRACE_ACTION_HIDE) + break; + } + + utrace->u.live.cloning = NULL; + + check_detach(tsk, action); +} + +static unsigned long +report_quiescent(struct task_struct *tsk, struct utrace *utrace, u32 action) +{ + struct list_head *pos, *next; + struct utrace_attached_engine *engine; + + list_for_each_safe_rcu(pos, next, &utrace->engines) { + engine = list_entry(pos, struct utrace_attached_engine, entry); + if (engine->flags & UTRACE_EVENT(QUIESCE)) + REPORT(report_quiesce); + action |= engine->flags & UTRACE_ACTION_STATE_MASK; + } + + return check_detach(tsk, action); +} + +/* + * Called iff UTRACE_EVENT(JCTL) flag is set. + */ +int +utrace_report_jctl(int what) +{ + struct task_struct *tsk = current; + struct utrace *utrace = tsk->utrace; + struct list_head *pos, *next; + struct utrace_attached_engine *engine; + unsigned long action; + + /* XXX must change for sharing */ + action = UTRACE_ACTION_RESUME; + list_for_each_safe_rcu(pos, next, &utrace->engines) { + engine = list_entry(pos, struct utrace_attached_engine, entry); + if (engine->flags & UTRACE_EVENT(JCTL)) + REPORT(report_jctl, what); + if (action & UTRACE_ACTION_HIDE) + break; + } + + /* + * We are becoming quiescent, so report it now. + * We don't block in utrace_quiescent because we are stopping anyway. + * We know that upon resuming we'll go through tracehook_induce_signal, + * which will keep us quiescent or set us up to resume with tracing. + */ + action = report_quiescent(tsk, utrace, action); + + if (what == CLD_STOPPED && tsk->state != TASK_STOPPED) { + /* + * The event report hooks could have blocked, though + * it should have been briefly. Make sure we're in + * TASK_STOPPED state again to block properly, unless + * we've just come back out of job control stop. + */ + spin_lock_irq(&tsk->sighand->siglock); + if (tsk->signal->flags & SIGNAL_STOP_STOPPED) + set_current_state(TASK_STOPPED); + spin_unlock_irq(&tsk->sighand->siglock); + } + + return action & UTRACE_JCTL_NOSIGCHLD; +} + + +/* + * Called if UTRACE_EVENT(QUIESCE) or UTRACE_ACTION_QUIESCE flag is set. + * Also called after other event reports. + * It is a good time to block. + */ +void +utrace_quiescent(struct task_struct *tsk) +{ + struct utrace *utrace = tsk->utrace; + unsigned long action; + +restart: + /* XXX must change for sharing */ + + action = report_quiescent(tsk, utrace, UTRACE_ACTION_RESUME); + + /* + * If some engines want us quiescent, we block here. + */ + if (action & UTRACE_ACTION_QUIESCE) { + spin_lock_irq(&tsk->sighand->siglock); + /* + * If wake_quiescent is trying to wake us up now, it will + * have cleared the QUIESCE flag before trying to take the + * siglock. Now we have the siglock, so either it has + * already cleared the flag, or it will wake us up after we + * release the siglock it's waiting for. + * Never stop when there is a SIGKILL bringing us down. + */ + if ((tsk->utrace_flags & UTRACE_ACTION_QUIESCE) + /*&& !(tsk->signal->flags & SIGNAL_GROUP_SIGKILL)*/) { + set_current_state(TASK_TRACED); + /* + * If there is a group stop in progress, + * we must participate in the bookkeeping. + */ + if (tsk->signal->group_stop_count > 0) + --tsk->signal->group_stop_count; + spin_unlock_irq(&tsk->sighand->siglock); + schedule(); + } + else + spin_unlock_irq(&tsk->sighand->siglock); + + /* + * We've woken up. One engine could be waking us up while + * another has asked us to quiesce. So check afresh. We + * could have been detached while quiescent. Now we are no + * longer quiescent, so don't need to do any RCU locking. + * But we do need to check our utrace pointer anew. + */ + utrace = tsk->utrace; + if (tsk->utrace_flags + & (UTRACE_EVENT(QUIESCE) | UTRACE_ACTION_STATE_MASK)) + goto restart; + } + else if (tsk->utrace_flags & UTRACE_ACTION_QUIESCE) { + /* + * Our flags are out of date. + * Update the set of events of interest from the union + * of the interests of the remaining tracing engines. + */ + struct utrace_attached_engine *engine; + unsigned long flags = 0; + utrace = rcu_dereference(tsk->utrace); + utrace_lock(utrace); + list_for_each_entry(engine, &utrace->engines, entry) + flags |= engine->flags | UTRACE_EVENT(REAP); + tsk->utrace_flags = flags; + utrace_unlock(utrace); + } + + /* + * We're resuming. Update the machine layer tracing state and then go. + */ +#ifdef ARCH_HAS_SINGLE_STEP + if (action & UTRACE_ACTION_SINGLESTEP) + tracehook_enable_single_step(tsk); + else + tracehook_disable_single_step(tsk); +#endif +#ifdef ARCH_HAS_BLOCK_STEP + if ((action & (UTRACE_ACTION_BLOCKSTEP|UTRACE_ACTION_SINGLESTEP)) + == UTRACE_ACTION_BLOCKSTEP) + tracehook_enable_block_step(tsk); + else + tracehook_disable_block_step(tsk); +#endif + if (tsk->utrace_flags & UTRACE_EVENT_SYSCALL) + tracehook_enable_syscall_trace(tsk); + else + tracehook_disable_syscall_trace(tsk); +} + + +/* + * Called iff UTRACE_EVENT(EXIT) flag is set. + */ +void +utrace_report_exit(long *exit_code) +{ + struct task_struct *tsk = current; + struct utrace *utrace = tsk->utrace; + struct list_head *pos, *next; + struct utrace_attached_engine *engine; + unsigned long action; + long orig_code = *exit_code; + + /* XXX must change for sharing */ + action = UTRACE_ACTION_RESUME; + list_for_each_safe_rcu(pos, next, &utrace->engines) { + engine = list_entry(pos, struct utrace_attached_engine, entry); + if (engine->flags & UTRACE_EVENT(EXIT)) + REPORT(report_exit, orig_code, exit_code); + } + action = check_detach(tsk, action); + check_quiescent(tsk, action); +} + +/* + * Called iff UTRACE_EVENT(DEATH) flag is set. + * + * It is always possible that we are racing with utrace_release_task here, + * if UTRACE_ACTION_NOREAP is not set, or in the case of non-leader exec + * where the old leader will get released regardless of NOREAP. For this + * reason, utrace_release_task checks for the event bits that get us here, + * and delays its cleanup for us to do. + */ +void +utrace_report_death(struct task_struct *tsk, struct utrace *utrace) +{ + struct list_head *pos, *next; + struct utrace_attached_engine *engine; + u32 action, oaction; + + BUG_ON(!tsk->exit_state); + + oaction = tsk->utrace_flags; + + /* XXX must change for sharing */ + action = UTRACE_ACTION_RESUME; + list_for_each_safe_rcu(pos, next, &utrace->engines) { + engine = list_entry(pos, struct utrace_attached_engine, entry); + if (engine->flags & UTRACE_EVENT(DEATH)) + REPORT(report_death); + if (engine->flags & UTRACE_EVENT(QUIESCE)) + REPORT(report_quiesce); + } + /* + * Unconditionally lock and recompute the flags. + * This may notice that there are no engines left and + * free the utrace struct. + */ + utrace_lock(utrace); + if (utrace->u.exit.reap) { + /* + * utrace_release_task was already called in parallel. + * We must complete its work now. + */ + reap: + utrace_reap(tsk, utrace); + } + else { + action = remove_detached(tsk, utrace, &utrace, action); + + if (utrace != NULL) { + utrace_lock(utrace); + if (utrace->u.exit.reap) + goto reap; + + /* + * Clear event bits we can't see any more. This + * tells utrace_release_task we have already + * finished, if it comes along later. + */ + tsk->utrace_flags &= (UTRACE_EVENT(REAP) + | UTRACE_ACTION_NOREAP); + + utrace_unlock(utrace); + } + + check_noreap(tsk, utrace, oaction, action); + } +} + +/* + * Called iff UTRACE_EVENT(VFORK_DONE) flag is set. + */ +void +utrace_report_vfork_done(pid_t child_pid) +{ + struct task_struct *tsk = current; + struct utrace *utrace = tsk->utrace; + struct list_head *pos, *next; + struct utrace_attached_engine *engine; + unsigned long action; + + /* XXX must change for sharing */ + action = UTRACE_ACTION_RESUME; + list_for_each_safe_rcu(pos, next, &utrace->engines) { + engine = list_entry(pos, struct utrace_attached_engine, entry); + if (engine->flags & UTRACE_EVENT(VFORK_DONE)) + REPORT(report_vfork_done, child_pid); + if (action & UTRACE_ACTION_HIDE) + break; + } + action = check_detach(tsk, action); + check_quiescent(tsk, action); +} + +/* + * Called iff UTRACE_EVENT(EXEC) flag is set. + */ +void +utrace_report_exec(struct linux_binprm *bprm, struct pt_regs *regs) +{ + struct task_struct *tsk = current; + struct utrace *utrace = tsk->utrace; + struct list_head *pos, *next; + struct utrace_attached_engine *engine; + unsigned long action; + + /* XXX must change for sharing */ + action = UTRACE_ACTION_RESUME; + list_for_each_safe_rcu(pos, next, &utrace->engines) { + engine = list_entry(pos, struct utrace_attached_engine, entry); + if (engine->flags & UTRACE_EVENT(EXEC)) + REPORT(report_exec, bprm, regs); + if (action & UTRACE_ACTION_HIDE) + break; + } + action = check_detach(tsk, action); + check_quiescent(tsk, action); +} + +/* + * Called iff UTRACE_EVENT(SYSCALL_{ENTRY,EXIT}) flag is set. + */ +void +utrace_report_syscall(struct pt_regs *regs, int is_exit) +{ + struct task_struct *tsk = current; + struct utrace *utrace = tsk->utrace; + struct list_head *pos, *next; + struct utrace_attached_engine *engine; + unsigned long action, ev; + +/* + XXX pass syscall # to engine hook directly, let it return inhibit-action + to reset to -1 + long syscall = tracehook_syscall_number(regs, is_exit); +*/ + + ev = is_exit ? UTRACE_EVENT(SYSCALL_EXIT) : UTRACE_EVENT(SYSCALL_ENTRY); + + /* XXX must change for sharing */ + action = UTRACE_ACTION_RESUME; + list_for_each_safe_rcu(pos, next, &utrace->engines) { + engine = list_entry(pos, struct utrace_attached_engine, entry); + if (engine->flags & ev) { + if (is_exit) + REPORT(report_syscall_exit, regs); + else + REPORT(report_syscall_entry, regs); + } + if (action & UTRACE_ACTION_HIDE) + break; + } + action = check_detach(tsk, action); + check_quiescent(tsk, action); +} + +// XXX copied from signal.c +#ifdef SIGEMT +#define M_SIGEMT M(SIGEMT) +#else +#define M_SIGEMT 0 +#endif + +#if SIGRTMIN > BITS_PER_LONG +#define M(sig) (1ULL << ((sig)-1)) +#else +#define M(sig) (1UL << ((sig)-1)) +#endif +#define T(sig, mask) (M(sig) & (mask)) + +#define SIG_KERNEL_ONLY_MASK (\ + M(SIGKILL) | M(SIGSTOP) ) + +#define SIG_KERNEL_STOP_MASK (\ + M(SIGSTOP) | M(SIGTSTP) | M(SIGTTIN) | M(SIGTTOU) ) + +#define SIG_KERNEL_COREDUMP_MASK (\ + M(SIGQUIT) | M(SIGILL) | M(SIGTRAP) | M(SIGABRT) | \ + M(SIGFPE) | M(SIGSEGV) | M(SIGBUS) | M(SIGSYS) | \ + M(SIGXCPU) | M(SIGXFSZ) | M_SIGEMT ) + +#define SIG_KERNEL_IGNORE_MASK (\ + M(SIGCONT) | M(SIGCHLD) | M(SIGWINCH) | M(SIGURG) ) + +#define sig_kernel_only(sig) \ + (((sig) < SIGRTMIN) && T(sig, SIG_KERNEL_ONLY_MASK)) +#define sig_kernel_coredump(sig) \ + (((sig) < SIGRTMIN) && T(sig, SIG_KERNEL_COREDUMP_MASK)) +#define sig_kernel_ignore(sig) \ + (((sig) < SIGRTMIN) && T(sig, SIG_KERNEL_IGNORE_MASK)) +#define sig_kernel_stop(sig) \ + (((sig) < SIGRTMIN) && T(sig, SIG_KERNEL_STOP_MASK)) + + +/* + * Call each interested tracing engine's report_signal callback. + */ +static u32 +report_signal(struct task_struct *tsk, struct pt_regs *regs, + struct utrace *utrace, u32 action, + unsigned long flags1, unsigned long flags2, siginfo_t *info, + const struct k_sigaction *ka, struct k_sigaction *return_ka) +{ + struct list_head *pos, *next; + struct utrace_attached_engine *engine; + + /* XXX must change for sharing */ + list_for_each_safe_rcu(pos, next, &utrace->engines) { + engine = list_entry(pos, struct utrace_attached_engine, entry); + if ((engine->flags & flags1) && (engine->flags & flags2)) { + u32 disp = action & UTRACE_ACTION_OP_MASK; + action &= ~UTRACE_ACTION_OP_MASK; + REPORT(report_signal, regs, disp, info, ka, return_ka); + if ((action & UTRACE_ACTION_OP_MASK) == 0) + action |= disp; + if (action & UTRACE_ACTION_HIDE) + break; + } + } + + return action; +} + +void +utrace_signal_handler_singlestep(struct task_struct *tsk, struct pt_regs *regs) +{ + u32 action; + action = report_signal(tsk, regs, tsk->utrace, UTRACE_SIGNAL_HANDLER, + UTRACE_EVENT_SIGNAL_ALL, + UTRACE_ACTION_SINGLESTEP|UTRACE_ACTION_BLOCKSTEP, + NULL, NULL, NULL); + action = check_detach(tsk, action); + check_quiescent(tsk, action); +} + + +/* + * This is the hook from the signals code, called with the siglock held. + * Here is the ideal place to quiesce. We also dequeue and intercept signals. + */ +int +utrace_get_signal(struct task_struct *tsk, struct pt_regs *regs, + siginfo_t *info, struct k_sigaction *return_ka) +{ + struct utrace *utrace = tsk->utrace; + struct utrace_signal signal = { info, return_ka, 0 }; + struct k_sigaction *ka; + unsigned long action, event; + +#if 0 /* XXX */ + if (tsk->signal->flags & SIGNAL_GROUP_SIGKILL) + return 0; +#endif + + /* + * If we should quiesce, now is the time. + * First stash a pointer to the state on our stack, + * so that utrace_inject_signal can tell us what to do. + */ + if (utrace->u.live.signal == NULL) + utrace->u.live.signal = &signal; + + if (tsk->utrace_flags & UTRACE_ACTION_QUIESCE) { + spin_unlock_irq(&tsk->sighand->siglock); + utrace_quiescent(tsk); + if (signal.signr == 0) + /* + * This return value says to reacquire the siglock + * and check again. This will check for a pending + * group stop and process it before coming back here. + */ + return -1; + spin_lock_irq(&tsk->sighand->siglock); + } + + /* + * If a signal was injected previously, it could not use our + * stack space directly. It had to allocate a data structure, + * which we can now copy out of and free. + */ + if (utrace->u.live.signal != &signal) { + signal.signr = utrace->u.live.signal->signr; + copy_siginfo(info, utrace->u.live.signal->info); + if (utrace->u.live.signal->return_ka) + *return_ka = *utrace->u.live.signal->return_ka; + else + signal.return_ka = NULL; + kfree(utrace->u.live.signal); + } + utrace->u.live.signal = NULL; + + /* + * If a signal was injected, everything is in place now. Go do it. + */ + if (signal.signr != 0) { + if (signal.return_ka == NULL) { + ka = &tsk->sighand->action[signal.signr - 1]; + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + *return_ka = *ka; + } + else + BUG_ON(signal.return_ka != return_ka); + return signal.signr; + } + + /* + * If noone is interested in intercepting signals, let the caller + * just dequeue them normally. + */ + if ((tsk->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) == 0) + return 0; + + /* + * Steal the next signal so we can let tracing engines examine it. + * From the signal number and sigaction, determine what normal + * delivery would do. If no engine perturbs it, we'll do that + * by returning the signal number after setting *return_ka. + */ + signal.signr = dequeue_signal(tsk, &tsk->blocked, info); + if (signal.signr == 0) + return 0; + + BUG_ON(signal.signr != info->si_signo); + + ka = &tsk->sighand->action[signal.signr - 1]; + *return_ka = *ka; + + if (signal.signr == SIGKILL) + return signal.signr; + + if (ka->sa.sa_handler == SIG_IGN) { + event = UTRACE_EVENT(SIGNAL_IGN); + action = UTRACE_SIGNAL_IGN; + } + else if (ka->sa.sa_handler != SIG_DFL) { + event = UTRACE_EVENT(SIGNAL); + action = UTRACE_ACTION_RESUME; + } + else if (sig_kernel_coredump(signal.signr)) { + event = UTRACE_EVENT(SIGNAL_CORE); + action = UTRACE_SIGNAL_CORE; + } + else if (sig_kernel_ignore(signal.signr)) { + event = UTRACE_EVENT(SIGNAL_IGN); + action = UTRACE_SIGNAL_IGN; + } + else if (sig_kernel_stop(signal.signr)) { + event = UTRACE_EVENT(SIGNAL_STOP); + action = (signal.signr == SIGSTOP + ? UTRACE_SIGNAL_STOP : UTRACE_SIGNAL_TSTP); + } + else { + event = UTRACE_EVENT(SIGNAL_TERM); + action = UTRACE_SIGNAL_TERM; + } + + if (tsk->utrace_flags & event) { + /* + * We have some interested engines, so tell them about the + * signal and let them change its disposition. + */ + + spin_unlock_irq(&tsk->sighand->siglock); + + action = report_signal(tsk, regs, utrace, action, event, event, + info, ka, return_ka); + action &= UTRACE_ACTION_OP_MASK; + + if (action & UTRACE_SIGNAL_HOLD) { + struct sigqueue *q = sigqueue_alloc(); + if (likely(q != NULL)) { + q->flags = 0; + copy_siginfo(&q->info, info); + } + action &= ~UTRACE_SIGNAL_HOLD; + spin_lock_irq(&tsk->sighand->siglock); + sigaddset(&tsk->pending.signal, info->si_signo); + if (likely(q != NULL)) + list_add(&q->list, &tsk->pending.list); + } + else + spin_lock_irq(&tsk->sighand->siglock); + + recalc_sigpending_tsk(tsk); + } + + if (tsk->utrace != utrace) + rcu_utrace_free(utrace); + + /* + * We express the chosen action to the signals code in terms + * of a representative signal whose default action does it. + */ + switch (action) { + case UTRACE_SIGNAL_IGN: + /* + * We've eaten the signal. That's all we do. + * Tell the caller to restart. + */ + spin_unlock_irq(&tsk->sighand->siglock); + return -1; + + case UTRACE_ACTION_RESUME: + case UTRACE_SIGNAL_DELIVER: + /* + * The handler will run. We do the SA_ONESHOT work here + * since the normal path will only touch *return_ka now. + */ + if (return_ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + break; + + case UTRACE_SIGNAL_TSTP: + signal.signr = SIGTSTP; + tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; + return_ka->sa.sa_handler = SIG_DFL; + break; + + case UTRACE_SIGNAL_STOP: + signal.signr = SIGSTOP; + tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; + return_ka->sa.sa_handler = SIG_DFL; + break; + + case UTRACE_SIGNAL_TERM: + signal.signr = SIGTERM; + return_ka->sa.sa_handler = SIG_DFL; + break; + + case UTRACE_SIGNAL_CORE: + signal.signr = SIGQUIT; + return_ka->sa.sa_handler = SIG_DFL; + break; + + default: + BUG(); + } + + return signal.signr; +} + + +/* + * Cause a specified signal delivery in the target thread, + * which must be quiescent. The action has UTRACE_SIGNAL_* bits + * as returned from a report_signal callback. If ka is non-null, + * it gives the sigaction to follow for UTRACE_SIGNAL_DELIVER; + * otherwise, the installed sigaction at the time of delivery is used. + */ +int +utrace_inject_signal(struct task_struct *target, + struct utrace_attached_engine *engine, + u32 action, siginfo_t *info, + const struct k_sigaction *ka) +{ + struct utrace *utrace; + struct utrace_signal *signal; + int ret; + + if (info->si_signo == 0 || !valid_signal(info->si_signo)) + return -EINVAL; + + rcu_read_lock(); + utrace = rcu_dereference(target->utrace); + if (utrace == NULL) { + rcu_read_unlock(); + return -ESRCH; + } + utrace_lock(utrace); + rcu_read_unlock(); + + ret = 0; + signal = utrace->u.live.signal; + if (signal == NULL) { + ret = -ENOSYS; /* XXX */ + } + else if (signal->signr != 0) + ret = -EAGAIN; + else { + if (info != signal->info) + copy_siginfo(signal->info, info); + + switch (action) { + default: + ret = -EINVAL; + break; + + case UTRACE_SIGNAL_IGN: + break; + + case UTRACE_ACTION_RESUME: + case UTRACE_SIGNAL_DELIVER: + /* + * The handler will run. We do the SA_ONESHOT work + * here since the normal path will not touch the + * real sigaction when using an injected signal. + */ + if (ka == NULL) + signal->return_ka = NULL; + else if (ka != signal->return_ka) + *signal->return_ka = *ka; + if (ka && ka->sa.sa_flags & SA_ONESHOT) { + struct k_sigaction *a; + a = &target->sighand->action[info->si_signo-1]; + spin_lock_irq(&target->sighand->siglock); + a->sa.sa_handler = SIG_DFL; + spin_unlock_irq(&target->sighand->siglock); + } + signal->signr = info->si_signo; + break; + + case UTRACE_SIGNAL_TSTP: + signal->signr = SIGTSTP; + spin_lock_irq(&target->sighand->siglock); + target->signal->flags |= SIGNAL_STOP_DEQUEUED; + spin_unlock_irq(&target->sighand->siglock); + signal->return_ka->sa.sa_handler = SIG_DFL; + break; + + case UTRACE_SIGNAL_STOP: + signal->signr = SIGSTOP; + spin_lock_irq(&target->sighand->siglock); + target->signal->flags |= SIGNAL_STOP_DEQUEUED; + spin_unlock_irq(&target->sighand->siglock); + signal->return_ka->sa.sa_handler = SIG_DFL; + break; + + case UTRACE_SIGNAL_TERM: + signal->signr = SIGTERM; + signal->return_ka->sa.sa_handler = SIG_DFL; + break; + + case UTRACE_SIGNAL_CORE: + signal->signr = SIGQUIT; + signal->return_ka->sa.sa_handler = SIG_DFL; + break; + } + } + + utrace_unlock(utrace); + + return ret; +} +EXPORT_SYMBOL_GPL(utrace_inject_signal); + + +const struct utrace_regset * +utrace_regset(struct task_struct *target, + struct utrace_attached_engine *engine, + const struct utrace_regset_view *view, int which) +{ + if (unlikely((unsigned) which >= view->n)) + return NULL; + + if (target != current) + wait_task_inactive(target); + + return &view->regsets[which]; +} +EXPORT_SYMBOL_GPL(utrace_regset); + + +/* + * Return the task_struct for the task using ptrace on this one, or NULL. + * Must be called with rcu_read_lock held to keep the returned struct alive. + * + * At exec time, this may be called with task_lock(p) still held from when + * tracehook_unsafe_exec was just called. In that case it must give + * results consistent with those unsafe_exec results, i.e. non-NULL if + * any LSM_UNSAFE_PTRACE_* bits were set. + * + * The value is also used to display after "TracerPid:" in /proc/PID/status, + * where it is called with only rcu_read_lock held. + */ +struct task_struct * +utrace_tracer_task(struct task_struct *target) +{ + struct utrace *utrace; + struct task_struct *tracer = NULL; + + utrace = rcu_dereference(target->utrace); + if (utrace != NULL) { + struct list_head *pos, *next; + struct utrace_attached_engine *engine; + const struct utrace_engine_ops *ops; + list_for_each_safe_rcu(pos, next, &utrace->engines) { + engine = list_entry(pos, struct utrace_attached_engine, + entry); + ops = rcu_dereference(engine->ops); + if (ops->tracer_task) { + tracer = (*ops->tracer_task)(engine, target); + if (tracer != NULL) + break; + } + } + } + + return tracer; +} + +int +utrace_allow_access_process_vm(struct task_struct *target) +{ + struct utrace *utrace; + int ret = 0; + + rcu_read_lock(); + utrace = rcu_dereference(target->utrace); + if (utrace != NULL) { + struct list_head *pos, *next; + struct utrace_attached_engine *engine; + const struct utrace_engine_ops *ops; + list_for_each_safe_rcu(pos, next, &utrace->engines) { + engine = list_entry(pos, struct utrace_attached_engine, + entry); + ops = rcu_dereference(engine->ops); + if (ops->allow_access_process_vm) { + ret = (*ops->allow_access_process_vm)(engine, + target, + current); + if (ret) + break; + } + } + } + rcu_read_unlock(); + + return ret; +} + +/* + * Called on the current task to return LSM_UNSAFE_* bits implied by tracing. + * Called with task_lock held. + */ +int +utrace_unsafe_exec(struct task_struct *tsk) +{ + struct utrace *utrace = tsk->utrace; + struct list_head *pos, *next; + struct utrace_attached_engine *engine; + const struct utrace_engine_ops *ops; + int unsafe = 0; + + /* XXX must change for sharing */ + list_for_each_safe_rcu(pos, next, &utrace->engines) { + engine = list_entry(pos, struct utrace_attached_engine, entry); + ops = rcu_dereference(engine->ops); + if (ops->unsafe_exec) + unsafe |= (*ops->unsafe_exec)(engine, tsk); + } + + return unsafe; +} diff --git a/lib/audit.c b/lib/audit.c new file mode 100644 index 000000000..3b1289fad --- /dev/null +++ b/lib/audit.c @@ -0,0 +1,55 @@ +#include <linux/init.h> +#include <linux/types.h> +#include <linux/audit.h> +#include <asm/unistd.h> + +static unsigned dir_class[] = { +#include <asm-generic/audit_dir_write.h> +~0U +}; + +static unsigned read_class[] = { +#include <asm-generic/audit_read.h> +~0U +}; + +static unsigned write_class[] = { +#include <asm-generic/audit_write.h> +~0U +}; + +static unsigned chattr_class[] = { +#include <asm-generic/audit_change_attr.h> +~0U +}; + +int audit_classify_syscall(int abi, unsigned syscall) +{ + switch(syscall) { + case __NR_open: + return 2; +#ifdef __NR_openat + case __NR_openat: + return 3; +#endif +#ifdef __NR_socketcall + case __NR_socketcall: + return 4; +#endif + case __NR_execve: + return 5; + default: + return 0; + } +} + +static int __init audit_classes_init(void) +{ + audit_register_class(AUDIT_CLASS_WRITE, write_class); + audit_register_class(AUDIT_CLASS_READ, read_class); + audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); + audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); + return 0; +} + +__initcall(audit_classes_init); diff --git a/lib/debug_locks.c b/lib/debug_locks.c new file mode 100644 index 000000000..0ef01d147 --- /dev/null +++ b/lib/debug_locks.c @@ -0,0 +1,45 @@ +/* + * lib/debug_locks.c + * + * Generic place for common debugging facilities for various locks: + * spinlocks, rwlocks, mutexes and rwsems. + * + * Started by Ingo Molnar: + * + * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + */ +#include <linux/rwsem.h> +#include <linux/mutex.h> +#include <linux/module.h> +#include <linux/spinlock.h> +#include <linux/debug_locks.h> + +/* + * We want to turn all lock-debugging facilities on/off at once, + * via a global flag. The reason is that once a single bug has been + * detected and reported, there might be cascade of followup bugs + * that would just muddy the log. So we report the first one and + * shut up after that. + */ +int debug_locks = 1; + +/* + * The locking-testsuite uses <debug_locks_silent> to get a + * 'silent failure': nothing is printed to the console when + * a locking bug is detected. + */ +int debug_locks_silent; + +/* + * Generic 'turn off all lock debugging' function: + */ +int debug_locks_off(void) +{ + if (xchg(&debug_locks, 0)) { + if (!debug_locks_silent) { + console_verbose(); + return 1; + } + } + return 0; +} diff --git a/lib/list_debug.c b/lib/list_debug.c new file mode 100644 index 000000000..1aae85cef --- /dev/null +++ b/lib/list_debug.c @@ -0,0 +1,77 @@ +/* + * Copyright 2006, Red Hat, Inc., Dave Jones + * Released under the General Public License (GPL). + * + * This file contains the linked list implementations for + * DEBUG_LIST. + */ + +#include <linux/module.h> +#include <linux/list.h> + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ + +void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + if (unlikely(next->prev != prev)) { + printk(KERN_ERR "list_add corruption. next->prev should be %p, but was %p\n", + prev, next->prev); + BUG(); + } + if (unlikely(prev->next != next)) { + printk(KERN_ERR "list_add corruption. prev->next should be %p, but was %p\n", + next, prev->next); + BUG(); + } + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} +EXPORT_SYMBOL(__list_add); + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} +EXPORT_SYMBOL(list_add); + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is + * in an undefined state. + */ +void list_del(struct list_head *entry) +{ + if (unlikely(entry->prev->next != entry)) { + printk(KERN_ERR "list_del corruption. prev->next should be %p, but was %p\n", + entry, entry->prev->next); + BUG(); + } + if (unlikely(entry->next->prev != entry)) { + printk(KERN_ERR "list_del corruption. next->prev should be %p, but was %p\n", + entry, entry->next->prev); + BUG(); + } + __list_del(entry->prev, entry->next); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} +EXPORT_SYMBOL(list_del); + diff --git a/lib/locking-selftest-hardirq.h b/lib/locking-selftest-hardirq.h new file mode 100644 index 000000000..10d4a150b --- /dev/null +++ b/lib/locking-selftest-hardirq.h @@ -0,0 +1,9 @@ +#undef IRQ_DISABLE +#undef IRQ_ENABLE +#undef IRQ_ENTER +#undef IRQ_EXIT + +#define IRQ_ENABLE HARDIRQ_ENABLE +#define IRQ_DISABLE HARDIRQ_DISABLE +#define IRQ_ENTER HARDIRQ_ENTER +#define IRQ_EXIT HARDIRQ_EXIT diff --git a/lib/locking-selftest-mutex.h b/lib/locking-selftest-mutex.h new file mode 100644 index 000000000..68601b6f5 --- /dev/null +++ b/lib/locking-selftest-mutex.h @@ -0,0 +1,11 @@ +#undef LOCK +#define LOCK ML + +#undef UNLOCK +#define UNLOCK MU + +#undef RLOCK +#undef WLOCK + +#undef INIT +#define INIT MI diff --git a/lib/locking-selftest-rlock-hardirq.h b/lib/locking-selftest-rlock-hardirq.h new file mode 100644 index 000000000..9f517ebcb --- /dev/null +++ b/lib/locking-selftest-rlock-hardirq.h @@ -0,0 +1,2 @@ +#include "locking-selftest-rlock.h" +#include "locking-selftest-hardirq.h" diff --git a/lib/locking-selftest-rlock-softirq.h b/lib/locking-selftest-rlock-softirq.h new file mode 100644 index 000000000..981455db7 --- /dev/null +++ b/lib/locking-selftest-rlock-softirq.h @@ -0,0 +1,2 @@ +#include "locking-selftest-rlock.h" +#include "locking-selftest-softirq.h" diff --git a/lib/locking-selftest-rlock.h b/lib/locking-selftest-rlock.h new file mode 100644 index 000000000..6789044f4 --- /dev/null +++ b/lib/locking-selftest-rlock.h @@ -0,0 +1,14 @@ +#undef LOCK +#define LOCK RL + +#undef UNLOCK +#define UNLOCK RU + +#undef RLOCK +#define RLOCK RL + +#undef WLOCK +#define WLOCK WL + +#undef INIT +#define INIT RWI diff --git a/lib/locking-selftest-rsem.h b/lib/locking-selftest-rsem.h new file mode 100644 index 000000000..62da88668 --- /dev/null +++ b/lib/locking-selftest-rsem.h @@ -0,0 +1,14 @@ +#undef LOCK +#define LOCK RSL + +#undef UNLOCK +#define UNLOCK RSU + +#undef RLOCK +#define RLOCK RSL + +#undef WLOCK +#define WLOCK WSL + +#undef INIT +#define INIT RWSI diff --git a/lib/locking-selftest-softirq.h b/lib/locking-selftest-softirq.h new file mode 100644 index 000000000..a83de2a04 --- /dev/null +++ b/lib/locking-selftest-softirq.h @@ -0,0 +1,9 @@ +#undef IRQ_DISABLE +#undef IRQ_ENABLE +#undef IRQ_ENTER +#undef IRQ_EXIT + +#define IRQ_DISABLE SOFTIRQ_DISABLE +#define IRQ_ENABLE SOFTIRQ_ENABLE +#define IRQ_ENTER SOFTIRQ_ENTER +#define IRQ_EXIT SOFTIRQ_EXIT diff --git a/lib/locking-selftest-spin-hardirq.h b/lib/locking-selftest-spin-hardirq.h new file mode 100644 index 000000000..693198dce --- /dev/null +++ b/lib/locking-selftest-spin-hardirq.h @@ -0,0 +1,2 @@ +#include "locking-selftest-spin.h" +#include "locking-selftest-hardirq.h" diff --git a/lib/locking-selftest-spin-softirq.h b/lib/locking-selftest-spin-softirq.h new file mode 100644 index 000000000..c472e2a87 --- /dev/null +++ b/lib/locking-selftest-spin-softirq.h @@ -0,0 +1,2 @@ +#include "locking-selftest-spin.h" +#include "locking-selftest-softirq.h" diff --git a/lib/locking-selftest-spin.h b/lib/locking-selftest-spin.h new file mode 100644 index 000000000..ccd1b4b09 --- /dev/null +++ b/lib/locking-selftest-spin.h @@ -0,0 +1,11 @@ +#undef LOCK +#define LOCK L + +#undef UNLOCK +#define UNLOCK U + +#undef RLOCK +#undef WLOCK + +#undef INIT +#define INIT SI diff --git a/lib/locking-selftest-wlock-hardirq.h b/lib/locking-selftest-wlock-hardirq.h new file mode 100644 index 000000000..2dd2e5122 --- /dev/null +++ b/lib/locking-selftest-wlock-hardirq.h @@ -0,0 +1,2 @@ +#include "locking-selftest-wlock.h" +#include "locking-selftest-hardirq.h" diff --git a/lib/locking-selftest-wlock-softirq.h b/lib/locking-selftest-wlock-softirq.h new file mode 100644 index 000000000..cb80d1cb9 --- /dev/null +++ b/lib/locking-selftest-wlock-softirq.h @@ -0,0 +1,2 @@ +#include "locking-selftest-wlock.h" +#include "locking-selftest-softirq.h" diff --git a/lib/locking-selftest-wlock.h b/lib/locking-selftest-wlock.h new file mode 100644 index 000000000..0815322d9 --- /dev/null +++ b/lib/locking-selftest-wlock.h @@ -0,0 +1,14 @@ +#undef LOCK +#define LOCK WL + +#undef UNLOCK +#define UNLOCK WU + +#undef RLOCK +#define RLOCK RL + +#undef WLOCK +#define WLOCK WL + +#undef INIT +#define INIT RWI diff --git a/lib/locking-selftest-wsem.h b/lib/locking-selftest-wsem.h new file mode 100644 index 000000000..b88c5f2dc --- /dev/null +++ b/lib/locking-selftest-wsem.h @@ -0,0 +1,14 @@ +#undef LOCK +#define LOCK WSL + +#undef UNLOCK +#define UNLOCK WSU + +#undef RLOCK +#define RLOCK RSL + +#undef WLOCK +#define WLOCK WSL + +#undef INIT +#define INIT RWSI diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c new file mode 100644 index 000000000..7945787f4 --- /dev/null +++ b/lib/locking-selftest.c @@ -0,0 +1,1216 @@ +/* + * lib/locking-selftest.c + * + * Testsuite for various locking APIs: spinlocks, rwlocks, + * mutexes and rw-semaphores. + * + * It is checking both false positives and false negatives. + * + * Started by Ingo Molnar: + * + * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com> + */ +#include <linux/rwsem.h> +#include <linux/mutex.h> +#include <linux/sched.h> +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/lockdep.h> +#include <linux/spinlock.h> +#include <linux/kallsyms.h> +#include <linux/interrupt.h> +#include <linux/debug_locks.h> +#include <linux/irqflags.h> + +/* + * Change this to 1 if you want to see the failure printouts: + */ +static unsigned int debug_locks_verbose; + +static int __init setup_debug_locks_verbose(char *str) +{ + get_option(&str, &debug_locks_verbose); + + return 1; +} + +__setup("debug_locks_verbose=", setup_debug_locks_verbose); + +#define FAILURE 0 +#define SUCCESS 1 + +#define LOCKTYPE_SPIN 0x1 +#define LOCKTYPE_RWLOCK 0x2 +#define LOCKTYPE_MUTEX 0x4 +#define LOCKTYPE_RWSEM 0x8 + +/* + * Normal standalone locks, for the circular and irq-context + * dependency tests: + */ +static DEFINE_SPINLOCK(lock_A); +static DEFINE_SPINLOCK(lock_B); +static DEFINE_SPINLOCK(lock_C); +static DEFINE_SPINLOCK(lock_D); + +static DEFINE_RWLOCK(rwlock_A); +static DEFINE_RWLOCK(rwlock_B); +static DEFINE_RWLOCK(rwlock_C); +static DEFINE_RWLOCK(rwlock_D); + +static DEFINE_MUTEX(mutex_A); +static DEFINE_MUTEX(mutex_B); +static DEFINE_MUTEX(mutex_C); +static DEFINE_MUTEX(mutex_D); + +static DECLARE_RWSEM(rwsem_A); +static DECLARE_RWSEM(rwsem_B); +static DECLARE_RWSEM(rwsem_C); +static DECLARE_RWSEM(rwsem_D); + +/* + * Locks that we initialize dynamically as well so that + * e.g. X1 and X2 becomes two instances of the same class, + * but X* and Y* are different classes. We do this so that + * we do not trigger a real lockup: + */ +static DEFINE_SPINLOCK(lock_X1); +static DEFINE_SPINLOCK(lock_X2); +static DEFINE_SPINLOCK(lock_Y1); +static DEFINE_SPINLOCK(lock_Y2); +static DEFINE_SPINLOCK(lock_Z1); +static DEFINE_SPINLOCK(lock_Z2); + +static DEFINE_RWLOCK(rwlock_X1); +static DEFINE_RWLOCK(rwlock_X2); +static DEFINE_RWLOCK(rwlock_Y1); +static DEFINE_RWLOCK(rwlock_Y2); +static DEFINE_RWLOCK(rwlock_Z1); +static DEFINE_RWLOCK(rwlock_Z2); + +static DEFINE_MUTEX(mutex_X1); +static DEFINE_MUTEX(mutex_X2); +static DEFINE_MUTEX(mutex_Y1); +static DEFINE_MUTEX(mutex_Y2); +static DEFINE_MUTEX(mutex_Z1); +static DEFINE_MUTEX(mutex_Z2); + +static DECLARE_RWSEM(rwsem_X1); +static DECLARE_RWSEM(rwsem_X2); +static DECLARE_RWSEM(rwsem_Y1); +static DECLARE_RWSEM(rwsem_Y2); +static DECLARE_RWSEM(rwsem_Z1); +static DECLARE_RWSEM(rwsem_Z2); + +/* + * non-inlined runtime initializers, to let separate locks share + * the same lock-class: + */ +#define INIT_CLASS_FUNC(class) \ +static noinline void \ +init_class_##class(spinlock_t *lock, rwlock_t *rwlock, struct mutex *mutex, \ + struct rw_semaphore *rwsem) \ +{ \ + spin_lock_init(lock); \ + rwlock_init(rwlock); \ + mutex_init(mutex); \ + init_rwsem(rwsem); \ +} + +INIT_CLASS_FUNC(X) +INIT_CLASS_FUNC(Y) +INIT_CLASS_FUNC(Z) + +static void init_shared_classes(void) +{ + init_class_X(&lock_X1, &rwlock_X1, &mutex_X1, &rwsem_X1); + init_class_X(&lock_X2, &rwlock_X2, &mutex_X2, &rwsem_X2); + + init_class_Y(&lock_Y1, &rwlock_Y1, &mutex_Y1, &rwsem_Y1); + init_class_Y(&lock_Y2, &rwlock_Y2, &mutex_Y2, &rwsem_Y2); + + init_class_Z(&lock_Z1, &rwlock_Z1, &mutex_Z1, &rwsem_Z1); + init_class_Z(&lock_Z2, &rwlock_Z2, &mutex_Z2, &rwsem_Z2); +} + +/* + * For spinlocks and rwlocks we also do hardirq-safe / softirq-safe tests. + * The following functions use a lock from a simulated hardirq/softirq + * context, causing the locks to be marked as hardirq-safe/softirq-safe: + */ + +#define HARDIRQ_DISABLE local_irq_disable +#define HARDIRQ_ENABLE local_irq_enable + +#define HARDIRQ_ENTER() \ + local_irq_disable(); \ + irq_enter(); \ + WARN_ON(!in_irq()); + +#define HARDIRQ_EXIT() \ + __irq_exit(); \ + local_irq_enable(); + +#define SOFTIRQ_DISABLE local_bh_disable +#define SOFTIRQ_ENABLE local_bh_enable + +#define SOFTIRQ_ENTER() \ + local_bh_disable(); \ + local_irq_disable(); \ + trace_softirq_enter(); \ + WARN_ON(!in_softirq()); + +#define SOFTIRQ_EXIT() \ + trace_softirq_exit(); \ + local_irq_enable(); \ + local_bh_enable(); + +/* + * Shortcuts for lock/unlock API variants, to keep + * the testcases compact: + */ +#define L(x) spin_lock(&lock_##x) +#define U(x) spin_unlock(&lock_##x) +#define LU(x) L(x); U(x) +#define SI(x) spin_lock_init(&lock_##x) + +#define WL(x) write_lock(&rwlock_##x) +#define WU(x) write_unlock(&rwlock_##x) +#define WLU(x) WL(x); WU(x) + +#define RL(x) read_lock(&rwlock_##x) +#define RU(x) read_unlock(&rwlock_##x) +#define RLU(x) RL(x); RU(x) +#define RWI(x) rwlock_init(&rwlock_##x) + +#define ML(x) mutex_lock(&mutex_##x) +#define MU(x) mutex_unlock(&mutex_##x) +#define MI(x) mutex_init(&mutex_##x) + +#define WSL(x) down_write(&rwsem_##x) +#define WSU(x) up_write(&rwsem_##x) + +#define RSL(x) down_read(&rwsem_##x) +#define RSU(x) up_read(&rwsem_##x) +#define RWSI(x) init_rwsem(&rwsem_##x) + +#define LOCK_UNLOCK_2(x,y) LOCK(x); LOCK(y); UNLOCK(y); UNLOCK(x) + +/* + * Generate different permutations of the same testcase, using + * the same basic lock-dependency/state events: + */ + +#define GENERATE_TESTCASE(name) \ + \ +static void name(void) { E(); } + +#define GENERATE_PERMUTATIONS_2_EVENTS(name) \ + \ +static void name##_12(void) { E1(); E2(); } \ +static void name##_21(void) { E2(); E1(); } + +#define GENERATE_PERMUTATIONS_3_EVENTS(name) \ + \ +static void name##_123(void) { E1(); E2(); E3(); } \ +static void name##_132(void) { E1(); E3(); E2(); } \ +static void name##_213(void) { E2(); E1(); E3(); } \ +static void name##_231(void) { E2(); E3(); E1(); } \ +static void name##_312(void) { E3(); E1(); E2(); } \ +static void name##_321(void) { E3(); E2(); E1(); } + +/* + * AA deadlock: + */ + +#define E() \ + \ + LOCK(X1); \ + LOCK(X2); /* this one should fail */ + +/* + * 6 testcases: + */ +#include "locking-selftest-spin.h" +GENERATE_TESTCASE(AA_spin) +#include "locking-selftest-wlock.h" +GENERATE_TESTCASE(AA_wlock) +#include "locking-selftest-rlock.h" +GENERATE_TESTCASE(AA_rlock) +#include "locking-selftest-mutex.h" +GENERATE_TESTCASE(AA_mutex) +#include "locking-selftest-wsem.h" +GENERATE_TESTCASE(AA_wsem) +#include "locking-selftest-rsem.h" +GENERATE_TESTCASE(AA_rsem) + +#undef E + +/* + * Special-case for read-locking, they are + * allowed to recurse on the same lock class: + */ +static void rlock_AA1(void) +{ + RL(X1); + RL(X1); // this one should NOT fail +} + +static void rlock_AA1B(void) +{ + RL(X1); + RL(X2); // this one should NOT fail +} + +static void rsem_AA1(void) +{ + RSL(X1); + RSL(X1); // this one should fail +} + +static void rsem_AA1B(void) +{ + RSL(X1); + RSL(X2); // this one should fail +} +/* + * The mixing of read and write locks is not allowed: + */ +static void rlock_AA2(void) +{ + RL(X1); + WL(X2); // this one should fail +} + +static void rsem_AA2(void) +{ + RSL(X1); + WSL(X2); // this one should fail +} + +static void rlock_AA3(void) +{ + WL(X1); + RL(X2); // this one should fail +} + +static void rsem_AA3(void) +{ + WSL(X1); + RSL(X2); // this one should fail +} + +/* + * ABBA deadlock: + */ + +#define E() \ + \ + LOCK_UNLOCK_2(A, B); \ + LOCK_UNLOCK_2(B, A); /* fail */ + +/* + * 6 testcases: + */ +#include "locking-selftest-spin.h" +GENERATE_TESTCASE(ABBA_spin) +#include "locking-selftest-wlock.h" +GENERATE_TESTCASE(ABBA_wlock) +#include "locking-selftest-rlock.h" +GENERATE_TESTCASE(ABBA_rlock) +#include "locking-selftest-mutex.h" +GENERATE_TESTCASE(ABBA_mutex) +#include "locking-selftest-wsem.h" +GENERATE_TESTCASE(ABBA_wsem) +#include "locking-selftest-rsem.h" +GENERATE_TESTCASE(ABBA_rsem) + +#undef E + +/* + * AB BC CA deadlock: + */ + +#define E() \ + \ + LOCK_UNLOCK_2(A, B); \ + LOCK_UNLOCK_2(B, C); \ + LOCK_UNLOCK_2(C, A); /* fail */ + +/* + * 6 testcases: + */ +#include "locking-selftest-spin.h" +GENERATE_TESTCASE(ABBCCA_spin) +#include "locking-selftest-wlock.h" +GENERATE_TESTCASE(ABBCCA_wlock) +#include "locking-selftest-rlock.h" +GENERATE_TESTCASE(ABBCCA_rlock) +#include "locking-selftest-mutex.h" +GENERATE_TESTCASE(ABBCCA_mutex) +#include "locking-selftest-wsem.h" +GENERATE_TESTCASE(ABBCCA_wsem) +#include "locking-selftest-rsem.h" +GENERATE_TESTCASE(ABBCCA_rsem) + +#undef E + +/* + * AB CA BC deadlock: + */ + +#define E() \ + \ + LOCK_UNLOCK_2(A, B); \ + LOCK_UNLOCK_2(C, A); \ + LOCK_UNLOCK_2(B, C); /* fail */ + +/* + * 6 testcases: + */ +#include "locking-selftest-spin.h" +GENERATE_TESTCASE(ABCABC_spin) +#include "locking-selftest-wlock.h" +GENERATE_TESTCASE(ABCABC_wlock) +#include "locking-selftest-rlock.h" +GENERATE_TESTCASE(ABCABC_rlock) +#include "locking-selftest-mutex.h" +GENERATE_TESTCASE(ABCABC_mutex) +#include "locking-selftest-wsem.h" +GENERATE_TESTCASE(ABCABC_wsem) +#include "locking-selftest-rsem.h" +GENERATE_TESTCASE(ABCABC_rsem) + +#undef E + +/* + * AB BC CD DA deadlock: + */ + +#define E() \ + \ + LOCK_UNLOCK_2(A, B); \ + LOCK_UNLOCK_2(B, C); \ + LOCK_UNLOCK_2(C, D); \ + LOCK_UNLOCK_2(D, A); /* fail */ + +/* + * 6 testcases: + */ +#include "locking-selftest-spin.h" +GENERATE_TESTCASE(ABBCCDDA_spin) +#include "locking-selftest-wlock.h" +GENERATE_TESTCASE(ABBCCDDA_wlock) +#include "locking-selftest-rlock.h" +GENERATE_TESTCASE(ABBCCDDA_rlock) +#include "locking-selftest-mutex.h" +GENERATE_TESTCASE(ABBCCDDA_mutex) +#include "locking-selftest-wsem.h" +GENERATE_TESTCASE(ABBCCDDA_wsem) +#include "locking-selftest-rsem.h" +GENERATE_TESTCASE(ABBCCDDA_rsem) + +#undef E + +/* + * AB CD BD DA deadlock: + */ +#define E() \ + \ + LOCK_UNLOCK_2(A, B); \ + LOCK_UNLOCK_2(C, D); \ + LOCK_UNLOCK_2(B, D); \ + LOCK_UNLOCK_2(D, A); /* fail */ + +/* + * 6 testcases: + */ +#include "locking-selftest-spin.h" +GENERATE_TESTCASE(ABCDBDDA_spin) +#include "locking-selftest-wlock.h" +GENERATE_TESTCASE(ABCDBDDA_wlock) +#include "locking-selftest-rlock.h" +GENERATE_TESTCASE(ABCDBDDA_rlock) +#include "locking-selftest-mutex.h" +GENERATE_TESTCASE(ABCDBDDA_mutex) +#include "locking-selftest-wsem.h" +GENERATE_TESTCASE(ABCDBDDA_wsem) +#include "locking-selftest-rsem.h" +GENERATE_TESTCASE(ABCDBDDA_rsem) + +#undef E + +/* + * AB CD BC DA deadlock: + */ +#define E() \ + \ + LOCK_UNLOCK_2(A, B); \ + LOCK_UNLOCK_2(C, D); \ + LOCK_UNLOCK_2(B, C); \ + LOCK_UNLOCK_2(D, A); /* fail */ + +/* + * 6 testcases: + */ +#include "locking-selftest-spin.h" +GENERATE_TESTCASE(ABCDBCDA_spin) +#include "locking-selftest-wlock.h" +GENERATE_TESTCASE(ABCDBCDA_wlock) +#include "locking-selftest-rlock.h" +GENERATE_TESTCASE(ABCDBCDA_rlock) +#include "locking-selftest-mutex.h" +GENERATE_TESTCASE(ABCDBCDA_mutex) +#include "locking-selftest-wsem.h" +GENERATE_TESTCASE(ABCDBCDA_wsem) +#include "locking-selftest-rsem.h" +GENERATE_TESTCASE(ABCDBCDA_rsem) + +#undef E + +/* + * Double unlock: + */ +#define E() \ + \ + LOCK(A); \ + UNLOCK(A); \ + UNLOCK(A); /* fail */ + +/* + * 6 testcases: + */ +#include "locking-selftest-spin.h" +GENERATE_TESTCASE(double_unlock_spin) +#include "locking-selftest-wlock.h" +GENERATE_TESTCASE(double_unlock_wlock) +#include "locking-selftest-rlock.h" +GENERATE_TESTCASE(double_unlock_rlock) +#include "locking-selftest-mutex.h" +GENERATE_TESTCASE(double_unlock_mutex) +#include "locking-selftest-wsem.h" +GENERATE_TESTCASE(double_unlock_wsem) +#include "locking-selftest-rsem.h" +GENERATE_TESTCASE(double_unlock_rsem) + +#undef E + +/* + * Bad unlock ordering: + */ +#define E() \ + \ + LOCK(A); \ + LOCK(B); \ + UNLOCK(A); /* fail */ \ + UNLOCK(B); + +/* + * 6 testcases: + */ +#include "locking-selftest-spin.h" +GENERATE_TESTCASE(bad_unlock_order_spin) +#include "locking-selftest-wlock.h" +GENERATE_TESTCASE(bad_unlock_order_wlock) +#include "locking-selftest-rlock.h" +GENERATE_TESTCASE(bad_unlock_order_rlock) +#include "locking-selftest-mutex.h" +GENERATE_TESTCASE(bad_unlock_order_mutex) +#include "locking-selftest-wsem.h" +GENERATE_TESTCASE(bad_unlock_order_wsem) +#include "locking-selftest-rsem.h" +GENERATE_TESTCASE(bad_unlock_order_rsem) + +#undef E + +/* + * initializing a held lock: + */ +#define E() \ + \ + LOCK(A); \ + INIT(A); /* fail */ + +/* + * 6 testcases: + */ +#include "locking-selftest-spin.h" +GENERATE_TESTCASE(init_held_spin) +#include "locking-selftest-wlock.h" +GENERATE_TESTCASE(init_held_wlock) +#include "locking-selftest-rlock.h" +GENERATE_TESTCASE(init_held_rlock) +#include "locking-selftest-mutex.h" +GENERATE_TESTCASE(init_held_mutex) +#include "locking-selftest-wsem.h" +GENERATE_TESTCASE(init_held_wsem) +#include "locking-selftest-rsem.h" +GENERATE_TESTCASE(init_held_rsem) + +#undef E + +/* + * locking an irq-safe lock with irqs enabled: + */ +#define E1() \ + \ + IRQ_ENTER(); \ + LOCK(A); \ + UNLOCK(A); \ + IRQ_EXIT(); + +#define E2() \ + \ + LOCK(A); \ + UNLOCK(A); + +/* + * Generate 24 testcases: + */ +#include "locking-selftest-spin-hardirq.h" +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_spin) + +#include "locking-selftest-rlock-hardirq.h" +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_rlock) + +#include "locking-selftest-wlock-hardirq.h" +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_wlock) + +#include "locking-selftest-spin-softirq.h" +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_soft_spin) + +#include "locking-selftest-rlock-softirq.h" +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_soft_rlock) + +#include "locking-selftest-wlock-softirq.h" +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_soft_wlock) + +#undef E1 +#undef E2 + +/* + * Enabling hardirqs with a softirq-safe lock held: + */ +#define E1() \ + \ + SOFTIRQ_ENTER(); \ + LOCK(A); \ + UNLOCK(A); \ + SOFTIRQ_EXIT(); + +#define E2() \ + \ + HARDIRQ_DISABLE(); \ + LOCK(A); \ + HARDIRQ_ENABLE(); \ + UNLOCK(A); + +/* + * Generate 12 testcases: + */ +#include "locking-selftest-spin.h" +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_spin) + +#include "locking-selftest-wlock.h" +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_wlock) + +#include "locking-selftest-rlock.h" +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_rlock) + +#undef E1 +#undef E2 + +/* + * Enabling irqs with an irq-safe lock held: + */ +#define E1() \ + \ + IRQ_ENTER(); \ + LOCK(A); \ + UNLOCK(A); \ + IRQ_EXIT(); + +#define E2() \ + \ + IRQ_DISABLE(); \ + LOCK(A); \ + IRQ_ENABLE(); \ + UNLOCK(A); + +/* + * Generate 24 testcases: + */ +#include "locking-selftest-spin-hardirq.h" +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_spin) + +#include "locking-selftest-rlock-hardirq.h" +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_rlock) + +#include "locking-selftest-wlock-hardirq.h" +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_wlock) + +#include "locking-selftest-spin-softirq.h" +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_spin) + +#include "locking-selftest-rlock-softirq.h" +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_rlock) + +#include "locking-selftest-wlock-softirq.h" +GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_wlock) + +#undef E1 +#undef E2 + +/* + * Acquiring a irq-unsafe lock while holding an irq-safe-lock: + */ +#define E1() \ + \ + LOCK(A); \ + LOCK(B); \ + UNLOCK(B); \ + UNLOCK(A); \ + +#define E2() \ + \ + LOCK(B); \ + UNLOCK(B); + +#define E3() \ + \ + IRQ_ENTER(); \ + LOCK(A); \ + UNLOCK(A); \ + IRQ_EXIT(); + +/* + * Generate 36 testcases: + */ +#include "locking-selftest-spin-hardirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_spin) + +#include "locking-selftest-rlock-hardirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_rlock) + +#include "locking-selftest-wlock-hardirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_wlock) + +#include "locking-selftest-spin-softirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_spin) + +#include "locking-selftest-rlock-softirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_rlock) + +#include "locking-selftest-wlock-softirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_wlock) + +#undef E1 +#undef E2 +#undef E3 + +/* + * If a lock turns into softirq-safe, but earlier it took + * a softirq-unsafe lock: + */ + +#define E1() \ + IRQ_DISABLE(); \ + LOCK(A); \ + LOCK(B); \ + UNLOCK(B); \ + UNLOCK(A); \ + IRQ_ENABLE(); + +#define E2() \ + LOCK(B); \ + UNLOCK(B); + +#define E3() \ + IRQ_ENTER(); \ + LOCK(A); \ + UNLOCK(A); \ + IRQ_EXIT(); + +/* + * Generate 36 testcases: + */ +#include "locking-selftest-spin-hardirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_spin) + +#include "locking-selftest-rlock-hardirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_rlock) + +#include "locking-selftest-wlock-hardirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_wlock) + +#include "locking-selftest-spin-softirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_spin) + +#include "locking-selftest-rlock-softirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_rlock) + +#include "locking-selftest-wlock-softirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_wlock) + +#undef E1 +#undef E2 +#undef E3 + +/* + * read-lock / write-lock irq inversion. + * + * Deadlock scenario: + * + * CPU#1 is at #1, i.e. it has write-locked A, but has not + * taken B yet. + * + * CPU#2 is at #2, i.e. it has locked B. + * + * Hardirq hits CPU#2 at point #2 and is trying to read-lock A. + * + * The deadlock occurs because CPU#1 will spin on B, and CPU#2 + * will spin on A. + */ + +#define E1() \ + \ + IRQ_DISABLE(); \ + WL(A); \ + LOCK(B); \ + UNLOCK(B); \ + WU(A); \ + IRQ_ENABLE(); + +#define E2() \ + \ + LOCK(B); \ + UNLOCK(B); + +#define E3() \ + \ + IRQ_ENTER(); \ + RL(A); \ + RU(A); \ + IRQ_EXIT(); + +/* + * Generate 36 testcases: + */ +#include "locking-selftest-spin-hardirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_hard_spin) + +#include "locking-selftest-rlock-hardirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_hard_rlock) + +#include "locking-selftest-wlock-hardirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_hard_wlock) + +#include "locking-selftest-spin-softirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_soft_spin) + +#include "locking-selftest-rlock-softirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_soft_rlock) + +#include "locking-selftest-wlock-softirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_soft_wlock) + +#undef E1 +#undef E2 +#undef E3 + +/* + * read-lock / write-lock recursion that is actually safe. + */ + +#define E1() \ + \ + IRQ_DISABLE(); \ + WL(A); \ + WU(A); \ + IRQ_ENABLE(); + +#define E2() \ + \ + RL(A); \ + RU(A); \ + +#define E3() \ + \ + IRQ_ENTER(); \ + RL(A); \ + L(B); \ + U(B); \ + RU(A); \ + IRQ_EXIT(); + +/* + * Generate 12 testcases: + */ +#include "locking-selftest-hardirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_hard) + +#include "locking-selftest-softirq.h" +GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_soft) + +#undef E1 +#undef E2 +#undef E3 + +/* + * read-lock / write-lock recursion that is unsafe. + */ + +#define E1() \ + \ + IRQ_DISABLE(); \ + L(B); \ + WL(A); \ + WU(A); \ + U(B); \ + IRQ_ENABLE(); + +#define E2() \ + \ + RL(A); \ + RU(A); \ + +#define E3() \ + \ + IRQ_ENTER(); \ + L(B); \ + U(B); \ + IRQ_EXIT(); + +/* + * Generate 12 testcases: + */ +#include "locking-selftest-hardirq.h" +// GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion2_hard) + +#include "locking-selftest-softirq.h" +// GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion2_soft) + +#ifdef CONFIG_DEBUG_LOCK_ALLOC +# define I_SPINLOCK(x) lockdep_reset_lock(&lock_##x.dep_map) +# define I_RWLOCK(x) lockdep_reset_lock(&rwlock_##x.dep_map) +# define I_MUTEX(x) lockdep_reset_lock(&mutex_##x.dep_map) +# define I_RWSEM(x) lockdep_reset_lock(&rwsem_##x.dep_map) +#else +# define I_SPINLOCK(x) +# define I_RWLOCK(x) +# define I_MUTEX(x) +# define I_RWSEM(x) +#endif + +#define I1(x) \ + do { \ + I_SPINLOCK(x); \ + I_RWLOCK(x); \ + I_MUTEX(x); \ + I_RWSEM(x); \ + } while (0) + +#define I2(x) \ + do { \ + spin_lock_init(&lock_##x); \ + rwlock_init(&rwlock_##x); \ + mutex_init(&mutex_##x); \ + init_rwsem(&rwsem_##x); \ + } while (0) + +static void reset_locks(void) +{ + local_irq_disable(); + I1(A); I1(B); I1(C); I1(D); + I1(X1); I1(X2); I1(Y1); I1(Y2); I1(Z1); I1(Z2); + lockdep_reset(); + I2(A); I2(B); I2(C); I2(D); + init_shared_classes(); + local_irq_enable(); +} + +#undef I + +static int testcase_total; +static int testcase_successes; +static int expected_testcase_failures; +static int unexpected_testcase_failures; + +static void dotest(void (*testcase_fn)(void), int expected, int lockclass_mask) +{ + unsigned long saved_preempt_count = preempt_count(); + int expected_failure = 0; + + WARN_ON(irqs_disabled()); + + testcase_fn(); + /* + * Filter out expected failures: + */ +#ifndef CONFIG_PROVE_LOCKING + if ((lockclass_mask & LOCKTYPE_SPIN) && debug_locks != expected) + expected_failure = 1; + if ((lockclass_mask & LOCKTYPE_RWLOCK) && debug_locks != expected) + expected_failure = 1; + if ((lockclass_mask & LOCKTYPE_MUTEX) && debug_locks != expected) + expected_failure = 1; + if ((lockclass_mask & LOCKTYPE_RWSEM) && debug_locks != expected) + expected_failure = 1; +#endif + if (debug_locks != expected) { + if (expected_failure) { + expected_testcase_failures++; + printk("failed|"); + } else { + unexpected_testcase_failures++; + printk("FAILED|"); + } + } else { + testcase_successes++; + printk(" ok |"); + } + testcase_total++; + + if (debug_locks_verbose) + printk(" lockclass mask: %x, debug_locks: %d, expected: %d\n", + lockclass_mask, debug_locks, expected); + /* + * Some tests (e.g. double-unlock) might corrupt the preemption + * count, so restore it: + */ + preempt_count() = saved_preempt_count; +#ifdef CONFIG_TRACE_IRQFLAGS + if (softirq_count()) + current->softirqs_enabled = 0; + else + current->softirqs_enabled = 1; +#endif + + reset_locks(); +} + +static inline void print_testname(const char *testname) +{ + printk("%33s:", testname); +} + +#define DO_TESTCASE_1(desc, name, nr) \ + print_testname(desc"/"#nr); \ + dotest(name##_##nr, SUCCESS, LOCKTYPE_RWLOCK); \ + printk("\n"); + +#define DO_TESTCASE_1B(desc, name, nr) \ + print_testname(desc"/"#nr); \ + dotest(name##_##nr, FAILURE, LOCKTYPE_RWLOCK); \ + printk("\n"); + +#define DO_TESTCASE_3(desc, name, nr) \ + print_testname(desc"/"#nr); \ + dotest(name##_spin_##nr, FAILURE, LOCKTYPE_SPIN); \ + dotest(name##_wlock_##nr, FAILURE, LOCKTYPE_RWLOCK); \ + dotest(name##_rlock_##nr, SUCCESS, LOCKTYPE_RWLOCK); \ + printk("\n"); + +#define DO_TESTCASE_3RW(desc, name, nr) \ + print_testname(desc"/"#nr); \ + dotest(name##_spin_##nr, FAILURE, LOCKTYPE_SPIN|LOCKTYPE_RWLOCK);\ + dotest(name##_wlock_##nr, FAILURE, LOCKTYPE_RWLOCK); \ + dotest(name##_rlock_##nr, SUCCESS, LOCKTYPE_RWLOCK); \ + printk("\n"); + +#define DO_TESTCASE_6(desc, name) \ + print_testname(desc); \ + dotest(name##_spin, FAILURE, LOCKTYPE_SPIN); \ + dotest(name##_wlock, FAILURE, LOCKTYPE_RWLOCK); \ + dotest(name##_rlock, FAILURE, LOCKTYPE_RWLOCK); \ + dotest(name##_mutex, FAILURE, LOCKTYPE_MUTEX); \ + dotest(name##_wsem, FAILURE, LOCKTYPE_RWSEM); \ + dotest(name##_rsem, FAILURE, LOCKTYPE_RWSEM); \ + printk("\n"); + +#define DO_TESTCASE_6_SUCCESS(desc, name) \ + print_testname(desc); \ + dotest(name##_spin, SUCCESS, LOCKTYPE_SPIN); \ + dotest(name##_wlock, SUCCESS, LOCKTYPE_RWLOCK); \ + dotest(name##_rlock, SUCCESS, LOCKTYPE_RWLOCK); \ + dotest(name##_mutex, SUCCESS, LOCKTYPE_MUTEX); \ + dotest(name##_wsem, SUCCESS, LOCKTYPE_RWSEM); \ + dotest(name##_rsem, SUCCESS, LOCKTYPE_RWSEM); \ + printk("\n"); + +/* + * 'read' variant: rlocks must not trigger. + */ +#define DO_TESTCASE_6R(desc, name) \ + print_testname(desc); \ + dotest(name##_spin, FAILURE, LOCKTYPE_SPIN); \ + dotest(name##_wlock, FAILURE, LOCKTYPE_RWLOCK); \ + dotest(name##_rlock, SUCCESS, LOCKTYPE_RWLOCK); \ + dotest(name##_mutex, FAILURE, LOCKTYPE_MUTEX); \ + dotest(name##_wsem, FAILURE, LOCKTYPE_RWSEM); \ + dotest(name##_rsem, FAILURE, LOCKTYPE_RWSEM); \ + printk("\n"); + +#define DO_TESTCASE_2I(desc, name, nr) \ + DO_TESTCASE_1("hard-"desc, name##_hard, nr); \ + DO_TESTCASE_1("soft-"desc, name##_soft, nr); + +#define DO_TESTCASE_2IB(desc, name, nr) \ + DO_TESTCASE_1B("hard-"desc, name##_hard, nr); \ + DO_TESTCASE_1B("soft-"desc, name##_soft, nr); + +#define DO_TESTCASE_6I(desc, name, nr) \ + DO_TESTCASE_3("hard-"desc, name##_hard, nr); \ + DO_TESTCASE_3("soft-"desc, name##_soft, nr); + +#define DO_TESTCASE_6IRW(desc, name, nr) \ + DO_TESTCASE_3RW("hard-"desc, name##_hard, nr); \ + DO_TESTCASE_3RW("soft-"desc, name##_soft, nr); + +#define DO_TESTCASE_2x3(desc, name) \ + DO_TESTCASE_3(desc, name, 12); \ + DO_TESTCASE_3(desc, name, 21); + +#define DO_TESTCASE_2x6(desc, name) \ + DO_TESTCASE_6I(desc, name, 12); \ + DO_TESTCASE_6I(desc, name, 21); + +#define DO_TESTCASE_6x2(desc, name) \ + DO_TESTCASE_2I(desc, name, 123); \ + DO_TESTCASE_2I(desc, name, 132); \ + DO_TESTCASE_2I(desc, name, 213); \ + DO_TESTCASE_2I(desc, name, 231); \ + DO_TESTCASE_2I(desc, name, 312); \ + DO_TESTCASE_2I(desc, name, 321); + +#define DO_TESTCASE_6x2B(desc, name) \ + DO_TESTCASE_2IB(desc, name, 123); \ + DO_TESTCASE_2IB(desc, name, 132); \ + DO_TESTCASE_2IB(desc, name, 213); \ + DO_TESTCASE_2IB(desc, name, 231); \ + DO_TESTCASE_2IB(desc, name, 312); \ + DO_TESTCASE_2IB(desc, name, 321); + +#define DO_TESTCASE_6x6(desc, name) \ + DO_TESTCASE_6I(desc, name, 123); \ + DO_TESTCASE_6I(desc, name, 132); \ + DO_TESTCASE_6I(desc, name, 213); \ + DO_TESTCASE_6I(desc, name, 231); \ + DO_TESTCASE_6I(desc, name, 312); \ + DO_TESTCASE_6I(desc, name, 321); + +#define DO_TESTCASE_6x6RW(desc, name) \ + DO_TESTCASE_6IRW(desc, name, 123); \ + DO_TESTCASE_6IRW(desc, name, 132); \ + DO_TESTCASE_6IRW(desc, name, 213); \ + DO_TESTCASE_6IRW(desc, name, 231); \ + DO_TESTCASE_6IRW(desc, name, 312); \ + DO_TESTCASE_6IRW(desc, name, 321); + + +void locking_selftest(void) +{ + /* + * Got a locking failure before the selftest ran? + */ + if (!debug_locks) { + printk("----------------------------------\n"); + printk("| Locking API testsuite disabled |\n"); + printk("----------------------------------\n"); + return; + } + + /* + * Run the testsuite: + */ + printk("------------------------\n"); + printk("| Locking API testsuite:\n"); + printk("----------------------------------------------------------------------------\n"); + printk(" | spin |wlock |rlock |mutex | wsem | rsem |\n"); + printk(" --------------------------------------------------------------------------\n"); + + init_shared_classes(); + debug_locks_silent = !debug_locks_verbose; + + DO_TESTCASE_6R("A-A deadlock", AA); + DO_TESTCASE_6R("A-B-B-A deadlock", ABBA); + DO_TESTCASE_6R("A-B-B-C-C-A deadlock", ABBCCA); + DO_TESTCASE_6R("A-B-C-A-B-C deadlock", ABCABC); + DO_TESTCASE_6R("A-B-B-C-C-D-D-A deadlock", ABBCCDDA); + DO_TESTCASE_6R("A-B-C-D-B-D-D-A deadlock", ABCDBDDA); + DO_TESTCASE_6R("A-B-C-D-B-C-D-A deadlock", ABCDBCDA); + DO_TESTCASE_6("double unlock", double_unlock); + DO_TESTCASE_6("initialize held", init_held); + DO_TESTCASE_6_SUCCESS("bad unlock order", bad_unlock_order); + + printk(" --------------------------------------------------------------------------\n"); + print_testname("recursive read-lock"); + printk(" |"); + dotest(rlock_AA1, SUCCESS, LOCKTYPE_RWLOCK); + printk(" |"); + dotest(rsem_AA1, FAILURE, LOCKTYPE_RWSEM); + printk("\n"); + + print_testname("recursive read-lock #2"); + printk(" |"); + dotest(rlock_AA1B, SUCCESS, LOCKTYPE_RWLOCK); + printk(" |"); + dotest(rsem_AA1B, FAILURE, LOCKTYPE_RWSEM); + printk("\n"); + + print_testname("mixed read-write-lock"); + printk(" |"); + dotest(rlock_AA2, FAILURE, LOCKTYPE_RWLOCK); + printk(" |"); + dotest(rsem_AA2, FAILURE, LOCKTYPE_RWSEM); + printk("\n"); + + print_testname("mixed write-read-lock"); + printk(" |"); + dotest(rlock_AA3, FAILURE, LOCKTYPE_RWLOCK); + printk(" |"); + dotest(rsem_AA3, FAILURE, LOCKTYPE_RWSEM); + printk("\n"); + + printk(" --------------------------------------------------------------------------\n"); + + /* + * irq-context testcases: + */ + DO_TESTCASE_2x6("irqs-on + irq-safe-A", irqsafe1); + DO_TESTCASE_2x3("sirq-safe-A => hirqs-on", irqsafe2A); + DO_TESTCASE_2x6("safe-A + irqs-on", irqsafe2B); + DO_TESTCASE_6x6("safe-A + unsafe-B #1", irqsafe3); + DO_TESTCASE_6x6("safe-A + unsafe-B #2", irqsafe4); + DO_TESTCASE_6x6RW("irq lock-inversion", irq_inversion); + + DO_TESTCASE_6x2("irq read-recursion", irq_read_recursion); +// DO_TESTCASE_6x2B("irq read-recursion #2", irq_read_recursion2); + + if (unexpected_testcase_failures) { + printk("-----------------------------------------------------------------\n"); + debug_locks = 0; + printk("BUG: %3d unexpected failures (out of %3d) - debugging disabled! |\n", + unexpected_testcase_failures, testcase_total); + printk("-----------------------------------------------------------------\n"); + } else if (expected_testcase_failures && testcase_successes) { + printk("--------------------------------------------------------\n"); + printk("%3d out of %3d testcases failed, as expected. |\n", + expected_testcase_failures, testcase_total); + printk("----------------------------------------------------\n"); + debug_locks = 1; + } else if (expected_testcase_failures && !testcase_successes) { + printk("--------------------------------------------------------\n"); + printk("All %3d testcases failed, as expected. |\n", + expected_testcase_failures); + printk("----------------------------------------\n"); + debug_locks = 1; + } else { + printk("-------------------------------------------------------\n"); + printk("Good, all %3d testcases passed! |\n", + testcase_successes); + printk("---------------------------------\n"); + debug_locks = 1; + } + debug_locks_silent = 0; +} diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c new file mode 100644 index 000000000..850449080 --- /dev/null +++ b/lib/percpu_counter.c @@ -0,0 +1,46 @@ +/* + * Fast batching percpu counters. + */ + +#include <linux/percpu_counter.h> +#include <linux/module.h> + +void percpu_counter_mod(struct percpu_counter *fbc, s32 amount) +{ + long count; + s32 *pcount; + int cpu = get_cpu(); + + pcount = per_cpu_ptr(fbc->counters, cpu); + count = *pcount + amount; + if (count >= FBC_BATCH || count <= -FBC_BATCH) { + spin_lock(&fbc->lock); + fbc->count += count; + *pcount = 0; + spin_unlock(&fbc->lock); + } else { + *pcount = count; + } + put_cpu(); +} +EXPORT_SYMBOL(percpu_counter_mod); + +/* + * Add up all the per-cpu counts, return the result. This is a more accurate + * but much slower version of percpu_counter_read_positive() + */ +s64 percpu_counter_sum(struct percpu_counter *fbc) +{ + s64 ret; + int cpu; + + spin_lock(&fbc->lock); + ret = fbc->count; + for_each_possible_cpu(cpu) { + s32 *pcount = per_cpu_ptr(fbc->counters, cpu); + ret += *pcount; + } + spin_unlock(&fbc->lock); + return ret < 0 ? 0 : ret; +} +EXPORT_SYMBOL(percpu_counter_sum); diff --git a/lib/plist.c b/lib/plist.c new file mode 100644 index 000000000..3074a0227 --- /dev/null +++ b/lib/plist.c @@ -0,0 +1,118 @@ +/* + * lib/plist.c + * + * Descending-priority-sorted double-linked list + * + * (C) 2002-2003 Intel Corp + * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>. + * + * 2001-2005 (c) MontaVista Software, Inc. + * Daniel Walker <dwalker@mvista.com> + * + * (C) 2005 Thomas Gleixner <tglx@linutronix.de> + * + * Simplifications of the original code by + * Oleg Nesterov <oleg@tv-sign.ru> + * + * Licensed under the FSF's GNU Public License v2 or later. + * + * Based on simple lists (include/linux/list.h). + * + * This file contains the add / del functions which are considered to + * be too large to inline. See include/linux/plist.h for further + * information. + */ + +#include <linux/plist.h> +#include <linux/spinlock.h> + +#ifdef CONFIG_DEBUG_PI_LIST + +static void plist_check_prev_next(struct list_head *t, struct list_head *p, + struct list_head *n) +{ + if (n->prev != p || p->next != n) { + printk("top: %p, n: %p, p: %p\n", t, t->next, t->prev); + printk("prev: %p, n: %p, p: %p\n", p, p->next, p->prev); + printk("next: %p, n: %p, p: %p\n", n, n->next, n->prev); + WARN_ON(1); + } +} + +static void plist_check_list(struct list_head *top) +{ + struct list_head *prev = top, *next = top->next; + + plist_check_prev_next(top, prev, next); + while (next != top) { + prev = next; + next = prev->next; + plist_check_prev_next(top, prev, next); + } +} + +static void plist_check_head(struct plist_head *head) +{ + WARN_ON(!head->lock); + if (head->lock) + WARN_ON_SMP(!spin_is_locked(head->lock)); + plist_check_list(&head->prio_list); + plist_check_list(&head->node_list); +} + +#else +# define plist_check_head(h) do { } while (0) +#endif + +/** + * plist_add - add @node to @head + * + * @node: &struct plist_node pointer + * @head: &struct plist_head pointer + */ +void plist_add(struct plist_node *node, struct plist_head *head) +{ + struct plist_node *iter; + + plist_check_head(head); + WARN_ON(!plist_node_empty(node)); + + list_for_each_entry(iter, &head->prio_list, plist.prio_list) { + if (node->prio < iter->prio) + goto lt_prio; + else if (node->prio == iter->prio) { + iter = list_entry(iter->plist.prio_list.next, + struct plist_node, plist.prio_list); + goto eq_prio; + } + } + +lt_prio: + list_add_tail(&node->plist.prio_list, &iter->plist.prio_list); +eq_prio: + list_add_tail(&node->plist.node_list, &iter->plist.node_list); + + plist_check_head(head); +} + +/** + * plist_del - Remove a @node from plist. + * + * @node: &struct plist_node pointer - entry to be removed + * @head: &struct plist_head pointer - list head + */ +void plist_del(struct plist_node *node, struct plist_head *head) +{ + plist_check_head(head); + + if (!list_empty(&node->plist.prio_list)) { + struct plist_node *next = plist_first(&node->plist); + + list_move_tail(&next->plist.prio_list, &node->plist.prio_list); + list_del_init(&node->plist.prio_list); + } + + list_del_init(&node->plist.node_list); + + plist_check_head(head); +} diff --git a/lib/zlib_inflate/inflate.h b/lib/zlib_inflate/inflate.h new file mode 100644 index 000000000..df8a6c920 --- /dev/null +++ b/lib/zlib_inflate/inflate.h @@ -0,0 +1,107 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2004 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN, /* i: waiting for length/lit code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD or MEM mode -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME + NAME -> COMMENT -> HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or CHECK + STORED -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + /* gz_headerp head; */ /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned write; /* window write index */ + unsigned char *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const *lencode; /* starting table for length/literal codes */ + code const *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/mm/vmstat.c b/mm/vmstat.c new file mode 100644 index 000000000..321668aa6 --- /dev/null +++ b/mm/vmstat.c @@ -0,0 +1,701 @@ +/* + * linux/mm/vmstat.c + * + * Manages VM statistics + * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds + * + * zoned VM statistics + * Copyright (C) 2006 Silicon Graphics, Inc., + * Christoph Lameter <christoph@lameter.com> + */ + +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/cpu.h> + +void __get_zone_counts(unsigned long *active, unsigned long *inactive, + unsigned long *free, struct pglist_data *pgdat) +{ + struct zone *zones = pgdat->node_zones; + int i; + + *active = 0; + *inactive = 0; + *free = 0; + for (i = 0; i < MAX_NR_ZONES; i++) { + *active += zones[i].nr_active; + *inactive += zones[i].nr_inactive; + *free += zones[i].free_pages; + } +} + +void get_zone_counts(unsigned long *active, + unsigned long *inactive, unsigned long *free) +{ + struct pglist_data *pgdat; + + *active = 0; + *inactive = 0; + *free = 0; + for_each_online_pgdat(pgdat) { + unsigned long l, m, n; + __get_zone_counts(&l, &m, &n, pgdat); + *active += l; + *inactive += m; + *free += n; + } +} + +#ifdef CONFIG_VM_EVENT_COUNTERS +DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}}; +EXPORT_PER_CPU_SYMBOL(vm_event_states); + +static void sum_vm_events(unsigned long *ret, cpumask_t *cpumask) +{ + int cpu = 0; + int i; + + memset(ret, 0, NR_VM_EVENT_ITEMS * sizeof(unsigned long)); + + cpu = first_cpu(*cpumask); + while (cpu < NR_CPUS) { + struct vm_event_state *this = &per_cpu(vm_event_states, cpu); + + cpu = next_cpu(cpu, *cpumask); + + if (cpu < NR_CPUS) + prefetch(&per_cpu(vm_event_states, cpu)); + + + for (i = 0; i < NR_VM_EVENT_ITEMS; i++) + ret[i] += this->event[i]; + } +} + +/* + * Accumulate the vm event counters across all CPUs. + * The result is unavoidably approximate - it can change + * during and after execution of this function. +*/ +void all_vm_events(unsigned long *ret) +{ + sum_vm_events(ret, &cpu_online_map); +} +EXPORT_SYMBOL_GPL(all_vm_events); + +#ifdef CONFIG_HOTPLUG +/* + * Fold the foreign cpu events into our own. + * + * This is adding to the events on one processor + * but keeps the global counts constant. + */ +void vm_events_fold_cpu(int cpu) +{ + struct vm_event_state *fold_state = &per_cpu(vm_event_states, cpu); + int i; + + for (i = 0; i < NR_VM_EVENT_ITEMS; i++) { + count_vm_events(i, fold_state->event[i]); + fold_state->event[i] = 0; + } +} +#endif /* CONFIG_HOTPLUG */ + +#endif /* CONFIG_VM_EVENT_COUNTERS */ + +/* + * Manage combined zone based / global counters + * + * vm_stat contains the global counters + */ +atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS]; +EXPORT_SYMBOL(vm_stat); + +#ifdef CONFIG_SMP + +static int calculate_threshold(struct zone *zone) +{ + int threshold; + int mem; /* memory in 128 MB units */ + + /* + * The threshold scales with the number of processors and the amount + * of memory per zone. More memory means that we can defer updates for + * longer, more processors could lead to more contention. + * fls() is used to have a cheap way of logarithmic scaling. + * + * Some sample thresholds: + * + * Threshold Processors (fls) Zonesize fls(mem+1) + * ------------------------------------------------------------------ + * 8 1 1 0.9-1 GB 4 + * 16 2 2 0.9-1 GB 4 + * 20 2 2 1-2 GB 5 + * 24 2 2 2-4 GB 6 + * 28 2 2 4-8 GB 7 + * 32 2 2 8-16 GB 8 + * 4 2 2 <128M 1 + * 30 4 3 2-4 GB 5 + * 48 4 3 8-16 GB 8 + * 32 8 4 1-2 GB 4 + * 32 8 4 0.9-1GB 4 + * 10 16 5 <128M 1 + * 40 16 5 900M 4 + * 70 64 7 2-4 GB 5 + * 84 64 7 4-8 GB 6 + * 108 512 9 4-8 GB 6 + * 125 1024 10 8-16 GB 8 + * 125 1024 10 16-32 GB 9 + */ + + mem = zone->present_pages >> (27 - PAGE_SHIFT); + + threshold = 2 * fls(num_online_cpus()) * (1 + fls(mem)); + + /* + * Maximum threshold is 125 + */ + threshold = min(125, threshold); + + return threshold; +} + +/* + * Refresh the thresholds for each zone. + */ +static void refresh_zone_stat_thresholds(void) +{ + struct zone *zone; + int cpu; + int threshold; + + for_each_zone(zone) { + + if (!zone->present_pages) + continue; + + threshold = calculate_threshold(zone); + + for_each_online_cpu(cpu) + zone_pcp(zone, cpu)->stat_threshold = threshold; + } +} + +/* + * For use when we know that interrupts are disabled. + */ +void __mod_zone_page_state(struct zone *zone, enum zone_stat_item item, + int delta) +{ + struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id()); + s8 *p = pcp->vm_stat_diff + item; + long x; + + x = delta + *p; + + if (unlikely(x > pcp->stat_threshold || x < -pcp->stat_threshold)) { + zone_page_state_add(x, zone, item); + x = 0; + } + *p = x; +} +EXPORT_SYMBOL(__mod_zone_page_state); + +/* + * For an unknown interrupt state + */ +void mod_zone_page_state(struct zone *zone, enum zone_stat_item item, + int delta) +{ + unsigned long flags; + + local_irq_save(flags); + __mod_zone_page_state(zone, item, delta); + local_irq_restore(flags); +} +EXPORT_SYMBOL(mod_zone_page_state); + +/* + * Optimized increment and decrement functions. + * + * These are only for a single page and therefore can take a struct page * + * argument instead of struct zone *. This allows the inclusion of the code + * generated for page_zone(page) into the optimized functions. + * + * No overflow check is necessary and therefore the differential can be + * incremented or decremented in place which may allow the compilers to + * generate better code. + * The increment or decrement is known and therefore one boundary check can + * be omitted. + * + * NOTE: These functions are very performance sensitive. Change only + * with care. + * + * Some processors have inc/dec instructions that are atomic vs an interrupt. + * However, the code must first determine the differential location in a zone + * based on the processor number and then inc/dec the counter. There is no + * guarantee without disabling preemption that the processor will not change + * in between and therefore the atomicity vs. interrupt cannot be exploited + * in a useful way here. + */ +static void __inc_zone_state(struct zone *zone, enum zone_stat_item item) +{ + struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id()); + s8 *p = pcp->vm_stat_diff + item; + + (*p)++; + + if (unlikely(*p > pcp->stat_threshold)) { + int overstep = pcp->stat_threshold / 2; + + zone_page_state_add(*p + overstep, zone, item); + *p = -overstep; + } +} + +void __inc_zone_page_state(struct page *page, enum zone_stat_item item) +{ + __inc_zone_state(page_zone(page), item); +} +EXPORT_SYMBOL(__inc_zone_page_state); + +void __dec_zone_page_state(struct page *page, enum zone_stat_item item) +{ + struct zone *zone = page_zone(page); + struct per_cpu_pageset *pcp = zone_pcp(zone, smp_processor_id()); + s8 *p = pcp->vm_stat_diff + item; + + (*p)--; + + if (unlikely(*p < - pcp->stat_threshold)) { + int overstep = pcp->stat_threshold / 2; + + zone_page_state_add(*p - overstep, zone, item); + *p = overstep; + } +} +EXPORT_SYMBOL(__dec_zone_page_state); + +void inc_zone_state(struct zone *zone, enum zone_stat_item item) +{ + unsigned long flags; + + local_irq_save(flags); + __inc_zone_state(zone, item); + local_irq_restore(flags); +} + +void inc_zone_page_state(struct page *page, enum zone_stat_item item) +{ + unsigned long flags; + struct zone *zone; + + zone = page_zone(page); + local_irq_save(flags); + __inc_zone_state(zone, item); + local_irq_restore(flags); +} +EXPORT_SYMBOL(inc_zone_page_state); + +void dec_zone_page_state(struct page *page, enum zone_stat_item item) +{ + unsigned long flags; + + local_irq_save(flags); + __dec_zone_page_state(page, item); + local_irq_restore(flags); +} +EXPORT_SYMBOL(dec_zone_page_state); + +/* + * Update the zone counters for one cpu. + */ +void refresh_cpu_vm_stats(int cpu) +{ + struct zone *zone; + int i; + unsigned long flags; + + for_each_zone(zone) { + struct per_cpu_pageset *pcp; + + pcp = zone_pcp(zone, cpu); + + for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) + if (pcp->vm_stat_diff[i]) { + local_irq_save(flags); + zone_page_state_add(pcp->vm_stat_diff[i], + zone, i); + pcp->vm_stat_diff[i] = 0; + local_irq_restore(flags); + } + } +} + +static void __refresh_cpu_vm_stats(void *dummy) +{ + refresh_cpu_vm_stats(smp_processor_id()); +} + +/* + * Consolidate all counters. + * + * Note that the result is less inaccurate but still inaccurate + * if concurrent processes are allowed to run. + */ +void refresh_vm_stats(void) +{ + on_each_cpu(__refresh_cpu_vm_stats, NULL, 0, 1); +} +EXPORT_SYMBOL(refresh_vm_stats); + +#endif + +#ifdef CONFIG_NUMA +/* + * zonelist = the list of zones passed to the allocator + * z = the zone from which the allocation occurred. + * + * Must be called with interrupts disabled. + */ +void zone_statistics(struct zonelist *zonelist, struct zone *z) +{ + if (z->zone_pgdat == zonelist->zones[0]->zone_pgdat) { + __inc_zone_state(z, NUMA_HIT); + } else { + __inc_zone_state(z, NUMA_MISS); + __inc_zone_state(zonelist->zones[0], NUMA_FOREIGN); + } + if (z->zone_pgdat == NODE_DATA(numa_node_id())) + __inc_zone_state(z, NUMA_LOCAL); + else + __inc_zone_state(z, NUMA_OTHER); +} +#endif + +#ifdef CONFIG_PROC_FS + +#include <linux/seq_file.h> + +static void *frag_start(struct seq_file *m, loff_t *pos) +{ + pg_data_t *pgdat; + loff_t node = *pos; + for (pgdat = first_online_pgdat(); + pgdat && node; + pgdat = next_online_pgdat(pgdat)) + --node; + + return pgdat; +} + +static void *frag_next(struct seq_file *m, void *arg, loff_t *pos) +{ + pg_data_t *pgdat = (pg_data_t *)arg; + + (*pos)++; + return next_online_pgdat(pgdat); +} + +static void frag_stop(struct seq_file *m, void *arg) +{ +} + +/* + * This walks the free areas for each zone. + */ +static int frag_show(struct seq_file *m, void *arg) +{ + pg_data_t *pgdat = (pg_data_t *)arg; + struct zone *zone; + struct zone *node_zones = pgdat->node_zones; + unsigned long flags; + int order; + + for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) { + if (!populated_zone(zone)) + continue; + + spin_lock_irqsave(&zone->lock, flags); + seq_printf(m, "Node %d, zone %8s ", pgdat->node_id, zone->name); + for (order = 0; order < MAX_ORDER; ++order) + seq_printf(m, "%6lu ", zone->free_area[order].nr_free); + spin_unlock_irqrestore(&zone->lock, flags); + seq_putc(m, '\n'); + } + return 0; +} + +struct seq_operations fragmentation_op = { + .start = frag_start, + .next = frag_next, + .stop = frag_stop, + .show = frag_show, +}; + +static char *vmstat_text[] = { + /* Zoned VM counters */ + "nr_anon_pages", + "nr_mapped", + "nr_file_pages", + "nr_slab", + "nr_page_table_pages", + "nr_dirty", + "nr_writeback", + "nr_unstable", + "nr_bounce", + +#ifdef CONFIG_NUMA + "numa_hit", + "numa_miss", + "numa_foreign", + "numa_interleave", + "numa_local", + "numa_other", +#endif + +#ifdef CONFIG_VM_EVENT_COUNTERS + "pgpgin", + "pgpgout", + "pswpin", + "pswpout", + + "pgalloc_dma", + "pgalloc_dma32", + "pgalloc_normal", + "pgalloc_high", + + "pgfree", + "pgactivate", + "pgdeactivate", + + "pgfault", + "pgmajfault", + + "pgrefill_dma", + "pgrefill_dma32", + "pgrefill_normal", + "pgrefill_high", + + "pgsteal_dma", + "pgsteal_dma32", + "pgsteal_normal", + "pgsteal_high", + + "pgscan_kswapd_dma", + "pgscan_kswapd_dma32", + "pgscan_kswapd_normal", + "pgscan_kswapd_high", + + "pgscan_direct_dma", + "pgscan_direct_dma32", + "pgscan_direct_normal", + "pgscan_direct_high", + + "pginodesteal", + "slabs_scanned", + "kswapd_steal", + "kswapd_inodesteal", + "pageoutrun", + "allocstall", + + "pgrotated", +#endif +}; + +/* + * Output information about zones in @pgdat. + */ +static int zoneinfo_show(struct seq_file *m, void *arg) +{ + pg_data_t *pgdat = arg; + struct zone *zone; + struct zone *node_zones = pgdat->node_zones; + unsigned long flags; + + for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; zone++) { + int i; + + if (!populated_zone(zone)) + continue; + + spin_lock_irqsave(&zone->lock, flags); + seq_printf(m, "Node %d, zone %8s", pgdat->node_id, zone->name); + seq_printf(m, + "\n pages free %lu" + "\n min %lu" + "\n low %lu" + "\n high %lu" + "\n active %lu" + "\n inactive %lu" + "\n scanned %lu (a: %lu i: %lu)" + "\n spanned %lu" + "\n present %lu", + zone->free_pages, + zone->pages_min, + zone->pages_low, + zone->pages_high, + zone->nr_active, + zone->nr_inactive, + zone->pages_scanned, + zone->nr_scan_active, zone->nr_scan_inactive, + zone->spanned_pages, + zone->present_pages); + + for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) + seq_printf(m, "\n %-12s %lu", vmstat_text[i], + zone_page_state(zone, i)); + + seq_printf(m, + "\n protection: (%lu", + zone->lowmem_reserve[0]); + for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++) + seq_printf(m, ", %lu", zone->lowmem_reserve[i]); + seq_printf(m, + ")" + "\n pagesets"); + for_each_online_cpu(i) { + struct per_cpu_pageset *pageset; + int j; + + pageset = zone_pcp(zone, i); + for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) { + if (pageset->pcp[j].count) + break; + } + if (j == ARRAY_SIZE(pageset->pcp)) + continue; + for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) { + seq_printf(m, + "\n cpu: %i pcp: %i" + "\n count: %i" + "\n high: %i" + "\n batch: %i", + i, j, + pageset->pcp[j].count, + pageset->pcp[j].high, + pageset->pcp[j].batch); + } +#ifdef CONFIG_SMP + seq_printf(m, "\n vm stats threshold: %d", + pageset->stat_threshold); +#endif + } + seq_printf(m, + "\n all_unreclaimable: %u" + "\n prev_priority: %i" + "\n start_pfn: %lu", + zone->all_unreclaimable, + zone->prev_priority, + zone->zone_start_pfn); + spin_unlock_irqrestore(&zone->lock, flags); + seq_putc(m, '\n'); + } + return 0; +} + +struct seq_operations zoneinfo_op = { + .start = frag_start, /* iterate over all zones. The same as in + * fragmentation. */ + .next = frag_next, + .stop = frag_stop, + .show = zoneinfo_show, +}; + +static void *vmstat_start(struct seq_file *m, loff_t *pos) +{ + unsigned long *v; +#ifdef CONFIG_VM_EVENT_COUNTERS + unsigned long *e; +#endif + int i; + + if (*pos >= ARRAY_SIZE(vmstat_text)) + return NULL; + +#ifdef CONFIG_VM_EVENT_COUNTERS + v = kmalloc(NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long) + + sizeof(struct vm_event_state), GFP_KERNEL); +#else + v = kmalloc(NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long), + GFP_KERNEL); +#endif + m->private = v; + if (!v) + return ERR_PTR(-ENOMEM); + for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++) + v[i] = global_page_state(i); +#ifdef CONFIG_VM_EVENT_COUNTERS + e = v + NR_VM_ZONE_STAT_ITEMS; + all_vm_events(e); + e[PGPGIN] /= 2; /* sectors -> kbytes */ + e[PGPGOUT] /= 2; +#endif + return v + *pos; +} + +static void *vmstat_next(struct seq_file *m, void *arg, loff_t *pos) +{ + (*pos)++; + if (*pos >= ARRAY_SIZE(vmstat_text)) + return NULL; + return (unsigned long *)m->private + *pos; +} + +static int vmstat_show(struct seq_file *m, void *arg) +{ + unsigned long *l = arg; + unsigned long off = l - (unsigned long *)m->private; + + seq_printf(m, "%s %lu\n", vmstat_text[off], *l); + return 0; +} + +static void vmstat_stop(struct seq_file *m, void *arg) +{ + kfree(m->private); + m->private = NULL; +} + +struct seq_operations vmstat_op = { + .start = vmstat_start, + .next = vmstat_next, + .stop = vmstat_stop, + .show = vmstat_show, +}; + +#endif /* CONFIG_PROC_FS */ + +#ifdef CONFIG_SMP +/* + * Use the cpu notifier to insure that the thresholds are recalculated + * when necessary. + */ +static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb, + unsigned long action, + void *hcpu) +{ + switch (action) { + case CPU_UP_PREPARE: + case CPU_UP_CANCELED: + case CPU_DEAD: + refresh_zone_stat_thresholds(); + break; + default: + break; + } + return NOTIFY_OK; +} + +static struct notifier_block __cpuinitdata vmstat_notifier = + { &vmstat_cpuup_callback, NULL, 0 }; + +int __init setup_vmstat(void) +{ + refresh_zone_stat_thresholds(); + register_cpu_notifier(&vmstat_notifier); + return 0; +} +module_init(setup_vmstat) +#endif diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c new file mode 100644 index 000000000..c0a4ae28f --- /dev/null +++ b/net/atm/atm_sysfs.c @@ -0,0 +1,175 @@ +/* ATM driver model support. */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/kobject.h> +#include <linux/atmdev.h> +#include "common.h" +#include "resources.h" + +#define to_atm_dev(cldev) container_of(cldev, struct atm_dev, class_dev) + +static ssize_t show_type(struct class_device *cdev, char *buf) +{ + struct atm_dev *adev = to_atm_dev(cdev); + return sprintf(buf, "%s\n", adev->type); +} + +static ssize_t show_address(struct class_device *cdev, char *buf) +{ + char *pos = buf; + struct atm_dev *adev = to_atm_dev(cdev); + int i; + + for (i = 0; i < (ESI_LEN - 1); i++) + pos += sprintf(pos, "%02x:", adev->esi[i]); + pos += sprintf(pos, "%02x\n", adev->esi[i]); + + return pos - buf; +} + +static ssize_t show_atmaddress(struct class_device *cdev, char *buf) +{ + unsigned long flags; + char *pos = buf; + struct atm_dev *adev = to_atm_dev(cdev); + struct atm_dev_addr *aaddr; + int bin[] = { 1, 2, 10, 6, 1 }, *fmt = bin; + int i, j; + + spin_lock_irqsave(&adev->lock, flags); + list_for_each_entry(aaddr, &adev->local, entry) { + for(i = 0, j = 0; i < ATM_ESA_LEN; ++i, ++j) { + if (j == *fmt) { + pos += sprintf(pos, "."); + ++fmt; + j = 0; + } + pos += sprintf(pos, "%02x", aaddr->addr.sas_addr.prv[i]); + } + pos += sprintf(pos, "\n"); + } + spin_unlock_irqrestore(&adev->lock, flags); + + return pos - buf; +} + +static ssize_t show_carrier(struct class_device *cdev, char *buf) +{ + char *pos = buf; + struct atm_dev *adev = to_atm_dev(cdev); + + pos += sprintf(pos, "%d\n", + adev->signal == ATM_PHY_SIG_LOST ? 0 : 1); + + return pos - buf; +} + +static ssize_t show_link_rate(struct class_device *cdev, char *buf) +{ + char *pos = buf; + struct atm_dev *adev = to_atm_dev(cdev); + int link_rate; + + /* show the link rate, not the data rate */ + switch (adev->link_rate) { + case ATM_OC3_PCR: + link_rate = 155520000; + break; + case ATM_OC12_PCR: + link_rate = 622080000; + break; + case ATM_25_PCR: + link_rate = 25600000; + break; + default: + link_rate = adev->link_rate * 8 * 53; + } + pos += sprintf(pos, "%d\n", link_rate); + + return pos - buf; +} + +static CLASS_DEVICE_ATTR(address, S_IRUGO, show_address, NULL); +static CLASS_DEVICE_ATTR(atmaddress, S_IRUGO, show_atmaddress, NULL); +static CLASS_DEVICE_ATTR(carrier, S_IRUGO, show_carrier, NULL); +static CLASS_DEVICE_ATTR(type, S_IRUGO, show_type, NULL); +static CLASS_DEVICE_ATTR(link_rate, S_IRUGO, show_link_rate, NULL); + +static struct class_device_attribute *atm_attrs[] = { + &class_device_attr_atmaddress, + &class_device_attr_address, + &class_device_attr_carrier, + &class_device_attr_type, + &class_device_attr_link_rate, + NULL +}; + +static int atm_uevent(struct class_device *cdev, char **envp, int num_envp, char *buf, int size) +{ + struct atm_dev *adev; + int i = 0, len = 0; + + if (!cdev) + return -ENODEV; + + adev = to_atm_dev(cdev); + if (!adev) + return -ENODEV; + + if (add_uevent_var(envp, num_envp, &i, buf, size, &len, + "NAME=%s%d", adev->type, adev->number)) + return -ENOMEM; + + envp[i] = NULL; + return 0; +} + +static void atm_release(struct class_device *cdev) +{ + struct atm_dev *adev = to_atm_dev(cdev); + + kfree(adev); +} + +static struct class atm_class = { + .name = "atm", + .release = atm_release, + .uevent = atm_uevent, +}; + +int atm_register_sysfs(struct atm_dev *adev) +{ + struct class_device *cdev = &adev->class_dev; + int i, err; + + cdev->class = &atm_class; + class_set_devdata(cdev, adev); + + snprintf(cdev->class_id, BUS_ID_SIZE, "%s%d", adev->type, adev->number); + err = class_device_register(cdev); + if (err < 0) + return err; + + for (i = 0; atm_attrs[i]; i++) + class_device_create_file(cdev, atm_attrs[i]); + + return 0; +} + +void atm_unregister_sysfs(struct atm_dev *adev) +{ + struct class_device *cdev = &adev->class_dev; + + class_device_del(cdev); +} + +int __init atm_sysfs_init(void) +{ + return class_register(&atm_class); +} + +void __exit atm_sysfs_exit(void) +{ + class_unregister(&atm_class); +} diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c new file mode 100644 index 000000000..53086fb75 --- /dev/null +++ b/net/bridge/br_netlink.c @@ -0,0 +1,200 @@ +/* + * Bridge netlink control interface + * + * Authors: + * Stephen Hemminger <shemminger@osdl.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/rtnetlink.h> +#include "br_private.h" + +/* + * Create one netlink message for one interface + * Contains port and master info as well as carrier and bridge state. + */ +static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *port, + u32 pid, u32 seq, int event, unsigned int flags) +{ + const struct net_bridge *br = port->br; + const struct net_device *dev = port->dev; + struct ifinfomsg *r; + struct nlmsghdr *nlh; + unsigned char *b = skb->tail; + u32 mtu = dev->mtu; + u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN; + u8 portstate = port->state; + + pr_debug("br_fill_info event %d port %s master %s\n", + event, dev->name, br->dev->name); + + nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags); + r = NLMSG_DATA(nlh); + r->ifi_family = AF_BRIDGE; + r->__ifi_pad = 0; + r->ifi_type = dev->type; + r->ifi_index = dev->ifindex; + r->ifi_flags = dev_get_flags(dev); + r->ifi_change = 0; + + RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name); + + RTA_PUT(skb, IFLA_MASTER, sizeof(int), &br->dev->ifindex); + + if (dev->addr_len) + RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); + + RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu); + if (dev->ifindex != dev->iflink) + RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink); + + + RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate); + + if (event == RTM_NEWLINK) + RTA_PUT(skb, IFLA_PROTINFO, sizeof(portstate), &portstate); + + nlh->nlmsg_len = skb->tail - b; + + return skb->len; + +nlmsg_failure: +rtattr_failure: + + skb_trim(skb, b - skb->data); + return -EINVAL; +} + +/* + * Notify listeners of a change in port information + */ +void br_ifinfo_notify(int event, struct net_bridge_port *port) +{ + struct sk_buff *skb; + int err = -ENOMEM; + + pr_debug("bridge notify event=%d\n", event); + skb = alloc_skb(NLMSG_SPACE(sizeof(struct ifinfomsg) + 128), + GFP_ATOMIC); + if (!skb) + goto err_out; + + err = br_fill_ifinfo(skb, port, current->pid, 0, event, 0); + if (err < 0) + goto err_kfree; + + NETLINK_CB(skb).dst_group = RTNLGRP_LINK; + netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_ATOMIC); + return; + +err_kfree: + kfree_skb(skb); +err_out: + netlink_set_err(rtnl, 0, RTNLGRP_LINK, err); +} + +/* + * Dump information about all ports, in response to GETLINK + */ +static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) +{ + struct net_device *dev; + int idx; + int s_idx = cb->args[0]; + int err = 0; + + read_lock(&dev_base_lock); + for (dev = dev_base, idx = 0; dev; dev = dev->next) { + struct net_bridge_port *p = dev->br_port; + + /* not a bridge port */ + if (!p) + continue; + + if (idx < s_idx) + goto cont; + + err = br_fill_ifinfo(skb, p, NETLINK_CB(cb->skb).pid, + cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI); + if (err <= 0) + break; +cont: + ++idx; + } + read_unlock(&dev_base_lock); + + cb->args[0] = idx; + + return skb->len; +} + +/* + * Change state of port (ie from forwarding to blocking etc) + * Used by spanning tree in user space. + */ +static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) +{ + struct rtattr **rta = arg; + struct ifinfomsg *ifm = NLMSG_DATA(nlh); + struct net_device *dev; + struct net_bridge_port *p; + u8 new_state; + + if (ifm->ifi_family != AF_BRIDGE) + return -EPFNOSUPPORT; + + /* Must pass valid state as PROTINFO */ + if (rta[IFLA_PROTINFO-1]) { + u8 *pstate = RTA_DATA(rta[IFLA_PROTINFO-1]); + new_state = *pstate; + } else + return -EINVAL; + + if (new_state > BR_STATE_BLOCKING) + return -EINVAL; + + /* Find bridge port */ + dev = __dev_get_by_index(ifm->ifi_index); + if (!dev) + return -ENODEV; + + p = dev->br_port; + if (!p) + return -EINVAL; + + /* if kernel STP is running, don't allow changes */ + if (p->br->stp_enabled) + return -EBUSY; + + if (!netif_running(dev)) + return -ENETDOWN; + + if (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED) + return -ENETDOWN; + + p->state = new_state; + br_log_state(p); + return 0; +} + + +static struct rtnetlink_link bridge_rtnetlink_table[RTM_NR_MSGTYPES] = { + [RTM_GETLINK - RTM_BASE] = { .dumpit = br_dump_ifinfo, }, + [RTM_SETLINK - RTM_BASE] = { .doit = br_rtm_setlink, }, +}; + +void __init br_netlink_init(void) +{ + rtnetlink_links[PF_BRIDGE] = bridge_rtnetlink_table; +} + +void __exit br_netlink_fini(void) +{ + rtnetlink_links[PF_BRIDGE] = NULL; +} + diff --git a/net/core/netevent.c b/net/core/netevent.c new file mode 100644 index 000000000..35d02c385 --- /dev/null +++ b/net/core/netevent.c @@ -0,0 +1,69 @@ +/* + * Network event notifiers + * + * Authors: + * Tom Tucker <tom@opengridcomputing.com> + * Steve Wise <swise@opengridcomputing.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Fixes: + */ + +#include <linux/rtnetlink.h> +#include <linux/notifier.h> + +static ATOMIC_NOTIFIER_HEAD(netevent_notif_chain); + +/** + * register_netevent_notifier - register a netevent notifier block + * @nb: notifier + * + * Register a notifier to be called when a netevent occurs. + * The notifier passed is linked into the kernel structures and must + * not be reused until it has been unregistered. A negative errno code + * is returned on a failure. + */ +int register_netevent_notifier(struct notifier_block *nb) +{ + int err; + + err = atomic_notifier_chain_register(&netevent_notif_chain, nb); + return err; +} + +/** + * netevent_unregister_notifier - unregister a netevent notifier block + * @nb: notifier + * + * Unregister a notifier previously registered by + * register_neigh_notifier(). The notifier is unlinked into the + * kernel structures and may then be reused. A negative errno code + * is returned on a failure. + */ + +int unregister_netevent_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&netevent_notif_chain, nb); +} + +/** + * call_netevent_notifiers - call all netevent notifier blocks + * @val: value passed unmodified to notifier function + * @v: pointer passed unmodified to notifier function + * + * Call all neighbour notifier blocks. Parameters and return value + * are as for notifier_call_chain(). + */ + +int call_netevent_notifiers(unsigned long val, void *v) +{ + return atomic_notifier_call_chain(&netevent_notif_chain, val, v); +} + +EXPORT_SYMBOL_GPL(register_netevent_notifier); +EXPORT_SYMBOL_GPL(unregister_netevent_notifier); +EXPORT_SYMBOL_GPL(call_netevent_notifiers); diff --git a/net/core/user_dma.c b/net/core/user_dma.c new file mode 100644 index 000000000..248a6b666 --- /dev/null +++ b/net/core/user_dma.c @@ -0,0 +1,132 @@ +/* + * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved. + * Portions based on net/core/datagram.c and copyrighted by their authors. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + +/* + * This code allows the net stack to make use of a DMA engine for + * skb to iovec copies. + */ + +#include <linux/dmaengine.h> +#include <linux/socket.h> +#include <linux/rtnetlink.h> /* for BUG_TRAP */ +#include <net/tcp.h> +#include <net/netdma.h> + +#define NET_DMA_DEFAULT_COPYBREAK 4096 + +int sysctl_tcp_dma_copybreak = NET_DMA_DEFAULT_COPYBREAK; + +/** + * dma_skb_copy_datagram_iovec - Copy a datagram to an iovec. + * @skb - buffer to copy + * @offset - offset in the buffer to start copying from + * @iovec - io vector to copy to + * @len - amount of data to copy from buffer to iovec + * @pinned_list - locked iovec buffer data + * + * Note: the iovec is modified during the copy. + */ +int dma_skb_copy_datagram_iovec(struct dma_chan *chan, + struct sk_buff *skb, int offset, struct iovec *to, + size_t len, struct dma_pinned_list *pinned_list) +{ + int start = skb_headlen(skb); + int i, copy = start - offset; + dma_cookie_t cookie = 0; + + /* Copy header. */ + if (copy > 0) { + if (copy > len) + copy = len; + cookie = dma_memcpy_to_iovec(chan, to, pinned_list, + skb->data + offset, copy); + if (cookie < 0) + goto fault; + len -= copy; + if (len == 0) + goto end; + offset += copy; + } + + /* Copy paged appendix. Hmm... why does this look so complicated? */ + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + int end; + + BUG_TRAP(start <= offset + len); + + end = start + skb_shinfo(skb)->frags[i].size; + copy = end - offset; + if ((copy = end - offset) > 0) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + struct page *page = frag->page; + + if (copy > len) + copy = len; + + cookie = dma_memcpy_pg_to_iovec(chan, to, pinned_list, page, + frag->page_offset + offset - start, copy); + if (cookie < 0) + goto fault; + len -= copy; + if (len == 0) + goto end; + offset += copy; + } + start = end; + } + + if (skb_shinfo(skb)->frag_list) { + struct sk_buff *list = skb_shinfo(skb)->frag_list; + + for (; list; list = list->next) { + int end; + + BUG_TRAP(start <= offset + len); + + end = start + list->len; + copy = end - offset; + if (copy > 0) { + if (copy > len) + copy = len; + cookie = dma_skb_copy_datagram_iovec(chan, list, + offset - start, to, copy, + pinned_list); + if (cookie < 0) + goto fault; + len -= copy; + if (len == 0) + goto end; + offset += copy; + } + start = end; + } + } + +end: + if (!len) { + skb->dma_cookie = cookie; + return cookie; + } + +fault: + return -EFAULT; +} diff --git a/net/ipv4/netfilter/ip_conntrack_sip.c b/net/ipv4/netfilter/ip_conntrack_sip.c new file mode 100644 index 000000000..2893e9c74 --- /dev/null +++ b/net/ipv4/netfilter/ip_conntrack_sip.c @@ -0,0 +1,470 @@ +/* SIP extension for IP connection tracking. + * + * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar> + * based on RR's ip_conntrack_ftp.c and other modules. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/ctype.h> +#include <linux/skbuff.h> +#include <linux/in.h> +#include <linux/ip.h> +#include <linux/udp.h> + +#include <linux/netfilter.h> +#include <linux/netfilter_ipv4.h> +#include <linux/netfilter_ipv4/ip_conntrack_helper.h> +#include <linux/netfilter_ipv4/ip_conntrack_sip.h> + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(format, args...) +#endif + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>"); +MODULE_DESCRIPTION("SIP connection tracking helper"); + +#define MAX_PORTS 8 +static unsigned short ports[MAX_PORTS]; +static int ports_c; +module_param_array(ports, ushort, &ports_c, 0400); +MODULE_PARM_DESC(ports, "port numbers of sip servers"); + +static unsigned int sip_timeout = SIP_TIMEOUT; +module_param(sip_timeout, uint, 0600); +MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session"); + +unsigned int (*ip_nat_sip_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct ip_conntrack *ct, + const char **dptr); +EXPORT_SYMBOL_GPL(ip_nat_sip_hook); + +unsigned int (*ip_nat_sdp_hook)(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct ip_conntrack_expect *exp, + const char *dptr); +EXPORT_SYMBOL_GPL(ip_nat_sdp_hook); + +int ct_sip_get_info(const char *dptr, size_t dlen, + unsigned int *matchoff, + unsigned int *matchlen, + struct sip_header_nfo *hnfo); +EXPORT_SYMBOL_GPL(ct_sip_get_info); + + +static int digits_len(const char *dptr, const char *limit, int *shift); +static int epaddr_len(const char *dptr, const char *limit, int *shift); +static int skp_digits_len(const char *dptr, const char *limit, int *shift); +static int skp_epaddr_len(const char *dptr, const char *limit, int *shift); + +struct sip_header_nfo ct_sip_hdrs[] = { + { /* Via header */ + .lname = "Via:", + .lnlen = sizeof("Via:") - 1, + .sname = "\r\nv:", + .snlen = sizeof("\r\nv:") - 1, /* rfc3261 "\r\n" */ + .ln_str = "UDP ", + .ln_strlen = sizeof("UDP ") - 1, + .match_len = epaddr_len, + }, + { /* Contact header */ + .lname = "Contact:", + .lnlen = sizeof("Contact:") - 1, + .sname = "\r\nm:", + .snlen = sizeof("\r\nm:") - 1, + .ln_str = "sip:", + .ln_strlen = sizeof("sip:") - 1, + .match_len = skp_epaddr_len + }, + { /* Content length header */ + .lname = "Content-Length:", + .lnlen = sizeof("Content-Length:") - 1, + .sname = "\r\nl:", + .snlen = sizeof("\r\nl:") - 1, + .ln_str = ":", + .ln_strlen = sizeof(":") - 1, + .match_len = skp_digits_len + }, + { /* SDP media info */ + .lname = "\nm=", + .lnlen = sizeof("\nm=") - 1, + .sname = "\rm=", + .snlen = sizeof("\rm=") - 1, + .ln_str = "audio ", + .ln_strlen = sizeof("audio ") - 1, + .match_len = digits_len + }, + { /* SDP owner address*/ + .lname = "\no=", + .lnlen = sizeof("\no=") - 1, + .sname = "\ro=", + .snlen = sizeof("\ro=") - 1, + .ln_str = "IN IP4 ", + .ln_strlen = sizeof("IN IP4 ") - 1, + .match_len = epaddr_len + }, + { /* SDP connection info */ + .lname = "\nc=", + .lnlen = sizeof("\nc=") - 1, + .sname = "\rc=", + .snlen = sizeof("\rc=") - 1, + .ln_str = "IN IP4 ", + .ln_strlen = sizeof("IN IP4 ") - 1, + .match_len = epaddr_len + }, + { /* Requests headers */ + .lname = "sip:", + .lnlen = sizeof("sip:") - 1, + .sname = "sip:", + .snlen = sizeof("sip:") - 1, /* yes, i know.. ;) */ + .ln_str = "@", + .ln_strlen = sizeof("@") - 1, + .match_len = epaddr_len + }, + { /* SDP version header */ + .lname = "\nv=", + .lnlen = sizeof("\nv=") - 1, + .sname = "\rv=", + .snlen = sizeof("\rv=") - 1, + .ln_str = "=", + .ln_strlen = sizeof("=") - 1, + .match_len = digits_len + } +}; +EXPORT_SYMBOL_GPL(ct_sip_hdrs); + +/* get line lenght until first CR or LF seen. */ +int ct_sip_lnlen(const char *line, const char *limit) +{ + const char *k = line; + + while ((line <= limit) && (*line == '\r' || *line == '\n')) + line++; + + while (line <= limit) { + if (*line == '\r' || *line == '\n') + break; + line++; + } + return line - k; +} +EXPORT_SYMBOL_GPL(ct_sip_lnlen); + +/* Linear string search, case sensitive. */ +const char *ct_sip_search(const char *needle, const char *haystack, + size_t needle_len, size_t haystack_len) +{ + const char *limit = haystack + (haystack_len - needle_len); + + while (haystack <= limit) { + if (memcmp(haystack, needle, needle_len) == 0) + return haystack; + haystack++; + } + return NULL; +} +EXPORT_SYMBOL_GPL(ct_sip_search); + +static int digits_len(const char *dptr, const char *limit, int *shift) +{ + int len = 0; + while (dptr <= limit && isdigit(*dptr)) { + dptr++; + len++; + } + return len; +} + +/* get digits lenght, skiping blank spaces. */ +static int skp_digits_len(const char *dptr, const char *limit, int *shift) +{ + for (; dptr <= limit && *dptr == ' '; dptr++) + (*shift)++; + + return digits_len(dptr, limit, shift); +} + +/* Simple ipaddr parser.. */ +static int parse_ipaddr(const char *cp, const char **endp, + u_int32_t *ipaddr, const char *limit) +{ + unsigned long int val; + int i, digit = 0; + + for (i = 0, *ipaddr = 0; cp <= limit && i < 4; i++) { + digit = 0; + if (!isdigit(*cp)) + break; + + val = simple_strtoul(cp, (char **)&cp, 10); + if (val > 0xFF) + return -1; + + ((u_int8_t *)ipaddr)[i] = val; + digit = 1; + + if (*cp != '.') + break; + cp++; + } + if (!digit) + return -1; + + if (endp) + *endp = cp; + + return 0; +} + +/* skip ip address. returns it lenght. */ +static int epaddr_len(const char *dptr, const char *limit, int *shift) +{ + const char *aux = dptr; + u_int32_t ip; + + if (parse_ipaddr(dptr, &dptr, &ip, limit) < 0) { + DEBUGP("ip: %s parse failed.!\n", dptr); + return 0; + } + + /* Port number */ + if (*dptr == ':') { + dptr++; + dptr += digits_len(dptr, limit, shift); + } + return dptr - aux; +} + +/* get address length, skiping user info. */ +static int skp_epaddr_len(const char *dptr, const char *limit, int *shift) +{ + int s = *shift; + + for (; dptr <= limit && *dptr != '@'; dptr++) + (*shift)++; + + if (*dptr == '@') { + dptr++; + (*shift)++; + } else + *shift = s; + + return epaddr_len(dptr, limit, shift); +} + +/* Returns 0 if not found, -1 error parsing. */ +int ct_sip_get_info(const char *dptr, size_t dlen, + unsigned int *matchoff, + unsigned int *matchlen, + struct sip_header_nfo *hnfo) +{ + const char *limit, *aux, *k = dptr; + int shift = 0; + + limit = dptr + (dlen - hnfo->lnlen); + + while (dptr <= limit) { + if ((strncmp(dptr, hnfo->lname, hnfo->lnlen) != 0) && + (strncmp(dptr, hnfo->sname, hnfo->snlen) != 0)) { + dptr++; + continue; + } + aux = ct_sip_search(hnfo->ln_str, dptr, hnfo->ln_strlen, + ct_sip_lnlen(dptr, limit)); + if (!aux) { + DEBUGP("'%s' not found in '%s'.\n", hnfo->ln_str, + hnfo->lname); + return -1; + } + aux += hnfo->ln_strlen; + + *matchlen = hnfo->match_len(aux, limit, &shift); + if (!*matchlen) + return -1; + + *matchoff = (aux - k) + shift; + + DEBUGP("%s match succeeded! - len: %u\n", hnfo->lname, + *matchlen); + return 1; + } + DEBUGP("%s header not found.\n", hnfo->lname); + return 0; +} + +static int set_expected_rtp(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo, + u_int32_t ipaddr, u_int16_t port, + const char *dptr) +{ + struct ip_conntrack_expect *exp; + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); + int ret; + + exp = ip_conntrack_expect_alloc(ct); + if (exp == NULL) + return NF_DROP; + + exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip; + exp->tuple.src.u.udp.port = 0; + exp->tuple.dst.ip = ipaddr; + exp->tuple.dst.u.udp.port = htons(port); + exp->tuple.dst.protonum = IPPROTO_UDP; + + exp->mask.src.ip = 0xFFFFFFFF; + exp->mask.src.u.udp.port = 0; + exp->mask.dst.ip = 0xFFFFFFFF; + exp->mask.dst.u.udp.port = 0xFFFF; + exp->mask.dst.protonum = 0xFF; + + exp->expectfn = NULL; + exp->flags = 0; + + if (ip_nat_sdp_hook) + ret = ip_nat_sdp_hook(pskb, ctinfo, exp, dptr); + else { + if (ip_conntrack_expect_related(exp) != 0) + ret = NF_DROP; + else + ret = NF_ACCEPT; + } + ip_conntrack_expect_put(exp); + + return ret; +} + +static int sip_help(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo) +{ + unsigned int dataoff, datalen; + const char *dptr; + int ret = NF_ACCEPT; + int matchoff, matchlen; + u_int32_t ipaddr; + u_int16_t port; + + /* No Data ? */ + dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); + if (dataoff >= (*pskb)->len) { + DEBUGP("skb->len = %u\n", (*pskb)->len); + return NF_ACCEPT; + } + + ip_ct_refresh(ct, *pskb, sip_timeout * HZ); + + if (!skb_is_nonlinear(*pskb)) + dptr = (*pskb)->data + dataoff; + else { + DEBUGP("Copy of skbuff not supported yet.\n"); + goto out; + } + + if (ip_nat_sip_hook) { + if (!ip_nat_sip_hook(pskb, ctinfo, ct, &dptr)) { + ret = NF_DROP; + goto out; + } + } + + /* After this point NAT, could have mangled skb, so + we need to recalculate payload lenght. */ + datalen = (*pskb)->len - dataoff; + + if (datalen < (sizeof("SIP/2.0 200") - 1)) + goto out; + + /* RTP info only in some SDP pkts */ + if (memcmp(dptr, "INVITE", sizeof("INVITE") - 1) != 0 && + memcmp(dptr, "SIP/2.0 200", sizeof("SIP/2.0 200") - 1) != 0) { + goto out; + } + /* Get ip and port address from SDP packet. */ + if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen, + &ct_sip_hdrs[POS_CONNECTION]) > 0) { + + /* We'll drop only if there are parse problems. */ + if (parse_ipaddr(dptr + matchoff, NULL, &ipaddr, + dptr + datalen) < 0) { + ret = NF_DROP; + goto out; + } + if (ct_sip_get_info(dptr, datalen, &matchoff, &matchlen, + &ct_sip_hdrs[POS_MEDIA]) > 0) { + + port = simple_strtoul(dptr + matchoff, NULL, 10); + if (port < 1024) { + ret = NF_DROP; + goto out; + } + ret = set_expected_rtp(pskb, ct, ctinfo, + ipaddr, port, dptr); + } + } +out: + return ret; +} + +static struct ip_conntrack_helper sip[MAX_PORTS]; +static char sip_names[MAX_PORTS][10]; + +static void fini(void) +{ + int i; + for (i = 0; i < ports_c; i++) { + DEBUGP("unregistering helper for port %d\n", ports[i]); + ip_conntrack_helper_unregister(&sip[i]); + } +} + +static int __init init(void) +{ + int i, ret; + char *tmpname; + + if (ports_c == 0) + ports[ports_c++] = SIP_PORT; + + for (i = 0; i < ports_c; i++) { + /* Create helper structure */ + memset(&sip[i], 0, sizeof(struct ip_conntrack_helper)); + + sip[i].tuple.dst.protonum = IPPROTO_UDP; + sip[i].tuple.src.u.udp.port = htons(ports[i]); + sip[i].mask.src.u.udp.port = 0xFFFF; + sip[i].mask.dst.protonum = 0xFF; + sip[i].max_expected = 2; + sip[i].timeout = 3 * 60; /* 3 minutes */ + sip[i].me = THIS_MODULE; + sip[i].help = sip_help; + + tmpname = &sip_names[i][0]; + if (ports[i] == SIP_PORT) + sprintf(tmpname, "sip"); + else + sprintf(tmpname, "sip-%d", i); + sip[i].name = tmpname; + + DEBUGP("port #%d: %d\n", i, ports[i]); + + ret = ip_conntrack_helper_register(&sip[i]); + if (ret) { + printk("ERROR registering helper for port %d\n", + ports[i]); + fini(); + return ret; + } + } + return 0; +} + +module_init(init); +module_exit(fini); diff --git a/net/ipv4/netfilter/ip_nat_sip.c b/net/ipv4/netfilter/ip_nat_sip.c new file mode 100644 index 000000000..6ffba63ad --- /dev/null +++ b/net/ipv4/netfilter/ip_nat_sip.c @@ -0,0 +1,249 @@ +/* SIP extension for UDP NAT alteration. + * + * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar> + * based on RR's ip_nat_ftp.c and other modules. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/ip.h> +#include <linux/udp.h> + +#include <linux/netfilter_ipv4.h> +#include <linux/netfilter_ipv4/ip_nat.h> +#include <linux/netfilter_ipv4/ip_nat_helper.h> +#include <linux/netfilter_ipv4/ip_conntrack_helper.h> +#include <linux/netfilter_ipv4/ip_conntrack_sip.h> + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>"); +MODULE_DESCRIPTION("SIP NAT helper"); + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(format, args...) +#endif + +extern struct sip_header_nfo ct_sip_hdrs[]; + +static unsigned int mangle_sip_packet(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct ip_conntrack *ct, + const char **dptr, size_t dlen, + char *buffer, int bufflen, + struct sip_header_nfo *hnfo) +{ + unsigned int matchlen, matchoff; + + if (ct_sip_get_info(*dptr, dlen, &matchoff, &matchlen, hnfo) <= 0) + return 0; + + if (!ip_nat_mangle_udp_packet(pskb, ct, ctinfo, + matchoff, matchlen, buffer, bufflen)) + return 0; + + /* We need to reload this. Thanks Patrick. */ + *dptr = (*pskb)->data + (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); + return 1; +} + +static unsigned int ip_nat_sip(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct ip_conntrack *ct, + const char **dptr) +{ + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); + char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; + unsigned int bufflen, dataoff; + u_int32_t ip; + u_int16_t port; + + dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); + + ip = ct->tuplehash[!dir].tuple.dst.ip; + port = ct->tuplehash[!dir].tuple.dst.u.udp.port; + bufflen = sprintf(buffer, "%u.%u.%u.%u:%u", NIPQUAD(ip), ntohs(port)); + + /* short packet ? */ + if (((*pskb)->len - dataoff) < (sizeof("SIP/2.0") - 1)) + return 0; + + /* Basic rules: requests and responses. */ + if (memcmp(*dptr, "SIP/2.0", sizeof("SIP/2.0") - 1) == 0) { + const char *aux; + + if ((ctinfo) < IP_CT_IS_REPLY) { + mangle_sip_packet(pskb, ctinfo, ct, dptr, + (*pskb)->len - dataoff, + buffer, bufflen, + &ct_sip_hdrs[POS_CONTACT]); + return 1; + } + + if (!mangle_sip_packet(pskb, ctinfo, ct, dptr, + (*pskb)->len - dataoff, + buffer, bufflen, &ct_sip_hdrs[POS_VIA])) + return 0; + + /* This search should ignore case, but later.. */ + aux = ct_sip_search("CSeq:", *dptr, sizeof("CSeq:") - 1, + (*pskb)->len - dataoff); + if (!aux) + return 0; + + if (!ct_sip_search("REGISTER", aux, sizeof("REGISTER"), + ct_sip_lnlen(aux, *dptr + (*pskb)->len - dataoff))) + return 1; + + return mangle_sip_packet(pskb, ctinfo, ct, dptr, + (*pskb)->len - dataoff, + buffer, bufflen, + &ct_sip_hdrs[POS_CONTACT]); + } + if ((ctinfo) < IP_CT_IS_REPLY) { + if (!mangle_sip_packet(pskb, ctinfo, ct, dptr, + (*pskb)->len - dataoff, + buffer, bufflen, &ct_sip_hdrs[POS_VIA])) + return 0; + + /* Mangle Contact if exists only. - watch udp_nat_mangle()! */ + mangle_sip_packet(pskb, ctinfo, ct, dptr, (*pskb)->len - dataoff, + buffer, bufflen, &ct_sip_hdrs[POS_CONTACT]); + return 1; + } + /* This mangle requests headers. */ + return mangle_sip_packet(pskb, ctinfo, ct, dptr, + ct_sip_lnlen(*dptr, + *dptr + (*pskb)->len - dataoff), + buffer, bufflen, &ct_sip_hdrs[POS_REQ_HEADER]); +} + +static int mangle_content_len(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct ip_conntrack *ct, + const char *dptr) +{ + unsigned int dataoff, matchoff, matchlen; + char buffer[sizeof("65536")]; + int bufflen; + + dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); + + /* Get actual SDP lenght */ + if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff, + &matchlen, &ct_sip_hdrs[POS_SDP_HEADER]) > 0) { + + /* since ct_sip_get_info() give us a pointer passing 'v=' + we need to add 2 bytes in this count. */ + int c_len = (*pskb)->len - dataoff - matchoff + 2; + + /* Now, update SDP lenght */ + if (ct_sip_get_info(dptr, (*pskb)->len - dataoff, &matchoff, + &matchlen, &ct_sip_hdrs[POS_CONTENT]) > 0) { + + bufflen = sprintf(buffer, "%u", c_len); + + return ip_nat_mangle_udp_packet(pskb, ct, ctinfo, + matchoff, matchlen, + buffer, bufflen); + } + } + return 0; +} + +static unsigned int mangle_sdp(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct ip_conntrack *ct, + u_int32_t newip, u_int16_t port, + const char *dptr) +{ + char buffer[sizeof("nnn.nnn.nnn.nnn")]; + unsigned int dataoff, bufflen; + + dataoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct udphdr); + + /* Mangle owner and contact info. */ + bufflen = sprintf(buffer, "%u.%u.%u.%u", NIPQUAD(newip)); + if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, + buffer, bufflen, &ct_sip_hdrs[POS_OWNER])) + return 0; + + if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, + buffer, bufflen, &ct_sip_hdrs[POS_CONNECTION])) + return 0; + + /* Mangle media port. */ + bufflen = sprintf(buffer, "%u", port); + if (!mangle_sip_packet(pskb, ctinfo, ct, &dptr, (*pskb)->len - dataoff, + buffer, bufflen, &ct_sip_hdrs[POS_MEDIA])) + return 0; + + return mangle_content_len(pskb, ctinfo, ct, dptr); +} + +/* So, this packet has hit the connection tracking matching code. + Mangle it, and change the expectation to match the new version. */ +static unsigned int ip_nat_sdp(struct sk_buff **pskb, + enum ip_conntrack_info ctinfo, + struct ip_conntrack_expect *exp, + const char *dptr) +{ + struct ip_conntrack *ct = exp->master; + enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); + u_int32_t newip; + u_int16_t port; + + DEBUGP("ip_nat_sdp():\n"); + + /* Connection will come from reply */ + newip = ct->tuplehash[!dir].tuple.dst.ip; + + exp->tuple.dst.ip = newip; + exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port; + exp->dir = !dir; + + /* When you see the packet, we need to NAT it the same as the + this one. */ + exp->expectfn = ip_nat_follow_master; + + /* Try to get same port: if not, try to change it. */ + for (port = ntohs(exp->saved_proto.udp.port); port != 0; port++) { + exp->tuple.dst.u.udp.port = htons(port); + if (ip_conntrack_expect_related(exp) == 0) + break; + } + + if (port == 0) + return NF_DROP; + + if (!mangle_sdp(pskb, ctinfo, ct, newip, port, dptr)) { + ip_conntrack_unexpect_related(exp); + return NF_DROP; + } + return NF_ACCEPT; +} + +static void __exit fini(void) +{ + ip_nat_sip_hook = NULL; + ip_nat_sdp_hook = NULL; + /* Make sure noone calls it, meanwhile. */ + synchronize_net(); +} + +static int __init init(void) +{ + BUG_ON(ip_nat_sip_hook); + BUG_ON(ip_nat_sdp_hook); + ip_nat_sip_hook = ip_nat_sip; + ip_nat_sdp_hook = ip_nat_sdp; + return 0; +} + +module_init(init); +module_exit(fini); diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c new file mode 100644 index 000000000..649ebaed1 --- /dev/null +++ b/net/ipv4/tcp_lp.c @@ -0,0 +1,344 @@ +/* + * TCP Low Priority (TCP-LP) + * + * TCP Low Priority is a distributed algorithm whose goal is to utilize only + * the excess network bandwidth as compared to the ``fair share`` of + * bandwidth as targeted by TCP. + * + * As of 2.6.13, Linux supports pluggable congestion control algorithms. + * Due to the limitation of the API, we take the following changes from + * the original TCP-LP implementation: + * o We use newReno in most core CA handling. Only add some checking + * within cong_avoid. + * o Error correcting in remote HZ, therefore remote HZ will be keeped + * on checking and updating. + * o Handling calculation of One-Way-Delay (OWD) within rtt_sample, sicne + * OWD have a similar meaning as RTT. Also correct the buggy formular. + * o Handle reaction for Early Congestion Indication (ECI) within + * pkts_acked, as mentioned within pseudo code. + * o OWD is handled in relative format, where local time stamp will in + * tcp_time_stamp format. + * + * Original Author: + * Aleksandar Kuzmanovic <akuzma@northwestern.edu> + * Available from: + * http://www.ece.rice.edu/~akuzma/Doc/akuzma/TCP-LP.pdf + * Original implementation for 2.4.19: + * http://www-ece.rice.edu/networks/TCP-LP/ + * + * 2.6.x module Authors: + * Wong Hoi Sing, Edison <hswong3i@gmail.com> + * Hung Hing Lun, Mike <hlhung3i@gmail.com> + * SourceForge project page: + * http://tcp-lp-mod.sourceforge.net/ + * + * Version: $Id: tcp_lp.c,v 1.24 2006/09/05 20:22:53 hswong3i Exp $ + */ + +#include <linux/module.h> +#include <net/tcp.h> + +/* resolution of owd */ +#define LP_RESOL 1000 + +/** + * enum tcp_lp_state + * @LP_VALID_RHZ: is remote HZ valid? + * @LP_VALID_OWD: is OWD valid? + * @LP_WITHIN_THR: are we within threshold? + * @LP_WITHIN_INF: are we within inference? + * + * TCP-LP's state flags. + * We create this set of state flag mainly for debugging. + */ +enum tcp_lp_state { + LP_VALID_RHZ = (1 << 0), + LP_VALID_OWD = (1 << 1), + LP_WITHIN_THR = (1 << 3), + LP_WITHIN_INF = (1 << 4), +}; + +/** + * struct lp + * @flag: TCP-LP state flag + * @sowd: smoothed OWD << 3 + * @owd_min: min OWD + * @owd_max: max OWD + * @owd_max_rsv: resrved max owd + * @remote_hz: estimated remote HZ + * @remote_ref_time: remote reference time + * @local_ref_time: local reference time + * @last_drop: time for last active drop + * @inference: current inference + * + * TCP-LP's private struct. + * We get the idea from original TCP-LP implementation where only left those we + * found are really useful. + */ +struct lp { + u32 flag; + u32 sowd; + u32 owd_min; + u32 owd_max; + u32 owd_max_rsv; + u32 remote_hz; + u32 remote_ref_time; + u32 local_ref_time; + u32 last_drop; + u32 inference; +}; + +/** + * tcp_lp_init + * + * Init all required variables. + * Clone the handling from Vegas module implementation. + */ +static void tcp_lp_init(struct sock *sk) +{ + struct lp *lp = inet_csk_ca(sk); + + lp->flag = 0; + lp->sowd = 0; + lp->owd_min = 0xffffffff; + lp->owd_max = 0; + lp->owd_max_rsv = 0; + lp->remote_hz = 0; + lp->remote_ref_time = 0; + lp->local_ref_time = 0; + lp->last_drop = 0; + lp->inference = 0; +} + +/** + * tcp_lp_cong_avoid + * + * Implementation of cong_avoid. + * Will only call newReno CA when away from inference. + * From TCP-LP's paper, this will be handled in additive increasement. + */ +static void tcp_lp_cong_avoid(struct sock *sk, u32 ack, u32 rtt, u32 in_flight, + int flag) +{ + struct lp *lp = inet_csk_ca(sk); + + if (!(lp->flag & LP_WITHIN_INF)) + tcp_reno_cong_avoid(sk, ack, rtt, in_flight, flag); +} + +/** + * tcp_lp_remote_hz_estimator + * + * Estimate remote HZ. + * We keep on updating the estimated value, where original TCP-LP + * implementation only guest it for once and use forever. + */ +static u32 tcp_lp_remote_hz_estimator(struct sock *sk) +{ + struct tcp_sock *tp = tcp_sk(sk); + struct lp *lp = inet_csk_ca(sk); + s64 rhz = lp->remote_hz << 6; /* remote HZ << 6 */ + s64 m = 0; + + /* not yet record reference time + * go away!! record it before come back!! */ + if (lp->remote_ref_time == 0 || lp->local_ref_time == 0) + goto out; + + /* we can't calc remote HZ with no different!! */ + if (tp->rx_opt.rcv_tsval == lp->remote_ref_time + || tp->rx_opt.rcv_tsecr == lp->local_ref_time) + goto out; + + m = HZ * (tp->rx_opt.rcv_tsval - + lp->remote_ref_time) / (tp->rx_opt.rcv_tsecr - + lp->local_ref_time); + if (m < 0) + m = -m; + + if (rhz > 0) { + m -= rhz >> 6; /* m is now error in remote HZ est */ + rhz += m; /* 63/64 old + 1/64 new */ + } else + rhz = m << 6; + + out: + /* record time for successful remote HZ calc */ + if (rhz > 0) + lp->flag |= LP_VALID_RHZ; + else + lp->flag &= ~LP_VALID_RHZ; + + /* record reference time stamp */ + lp->remote_ref_time = tp->rx_opt.rcv_tsval; + lp->local_ref_time = tp->rx_opt.rcv_tsecr; + + return rhz >> 6; +} + +/** + * tcp_lp_owd_calculator + * + * Calculate one way delay (in relative format). + * Original implement OWD as minus of remote time difference to local time + * difference directly. As this time difference just simply equal to RTT, when + * the network status is stable, remote RTT will equal to local RTT, and result + * OWD into zero. + * It seems to be a bug and so we fixed it. + */ +static u32 tcp_lp_owd_calculator(struct sock *sk) +{ + struct tcp_sock *tp = tcp_sk(sk); + struct lp *lp = inet_csk_ca(sk); + s64 owd = 0; + + lp->remote_hz = tcp_lp_remote_hz_estimator(sk); + + if (lp->flag & LP_VALID_RHZ) { + owd = + tp->rx_opt.rcv_tsval * (LP_RESOL / lp->remote_hz) - + tp->rx_opt.rcv_tsecr * (LP_RESOL / HZ); + if (owd < 0) + owd = -owd; + } + + if (owd > 0) + lp->flag |= LP_VALID_OWD; + else + lp->flag &= ~LP_VALID_OWD; + + return owd; +} + +/** + * tcp_lp_rtt_sample + * + * Implementation or rtt_sample. + * Will take the following action, + * 1. calc OWD, + * 2. record the min/max OWD, + * 3. calc smoothed OWD (SOWD). + * Most ideas come from the original TCP-LP implementation. + */ +static void tcp_lp_rtt_sample(struct sock *sk, u32 usrtt) +{ + struct lp *lp = inet_csk_ca(sk); + s64 mowd = tcp_lp_owd_calculator(sk); + + /* sorry that we don't have valid data */ + if (!(lp->flag & LP_VALID_RHZ) || !(lp->flag & LP_VALID_OWD)) + return; + + /* record the next min owd */ + if (mowd < lp->owd_min) + lp->owd_min = mowd; + + /* always forget the max of the max + * we just set owd_max as one below it */ + if (mowd > lp->owd_max) { + if (mowd > lp->owd_max_rsv) { + if (lp->owd_max_rsv == 0) + lp->owd_max = mowd; + else + lp->owd_max = lp->owd_max_rsv; + lp->owd_max_rsv = mowd; + } else + lp->owd_max = mowd; + } + + /* calc for smoothed owd */ + if (lp->sowd != 0) { + mowd -= lp->sowd >> 3; /* m is now error in owd est */ + lp->sowd += mowd; /* owd = 7/8 owd + 1/8 new */ + } else + lp->sowd = mowd << 3; /* take the measured time be owd */ +} + +/** + * tcp_lp_pkts_acked + * + * Implementation of pkts_acked. + * Deal with active drop under Early Congestion Indication. + * Only drop to half and 1 will be handle, because we hope to use back + * newReno in increase case. + * We work it out by following the idea from TCP-LP's paper directly + */ +static void tcp_lp_pkts_acked(struct sock *sk, u32 num_acked) +{ + struct tcp_sock *tp = tcp_sk(sk); + struct lp *lp = inet_csk_ca(sk); + + /* calc inference */ + if (tcp_time_stamp > tp->rx_opt.rcv_tsecr) + lp->inference = 3 * (tcp_time_stamp - tp->rx_opt.rcv_tsecr); + + /* test if within inference */ + if (lp->last_drop && (tcp_time_stamp - lp->last_drop < lp->inference)) + lp->flag |= LP_WITHIN_INF; + else + lp->flag &= ~LP_WITHIN_INF; + + /* test if within threshold */ + if (lp->sowd >> 3 < + lp->owd_min + 15 * (lp->owd_max - lp->owd_min) / 100) + lp->flag |= LP_WITHIN_THR; + else + lp->flag &= ~LP_WITHIN_THR; + + pr_debug("TCP-LP: %05o|%5u|%5u|%15u|%15u|%15u\n", lp->flag, + tp->snd_cwnd, lp->remote_hz, lp->owd_min, lp->owd_max, + lp->sowd >> 3); + + if (lp->flag & LP_WITHIN_THR) + return; + + /* FIXME: try to reset owd_min and owd_max here + * so decrease the chance the min/max is no longer suitable + * and will usually within threshold when whithin inference */ + lp->owd_min = lp->sowd >> 3; + lp->owd_max = lp->sowd >> 2; + lp->owd_max_rsv = lp->sowd >> 2; + + /* happened within inference + * drop snd_cwnd into 1 */ + if (lp->flag & LP_WITHIN_INF) + tp->snd_cwnd = 1U; + + /* happened after inference + * cut snd_cwnd into half */ + else + tp->snd_cwnd = max(tp->snd_cwnd >> 1U, 1U); + + /* record this drop time */ + lp->last_drop = tcp_time_stamp; +} + +static struct tcp_congestion_ops tcp_lp = { + .init = tcp_lp_init, + .ssthresh = tcp_reno_ssthresh, + .cong_avoid = tcp_lp_cong_avoid, + .min_cwnd = tcp_reno_min_cwnd, + .rtt_sample = tcp_lp_rtt_sample, + .pkts_acked = tcp_lp_pkts_acked, + + .owner = THIS_MODULE, + .name = "lp" +}; + +static int __init tcp_lp_register(void) +{ + BUG_ON(sizeof(struct lp) > ICSK_CA_PRIV_SIZE); + return tcp_register_congestion_control(&tcp_lp); +} + +static void __exit tcp_lp_unregister(void) +{ + tcp_unregister_congestion_control(&tcp_lp); +} + +module_init(tcp_lp_register); +module_exit(tcp_lp_unregister); + +MODULE_AUTHOR("Wong Hoi Sing Edison, Hung Hing Lun Mike"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("TCP Low Priority"); diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c new file mode 100644 index 000000000..dab37d2f6 --- /dev/null +++ b/net/ipv4/tcp_probe.c @@ -0,0 +1,182 @@ +/* + * tcpprobe - Observe the TCP flow with kprobes. + * + * The idea for this came from Werner Almesberger's umlsim + * Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/kernel.h> +#include <linux/kprobes.h> +#include <linux/socket.h> +#include <linux/tcp.h> +#include <linux/proc_fs.h> +#include <linux/module.h> +#include <linux/kfifo.h> +#include <linux/vmalloc.h> + +#include <net/tcp.h> + +MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>"); +MODULE_DESCRIPTION("TCP cwnd snooper"); +MODULE_LICENSE("GPL"); + +static int port = 0; +MODULE_PARM_DESC(port, "Port to match (0=all)"); +module_param(port, int, 0); + +static int bufsize = 64*1024; +MODULE_PARM_DESC(bufsize, "Log buffer size (default 64k)"); +module_param(bufsize, int, 0); + +static const char procname[] = "tcpprobe"; + +struct { + struct kfifo *fifo; + spinlock_t lock; + wait_queue_head_t wait; + struct timeval tstart; +} tcpw; + +static void printl(const char *fmt, ...) +{ + va_list args; + int len; + struct timeval now; + char tbuf[256]; + + va_start(args, fmt); + do_gettimeofday(&now); + + now.tv_sec -= tcpw.tstart.tv_sec; + now.tv_usec -= tcpw.tstart.tv_usec; + if (now.tv_usec < 0) { + --now.tv_sec; + now.tv_usec += 1000000; + } + + len = sprintf(tbuf, "%lu.%06lu ", + (unsigned long) now.tv_sec, + (unsigned long) now.tv_usec); + len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args); + va_end(args); + + kfifo_put(tcpw.fifo, tbuf, len); + wake_up(&tcpw.wait); +} + +static int jtcp_sendmsg(struct kiocb *iocb, struct sock *sk, + struct msghdr *msg, size_t size) +{ + const struct tcp_sock *tp = tcp_sk(sk); + const struct inet_sock *inet = inet_sk(sk); + + if (port == 0 || ntohs(inet->dport) == port || + ntohs(inet->sport) == port) { + printl("%d.%d.%d.%d:%u %d.%d.%d.%d:%u %d %#x %#x %u %u %u\n", + NIPQUAD(inet->saddr), ntohs(inet->sport), + NIPQUAD(inet->daddr), ntohs(inet->dport), + size, tp->snd_nxt, tp->snd_una, + tp->snd_cwnd, tcp_current_ssthresh(sk), + tp->snd_wnd); + } + + jprobe_return(); + return 0; +} + +static struct jprobe tcp_send_probe = { + .kp = { .addr = (kprobe_opcode_t *) &tcp_sendmsg, }, + .entry = (kprobe_opcode_t *) &jtcp_sendmsg, +}; + + +static int tcpprobe_open(struct inode * inode, struct file * file) +{ + kfifo_reset(tcpw.fifo); + do_gettimeofday(&tcpw.tstart); + return 0; +} + +static ssize_t tcpprobe_read(struct file *file, char __user *buf, + size_t len, loff_t *ppos) +{ + int error = 0, cnt = 0; + unsigned char *tbuf; + + if (!buf || len < 0) + return -EINVAL; + + if (len == 0) + return 0; + + tbuf = vmalloc(len); + if (!tbuf) + return -ENOMEM; + + error = wait_event_interruptible(tcpw.wait, + __kfifo_len(tcpw.fifo) != 0); + if (error) + goto out_free; + + cnt = kfifo_get(tcpw.fifo, tbuf, len); + error = copy_to_user(buf, tbuf, cnt); + +out_free: + vfree(tbuf); + + return error ? error : cnt; +} + +static struct file_operations tcpprobe_fops = { + .owner = THIS_MODULE, + .open = tcpprobe_open, + .read = tcpprobe_read, +}; + +static __init int tcpprobe_init(void) +{ + int ret = -ENOMEM; + + init_waitqueue_head(&tcpw.wait); + spin_lock_init(&tcpw.lock); + tcpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &tcpw.lock); + + if (!proc_net_fops_create(procname, S_IRUSR, &tcpprobe_fops)) + goto err0; + + ret = register_jprobe(&tcp_send_probe); + if (ret) + goto err1; + + pr_info("TCP watch registered (port=%d)\n", port); + return 0; + err1: + proc_net_remove(procname); + err0: + kfifo_free(tcpw.fifo); + return ret; +} +module_init(tcpprobe_init); + +static __exit void tcpprobe_exit(void) +{ + kfifo_free(tcpw.fifo); + proc_net_remove(procname); + unregister_jprobe(&tcp_send_probe); + +} +module_exit(tcpprobe_exit); diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c new file mode 100644 index 000000000..5b2fe6d2a --- /dev/null +++ b/net/ipv4/tcp_veno.c @@ -0,0 +1,230 @@ +/* + * TCP Veno congestion control + * + * This is based on the congestion detection/avoidance scheme described in + * C. P. Fu, S. C. Liew. + * "TCP Veno: TCP Enhancement for Transmission over Wireless Access Networks." + * IEEE Journal on Selected Areas in Communication, + * Feb. 2003. + * See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf + */ + +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/inet_diag.h> + +#include <net/tcp.h> + +/* Default values of the Veno variables, in fixed-point representation + * with V_PARAM_SHIFT bits to the right of the binary point. + */ +#define V_PARAM_SHIFT 1 +static const int beta = 3 << V_PARAM_SHIFT; + +/* Veno variables */ +struct veno { + u8 doing_veno_now; /* if true, do veno for this rtt */ + u16 cntrtt; /* # of rtts measured within last rtt */ + u32 minrtt; /* min of rtts measured within last rtt (in usec) */ + u32 basertt; /* the min of all Veno rtt measurements seen (in usec) */ + u32 inc; /* decide whether to increase cwnd */ + u32 diff; /* calculate the diff rate */ +}; + +/* There are several situations when we must "re-start" Veno: + * + * o when a connection is established + * o after an RTO + * o after fast recovery + * o when we send a packet and there is no outstanding + * unacknowledged data (restarting an idle connection) + * + */ +static inline void veno_enable(struct sock *sk) +{ + struct veno *veno = inet_csk_ca(sk); + + /* turn on Veno */ + veno->doing_veno_now = 1; + + veno->minrtt = 0x7fffffff; +} + +static inline void veno_disable(struct sock *sk) +{ + struct veno *veno = inet_csk_ca(sk); + + /* turn off Veno */ + veno->doing_veno_now = 0; +} + +static void tcp_veno_init(struct sock *sk) +{ + struct veno *veno = inet_csk_ca(sk); + + veno->basertt = 0x7fffffff; + veno->inc = 1; + veno_enable(sk); +} + +/* Do rtt sampling needed for Veno. */ +static void tcp_veno_rtt_calc(struct sock *sk, u32 usrtt) +{ + struct veno *veno = inet_csk_ca(sk); + u32 vrtt = usrtt + 1; /* Never allow zero rtt or basertt */ + + /* Filter to find propagation delay: */ + if (vrtt < veno->basertt) + veno->basertt = vrtt; + + /* Find the min rtt during the last rtt to find + * the current prop. delay + queuing delay: + */ + veno->minrtt = min(veno->minrtt, vrtt); + veno->cntrtt++; +} + +static void tcp_veno_state(struct sock *sk, u8 ca_state) +{ + if (ca_state == TCP_CA_Open) + veno_enable(sk); + else + veno_disable(sk); +} + +/* + * If the connection is idle and we are restarting, + * then we don't want to do any Veno calculations + * until we get fresh rtt samples. So when we + * restart, we reset our Veno state to a clean + * state. After we get acks for this flight of + * packets, _then_ we can make Veno calculations + * again. + */ +static void tcp_veno_cwnd_event(struct sock *sk, enum tcp_ca_event event) +{ + if (event == CA_EVENT_CWND_RESTART || event == CA_EVENT_TX_START) + tcp_veno_init(sk); +} + +static void tcp_veno_cong_avoid(struct sock *sk, u32 ack, + u32 seq_rtt, u32 in_flight, int flag) +{ + struct tcp_sock *tp = tcp_sk(sk); + struct veno *veno = inet_csk_ca(sk); + + if (!veno->doing_veno_now) + return tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, flag); + + /* limited by applications */ + if (!tcp_is_cwnd_limited(sk, in_flight)) + return; + + /* We do the Veno calculations only if we got enough rtt samples */ + if (veno->cntrtt <= 2) { + /* We don't have enough rtt samples to do the Veno + * calculation, so we'll behave like Reno. + */ + tcp_reno_cong_avoid(sk, ack, seq_rtt, in_flight, flag); + } else { + u32 rtt, target_cwnd; + + /* We have enough rtt samples, so, using the Veno + * algorithm, we determine the state of the network. + */ + + rtt = veno->minrtt; + + target_cwnd = ((tp->snd_cwnd * veno->basertt) + << V_PARAM_SHIFT) / rtt; + + veno->diff = (tp->snd_cwnd << V_PARAM_SHIFT) - target_cwnd; + + if (tp->snd_cwnd <= tp->snd_ssthresh) { + /* Slow start. */ + tcp_slow_start(tp); + } else { + /* Congestion avoidance. */ + if (veno->diff < beta) { + /* In the "non-congestive state", increase cwnd + * every rtt. + */ + if (tp->snd_cwnd_cnt >= tp->snd_cwnd) { + if (tp->snd_cwnd < tp->snd_cwnd_clamp) + tp->snd_cwnd++; + tp->snd_cwnd_cnt = 0; + } else + tp->snd_cwnd_cnt++; + } else { + /* In the "congestive state", increase cwnd + * every other rtt. + */ + if (tp->snd_cwnd_cnt >= tp->snd_cwnd) { + if (veno->inc + && tp->snd_cwnd < + tp->snd_cwnd_clamp) { + tp->snd_cwnd++; + veno->inc = 0; + } else + veno->inc = 1; + tp->snd_cwnd_cnt = 0; + } else + tp->snd_cwnd_cnt++; + } + + } + if (tp->snd_cwnd < 2) + tp->snd_cwnd = 2; + else if (tp->snd_cwnd > tp->snd_cwnd_clamp) + tp->snd_cwnd = tp->snd_cwnd_clamp; + } + /* Wipe the slate clean for the next rtt. */ + /* veno->cntrtt = 0; */ + veno->minrtt = 0x7fffffff; +} + +/* Veno MD phase */ +static u32 tcp_veno_ssthresh(struct sock *sk) +{ + const struct tcp_sock *tp = tcp_sk(sk); + struct veno *veno = inet_csk_ca(sk); + + if (veno->diff < beta) + /* in "non-congestive state", cut cwnd by 1/5 */ + return max(tp->snd_cwnd * 4 / 5, 2U); + else + /* in "congestive state", cut cwnd by 1/2 */ + return max(tp->snd_cwnd >> 1U, 2U); +} + +static struct tcp_congestion_ops tcp_veno = { + .init = tcp_veno_init, + .ssthresh = tcp_veno_ssthresh, + .cong_avoid = tcp_veno_cong_avoid, + .rtt_sample = tcp_veno_rtt_calc, + .set_state = tcp_veno_state, + .cwnd_event = tcp_veno_cwnd_event, + + .owner = THIS_MODULE, + .name = "veno", +}; + +static int __init tcp_veno_register(void) +{ + BUG_ON(sizeof(struct veno) > ICSK_CA_PRIV_SIZE); + tcp_register_congestion_control(&tcp_veno); + return 0; +} + +static void __exit tcp_veno_unregister(void) +{ + tcp_unregister_congestion_control(&tcp_veno); +} + +module_init(tcp_veno_register); +module_exit(tcp_veno_unregister); + +MODULE_AUTHOR("Bin Zhou, Cheng Peng Fu"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("TCP Veno"); diff --git a/net/ipv4/xfrm4_mode_transport.c b/net/ipv4/xfrm4_mode_transport.c new file mode 100644 index 000000000..a9e6b3dd1 --- /dev/null +++ b/net/ipv4/xfrm4_mode_transport.c @@ -0,0 +1,83 @@ +/* + * xfrm4_mode_transport.c - Transport mode encapsulation for IPv4. + * + * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au> + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/stringify.h> +#include <net/dst.h> +#include <net/ip.h> +#include <net/xfrm.h> + +/* Add encapsulation header. + * + * The IP header will be moved forward to make space for the encapsulation + * header. + * + * On exit, skb->h will be set to the start of the payload to be processed + * by x->type->output and skb->nh will be set to the top IP header. + */ +static int xfrm4_transport_output(struct sk_buff *skb) +{ + struct xfrm_state *x; + struct iphdr *iph; + int ihl; + + iph = skb->nh.iph; + skb->h.ipiph = iph; + + ihl = iph->ihl * 4; + skb->h.raw += ihl; + + x = skb->dst->xfrm; + skb->nh.raw = memmove(skb_push(skb, x->props.header_len), iph, ihl); + return 0; +} + +/* Remove encapsulation header. + * + * The IP header will be moved over the top of the encapsulation header. + * + * On entry, skb->h shall point to where the IP header should be and skb->nh + * shall be set to where the IP header currently is. skb->data shall point + * to the start of the payload. + */ +static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb) +{ + int ihl = skb->data - skb->h.raw; + + if (skb->h.raw != skb->nh.raw) + skb->nh.raw = memmove(skb->h.raw, skb->nh.raw, ihl); + skb->nh.iph->tot_len = htons(skb->len + ihl); + skb->h.raw = skb->data; + return 0; +} + +static struct xfrm_mode xfrm4_transport_mode = { + .input = xfrm4_transport_input, + .output = xfrm4_transport_output, + .owner = THIS_MODULE, + .encap = XFRM_MODE_TRANSPORT, +}; + +static int __init xfrm4_transport_init(void) +{ + return xfrm_register_mode(&xfrm4_transport_mode, AF_INET); +} + +static void __exit xfrm4_transport_exit(void) +{ + int err; + + err = xfrm_unregister_mode(&xfrm4_transport_mode, AF_INET); + BUG_ON(err); +} + +module_init(xfrm4_transport_init); +module_exit(xfrm4_transport_exit); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TRANSPORT); diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c new file mode 100644 index 000000000..13cafbe56 --- /dev/null +++ b/net/ipv4/xfrm4_mode_tunnel.c @@ -0,0 +1,124 @@ +/* + * xfrm4_mode_tunnel.c - Tunnel mode encapsulation for IPv4. + * + * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au> + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/stringify.h> +#include <net/dst.h> +#include <net/inet_ecn.h> +#include <net/ip.h> +#include <net/xfrm.h> + +static inline void ipip_ecn_decapsulate(struct sk_buff *skb) +{ + struct iphdr *outer_iph = skb->nh.iph; + struct iphdr *inner_iph = skb->h.ipiph; + + if (INET_ECN_is_ce(outer_iph->tos)) + IP_ECN_set_ce(inner_iph); +} + +/* Add encapsulation header. + * + * The top IP header will be constructed per RFC 2401. The following fields + * in it shall be filled in by x->type->output: + * tot_len + * check + * + * On exit, skb->h will be set to the start of the payload to be processed + * by x->type->output and skb->nh will be set to the top IP header. + */ +static int xfrm4_tunnel_output(struct sk_buff *skb) +{ + struct dst_entry *dst = skb->dst; + struct xfrm_state *x = dst->xfrm; + struct iphdr *iph, *top_iph; + int flags; + + iph = skb->nh.iph; + skb->h.ipiph = iph; + + skb->nh.raw = skb_push(skb, x->props.header_len); + top_iph = skb->nh.iph; + + top_iph->ihl = 5; + top_iph->version = 4; + + /* DS disclosed */ + top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos); + + flags = x->props.flags; + if (flags & XFRM_STATE_NOECN) + IP_ECN_clear(top_iph); + + top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ? + 0 : (iph->frag_off & htons(IP_DF)); + if (!top_iph->frag_off) + __ip_select_ident(top_iph, dst->child, 0); + + top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT); + + top_iph->saddr = x->props.saddr.a4; + top_iph->daddr = x->id.daddr.a4; + top_iph->protocol = IPPROTO_IPIP; + + memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); + return 0; +} + +static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) +{ + struct iphdr *iph = skb->nh.iph; + int err = -EINVAL; + + if (iph->protocol != IPPROTO_IPIP) + goto out; + if (!pskb_may_pull(skb, sizeof(struct iphdr))) + goto out; + + if (skb_cloned(skb) && + (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) + goto out; + + if (x->props.flags & XFRM_STATE_DECAP_DSCP) + ipv4_copy_dscp(iph, skb->h.ipiph); + if (!(x->props.flags & XFRM_STATE_NOECN)) + ipip_ecn_decapsulate(skb); + skb->mac.raw = memmove(skb->data - skb->mac_len, + skb->mac.raw, skb->mac_len); + skb->nh.raw = skb->data; + err = 0; + +out: + return err; +} + +static struct xfrm_mode xfrm4_tunnel_mode = { + .input = xfrm4_tunnel_input, + .output = xfrm4_tunnel_output, + .owner = THIS_MODULE, + .encap = XFRM_MODE_TUNNEL, +}; + +static int __init xfrm4_tunnel_init(void) +{ + return xfrm_register_mode(&xfrm4_tunnel_mode, AF_INET); +} + +static void __exit xfrm4_tunnel_exit(void) +{ + int err; + + err = xfrm_unregister_mode(&xfrm4_tunnel_mode, AF_INET); + BUG_ON(err); +} + +module_init(xfrm4_tunnel_init); +module_exit(xfrm4_tunnel_exit); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TUNNEL); diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c new file mode 100644 index 000000000..711d713e3 --- /dev/null +++ b/net/ipv6/xfrm6_mode_transport.c @@ -0,0 +1,88 @@ +/* + * xfrm6_mode_transport.c - Transport mode encapsulation for IPv6. + * + * Copyright (C) 2002 USAGI/WIDE Project + * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au> + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/stringify.h> +#include <net/dst.h> +#include <net/ipv6.h> +#include <net/xfrm.h> + +/* Add encapsulation header. + * + * The IP header and mutable extension headers will be moved forward to make + * space for the encapsulation header. + * + * On exit, skb->h will be set to the start of the encapsulation header to be + * filled in by x->type->output and skb->nh will be set to the nextheader field + * of the extension header directly preceding the encapsulation header, or in + * its absence, that of the top IP header. The value of skb->data will always + * point to the top IP header. + */ +static int xfrm6_transport_output(struct sk_buff *skb) +{ + struct xfrm_state *x = skb->dst->xfrm; + struct ipv6hdr *iph; + u8 *prevhdr; + int hdr_len; + + skb_push(skb, x->props.header_len); + iph = skb->nh.ipv6h; + + hdr_len = ip6_find_1stfragopt(skb, &prevhdr); + skb->nh.raw = prevhdr - x->props.header_len; + skb->h.raw = skb->data + hdr_len; + memmove(skb->data, iph, hdr_len); + return 0; +} + +/* Remove encapsulation header. + * + * The IP header will be moved over the top of the encapsulation header. + * + * On entry, skb->h shall point to where the IP header should be and skb->nh + * shall be set to where the IP header currently is. skb->data shall point + * to the start of the payload. + */ +static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb) +{ + int ihl = skb->data - skb->h.raw; + + if (skb->h.raw != skb->nh.raw) + skb->nh.raw = memmove(skb->h.raw, skb->nh.raw, ihl); + skb->nh.ipv6h->payload_len = htons(skb->len + ihl - + sizeof(struct ipv6hdr)); + skb->h.raw = skb->data; + return 0; +} + +static struct xfrm_mode xfrm6_transport_mode = { + .input = xfrm6_transport_input, + .output = xfrm6_transport_output, + .owner = THIS_MODULE, + .encap = XFRM_MODE_TRANSPORT, +}; + +static int __init xfrm6_transport_init(void) +{ + return xfrm_register_mode(&xfrm6_transport_mode, AF_INET6); +} + +static void __exit xfrm6_transport_exit(void) +{ + int err; + + err = xfrm_unregister_mode(&xfrm6_transport_mode, AF_INET6); + BUG_ON(err); +} + +module_init(xfrm6_transport_init); +module_exit(xfrm6_transport_exit); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TRANSPORT); diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c new file mode 100644 index 000000000..8af79be2e --- /dev/null +++ b/net/ipv6/xfrm6_mode_tunnel.c @@ -0,0 +1,121 @@ +/* + * xfrm6_mode_tunnel.c - Tunnel mode encapsulation for IPv6. + * + * Copyright (C) 2002 USAGI/WIDE Project + * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au> + */ + +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/stringify.h> +#include <net/dsfield.h> +#include <net/dst.h> +#include <net/inet_ecn.h> +#include <net/ipv6.h> +#include <net/xfrm.h> + +static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) +{ + struct ipv6hdr *outer_iph = skb->nh.ipv6h; + struct ipv6hdr *inner_iph = skb->h.ipv6h; + + if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph))) + IP6_ECN_set_ce(inner_iph); +} + +/* Add encapsulation header. + * + * The top IP header will be constructed per RFC 2401. The following fields + * in it shall be filled in by x->type->output: + * payload_len + * + * On exit, skb->h will be set to the start of the encapsulation header to be + * filled in by x->type->output and skb->nh will be set to the nextheader field + * of the extension header directly preceding the encapsulation header, or in + * its absence, that of the top IP header. The value of skb->data will always + * point to the top IP header. + */ +static int xfrm6_tunnel_output(struct sk_buff *skb) +{ + struct dst_entry *dst = skb->dst; + struct xfrm_state *x = dst->xfrm; + struct ipv6hdr *iph, *top_iph; + int dsfield; + + skb_push(skb, x->props.header_len); + iph = skb->nh.ipv6h; + + skb->nh.raw = skb->data; + top_iph = skb->nh.ipv6h; + skb->nh.raw = &top_iph->nexthdr; + skb->h.ipv6h = top_iph + 1; + + top_iph->version = 6; + top_iph->priority = iph->priority; + top_iph->flow_lbl[0] = iph->flow_lbl[0]; + top_iph->flow_lbl[1] = iph->flow_lbl[1]; + top_iph->flow_lbl[2] = iph->flow_lbl[2]; + dsfield = ipv6_get_dsfield(top_iph); + dsfield = INET_ECN_encapsulate(dsfield, dsfield); + if (x->props.flags & XFRM_STATE_NOECN) + dsfield &= ~INET_ECN_MASK; + ipv6_change_dsfield(top_iph, 0, dsfield); + top_iph->nexthdr = IPPROTO_IPV6; + top_iph->hop_limit = dst_metric(dst->child, RTAX_HOPLIMIT); + ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); + ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); + return 0; +} + +static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) +{ + int err = -EINVAL; + + if (skb->nh.raw[IP6CB(skb)->nhoff] != IPPROTO_IPV6) + goto out; + if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) + goto out; + + if (skb_cloned(skb) && + (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) + goto out; + + if (x->props.flags & XFRM_STATE_DECAP_DSCP) + ipv6_copy_dscp(skb->nh.ipv6h, skb->h.ipv6h); + if (!(x->props.flags & XFRM_STATE_NOECN)) + ipip6_ecn_decapsulate(skb); + skb->mac.raw = memmove(skb->data - skb->mac_len, + skb->mac.raw, skb->mac_len); + skb->nh.raw = skb->data; + err = 0; + +out: + return err; +} + +static struct xfrm_mode xfrm6_tunnel_mode = { + .input = xfrm6_tunnel_input, + .output = xfrm6_tunnel_output, + .owner = THIS_MODULE, + .encap = XFRM_MODE_TUNNEL, +}; + +static int __init xfrm6_tunnel_init(void) +{ + return xfrm_register_mode(&xfrm6_tunnel_mode, AF_INET6); +} + +static void __exit xfrm6_tunnel_exit(void) +{ + int err; + + err = xfrm_unregister_mode(&xfrm6_tunnel_mode, AF_INET6); + BUG_ON(err); +} + +module_init(xfrm6_tunnel_init); +module_exit(xfrm6_tunnel_exit); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TUNNEL); diff --git a/net/netfilter/xt_CONNSECMARK.c b/net/netfilter/xt_CONNSECMARK.c new file mode 100644 index 000000000..8c011e020 --- /dev/null +++ b/net/netfilter/xt_CONNSECMARK.c @@ -0,0 +1,155 @@ +/* + * This module is used to copy security markings from packets + * to connections, and restore security markings from connections + * back to packets. This would normally be performed in conjunction + * with the SECMARK target and state match. + * + * Based somewhat on CONNMARK: + * Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> + * by Henrik Nordstrom <hno@marasystems.com> + * + * (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_CONNSECMARK.h> +#include <net/netfilter/nf_conntrack_compat.h> + +#define PFX "CONNSECMARK: " + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("James Morris <jmorris@redhat.com>"); +MODULE_DESCRIPTION("ip[6]tables CONNSECMARK module"); +MODULE_ALIAS("ipt_CONNSECMARK"); +MODULE_ALIAS("ip6t_CONNSECMARK"); + +/* + * If the packet has a security mark and the connection does not, copy + * the security mark from the packet to the connection. + */ +static void secmark_save(struct sk_buff *skb) +{ + if (skb->secmark) { + u32 *connsecmark; + enum ip_conntrack_info ctinfo; + + connsecmark = nf_ct_get_secmark(skb, &ctinfo); + if (connsecmark && !*connsecmark) + if (*connsecmark != skb->secmark) + *connsecmark = skb->secmark; + } +} + +/* + * If packet has no security mark, and the connection does, restore the + * security mark from the connection to the packet. + */ +static void secmark_restore(struct sk_buff *skb) +{ + if (!skb->secmark) { + u32 *connsecmark; + enum ip_conntrack_info ctinfo; + + connsecmark = nf_ct_get_secmark(skb, &ctinfo); + if (connsecmark && *connsecmark) + if (skb->secmark != *connsecmark) + skb->secmark = *connsecmark; + } +} + +static unsigned int target(struct sk_buff **pskb, const struct net_device *in, + const struct net_device *out, unsigned int hooknum, + const struct xt_target *target, + const void *targinfo, void *userinfo) +{ + struct sk_buff *skb = *pskb; + const struct xt_connsecmark_target_info *info = targinfo; + + switch (info->mode) { + case CONNSECMARK_SAVE: + secmark_save(skb); + break; + + case CONNSECMARK_RESTORE: + secmark_restore(skb); + break; + + default: + BUG(); + } + + return XT_CONTINUE; +} + +static int checkentry(const char *tablename, const void *entry, + const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) +{ + struct xt_connsecmark_target_info *info = targinfo; + + switch (info->mode) { + case CONNSECMARK_SAVE: + case CONNSECMARK_RESTORE: + break; + + default: + printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode); + return 0; + } + + return 1; +} + +static struct xt_target ipt_connsecmark_reg = { + .name = "CONNSECMARK", + .target = target, + .targetsize = sizeof(struct xt_connsecmark_target_info), + .table = "mangle", + .checkentry = checkentry, + .me = THIS_MODULE, + .family = AF_INET, + .revision = 0, +}; + +static struct xt_target ip6t_connsecmark_reg = { + .name = "CONNSECMARK", + .target = target, + .targetsize = sizeof(struct xt_connsecmark_target_info), + .table = "mangle", + .checkentry = checkentry, + .me = THIS_MODULE, + .family = AF_INET6, + .revision = 0, +}; + +static int __init xt_connsecmark_init(void) +{ + int err; + + need_conntrack(); + + err = xt_register_target(&ipt_connsecmark_reg); + if (err) + return err; + + err = xt_register_target(&ip6t_connsecmark_reg); + if (err) + xt_unregister_target(&ipt_connsecmark_reg); + + return err; +} + +static void __exit xt_connsecmark_fini(void) +{ + xt_unregister_target(&ip6t_connsecmark_reg); + xt_unregister_target(&ipt_connsecmark_reg); +} + +module_init(xt_connsecmark_init); +module_exit(xt_connsecmark_fini); diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c new file mode 100644 index 000000000..de9537ad9 --- /dev/null +++ b/net/netfilter/xt_SECMARK.c @@ -0,0 +1,158 @@ +/* + * Module for modifying the secmark field of the skb, for use by + * security subsystems. + * + * Based on the nfmark match by: + * (C) 1999-2001 Marc Boucher <marc@mbsi.ca> + * + * (C) 2006 Red Hat, Inc., James Morris <jmorris@redhat.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/selinux.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_SECMARK.h> + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("James Morris <jmorris@redhat.com>"); +MODULE_DESCRIPTION("ip[6]tables SECMARK modification module"); +MODULE_ALIAS("ipt_SECMARK"); +MODULE_ALIAS("ip6t_SECMARK"); + +#define PFX "SECMARK: " + +static u8 mode; + +static unsigned int target(struct sk_buff **pskb, const struct net_device *in, + const struct net_device *out, unsigned int hooknum, + const struct xt_target *target, + const void *targinfo, void *userinfo) +{ + u32 secmark = 0; + const struct xt_secmark_target_info *info = targinfo; + + BUG_ON(info->mode != mode); + + switch (mode) { + case SECMARK_MODE_SEL: + secmark = info->u.sel.selsid; + break; + + default: + BUG(); + } + + if ((*pskb)->secmark != secmark) + (*pskb)->secmark = secmark; + + return XT_CONTINUE; +} + +static int checkentry_selinux(struct xt_secmark_target_info *info) +{ + int err; + struct xt_secmark_target_selinux_info *sel = &info->u.sel; + + sel->selctx[SECMARK_SELCTX_MAX - 1] = '\0'; + + err = selinux_string_to_sid(sel->selctx, &sel->selsid); + if (err) { + if (err == -EINVAL) + printk(KERN_INFO PFX "invalid SELinux context \'%s\'\n", + sel->selctx); + return 0; + } + + if (!sel->selsid) { + printk(KERN_INFO PFX "unable to map SELinux context \'%s\'\n", + sel->selctx); + return 0; + } + + err = selinux_relabel_packet_permission(sel->selsid); + if (err) { + printk(KERN_INFO PFX "unable to obtain relabeling permission\n"); + return 0; + } + + return 1; +} + +static int checkentry(const char *tablename, const void *entry, + const struct xt_target *target, void *targinfo, + unsigned int targinfosize, unsigned int hook_mask) +{ + struct xt_secmark_target_info *info = targinfo; + + if (mode && mode != info->mode) { + printk(KERN_INFO PFX "mode already set to %hu cannot mix with " + "rules for mode %hu\n", mode, info->mode); + return 0; + } + + switch (info->mode) { + case SECMARK_MODE_SEL: + if (!checkentry_selinux(info)) + return 0; + break; + + default: + printk(KERN_INFO PFX "invalid mode: %hu\n", info->mode); + return 0; + } + + if (!mode) + mode = info->mode; + return 1; +} + +static struct xt_target ipt_secmark_reg = { + .name = "SECMARK", + .target = target, + .targetsize = sizeof(struct xt_secmark_target_info), + .table = "mangle", + .checkentry = checkentry, + .me = THIS_MODULE, + .family = AF_INET, + .revision = 0, +}; + +static struct xt_target ip6t_secmark_reg = { + .name = "SECMARK", + .target = target, + .targetsize = sizeof(struct xt_secmark_target_info), + .table = "mangle", + .checkentry = checkentry, + .me = THIS_MODULE, + .family = AF_INET6, + .revision = 0, +}; + +static int __init xt_secmark_init(void) +{ + int err; + + err = xt_register_target(&ipt_secmark_reg); + if (err) + return err; + + err = xt_register_target(&ip6t_secmark_reg); + if (err) + xt_unregister_target(&ipt_secmark_reg); + + return err; +} + +static void __exit xt_secmark_fini(void) +{ + xt_unregister_target(&ip6t_secmark_reg); + xt_unregister_target(&ipt_secmark_reg); +} + +module_init(xt_secmark_init); +module_exit(xt_secmark_fini); diff --git a/net/netfilter/xt_quota.c b/net/netfilter/xt_quota.c new file mode 100644 index 000000000..be8d3c26b --- /dev/null +++ b/net/netfilter/xt_quota.c @@ -0,0 +1,98 @@ +/* + * netfilter module to enforce network quotas + * + * Sam Johnston <samj@samj.net> + */ +#include <linux/skbuff.h> +#include <linux/spinlock.h> + +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_quota.h> + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Sam Johnston <samj@samj.net>"); +MODULE_ALIAS("ipt_quota"); +MODULE_ALIAS("ip6t_quota"); + +static DEFINE_SPINLOCK(quota_lock); + +static int +match(const struct sk_buff *skb, + const struct net_device *in, const struct net_device *out, + const struct xt_match *match, const void *matchinfo, + int offset, unsigned int protoff, int *hotdrop) +{ + struct xt_quota_info *q = ((struct xt_quota_info *)matchinfo)->master; + int ret = q->flags & XT_QUOTA_INVERT ? 1 : 0; + + spin_lock_bh("a_lock); + if (q->quota >= skb->len) { + q->quota -= skb->len; + ret ^= 1; + } else { + /* we do not allow even small packets from now on */ + q->quota = 0; + } + spin_unlock_bh("a_lock); + + return ret; +} + +static int +checkentry(const char *tablename, const void *entry, + const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) +{ + struct xt_quota_info *q = (struct xt_quota_info *)matchinfo; + + if (q->flags & ~XT_QUOTA_MASK) + return 0; + /* For SMP, we only want to use one set of counters. */ + q->master = q; + return 1; +} + +static struct xt_match quota_match = { + .name = "quota", + .family = AF_INET, + .match = match, + .matchsize = sizeof(struct xt_quota_info), + .checkentry = checkentry, + .me = THIS_MODULE +}; + +static struct xt_match quota_match6 = { + .name = "quota", + .family = AF_INET6, + .match = match, + .matchsize = sizeof(struct xt_quota_info), + .checkentry = checkentry, + .me = THIS_MODULE +}; + +static int __init xt_quota_init(void) +{ + int ret; + + ret = xt_register_match("a_match); + if (ret) + goto err1; + ret = xt_register_match("a_match6); + if (ret) + goto err2; + return ret; + +err2: + xt_unregister_match("a_match); +err1: + return ret; +} + +static void __exit xt_quota_fini(void) +{ + xt_unregister_match("a_match6); + xt_unregister_match("a_match); +} + +module_init(xt_quota_init); +module_exit(xt_quota_fini); diff --git a/net/netfilter/xt_statistic.c b/net/netfilter/xt_statistic.c new file mode 100644 index 000000000..de1037f58 --- /dev/null +++ b/net/netfilter/xt_statistic.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2006 Patrick McHardy <kaber@trash.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Based on ipt_random and ipt_nth by Fabrice MARIE <fabrice@netfilter.org>. + */ + +#include <linux/init.h> +#include <linux/spinlock.h> +#include <linux/skbuff.h> +#include <linux/net.h> + +#include <linux/netfilter/xt_statistic.h> +#include <linux/netfilter/x_tables.h> + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); +MODULE_DESCRIPTION("xtables statistical match module"); +MODULE_ALIAS("ipt_statistic"); +MODULE_ALIAS("ip6t_statistic"); + +static DEFINE_SPINLOCK(nth_lock); + +static int +match(const struct sk_buff *skb, + const struct net_device *in, const struct net_device *out, + const struct xt_match *match, const void *matchinfo, + int offset, unsigned int protoff, int *hotdrop) +{ + struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo; + int ret = info->flags & XT_STATISTIC_INVERT ? 1 : 0; + + switch (info->mode) { + case XT_STATISTIC_MODE_RANDOM: + if ((net_random() & 0x7FFFFFFF) < info->u.random.probability) + ret ^= 1; + break; + case XT_STATISTIC_MODE_NTH: + info = info->master; + spin_lock_bh(&nth_lock); + if (info->u.nth.count++ == info->u.nth.every) { + info->u.nth.count = 0; + ret ^= 1; + } + spin_unlock_bh(&nth_lock); + break; + } + + return ret; +} + +static int +checkentry(const char *tablename, const void *entry, + const struct xt_match *match, void *matchinfo, + unsigned int matchsize, unsigned int hook_mask) +{ + struct xt_statistic_info *info = (struct xt_statistic_info *)matchinfo; + + if (info->mode > XT_STATISTIC_MODE_MAX || + info->flags & ~XT_STATISTIC_MASK) + return 0; + info->master = info; + return 1; +} + +static struct xt_match statistic_match = { + .name = "statistic", + .match = match, + .matchsize = sizeof(struct xt_statistic_info), + .checkentry = checkentry, + .family = AF_INET, + .me = THIS_MODULE, +}; + +static struct xt_match statistic_match6 = { + .name = "statistic", + .match = match, + .matchsize = sizeof(struct xt_statistic_info), + .checkentry = checkentry, + .family = AF_INET6, + .me = THIS_MODULE, +}; + +static int __init xt_statistic_init(void) +{ + int ret; + + ret = xt_register_match(&statistic_match); + if (ret) + goto err1; + + ret = xt_register_match(&statistic_match6); + if (ret) + goto err2; + return ret; +err2: + xt_unregister_match(&statistic_match); +err1: + return ret; +} + +static void __exit xt_statistic_fini(void) +{ + xt_unregister_match(&statistic_match6); + xt_unregister_match(&statistic_match); +} + +module_init(xt_statistic_init); +module_exit(xt_statistic_fini); diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst new file mode 100644 index 000000000..12e1daf87 --- /dev/null +++ b/scripts/Makefile.headersinst @@ -0,0 +1,160 @@ +# ========================================================================== +# Installing headers +# +# header-y files will be installed verbatim +# unifdef-y are the files where unifdef will be run before installing files +# objhdr-y are generated files that will be installed verbatim +# +# ========================================================================== + +UNIFDEF := unifdef -U__KERNEL__ + +# Eliminate the contents of (and inclusions of) compiler.h +HDRSED := sed -e "s/ inline / __inline__ /g" \ + -e "s/[[:space:]]__user[[:space:]]\+/ /g" \ + -e "s/(__user[[:space:]]\+/ (/g" \ + -e "s/[[:space:]]__force[[:space:]]\+/ /g" \ + -e "s/(__force[[:space:]]\+/ (/g" \ + -e "s/[[:space:]]__iomem[[:space:]]\+/ /g" \ + -e "s/(__iomem[[:space:]]\+/ (/g" \ + -e "s/[[:space:]]__attribute_const__[[:space:]]\+/\ /g" \ + -e "s/[[:space:]]__attribute_const__$$//" \ + -e "/^\#include <linux\/compiler.h>/d" + +_dst := $(if $(dst),$(dst),$(obj)) + +.PHONY: __headersinst +__headersinst: + + +ifeq (,$(patsubst include/asm/%,,$(obj)/)) +# For producing the generated stuff in include/asm for biarch builds, include +# both sets of Kbuild files; we'll generate anything which is mentioned in +# _either_ arch, and recurse into subdirectories which are mentioned in either +# arch. Since some directories may exist in one but not the other, we must +# use '-include'. +GENASM := 1 +archasm := $(subst include/asm,asm-$(ARCH),$(obj)) +altarchasm := $(subst include/asm,asm-$(ALTARCH),$(obj)) +-include $(srctree)/include/$(archasm)/Kbuild +-include $(srctree)/include/$(altarchasm)/Kbuild +else +include $(srctree)/$(obj)/Kbuild +endif + +include scripts/Kbuild.include + +# If this is include/asm-$(ARCH) and there's no $(ALTARCH), then +# override $(_dst) so that we install to include/asm directly. +ifeq ($(obj)$(ALTARCH),include/asm-$(ARCH)) + _dst := include/asm +endif + +header-y := $(sort $(header-y)) +unifdef-y := $(sort $(unifdef-y)) +subdir-y := $(patsubst %/,%,$(filter %/, $(header-y))) +header-y := $(filter-out %/, $(header-y)) +header-y := $(filter-out $(unifdef-y),$(header-y)) + +ifdef ALTARCH +ifeq ($(obj),include/asm-$(ARCH)) +altarch-y := altarch-dir +endif +endif + +# Make the definitions visible for recursive make invocations +export ALTARCH +export ARCHDEF +export ALTARCHDEF + +quiet_cmd_o_hdr_install = INSTALL $(_dst)/$@ + cmd_o_hdr_install = cp $(objtree)/$(obj)/$@ $(INSTALL_HDR_PATH)/$(_dst) + +quiet_cmd_headers_install = INSTALL $(_dst)/$@ + cmd_headers_install = $(HDRSED) $(srctree)/$(obj)/$@ \ + > $(INSTALL_HDR_PATH)/$(_dst)/$@ + +quiet_cmd_unifdef = UNIFDEF $(_dst)/$@ + cmd_unifdef = $(UNIFDEF) $(srctree)/$(obj)/$@ | $(HDRSED) \ + > $(INSTALL_HDR_PATH)/$(_dst)/$@ || : + +quiet_cmd_check = CHECK $(_dst)/$@ + cmd_check = $(srctree)/scripts/hdrcheck.sh \ + $(INSTALL_HDR_PATH)/include \ + $(INSTALL_HDR_PATH)/$(_dst)/$@ + +quiet_cmd_mkdir = MKDIR $@ + cmd_mkdir = mkdir -p $(INSTALL_HDR_PATH)/$@ + +quiet_cmd_gen = GEN $(_dst)/$@ + cmd_gen = \ +STUBDEF=__ASM_STUB_`echo $@ | tr a-z. A-Z_`; \ +(echo "/* File autogenerated by 'make headers_install' */" ; \ +echo "\#ifndef $$STUBDEF" ; \ +echo "\#define $$STUBDEF" ; \ +echo "\# if $(ARCHDEF)" ; \ +if [ -r $(INSTALL_HDR_PATH)/include/$(archasm)/$@ ]; then \ + echo "\# include <$(archasm)/$@>" ; \ +else \ + echo "\# error $(archasm)/$@ does not exist in" \ + "the $(ARCH) architecture" ; \ +fi ; \ +echo "\# elif $(ALTARCHDEF)" ; \ +if [ -r $(INSTALL_HDR_PATH)/include/$(altarchasm)/$@ ]; then \ + echo "\# include <$(altarchasm)/$@>" ; \ +else \ + echo "\# error $(altarchasm)/$@ does not exist in" \ + "the $(ALTARCH) architecture" ; \ +fi ; \ +echo "\# else" ; \ +echo "\# warning This machine appears to be" \ + "neither $(ARCH) nor $(ALTARCH)." ; \ +echo "\# endif" ; \ +echo "\#endif /* $$STUBDEF */" ; \ +) > $(INSTALL_HDR_PATH)/$(_dst)/$@ + +__headersinst: $(subdir-y) $(header-y) $(unifdef-y) $(altarch-y) $(objhdr-y) + +.PHONY: $(header-y) $(unifdef-y) $(subdir-y) + +ifdef HDRCHECK +# Rules for checking headers +$(objhdr-y) $(header-y) $(unifdef-y): + $(call cmd,check) +else +# Rules for installing headers + +$(objhdr-y) $(subdir-y) $(header-y) $(unifdef-y): $(_dst) + +.PHONY: $(_dst) +$(_dst): + $(call cmd,mkdir) + +ifdef GENASM +$(objhdr-y) $(header-y) $(unifdef-y): + $(call cmd,gen) + +else +$(objhdr-y): + $(call cmd,o_hdr_install) + +$(header-y): + $(call cmd,headers_install) + +$(unifdef-y): + $(call cmd,unifdef) +endif +endif + +hdrinst := -rR -f $(srctree)/scripts/Makefile.headersinst obj + +.PHONY: altarch-dir +# All the files in the normal arch dir must be created first, since we test +# for their existence. +altarch-dir: $(subdir-y) $(header-y) $(unifdef-y) $(objhdr-y) + $(Q)$(MAKE) $(hdrinst)=include/asm-$(ALTARCH) dst=include/asm-$(ALTARCH) + $(Q)$(MAKE) $(hdrinst)=include/asm dst=include/asm + +# Recursion +$(subdir-y): + $(Q)$(MAKE) $(hdrinst)=$(obj)/$@ dst=$(_dst)/$@ rel=../$(rel) diff --git a/scripts/export_report.pl b/scripts/export_report.pl new file mode 100644 index 000000000..9ed00d9bb --- /dev/null +++ b/scripts/export_report.pl @@ -0,0 +1,169 @@ +#!/usr/bin/perl -w +# +# (C) Copyright IBM Corporation 2006. +# Released under GPL v2. +# Author : Ram Pai (linuxram@us.ibm.com) +# +# Usage: export_report.pl -k Module.symvers [-o report_file ] -f *.mod.c +# + +use Getopt::Std; +use strict; + +sub numerically { + my $no1 = (split /\s+/, $a)[1]; + my $no2 = (split /\s+/, $b)[1]; + return $no1 <=> $no2; +} + +sub alphabetically { + my ($module1, $value1) = @{$a}; + my ($module2, $value2) = @{$b}; + return $value1 <=> $value2 || $module2 cmp $module1; +} + +sub print_depends_on { + my ($href) = @_; + print "\n"; + while (my ($mod, $list) = each %$href) { + print "\t$mod:\n"; + foreach my $sym (sort numerically @{$list}) { + my ($symbol, $no) = split /\s+/, $sym; + printf("\t\t%-25s\t%-25d\n", $symbol, $no); + } + print "\n"; + } + print "\n"; + print "~"x80 , "\n"; +} + +sub usage { + print "Usage: @_ -h -k Module.symvers [ -o outputfile ] \n", + "\t-f: treat all the non-option argument as .mod.c files. ", + "Recommend using this as the last option\n", + "\t-h: print detailed help\n", + "\t-k: the path to Module.symvers file. By default uses ", + "the file from the current directory\n", + "\t-o outputfile: output the report to outputfile\n"; + exit 0; +} + +sub collectcfiles { + my @file = `cat .tmp_versions/*.mod | grep '.*\.ko\$'`; + @file = grep {s/\.ko/.mod.c/} @file; + chomp @file; + return @file; +} + +my (%SYMBOL, %MODULE, %opt, @allcfiles); + +if (not getopts('hk:o:f',\%opt) or defined $opt{'h'}) { + usage($0); +} + +if (defined $opt{'f'}) { + @allcfiles = @ARGV; +} else { + @allcfiles = collectcfiles(); +} + +if (not defined $opt{'k'}) { + $opt{'k'} = "Module.symvers"; +} + +unless (open(MODULE_SYMVERS, $opt{'k'})) { + die "Sorry, cannot open $opt{'k'}: $!\n"; +} + +if (defined $opt{'o'}) { + unless (open(OUTPUT_HANDLE, ">$opt{'o'}")) { + die "Sorry, cannot open $opt{'o'} $!\n"; + } + select OUTPUT_HANDLE; +} +# +# collect all the symbols and their attributes from the +# Module.symvers file +# +while ( <MODULE_SYMVERS> ) { + chomp; + my (undef, $symbol, $module, $gpl) = split; + $SYMBOL { $symbol } = [ $module , "0" , $symbol, $gpl]; +} +close(MODULE_SYMVERS); + +# +# collect the usage count of each symbol. +# +foreach my $thismod (@allcfiles) { + unless (open(MODULE_MODULE, $thismod)) { + print "Sorry, cannot open $thismod: $!\n"; + next; + } + my $state=0; + while ( <MODULE_MODULE> ) { + chomp; + if ($state eq 0) { + $state = 1 if ($_ =~ /static const struct modversion_info/); + next; + } + if ($state eq 1) { + $state = 2 if ($_ =~ /__attribute__\(\(section\("__versions"\)\)\)/); + next; + } + if ($state eq 2) { + if ( $_ !~ /0x[0-9a-f]{7,8},/ ) { + next; + } + my $sym = (split /([,"])/,)[4]; + my ($module, $value, $symbol, $gpl) = @{$SYMBOL{$sym}}; + $SYMBOL{ $sym } = [ $module, $value+1, $symbol, $gpl]; + push(@{$MODULE{$thismod}} , $sym); + } + } + if ($state ne 2) { + print "WARNING:$thismod is not built with CONFIG_MODVERSION enabled\n"; + } + close(MODULE_MODULE); +} + +print "\tThis file reports the exported symbols usage patterns by in-tree\n", + "\t\t\t\tmodules\n"; +printf("%s\n\n\n","x"x80); +printf("\t\t\t\tINDEX\n\n\n"); +printf("SECTION 1: Usage counts of all exported symbols\n"); +printf("SECTION 2: List of modules and the exported symbols they use\n"); +printf("%s\n\n\n","x"x80); +printf("SECTION 1:\tThe exported symbols and their usage count\n\n"); +printf("%-25s\t%-25s\t%-5s\t%-25s\n", "Symbol", "Module", "Usage count", + "export type"); + +# +# print the list of unused exported symbols +# +foreach my $list (sort alphabetically values(%SYMBOL)) { + my ($module, $value, $symbol, $gpl) = @{$list}; + printf("%-25s\t%-25s\t%-10s\t", $symbol, $module, $value); + if (defined $gpl) { + printf("%-25s\n",$gpl); + } else { + printf("\n"); + } +} +printf("%s\n\n\n","x"x80); + +printf("SECTION 2:\n\tThis section reports export-symbol-usage of in-kernel +modules. Each module lists the modules, and the symbols from that module that +it uses. Each listed symbol reports the number of modules using it\n"); + +print "~"x80 , "\n"; +while (my ($thismod, $list) = each %MODULE) { + my %depends; + $thismod =~ s/\.mod\.c/.ko/; + print "\t\t\t$thismod\n"; + foreach my $symbol (@{$list}) { + my ($module, $value, undef, $gpl) = @{$SYMBOL{$symbol}}; + push (@{$depends{"$module"}}, "$symbol $value"); + } + print_depends_on(\%depends); +} diff --git a/scripts/hdrcheck.sh b/scripts/hdrcheck.sh new file mode 100755 index 000000000..b5ca35aa1 --- /dev/null +++ b/scripts/hdrcheck.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +for FILE in `grep '^[ \t]*#[ \t]*include[ \t]*<' $2 | cut -f2 -d\< | cut -f1 -d\> | egrep ^linux\|^asm` ; do + if [ ! -r $1/$FILE ]; then + echo $2 requires $FILE, which does not exist in exported headers + exit 1 + fi +done diff --git a/scripts/rt-tester/check-all.sh b/scripts/rt-tester/check-all.sh new file mode 100644 index 000000000..43098afe7 --- /dev/null +++ b/scripts/rt-tester/check-all.sh @@ -0,0 +1,22 @@ + + +function testit () +{ + printf "%-30s: " $1 + ./rt-tester.py $1 | grep Pass +} + +testit t2-l1-2rt-sameprio.tst +testit t2-l1-pi.tst +testit t2-l1-signal.tst +#testit t2-l2-2rt-deadlock.tst +testit t3-l1-pi-1rt.tst +testit t3-l1-pi-2rt.tst +testit t3-l1-pi-3rt.tst +testit t3-l1-pi-signal.tst +testit t3-l1-pi-steal.tst +testit t3-l2-pi.tst +testit t4-l2-pi-deboost.tst +testit t5-l4-pi-boost-deboost.tst +testit t5-l4-pi-boost-deboost-setsched.tst + diff --git a/scripts/rt-tester/rt-tester.py b/scripts/rt-tester/rt-tester.py new file mode 100644 index 000000000..4c7966079 --- /dev/null +++ b/scripts/rt-tester/rt-tester.py @@ -0,0 +1,222 @@ +#!/usr/bin/env python +# +# rt-mutex tester +# +# (C) 2006 Thomas Gleixner <tglx@linutronix.de> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +import os +import sys +import getopt +import shutil +import string + +# Globals +quiet = 0 +test = 0 +comments = 0 + +sysfsprefix = "/sys/devices/system/rttest/rttest" +statusfile = "/status" +commandfile = "/command" + +# Command opcodes +cmd_opcodes = { + "schedother" : "1", + "schedfifo" : "2", + "lock" : "3", + "locknowait" : "4", + "lockint" : "5", + "lockintnowait" : "6", + "lockcont" : "7", + "unlock" : "8", + "lockbkl" : "9", + "unlockbkl" : "10", + "signal" : "11", + "resetevent" : "98", + "reset" : "99", + } + +test_opcodes = { + "prioeq" : ["P" , "eq" , None], + "priolt" : ["P" , "lt" , None], + "priogt" : ["P" , "gt" , None], + "nprioeq" : ["N" , "eq" , None], + "npriolt" : ["N" , "lt" , None], + "npriogt" : ["N" , "gt" , None], + "unlocked" : ["M" , "eq" , 0], + "trylock" : ["M" , "eq" , 1], + "blocked" : ["M" , "eq" , 2], + "blockedwake" : ["M" , "eq" , 3], + "locked" : ["M" , "eq" , 4], + "opcodeeq" : ["O" , "eq" , None], + "opcodelt" : ["O" , "lt" , None], + "opcodegt" : ["O" , "gt" , None], + "eventeq" : ["E" , "eq" , None], + "eventlt" : ["E" , "lt" , None], + "eventgt" : ["E" , "gt" , None], + } + +# Print usage information +def usage(): + print "rt-tester.py <-c -h -q -t> <testfile>" + print " -c display comments after first command" + print " -h help" + print " -q quiet mode" + print " -t test mode (syntax check)" + print " testfile: read test specification from testfile" + print " otherwise from stdin" + return + +# Print progress when not in quiet mode +def progress(str): + if not quiet: + print str + +# Analyse a status value +def analyse(val, top, arg): + + intval = int(val) + + if top[0] == "M": + intval = intval / (10 ** int(arg)) + intval = intval % 10 + argval = top[2] + elif top[0] == "O": + argval = int(cmd_opcodes.get(arg, arg)) + else: + argval = int(arg) + + # progress("%d %s %d" %(intval, top[1], argval)) + + if top[1] == "eq" and intval == argval: + return 1 + if top[1] == "lt" and intval < argval: + return 1 + if top[1] == "gt" and intval > argval: + return 1 + return 0 + +# Parse the commandline +try: + (options, arguments) = getopt.getopt(sys.argv[1:],'chqt') +except getopt.GetoptError, ex: + usage() + sys.exit(1) + +# Parse commandline options +for option, value in options: + if option == "-c": + comments = 1 + elif option == "-q": + quiet = 1 + elif option == "-t": + test = 1 + elif option == '-h': + usage() + sys.exit(0) + +# Select the input source +if arguments: + try: + fd = open(arguments[0]) + except Exception,ex: + sys.stderr.write("File not found %s\n" %(arguments[0])) + sys.exit(1) +else: + fd = sys.stdin + +linenr = 0 + +# Read the test patterns +while 1: + + linenr = linenr + 1 + line = fd.readline() + if not len(line): + break + + line = line.strip() + parts = line.split(":") + + if not parts or len(parts) < 1: + continue + + if len(parts[0]) == 0: + continue + + if parts[0].startswith("#"): + if comments > 1: + progress(line) + continue + + if comments == 1: + comments = 2 + + progress(line) + + cmd = parts[0].strip().lower() + opc = parts[1].strip().lower() + tid = parts[2].strip() + dat = parts[3].strip() + + try: + # Test or wait for a status value + if cmd == "t" or cmd == "w": + testop = test_opcodes[opc] + + fname = "%s%s%s" %(sysfsprefix, tid, statusfile) + if test: + print fname + continue + + while 1: + query = 1 + fsta = open(fname, 'r') + status = fsta.readline().strip() + fsta.close() + stat = status.split(",") + for s in stat: + s = s.strip() + if s.startswith(testop[0]): + # Seperate status value + val = s[2:].strip() + query = analyse(val, testop, dat) + break + if query or cmd == "t": + break + + progress(" " + status) + + if not query: + sys.stderr.write("Test failed in line %d\n" %(linenr)) + sys.exit(1) + + # Issue a command to the tester + elif cmd == "c": + cmdnr = cmd_opcodes[opc] + # Build command string and sys filename + cmdstr = "%s:%s" %(cmdnr, dat) + fname = "%s%s%s" %(sysfsprefix, tid, commandfile) + if test: + print fname + continue + fcmd = open(fname, 'w') + fcmd.write(cmdstr) + fcmd.close() + + except Exception,ex: + sys.stderr.write(str(ex)) + sys.stderr.write("\nSyntax error in line %d\n" %(linenr)) + if not test: + fd.close() + sys.exit(1) + +# Normal exit pass +print "Pass" +sys.exit(0) + + diff --git a/scripts/rt-tester/t2-l1-2rt-sameprio.tst b/scripts/rt-tester/t2-l1-2rt-sameprio.tst new file mode 100644 index 000000000..8821f27cc --- /dev/null +++ b/scripts/rt-tester/t2-l1-2rt-sameprio.tst @@ -0,0 +1,99 @@ +# +# RT-Mutex test +# +# Op: C(ommand)/T(est)/W(ait) +# | opcode +# | | threadid: 0-7 +# | | | opcode argument +# | | | | +# C: lock: 0: 0 +# +# Commands +# +# opcode opcode argument +# schedother nice value +# schedfifo priority +# lock lock nr (0-7) +# locknowait lock nr (0-7) +# lockint lock nr (0-7) +# lockintnowait lock nr (0-7) +# lockcont lock nr (0-7) +# unlock lock nr (0-7) +# lockbkl lock nr (0-7) +# unlockbkl lock nr (0-7) +# signal 0 +# reset 0 +# resetevent 0 +# +# Tests / Wait +# +# opcode opcode argument +# +# prioeq priority +# priolt priority +# priogt priority +# nprioeq normal priority +# npriolt normal priority +# npriogt normal priority +# locked lock nr (0-7) +# blocked lock nr (0-7) +# blockedwake lock nr (0-7) +# unlocked lock nr (0-7) +# lockedbkl dont care +# blockedbkl dont care +# unlockedbkl dont care +# opcodeeq command opcode or number +# opcodelt number +# opcodegt number +# eventeq number +# eventgt number +# eventlt number + +# +# 2 threads 1 lock +# +C: resetevent: 0: 0 +W: opcodeeq: 0: 0 + +# Set schedulers +C: schedfifo: 0: 80 +C: schedfifo: 1: 80 + +# T0 lock L0 +C: locknowait: 0: 0 +C: locknowait: 1: 0 +W: locked: 0: 0 +W: blocked: 1: 0 +T: prioeq: 0: 80 + +# T0 unlock L0 +C: unlock: 0: 0 +W: locked: 1: 0 + +# Verify T0 +W: unlocked: 0: 0 +T: prioeq: 0: 80 + +# Unlock +C: unlock: 1: 0 +W: unlocked: 1: 0 + +# T1,T0 lock L0 +C: locknowait: 1: 0 +C: locknowait: 0: 0 +W: locked: 1: 0 +W: blocked: 0: 0 +T: prioeq: 1: 80 + +# T1 unlock L0 +C: unlock: 1: 0 +W: locked: 0: 0 + +# Verify T1 +W: unlocked: 1: 0 +T: prioeq: 1: 80 + +# Unlock and exit +C: unlock: 0: 0 +W: unlocked: 0: 0 + diff --git a/scripts/rt-tester/t2-l1-pi.tst b/scripts/rt-tester/t2-l1-pi.tst new file mode 100644 index 000000000..cde1f189a --- /dev/null +++ b/scripts/rt-tester/t2-l1-pi.tst @@ -0,0 +1,82 @@ +# +# RT-Mutex test +# +# Op: C(ommand)/T(est)/W(ait) +# | opcode +# | | threadid: 0-7 +# | | | opcode argument +# | | | | +# C: lock: 0: 0 +# +# Commands +# +# opcode opcode argument +# schedother nice value +# schedfifo priority +# lock lock nr (0-7) +# locknowait lock nr (0-7) +# lockint lock nr (0-7) +# lockintnowait lock nr (0-7) +# lockcont lock nr (0-7) +# unlock lock nr (0-7) +# lockbkl lock nr (0-7) +# unlockbkl lock nr (0-7) +# signal 0 +# reset 0 +# resetevent 0 +# +# Tests / Wait +# +# opcode opcode argument +# +# prioeq priority +# priolt priority +# priogt priority +# nprioeq normal priority +# npriolt normal priority +# npriogt normal priority +# locked lock nr (0-7) +# blocked lock nr (0-7) +# blockedwake lock nr (0-7) +# unlocked lock nr (0-7) +# lockedbkl dont care +# blockedbkl dont care +# unlockedbkl dont care +# opcodeeq command opcode or number +# opcodelt number +# opcodegt number +# eventeq number +# eventgt number +# eventlt number + +# +# 2 threads 1 lock with priority inversion +# +C: resetevent: 0: 0 +W: opcodeeq: 0: 0 + +# Set schedulers +C: schedother: 0: 0 +C: schedfifo: 1: 80 + +# T0 lock L0 +C: locknowait: 0: 0 +W: locked: 0: 0 + +# T1 lock L0 +C: locknowait: 1: 0 +W: blocked: 1: 0 +T: prioeq: 0: 80 + +# T0 unlock L0 +C: unlock: 0: 0 +W: locked: 1: 0 + +# Verify T1 +W: unlocked: 0: 0 +T: priolt: 0: 1 + +# Unlock and exit +C: unlock: 1: 0 +W: unlocked: 1: 0 + diff --git a/scripts/rt-tester/t2-l1-signal.tst b/scripts/rt-tester/t2-l1-signal.tst new file mode 100644 index 000000000..3ab0bfc49 --- /dev/null +++ b/scripts/rt-tester/t2-l1-signal.tst @@ -0,0 +1,77 @@ +# +# RT-Mutex test +# +# Op: C(ommand)/T(est)/W(ait) +# | opcode +# | | threadid: 0-7 +# | | | opcode argument +# | | | | +# C: lock: 0: 0 +# +# Commands +# +# opcode opcode argument +# schedother nice value +# schedfifo priority +# lock lock nr (0-7) +# locknowait lock nr (0-7) +# lockint lock nr (0-7) +# lockintnowait lock nr (0-7) +# lockcont lock nr (0-7) +# unlock lock nr (0-7) +# lockbkl lock nr (0-7) +# unlockbkl lock nr (0-7) +# signal 0 +# reset 0 +# resetevent 0 +# +# Tests / Wait +# +# opcode opcode argument +# +# prioeq priority +# priolt priority +# priogt priority +# nprioeq normal priority +# npriolt normal priority +# npriogt normal priority +# locked lock nr (0-7) +# blocked lock nr (0-7) +# blockedwake lock nr (0-7) +# unlocked lock nr (0-7) +# lockedbkl dont care +# blockedbkl dont care +# unlockedbkl dont care +# opcodeeq command opcode or number +# opcodelt number +# opcodegt number +# eventeq number +# eventgt number +# eventlt number + +# +# 2 threads 1 lock with priority inversion +# +C: resetevent: 0: 0 +W: opcodeeq: 0: 0 + +# Set schedulers +C: schedother: 0: 0 +C: schedother: 1: 0 + +# T0 lock L0 +C: locknowait: 0: 0 +W: locked: 0: 0 + +# T1 lock L0 +C: lockintnowait: 1: 0 +W: blocked: 1: 0 + +# Interrupt T1 +C: signal: 1: 0 +W: unlocked: 1: 0 +T: opcodeeq: 1: -4 + +# Unlock and exit +C: unlock: 0: 0 +W: unlocked: 0: 0 diff --git a/scripts/rt-tester/t2-l2-2rt-deadlock.tst b/scripts/rt-tester/t2-l2-2rt-deadlock.tst new file mode 100644 index 000000000..f4b5d5d62 --- /dev/null +++ b/scripts/rt-tester/t2-l2-2rt-deadlock.tst @@ -0,0 +1,89 @@ +# +# RT-Mutex test +# +# Op: C(ommand)/T(est)/W(ait) +# | opcode +# | | threadid: 0-7 +# | | | opcode argument +# | | | | +# C: lock: 0: 0 +# +# Commands +# +# opcode opcode argument +# schedother nice value +# schedfifo priority +# lock lock nr (0-7) +# locknowait lock nr (0-7) +# lockint lock nr (0-7) +# lockintnowait lock nr (0-7) +# lockcont lock nr (0-7) +# unlock lock nr (0-7) +# lockbkl lock nr (0-7) +# unlockbkl lock nr (0-7) +# signal 0 +# reset 0 +# resetevent 0 +# +# Tests / Wait +# +# opcode opcode argument +# +# prioeq priority +# priolt priority +# priogt priority +# nprioeq normal priority +# npriolt normal priority +# npriogt normal priority +# locked lock nr (0-7) +# blocked lock nr (0-7) +# blockedwake lock nr (0-7) +# unlocked lock nr (0-7) +# lockedbkl dont care +# blockedbkl dont care +# unlockedbkl dont care +# opcodeeq command opcode or number +# opcodelt number +# opcodegt number +# eventeq number +# eventgt number +# eventlt number + +# +# 2 threads 2 lock +# +C: resetevent: 0: 0 +W: opcodeeq: 0: 0 + +# Set schedulers +C: schedfifo: 0: 80 +C: schedfifo: 1: 80 + +# T0 lock L0 +C: locknowait: 0: 0 +W: locked: 0: 0 + +# T1 lock L1 +C: locknowait: 1: 1 +W: locked: 1: 1 + +# T0 lock L1 +C: lockintnowait: 0: 1 +W: blocked: 0: 1 + +# T1 lock L0 +C: lockintnowait: 1: 0 +W: blocked: 1: 0 + +# Make deadlock go away +C: signal: 1: 0 +W: unlocked: 1: 0 +C: signal: 0: 0 +W: unlocked: 0: 1 + +# Unlock and exit +C: unlock: 0: 0 +W: unlocked: 0: 0 +C: unlock: 1: 1 +W: unlocked: 1: 1 + diff --git a/scripts/rt-tester/t3-l1-pi-1rt.tst b/scripts/rt-tester/t3-l1-pi-1rt.tst new file mode 100644 index 000000000..63440ca2c --- /dev/null +++ b/scripts/rt-tester/t3-l1-pi-1rt.tst @@ -0,0 +1,92 @@ +# +# rt-mutex test +# +# Op: C(ommand)/T(est)/W(ait) +# | opcode +# | | threadid: 0-7 +# | | | opcode argument +# | | | | +# C: lock: 0: 0 +# +# Commands +# +# opcode opcode argument +# schedother nice value +# schedfifo priority +# lock lock nr (0-7) +# locknowait lock nr (0-7) +# lockint lock nr (0-7) +# lockintnowait lock nr (0-7) +# lockcont lock nr (0-7) +# unlock lock nr (0-7) +# lockbkl lock nr (0-7) +# unlockbkl lock nr (0-7) +# signal thread to signal (0-7) +# reset 0 +# resetevent 0 +# +# Tests / Wait +# +# opcode opcode argument +# +# prioeq priority +# priolt priority +# priogt priority +# nprioeq normal priority +# npriolt normal priority +# npriogt normal priority +# locked lock nr (0-7) +# blocked lock nr (0-7) +# blockedwake lock nr (0-7) +# unlocked lock nr (0-7) +# lockedbkl dont care +# blockedbkl dont care +# unlockedbkl dont care +# opcodeeq command opcode or number +# opcodelt number +# opcodegt number +# eventeq number +# eventgt number +# eventlt number + +# +# 3 threads 1 lock PI +# +C: resetevent: 0: 0 +W: opcodeeq: 0: 0 + +# Set schedulers +C: schedother: 0: 0 +C: schedother: 1: 0 +C: schedfifo: 2: 82 + +# T0 lock L0 +C: locknowait: 0: 0 +W: locked: 0: 0 + +# T1 lock L0 +C: locknowait: 1: 0 +W: blocked: 1: 0 +T: priolt: 0: 1 + +# T2 lock L0 +C: locknowait: 2: 0 +W: blocked: 2: 0 +T: prioeq: 0: 82 + +# T0 unlock L0 +C: unlock: 0: 0 + +# Wait until T2 got the lock +W: locked: 2: 0 +W: unlocked: 0: 0 +T: priolt: 0: 1 + +# T2 unlock L0 +C: unlock: 2: 0 + +W: unlocked: 2: 0 +W: locked: 1: 0 + +C: unlock: 1: 0 +W: unlocked: 1: 0 diff --git a/scripts/rt-tester/t3-l1-pi-2rt.tst b/scripts/rt-tester/t3-l1-pi-2rt.tst new file mode 100644 index 000000000..e5816fe67 --- /dev/null +++ b/scripts/rt-tester/t3-l1-pi-2rt.tst @@ -0,0 +1,93 @@ +# +# rt-mutex test +# +# Op: C(ommand)/T(est)/W(ait) +# | opcode +# | | threadid: 0-7 +# | | | opcode argument +# | | | | +# C: lock: 0: 0 +# +# Commands +# +# opcode opcode argument +# schedother nice value +# schedfifo priority +# lock lock nr (0-7) +# locknowait lock nr (0-7) +# lockint lock nr (0-7) +# lockintnowait lock nr (0-7) +# lockcont lock nr (0-7) +# unlock lock nr (0-7) +# lockbkl lock nr (0-7) +# unlockbkl lock nr (0-7) +# signal thread to signal (0-7) +# reset 0 +# resetevent 0 +# +# Tests / Wait +# +# opcode opcode argument +# +# prioeq priority +# priolt priority +# priogt priority +# nprioeq normal priority +# npriolt normal priority +# npriogt normal priority +# locked lock nr (0-7) +# blocked lock nr (0-7) +# blockedwake lock nr (0-7) +# unlocked lock nr (0-7) +# lockedbkl dont care +# blockedbkl dont care +# unlockedbkl dont care +# opcodeeq command opcode or number +# opcodelt number +# opcodegt number +# eventeq number +# eventgt number +# eventlt number + +# +# 3 threads 1 lock PI +# +C: resetevent: 0: 0 +W: opcodeeq: 0: 0 + +# Set schedulers +C: schedother: 0: 0 +C: schedfifo: 1: 81 +C: schedfifo: 2: 82 + +# T0 lock L0 +C: locknowait: 0: 0 +W: locked: 0: 0 + +# T1 lock L0 +C: locknowait: 1: 0 +W: blocked: 1: 0 +T: prioeq: 0: 81 + +# T2 lock L0 +C: locknowait: 2: 0 +W: blocked: 2: 0 +T: prioeq: 0: 82 +T: prioeq: 1: 81 + +# T0 unlock L0 +C: unlock: 0: 0 + +# Wait until T2 got the lock +W: locked: 2: 0 +W: unlocked: 0: 0 +T: priolt: 0: 1 + +# T2 unlock L0 +C: unlock: 2: 0 + +W: unlocked: 2: 0 +W: locked: 1: 0 + +C: unlock: 1: 0 +W: unlocked: 1: 0 diff --git a/scripts/rt-tester/t3-l1-pi-3rt.tst b/scripts/rt-tester/t3-l1-pi-3rt.tst new file mode 100644 index 000000000..718b82b5d --- /dev/null +++ b/scripts/rt-tester/t3-l1-pi-3rt.tst @@ -0,0 +1,92 @@ +# +# rt-mutex test +# +# Op: C(ommand)/T(est)/W(ait) +# | opcode +# | | threadid: 0-7 +# | | | opcode argument +# | | | | +# C: lock: 0: 0 +# +# Commands +# +# opcode opcode argument +# schedother nice value +# schedfifo priority +# lock lock nr (0-7) +# locknowait lock nr (0-7) +# lockint lock nr (0-7) +# lockintnowait lock nr (0-7) +# lockcont lock nr (0-7) +# unlock lock nr (0-7) +# lockbkl lock nr (0-7) +# unlockbkl lock nr (0-7) +# signal thread to signal (0-7) +# reset 0 +# resetevent 0 +# +# Tests / Wait +# +# opcode opcode argument +# +# prioeq priority +# priolt priority +# priogt priority +# nprioeq normal priority +# npriolt normal priority +# npriogt normal priority +# locked lock nr (0-7) +# blocked lock nr (0-7) +# blockedwake lock nr (0-7) +# unlocked lock nr (0-7) +# lockedbkl dont care +# blockedbkl dont care +# unlockedbkl dont care +# opcodeeq command opcode or number +# opcodelt number +# opcodegt number +# eventeq number +# eventgt number +# eventlt number + +# +# 3 threads 1 lock PI +# +C: resetevent: 0: 0 +W: opcodeeq: 0: 0 + +# Set schedulers +C: schedfifo: 0: 80 +C: schedfifo: 1: 81 +C: schedfifo: 2: 82 + +# T0 lock L0 +C: locknowait: 0: 0 +W: locked: 0: 0 + +# T1 lock L0 +C: locknowait: 1: 0 +W: blocked: 1: 0 +T: prioeq: 0: 81 + +# T2 lock L0 +C: locknowait: 2: 0 +W: blocked: 2: 0 +T: prioeq: 0: 82 + +# T0 unlock L0 +C: unlock: 0: 0 + +# Wait until T2 got the lock +W: locked: 2: 0 +W: unlocked: 0: 0 +T: prioeq: 0: 80 + +# T2 unlock L0 +C: unlock: 2: 0 + +W: locked: 1: 0 +W: unlocked: 2: 0 + +C: unlock: 1: 0 +W: unlocked: 1: 0 diff --git a/scripts/rt-tester/t3-l1-pi-signal.tst b/scripts/rt-tester/t3-l1-pi-signal.tst new file mode 100644 index 000000000..c6e213563 --- /dev/null +++ b/scripts/rt-tester/t3-l1-pi-signal.tst @@ -0,0 +1,98 @@ +# +# rt-mutex test +# +# Op: C(ommand)/T(est)/W(ait) +# | opcode +# | | threadid: 0-7 +# | | | opcode argument +# | | | | +# C: lock: 0: 0 +# +# Commands +# +# opcode opcode argument +# schedother nice value +# schedfifo priority +# lock lock nr (0-7) +# locknowait lock nr (0-7) +# lockint lock nr (0-7) +# lockintnowait lock nr (0-7) +# lockcont lock nr (0-7) +# unlock lock nr (0-7) +# lockbkl lock nr (0-7) +# unlockbkl lock nr (0-7) +# signal thread to signal (0-7) +# reset 0 +# resetevent 0 +# +# Tests / Wait +# +# opcode opcode argument +# +# prioeq priority +# priolt priority +# priogt priority +# nprioeq normal priority +# npriolt normal priority +# npriogt normal priority +# locked lock nr (0-7) +# blocked lock nr (0-7) +# blockedwake lock nr (0-7) +# unlocked lock nr (0-7) +# lockedbkl dont care +# blockedbkl dont care +# unlockedbkl dont care +# opcodeeq command opcode or number +# opcodelt number +# opcodegt number +# eventeq number +# eventgt number +# eventlt number + +# Reset event counter +C: resetevent: 0: 0 +W: opcodeeq: 0: 0 + +# Set priorities +C: schedother: 0: 0 +C: schedfifo: 1: 80 +C: schedfifo: 2: 81 + +# T0 lock L0 +C: lock: 0: 0 +W: locked: 0: 0 + +# T1 lock L0, no wait in the wakeup path +C: locknowait: 1: 0 +W: blocked: 1: 0 +T: prioeq: 0: 80 +T: prioeq: 1: 80 + +# T2 lock L0 interruptible, no wait in the wakeup path +C: lockintnowait: 2: 0 +W: blocked: 2: 0 +T: prioeq: 0: 81 +T: prioeq: 1: 80 + +# Interrupt T2 +C: signal: 2: 2 +W: unlocked: 2: 0 +T: prioeq: 1: 80 +T: prioeq: 0: 80 + +T: locked: 0: 0 +T: blocked: 1: 0 + +# T0 unlock L0 +C: unlock: 0: 0 + +# Wait until T1 has locked L0 and exit +W: locked: 1: 0 +W: unlocked: 0: 0 +T: priolt: 0: 1 + +C: unlock: 1: 0 +W: unlocked: 1: 0 + + + diff --git a/scripts/rt-tester/t3-l1-pi-steal.tst b/scripts/rt-tester/t3-l1-pi-steal.tst new file mode 100644 index 000000000..f53749d59 --- /dev/null +++ b/scripts/rt-tester/t3-l1-pi-steal.tst @@ -0,0 +1,96 @@ +# +# rt-mutex test +# +# Op: C(ommand)/T(est)/W(ait) +# | opcode +# | | threadid: 0-7 +# | | | opcode argument +# | | | | +# C: lock: 0: 0 +# +# Commands +# +# opcode opcode argument +# schedother nice value +# schedfifo priority +# lock lock nr (0-7) +# locknowait lock nr (0-7) +# lockint lock nr (0-7) +# lockintnowait lock nr (0-7) +# lockcont lock nr (0-7) +# unlock lock nr (0-7) +# lockbkl lock nr (0-7) +# unlockbkl lock nr (0-7) +# signal thread to signal (0-7) +# reset 0 +# resetevent 0 +# +# Tests / Wait +# +# opcode opcode argument +# +# prioeq priority +# priolt priority +# priogt priority +# nprioeq normal priority +# npriolt normal priority +# npriogt normal priority +# locked lock nr (0-7) +# blocked lock nr (0-7) +# blockedwake lock nr (0-7) +# unlocked lock nr (0-7) +# lockedbkl dont care +# blockedbkl dont care +# unlockedbkl dont care +# opcodeeq command opcode or number +# opcodelt number +# opcodegt number +# eventeq number +# eventgt number +# eventlt number + +# +# 3 threads 1 lock PI steal pending ownership +# +C: resetevent: 0: 0 +W: opcodeeq: 0: 0 + +# Set schedulers +C: schedother: 0: 0 +C: schedfifo: 1: 80 +C: schedfifo: 2: 81 + +# T0 lock L0 +C: lock: 0: 0 +W: locked: 0: 0 + +# T1 lock L0 +C: lock: 1: 0 +W: blocked: 1: 0 +T: prioeq: 0: 80 + +# T0 unlock L0 +C: unlock: 0: 0 + +# Wait until T1 is in the wakeup loop +W: blockedwake: 1: 0 +T: priolt: 0: 1 + +# T2 lock L0 +C: lock: 2: 0 +# T1 leave wakeup loop +C: lockcont: 1: 0 + +# T2 must have the lock and T1 must be blocked +W: locked: 2: 0 +W: blocked: 1: 0 + +# T2 unlock L0 +C: unlock: 2: 0 + +# Wait until T1 is in the wakeup loop and let it run +W: blockedwake: 1: 0 +C: lockcont: 1: 0 +W: locked: 1: 0 +C: unlock: 1: 0 +W: unlocked: 1: 0 diff --git a/scripts/rt-tester/t3-l2-pi.tst b/scripts/rt-tester/t3-l2-pi.tst new file mode 100644 index 000000000..cdc3e4fd7 --- /dev/null +++ b/scripts/rt-tester/t3-l2-pi.tst @@ -0,0 +1,92 @@ +# +# rt-mutex test +# +# Op: C(ommand)/T(est)/W(ait) +# | opcode +# | | threadid: 0-7 +# | | | opcode argument +# | | | | +# C: lock: 0: 0 +# +# Commands +# +# opcode opcode argument +# schedother nice value +# schedfifo priority +# lock lock nr (0-7) +# locknowait lock nr (0-7) +# lockint lock nr (0-7) +# lockintnowait lock nr (0-7) +# lockcont lock nr (0-7) +# unlock lock nr (0-7) +# lockbkl lock nr (0-7) +# unlockbkl lock nr (0-7) +# signal thread to signal (0-7) +# reset 0 +# resetevent 0 +# +# Tests / Wait +# +# opcode opcode argument +# +# prioeq priority +# priolt priority +# priogt priority +# nprioeq normal priority +# npriolt normal priority +# npriogt normal priority +# locked lock nr (0-7) +# blocked lock nr (0-7) +# blockedwake lock nr (0-7) +# unlocked lock nr (0-7) +# lockedbkl dont care +# blockedbkl dont care +# unlockedbkl dont care +# opcodeeq command opcode or number +# opcodelt number +# opcodegt number +# eventeq number +# eventgt number +# eventlt number + +# +# 3 threads 2 lock PI +# +C: resetevent: 0: 0 +W: opcodeeq: 0: 0 + +# Set schedulers +C: schedother: 0: 0 +C: schedother: 1: 0 +C: schedfifo: 2: 82 + +# T0 lock L0 +C: locknowait: 0: 0 +W: locked: 0: 0 + +# T1 lock L0 +C: locknowait: 1: 0 +W: blocked: 1: 0 +T: priolt: 0: 1 + +# T2 lock L0 +C: locknowait: 2: 0 +W: blocked: 2: 0 +T: prioeq: 0: 82 + +# T0 unlock L0 +C: unlock: 0: 0 + +# Wait until T2 got the lock +W: locked: 2: 0 +W: unlocked: 0: 0 +T: priolt: 0: 1 + +# T2 unlock L0 +C: unlock: 2: 0 + +W: unlocked: 2: 0 +W: locked: 1: 0 + +C: unlock: 1: 0 +W: unlocked: 1: 0 diff --git a/scripts/rt-tester/t4-l2-pi-deboost.tst b/scripts/rt-tester/t4-l2-pi-deboost.tst new file mode 100644 index 000000000..baa14137f --- /dev/null +++ b/scripts/rt-tester/t4-l2-pi-deboost.tst @@ -0,0 +1,123 @@ +# +# rt-mutex test +# +# Op: C(ommand)/T(est)/W(ait) +# | opcode +# | | threadid: 0-7 +# | | | opcode argument +# | | | | +# C: lock: 0: 0 +# +# Commands +# +# opcode opcode argument +# schedother nice value +# schedfifo priority +# lock lock nr (0-7) +# locknowait lock nr (0-7) +# lockint lock nr (0-7) +# lockintnowait lock nr (0-7) +# lockcont lock nr (0-7) +# unlock lock nr (0-7) +# lockbkl lock nr (0-7) +# unlockbkl lock nr (0-7) +# signal thread to signal (0-7) +# reset 0 +# resetevent 0 +# +# Tests / Wait +# +# opcode opcode argument +# +# prioeq priority +# priolt priority +# priogt priority +# nprioeq normal priority +# npriolt normal priority +# npriogt normal priority +# locked lock nr (0-7) +# blocked lock nr (0-7) +# blockedwake lock nr (0-7) +# unlocked lock nr (0-7) +# lockedbkl dont care +# blockedbkl dont care +# unlockedbkl dont care +# opcodeeq command opcode or number +# opcodelt number +# opcodegt number +# eventeq number +# eventgt number +# eventlt number + +# +# 4 threads 2 lock PI +# +C: resetevent: 0: 0 +W: opcodeeq: 0: 0 + +# Set schedulers +C: schedother: 0: 0 +C: schedother: 1: 0 +C: schedfifo: 2: 82 +C: schedfifo: 3: 83 + +# T0 lock L0 +C: locknowait: 0: 0 +W: locked: 0: 0 + +# T1 lock L1 +C: locknowait: 1: 1 +W: locked: 1: 1 + +# T3 lock L0 +C: lockintnowait: 3: 0 +W: blocked: 3: 0 +T: prioeq: 0: 83 + +# T0 lock L1 +C: lock: 0: 1 +W: blocked: 0: 1 +T: prioeq: 1: 83 + +# T1 unlock L1 +C: unlock: 1: 1 + +# Wait until T0 is in the wakeup code +W: blockedwake: 0: 1 + +# Verify that T1 is unboosted +W: unlocked: 1: 1 +T: priolt: 1: 1 + +# T2 lock L1 (T0 is boosted and pending owner !) +C: locknowait: 2: 1 +W: blocked: 2: 1 +T: prioeq: 0: 83 + +# Interrupt T3 and wait until T3 returned +C: signal: 3: 0 +W: unlocked: 3: 0 + +# Verify prio of T0 (still pending owner, +# but T2 is enqueued due to the previous boost by T3 +T: prioeq: 0: 82 + +# Let T0 continue +C: lockcont: 0: 1 +W: locked: 0: 1 + +# Unlock L1 and let T2 get L1 +C: unlock: 0: 1 +W: locked: 2: 1 + +# Verify that T0 is unboosted +W: unlocked: 0: 1 +T: priolt: 0: 1 + +# Unlock everything and exit +C: unlock: 2: 1 +W: unlocked: 2: 1 + +C: unlock: 0: 0 +W: unlocked: 0: 0 + diff --git a/scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst b/scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst new file mode 100644 index 000000000..e6ec0c81b --- /dev/null +++ b/scripts/rt-tester/t5-l4-pi-boost-deboost-setsched.tst @@ -0,0 +1,183 @@ +# +# rt-mutex test +# +# Op: C(ommand)/T(est)/W(ait) +# | opcode +# | | threadid: 0-7 +# | | | opcode argument +# | | | | +# C: lock: 0: 0 +# +# Commands +# +# opcode opcode argument +# schedother nice value +# schedfifo priority +# lock lock nr (0-7) +# locknowait lock nr (0-7) +# lockint lock nr (0-7) +# lockintnowait lock nr (0-7) +# lockcont lock nr (0-7) +# unlock lock nr (0-7) +# lockbkl lock nr (0-7) +# unlockbkl lock nr (0-7) +# signal thread to signal (0-7) +# reset 0 +# resetevent 0 +# +# Tests / Wait +# +# opcode opcode argument +# +# prioeq priority +# priolt priority +# priogt priority +# nprioeq normal priority +# npriolt normal priority +# npriogt normal priority +# locked lock nr (0-7) +# blocked lock nr (0-7) +# blockedwake lock nr (0-7) +# unlocked lock nr (0-7) +# lockedbkl dont care +# blockedbkl dont care +# unlockedbkl dont care +# opcodeeq command opcode or number +# opcodelt number +# opcodegt number +# eventeq number +# eventgt number +# eventlt number + +# +# 5 threads 4 lock PI - modify priority of blocked threads +# +C: resetevent: 0: 0 +W: opcodeeq: 0: 0 + +# Set schedulers +C: schedother: 0: 0 +C: schedfifo: 1: 81 +C: schedfifo: 2: 82 +C: schedfifo: 3: 83 +C: schedfifo: 4: 84 + +# T0 lock L0 +C: locknowait: 0: 0 +W: locked: 0: 0 + +# T1 lock L1 +C: locknowait: 1: 1 +W: locked: 1: 1 + +# T1 lock L0 +C: lockintnowait: 1: 0 +W: blocked: 1: 0 +T: prioeq: 0: 81 + +# T2 lock L2 +C: locknowait: 2: 2 +W: locked: 2: 2 + +# T2 lock L1 +C: lockintnowait: 2: 1 +W: blocked: 2: 1 +T: prioeq: 0: 82 +T: prioeq: 1: 82 + +# T3 lock L3 +C: locknowait: 3: 3 +W: locked: 3: 3 + +# T3 lock L2 +C: lockintnowait: 3: 2 +W: blocked: 3: 2 +T: prioeq: 0: 83 +T: prioeq: 1: 83 +T: prioeq: 2: 83 + +# T4 lock L3 +C: lockintnowait: 4: 3 +W: blocked: 4: 3 +T: prioeq: 0: 84 +T: prioeq: 1: 84 +T: prioeq: 2: 84 +T: prioeq: 3: 84 + +# Reduce prio of T4 +C: schedfifo: 4: 80 +T: prioeq: 0: 83 +T: prioeq: 1: 83 +T: prioeq: 2: 83 +T: prioeq: 3: 83 +T: prioeq: 4: 80 + +# Increase prio of T4 +C: schedfifo: 4: 84 +T: prioeq: 0: 84 +T: prioeq: 1: 84 +T: prioeq: 2: 84 +T: prioeq: 3: 84 +T: prioeq: 4: 84 + +# Reduce prio of T3 +C: schedfifo: 3: 80 +T: prioeq: 0: 84 +T: prioeq: 1: 84 +T: prioeq: 2: 84 +T: prioeq: 3: 84 +T: prioeq: 4: 84 + +# Increase prio of T3 +C: schedfifo: 3: 85 +T: prioeq: 0: 85 +T: prioeq: 1: 85 +T: prioeq: 2: 85 +T: prioeq: 3: 85 +T: prioeq: 4: 84 + +# Reduce prio of T3 +C: schedfifo: 3: 83 +T: prioeq: 0: 84 +T: prioeq: 1: 84 +T: prioeq: 2: 84 +T: prioeq: 3: 84 +T: prioeq: 4: 84 + +# Signal T4 +C: signal: 4: 0 +W: unlocked: 4: 3 +T: prioeq: 0: 83 +T: prioeq: 1: 83 +T: prioeq: 2: 83 +T: prioeq: 3: 83 + +# Signal T3 +C: signal: 3: 0 +W: unlocked: 3: 2 +T: prioeq: 0: 82 +T: prioeq: 1: 82 +T: prioeq: 2: 82 + +# Signal T2 +C: signal: 2: 0 +W: unlocked: 2: 1 +T: prioeq: 0: 81 +T: prioeq: 1: 81 + +# Signal T1 +C: signal: 1: 0 +W: unlocked: 1: 0 +T: priolt: 0: 1 + +# Unlock and exit +C: unlock: 3: 3 +C: unlock: 2: 2 +C: unlock: 1: 1 +C: unlock: 0: 0 + +W: unlocked: 3: 3 +W: unlocked: 2: 2 +W: unlocked: 1: 1 +W: unlocked: 0: 0 + diff --git a/scripts/rt-tester/t5-l4-pi-boost-deboost.tst b/scripts/rt-tester/t5-l4-pi-boost-deboost.tst new file mode 100644 index 000000000..ca64f8bbf --- /dev/null +++ b/scripts/rt-tester/t5-l4-pi-boost-deboost.tst @@ -0,0 +1,143 @@ +# +# rt-mutex test +# +# Op: C(ommand)/T(est)/W(ait) +# | opcode +# | | threadid: 0-7 +# | | | opcode argument +# | | | | +# C: lock: 0: 0 +# +# Commands +# +# opcode opcode argument +# schedother nice value +# schedfifo priority +# lock lock nr (0-7) +# locknowait lock nr (0-7) +# lockint lock nr (0-7) +# lockintnowait lock nr (0-7) +# lockcont lock nr (0-7) +# unlock lock nr (0-7) +# lockbkl lock nr (0-7) +# unlockbkl lock nr (0-7) +# signal thread to signal (0-7) +# reset 0 +# resetevent 0 +# +# Tests / Wait +# +# opcode opcode argument +# +# prioeq priority +# priolt priority +# priogt priority +# nprioeq normal priority +# npriolt normal priority +# npriogt normal priority +# locked lock nr (0-7) +# blocked lock nr (0-7) +# blockedwake lock nr (0-7) +# unlocked lock nr (0-7) +# lockedbkl dont care +# blockedbkl dont care +# unlockedbkl dont care +# opcodeeq command opcode or number +# opcodelt number +# opcodegt number +# eventeq number +# eventgt number +# eventlt number + +# +# 5 threads 4 lock PI +# +C: resetevent: 0: 0 +W: opcodeeq: 0: 0 + +# Set schedulers +C: schedother: 0: 0 +C: schedfifo: 1: 81 +C: schedfifo: 2: 82 +C: schedfifo: 3: 83 +C: schedfifo: 4: 84 + +# T0 lock L0 +C: locknowait: 0: 0 +W: locked: 0: 0 + +# T1 lock L1 +C: locknowait: 1: 1 +W: locked: 1: 1 + +# T1 lock L0 +C: lockintnowait: 1: 0 +W: blocked: 1: 0 +T: prioeq: 0: 81 + +# T2 lock L2 +C: locknowait: 2: 2 +W: locked: 2: 2 + +# T2 lock L1 +C: lockintnowait: 2: 1 +W: blocked: 2: 1 +T: prioeq: 0: 82 +T: prioeq: 1: 82 + +# T3 lock L3 +C: locknowait: 3: 3 +W: locked: 3: 3 + +# T3 lock L2 +C: lockintnowait: 3: 2 +W: blocked: 3: 2 +T: prioeq: 0: 83 +T: prioeq: 1: 83 +T: prioeq: 2: 83 + +# T4 lock L3 +C: lockintnowait: 4: 3 +W: blocked: 4: 3 +T: prioeq: 0: 84 +T: prioeq: 1: 84 +T: prioeq: 2: 84 +T: prioeq: 3: 84 + +# Signal T4 +C: signal: 4: 0 +W: unlocked: 4: 3 +T: prioeq: 0: 83 +T: prioeq: 1: 83 +T: prioeq: 2: 83 +T: prioeq: 3: 83 + +# Signal T3 +C: signal: 3: 0 +W: unlocked: 3: 2 +T: prioeq: 0: 82 +T: prioeq: 1: 82 +T: prioeq: 2: 82 + +# Signal T2 +C: signal: 2: 0 +W: unlocked: 2: 1 +T: prioeq: 0: 81 +T: prioeq: 1: 81 + +# Signal T1 +C: signal: 1: 0 +W: unlocked: 1: 0 +T: priolt: 0: 1 + +# Unlock and exit +C: unlock: 3: 3 +C: unlock: 2: 2 +C: unlock: 1: 1 +C: unlock: 0: 0 + +W: unlocked: 3: 3 +W: unlocked: 2: 2 +W: unlocked: 1: 1 +W: unlocked: 0: 0 + diff --git a/sound/aoa/Kconfig b/sound/aoa/Kconfig new file mode 100644 index 000000000..2f4334d19 --- /dev/null +++ b/sound/aoa/Kconfig @@ -0,0 +1,18 @@ +menu "Apple Onboard Audio driver" + depends on SND!=n && PPC + +config SND_AOA + tristate "Apple Onboard Audio driver" + depends on SND + select SND_PCM + ---help--- + This option enables the new driver for the various + Apple Onboard Audio components. + +source "sound/aoa/fabrics/Kconfig" + +source "sound/aoa/codecs/Kconfig" + +source "sound/aoa/soundbus/Kconfig" + +endmenu diff --git a/sound/aoa/Makefile b/sound/aoa/Makefile new file mode 100644 index 000000000..a8c037f90 --- /dev/null +++ b/sound/aoa/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_SND_AOA) += core/ +obj-$(CONFIG_SND_AOA_SOUNDBUS) += soundbus/ +obj-$(CONFIG_SND_AOA) += fabrics/ +obj-$(CONFIG_SND_AOA) += codecs/ diff --git a/sound/aoa/aoa-gpio.h b/sound/aoa/aoa-gpio.h new file mode 100644 index 000000000..3a61f3115 --- /dev/null +++ b/sound/aoa/aoa-gpio.h @@ -0,0 +1,81 @@ +/* + * Apple Onboard Audio GPIO definitions + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + */ + +#ifndef __AOA_GPIO_H +#define __AOA_GPIO_H +#include <linux/workqueue.h> +#include <linux/mutex.h> +#include <asm/prom.h> + +typedef void (*notify_func_t)(void *data); + +enum notify_type { + AOA_NOTIFY_HEADPHONE, + AOA_NOTIFY_LINE_IN, + AOA_NOTIFY_LINE_OUT, +}; + +struct gpio_runtime; +struct gpio_methods { + /* for initialisation/de-initialisation of the GPIO layer */ + void (*init)(struct gpio_runtime *rt); + void (*exit)(struct gpio_runtime *rt); + + /* turn off headphone, speakers, lineout */ + void (*all_amps_off)(struct gpio_runtime *rt); + /* turn headphone, speakers, lineout back to previous setting */ + void (*all_amps_restore)(struct gpio_runtime *rt); + + void (*set_headphone)(struct gpio_runtime *rt, int on); + void (*set_speakers)(struct gpio_runtime *rt, int on); + void (*set_lineout)(struct gpio_runtime *rt, int on); + + int (*get_headphone)(struct gpio_runtime *rt); + int (*get_speakers)(struct gpio_runtime *rt); + int (*get_lineout)(struct gpio_runtime *rt); + + void (*set_hw_reset)(struct gpio_runtime *rt, int on); + + /* use this to be notified of any events. The notification + * function is passed the data, and is called in process + * context by the use of schedule_work. + * The interface for it is that setting a function to NULL + * removes it, and they return 0 if the operation succeeded, + * and -EBUSY if the notification is already assigned by + * someone else. */ + int (*set_notify)(struct gpio_runtime *rt, + enum notify_type type, + notify_func_t notify, + void *data); + /* returns 0 if not plugged in, 1 if plugged in + * or a negative error code */ + int (*get_detect)(struct gpio_runtime *rt, + enum notify_type type); +}; + +struct gpio_notification { + notify_func_t notify; + void *data; + void *gpio_private; + struct work_struct work; + struct mutex mutex; +}; + +struct gpio_runtime { + /* to be assigned by fabric */ + struct device_node *node; + /* since everyone needs this pointer anyway... */ + struct gpio_methods *methods; + /* to be used by the gpio implementation */ + int implementation_private; + struct gpio_notification headphone_notify; + struct gpio_notification line_in_notify; + struct gpio_notification line_out_notify; +}; + +#endif /* __AOA_GPIO_H */ diff --git a/sound/aoa/aoa.h b/sound/aoa/aoa.h new file mode 100644 index 000000000..378ef1e98 --- /dev/null +++ b/sound/aoa/aoa.h @@ -0,0 +1,131 @@ +/* + * Apple Onboard Audio definitions + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + */ + +#ifndef __AOA_H +#define __AOA_H +#include <asm/prom.h> +#include <linux/module.h> +/* So apparently there's a reason for requiring driver.h to be included first! */ +#include <sound/driver.h> +#include <sound/core.h> +#include <sound/asound.h> +#include <sound/control.h> +#include "aoa-gpio.h" +#include "soundbus/soundbus.h" + +#define MAX_CODEC_NAME_LEN 32 + +struct aoa_codec { + char name[MAX_CODEC_NAME_LEN]; + + struct module *owner; + + /* called when the fabric wants to init this codec. + * Do alsa card manipulations from here. */ + int (*init)(struct aoa_codec *codec); + + /* called when the fabric is done with the codec. + * The alsa card will be cleaned up so don't bother. */ + void (*exit)(struct aoa_codec *codec); + + /* May be NULL, but can be used by the fabric. + * Refcounting is the codec driver's responsibility */ + struct device_node *node; + + /* assigned by fabric before init() is called, points + * to the soundbus device. Cannot be NULL. */ + struct soundbus_dev *soundbus_dev; + + /* assigned by the fabric before init() is called, points + * to the fabric's gpio runtime record for the relevant + * device. */ + struct gpio_runtime *gpio; + + /* assigned by the fabric before init() is called, contains + * a codec specific bitmask of what outputs and inputs are + * actually connected */ + u32 connected; + + /* data the fabric can associate with this structure */ + void *fabric_data; + + /* private! */ + struct list_head list; + struct aoa_fabric *fabric; +}; + +/* return 0 on success */ +extern int +aoa_codec_register(struct aoa_codec *codec); +extern void +aoa_codec_unregister(struct aoa_codec *codec); + +#define MAX_LAYOUT_NAME_LEN 32 + +struct aoa_fabric { + char name[MAX_LAYOUT_NAME_LEN]; + + struct module *owner; + + /* once codecs register, they are passed here after. + * They are of course not initialised, since the + * fabric is responsible for initialising some fields + * in the codec structure! */ + int (*found_codec)(struct aoa_codec *codec); + /* called for each codec when it is removed, + * also in the case that aoa_fabric_unregister + * is called and all codecs are removed + * from this fabric. + * Also called if found_codec returned 0 but + * the codec couldn't initialise. */ + void (*remove_codec)(struct aoa_codec *codec); + /* If found_codec returned 0, and the codec + * could be initialised, this is called. */ + void (*attached_codec)(struct aoa_codec *codec); +}; + +/* return 0 on success, -EEXIST if another fabric is + * registered, -EALREADY if the same fabric is registered. + * Passing NULL can be used to test for the presence + * of another fabric, if -EALREADY is returned there is + * no other fabric present. + * In the case that the function returns -EALREADY + * and the fabric passed is not NULL, all codecs + * that are not assigned yet are passed to the fabric + * again for reconsideration. */ +extern int +aoa_fabric_register(struct aoa_fabric *fabric); + +/* it is vital to call this when the fabric exits! + * When calling, the remove_codec will be called + * for all codecs, unless it is NULL. */ +extern void +aoa_fabric_unregister(struct aoa_fabric *fabric); + +/* if for some reason you want to get rid of a codec + * before the fabric is removed, use this. + * Note that remove_codec is called for it! */ +extern void +aoa_fabric_unlink_codec(struct aoa_codec *codec); + +/* alsa help methods */ +struct aoa_card { + struct snd_card *alsa_card; +}; + +extern int aoa_snd_device_new(snd_device_type_t type, + void * device_data, struct snd_device_ops * ops); +extern struct snd_card *aoa_get_card(void); +extern int aoa_snd_ctl_add(struct snd_kcontrol* control); + +/* GPIO stuff */ +extern struct gpio_methods *pmf_gpio_methods; +extern struct gpio_methods *ftr_gpio_methods; +/* extern struct gpio_methods *map_gpio_methods; */ + +#endif /* __AOA_H */ diff --git a/sound/aoa/codecs/Kconfig b/sound/aoa/codecs/Kconfig new file mode 100644 index 000000000..90cf58f68 --- /dev/null +++ b/sound/aoa/codecs/Kconfig @@ -0,0 +1,32 @@ +config SND_AOA_ONYX + tristate "support Onyx chip" + depends on SND_AOA + ---help--- + This option enables support for the Onyx (pcm3052) + codec chip found in the latest Apple machines + (most of those with digital audio output). + +#config SND_AOA_TOPAZ +# tristate "support Topaz chips" +# depends on SND_AOA +# ---help--- +# This option enables support for the Topaz (CS84xx) +# codec chips found in the latest Apple machines, +# these chips do the digital input and output on +# some PowerMacs. + +config SND_AOA_TAS + tristate "support TAS chips" + depends on SND_AOA + ---help--- + This option enables support for the tas chips + found in a lot of Apple Machines, especially + iBooks and PowerBooks without digital. + +config SND_AOA_TOONIE + tristate "support Toonie chip" + depends on SND_AOA + ---help--- + This option enables support for the toonie codec + found in the Mac Mini. If you have a Mac Mini and + want to hear sound, select this option. diff --git a/sound/aoa/codecs/Makefile b/sound/aoa/codecs/Makefile new file mode 100644 index 000000000..31cbe68fd --- /dev/null +++ b/sound/aoa/codecs/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_SND_AOA_ONYX) += snd-aoa-codec-onyx.o +obj-$(CONFIG_SND_AOA_TAS) += snd-aoa-codec-tas.o +obj-$(CONFIG_SND_AOA_TOONIE) += snd-aoa-codec-toonie.o diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.c b/sound/aoa/codecs/snd-aoa-codec-onyx.c new file mode 100644 index 000000000..0b7650788 --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-onyx.c @@ -0,0 +1,1113 @@ +/* + * Apple Onboard Audio driver for Onyx codec + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + * + * + * This is a driver for the pcm3052 codec chip (codenamed Onyx) + * that is present in newer Apple hardware (with digital output). + * + * The Onyx codec has the following connections (listed by the bit + * to be used in aoa_codec.connected): + * 0: analog output + * 1: digital output + * 2: line input + * 3: microphone input + * Note that even though I know of no machine that has for example + * the digital output connected but not the analog, I have handled + * all the different cases in the code so that this driver may serve + * as a good example of what to do. + * + * NOTE: This driver assumes that there's at most one chip to be + * used with one alsa card, in form of creating all kinds + * of mixer elements without regard for their existence. + * But snd-aoa assumes that there's at most one card, so + * this means you can only have one onyx on a system. This + * should probably be fixed by changing the assumption of + * having just a single card on a system, and making the + * 'card' pointer accessible to anyone who needs it instead + * of hiding it in the aoa_snd_* functions... + * + */ +#include <linux/delay.h> +#include <linux/module.h> +MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa"); + +#include "snd-aoa-codec-onyx.h" +#include "../aoa.h" +#include "../soundbus/soundbus.h" + + +#define PFX "snd-aoa-codec-onyx: " + +struct onyx { + /* cache registers 65 to 80, they are write-only! */ + u8 cache[16]; + struct i2c_client i2c; + struct aoa_codec codec; + u32 initialised:1, + spdif_locked:1, + analog_locked:1, + original_mute:2; + int open_count; + struct codec_info *codec_info; + + /* mutex serializes concurrent access to the device + * and this structure. + */ + struct mutex mutex; +}; +#define codec_to_onyx(c) container_of(c, struct onyx, codec) + +/* both return 0 if all ok, else on error */ +static int onyx_read_register(struct onyx *onyx, u8 reg, u8 *value) +{ + s32 v; + + if (reg != ONYX_REG_CONTROL) { + *value = onyx->cache[reg-FIRSTREGISTER]; + return 0; + } + v = i2c_smbus_read_byte_data(&onyx->i2c, reg); + if (v < 0) + return -1; + *value = (u8)v; + onyx->cache[ONYX_REG_CONTROL-FIRSTREGISTER] = *value; + return 0; +} + +static int onyx_write_register(struct onyx *onyx, u8 reg, u8 value) +{ + int result; + + result = i2c_smbus_write_byte_data(&onyx->i2c, reg, value); + if (!result) + onyx->cache[reg-FIRSTREGISTER] = value; + return result; +} + +/* alsa stuff */ + +static int onyx_dev_register(struct snd_device *dev) +{ + return 0; +} + +static struct snd_device_ops ops = { + .dev_register = onyx_dev_register, +}; + +/* this is necessary because most alsa mixer programs + * can't properly handle the negative range */ +#define VOLUME_RANGE_SHIFT 128 + +static int onyx_snd_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = -128 + VOLUME_RANGE_SHIFT; + uinfo->value.integer.max = -1 + VOLUME_RANGE_SHIFT; + return 0; +} + +static int onyx_snd_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + s8 l, r; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l); + onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r); + mutex_unlock(&onyx->mutex); + + ucontrol->value.integer.value[0] = l + VOLUME_RANGE_SHIFT; + ucontrol->value.integer.value[1] = r + VOLUME_RANGE_SHIFT; + + return 0; +} + +static int onyx_snd_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + s8 l, r; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l); + onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r); + + if (l + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[0] && + r + VOLUME_RANGE_SHIFT == ucontrol->value.integer.value[1]) { + mutex_unlock(&onyx->mutex); + return 0; + } + + onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, + ucontrol->value.integer.value[0] + - VOLUME_RANGE_SHIFT); + onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, + ucontrol->value.integer.value[1] + - VOLUME_RANGE_SHIFT); + mutex_unlock(&onyx->mutex); + + return 1; +} + +static struct snd_kcontrol_new volume_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Master Playback Volume", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = onyx_snd_vol_info, + .get = onyx_snd_vol_get, + .put = onyx_snd_vol_put, +}; + +/* like above, this is necessary because a lot + * of alsa mixer programs don't handle ranges + * that don't start at 0 properly. + * even alsamixer is one of them... */ +#define INPUTGAIN_RANGE_SHIFT (-3) + +static int onyx_snd_inputgain_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 3 + INPUTGAIN_RANGE_SHIFT; + uinfo->value.integer.max = 28 + INPUTGAIN_RANGE_SHIFT; + return 0; +} + +static int onyx_snd_inputgain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + u8 ig; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &ig); + mutex_unlock(&onyx->mutex); + + ucontrol->value.integer.value[0] = + (ig & ONYX_ADC_PGA_GAIN_MASK) + INPUTGAIN_RANGE_SHIFT; + + return 0; +} + +static int onyx_snd_inputgain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + u8 v, n; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); + n = v; + n &= ~ONYX_ADC_PGA_GAIN_MASK; + n |= (ucontrol->value.integer.value[0] - INPUTGAIN_RANGE_SHIFT) + & ONYX_ADC_PGA_GAIN_MASK; + onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, n); + mutex_unlock(&onyx->mutex); + + return n != v; +} + +static struct snd_kcontrol_new inputgain_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Master Capture Volume", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = onyx_snd_inputgain_info, + .get = onyx_snd_inputgain_get, + .put = onyx_snd_inputgain_put, +}; + +static int onyx_snd_capture_source_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static char *texts[] = { "Line-In", "Microphone" }; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = 2; + if (uinfo->value.enumerated.item > 1) + uinfo->value.enumerated.item = 1; + strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); + return 0; +} + +static int onyx_snd_capture_source_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + s8 v; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); + mutex_unlock(&onyx->mutex); + + ucontrol->value.enumerated.item[0] = !!(v&ONYX_ADC_INPUT_MIC); + + return 0; +} + +static void onyx_set_capture_source(struct onyx *onyx, int mic) +{ + s8 v; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &v); + v &= ~ONYX_ADC_INPUT_MIC; + if (mic) + v |= ONYX_ADC_INPUT_MIC; + onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, v); + mutex_unlock(&onyx->mutex); +} + +static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + onyx_set_capture_source(snd_kcontrol_chip(kcontrol), + ucontrol->value.enumerated.item[0]); + return 1; +} + +static struct snd_kcontrol_new capture_source_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* If we name this 'Input Source', it properly shows up in + * alsamixer as a selection, * but it's shown under the + * 'Playback' category. + * If I name it 'Capture Source', it shows up in strange + * ways (two bools of which one can be selected at a + * time) but at least it's shown in the 'Capture' + * category. + * I was told that this was due to backward compatibility, + * but I don't understand then why the mangling is *not* + * done when I name it "Input Source"..... + */ + .name = "Capture Source", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = onyx_snd_capture_source_info, + .get = onyx_snd_capture_source_get, + .put = onyx_snd_capture_source_put, +}; + +static int onyx_snd_mute_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int onyx_snd_mute_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + u8 c; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &c); + mutex_unlock(&onyx->mutex); + + ucontrol->value.integer.value[0] = !(c & ONYX_MUTE_LEFT); + ucontrol->value.integer.value[1] = !(c & ONYX_MUTE_RIGHT); + + return 0; +} + +static int onyx_snd_mute_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + u8 v = 0, c = 0; + int err = -EBUSY; + + mutex_lock(&onyx->mutex); + if (onyx->analog_locked) + goto out_unlock; + + onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); + c = v; + c &= ~(ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT); + if (!ucontrol->value.integer.value[0]) + c |= ONYX_MUTE_LEFT; + if (!ucontrol->value.integer.value[1]) + c |= ONYX_MUTE_RIGHT; + err = onyx_write_register(onyx, ONYX_REG_DAC_CONTROL, c); + + out_unlock: + mutex_unlock(&onyx->mutex); + + return !err ? (v != c) : err; +} + +static struct snd_kcontrol_new mute_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Master Playback Switch", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = onyx_snd_mute_info, + .get = onyx_snd_mute_get, + .put = onyx_snd_mute_put, +}; + + +static int onyx_snd_single_bit_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +#define FLAG_POLARITY_INVERT 1 +#define FLAG_SPDIFLOCK 2 + +static int onyx_snd_single_bit_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + u8 c; + long int pv = kcontrol->private_value; + u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT; + u8 address = (pv >> 8) & 0xff; + u8 mask = pv & 0xff; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, address, &c); + mutex_unlock(&onyx->mutex); + + ucontrol->value.integer.value[0] = !!(c & mask) ^ polarity; + + return 0; +} + +static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + u8 v = 0, c = 0; + int err; + long int pv = kcontrol->private_value; + u8 polarity = (pv >> 16) & FLAG_POLARITY_INVERT; + u8 spdiflock = (pv >> 16) & FLAG_SPDIFLOCK; + u8 address = (pv >> 8) & 0xff; + u8 mask = pv & 0xff; + + mutex_lock(&onyx->mutex); + if (spdiflock && onyx->spdif_locked) { + /* even if alsamixer doesn't care.. */ + err = -EBUSY; + goto out_unlock; + } + onyx_read_register(onyx, address, &v); + c = v; + c &= ~(mask); + if (!!ucontrol->value.integer.value[0] ^ polarity) + c |= mask; + err = onyx_write_register(onyx, address, c); + + out_unlock: + mutex_unlock(&onyx->mutex); + + return !err ? (v != c) : err; +} + +#define SINGLE_BIT(n, type, description, address, mask, flags) \ +static struct snd_kcontrol_new n##_control = { \ + .iface = SNDRV_CTL_ELEM_IFACE_##type, \ + .name = description, \ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .info = onyx_snd_single_bit_info, \ + .get = onyx_snd_single_bit_get, \ + .put = onyx_snd_single_bit_put, \ + .private_value = (flags << 16) | (address << 8) | mask \ +} + +SINGLE_BIT(spdif, + MIXER, + SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH), + ONYX_REG_DIG_INFO4, + ONYX_SPDIF_ENABLE, + FLAG_SPDIFLOCK); +SINGLE_BIT(ovr1, + MIXER, + "Oversampling Rate", + ONYX_REG_DAC_CONTROL, + ONYX_OVR1, + 0); +SINGLE_BIT(flt0, + MIXER, + "Fast Digital Filter Rolloff", + ONYX_REG_DAC_FILTER, + ONYX_ROLLOFF_FAST, + FLAG_POLARITY_INVERT); +SINGLE_BIT(hpf, + MIXER, + "Highpass Filter", + ONYX_REG_ADC_HPF_BYPASS, + ONYX_HPF_DISABLE, + FLAG_POLARITY_INVERT); +SINGLE_BIT(dm12, + MIXER, + "Digital De-Emphasis", + ONYX_REG_DAC_DEEMPH, + ONYX_DIGDEEMPH_CTRL, + 0); + +static int onyx_spdif_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; + uinfo->count = 1; + return 0; +} + +static int onyx_spdif_mask_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + /* datasheet page 30, all others are 0 */ + ucontrol->value.iec958.status[0] = 0x3e; + ucontrol->value.iec958.status[1] = 0xff; + + ucontrol->value.iec958.status[3] = 0x3f; + ucontrol->value.iec958.status[4] = 0x0f; + + return 0; +} + +static struct snd_kcontrol_new onyx_spdif_mask = { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK), + .info = onyx_spdif_info, + .get = onyx_spdif_mask_get, +}; + +static int onyx_spdif_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + u8 v; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v); + ucontrol->value.iec958.status[0] = v & 0x3e; + + onyx_read_register(onyx, ONYX_REG_DIG_INFO2, &v); + ucontrol->value.iec958.status[1] = v; + + onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v); + ucontrol->value.iec958.status[3] = v & 0x3f; + + onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); + ucontrol->value.iec958.status[4] = v & 0x0f; + mutex_unlock(&onyx->mutex); + + return 0; +} + +static int onyx_spdif_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct onyx *onyx = snd_kcontrol_chip(kcontrol); + u8 v; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_DIG_INFO1, &v); + v = (v & ~0x3e) | (ucontrol->value.iec958.status[0] & 0x3e); + onyx_write_register(onyx, ONYX_REG_DIG_INFO1, v); + + v = ucontrol->value.iec958.status[1]; + onyx_write_register(onyx, ONYX_REG_DIG_INFO2, v); + + onyx_read_register(onyx, ONYX_REG_DIG_INFO3, &v); + v = (v & ~0x3f) | (ucontrol->value.iec958.status[3] & 0x3f); + onyx_write_register(onyx, ONYX_REG_DIG_INFO3, v); + + onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); + v = (v & ~0x0f) | (ucontrol->value.iec958.status[4] & 0x0f); + onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v); + mutex_unlock(&onyx->mutex); + + return 1; +} + +static struct snd_kcontrol_new onyx_spdif_ctrl = { + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), + .info = onyx_spdif_info, + .get = onyx_spdif_get, + .put = onyx_spdif_put, +}; + +/* our registers */ + +static u8 register_map[] = { + ONYX_REG_DAC_ATTEN_LEFT, + ONYX_REG_DAC_ATTEN_RIGHT, + ONYX_REG_CONTROL, + ONYX_REG_DAC_CONTROL, + ONYX_REG_DAC_DEEMPH, + ONYX_REG_DAC_FILTER, + ONYX_REG_DAC_OUTPHASE, + ONYX_REG_ADC_CONTROL, + ONYX_REG_ADC_HPF_BYPASS, + ONYX_REG_DIG_INFO1, + ONYX_REG_DIG_INFO2, + ONYX_REG_DIG_INFO3, + ONYX_REG_DIG_INFO4 +}; + +static u8 initial_values[ARRAY_SIZE(register_map)] = { + 0x80, 0x80, /* muted */ + ONYX_MRST | ONYX_SRST, /* but handled specially! */ + ONYX_MUTE_LEFT | ONYX_MUTE_RIGHT, + 0, /* no deemphasis */ + ONYX_DAC_FILTER_ALWAYS, + ONYX_OUTPHASE_INVERTED, + (-1 /*dB*/ + 8) & 0xF, /* line in selected, -1 dB gain*/ + ONYX_ADC_HPF_ALWAYS, + (1<<2), /* pcm audio */ + 2, /* category: pcm coder */ + 0, /* sampling frequency 44.1 kHz, clock accuracy level II */ + 1 /* 24 bit depth */ +}; + +/* reset registers of chip, either to initial or to previous values */ +static int onyx_register_init(struct onyx *onyx) +{ + int i; + u8 val; + u8 regs[sizeof(initial_values)]; + + if (!onyx->initialised) { + memcpy(regs, initial_values, sizeof(initial_values)); + if (onyx_read_register(onyx, ONYX_REG_CONTROL, &val)) + return -1; + val &= ~ONYX_SILICONVERSION; + val |= initial_values[3]; + regs[3] = val; + } else { + for (i=0; i<sizeof(register_map); i++) + regs[i] = onyx->cache[register_map[i]-FIRSTREGISTER]; + } + + for (i=0; i<sizeof(register_map); i++) { + if (onyx_write_register(onyx, register_map[i], regs[i])) + return -1; + } + onyx->initialised = 1; + return 0; +} + +static struct transfer_info onyx_transfers[] = { + /* this is first so we can skip it if no input is present... + * No hardware exists with that, but it's here as an example + * of what to do :) */ + { + /* analog input */ + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_BE, + .rates = SNDRV_PCM_RATE_8000_96000, + .transfer_in = 1, + .must_be_clock_source = 0, + .tag = 0, + }, + { + /* if analog and digital are currently off, anything should go, + * so this entry describes everything we can do... */ + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_BE +#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE + | SNDRV_PCM_FMTBIT_COMPRESSED_16BE +#endif + , + .rates = SNDRV_PCM_RATE_8000_96000, + .tag = 0, + }, + { + /* analog output */ + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_BE, + .rates = SNDRV_PCM_RATE_8000_96000, + .transfer_in = 0, + .must_be_clock_source = 0, + .tag = 1, + }, + { + /* digital pcm output, also possible for analog out */ + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_BE, + .rates = SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000, + .transfer_in = 0, + .must_be_clock_source = 0, + .tag = 2, + }, +#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE +Once alsa gets supports for this kind of thing we can add it... + { + /* digital compressed output */ + .formats = SNDRV_PCM_FMTBIT_COMPRESSED_16BE, + .rates = SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000, + .tag = 2, + }, +#endif + {} +}; + +static int onyx_usable(struct codec_info_item *cii, + struct transfer_info *ti, + struct transfer_info *out) +{ + u8 v; + struct onyx *onyx = cii->codec_data; + int spdif_enabled, analog_enabled; + + mutex_lock(&onyx->mutex); + onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); + spdif_enabled = !!(v & ONYX_SPDIF_ENABLE); + onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); + analog_enabled = + (v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT)) + != (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT); + mutex_unlock(&onyx->mutex); + + switch (ti->tag) { + case 0: return 1; + case 1: return analog_enabled; + case 2: return spdif_enabled; + } + return 1; +} + +static int onyx_prepare(struct codec_info_item *cii, + struct bus_info *bi, + struct snd_pcm_substream *substream) +{ + u8 v; + struct onyx *onyx = cii->codec_data; + int err = -EBUSY; + + mutex_lock(&onyx->mutex); + +#ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE + if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) { + /* mute and lock analog output */ + onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); + if (onyx_write_register(onyx + ONYX_REG_DAC_CONTROL, + v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT)) + goto out_unlock; + onyx->analog_locked = 1; + err = 0; + goto out_unlock; + } +#endif + switch (substream->runtime->rate) { + case 32000: + case 44100: + case 48000: + /* these rates are ok for all outputs */ + /* FIXME: program spdif channel control bits here so that + * userspace doesn't have to if it only plays pcm! */ + err = 0; + goto out_unlock; + default: + /* got some rate that the digital output can't do, + * so disable and lock it */ + onyx_read_register(cii->codec_data, ONYX_REG_DIG_INFO4, &v); + if (onyx_write_register(onyx, + ONYX_REG_DIG_INFO4, + v & ~ONYX_SPDIF_ENABLE)) + goto out_unlock; + onyx->spdif_locked = 1; + err = 0; + goto out_unlock; + } + + out_unlock: + mutex_unlock(&onyx->mutex); + + return err; +} + +static int onyx_open(struct codec_info_item *cii, + struct snd_pcm_substream *substream) +{ + struct onyx *onyx = cii->codec_data; + + mutex_lock(&onyx->mutex); + onyx->open_count++; + mutex_unlock(&onyx->mutex); + + return 0; +} + +static int onyx_close(struct codec_info_item *cii, + struct snd_pcm_substream *substream) +{ + struct onyx *onyx = cii->codec_data; + + mutex_lock(&onyx->mutex); + onyx->open_count--; + if (!onyx->open_count) + onyx->spdif_locked = onyx->analog_locked = 0; + mutex_unlock(&onyx->mutex); + + return 0; +} + +static int onyx_switch_clock(struct codec_info_item *cii, + enum clock_switch what) +{ + struct onyx *onyx = cii->codec_data; + + mutex_lock(&onyx->mutex); + /* this *MUST* be more elaborate later... */ + switch (what) { + case CLOCK_SWITCH_PREPARE_SLAVE: + onyx->codec.gpio->methods->all_amps_off(onyx->codec.gpio); + break; + case CLOCK_SWITCH_SLAVE: + onyx->codec.gpio->methods->all_amps_restore(onyx->codec.gpio); + break; + default: /* silence warning */ + break; + } + mutex_unlock(&onyx->mutex); + + return 0; +} + +#ifdef CONFIG_PM + +static int onyx_suspend(struct codec_info_item *cii, pm_message_t state) +{ + struct onyx *onyx = cii->codec_data; + u8 v; + int err = -ENXIO; + + mutex_lock(&onyx->mutex); + if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v)) + goto out_unlock; + onyx_write_register(onyx, ONYX_REG_CONTROL, v | ONYX_ADPSV | ONYX_DAPSV); + /* Apple does a sleep here but the datasheet says to do it on resume */ + err = 0; + out_unlock: + mutex_unlock(&onyx->mutex); + + return err; +} + +static int onyx_resume(struct codec_info_item *cii) +{ + struct onyx *onyx = cii->codec_data; + u8 v; + int err = -ENXIO; + + mutex_lock(&onyx->mutex); + /* take codec out of suspend */ + if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v)) + goto out_unlock; + onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV)); + /* FIXME: should divide by sample rate, but 8k is the lowest we go */ + msleep(2205000/8000); + /* reset all values */ + onyx_register_init(onyx); + err = 0; + out_unlock: + mutex_unlock(&onyx->mutex); + + return err; +} + +#endif /* CONFIG_PM */ + +static struct codec_info onyx_codec_info = { + .transfers = onyx_transfers, + .sysclock_factor = 256, + .bus_factor = 64, + .owner = THIS_MODULE, + .usable = onyx_usable, + .prepare = onyx_prepare, + .open = onyx_open, + .close = onyx_close, + .switch_clock = onyx_switch_clock, +#ifdef CONFIG_PM + .suspend = onyx_suspend, + .resume = onyx_resume, +#endif +}; + +static int onyx_init_codec(struct aoa_codec *codec) +{ + struct onyx *onyx = codec_to_onyx(codec); + struct snd_kcontrol *ctl; + struct codec_info *ci = &onyx_codec_info; + u8 v; + int err; + + if (!onyx->codec.gpio || !onyx->codec.gpio->methods) { + printk(KERN_ERR PFX "gpios not assigned!!\n"); + return -EINVAL; + } + + onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); + msleep(1); + onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1); + msleep(1); + onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); + msleep(1); + + if (onyx_register_init(onyx)) { + printk(KERN_ERR PFX "failed to initialise onyx registers\n"); + return -ENODEV; + } + + if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, onyx, &ops)) { + printk(KERN_ERR PFX "failed to create onyx snd device!\n"); + return -ENODEV; + } + + /* nothing connected? what a joke! */ + if ((onyx->codec.connected & 0xF) == 0) + return -ENOTCONN; + + /* if no inputs are present... */ + if ((onyx->codec.connected & 0xC) == 0) { + if (!onyx->codec_info) + onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL); + if (!onyx->codec_info) + return -ENOMEM; + ci = onyx->codec_info; + *ci = onyx_codec_info; + ci->transfers++; + } + + /* if no outputs are present... */ + if ((onyx->codec.connected & 3) == 0) { + if (!onyx->codec_info) + onyx->codec_info = kmalloc(sizeof(struct codec_info), GFP_KERNEL); + if (!onyx->codec_info) + return -ENOMEM; + ci = onyx->codec_info; + /* this is fine as there have to be inputs + * if we end up in this part of the code */ + *ci = onyx_codec_info; + ci->transfers[1].formats = 0; + } + + if (onyx->codec.soundbus_dev->attach_codec(onyx->codec.soundbus_dev, + aoa_get_card(), + ci, onyx)) { + printk(KERN_ERR PFX "error creating onyx pcm\n"); + return -ENODEV; + } +#define ADDCTL(n) \ + do { \ + ctl = snd_ctl_new1(&n, onyx); \ + if (ctl) { \ + ctl->id.device = \ + onyx->codec.soundbus_dev->pcm->device; \ + err = aoa_snd_ctl_add(ctl); \ + if (err) \ + goto error; \ + } \ + } while (0) + + if (onyx->codec.soundbus_dev->pcm) { + /* give the user appropriate controls + * depending on what inputs are connected */ + if ((onyx->codec.connected & 0xC) == 0xC) + ADDCTL(capture_source_control); + else if (onyx->codec.connected & 4) + onyx_set_capture_source(onyx, 0); + else + onyx_set_capture_source(onyx, 1); + if (onyx->codec.connected & 0xC) + ADDCTL(inputgain_control); + + /* depending on what output is connected, + * give the user appropriate controls */ + if (onyx->codec.connected & 1) { + ADDCTL(volume_control); + ADDCTL(mute_control); + ADDCTL(ovr1_control); + ADDCTL(flt0_control); + ADDCTL(hpf_control); + ADDCTL(dm12_control); + /* spdif control defaults to off */ + } + if (onyx->codec.connected & 2) { + ADDCTL(onyx_spdif_mask); + ADDCTL(onyx_spdif_ctrl); + } + if ((onyx->codec.connected & 3) == 3) + ADDCTL(spdif_control); + /* if only S/PDIF is connected, enable it unconditionally */ + if ((onyx->codec.connected & 3) == 2) { + onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); + v |= ONYX_SPDIF_ENABLE; + onyx_write_register(onyx, ONYX_REG_DIG_INFO4, v); + } + } +#undef ADDCTL + printk(KERN_INFO PFX "attached to onyx codec via i2c\n"); + + return 0; + error: + onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx); + snd_device_free(aoa_get_card(), onyx); + return err; +} + +static void onyx_exit_codec(struct aoa_codec *codec) +{ + struct onyx *onyx = codec_to_onyx(codec); + + if (!onyx->codec.soundbus_dev) { + printk(KERN_ERR PFX "onyx_exit_codec called without soundbus_dev!\n"); + return; + } + onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx); +} + +static struct i2c_driver onyx_driver; + +static int onyx_create(struct i2c_adapter *adapter, + struct device_node *node, + int addr) +{ + struct onyx *onyx; + u8 dummy; + + onyx = kzalloc(sizeof(struct onyx), GFP_KERNEL); + + if (!onyx) + return -ENOMEM; + + mutex_init(&onyx->mutex); + onyx->i2c.driver = &onyx_driver; + onyx->i2c.adapter = adapter; + onyx->i2c.addr = addr & 0x7f; + strlcpy(onyx->i2c.name, "onyx audio codec", I2C_NAME_SIZE-1); + + if (i2c_attach_client(&onyx->i2c)) { + printk(KERN_ERR PFX "failed to attach to i2c\n"); + goto fail; + } + + /* we try to read from register ONYX_REG_CONTROL + * to check if the codec is present */ + if (onyx_read_register(onyx, ONYX_REG_CONTROL, &dummy) != 0) { + i2c_detach_client(&onyx->i2c); + printk(KERN_ERR PFX "failed to read control register\n"); + goto fail; + } + + strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN-1); + onyx->codec.owner = THIS_MODULE; + onyx->codec.init = onyx_init_codec; + onyx->codec.exit = onyx_exit_codec; + onyx->codec.node = of_node_get(node); + + if (aoa_codec_register(&onyx->codec)) { + i2c_detach_client(&onyx->i2c); + goto fail; + } + printk(KERN_DEBUG PFX "created and attached onyx instance\n"); + return 0; + fail: + kfree(onyx); + return -EINVAL; +} + +static int onyx_i2c_attach(struct i2c_adapter *adapter) +{ + struct device_node *busnode, *dev = NULL; + struct pmac_i2c_bus *bus; + + bus = pmac_i2c_adapter_to_bus(adapter); + if (bus == NULL) + return -ENODEV; + busnode = pmac_i2c_get_bus_node(bus); + + while ((dev = of_get_next_child(busnode, dev)) != NULL) { + if (device_is_compatible(dev, "pcm3052")) { + u32 *addr; + printk(KERN_DEBUG PFX "found pcm3052\n"); + addr = (u32 *) get_property(dev, "reg", NULL); + if (!addr) + return -ENODEV; + return onyx_create(adapter, dev, (*addr)>>1); + } + } + + /* if that didn't work, try desperate mode for older + * machines that have stuff missing from the device tree */ + + if (!device_is_compatible(busnode, "k2-i2c")) + return -ENODEV; + + printk(KERN_DEBUG PFX "found k2-i2c, checking if onyx chip is on it\n"); + /* probe both possible addresses for the onyx chip */ + if (onyx_create(adapter, NULL, 0x46) == 0) + return 0; + return onyx_create(adapter, NULL, 0x47); +} + +static int onyx_i2c_detach(struct i2c_client *client) +{ + struct onyx *onyx = container_of(client, struct onyx, i2c); + int err; + + if ((err = i2c_detach_client(client))) + return err; + aoa_codec_unregister(&onyx->codec); + of_node_put(onyx->codec.node); + if (onyx->codec_info) + kfree(onyx->codec_info); + kfree(onyx); + return 0; +} + +static struct i2c_driver onyx_driver = { + .driver = { + .name = "aoa_codec_onyx", + .owner = THIS_MODULE, + }, + .attach_adapter = onyx_i2c_attach, + .detach_client = onyx_i2c_detach, +}; + +static int __init onyx_init(void) +{ + return i2c_add_driver(&onyx_driver); +} + +static void __exit onyx_exit(void) +{ + i2c_del_driver(&onyx_driver); +} + +module_init(onyx_init); +module_exit(onyx_exit); diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.h b/sound/aoa/codecs/snd-aoa-codec-onyx.h new file mode 100644 index 000000000..aeedda773 --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-onyx.h @@ -0,0 +1,76 @@ +/* + * Apple Onboard Audio driver for Onyx codec (header) + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + */ +#ifndef __SND_AOA_CODEC_ONYX_H +#define __SND_AOA_CODEC_ONYX_H +#include <stddef.h> +#include <linux/i2c.h> +#include <linux/i2c-dev.h> +#include <asm/pmac_low_i2c.h> +#include <asm/prom.h> + +/* PCM3052 register definitions */ + +/* the attenuation registers take values from + * -1 (0dB) to -127 (-63.0 dB) or others (muted) */ +#define ONYX_REG_DAC_ATTEN_LEFT 65 +#define FIRSTREGISTER ONYX_REG_DAC_ATTEN_LEFT +#define ONYX_REG_DAC_ATTEN_RIGHT 66 + +#define ONYX_REG_CONTROL 67 +# define ONYX_MRST (1<<7) +# define ONYX_SRST (1<<6) +# define ONYX_ADPSV (1<<5) +# define ONYX_DAPSV (1<<4) +# define ONYX_SILICONVERSION (1<<0) +/* all others reserved */ + +#define ONYX_REG_DAC_CONTROL 68 +# define ONYX_OVR1 (1<<6) +# define ONYX_MUTE_RIGHT (1<<1) +# define ONYX_MUTE_LEFT (1<<0) + +#define ONYX_REG_DAC_DEEMPH 69 +# define ONYX_DIGDEEMPH_SHIFT 5 +# define ONYX_DIGDEEMPH_MASK (3<<ONYX_DIGDEEMPH_SHIFT) +# define ONYX_DIGDEEMPH_CTRL (1<<4) + +#define ONYX_REG_DAC_FILTER 70 +# define ONYX_ROLLOFF_FAST (1<<5) +# define ONYX_DAC_FILTER_ALWAYS (1<<2) + +#define ONYX_REG_DAC_OUTPHASE 71 +# define ONYX_OUTPHASE_INVERTED (1<<0) + +#define ONYX_REG_ADC_CONTROL 72 +# define ONYX_ADC_INPUT_MIC (1<<5) +/* 8 + input gain in dB, valid range for input gain is -4 .. 20 dB */ +# define ONYX_ADC_PGA_GAIN_MASK 0x1f + +#define ONYX_REG_ADC_HPF_BYPASS 75 +# define ONYX_HPF_DISABLE (1<<3) +# define ONYX_ADC_HPF_ALWAYS (1<<2) + +#define ONYX_REG_DIG_INFO1 77 +# define ONYX_MASK_DIN_TO_BPZ (1<<7) +/* bits 1-5 control channel bits 1-5 */ +# define ONYX_DIGOUT_DISABLE (1<<0) + +#define ONYX_REG_DIG_INFO2 78 +/* controls channel bits 8-15 */ + +#define ONYX_REG_DIG_INFO3 79 +/* control channel bits 24-29, high 2 bits reserved */ + +#define ONYX_REG_DIG_INFO4 80 +# define ONYX_VALIDL (1<<7) +# define ONYX_VALIDR (1<<6) +# define ONYX_SPDIF_ENABLE (1<<5) +/* lower 4 bits control bits 32-35 of channel control and word length */ +# define ONYX_WORDLEN_MASK (0xF) + +#endif /* __SND_AOA_CODEC_ONYX_H */ diff --git a/sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h b/sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h new file mode 100644 index 000000000..69b61136f --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h @@ -0,0 +1,134 @@ +/* + * This file is only included exactly once! + * + * The tables here are derived from the tas3004 datasheet, + * modulo typo corrections and some smoothing... + */ + +#define TAS3004_TREBLE_MIN 0 +#define TAS3004_TREBLE_MAX 72 +#define TAS3004_BASS_MIN 0 +#define TAS3004_BASS_MAX 72 +#define TAS3004_TREBLE_ZERO 36 +#define TAS3004_BASS_ZERO 36 + +static u8 tas3004_treble_table[] = { + 150, /* -18 dB */ + 149, + 148, + 147, + 146, + 145, + 144, + 143, + 142, + 141, + 140, + 139, + 138, + 137, + 136, + 135, + 134, + 133, + 132, + 131, + 130, + 129, + 128, + 127, + 126, + 125, + 124, + 123, + 122, + 121, + 120, + 119, + 118, + 117, + 116, + 115, + 114, /* 0 dB */ + 113, + 112, + 111, + 109, + 108, + 107, + 105, + 104, + 103, + 101, + 99, + 98, + 96, + 93, + 91, + 89, + 86, + 83, + 81, + 77, + 74, + 71, + 67, + 63, + 59, + 54, + 49, + 44, + 38, + 32, + 26, + 19, + 10, + 4, + 2, + 1, /* +18 dB */ +}; + +static inline u8 tas3004_treble(int idx) +{ + return tas3004_treble_table[idx]; +} + +/* I only save the difference here to the treble table + * so that the binary is smaller... + * I have also ignored completely differences of + * +/- 1 + */ +static s8 tas3004_bass_diff_to_treble[] = { + 2, /* 7 dB, offset 50 */ + 2, + 2, + 2, + 2, + 1, + 2, + 2, + 2, + 3, + 4, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 14, + 13, + 8, + 1, /* 18 dB */ +}; + +static inline u8 tas3004_bass(int idx) +{ + u8 result = tas3004_treble_table[idx]; + + if (idx >= 50) + result += tas3004_bass_diff_to_treble[idx-50]; + return result; +} diff --git a/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h b/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h new file mode 100644 index 000000000..4cfa67577 --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h @@ -0,0 +1,209 @@ +/* + This is the program used to generate below table. + +#include <stdio.h> +#include <math.h> +int main() { + int dB2; + printf("/" "* This file is only included exactly once!\n"); + printf(" *\n"); + printf(" * If they'd only tell us that generating this table was\n"); + printf(" * as easy as calculating\n"); + printf(" * hwvalue = 1048576.0*exp(0.057564628*dB*2)\n"); + printf(" * :) *" "/\n"); + printf("static int tas_gaintable[] = {\n"); + printf(" 0x000000, /" "* -infinity dB *" "/\n"); + for (dB2=-140;dB2<=36;dB2++) + printf(" 0x%.6x, /" "* %-02.1f dB *" "/\n", (int)(1048576.0*exp(0.057564628*dB2)), dB2/2.0); + printf("};\n\n"); +} + +*/ + +/* This file is only included exactly once! + * + * If they'd only tell us that generating this table was + * as easy as calculating + * hwvalue = 1048576.0*exp(0.057564628*dB*2) + * :) */ +static int tas_gaintable[] = { + 0x000000, /* -infinity dB */ + 0x00014b, /* -70.0 dB */ + 0x00015f, /* -69.5 dB */ + 0x000174, /* -69.0 dB */ + 0x00018a, /* -68.5 dB */ + 0x0001a1, /* -68.0 dB */ + 0x0001ba, /* -67.5 dB */ + 0x0001d4, /* -67.0 dB */ + 0x0001f0, /* -66.5 dB */ + 0x00020d, /* -66.0 dB */ + 0x00022c, /* -65.5 dB */ + 0x00024d, /* -65.0 dB */ + 0x000270, /* -64.5 dB */ + 0x000295, /* -64.0 dB */ + 0x0002bc, /* -63.5 dB */ + 0x0002e6, /* -63.0 dB */ + 0x000312, /* -62.5 dB */ + 0x000340, /* -62.0 dB */ + 0x000372, /* -61.5 dB */ + 0x0003a6, /* -61.0 dB */ + 0x0003dd, /* -60.5 dB */ + 0x000418, /* -60.0 dB */ + 0x000456, /* -59.5 dB */ + 0x000498, /* -59.0 dB */ + 0x0004de, /* -58.5 dB */ + 0x000528, /* -58.0 dB */ + 0x000576, /* -57.5 dB */ + 0x0005c9, /* -57.0 dB */ + 0x000620, /* -56.5 dB */ + 0x00067d, /* -56.0 dB */ + 0x0006e0, /* -55.5 dB */ + 0x000748, /* -55.0 dB */ + 0x0007b7, /* -54.5 dB */ + 0x00082c, /* -54.0 dB */ + 0x0008a8, /* -53.5 dB */ + 0x00092b, /* -53.0 dB */ + 0x0009b6, /* -52.5 dB */ + 0x000a49, /* -52.0 dB */ + 0x000ae5, /* -51.5 dB */ + 0x000b8b, /* -51.0 dB */ + 0x000c3a, /* -50.5 dB */ + 0x000cf3, /* -50.0 dB */ + 0x000db8, /* -49.5 dB */ + 0x000e88, /* -49.0 dB */ + 0x000f64, /* -48.5 dB */ + 0x00104e, /* -48.0 dB */ + 0x001145, /* -47.5 dB */ + 0x00124b, /* -47.0 dB */ + 0x001361, /* -46.5 dB */ + 0x001487, /* -46.0 dB */ + 0x0015be, /* -45.5 dB */ + 0x001708, /* -45.0 dB */ + 0x001865, /* -44.5 dB */ + 0x0019d8, /* -44.0 dB */ + 0x001b60, /* -43.5 dB */ + 0x001cff, /* -43.0 dB */ + 0x001eb7, /* -42.5 dB */ + 0x002089, /* -42.0 dB */ + 0x002276, /* -41.5 dB */ + 0x002481, /* -41.0 dB */ + 0x0026ab, /* -40.5 dB */ + 0x0028f5, /* -40.0 dB */ + 0x002b63, /* -39.5 dB */ + 0x002df5, /* -39.0 dB */ + 0x0030ae, /* -38.5 dB */ + 0x003390, /* -38.0 dB */ + 0x00369e, /* -37.5 dB */ + 0x0039db, /* -37.0 dB */ + 0x003d49, /* -36.5 dB */ + 0x0040ea, /* -36.0 dB */ + 0x0044c3, /* -35.5 dB */ + 0x0048d6, /* -35.0 dB */ + 0x004d27, /* -34.5 dB */ + 0x0051b9, /* -34.0 dB */ + 0x005691, /* -33.5 dB */ + 0x005bb2, /* -33.0 dB */ + 0x006121, /* -32.5 dB */ + 0x0066e3, /* -32.0 dB */ + 0x006cfb, /* -31.5 dB */ + 0x007370, /* -31.0 dB */ + 0x007a48, /* -30.5 dB */ + 0x008186, /* -30.0 dB */ + 0x008933, /* -29.5 dB */ + 0x009154, /* -29.0 dB */ + 0x0099f1, /* -28.5 dB */ + 0x00a310, /* -28.0 dB */ + 0x00acba, /* -27.5 dB */ + 0x00b6f6, /* -27.0 dB */ + 0x00c1cd, /* -26.5 dB */ + 0x00cd49, /* -26.0 dB */ + 0x00d973, /* -25.5 dB */ + 0x00e655, /* -25.0 dB */ + 0x00f3fb, /* -24.5 dB */ + 0x010270, /* -24.0 dB */ + 0x0111c0, /* -23.5 dB */ + 0x0121f9, /* -23.0 dB */ + 0x013328, /* -22.5 dB */ + 0x01455b, /* -22.0 dB */ + 0x0158a2, /* -21.5 dB */ + 0x016d0e, /* -21.0 dB */ + 0x0182af, /* -20.5 dB */ + 0x019999, /* -20.0 dB */ + 0x01b1de, /* -19.5 dB */ + 0x01cb94, /* -19.0 dB */ + 0x01e6cf, /* -18.5 dB */ + 0x0203a7, /* -18.0 dB */ + 0x022235, /* -17.5 dB */ + 0x024293, /* -17.0 dB */ + 0x0264db, /* -16.5 dB */ + 0x02892c, /* -16.0 dB */ + 0x02afa3, /* -15.5 dB */ + 0x02d862, /* -15.0 dB */ + 0x03038a, /* -14.5 dB */ + 0x033142, /* -14.0 dB */ + 0x0361af, /* -13.5 dB */ + 0x0394fa, /* -13.0 dB */ + 0x03cb50, /* -12.5 dB */ + 0x0404de, /* -12.0 dB */ + 0x0441d5, /* -11.5 dB */ + 0x048268, /* -11.0 dB */ + 0x04c6d0, /* -10.5 dB */ + 0x050f44, /* -10.0 dB */ + 0x055c04, /* -9.5 dB */ + 0x05ad50, /* -9.0 dB */ + 0x06036e, /* -8.5 dB */ + 0x065ea5, /* -8.0 dB */ + 0x06bf44, /* -7.5 dB */ + 0x07259d, /* -7.0 dB */ + 0x079207, /* -6.5 dB */ + 0x0804dc, /* -6.0 dB */ + 0x087e80, /* -5.5 dB */ + 0x08ff59, /* -5.0 dB */ + 0x0987d5, /* -4.5 dB */ + 0x0a1866, /* -4.0 dB */ + 0x0ab189, /* -3.5 dB */ + 0x0b53be, /* -3.0 dB */ + 0x0bff91, /* -2.5 dB */ + 0x0cb591, /* -2.0 dB */ + 0x0d765a, /* -1.5 dB */ + 0x0e4290, /* -1.0 dB */ + 0x0f1adf, /* -0.5 dB */ + 0x100000, /* 0.0 dB */ + 0x10f2b4, /* 0.5 dB */ + 0x11f3c9, /* 1.0 dB */ + 0x13041a, /* 1.5 dB */ + 0x14248e, /* 2.0 dB */ + 0x15561a, /* 2.5 dB */ + 0x1699c0, /* 3.0 dB */ + 0x17f094, /* 3.5 dB */ + 0x195bb8, /* 4.0 dB */ + 0x1adc61, /* 4.5 dB */ + 0x1c73d5, /* 5.0 dB */ + 0x1e236d, /* 5.5 dB */ + 0x1fec98, /* 6.0 dB */ + 0x21d0d9, /* 6.5 dB */ + 0x23d1cd, /* 7.0 dB */ + 0x25f125, /* 7.5 dB */ + 0x2830af, /* 8.0 dB */ + 0x2a9254, /* 8.5 dB */ + 0x2d1818, /* 9.0 dB */ + 0x2fc420, /* 9.5 dB */ + 0x3298b0, /* 10.0 dB */ + 0x35982f, /* 10.5 dB */ + 0x38c528, /* 11.0 dB */ + 0x3c224c, /* 11.5 dB */ + 0x3fb278, /* 12.0 dB */ + 0x4378b0, /* 12.5 dB */ + 0x477829, /* 13.0 dB */ + 0x4bb446, /* 13.5 dB */ + 0x5030a1, /* 14.0 dB */ + 0x54f106, /* 14.5 dB */ + 0x59f980, /* 15.0 dB */ + 0x5f4e52, /* 15.5 dB */ + 0x64f403, /* 16.0 dB */ + 0x6aef5e, /* 16.5 dB */ + 0x714575, /* 17.0 dB */ + 0x77fbaa, /* 17.5 dB */ + 0x7f17af, /* 18.0 dB */ +}; + diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c new file mode 100644 index 000000000..16c0b6b0a --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-tas.c @@ -0,0 +1,935 @@ +/* + * Apple Onboard Audio driver for tas codec + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + * + * Open questions: + * - How to distinguish between 3004 and versions? + * + * FIXMEs: + * - This codec driver doesn't honour the 'connected' + * property of the aoa_codec struct, hence if + * it is used in machines where not everything is + * connected it will display wrong mixer elements. + * - Driver assumes that the microphone is always + * monaureal and connected to the right channel of + * the input. This should also be a codec-dependent + * flag, maybe the codec should have 3 different + * bits for the three different possibilities how + * it can be hooked up... + * But as long as I don't see any hardware hooked + * up that way... + * - As Apple notes in their code, the tas3004 seems + * to delay the right channel by one sample. You can + * see this when for example recording stereo in + * audacity, or recording the tas output via cable + * on another machine (use a sinus generator or so). + * I tried programming the BiQuads but couldn't + * make the delay work, maybe someone can read the + * datasheet and fix it. The relevant Apple comment + * is in AppleTAS3004Audio.cpp lines 1637 ff. Note + * that their comment describing how they program + * the filters sucks... + * + * Other things: + * - this should actually register *two* aoa_codec + * structs since it has two inputs. Then it must + * use the prepare callback to forbid running the + * secondary output on a different clock. + * Also, whatever bus knows how to do this must + * provide two soundbus_dev devices and the fabric + * must be able to link them correctly. + * + * I don't even know if Apple ever uses the second + * port on the tas3004 though, I don't think their + * i2s controllers can even do it. OTOH, they all + * derive the clocks from common clocks, so it + * might just be possible. The framework allows the + * codec to refine the transfer_info items in the + * usable callback, so we can simply remove the + * rates the second instance is not using when it + * actually is in use. + * Maybe we'll need to make the sound busses have + * a 'clock group id' value so the codec can + * determine if the two outputs can be driven at + * the same time. But that is likely overkill, up + * to the fabric to not link them up incorrectly, + * and up to the hardware designer to not wire + * them up in some weird unusable way. + */ +#include <stddef.h> +#include <linux/i2c.h> +#include <linux/i2c-dev.h> +#include <asm/pmac_low_i2c.h> +#include <asm/prom.h> +#include <linux/delay.h> +#include <linux/module.h> +MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("tas codec driver for snd-aoa"); + +#include "snd-aoa-codec-tas.h" +#include "snd-aoa-codec-tas-gain-table.h" +#include "snd-aoa-codec-tas-basstreble.h" +#include "../aoa.h" +#include "../soundbus/soundbus.h" + +#define PFX "snd-aoa-codec-tas: " + + +struct tas { + struct aoa_codec codec; + struct i2c_client i2c; + u32 mute_l:1, mute_r:1 , + controls_created:1 , + drc_enabled:1, + hw_enabled:1; + u8 cached_volume_l, cached_volume_r; + u8 mixer_l[3], mixer_r[3]; + u8 bass, treble; + u8 acr; + int drc_range; +}; + +static int tas_reset_init(struct tas *tas); + +static struct tas *codec_to_tas(struct aoa_codec *codec) +{ + return container_of(codec, struct tas, codec); +} + +static inline int tas_write_reg(struct tas *tas, u8 reg, u8 len, u8 *data) +{ + if (len == 1) + return i2c_smbus_write_byte_data(&tas->i2c, reg, *data); + else + return i2c_smbus_write_i2c_block_data(&tas->i2c, reg, len, data); +} + +static void tas3004_set_drc(struct tas *tas) +{ + unsigned char val[6]; + + if (tas->drc_enabled) + val[0] = 0x50; /* 3:1 above threshold */ + else + val[0] = 0x51; /* disabled */ + val[1] = 0x02; /* 1:1 below threshold */ + if (tas->drc_range > 0xef) + val[2] = 0xef; + else if (tas->drc_range < 0) + val[2] = 0x00; + else + val[2] = tas->drc_range; + val[3] = 0xb0; + val[4] = 0x60; + val[5] = 0xa0; + + tas_write_reg(tas, TAS_REG_DRC, 6, val); +} + +static void tas_set_treble(struct tas *tas) +{ + u8 tmp; + + tmp = tas3004_treble(tas->treble); + tas_write_reg(tas, TAS_REG_TREBLE, 1, &tmp); +} + +static void tas_set_bass(struct tas *tas) +{ + u8 tmp; + + tmp = tas3004_bass(tas->bass); + tas_write_reg(tas, TAS_REG_BASS, 1, &tmp); +} + +static void tas_set_volume(struct tas *tas) +{ + u8 block[6]; + int tmp; + u8 left, right; + + left = tas->cached_volume_l; + right = tas->cached_volume_r; + + if (left > 177) left = 177; + if (right > 177) right = 177; + + if (tas->mute_l) left = 0; + if (tas->mute_r) right = 0; + + /* analysing the volume and mixer tables shows + * that they are similar enough when we shift + * the mixer table down by 4 bits. The error + * is miniscule, in just one item the error + * is 1, at a value of 0x07f17b (mixer table + * value is 0x07f17a) */ + tmp = tas_gaintable[left]; + block[0] = tmp>>20; + block[1] = tmp>>12; + block[2] = tmp>>4; + tmp = tas_gaintable[right]; + block[3] = tmp>>20; + block[4] = tmp>>12; + block[5] = tmp>>4; + tas_write_reg(tas, TAS_REG_VOL, 6, block); +} + +static void tas_set_mixer(struct tas *tas) +{ + u8 block[9]; + int tmp, i; + u8 val; + + for (i=0;i<3;i++) { + val = tas->mixer_l[i]; + if (val > 177) val = 177; + tmp = tas_gaintable[val]; + block[3*i+0] = tmp>>16; + block[3*i+1] = tmp>>8; + block[3*i+2] = tmp; + } + tas_write_reg(tas, TAS_REG_LMIX, 9, block); + + for (i=0;i<3;i++) { + val = tas->mixer_r[i]; + if (val > 177) val = 177; + tmp = tas_gaintable[val]; + block[3*i+0] = tmp>>16; + block[3*i+1] = tmp>>8; + block[3*i+2] = tmp; + } + tas_write_reg(tas, TAS_REG_RMIX, 9, block); +} + +/* alsa stuff */ + +static int tas_dev_register(struct snd_device *dev) +{ + return 0; +} + +static struct snd_device_ops ops = { + .dev_register = tas_dev_register, +}; + +static int tas_snd_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 177; + return 0; +} + +static int tas_snd_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = tas->cached_volume_l; + ucontrol->value.integer.value[1] = tas->cached_volume_r; + return 0; +} + +static int tas_snd_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + if (tas->cached_volume_l == ucontrol->value.integer.value[0] + && tas->cached_volume_r == ucontrol->value.integer.value[1]) + return 0; + + tas->cached_volume_l = ucontrol->value.integer.value[0]; + tas->cached_volume_r = ucontrol->value.integer.value[1]; + if (tas->hw_enabled) + tas_set_volume(tas); + return 1; +} + +static struct snd_kcontrol_new volume_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Master Playback Volume", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = tas_snd_vol_info, + .get = tas_snd_vol_get, + .put = tas_snd_vol_put, +}; + +static int tas_snd_mute_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int tas_snd_mute_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = !tas->mute_l; + ucontrol->value.integer.value[1] = !tas->mute_r; + return 0; +} + +static int tas_snd_mute_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + if (tas->mute_l == !ucontrol->value.integer.value[0] + && tas->mute_r == !ucontrol->value.integer.value[1]) + return 0; + + tas->mute_l = !ucontrol->value.integer.value[0]; + tas->mute_r = !ucontrol->value.integer.value[1]; + if (tas->hw_enabled) + tas_set_volume(tas); + return 1; +} + +static struct snd_kcontrol_new mute_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Master Playback Switch", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = tas_snd_mute_info, + .get = tas_snd_mute_get, + .put = tas_snd_mute_put, +}; + +static int tas_snd_mixer_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 2; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 177; + return 0; +} + +static int tas_snd_mixer_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + int idx = kcontrol->private_value; + + ucontrol->value.integer.value[0] = tas->mixer_l[idx]; + ucontrol->value.integer.value[1] = tas->mixer_r[idx]; + + return 0; +} + +static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + int idx = kcontrol->private_value; + + if (tas->mixer_l[idx] == ucontrol->value.integer.value[0] + && tas->mixer_r[idx] == ucontrol->value.integer.value[1]) + return 0; + + tas->mixer_l[idx] = ucontrol->value.integer.value[0]; + tas->mixer_r[idx] = ucontrol->value.integer.value[1]; + + if (tas->hw_enabled) + tas_set_mixer(tas); + return 1; +} + +#define MIXER_CONTROL(n,descr,idx) \ +static struct snd_kcontrol_new n##_control = { \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = descr " Playback Volume", \ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .info = tas_snd_mixer_info, \ + .get = tas_snd_mixer_get, \ + .put = tas_snd_mixer_put, \ + .private_value = idx, \ +} + +MIXER_CONTROL(pcm1, "PCM", 0); +MIXER_CONTROL(monitor, "Monitor", 2); + +static int tas_snd_drc_range_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = TAS3004_DRC_MAX; + return 0; +} + +static int tas_snd_drc_range_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = tas->drc_range; + return 0; +} + +static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + if (tas->drc_range == ucontrol->value.integer.value[0]) + return 0; + + tas->drc_range = ucontrol->value.integer.value[0]; + if (tas->hw_enabled) + tas3004_set_drc(tas); + return 1; +} + +static struct snd_kcontrol_new drc_range_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "DRC Range", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = tas_snd_drc_range_info, + .get = tas_snd_drc_range_get, + .put = tas_snd_drc_range_put, +}; + +static int tas_snd_drc_switch_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int tas_snd_drc_switch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = tas->drc_enabled; + return 0; +} + +static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + if (tas->drc_enabled == ucontrol->value.integer.value[0]) + return 0; + + tas->drc_enabled = ucontrol->value.integer.value[0]; + if (tas->hw_enabled) + tas3004_set_drc(tas); + return 1; +} + +static struct snd_kcontrol_new drc_switch_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "DRC Range Switch", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = tas_snd_drc_switch_info, + .get = tas_snd_drc_switch_get, + .put = tas_snd_drc_switch_put, +}; + +static int tas_snd_capture_source_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static char *texts[] = { "Line-In", "Microphone" }; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = 2; + if (uinfo->value.enumerated.item > 1) + uinfo->value.enumerated.item = 1; + strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); + return 0; +} + +static int tas_snd_capture_source_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + ucontrol->value.enumerated.item[0] = !!(tas->acr & TAS_ACR_INPUT_B); + return 0; +} + +static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + int oldacr = tas->acr; + + tas->acr &= ~TAS_ACR_INPUT_B; + if (ucontrol->value.enumerated.item[0]) + tas->acr |= TAS_ACR_INPUT_B; + if (oldacr == tas->acr) + return 0; + if (tas->hw_enabled) + tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); + return 1; +} + +static struct snd_kcontrol_new capture_source_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* If we name this 'Input Source', it properly shows up in + * alsamixer as a selection, * but it's shown under the + * 'Playback' category. + * If I name it 'Capture Source', it shows up in strange + * ways (two bools of which one can be selected at a + * time) but at least it's shown in the 'Capture' + * category. + * I was told that this was due to backward compatibility, + * but I don't understand then why the mangling is *not* + * done when I name it "Input Source"..... + */ + .name = "Capture Source", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = tas_snd_capture_source_info, + .get = tas_snd_capture_source_get, + .put = tas_snd_capture_source_put, +}; + +static int tas_snd_treble_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = TAS3004_TREBLE_MIN; + uinfo->value.integer.max = TAS3004_TREBLE_MAX; + return 0; +} + +static int tas_snd_treble_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = tas->treble; + return 0; +} + +static int tas_snd_treble_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + if (tas->treble == ucontrol->value.integer.value[0]) + return 0; + + tas->treble = ucontrol->value.integer.value[0]; + if (tas->hw_enabled) + tas_set_treble(tas); + return 1; +} + +static struct snd_kcontrol_new treble_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Treble", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = tas_snd_treble_info, + .get = tas_snd_treble_get, + .put = tas_snd_treble_put, +}; + +static int tas_snd_bass_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = TAS3004_BASS_MIN; + uinfo->value.integer.max = TAS3004_BASS_MAX; + return 0; +} + +static int tas_snd_bass_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = tas->bass; + return 0; +} + +static int tas_snd_bass_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct tas *tas = snd_kcontrol_chip(kcontrol); + + if (tas->bass == ucontrol->value.integer.value[0]) + return 0; + + tas->bass = ucontrol->value.integer.value[0]; + if (tas->hw_enabled) + tas_set_bass(tas); + return 1; +} + +static struct snd_kcontrol_new bass_control = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Bass", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = tas_snd_bass_info, + .get = tas_snd_bass_get, + .put = tas_snd_bass_put, +}; + +static struct transfer_info tas_transfers[] = { + { + /* input */ + .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE, + .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, + .transfer_in = 1, + }, + { + /* output */ + .formats = SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S24_BE, + .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, + .transfer_in = 0, + }, + {} +}; + +static int tas_usable(struct codec_info_item *cii, + struct transfer_info *ti, + struct transfer_info *out) +{ + return 1; +} + +static int tas_reset_init(struct tas *tas) +{ + u8 tmp; + + tas->codec.gpio->methods->all_amps_off(tas->codec.gpio); + msleep(5); + tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); + msleep(5); + tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 1); + msleep(20); + tas->codec.gpio->methods->set_hw_reset(tas->codec.gpio, 0); + msleep(10); + tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); + + tmp = TAS_MCS_SCLK64 | TAS_MCS_SPORT_MODE_I2S | TAS_MCS_SPORT_WL_24BIT; + if (tas_write_reg(tas, TAS_REG_MCS, 1, &tmp)) + return -ENODEV; + + tas->acr |= TAS_ACR_ANALOG_PDOWN | TAS_ACR_B_MONAUREAL | + TAS_ACR_B_MON_SEL_RIGHT; + if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) + return -ENODEV; + + tmp = 0; + if (tas_write_reg(tas, TAS_REG_MCS2, 1, &tmp)) + return -ENODEV; + + tas3004_set_drc(tas); + + /* Set treble & bass to 0dB */ + tas->treble = TAS3004_TREBLE_ZERO; + tas->bass = TAS3004_BASS_ZERO; + tas_set_treble(tas); + tas_set_bass(tas); + + tas->acr &= ~TAS_ACR_ANALOG_PDOWN; + if (tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr)) + return -ENODEV; + + return 0; +} + +static int tas_switch_clock(struct codec_info_item *cii, enum clock_switch clock) +{ + struct tas *tas = cii->codec_data; + + switch(clock) { + case CLOCK_SWITCH_PREPARE_SLAVE: + /* Clocks are going away, mute mute mute */ + tas->codec.gpio->methods->all_amps_off(tas->codec.gpio); + tas->hw_enabled = 0; + break; + case CLOCK_SWITCH_SLAVE: + /* Clocks are back, re-init the codec */ + tas_reset_init(tas); + tas_set_volume(tas); + tas_set_mixer(tas); + tas->hw_enabled = 1; + tas->codec.gpio->methods->all_amps_restore(tas->codec.gpio); + break; + default: + /* doesn't happen as of now */ + return -EINVAL; + } + return 0; +} + +/* we are controlled via i2c and assume that is always up + * If that wasn't the case, we'd have to suspend once + * our i2c device is suspended, and then take note of that! */ +static int tas_suspend(struct tas *tas) +{ + tas->hw_enabled = 0; + tas->acr |= TAS_ACR_ANALOG_PDOWN; + tas_write_reg(tas, TAS_REG_ACR, 1, &tas->acr); + return 0; +} + +static int tas_resume(struct tas *tas) +{ + /* reset codec */ + tas_reset_init(tas); + tas_set_volume(tas); + tas_set_mixer(tas); + tas->hw_enabled = 1; + return 0; +} + +#ifdef CONFIG_PM +static int _tas_suspend(struct codec_info_item *cii, pm_message_t state) +{ + return tas_suspend(cii->codec_data); +} + +static int _tas_resume(struct codec_info_item *cii) +{ + return tas_resume(cii->codec_data); +} +#endif + +static struct codec_info tas_codec_info = { + .transfers = tas_transfers, + /* in theory, we can drive it at 512 too... + * but so far the framework doesn't allow + * for that and I don't see much point in it. */ + .sysclock_factor = 256, + /* same here, could be 32 for just one 16 bit format */ + .bus_factor = 64, + .owner = THIS_MODULE, + .usable = tas_usable, + .switch_clock = tas_switch_clock, +#ifdef CONFIG_PM + .suspend = _tas_suspend, + .resume = _tas_resume, +#endif +}; + +static int tas_init_codec(struct aoa_codec *codec) +{ + struct tas *tas = codec_to_tas(codec); + int err; + + if (!tas->codec.gpio || !tas->codec.gpio->methods) { + printk(KERN_ERR PFX "gpios not assigned!!\n"); + return -EINVAL; + } + + if (tas_reset_init(tas)) { + printk(KERN_ERR PFX "tas failed to initialise\n"); + return -ENXIO; + } + tas->hw_enabled = 1; + + if (tas->codec.soundbus_dev->attach_codec(tas->codec.soundbus_dev, + aoa_get_card(), + &tas_codec_info, tas)) { + printk(KERN_ERR PFX "error attaching tas to soundbus\n"); + return -ENODEV; + } + + if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, tas, &ops)) { + printk(KERN_ERR PFX "failed to create tas snd device!\n"); + return -ENODEV; + } + err = aoa_snd_ctl_add(snd_ctl_new1(&volume_control, tas)); + if (err) + goto error; + + err = aoa_snd_ctl_add(snd_ctl_new1(&mute_control, tas)); + if (err) + goto error; + + err = aoa_snd_ctl_add(snd_ctl_new1(&pcm1_control, tas)); + if (err) + goto error; + + err = aoa_snd_ctl_add(snd_ctl_new1(&monitor_control, tas)); + if (err) + goto error; + + err = aoa_snd_ctl_add(snd_ctl_new1(&capture_source_control, tas)); + if (err) + goto error; + + err = aoa_snd_ctl_add(snd_ctl_new1(&drc_range_control, tas)); + if (err) + goto error; + + err = aoa_snd_ctl_add(snd_ctl_new1(&drc_switch_control, tas)); + if (err) + goto error; + + err = aoa_snd_ctl_add(snd_ctl_new1(&treble_control, tas)); + if (err) + goto error; + + err = aoa_snd_ctl_add(snd_ctl_new1(&bass_control, tas)); + if (err) + goto error; + + return 0; + error: + tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); + snd_device_free(aoa_get_card(), tas); + return err; +} + +static void tas_exit_codec(struct aoa_codec *codec) +{ + struct tas *tas = codec_to_tas(codec); + + if (!tas->codec.soundbus_dev) + return; + tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); +} + + +static struct i2c_driver tas_driver; + +static int tas_create(struct i2c_adapter *adapter, + struct device_node *node, + int addr) +{ + struct tas *tas; + + tas = kzalloc(sizeof(struct tas), GFP_KERNEL); + + if (!tas) + return -ENOMEM; + + tas->i2c.driver = &tas_driver; + tas->i2c.adapter = adapter; + tas->i2c.addr = addr; + /* seems that half is a saner default */ + tas->drc_range = TAS3004_DRC_MAX / 2; + strlcpy(tas->i2c.name, "tas audio codec", I2C_NAME_SIZE-1); + + if (i2c_attach_client(&tas->i2c)) { + printk(KERN_ERR PFX "failed to attach to i2c\n"); + goto fail; + } + + strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN-1); + tas->codec.owner = THIS_MODULE; + tas->codec.init = tas_init_codec; + tas->codec.exit = tas_exit_codec; + tas->codec.node = of_node_get(node); + + if (aoa_codec_register(&tas->codec)) { + goto detach; + } + printk(KERN_DEBUG + "snd-aoa-codec-tas: tas found, addr 0x%02x on %s\n", + addr, node->full_name); + return 0; + detach: + i2c_detach_client(&tas->i2c); + fail: + kfree(tas); + return -EINVAL; +} + +static int tas_i2c_attach(struct i2c_adapter *adapter) +{ + struct device_node *busnode, *dev = NULL; + struct pmac_i2c_bus *bus; + + bus = pmac_i2c_adapter_to_bus(adapter); + if (bus == NULL) + return -ENODEV; + busnode = pmac_i2c_get_bus_node(bus); + + while ((dev = of_get_next_child(busnode, dev)) != NULL) { + if (device_is_compatible(dev, "tas3004")) { + u32 *addr; + printk(KERN_DEBUG PFX "found tas3004\n"); + addr = (u32 *) get_property(dev, "reg", NULL); + if (!addr) + continue; + return tas_create(adapter, dev, ((*addr) >> 1) & 0x7f); + } + /* older machines have no 'codec' node with a 'compatible' + * property that says 'tas3004', they just have a 'deq' + * node without any such property... */ + if (strcmp(dev->name, "deq") == 0) { + u32 *_addr, addr; + printk(KERN_DEBUG PFX "found 'deq' node\n"); + _addr = (u32 *) get_property(dev, "i2c-address", NULL); + if (!_addr) + continue; + addr = ((*_addr) >> 1) & 0x7f; + /* now, if the address doesn't match any of the two + * that a tas3004 can have, we cannot handle this. + * I doubt it ever happens but hey. */ + if (addr != 0x34 && addr != 0x35) + continue; + return tas_create(adapter, dev, addr); + } + } + return -ENODEV; +} + +static int tas_i2c_detach(struct i2c_client *client) +{ + struct tas *tas = container_of(client, struct tas, i2c); + int err; + u8 tmp = TAS_ACR_ANALOG_PDOWN; + + if ((err = i2c_detach_client(client))) + return err; + aoa_codec_unregister(&tas->codec); + of_node_put(tas->codec.node); + + /* power down codec chip */ + tas_write_reg(tas, TAS_REG_ACR, 1, &tmp); + + kfree(tas); + return 0; +} + +static struct i2c_driver tas_driver = { + .driver = { + .name = "aoa_codec_tas", + .owner = THIS_MODULE, + }, + .attach_adapter = tas_i2c_attach, + .detach_client = tas_i2c_detach, +}; + +static int __init tas_init(void) +{ + return i2c_add_driver(&tas_driver); +} + +static void __exit tas_exit(void) +{ + i2c_del_driver(&tas_driver); +} + +module_init(tas_init); +module_exit(tas_exit); diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.h b/sound/aoa/codecs/snd-aoa-codec-tas.h new file mode 100644 index 000000000..ae177e346 --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-tas.h @@ -0,0 +1,55 @@ +/* + * Apple Onboard Audio driver for tas codec (header) + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + */ +#ifndef __SND_AOA_CODECTASH +#define __SND_AOA_CODECTASH + +#define TAS_REG_MCS 0x01 /* main control */ +# define TAS_MCS_FASTLOAD (1<<7) +# define TAS_MCS_SCLK64 (1<<6) +# define TAS_MCS_SPORT_MODE_MASK (3<<4) +# define TAS_MCS_SPORT_MODE_I2S (2<<4) +# define TAS_MCS_SPORT_MODE_RJ (1<<4) +# define TAS_MCS_SPORT_MODE_LJ (0<<4) +# define TAS_MCS_SPORT_WL_MASK (3<<0) +# define TAS_MCS_SPORT_WL_16BIT (0<<0) +# define TAS_MCS_SPORT_WL_18BIT (1<<0) +# define TAS_MCS_SPORT_WL_20BIT (2<<0) +# define TAS_MCS_SPORT_WL_24BIT (3<<0) + +#define TAS_REG_DRC 0x02 +#define TAS_REG_VOL 0x04 +#define TAS_REG_TREBLE 0x05 +#define TAS_REG_BASS 0x06 +#define TAS_REG_LMIX 0x07 +#define TAS_REG_RMIX 0x08 + +#define TAS_REG_ACR 0x40 /* analog control */ +# define TAS_ACR_B_MONAUREAL (1<<7) +# define TAS_ACR_B_MON_SEL_RIGHT (1<<6) +# define TAS_ACR_DEEMPH_MASK (3<<2) +# define TAS_ACR_DEEMPH_OFF (0<<2) +# define TAS_ACR_DEEMPH_48KHz (1<<2) +# define TAS_ACR_DEEMPH_44KHz (2<<2) +# define TAS_ACR_INPUT_B (1<<1) +# define TAS_ACR_ANALOG_PDOWN (1<<0) + +#define TAS_REG_MCS2 0x43 /* main control 2 */ +# define TAS_MCS2_ALLPASS (1<<1) + +#define TAS_REG_LEFT_BIQUAD6 0x10 +#define TAS_REG_RIGHT_BIQUAD6 0x19 + +#define TAS_REG_LEFT_LOUDNESS 0x21 +#define TAS_REG_RIGHT_LOUDNESS 0x22 +#define TAS_REG_LEFT_LOUDNESS_GAIN 0x23 +#define TAS_REG_RIGHT_LOUDNESS_GAIN 0x24 + +#define TAS3001_DRC_MAX 0x5f +#define TAS3004_DRC_MAX 0xef + +#endif /* __SND_AOA_CODECTASH */ diff --git a/sound/aoa/codecs/snd-aoa-codec-toonie.c b/sound/aoa/codecs/snd-aoa-codec-toonie.c new file mode 100644 index 000000000..3c7d1d8a9 --- /dev/null +++ b/sound/aoa/codecs/snd-aoa-codec-toonie.c @@ -0,0 +1,150 @@ +/* + * Apple Onboard Audio driver for Toonie codec + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + * + * + * This is a driver for the toonie codec chip. This chip is present + * on the Mac Mini and is nothing but a DAC. + */ +#include <linux/delay.h> +#include <linux/module.h> +MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("toonie codec driver for snd-aoa"); + +#include "../aoa.h" +#include "../soundbus/soundbus.h" + + +#define PFX "snd-aoa-codec-toonie: " + +struct toonie { + struct aoa_codec codec; +}; +#define codec_to_toonie(c) container_of(c, struct toonie, codec) + +static int toonie_dev_register(struct snd_device *dev) +{ + return 0; +} + +static struct snd_device_ops ops = { + .dev_register = toonie_dev_register, +}; + +static struct transfer_info toonie_transfers[] = { + /* This thing *only* has analog output, + * the rates are taken from Info.plist + * from Darwin. */ + { + .formats = SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_S24_BE, + .rates = SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000, + }, + {} +}; + +static int toonie_usable(struct codec_info_item *cii, + struct transfer_info *ti, + struct transfer_info *out) +{ + return 1; +} + +#ifdef CONFIG_PM +static int toonie_suspend(struct codec_info_item *cii, pm_message_t state) +{ + /* can we turn it off somehow? */ + return 0; +} + +static int toonie_resume(struct codec_info_item *cii) +{ + return 0; +} +#endif /* CONFIG_PM */ + +static struct codec_info toonie_codec_info = { + .transfers = toonie_transfers, + .sysclock_factor = 256, + .bus_factor = 64, + .owner = THIS_MODULE, + .usable = toonie_usable, +#ifdef CONFIG_PM + .suspend = toonie_suspend, + .resume = toonie_resume, +#endif +}; + +static int toonie_init_codec(struct aoa_codec *codec) +{ + struct toonie *toonie = codec_to_toonie(codec); + + /* nothing connected? what a joke! */ + if (toonie->codec.connected != 1) + return -ENOTCONN; + + if (aoa_snd_device_new(SNDRV_DEV_LOWLEVEL, toonie, &ops)) { + printk(KERN_ERR PFX "failed to create toonie snd device!\n"); + return -ENODEV; + } + + if (toonie->codec.soundbus_dev->attach_codec(toonie->codec.soundbus_dev, + aoa_get_card(), + &toonie_codec_info, toonie)) { + printk(KERN_ERR PFX "error creating toonie pcm\n"); + snd_device_free(aoa_get_card(), toonie); + return -ENODEV; + } + + return 0; +} + +static void toonie_exit_codec(struct aoa_codec *codec) +{ + struct toonie *toonie = codec_to_toonie(codec); + + if (!toonie->codec.soundbus_dev) { + printk(KERN_ERR PFX "toonie_exit_codec called without soundbus_dev!\n"); + return; + } + toonie->codec.soundbus_dev->detach_codec(toonie->codec.soundbus_dev, toonie); +} + +static struct toonie *toonie; + +static int __init toonie_init(void) +{ + toonie = kzalloc(sizeof(struct toonie), GFP_KERNEL); + + if (!toonie) + return -ENOMEM; + + strlcpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name)); + toonie->codec.owner = THIS_MODULE; + toonie->codec.init = toonie_init_codec; + toonie->codec.exit = toonie_exit_codec; + + if (aoa_codec_register(&toonie->codec)) { + kfree(toonie); + return -EINVAL; + } + + return 0; +} + +static void __exit toonie_exit(void) +{ + aoa_codec_unregister(&toonie->codec); + kfree(toonie); +} + +module_init(toonie_init); +module_exit(toonie_exit); diff --git a/sound/aoa/core/Makefile b/sound/aoa/core/Makefile new file mode 100644 index 000000000..62dc7287f --- /dev/null +++ b/sound/aoa/core/Makefile @@ -0,0 +1,5 @@ +obj-$(CONFIG_SND_AOA) += snd-aoa.o +snd-aoa-objs := snd-aoa-core.o \ + snd-aoa-alsa.o \ + snd-aoa-gpio-pmf.o \ + snd-aoa-gpio-feature.o diff --git a/sound/aoa/core/snd-aoa-alsa.c b/sound/aoa/core/snd-aoa-alsa.c new file mode 100644 index 000000000..b42fdea77 --- /dev/null +++ b/sound/aoa/core/snd-aoa-alsa.c @@ -0,0 +1,98 @@ +/* + * Apple Onboard Audio Alsa helpers + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + */ +#include <linux/module.h> +#include "snd-aoa-alsa.h" + +static int index = -1; +module_param(index, int, 0444); +MODULE_PARM_DESC(index, "index for AOA sound card."); + +static struct aoa_card *aoa_card; + +int aoa_alsa_init(char *name, struct module *mod) +{ + struct snd_card *alsa_card; + int err; + + if (aoa_card) + /* cannot be EEXIST due to usage in aoa_fabric_register */ + return -EBUSY; + + alsa_card = snd_card_new(index, name, mod, sizeof(struct aoa_card)); + if (!alsa_card) + return -ENOMEM; + aoa_card = alsa_card->private_data; + aoa_card->alsa_card = alsa_card; + strlcpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver)); + strlcpy(alsa_card->shortname, name, sizeof(alsa_card->shortname)); + strlcpy(alsa_card->longname, name, sizeof(alsa_card->longname)); + strlcpy(alsa_card->mixername, name, sizeof(alsa_card->mixername)); + err = snd_card_register(aoa_card->alsa_card); + if (err < 0) { + printk(KERN_ERR "snd-aoa: couldn't register alsa card\n"); + snd_card_free(aoa_card->alsa_card); + aoa_card = NULL; + return err; + } + return 0; +} + +struct snd_card *aoa_get_card(void) +{ + if (aoa_card) + return aoa_card->alsa_card; + return NULL; +} +EXPORT_SYMBOL_GPL(aoa_get_card); + +void aoa_alsa_cleanup(void) +{ + if (aoa_card) { + snd_card_free(aoa_card->alsa_card); + aoa_card = NULL; + } +} + +int aoa_snd_device_new(snd_device_type_t type, + void * device_data, struct snd_device_ops * ops) +{ + struct snd_card *card = aoa_get_card(); + int err; + + if (!card) return -ENOMEM; + + err = snd_device_new(card, type, device_data, ops); + if (err) { + printk(KERN_ERR "snd-aoa: failed to create snd device (%d)\n", err); + return err; + } + err = snd_device_register(card, device_data); + if (err) { + printk(KERN_ERR "snd-aoa: failed to register " + "snd device (%d)\n", err); + printk(KERN_ERR "snd-aoa: have you forgotten the " + "dev_register callback?\n"); + snd_device_free(card, device_data); + } + return err; +} +EXPORT_SYMBOL_GPL(aoa_snd_device_new); + +int aoa_snd_ctl_add(struct snd_kcontrol* control) +{ + int err; + + if (!aoa_card) return -ENODEV; + + err = snd_ctl_add(aoa_card->alsa_card, control); + if (err) + printk(KERN_ERR "snd-aoa: failed to add alsa control (%d)\n", + err); + return err; +} +EXPORT_SYMBOL_GPL(aoa_snd_ctl_add); diff --git a/sound/aoa/core/snd-aoa-alsa.h b/sound/aoa/core/snd-aoa-alsa.h new file mode 100644 index 000000000..660d2f179 --- /dev/null +++ b/sound/aoa/core/snd-aoa-alsa.h @@ -0,0 +1,16 @@ +/* + * Apple Onboard Audio Alsa private helpers + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + */ + +#ifndef __SND_AOA_ALSA_H +#define __SND_AOA_ALSA_H +#include "../aoa.h" + +extern int aoa_alsa_init(char *name, struct module *mod); +extern void aoa_alsa_cleanup(void); + +#endif /* __SND_AOA_ALSA_H */ diff --git a/sound/aoa/core/snd-aoa-core.c b/sound/aoa/core/snd-aoa-core.c new file mode 100644 index 000000000..ecd2d8263 --- /dev/null +++ b/sound/aoa/core/snd-aoa-core.c @@ -0,0 +1,162 @@ +/* + * Apple Onboard Audio driver core + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + */ + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/list.h> +#include "../aoa.h" +#include "snd-aoa-alsa.h" + +MODULE_DESCRIPTION("Apple Onboard Audio Sound Driver"); +MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); +MODULE_LICENSE("GPL"); + +/* We allow only one fabric. This simplifies things, + * and more don't really make that much sense */ +static struct aoa_fabric *fabric; +static LIST_HEAD(codec_list); + +static int attach_codec_to_fabric(struct aoa_codec *c) +{ + int err; + + if (!try_module_get(c->owner)) + return -EBUSY; + /* found_codec has to be assigned */ + err = -ENOENT; + if (fabric->found_codec) + err = fabric->found_codec(c); + if (err) { + module_put(c->owner); + printk(KERN_ERR "snd-aoa: fabric didn't like codec %s\n", + c->name); + return err; + } + c->fabric = fabric; + + err = 0; + if (c->init) + err = c->init(c); + if (err) { + printk(KERN_ERR "snd-aoa: codec %s didn't init\n", c->name); + c->fabric = NULL; + if (fabric->remove_codec) + fabric->remove_codec(c); + module_put(c->owner); + return err; + } + if (fabric->attached_codec) + fabric->attached_codec(c); + return 0; +} + +int aoa_codec_register(struct aoa_codec *codec) +{ + int err = 0; + + /* if there's a fabric already, we can tell if we + * will want to have this codec, so propagate error + * through. Otherwise, this will happen later... */ + if (fabric) + err = attach_codec_to_fabric(codec); + if (!err) + list_add(&codec->list, &codec_list); + return err; +} +EXPORT_SYMBOL_GPL(aoa_codec_register); + +void aoa_codec_unregister(struct aoa_codec *codec) +{ + list_del(&codec->list); + if (codec->fabric && codec->exit) + codec->exit(codec); + if (fabric && fabric->remove_codec) + fabric->remove_codec(codec); + codec->fabric = NULL; + module_put(codec->owner); +} +EXPORT_SYMBOL_GPL(aoa_codec_unregister); + +int aoa_fabric_register(struct aoa_fabric *new_fabric) +{ + struct aoa_codec *c; + int err; + + /* allow querying for presence of fabric + * (i.e. do this test first!) */ + if (new_fabric == fabric) { + err = -EALREADY; + goto attach; + } + if (fabric) + return -EEXIST; + if (!new_fabric) + return -EINVAL; + + err = aoa_alsa_init(new_fabric->name, new_fabric->owner); + if (err) + return err; + + fabric = new_fabric; + + attach: + list_for_each_entry(c, &codec_list, list) { + if (c->fabric != fabric) + attach_codec_to_fabric(c); + } + return err; +} +EXPORT_SYMBOL_GPL(aoa_fabric_register); + +void aoa_fabric_unregister(struct aoa_fabric *old_fabric) +{ + struct aoa_codec *c; + + if (fabric != old_fabric) + return; + + list_for_each_entry(c, &codec_list, list) { + if (c->fabric) + aoa_fabric_unlink_codec(c); + } + + aoa_alsa_cleanup(); + + fabric = NULL; +} +EXPORT_SYMBOL_GPL(aoa_fabric_unregister); + +void aoa_fabric_unlink_codec(struct aoa_codec *codec) +{ + if (!codec->fabric) { + printk(KERN_ERR "snd-aoa: fabric unassigned " + "in aoa_fabric_unlink_codec\n"); + dump_stack(); + return; + } + if (codec->exit) + codec->exit(codec); + if (codec->fabric->remove_codec) + codec->fabric->remove_codec(codec); + codec->fabric = NULL; + module_put(codec->owner); +} +EXPORT_SYMBOL_GPL(aoa_fabric_unlink_codec); + +static int __init aoa_init(void) +{ + return 0; +} + +static void __exit aoa_exit(void) +{ + aoa_alsa_cleanup(); +} + +module_init(aoa_init); +module_exit(aoa_exit); diff --git a/sound/aoa/core/snd-aoa-gpio-feature.c b/sound/aoa/core/snd-aoa-gpio-feature.c new file mode 100644 index 000000000..f69d33357 --- /dev/null +++ b/sound/aoa/core/snd-aoa-gpio-feature.c @@ -0,0 +1,412 @@ +/* + * Apple Onboard Audio feature call GPIO control + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + * + * This file contains the GPIO control routines for + * direct (through feature calls) access to the GPIO + * registers. + */ + +#include <asm/pmac_feature.h> +#include <linux/interrupt.h> +#include "../aoa.h" + +/* TODO: these are 20 global variables + * that aren't used on most machines... + * Move them into a dynamically allocated + * structure and use that. + */ + +/* these are the GPIO numbers (register addresses as offsets into + * the GPIO space) */ +static int headphone_mute_gpio; +static int amp_mute_gpio; +static int lineout_mute_gpio; +static int hw_reset_gpio; +static int lineout_detect_gpio; +static int headphone_detect_gpio; +static int linein_detect_gpio; + +/* see the SWITCH_GPIO macro */ +static int headphone_mute_gpio_activestate; +static int amp_mute_gpio_activestate; +static int lineout_mute_gpio_activestate; +static int hw_reset_gpio_activestate; +static int lineout_detect_gpio_activestate; +static int headphone_detect_gpio_activestate; +static int linein_detect_gpio_activestate; + +/* node pointers that we save when getting the GPIO number + * to get the interrupt later */ +static struct device_node *lineout_detect_node; +static struct device_node *linein_detect_node; +static struct device_node *headphone_detect_node; + +static int lineout_detect_irq; +static int linein_detect_irq; +static int headphone_detect_irq; + +static struct device_node *get_gpio(char *name, + char *altname, + int *gpioptr, + int *gpioactiveptr) +{ + struct device_node *np, *gpio; + u32 *reg; + char *audio_gpio; + + *gpioptr = -1; + + /* check if we can get it the easy way ... */ + np = of_find_node_by_name(NULL, name); + if (!np) { + /* some machines have only gpioX/extint-gpioX nodes, + * and an audio-gpio property saying what it is ... + * So what we have to do is enumerate all children + * of the gpio node and check them all. */ + gpio = of_find_node_by_name(NULL, "gpio"); + if (!gpio) + return NULL; + while ((np = of_get_next_child(gpio, np))) { + audio_gpio = get_property(np, "audio-gpio", NULL); + if (!audio_gpio) + continue; + if (strcmp(audio_gpio, name) == 0) + break; + if (altname && (strcmp(audio_gpio, altname) == 0)) + break; + } + /* still not found, assume not there */ + if (!np) + return NULL; + } + + reg = (u32 *)get_property(np, "reg", NULL); + if (!reg) + return NULL; + + *gpioptr = *reg; + + /* this is a hack, usually the GPIOs 'reg' property + * should have the offset based from the GPIO space + * which is at 0x50, but apparently not always... */ + if (*gpioptr < 0x50) + *gpioptr += 0x50; + + reg = (u32 *)get_property(np, "audio-gpio-active-state", NULL); + if (!reg) + /* Apple seems to default to 1, but + * that doesn't seem right at least on most + * machines. So until proven that the opposite + * is necessary, we default to 0 + * (which, incidentally, snd-powermac also does...) */ + *gpioactiveptr = 0; + else + *gpioactiveptr = *reg; + + return np; +} + +static void get_irq(struct device_node * np, int *irqptr) +{ + if (np) + *irqptr = irq_of_parse_and_map(np, 0); + else + *irqptr = NO_IRQ; +} + +/* 0x4 is outenable, 0x1 is out, thus 4 or 5 */ +#define SWITCH_GPIO(name, v, on) \ + (((v)&~1) | ((on)? \ + (name##_gpio_activestate==0?4:5): \ + (name##_gpio_activestate==0?5:4))) + +#define FTR_GPIO(name, bit) \ +static void ftr_gpio_set_##name(struct gpio_runtime *rt, int on)\ +{ \ + int v; \ + \ + if (unlikely(!rt)) return; \ + \ + if (name##_mute_gpio < 0) \ + return; \ + \ + v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, \ + name##_mute_gpio, \ + 0); \ + \ + /* muted = !on... */ \ + v = SWITCH_GPIO(name##_mute, v, !on); \ + \ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, \ + name##_mute_gpio, v); \ + \ + rt->implementation_private &= ~(1<<bit); \ + rt->implementation_private |= (!!on << bit); \ +} \ +static int ftr_gpio_get_##name(struct gpio_runtime *rt) \ +{ \ + if (unlikely(!rt)) return 0; \ + return (rt->implementation_private>>bit)&1; \ +} + +FTR_GPIO(headphone, 0); +FTR_GPIO(amp, 1); +FTR_GPIO(lineout, 2); + +static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on) +{ + int v; + + if (unlikely(!rt)) return; + if (hw_reset_gpio < 0) + return; + + v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, + hw_reset_gpio, 0); + v = SWITCH_GPIO(hw_reset, v, on); + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, + hw_reset_gpio, v); +} + +static void ftr_gpio_all_amps_off(struct gpio_runtime *rt) +{ + int saved; + + if (unlikely(!rt)) return; + saved = rt->implementation_private; + ftr_gpio_set_headphone(rt, 0); + ftr_gpio_set_amp(rt, 0); + ftr_gpio_set_lineout(rt, 0); + rt->implementation_private = saved; +} + +static void ftr_gpio_all_amps_restore(struct gpio_runtime *rt) +{ + int s; + + if (unlikely(!rt)) return; + s = rt->implementation_private; + ftr_gpio_set_headphone(rt, (s>>0)&1); + ftr_gpio_set_amp(rt, (s>>1)&1); + ftr_gpio_set_lineout(rt, (s>>2)&1); +} + +static void ftr_handle_notify(void *data) +{ + struct gpio_notification *notif = data; + + mutex_lock(¬if->mutex); + if (notif->notify) + notif->notify(notif->data); + mutex_unlock(¬if->mutex); +} + +static void gpio_enable_dual_edge(int gpio) +{ + int v; + + if (gpio == -1) + return; + v = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio, 0); + v |= 0x80; /* enable dual edge */ + pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, gpio, v); +} + +static void ftr_gpio_init(struct gpio_runtime *rt) +{ + get_gpio("headphone-mute", NULL, + &headphone_mute_gpio, + &headphone_mute_gpio_activestate); + get_gpio("amp-mute", NULL, + &_mute_gpio, + &_mute_gpio_activestate); + get_gpio("lineout-mute", NULL, + &lineout_mute_gpio, + &lineout_mute_gpio_activestate); + get_gpio("hw-reset", "audio-hw-reset", + &hw_reset_gpio, + &hw_reset_gpio_activestate); + + headphone_detect_node = get_gpio("headphone-detect", NULL, + &headphone_detect_gpio, + &headphone_detect_gpio_activestate); + /* go Apple, and thanks for giving these different names + * across the board... */ + lineout_detect_node = get_gpio("lineout-detect", "line-output-detect", + &lineout_detect_gpio, + &lineout_detect_gpio_activestate); + linein_detect_node = get_gpio("linein-detect", "line-input-detect", + &linein_detect_gpio, + &linein_detect_gpio_activestate); + + gpio_enable_dual_edge(headphone_detect_gpio); + gpio_enable_dual_edge(lineout_detect_gpio); + gpio_enable_dual_edge(linein_detect_gpio); + + get_irq(headphone_detect_node, &headphone_detect_irq); + get_irq(lineout_detect_node, &lineout_detect_irq); + get_irq(linein_detect_node, &linein_detect_irq); + + ftr_gpio_all_amps_off(rt); + rt->implementation_private = 0; + INIT_WORK(&rt->headphone_notify.work, ftr_handle_notify, + &rt->headphone_notify); + INIT_WORK(&rt->line_in_notify.work, ftr_handle_notify, + &rt->line_in_notify); + INIT_WORK(&rt->line_out_notify.work, ftr_handle_notify, + &rt->line_out_notify); + mutex_init(&rt->headphone_notify.mutex); + mutex_init(&rt->line_in_notify.mutex); + mutex_init(&rt->line_out_notify.mutex); +} + +static void ftr_gpio_exit(struct gpio_runtime *rt) +{ + ftr_gpio_all_amps_off(rt); + rt->implementation_private = 0; + if (rt->headphone_notify.notify) + free_irq(headphone_detect_irq, &rt->headphone_notify); + if (rt->line_in_notify.gpio_private) + free_irq(linein_detect_irq, &rt->line_in_notify); + if (rt->line_out_notify.gpio_private) + free_irq(lineout_detect_irq, &rt->line_out_notify); + cancel_delayed_work(&rt->headphone_notify.work); + cancel_delayed_work(&rt->line_in_notify.work); + cancel_delayed_work(&rt->line_out_notify.work); + flush_scheduled_work(); + mutex_destroy(&rt->headphone_notify.mutex); + mutex_destroy(&rt->line_in_notify.mutex); + mutex_destroy(&rt->line_out_notify.mutex); +} + +static irqreturn_t ftr_handle_notify_irq(int xx, + void *data, + struct pt_regs *regs) +{ + struct gpio_notification *notif = data; + + schedule_work(¬if->work); + + return IRQ_HANDLED; +} + +static int ftr_set_notify(struct gpio_runtime *rt, + enum notify_type type, + notify_func_t notify, + void *data) +{ + struct gpio_notification *notif; + notify_func_t old; + int irq; + char *name; + int err = -EBUSY; + + switch (type) { + case AOA_NOTIFY_HEADPHONE: + notif = &rt->headphone_notify; + name = "headphone-detect"; + irq = headphone_detect_irq; + break; + case AOA_NOTIFY_LINE_IN: + notif = &rt->line_in_notify; + name = "linein-detect"; + irq = linein_detect_irq; + break; + case AOA_NOTIFY_LINE_OUT: + notif = &rt->line_out_notify; + name = "lineout-detect"; + irq = lineout_detect_irq; + break; + default: + return -EINVAL; + } + + if (irq == NO_IRQ) + return -ENODEV; + + mutex_lock(¬if->mutex); + + old = notif->notify; + + if (!old && !notify) { + err = 0; + goto out_unlock; + } + + if (old && notify) { + if (old == notify && notif->data == data) + err = 0; + goto out_unlock; + } + + if (old && !notify) + free_irq(irq, notif); + + if (!old && notify) { + err = request_irq(irq, ftr_handle_notify_irq, 0, name, notif); + if (err) + goto out_unlock; + } + + notif->notify = notify; + notif->data = data; + + err = 0; + out_unlock: + mutex_unlock(¬if->mutex); + return err; +} + +static int ftr_get_detect(struct gpio_runtime *rt, + enum notify_type type) +{ + int gpio, ret, active; + + switch (type) { + case AOA_NOTIFY_HEADPHONE: + gpio = headphone_detect_gpio; + active = headphone_detect_gpio_activestate; + break; + case AOA_NOTIFY_LINE_IN: + gpio = linein_detect_gpio; + active = linein_detect_gpio_activestate; + break; + case AOA_NOTIFY_LINE_OUT: + gpio = lineout_detect_gpio; + active = lineout_detect_gpio_activestate; + break; + default: + return -EINVAL; + } + + if (gpio == -1) + return -ENODEV; + + ret = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio, 0); + if (ret < 0) + return ret; + return ((ret >> 1) & 1) == active; +} + +static struct gpio_methods methods = { + .init = ftr_gpio_init, + .exit = ftr_gpio_exit, + .all_amps_off = ftr_gpio_all_amps_off, + .all_amps_restore = ftr_gpio_all_amps_restore, + .set_headphone = ftr_gpio_set_headphone, + .set_speakers = ftr_gpio_set_amp, + .set_lineout = ftr_gpio_set_lineout, + .set_hw_reset = ftr_gpio_set_hw_reset, + .get_headphone = ftr_gpio_get_headphone, + .get_speakers = ftr_gpio_get_amp, + .get_lineout = ftr_gpio_get_lineout, + .set_notify = ftr_set_notify, + .get_detect = ftr_get_detect, +}; + +struct gpio_methods *ftr_gpio_methods = &methods; +EXPORT_SYMBOL_GPL(ftr_gpio_methods); diff --git a/sound/aoa/core/snd-aoa-gpio-pmf.c b/sound/aoa/core/snd-aoa-gpio-pmf.c new file mode 100644 index 000000000..2836c3218 --- /dev/null +++ b/sound/aoa/core/snd-aoa-gpio-pmf.c @@ -0,0 +1,254 @@ +/* + * Apple Onboard Audio pmf GPIOs + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + */ + +#include <asm/pmac_feature.h> +#include <asm/pmac_pfunc.h> +#include "../aoa.h" + +#define PMF_GPIO(name, bit) \ +static void pmf_gpio_set_##name(struct gpio_runtime *rt, int on)\ +{ \ + struct pmf_args args = { .count = 1, .u[0].v = !on }; \ + int rc; \ + \ + if (unlikely(!rt)) return; \ + rc = pmf_call_function(rt->node, #name "-mute", &args); \ + if (rc && rc != -ENODEV) \ + printk(KERN_WARNING "pmf_gpio_set_" #name \ + " failed, rc: %d\n", rc); \ + rt->implementation_private &= ~(1<<bit); \ + rt->implementation_private |= (!!on << bit); \ +} \ +static int pmf_gpio_get_##name(struct gpio_runtime *rt) \ +{ \ + if (unlikely(!rt)) return 0; \ + return (rt->implementation_private>>bit)&1; \ +} + +PMF_GPIO(headphone, 0); +PMF_GPIO(amp, 1); +PMF_GPIO(lineout, 2); + +static void pmf_gpio_set_hw_reset(struct gpio_runtime *rt, int on) +{ + struct pmf_args args = { .count = 1, .u[0].v = !!on }; + int rc; + + if (unlikely(!rt)) return; + rc = pmf_call_function(rt->node, "hw-reset", &args); + if (rc) + printk(KERN_WARNING "pmf_gpio_set_hw_reset" + " failed, rc: %d\n", rc); +} + +static void pmf_gpio_all_amps_off(struct gpio_runtime *rt) +{ + int saved; + + if (unlikely(!rt)) return; + saved = rt->implementation_private; + pmf_gpio_set_headphone(rt, 0); + pmf_gpio_set_amp(rt, 0); + pmf_gpio_set_lineout(rt, 0); + rt->implementation_private = saved; +} + +static void pmf_gpio_all_amps_restore(struct gpio_runtime *rt) +{ + int s; + + if (unlikely(!rt)) return; + s = rt->implementation_private; + pmf_gpio_set_headphone(rt, (s>>0)&1); + pmf_gpio_set_amp(rt, (s>>1)&1); + pmf_gpio_set_lineout(rt, (s>>2)&1); +} + +static void pmf_handle_notify(void *data) +{ + struct gpio_notification *notif = data; + + mutex_lock(¬if->mutex); + if (notif->notify) + notif->notify(notif->data); + mutex_unlock(¬if->mutex); +} + +static void pmf_gpio_init(struct gpio_runtime *rt) +{ + pmf_gpio_all_amps_off(rt); + rt->implementation_private = 0; + INIT_WORK(&rt->headphone_notify.work, pmf_handle_notify, + &rt->headphone_notify); + INIT_WORK(&rt->line_in_notify.work, pmf_handle_notify, + &rt->line_in_notify); + INIT_WORK(&rt->line_out_notify.work, pmf_handle_notify, + &rt->line_out_notify); + mutex_init(&rt->headphone_notify.mutex); + mutex_init(&rt->line_in_notify.mutex); + mutex_init(&rt->line_out_notify.mutex); +} + +static void pmf_gpio_exit(struct gpio_runtime *rt) +{ + pmf_gpio_all_amps_off(rt); + rt->implementation_private = 0; + + if (rt->headphone_notify.gpio_private) + pmf_unregister_irq_client(rt->headphone_notify.gpio_private); + if (rt->line_in_notify.gpio_private) + pmf_unregister_irq_client(rt->line_in_notify.gpio_private); + if (rt->line_out_notify.gpio_private) + pmf_unregister_irq_client(rt->line_out_notify.gpio_private); + + /* make sure no work is pending before freeing + * all things */ + cancel_delayed_work(&rt->headphone_notify.work); + cancel_delayed_work(&rt->line_in_notify.work); + cancel_delayed_work(&rt->line_out_notify.work); + flush_scheduled_work(); + + mutex_destroy(&rt->headphone_notify.mutex); + mutex_destroy(&rt->line_in_notify.mutex); + mutex_destroy(&rt->line_out_notify.mutex); + + if (rt->headphone_notify.gpio_private) + kfree(rt->headphone_notify.gpio_private); + if (rt->line_in_notify.gpio_private) + kfree(rt->line_in_notify.gpio_private); + if (rt->line_out_notify.gpio_private) + kfree(rt->line_out_notify.gpio_private); +} + +static void pmf_handle_notify_irq(void *data) +{ + struct gpio_notification *notif = data; + + schedule_work(¬if->work); +} + +static int pmf_set_notify(struct gpio_runtime *rt, + enum notify_type type, + notify_func_t notify, + void *data) +{ + struct gpio_notification *notif; + notify_func_t old; + struct pmf_irq_client *irq_client; + char *name; + int err = -EBUSY; + + switch (type) { + case AOA_NOTIFY_HEADPHONE: + notif = &rt->headphone_notify; + name = "headphone-detect"; + break; + case AOA_NOTIFY_LINE_IN: + notif = &rt->line_in_notify; + name = "linein-detect"; + break; + case AOA_NOTIFY_LINE_OUT: + notif = &rt->line_out_notify; + name = "lineout-detect"; + break; + default: + return -EINVAL; + } + + mutex_lock(¬if->mutex); + + old = notif->notify; + + if (!old && !notify) { + err = 0; + goto out_unlock; + } + + if (old && notify) { + if (old == notify && notif->data == data) + err = 0; + goto out_unlock; + } + + if (old && !notify) { + irq_client = notif->gpio_private; + pmf_unregister_irq_client(irq_client); + kfree(irq_client); + notif->gpio_private = NULL; + } + if (!old && notify) { + irq_client = kzalloc(sizeof(struct pmf_irq_client), + GFP_KERNEL); + irq_client->data = notif; + irq_client->handler = pmf_handle_notify_irq; + irq_client->owner = THIS_MODULE; + err = pmf_register_irq_client(rt->node, + name, + irq_client); + if (err) { + printk(KERN_ERR "snd-aoa: gpio layer failed to" + " register %s irq (%d)\n", name, err); + kfree(irq_client); + goto out_unlock; + } + notif->gpio_private = irq_client; + } + notif->notify = notify; + notif->data = data; + + err = 0; + out_unlock: + mutex_unlock(¬if->mutex); + return err; +} + +static int pmf_get_detect(struct gpio_runtime *rt, + enum notify_type type) +{ + char *name; + int err = -EBUSY, ret; + struct pmf_args args = { .count = 1, .u[0].p = &ret }; + + switch (type) { + case AOA_NOTIFY_HEADPHONE: + name = "headphone-detect"; + break; + case AOA_NOTIFY_LINE_IN: + name = "linein-detect"; + break; + case AOA_NOTIFY_LINE_OUT: + name = "lineout-detect"; + break; + default: + return -EINVAL; + } + + err = pmf_call_function(rt->node, name, &args); + if (err) + return err; + return ret; +} + +static struct gpio_methods methods = { + .init = pmf_gpio_init, + .exit = pmf_gpio_exit, + .all_amps_off = pmf_gpio_all_amps_off, + .all_amps_restore = pmf_gpio_all_amps_restore, + .set_headphone = pmf_gpio_set_headphone, + .set_speakers = pmf_gpio_set_amp, + .set_lineout = pmf_gpio_set_lineout, + .set_hw_reset = pmf_gpio_set_hw_reset, + .get_headphone = pmf_gpio_get_headphone, + .get_speakers = pmf_gpio_get_amp, + .get_lineout = pmf_gpio_get_lineout, + .set_notify = pmf_set_notify, + .get_detect = pmf_get_detect, +}; + +struct gpio_methods *pmf_gpio_methods = &methods; +EXPORT_SYMBOL_GPL(pmf_gpio_methods); diff --git a/sound/aoa/fabrics/Kconfig b/sound/aoa/fabrics/Kconfig new file mode 100644 index 000000000..c3bc7705c --- /dev/null +++ b/sound/aoa/fabrics/Kconfig @@ -0,0 +1,12 @@ +config SND_AOA_FABRIC_LAYOUT + tristate "layout-id fabric" + depends SND_AOA + select SND_AOA_SOUNDBUS + select SND_AOA_SOUNDBUS_I2S + ---help--- + This enables the layout-id fabric for the Apple Onboard + Audio driver, the module holding it all together + based on the device-tree's layout-id property. + + If you are unsure and have a later Apple machine, + compile it as a module. diff --git a/sound/aoa/fabrics/Makefile b/sound/aoa/fabrics/Makefile new file mode 100644 index 000000000..55fc5e7e5 --- /dev/null +++ b/sound/aoa/fabrics/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_SND_AOA_FABRIC_LAYOUT) += snd-aoa-fabric-layout.o diff --git a/sound/aoa/fabrics/snd-aoa-fabric-layout.c b/sound/aoa/fabrics/snd-aoa-fabric-layout.c new file mode 100644 index 000000000..172eb9547 --- /dev/null +++ b/sound/aoa/fabrics/snd-aoa-fabric-layout.c @@ -0,0 +1,1129 @@ +/* + * Apple Onboard Audio driver -- layout fabric + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + * + * + * This fabric module looks for sound codecs + * based on the layout-id property in the device tree. + * + */ + +#include <asm/prom.h> +#include <linux/list.h> +#include <linux/module.h> +#include "../aoa.h" +#include "../soundbus/soundbus.h" + +MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Layout-ID fabric for snd-aoa"); + +#define MAX_CODECS_PER_BUS 2 + +/* These are the connections the layout fabric + * knows about. It doesn't really care about the + * input ones, but I thought I'd separate them + * to give them proper names. The thing is that + * Apple usually will distinguish the active output + * by GPIOs, while the active input is set directly + * on the codec. Hence we here tell the codec what + * we think is connected. This information is hard- + * coded below ... */ +#define CC_SPEAKERS (1<<0) +#define CC_HEADPHONE (1<<1) +#define CC_LINEOUT (1<<2) +#define CC_DIGITALOUT (1<<3) +#define CC_LINEIN (1<<4) +#define CC_MICROPHONE (1<<5) +#define CC_DIGITALIN (1<<6) +/* pretty bogus but users complain... + * This is a flag saying that the LINEOUT + * should be renamed to HEADPHONE. + * be careful with input detection! */ +#define CC_LINEOUT_LABELLED_HEADPHONE (1<<7) + +struct codec_connection { + /* CC_ flags from above */ + int connected; + /* codec dependent bit to be set in the aoa_codec.connected field. + * This intentionally doesn't have any generic flags because the + * fabric has to know the codec anyway and all codecs might have + * different connectors */ + int codec_bit; +}; + +struct codec_connect_info { + char *name; + struct codec_connection *connections; +}; + +#define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF (1<<0) + +struct layout { + unsigned int layout_id; + struct codec_connect_info codecs[MAX_CODECS_PER_BUS]; + int flags; + + /* if busname is not assigned, we use 'Master' below, + * so that our layout table doesn't need to be filled + * too much. + * We only assign these two if we expect to find more + * than one soundbus, i.e. on those machines with + * multiple layout-ids */ + char *busname; + int pcmid; +}; + +MODULE_ALIAS("sound-layout-36"); +MODULE_ALIAS("sound-layout-41"); +MODULE_ALIAS("sound-layout-45"); +MODULE_ALIAS("sound-layout-47"); +MODULE_ALIAS("sound-layout-48"); +MODULE_ALIAS("sound-layout-49"); +MODULE_ALIAS("sound-layout-50"); +MODULE_ALIAS("sound-layout-51"); +MODULE_ALIAS("sound-layout-56"); +MODULE_ALIAS("sound-layout-57"); +MODULE_ALIAS("sound-layout-58"); +MODULE_ALIAS("sound-layout-60"); +MODULE_ALIAS("sound-layout-61"); +MODULE_ALIAS("sound-layout-62"); +MODULE_ALIAS("sound-layout-64"); +MODULE_ALIAS("sound-layout-65"); +MODULE_ALIAS("sound-layout-66"); +MODULE_ALIAS("sound-layout-67"); +MODULE_ALIAS("sound-layout-68"); +MODULE_ALIAS("sound-layout-69"); +MODULE_ALIAS("sound-layout-70"); +MODULE_ALIAS("sound-layout-72"); +MODULE_ALIAS("sound-layout-76"); +MODULE_ALIAS("sound-layout-80"); +MODULE_ALIAS("sound-layout-82"); +MODULE_ALIAS("sound-layout-84"); +MODULE_ALIAS("sound-layout-86"); +MODULE_ALIAS("sound-layout-90"); +MODULE_ALIAS("sound-layout-92"); +MODULE_ALIAS("sound-layout-94"); +MODULE_ALIAS("sound-layout-96"); +MODULE_ALIAS("sound-layout-98"); +MODULE_ALIAS("sound-layout-100"); + +/* onyx with all but microphone connected */ +static struct codec_connection onyx_connections_nomic[] = { + { + .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, + .codec_bit = 0, + }, + { + .connected = CC_DIGITALOUT, + .codec_bit = 1, + }, + { + .connected = CC_LINEIN, + .codec_bit = 2, + }, + {} /* terminate array by .connected == 0 */ +}; + +/* onyx on machines without headphone */ +static struct codec_connection onyx_connections_noheadphones[] = { + { + .connected = CC_SPEAKERS | CC_LINEOUT | + CC_LINEOUT_LABELLED_HEADPHONE, + .codec_bit = 0, + }, + { + .connected = CC_DIGITALOUT, + .codec_bit = 1, + }, + /* FIXME: are these correct? probably not for all the machines + * below ... If not this will need separating. */ + { + .connected = CC_LINEIN, + .codec_bit = 2, + }, + { + .connected = CC_MICROPHONE, + .codec_bit = 3, + }, + {} /* terminate array by .connected == 0 */ +}; + +/* onyx on machines with real line-out */ +static struct codec_connection onyx_connections_reallineout[] = { + { + .connected = CC_SPEAKERS | CC_LINEOUT | CC_HEADPHONE, + .codec_bit = 0, + }, + { + .connected = CC_DIGITALOUT, + .codec_bit = 1, + }, + { + .connected = CC_LINEIN, + .codec_bit = 2, + }, + {} /* terminate array by .connected == 0 */ +}; + +/* tas on machines without line out */ +static struct codec_connection tas_connections_nolineout[] = { + { + .connected = CC_SPEAKERS | CC_HEADPHONE, + .codec_bit = 0, + }, + { + .connected = CC_LINEIN, + .codec_bit = 2, + }, + { + .connected = CC_MICROPHONE, + .codec_bit = 3, + }, + {} /* terminate array by .connected == 0 */ +}; + +/* tas on machines with neither line out nor line in */ +static struct codec_connection tas_connections_noline[] = { + { + .connected = CC_SPEAKERS | CC_HEADPHONE, + .codec_bit = 0, + }, + { + .connected = CC_MICROPHONE, + .codec_bit = 3, + }, + {} /* terminate array by .connected == 0 */ +}; + +/* tas on machines without microphone */ +static struct codec_connection tas_connections_nomic[] = { + { + .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, + .codec_bit = 0, + }, + { + .connected = CC_LINEIN, + .codec_bit = 2, + }, + {} /* terminate array by .connected == 0 */ +}; + +/* tas on machines with everything connected */ +static struct codec_connection tas_connections_all[] = { + { + .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, + .codec_bit = 0, + }, + { + .connected = CC_LINEIN, + .codec_bit = 2, + }, + { + .connected = CC_MICROPHONE, + .codec_bit = 3, + }, + {} /* terminate array by .connected == 0 */ +}; + +static struct codec_connection toonie_connections[] = { + { + .connected = CC_SPEAKERS | CC_HEADPHONE, + .codec_bit = 0, + }, + {} /* terminate array by .connected == 0 */ +}; + +static struct codec_connection topaz_input[] = { + { + .connected = CC_DIGITALIN, + .codec_bit = 0, + }, + {} /* terminate array by .connected == 0 */ +}; + +static struct codec_connection topaz_output[] = { + { + .connected = CC_DIGITALOUT, + .codec_bit = 1, + }, + {} /* terminate array by .connected == 0 */ +}; + +static struct codec_connection topaz_inout[] = { + { + .connected = CC_DIGITALIN, + .codec_bit = 0, + }, + { + .connected = CC_DIGITALOUT, + .codec_bit = 1, + }, + {} /* terminate array by .connected == 0 */ +}; + +static struct layout layouts[] = { + /* last PowerBooks (15" Oct 2005) */ + { .layout_id = 82, + .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + .codecs[1] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + /* PowerMac9,1 */ + { .layout_id = 60, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_reallineout, + }, + }, + /* PowerMac9,1 */ + { .layout_id = 61, + .codecs[0] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + /* PowerBook5,7 */ + { .layout_id = 64, + .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + }, + /* PowerBook5,7 */ + { .layout_id = 65, + .codecs[0] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + /* PowerBook5,9 [17" Oct 2005] */ + { .layout_id = 84, + .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + .codecs[1] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + /* PowerMac8,1 */ + { .layout_id = 45, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + .codecs[1] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + /* Quad PowerMac (analog in, analog/digital out) */ + { .layout_id = 68, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_nomic, + }, + }, + /* Quad PowerMac (digital in) */ + { .layout_id = 69, + .codecs[0] = { + .name = "topaz", + .connections = topaz_input, + }, + .busname = "digital in", .pcmid = 1 }, + /* Early 2005 PowerBook (PowerBook 5,6) */ + { .layout_id = 70, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_nolineout, + }, + }, + /* PowerBook 5,4 */ + { .layout_id = 51, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_nolineout, + }, + }, + /* PowerBook6,7 */ + { .layout_id = 80, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_noline, + }, + }, + /* PowerBook6,8 */ + { .layout_id = 72, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_nolineout, + }, + }, + /* PowerMac8,2 */ + { .layout_id = 86, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_nomic, + }, + .codecs[1] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + /* PowerBook6,7 */ + { .layout_id = 92, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_nolineout, + }, + }, + /* PowerMac10,1 (Mac Mini) */ + { .layout_id = 58, + .codecs[0] = { + .name = "toonie", + .connections = toonie_connections, + }, + }, + { + .layout_id = 96, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + }, + /* unknown, untested, but this comes from Apple */ + { .layout_id = 41, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_all, + }, + }, + { .layout_id = 36, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_nomic, + }, + .codecs[1] = { + .name = "topaz", + .connections = topaz_inout, + }, + }, + { .layout_id = 47, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + }, + { .layout_id = 48, + .codecs[0] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + { .layout_id = 49, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_nomic, + }, + }, + { .layout_id = 50, + .codecs[0] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + { .layout_id = 56, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + }, + { .layout_id = 57, + .codecs[0] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + { .layout_id = 62, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + .codecs[1] = { + .name = "topaz", + .connections = topaz_output, + }, + }, + { .layout_id = 66, + .codecs[0] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + }, + { .layout_id = 67, + .codecs[0] = { + .name = "topaz", + .connections = topaz_input, + }, + }, + { .layout_id = 76, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_nomic, + }, + .codecs[1] = { + .name = "topaz", + .connections = topaz_inout, + }, + }, + { .layout_id = 90, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_noline, + }, + }, + { .layout_id = 94, + .codecs[0] = { + .name = "onyx", + /* but it has an external mic?? how to select? */ + .connections = onyx_connections_noheadphones, + }, + }, + { .layout_id = 98, + .codecs[0] = { + .name = "toonie", + .connections = toonie_connections, + }, + }, + { .layout_id = 100, + .codecs[0] = { + .name = "topaz", + .connections = topaz_input, + }, + .codecs[1] = { + .name = "onyx", + .connections = onyx_connections_noheadphones, + }, + }, + {} +}; + +static struct layout *find_layout_by_id(unsigned int id) +{ + struct layout *l; + + l = layouts; + while (l->layout_id) { + if (l->layout_id == id) + return l; + l++; + } + return NULL; +} + +static void use_layout(struct layout *l) +{ + int i; + + for (i=0; i<MAX_CODECS_PER_BUS; i++) { + if (l->codecs[i].name) { + request_module("snd-aoa-codec-%s", l->codecs[i].name); + } + } + /* now we wait for the codecs to call us back */ +} + +struct layout_dev; + +struct layout_dev_ptr { + struct layout_dev *ptr; +}; + +struct layout_dev { + struct list_head list; + struct soundbus_dev *sdev; + struct device_node *sound; + struct aoa_codec *codecs[MAX_CODECS_PER_BUS]; + struct layout *layout; + struct gpio_runtime gpio; + + /* we need these for headphone/lineout detection */ + struct snd_kcontrol *headphone_ctrl; + struct snd_kcontrol *lineout_ctrl; + struct snd_kcontrol *speaker_ctrl; + struct snd_kcontrol *headphone_detected_ctrl; + struct snd_kcontrol *lineout_detected_ctrl; + + struct layout_dev_ptr selfptr_headphone; + struct layout_dev_ptr selfptr_lineout; + + u32 have_lineout_detect:1, + have_headphone_detect:1, + switch_on_headphone:1, + switch_on_lineout:1; +}; + +static LIST_HEAD(layouts_list); +static int layouts_list_items; +/* this can go away but only if we allow multiple cards, + * make the fabric handle all the card stuff, etc... */ +static struct layout_dev *layout_device; + +static int control_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +#define AMP_CONTROL(n, description) \ +static int n##_control_get(struct snd_kcontrol *kcontrol, \ + struct snd_ctl_elem_value *ucontrol) \ +{ \ + struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \ + if (gpio->methods && gpio->methods->get_##n) \ + ucontrol->value.integer.value[0] = \ + gpio->methods->get_##n(gpio); \ + return 0; \ +} \ +static int n##_control_put(struct snd_kcontrol *kcontrol, \ + struct snd_ctl_elem_value *ucontrol) \ +{ \ + struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \ + if (gpio->methods && gpio->methods->get_##n) \ + gpio->methods->set_##n(gpio, \ + ucontrol->value.integer.value[0]); \ + return 1; \ +} \ +static struct snd_kcontrol_new n##_ctl = { \ + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ + .name = description, \ + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .info = control_info, \ + .get = n##_control_get, \ + .put = n##_control_put, \ +} + +AMP_CONTROL(headphone, "Headphone Switch"); +AMP_CONTROL(speakers, "Speakers Switch"); +AMP_CONTROL(lineout, "Line-Out Switch"); + +static int detect_choice_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); + + switch (kcontrol->private_value) { + case 0: + ucontrol->value.integer.value[0] = ldev->switch_on_headphone; + break; + case 1: + ucontrol->value.integer.value[0] = ldev->switch_on_lineout; + break; + default: + return -ENODEV; + } + return 0; +} + +static int detect_choice_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); + + switch (kcontrol->private_value) { + case 0: + ldev->switch_on_headphone = !!ucontrol->value.integer.value[0]; + break; + case 1: + ldev->switch_on_lineout = !!ucontrol->value.integer.value[0]; + break; + default: + return -ENODEV; + } + return 1; +} + +static struct snd_kcontrol_new headphone_detect_choice = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Headphone Detect Autoswitch", + .info = control_info, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .get = detect_choice_get, + .put = detect_choice_put, + .private_value = 0, +}; + +static struct snd_kcontrol_new lineout_detect_choice = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Line-Out Detect Autoswitch", + .info = control_info, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .get = detect_choice_get, + .put = detect_choice_put, + .private_value = 1, +}; + +static int detected_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); + int v; + + switch (kcontrol->private_value) { + case 0: + v = ldev->gpio.methods->get_detect(&ldev->gpio, + AOA_NOTIFY_HEADPHONE); + break; + case 1: + v = ldev->gpio.methods->get_detect(&ldev->gpio, + AOA_NOTIFY_LINE_OUT); + break; + default: + return -ENODEV; + } + ucontrol->value.integer.value[0] = v; + return 0; +} + +static struct snd_kcontrol_new headphone_detected = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Headphone Detected", + .info = control_info, + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .get = detected_get, + .private_value = 0, +}; + +static struct snd_kcontrol_new lineout_detected = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Line-Out Detected", + .info = control_info, + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .get = detected_get, + .private_value = 1, +}; + +static int check_codec(struct aoa_codec *codec, + struct layout_dev *ldev, + struct codec_connect_info *cci) +{ + u32 *ref; + char propname[32]; + struct codec_connection *cc; + + /* if the codec has a 'codec' node, we require a reference */ + if (codec->node && (strcmp(codec->node->name, "codec") == 0)) { + snprintf(propname, sizeof(propname), + "platform-%s-codec-ref", codec->name); + ref = (u32*)get_property(ldev->sound, propname, NULL); + if (!ref) { + printk(KERN_INFO "snd-aoa-fabric-layout: " + "required property %s not present\n", propname); + return -ENODEV; + } + if (*ref != codec->node->linux_phandle) { + printk(KERN_INFO "snd-aoa-fabric-layout: " + "%s doesn't match!\n", propname); + return -ENODEV; + } + } else { + if (layouts_list_items != 1) { + printk(KERN_INFO "snd-aoa-fabric-layout: " + "more than one soundbus, but no references.\n"); + return -ENODEV; + } + } + codec->soundbus_dev = ldev->sdev; + codec->gpio = &ldev->gpio; + + cc = cci->connections; + if (!cc) + return -EINVAL; + + printk(KERN_INFO "snd-aoa-fabric-layout: can use this codec\n"); + + codec->connected = 0; + codec->fabric_data = cc; + + while (cc->connected) { + codec->connected |= 1<<cc->codec_bit; + cc++; + } + + return 0; +} + +static int layout_found_codec(struct aoa_codec *codec) +{ + struct layout_dev *ldev; + int i; + + list_for_each_entry(ldev, &layouts_list, list) { + for (i=0; i<MAX_CODECS_PER_BUS; i++) { + if (!ldev->layout->codecs[i].name) + continue; + if (strcmp(ldev->layout->codecs[i].name, codec->name) == 0) { + if (check_codec(codec, + ldev, + &ldev->layout->codecs[i]) == 0) + return 0; + } + } + } + return -ENODEV; +} + +static void layout_remove_codec(struct aoa_codec *codec) +{ + int i; + /* here remove the codec from the layout dev's + * codec reference */ + + codec->soundbus_dev = NULL; + codec->gpio = NULL; + for (i=0; i<MAX_CODECS_PER_BUS; i++) { + } +} + +static void layout_notify(void *data) +{ + struct layout_dev_ptr *dptr = data; + struct layout_dev *ldev; + int v, update; + struct snd_kcontrol *detected, *c; + struct snd_card *card = aoa_get_card(); + + ldev = dptr->ptr; + if (data == &ldev->selfptr_headphone) { + v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_HEADPHONE); + detected = ldev->headphone_detected_ctrl; + update = ldev->switch_on_headphone; + if (update) { + ldev->gpio.methods->set_speakers(&ldev->gpio, !v); + ldev->gpio.methods->set_headphone(&ldev->gpio, v); + ldev->gpio.methods->set_lineout(&ldev->gpio, 0); + } + } else if (data == &ldev->selfptr_lineout) { + v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_LINE_OUT); + detected = ldev->lineout_detected_ctrl; + update = ldev->switch_on_lineout; + if (update) { + ldev->gpio.methods->set_speakers(&ldev->gpio, !v); + ldev->gpio.methods->set_headphone(&ldev->gpio, 0); + ldev->gpio.methods->set_lineout(&ldev->gpio, v); + } + } else + return; + + if (detected) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &detected->id); + if (update) { + c = ldev->headphone_ctrl; + if (c) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); + c = ldev->speaker_ctrl; + if (c) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); + c = ldev->lineout_ctrl; + if (c) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); + } +} + +static void layout_attached_codec(struct aoa_codec *codec) +{ + struct codec_connection *cc; + struct snd_kcontrol *ctl; + int headphones, lineout; + struct layout_dev *ldev = layout_device; + + /* need to add this codec to our codec array! */ + + cc = codec->fabric_data; + + headphones = codec->gpio->methods->get_detect(codec->gpio, + AOA_NOTIFY_HEADPHONE); + lineout = codec->gpio->methods->get_detect(codec->gpio, + AOA_NOTIFY_LINE_OUT); + + while (cc->connected) { + if (cc->connected & CC_SPEAKERS) { + if (headphones <= 0 && lineout <= 0) + ldev->gpio.methods->set_speakers(codec->gpio, 1); + ctl = snd_ctl_new1(&speakers_ctl, codec->gpio); + ldev->speaker_ctrl = ctl; + aoa_snd_ctl_add(ctl); + } + if (cc->connected & CC_HEADPHONE) { + if (headphones == 1) + ldev->gpio.methods->set_headphone(codec->gpio, 1); + ctl = snd_ctl_new1(&headphone_ctl, codec->gpio); + ldev->headphone_ctrl = ctl; + aoa_snd_ctl_add(ctl); + ldev->have_headphone_detect = + !ldev->gpio.methods + ->set_notify(&ldev->gpio, + AOA_NOTIFY_HEADPHONE, + layout_notify, + &ldev->selfptr_headphone); + if (ldev->have_headphone_detect) { + ctl = snd_ctl_new1(&headphone_detect_choice, + ldev); + aoa_snd_ctl_add(ctl); + ctl = snd_ctl_new1(&headphone_detected, + ldev); + ldev->headphone_detected_ctrl = ctl; + aoa_snd_ctl_add(ctl); + } + } + if (cc->connected & CC_LINEOUT) { + if (lineout == 1) + ldev->gpio.methods->set_lineout(codec->gpio, 1); + ctl = snd_ctl_new1(&lineout_ctl, codec->gpio); + if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) + strlcpy(ctl->id.name, + "Headphone Switch", sizeof(ctl->id.name)); + ldev->lineout_ctrl = ctl; + aoa_snd_ctl_add(ctl); + ldev->have_lineout_detect = + !ldev->gpio.methods + ->set_notify(&ldev->gpio, + AOA_NOTIFY_LINE_OUT, + layout_notify, + &ldev->selfptr_lineout); + if (ldev->have_lineout_detect) { + ctl = snd_ctl_new1(&lineout_detect_choice, + ldev); + if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) + strlcpy(ctl->id.name, + "Headphone Detect Autoswitch", + sizeof(ctl->id.name)); + aoa_snd_ctl_add(ctl); + ctl = snd_ctl_new1(&lineout_detected, + ldev); + if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) + strlcpy(ctl->id.name, + "Headphone Detected", + sizeof(ctl->id.name)); + ldev->lineout_detected_ctrl = ctl; + aoa_snd_ctl_add(ctl); + } + } + cc++; + } + /* now update initial state */ + if (ldev->have_headphone_detect) + layout_notify(&ldev->selfptr_headphone); + if (ldev->have_lineout_detect) + layout_notify(&ldev->selfptr_lineout); +} + +static struct aoa_fabric layout_fabric = { + .name = "SoundByLayout", + .owner = THIS_MODULE, + .found_codec = layout_found_codec, + .remove_codec = layout_remove_codec, + .attached_codec = layout_attached_codec, +}; + +static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) +{ + struct device_node *sound = NULL; + unsigned int *layout_id; + struct layout *layout; + struct layout_dev *ldev = NULL; + int err; + + /* hm, currently we can only have one ... */ + if (layout_device) + return -ENODEV; + + /* by breaking out we keep a reference */ + while ((sound = of_get_next_child(sdev->ofdev.node, sound))) { + if (sound->type && strcasecmp(sound->type, "soundchip") == 0) + break; + } + if (!sound) return -ENODEV; + + layout_id = (unsigned int *) get_property(sound, "layout-id", NULL); + if (!layout_id) + goto outnodev; + printk(KERN_INFO "snd-aoa-fabric-layout: found bus with layout %d\n", + *layout_id); + + layout = find_layout_by_id(*layout_id); + if (!layout) { + printk(KERN_ERR "snd-aoa-fabric-layout: unknown layout\n"); + goto outnodev; + } + + ldev = kzalloc(sizeof(struct layout_dev), GFP_KERNEL); + if (!ldev) + goto outnodev; + + layout_device = ldev; + ldev->sdev = sdev; + ldev->sound = sound; + ldev->layout = layout; + ldev->gpio.node = sound->parent; + switch (layout->layout_id) { + case 41: /* that unknown machine no one seems to have */ + case 51: /* PowerBook5,4 */ + case 58: /* Mac Mini */ + ldev->gpio.methods = ftr_gpio_methods; + printk(KERN_DEBUG + "snd-aoa-fabric-layout: Using direct GPIOs\n"); + break; + default: + ldev->gpio.methods = pmf_gpio_methods; + printk(KERN_DEBUG + "snd-aoa-fabric-layout: Using PMF GPIOs\n"); + } + ldev->selfptr_headphone.ptr = ldev; + ldev->selfptr_lineout.ptr = ldev; + sdev->ofdev.dev.driver_data = ldev; + list_add(&ldev->list, &layouts_list); + layouts_list_items++; + + /* assign these before registering ourselves, so + * callbacks that are done during registration + * already have the values */ + sdev->pcmid = ldev->layout->pcmid; + if (ldev->layout->busname) { + sdev->pcmname = ldev->layout->busname; + } else { + sdev->pcmname = "Master"; + } + + ldev->gpio.methods->init(&ldev->gpio); + + err = aoa_fabric_register(&layout_fabric); + if (err && err != -EALREADY) { + printk(KERN_INFO "snd-aoa-fabric-layout: can't use," + " another fabric is active!\n"); + goto outlistdel; + } + + use_layout(layout); + ldev->switch_on_headphone = 1; + ldev->switch_on_lineout = 1; + return 0; + outlistdel: + /* we won't be using these then... */ + ldev->gpio.methods->exit(&ldev->gpio); + /* reset if we didn't use it */ + sdev->pcmname = NULL; + sdev->pcmid = -1; + list_del(&ldev->list); + layouts_list_items--; + outnodev: + if (sound) of_node_put(sound); + layout_device = NULL; + if (ldev) kfree(ldev); + return -ENODEV; +} + +static int aoa_fabric_layout_remove(struct soundbus_dev *sdev) +{ + struct layout_dev *ldev = sdev->ofdev.dev.driver_data; + int i; + + for (i=0; i<MAX_CODECS_PER_BUS; i++) { + if (ldev->codecs[i]) { + aoa_fabric_unlink_codec(ldev->codecs[i]); + } + ldev->codecs[i] = NULL; + } + list_del(&ldev->list); + layouts_list_items--; + of_node_put(ldev->sound); + + ldev->gpio.methods->set_notify(&ldev->gpio, + AOA_NOTIFY_HEADPHONE, + NULL, + NULL); + ldev->gpio.methods->set_notify(&ldev->gpio, + AOA_NOTIFY_LINE_OUT, + NULL, + NULL); + + ldev->gpio.methods->exit(&ldev->gpio); + layout_device = NULL; + kfree(ldev); + sdev->pcmid = -1; + sdev->pcmname = NULL; + return 0; +} + +#ifdef CONFIG_PM +static int aoa_fabric_layout_suspend(struct soundbus_dev *sdev, pm_message_t state) +{ + struct layout_dev *ldev = sdev->ofdev.dev.driver_data; + + printk("aoa_fabric_layout_suspend()\n"); + + if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) + ldev->gpio.methods->all_amps_off(&ldev->gpio); + + return 0; +} + +static int aoa_fabric_layout_resume(struct soundbus_dev *sdev) +{ + struct layout_dev *ldev = sdev->ofdev.dev.driver_data; + + printk("aoa_fabric_layout_resume()\n"); + + if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) + ldev->gpio.methods->all_amps_restore(&ldev->gpio); + + return 0; +} +#endif + +static struct soundbus_driver aoa_soundbus_driver = { + .name = "snd_aoa_soundbus_drv", + .owner = THIS_MODULE, + .probe = aoa_fabric_layout_probe, + .remove = aoa_fabric_layout_remove, +#ifdef CONFIG_PM + .suspend = aoa_fabric_layout_suspend, + .resume = aoa_fabric_layout_resume, +#endif +}; + +static int __init aoa_fabric_layout_init(void) +{ + int err; + + err = soundbus_register_driver(&aoa_soundbus_driver); + if (err) + return err; + return 0; +} + +static void __exit aoa_fabric_layout_exit(void) +{ + soundbus_unregister_driver(&aoa_soundbus_driver); + aoa_fabric_unregister(&layout_fabric); +} + +module_init(aoa_fabric_layout_init); +module_exit(aoa_fabric_layout_exit); diff --git a/sound/aoa/soundbus/Kconfig b/sound/aoa/soundbus/Kconfig new file mode 100644 index 000000000..7368b7ddf --- /dev/null +++ b/sound/aoa/soundbus/Kconfig @@ -0,0 +1,15 @@ +config SND_AOA_SOUNDBUS + tristate "Apple Soundbus support" + depends on SOUND + select SND_PCM + ---help--- + This option enables the generic driver for the soundbus + support on Apple machines. + + It is required for the sound bus implementations. + +config SND_AOA_SOUNDBUS_I2S + tristate "I2S bus support" + depends on SND_AOA_SOUNDBUS && PCI + ---help--- + This option enables support for Apple I2S busses. diff --git a/sound/aoa/soundbus/Makefile b/sound/aoa/soundbus/Makefile new file mode 100644 index 000000000..0e61f5aa0 --- /dev/null +++ b/sound/aoa/soundbus/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_SND_AOA_SOUNDBUS) += snd-aoa-soundbus.o +snd-aoa-soundbus-objs := core.o sysfs.o +obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += i2sbus/ diff --git a/sound/aoa/soundbus/core.c b/sound/aoa/soundbus/core.c new file mode 100644 index 000000000..47b3e3768 --- /dev/null +++ b/sound/aoa/soundbus/core.c @@ -0,0 +1,250 @@ +/* + * soundbus + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + */ + +#include <linux/module.h> +#include "soundbus.h" + +MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Apple Soundbus"); + +struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev) +{ + struct device *tmp; + + if (!dev) + return NULL; + tmp = get_device(&dev->ofdev.dev); + if (tmp) + return to_soundbus_device(tmp); + else + return NULL; +} +EXPORT_SYMBOL_GPL(soundbus_dev_get); + +void soundbus_dev_put(struct soundbus_dev *dev) +{ + if (dev) + put_device(&dev->ofdev.dev); +} +EXPORT_SYMBOL_GPL(soundbus_dev_put); + +static int soundbus_probe(struct device *dev) +{ + int error = -ENODEV; + struct soundbus_driver *drv; + struct soundbus_dev *soundbus_dev; + + drv = to_soundbus_driver(dev->driver); + soundbus_dev = to_soundbus_device(dev); + + if (!drv->probe) + return error; + + soundbus_dev_get(soundbus_dev); + + error = drv->probe(soundbus_dev); + if (error) + soundbus_dev_put(soundbus_dev); + + return error; +} + + +static int soundbus_uevent(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) +{ + struct soundbus_dev * soundbus_dev; + struct of_device * of; + char *scratch, *compat, *compat2; + int i = 0; + int length, cplen, cplen2, seen = 0; + + if (!dev) + return -ENODEV; + + soundbus_dev = to_soundbus_device(dev); + if (!soundbus_dev) + return -ENODEV; + + of = &soundbus_dev->ofdev; + + /* stuff we want to pass to /sbin/hotplug */ + envp[i++] = scratch = buffer; + length = scnprintf (scratch, buffer_size, "OF_NAME=%s", of->node->name); + ++length; + buffer_size -= length; + if ((buffer_size <= 0) || (i >= num_envp)) + return -ENOMEM; + scratch += length; + + envp[i++] = scratch; + length = scnprintf (scratch, buffer_size, "OF_TYPE=%s", of->node->type); + ++length; + buffer_size -= length; + if ((buffer_size <= 0) || (i >= num_envp)) + return -ENOMEM; + scratch += length; + + /* Since the compatible field can contain pretty much anything + * it's not really legal to split it out with commas. We split it + * up using a number of environment variables instead. */ + + compat = (char *) get_property(of->node, "compatible", &cplen); + compat2 = compat; + cplen2= cplen; + while (compat && cplen > 0) { + envp[i++] = scratch; + length = scnprintf (scratch, buffer_size, + "OF_COMPATIBLE_%d=%s", seen, compat); + ++length; + buffer_size -= length; + if ((buffer_size <= 0) || (i >= num_envp)) + return -ENOMEM; + scratch += length; + length = strlen (compat) + 1; + compat += length; + cplen -= length; + seen++; + } + + envp[i++] = scratch; + length = scnprintf (scratch, buffer_size, "OF_COMPATIBLE_N=%d", seen); + ++length; + buffer_size -= length; + if ((buffer_size <= 0) || (i >= num_envp)) + return -ENOMEM; + scratch += length; + + envp[i++] = scratch; + length = scnprintf (scratch, buffer_size, "MODALIAS=%s", + soundbus_dev->modalias); + + buffer_size -= length; + if ((buffer_size <= 0) || (i >= num_envp)) + return -ENOMEM; + + envp[i] = NULL; + + return 0; +} + +static int soundbus_device_remove(struct device *dev) +{ + struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); + struct soundbus_driver * drv = to_soundbus_driver(dev->driver); + + if (dev->driver && drv->remove) + drv->remove(soundbus_dev); + soundbus_dev_put(soundbus_dev); + + return 0; +} + +static void soundbus_device_shutdown(struct device *dev) +{ + struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); + struct soundbus_driver * drv = to_soundbus_driver(dev->driver); + + if (dev->driver && drv->shutdown) + drv->shutdown(soundbus_dev); +} + +#ifdef CONFIG_PM + +static int soundbus_device_suspend(struct device *dev, pm_message_t state) +{ + struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); + struct soundbus_driver * drv = to_soundbus_driver(dev->driver); + + if (dev->driver && drv->suspend) + return drv->suspend(soundbus_dev, state); + return 0; +} + +static int soundbus_device_resume(struct device * dev) +{ + struct soundbus_dev * soundbus_dev = to_soundbus_device(dev); + struct soundbus_driver * drv = to_soundbus_driver(dev->driver); + + if (dev->driver && drv->resume) + return drv->resume(soundbus_dev); + return 0; +} + +#endif /* CONFIG_PM */ + +extern struct device_attribute soundbus_dev_attrs[]; + +static struct bus_type soundbus_bus_type = { + .name = "aoa-soundbus", + .probe = soundbus_probe, + .uevent = soundbus_uevent, + .remove = soundbus_device_remove, + .shutdown = soundbus_device_shutdown, +#ifdef CONFIG_PM + .suspend = soundbus_device_suspend, + .resume = soundbus_device_resume, +#endif + .dev_attrs = soundbus_dev_attrs, +}; + +int soundbus_add_one(struct soundbus_dev *dev) +{ + static int devcount; + + /* sanity checks */ + if (!dev->attach_codec || + !dev->ofdev.node || + dev->pcmname || + dev->pcmid != -1) { + printk(KERN_ERR "soundbus: adding device failed sanity check!\n"); + return -EINVAL; + } + + snprintf(dev->ofdev.dev.bus_id, BUS_ID_SIZE, "soundbus:%x", ++devcount); + dev->ofdev.dev.bus = &soundbus_bus_type; + return of_device_register(&dev->ofdev); +} +EXPORT_SYMBOL_GPL(soundbus_add_one); + +void soundbus_remove_one(struct soundbus_dev *dev) +{ + of_device_unregister(&dev->ofdev); +} +EXPORT_SYMBOL_GPL(soundbus_remove_one); + +int soundbus_register_driver(struct soundbus_driver *drv) +{ + /* initialize common driver fields */ + drv->driver.name = drv->name; + drv->driver.bus = &soundbus_bus_type; + + /* register with core */ + return driver_register(&drv->driver); +} +EXPORT_SYMBOL_GPL(soundbus_register_driver); + +void soundbus_unregister_driver(struct soundbus_driver *drv) +{ + driver_unregister(&drv->driver); +} +EXPORT_SYMBOL_GPL(soundbus_unregister_driver); + +static int __init soundbus_init(void) +{ + return bus_register(&soundbus_bus_type); +} + +static void __exit soundbus_exit(void) +{ + bus_unregister(&soundbus_bus_type); +} + +subsys_initcall(soundbus_init); +module_exit(soundbus_exit); diff --git a/sound/aoa/soundbus/i2sbus/Makefile b/sound/aoa/soundbus/i2sbus/Makefile new file mode 100644 index 000000000..e57a5cf65 --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += snd-aoa-i2sbus.o +snd-aoa-i2sbus-objs := i2sbus-core.o i2sbus-pcm.o i2sbus-control.o diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-control.c b/sound/aoa/soundbus/i2sbus/i2sbus-control.c new file mode 100644 index 000000000..87beb4ad4 --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/i2sbus-control.c @@ -0,0 +1,193 @@ +/* + * i2sbus driver -- bus control routines + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + */ + +#include <linux/kernel.h> +#include <linux/delay.h> + +#include <asm/io.h> +#include <asm/prom.h> +#include <asm/macio.h> +#include <asm/pmac_feature.h> +#include <asm/pmac_pfunc.h> +#include <asm/keylargo.h> + +#include "i2sbus.h" + +int i2sbus_control_init(struct macio_dev* dev, struct i2sbus_control **c) +{ + *c = kzalloc(sizeof(struct i2sbus_control), GFP_KERNEL); + if (!*c) + return -ENOMEM; + + INIT_LIST_HEAD(&(*c)->list); + + (*c)->macio = dev->bus->chip; + return 0; +} + +void i2sbus_control_destroy(struct i2sbus_control *c) +{ + kfree(c); +} + +/* this is serialised externally */ +int i2sbus_control_add_dev(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev) +{ + struct device_node *np; + + np = i2sdev->sound.ofdev.node; + i2sdev->enable = pmf_find_function(np, "enable"); + i2sdev->cell_enable = pmf_find_function(np, "cell-enable"); + i2sdev->clock_enable = pmf_find_function(np, "clock-enable"); + i2sdev->cell_disable = pmf_find_function(np, "cell-disable"); + i2sdev->clock_disable = pmf_find_function(np, "clock-disable"); + + /* if the bus number is not 0 or 1 we absolutely need to use + * the platform functions -- there's nothing in Darwin that + * would allow seeing a system behind what the FCRs are then, + * and I don't want to go parsing a bunch of platform functions + * by hand to try finding a system... */ + if (i2sdev->bus_number != 0 && i2sdev->bus_number != 1 && + (!i2sdev->enable || + !i2sdev->cell_enable || !i2sdev->clock_enable || + !i2sdev->cell_disable || !i2sdev->clock_disable)) { + pmf_put_function(i2sdev->enable); + pmf_put_function(i2sdev->cell_enable); + pmf_put_function(i2sdev->clock_enable); + pmf_put_function(i2sdev->cell_disable); + pmf_put_function(i2sdev->clock_disable); + return -ENODEV; + } + + list_add(&i2sdev->item, &c->list); + + return 0; +} + +void i2sbus_control_remove_dev(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev) +{ + /* this is serialised externally */ + list_del(&i2sdev->item); + if (list_empty(&c->list)) + i2sbus_control_destroy(c); +} + +int i2sbus_control_enable(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev) +{ + struct pmf_args args = { .count = 0 }; + struct macio_chip *macio = c->macio; + + if (i2sdev->enable) + return pmf_call_one(i2sdev->enable, &args); + + if (macio == NULL || macio->base == NULL) + return -ENODEV; + + switch (i2sdev->bus_number) { + case 0: + /* these need to be locked or done through + * newly created feature calls! */ + MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_ENABLE); + break; + case 1: + MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_ENABLE); + break; + default: + return -ENODEV; + } + return 0; +} + +int i2sbus_control_cell(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev, + int enable) +{ + struct pmf_args args = { .count = 0 }; + struct macio_chip *macio = c->macio; + + switch (enable) { + case 0: + if (i2sdev->cell_disable) + return pmf_call_one(i2sdev->cell_disable, &args); + break; + case 1: + if (i2sdev->cell_enable) + return pmf_call_one(i2sdev->cell_enable, &args); + break; + default: + printk(KERN_ERR "i2sbus: INVALID CELL ENABLE VALUE\n"); + return -ENODEV; + } + + if (macio == NULL || macio->base == NULL) + return -ENODEV; + + switch (i2sdev->bus_number) { + case 0: + if (enable) + MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE); + else + MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE); + break; + case 1: + if (enable) + MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE); + else + MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CELL_ENABLE); + break; + default: + return -ENODEV; + } + return 0; +} + +int i2sbus_control_clock(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev, + int enable) +{ + struct pmf_args args = { .count = 0 }; + struct macio_chip *macio = c->macio; + + switch (enable) { + case 0: + if (i2sdev->clock_disable) + return pmf_call_one(i2sdev->clock_disable, &args); + break; + case 1: + if (i2sdev->clock_enable) + return pmf_call_one(i2sdev->clock_enable, &args); + break; + default: + printk(KERN_ERR "i2sbus: INVALID CLOCK ENABLE VALUE\n"); + return -ENODEV; + } + + if (macio == NULL || macio->base == NULL) + return -ENODEV; + + switch (i2sdev->bus_number) { + case 0: + if (enable) + MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT); + else + MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT); + break; + case 1: + if (enable) + MACIO_BIS(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT); + else + MACIO_BIC(KEYLARGO_FCR1, KL1_I2S1_CLK_ENABLE_BIT); + break; + default: + return -ENODEV; + } + return 0; +} diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-core.c b/sound/aoa/soundbus/i2sbus/i2sbus-core.c new file mode 100644 index 000000000..23190aa6b --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/i2sbus-core.c @@ -0,0 +1,455 @@ +/* + * i2sbus driver + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + */ + +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/interrupt.h> +#include <linux/dma-mapping.h> + +#include <sound/driver.h> +#include <sound/core.h> + +#include <asm/macio.h> +#include <asm/dbdma.h> + +#include "../soundbus.h" +#include "i2sbus.h" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); +MODULE_DESCRIPTION("Apple Soundbus: I2S support"); +/* for auto-loading, declare that we handle this weird + * string that macio puts into the relevant device */ +MODULE_ALIAS("of:Ni2sTi2sC"); + +static int force; +module_param(force, int, 0444); +MODULE_PARM_DESC(force, "Force loading i2sbus even when" + " no layout-id property is present"); + +static struct of_device_id i2sbus_match[] = { + { .name = "i2s" }, + { } +}; + +static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev, + struct dbdma_command_mem *r, + int numcmds) +{ + /* one more for rounding */ + r->size = (numcmds+1) * sizeof(struct dbdma_cmd); + /* We use the PCI APIs for now until the generic one gets fixed + * enough or until we get some macio-specific versions + */ + r->space = dma_alloc_coherent( + &macio_get_pci_dev(i2sdev->macio)->dev, + r->size, + &r->bus_addr, + GFP_KERNEL); + + if (!r->space) return -ENOMEM; + + memset(r->space, 0, r->size); + r->cmds = (void*)DBDMA_ALIGN(r->space); + r->bus_cmd_start = r->bus_addr + + (dma_addr_t)((char*)r->cmds - (char*)r->space); + + return 0; +} + +static void free_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev, + struct dbdma_command_mem *r) +{ + if (!r->space) return; + + dma_free_coherent(&macio_get_pci_dev(i2sdev->macio)->dev, + r->size, r->space, r->bus_addr); +} + +static void i2sbus_release_dev(struct device *dev) +{ + struct i2sbus_dev *i2sdev; + int i; + + i2sdev = container_of(dev, struct i2sbus_dev, sound.ofdev.dev); + + if (i2sdev->intfregs) iounmap(i2sdev->intfregs); + if (i2sdev->out.dbdma) iounmap(i2sdev->out.dbdma); + if (i2sdev->in.dbdma) iounmap(i2sdev->in.dbdma); + for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) + if (i2sdev->allocated_resource[i]) + release_and_free_resource(i2sdev->allocated_resource[i]); + free_dbdma_descriptor_ring(i2sdev, &i2sdev->out.dbdma_ring); + free_dbdma_descriptor_ring(i2sdev, &i2sdev->in.dbdma_ring); + for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) + free_irq(i2sdev->interrupts[i], i2sdev); + i2sbus_control_remove_dev(i2sdev->control, i2sdev); + mutex_destroy(&i2sdev->lock); + kfree(i2sdev); +} + +static irqreturn_t i2sbus_bus_intr(int irq, void *devid, struct pt_regs *regs) +{ + struct i2sbus_dev *dev = devid; + u32 intreg; + + spin_lock(&dev->low_lock); + intreg = in_le32(&dev->intfregs->intr_ctl); + + /* acknowledge interrupt reasons */ + out_le32(&dev->intfregs->intr_ctl, intreg); + + spin_unlock(&dev->low_lock); + + return IRQ_HANDLED; +} + + +/* + * XXX FIXME: We test the layout_id's here to get the proper way of + * mapping in various registers, thanks to bugs in Apple device-trees. + * We could instead key off the machine model and the name of the i2s + * node (i2s-a). This we'll do when we move it all to macio_asic.c + * and have that export items for each sub-node too. + */ +static int i2sbus_get_and_fixup_rsrc(struct device_node *np, int index, + int layout, struct resource *res) +{ + struct device_node *parent; + int pindex, rc = -ENXIO; + u32 *reg; + + /* Machines with layout 76 and 36 (K2 based) have a weird device + * tree what we need to special case. + * Normal machines just fetch the resource from the i2s-X node. + * Darwin further divides normal machines into old and new layouts + * with a subtely different code path but that doesn't seem necessary + * in practice, they just bloated it. In addition, even on our K2 + * case the i2s-modem node, if we ever want to handle it, uses the + * normal layout + */ + if (layout != 76 && layout != 36) + return of_address_to_resource(np, index, res); + + parent = of_get_parent(np); + pindex = (index == aoa_resource_i2smmio) ? 0 : 1; + rc = of_address_to_resource(parent, pindex, res); + if (rc) + goto bail; + reg = (u32 *)get_property(np, "reg", NULL); + if (reg == NULL) { + rc = -ENXIO; + goto bail; + } + res->start += reg[index * 2]; + res->end = res->start + reg[index * 2 + 1] - 1; + bail: + of_node_put(parent); + return rc; +} + +/* FIXME: look at device node refcounting */ +static int i2sbus_add_dev(struct macio_dev *macio, + struct i2sbus_control *control, + struct device_node *np) +{ + struct i2sbus_dev *dev; + struct device_node *child = NULL, *sound = NULL; + struct resource *r; + int i, layout = 0, rlen; + static const char *rnames[] = { "i2sbus: %s (control)", + "i2sbus: %s (tx)", + "i2sbus: %s (rx)" }; + static irqreturn_t (*ints[])(int irq, void *devid, + struct pt_regs *regs) = { + i2sbus_bus_intr, + i2sbus_tx_intr, + i2sbus_rx_intr + }; + + if (strlen(np->name) != 5) + return 0; + if (strncmp(np->name, "i2s-", 4)) + return 0; + + dev = kzalloc(sizeof(struct i2sbus_dev), GFP_KERNEL); + if (!dev) + return 0; + + i = 0; + while ((child = of_get_next_child(np, child))) { + if (strcmp(child->name, "sound") == 0) { + i++; + sound = child; + } + } + if (i == 1) { + u32 *layout_id; + layout_id = (u32*) get_property(sound, "layout-id", NULL); + if (layout_id) { + layout = *layout_id; + snprintf(dev->sound.modalias, 32, + "sound-layout-%d", layout); + force = 1; + } + } + /* for the time being, until we can handle non-layout-id + * things in some fabric, refuse to attach if there is no + * layout-id property or we haven't been forced to attach. + * When there are two i2s busses and only one has a layout-id, + * then this depends on the order, but that isn't important + * either as the second one in that case is just a modem. */ + if (!force) { + kfree(dev); + return -ENODEV; + } + + mutex_init(&dev->lock); + spin_lock_init(&dev->low_lock); + dev->sound.ofdev.node = np; + dev->sound.ofdev.dma_mask = macio->ofdev.dma_mask; + dev->sound.ofdev.dev.dma_mask = &dev->sound.ofdev.dma_mask; + dev->sound.ofdev.dev.parent = &macio->ofdev.dev; + dev->sound.ofdev.dev.release = i2sbus_release_dev; + dev->sound.attach_codec = i2sbus_attach_codec; + dev->sound.detach_codec = i2sbus_detach_codec; + dev->sound.pcmid = -1; + dev->macio = macio; + dev->control = control; + dev->bus_number = np->name[4] - 'a'; + INIT_LIST_HEAD(&dev->sound.codec_list); + + for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) { + dev->interrupts[i] = -1; + snprintf(dev->rnames[i], sizeof(dev->rnames[i]), + rnames[i], np->name); + } + for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) { + int irq = irq_of_parse_and_map(np, i); + if (request_irq(irq, ints[i], 0, dev->rnames[i], dev)) + goto err; + dev->interrupts[i] = irq; + } + + + /* Resource handling is problematic as some device-trees contain + * useless crap (ugh ugh ugh). We work around that here by calling + * specific functions for calculating the appropriate resources. + * + * This will all be moved to macio_asic.c at one point + */ + for (i = aoa_resource_i2smmio; i <= aoa_resource_rxdbdma; i++) { + if (i2sbus_get_and_fixup_rsrc(np,i,layout,&dev->resources[i])) + goto err; + /* If only we could use our resource dev->resources[i]... + * but request_resource doesn't know about parents and + * contained resources... + */ + dev->allocated_resource[i] = + request_mem_region(dev->resources[i].start, + dev->resources[i].end - + dev->resources[i].start + 1, + dev->rnames[i]); + if (!dev->allocated_resource[i]) { + printk(KERN_ERR "i2sbus: failed to claim resource %d!\n", i); + goto err; + } + } + + r = &dev->resources[aoa_resource_i2smmio]; + rlen = r->end - r->start + 1; + if (rlen < sizeof(struct i2s_interface_regs)) + goto err; + dev->intfregs = ioremap(r->start, rlen); + + r = &dev->resources[aoa_resource_txdbdma]; + rlen = r->end - r->start + 1; + if (rlen < sizeof(struct dbdma_regs)) + goto err; + dev->out.dbdma = ioremap(r->start, rlen); + + r = &dev->resources[aoa_resource_rxdbdma]; + rlen = r->end - r->start + 1; + if (rlen < sizeof(struct dbdma_regs)) + goto err; + dev->in.dbdma = ioremap(r->start, rlen); + + if (!dev->intfregs || !dev->out.dbdma || !dev->in.dbdma) + goto err; + + if (alloc_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring, + MAX_DBDMA_COMMANDS)) + goto err; + if (alloc_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring, + MAX_DBDMA_COMMANDS)) + goto err; + + if (i2sbus_control_add_dev(dev->control, dev)) { + printk(KERN_ERR "i2sbus: control layer didn't like bus\n"); + goto err; + } + + if (soundbus_add_one(&dev->sound)) { + printk(KERN_DEBUG "i2sbus: device registration error!\n"); + goto err; + } + + /* enable this cell */ + i2sbus_control_cell(dev->control, dev, 1); + i2sbus_control_enable(dev->control, dev); + i2sbus_control_clock(dev->control, dev, 1); + + return 1; + err: + for (i=0;i<3;i++) + if (dev->interrupts[i] != -1) + free_irq(dev->interrupts[i], dev); + free_dbdma_descriptor_ring(dev, &dev->out.dbdma_ring); + free_dbdma_descriptor_ring(dev, &dev->in.dbdma_ring); + if (dev->intfregs) iounmap(dev->intfregs); + if (dev->out.dbdma) iounmap(dev->out.dbdma); + if (dev->in.dbdma) iounmap(dev->in.dbdma); + for (i=0;i<3;i++) + if (dev->allocated_resource[i]) + release_and_free_resource(dev->allocated_resource[i]); + mutex_destroy(&dev->lock); + kfree(dev); + return 0; +} + +static int i2sbus_probe(struct macio_dev* dev, const struct of_device_id *match) +{ + struct device_node *np = NULL; + int got = 0, err; + struct i2sbus_control *control = NULL; + + err = i2sbus_control_init(dev, &control); + if (err) + return err; + if (!control) { + printk(KERN_ERR "i2sbus_control_init API breakage\n"); + return -ENODEV; + } + + while ((np = of_get_next_child(dev->ofdev.node, np))) { + if (device_is_compatible(np, "i2sbus") || + device_is_compatible(np, "i2s-modem")) { + got += i2sbus_add_dev(dev, control, np); + } + } + + if (!got) { + /* found none, clean up */ + i2sbus_control_destroy(control); + return -ENODEV; + } + + dev->ofdev.dev.driver_data = control; + + return 0; +} + +static int i2sbus_remove(struct macio_dev* dev) +{ + struct i2sbus_control *control = dev->ofdev.dev.driver_data; + struct i2sbus_dev *i2sdev, *tmp; + + list_for_each_entry_safe(i2sdev, tmp, &control->list, item) + soundbus_remove_one(&i2sdev->sound); + + return 0; +} + +#ifdef CONFIG_PM +static int i2sbus_suspend(struct macio_dev* dev, pm_message_t state) +{ + struct i2sbus_control *control = dev->ofdev.dev.driver_data; + struct codec_info_item *cii; + struct i2sbus_dev* i2sdev; + int err, ret = 0; + + list_for_each_entry(i2sdev, &control->list, item) { + /* Notify Alsa */ + if (i2sdev->sound.pcm) { + /* Suspend PCM streams */ + snd_pcm_suspend_all(i2sdev->sound.pcm); + /* Probably useless as we handle + * power transitions ourselves */ + snd_power_change_state(i2sdev->sound.pcm->card, + SNDRV_CTL_POWER_D3hot); + } + /* Notify codecs */ + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { + err = 0; + if (cii->codec->suspend) + err = cii->codec->suspend(cii, state); + if (err) + ret = err; + } + } + return ret; +} + +static int i2sbus_resume(struct macio_dev* dev) +{ + struct i2sbus_control *control = dev->ofdev.dev.driver_data; + struct codec_info_item *cii; + struct i2sbus_dev* i2sdev; + int err, ret = 0; + + list_for_each_entry(i2sdev, &control->list, item) { + /* Notify codecs so they can re-initialize */ + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { + err = 0; + if (cii->codec->resume) + err = cii->codec->resume(cii); + if (err) + ret = err; + } + /* Notify Alsa */ + if (i2sdev->sound.pcm) { + /* Same comment as above, probably useless */ + snd_power_change_state(i2sdev->sound.pcm->card, + SNDRV_CTL_POWER_D0); + } + } + + return ret; +} +#endif /* CONFIG_PM */ + +static int i2sbus_shutdown(struct macio_dev* dev) +{ + return 0; +} + +static struct macio_driver i2sbus_drv = { + .name = "soundbus-i2s", + .owner = THIS_MODULE, + .match_table = i2sbus_match, + .probe = i2sbus_probe, + .remove = i2sbus_remove, +#ifdef CONFIG_PM + .suspend = i2sbus_suspend, + .resume = i2sbus_resume, +#endif + .shutdown = i2sbus_shutdown, +}; + +static int __init soundbus_i2sbus_init(void) +{ + return macio_register_driver(&i2sbus_drv); +} + +static void __exit soundbus_i2sbus_exit(void) +{ + macio_unregister_driver(&i2sbus_drv); +} + +module_init(soundbus_i2sbus_init); +module_exit(soundbus_i2sbus_exit); diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-interface.h b/sound/aoa/soundbus/i2sbus/i2sbus-interface.h new file mode 100644 index 000000000..c6b5f5452 --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/i2sbus-interface.h @@ -0,0 +1,187 @@ +/* + * i2sbus driver -- interface register definitions + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + */ +#ifndef __I2SBUS_INTERFACE_H +#define __I2SBUS_INTERFACE_H + +/* i2s bus control registers, at least what we know about them */ + +#define __PAD(m,n) u8 __pad##m[n] +#define _PAD(line, n) __PAD(line, n) +#define PAD(n) _PAD(__LINE__, (n)) +struct i2s_interface_regs { + __le32 intr_ctl; /* 0x00 */ + PAD(12); + __le32 serial_format; /* 0x10 */ + PAD(12); + __le32 codec_msg_out; /* 0x20 */ + PAD(12); + __le32 codec_msg_in; /* 0x30 */ + PAD(12); + __le32 frame_count; /* 0x40 */ + PAD(12); + __le32 frame_match; /* 0x50 */ + PAD(12); + __le32 data_word_sizes; /* 0x60 */ + PAD(12); + __le32 peak_level_sel; /* 0x70 */ + PAD(12); + __le32 peak_level_in0; /* 0x80 */ + PAD(12); + __le32 peak_level_in1; /* 0x90 */ + PAD(12); + /* total size: 0x100 bytes */ +} __attribute__((__packed__)); + +/* interrupt register is just a bitfield with + * interrupt enable and pending bits */ +#define I2S_REG_INTR_CTL 0x00 +# define I2S_INT_FRAME_COUNT (1<<31) +# define I2S_PENDING_FRAME_COUNT (1<<30) +# define I2S_INT_MESSAGE_FLAG (1<<29) +# define I2S_PENDING_MESSAGE_FLAG (1<<28) +# define I2S_INT_NEW_PEAK (1<<27) +# define I2S_PENDING_NEW_PEAK (1<<26) +# define I2S_INT_CLOCKS_STOPPED (1<<25) +# define I2S_PENDING_CLOCKS_STOPPED (1<<24) +# define I2S_INT_EXTERNAL_SYNC_ERROR (1<<23) +# define I2S_PENDING_EXTERNAL_SYNC_ERROR (1<<22) +# define I2S_INT_EXTERNAL_SYNC_OK (1<<21) +# define I2S_PENDING_EXTERNAL_SYNC_OK (1<<20) +# define I2S_INT_NEW_SAMPLE_RATE (1<<19) +# define I2S_PENDING_NEW_SAMPLE_RATE (1<<18) +# define I2S_INT_STATUS_FLAG (1<<17) +# define I2S_PENDING_STATUS_FLAG (1<<16) + +/* serial format register is more interesting :) + * It contains: + * - clock source + * - MClk divisor + * - SClk divisor + * - SClk master flag + * - serial format (sony, i2s 64x, i2s 32x, dav, silabs) + * - external sample frequency interrupt (don't understand) + * - external sample frequency + */ +#define I2S_REG_SERIAL_FORMAT 0x10 +/* clock source. You get either 18.432, 45.1584 or 49.1520 MHz */ +# define I2S_SF_CLOCK_SOURCE_SHIFT 30 +# define I2S_SF_CLOCK_SOURCE_MASK (3<<I2S_SF_CLOCK_SOURCE_SHIFT) +# define I2S_SF_CLOCK_SOURCE_18MHz (0<<I2S_SF_CLOCK_SOURCE_SHIFT) +# define I2S_SF_CLOCK_SOURCE_45MHz (1<<I2S_SF_CLOCK_SOURCE_SHIFT) +# define I2S_SF_CLOCK_SOURCE_49MHz (2<<I2S_SF_CLOCK_SOURCE_SHIFT) +/* also, let's define the exact clock speeds here, in Hz */ +#define I2S_CLOCK_SPEED_18MHz 18432000 +#define I2S_CLOCK_SPEED_45MHz 45158400 +#define I2S_CLOCK_SPEED_49MHz 49152000 +/* MClk is the clock that drives the codec, usually called its 'system clock'. + * It is derived by taking only every 'divisor' tick of the clock. + */ +# define I2S_SF_MCLKDIV_SHIFT 24 +# define I2S_SF_MCLKDIV_MASK (0x1F<<I2S_SF_MCLKDIV_SHIFT) +# define I2S_SF_MCLKDIV_1 (0x14<<I2S_SF_MCLKDIV_SHIFT) +# define I2S_SF_MCLKDIV_3 (0x13<<I2S_SF_MCLKDIV_SHIFT) +# define I2S_SF_MCLKDIV_5 (0x12<<I2S_SF_MCLKDIV_SHIFT) +# define I2S_SF_MCLKDIV_14 (0x0E<<I2S_SF_MCLKDIV_SHIFT) +# define I2S_SF_MCLKDIV_OTHER(div) (((div/2-1)<<I2S_SF_MCLKDIV_SHIFT)&I2S_SF_MCLKDIV_MASK) +static inline int i2s_sf_mclkdiv(int div, int *out) +{ + int d; + + switch(div) { + case 1: *out |= I2S_SF_MCLKDIV_1; return 0; + case 3: *out |= I2S_SF_MCLKDIV_3; return 0; + case 5: *out |= I2S_SF_MCLKDIV_5; return 0; + case 14: *out |= I2S_SF_MCLKDIV_14; return 0; + default: + if (div%2) return -1; + d = div/2-1; + if (d == 0x14 || d == 0x13 || d == 0x12 || d == 0x0E) + return -1; + *out |= I2S_SF_MCLKDIV_OTHER(div); + return 0; + } +} +/* SClk is the clock that drives the i2s wire bus. Note that it is + * derived from the MClk above by taking only every 'divisor' tick + * of MClk. + */ +# define I2S_SF_SCLKDIV_SHIFT 20 +# define I2S_SF_SCLKDIV_MASK (0xF<<I2S_SF_SCLKDIV_SHIFT) +# define I2S_SF_SCLKDIV_1 (8<<I2S_SF_SCLKDIV_SHIFT) +# define I2S_SF_SCLKDIV_3 (9<<I2S_SF_SCLKDIV_SHIFT) +# define I2S_SF_SCLKDIV_OTHER(div) (((div/2-1)<<I2S_SF_SCLKDIV_SHIFT)&I2S_SF_SCLKDIV_MASK) +static inline int i2s_sf_sclkdiv(int div, int *out) +{ + int d; + + switch(div) { + case 1: *out |= I2S_SF_SCLKDIV_1; return 0; + case 3: *out |= I2S_SF_SCLKDIV_3; return 0; + default: + if (div%2) return -1; + d = div/2-1; + if (d == 8 || d == 9) return -1; + *out |= I2S_SF_SCLKDIV_OTHER(div); + return 0; + } +} +# define I2S_SF_SCLK_MASTER (1<<19) +/* serial format is the way the data is put to the i2s wire bus */ +# define I2S_SF_SERIAL_FORMAT_SHIFT 16 +# define I2S_SF_SERIAL_FORMAT_MASK (7<<I2S_SF_SERIAL_FORMAT_SHIFT) +# define I2S_SF_SERIAL_FORMAT_SONY (0<<I2S_SF_SERIAL_FORMAT_SHIFT) +# define I2S_SF_SERIAL_FORMAT_I2S_64X (1<<I2S_SF_SERIAL_FORMAT_SHIFT) +# define I2S_SF_SERIAL_FORMAT_I2S_32X (2<<I2S_SF_SERIAL_FORMAT_SHIFT) +# define I2S_SF_SERIAL_FORMAT_I2S_DAV (4<<I2S_SF_SERIAL_FORMAT_SHIFT) +# define I2S_SF_SERIAL_FORMAT_I2S_SILABS (5<<I2S_SF_SERIAL_FORMAT_SHIFT) +/* unknown */ +# define I2S_SF_EXT_SAMPLE_FREQ_INT_SHIFT 12 +# define I2S_SF_EXT_SAMPLE_FREQ_INT_MASK (0xF<<I2S_SF_SAMPLE_FREQ_INT_SHIFT) +/* probably gives external frequency? */ +# define I2S_SF_EXT_SAMPLE_FREQ_MASK 0xFFF + +/* used to send codec messages, but how isn't clear */ +#define I2S_REG_CODEC_MSG_OUT 0x20 + +/* used to receive codec messages, but how isn't clear */ +#define I2S_REG_CODEC_MSG_IN 0x30 + +/* frame count reg isn't clear to me yet, but probably useful */ +#define I2S_REG_FRAME_COUNT 0x40 + +/* program to some value, and get interrupt if frame count reaches it */ +#define I2S_REG_FRAME_MATCH 0x50 + +/* this register describes how the bus transfers data */ +#define I2S_REG_DATA_WORD_SIZES 0x60 +/* number of interleaved input channels */ +# define I2S_DWS_NUM_CHANNELS_IN_SHIFT 24 +# define I2S_DWS_NUM_CHANNELS_IN_MASK (0x1F<<I2S_DWS_NUM_CHANNELS_IN_SHIFT) +/* word size of input data */ +# define I2S_DWS_DATA_IN_SIZE_SHIFT 16 +# define I2S_DWS_DATA_IN_16BIT (0<<I2S_DWS_DATA_IN_SIZE_SHIFT) +# define I2S_DWS_DATA_IN_24BIT (3<<I2S_DWS_DATA_IN_SIZE_SHIFT) +/* number of interleaved output channels */ +# define I2S_DWS_NUM_CHANNELS_OUT_SHIFT 8 +# define I2S_DWS_NUM_CHANNELS_OUT_MASK (0x1F<<I2S_DWS_NUM_CHANNELS_OUT_SHIFT) +/* word size of output data */ +# define I2S_DWS_DATA_OUT_SIZE_SHIFT 0 +# define I2S_DWS_DATA_OUT_16BIT (0<<I2S_DWS_DATA_OUT_SIZE_SHIFT) +# define I2S_DWS_DATA_OUT_24BIT (3<<I2S_DWS_DATA_OUT_SIZE_SHIFT) + + +/* unknown */ +#define I2S_REG_PEAK_LEVEL_SEL 0x70 + +/* unknown */ +#define I2S_REG_PEAK_LEVEL_IN0 0x80 + +/* unknown */ +#define I2S_REG_PEAK_LEVEL_IN1 0x90 + +#endif /* __I2SBUS_INTERFACE_H */ diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c new file mode 100644 index 000000000..3049015a0 --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c @@ -0,0 +1,1021 @@ +/* + * i2sbus driver -- pcm routines + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + */ + +#include <asm/io.h> +#include <linux/delay.h> +/* So apparently there's a reason for requiring driver.h + * to be included first, even if I don't know it... */ +#include <sound/driver.h> +#include <sound/core.h> +#include <asm/macio.h> +#include <linux/pci.h> +#include "../soundbus.h" +#include "i2sbus.h" + +static inline void get_pcm_info(struct i2sbus_dev *i2sdev, int in, + struct pcm_info **pi, struct pcm_info **other) +{ + if (in) { + if (pi) + *pi = &i2sdev->in; + if (other) + *other = &i2sdev->out; + } else { + if (pi) + *pi = &i2sdev->out; + if (other) + *other = &i2sdev->in; + } +} + +static int clock_and_divisors(int mclk, int sclk, int rate, int *out) +{ + /* sclk must be derived from mclk! */ + if (mclk % sclk) + return -1; + /* derive sclk register value */ + if (i2s_sf_sclkdiv(mclk / sclk, out)) + return -1; + + if (I2S_CLOCK_SPEED_18MHz % (rate * mclk) == 0) { + if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_18MHz / (rate * mclk), out)) { + *out |= I2S_SF_CLOCK_SOURCE_18MHz; + return 0; + } + } + if (I2S_CLOCK_SPEED_45MHz % (rate * mclk) == 0) { + if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_45MHz / (rate * mclk), out)) { + *out |= I2S_SF_CLOCK_SOURCE_45MHz; + return 0; + } + } + if (I2S_CLOCK_SPEED_49MHz % (rate * mclk) == 0) { + if (!i2s_sf_mclkdiv(I2S_CLOCK_SPEED_49MHz / (rate * mclk), out)) { + *out |= I2S_SF_CLOCK_SOURCE_49MHz; + return 0; + } + } + return -1; +} + +#define CHECK_RATE(rate) \ + do { if (rates & SNDRV_PCM_RATE_ ##rate) { \ + int dummy; \ + if (clock_and_divisors(sysclock_factor, \ + bus_factor, rate, &dummy)) \ + rates &= ~SNDRV_PCM_RATE_ ##rate; \ + } } while (0) + +static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in) +{ + struct pcm_info *pi, *other; + struct soundbus_dev *sdev; + int masks_inited = 0, err; + struct codec_info_item *cii, *rev; + struct snd_pcm_hardware *hw; + u64 formats = 0; + unsigned int rates = 0; + struct transfer_info v; + int result = 0; + int bus_factor = 0, sysclock_factor = 0; + int found_this; + + mutex_lock(&i2sdev->lock); + + get_pcm_info(i2sdev, in, &pi, &other); + + hw = &pi->substream->runtime->hw; + sdev = &i2sdev->sound; + + if (pi->active) { + /* alsa messed up */ + result = -EBUSY; + goto out_unlock; + } + + /* we now need to assign the hw */ + list_for_each_entry(cii, &sdev->codec_list, list) { + struct transfer_info *ti = cii->codec->transfers; + bus_factor = cii->codec->bus_factor; + sysclock_factor = cii->codec->sysclock_factor; + while (ti->formats && ti->rates) { + v = *ti; + if (ti->transfer_in == in + && cii->codec->usable(cii, ti, &v)) { + if (masks_inited) { + formats &= v.formats; + rates &= v.rates; + } else { + formats = v.formats; + rates = v.rates; + masks_inited = 1; + } + } + ti++; + } + } + if (!masks_inited || !bus_factor || !sysclock_factor) { + result = -ENODEV; + goto out_unlock; + } + /* bus dependent stuff */ + hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME; + + CHECK_RATE(5512); + CHECK_RATE(8000); + CHECK_RATE(11025); + CHECK_RATE(16000); + CHECK_RATE(22050); + CHECK_RATE(32000); + CHECK_RATE(44100); + CHECK_RATE(48000); + CHECK_RATE(64000); + CHECK_RATE(88200); + CHECK_RATE(96000); + CHECK_RATE(176400); + CHECK_RATE(192000); + hw->rates = rates; + + /* well. the codec might want 24 bits only, and we'll + * ever only transfer 24 bits, but they are top-aligned! + * So for alsa, we claim that we're doing full 32 bit + * while in reality we'll ignore the lower 8 bits of + * that when doing playback (they're transferred as 0 + * as far as I know, no codecs we have are 32-bit capable + * so I can't really test) and when doing recording we'll + * always have those lower 8 bits recorded as 0 */ + if (formats & SNDRV_PCM_FMTBIT_S24_BE) + formats |= SNDRV_PCM_FMTBIT_S32_BE; + if (formats & SNDRV_PCM_FMTBIT_U24_BE) + formats |= SNDRV_PCM_FMTBIT_U32_BE; + /* now mask off what we can support. I suppose we could + * also support S24_3LE and some similar formats, but I + * doubt there's a codec that would be able to use that, + * so we don't support it here. */ + hw->formats = formats & (SNDRV_PCM_FMTBIT_S16_BE | + SNDRV_PCM_FMTBIT_U16_BE | + SNDRV_PCM_FMTBIT_S32_BE | + SNDRV_PCM_FMTBIT_U32_BE); + + /* we need to set the highest and lowest rate possible. + * These are the highest and lowest rates alsa can + * support properly in its bitfield. + * Below, we'll use that to restrict to the rate + * currently in use (if any). */ + hw->rate_min = 5512; + hw->rate_max = 192000; + /* if the other stream is active, then we can only + * support what it is currently using. + * FIXME: I lied. This comment is wrong. We can support + * anything that works with the same serial format, ie. + * when recording 24 bit sound we can well play 16 bit + * sound at the same time iff using the same transfer mode. + */ + if (other->active) { + /* FIXME: is this guaranteed by the alsa api? */ + hw->formats &= (1ULL << i2sdev->format); + /* see above, restrict rates to the one we already have */ + hw->rate_min = i2sdev->rate; + hw->rate_max = i2sdev->rate; + } + + hw->channels_min = 2; + hw->channels_max = 2; + /* these are somewhat arbitrary */ + hw->buffer_bytes_max = 131072; + hw->period_bytes_min = 256; + hw->period_bytes_max = 16384; + hw->periods_min = 3; + hw->periods_max = MAX_DBDMA_COMMANDS; + list_for_each_entry(cii, &sdev->codec_list, list) { + if (cii->codec->open) { + err = cii->codec->open(cii, pi->substream); + if (err) { + result = err; + /* unwind */ + found_this = 0; + list_for_each_entry_reverse(rev, + &sdev->codec_list, list) { + if (found_this && rev->codec->close) { + rev->codec->close(rev, + pi->substream); + } + if (rev == cii) + found_this = 1; + } + goto out_unlock; + } + } + } + + out_unlock: + mutex_unlock(&i2sdev->lock); + return result; +} + +#undef CHECK_RATE + +static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in) +{ + struct codec_info_item *cii; + struct pcm_info *pi; + int err = 0, tmp; + + mutex_lock(&i2sdev->lock); + + get_pcm_info(i2sdev, in, &pi, NULL); + + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { + if (cii->codec->close) { + tmp = cii->codec->close(cii, pi->substream); + if (tmp) + err = tmp; + } + } + + pi->substream = NULL; + pi->active = 0; + mutex_unlock(&i2sdev->lock); + return err; +} + +static int i2sbus_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); +} + +static int i2sbus_hw_free(struct snd_pcm_substream *substream) +{ + snd_pcm_lib_free_pages(substream); + return 0; +} + +static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) +{ + /* whee. Hard work now. The user has selected a bitrate + * and bit format, so now we have to program our + * I2S controller appropriately. */ + struct snd_pcm_runtime *runtime; + struct dbdma_cmd *command; + int i, periodsize; + dma_addr_t offset; + struct bus_info bi; + struct codec_info_item *cii; + int sfr = 0; /* serial format register */ + int dws = 0; /* data word sizes reg */ + int input_16bit; + struct pcm_info *pi, *other; + int cnt; + int result = 0; + + mutex_lock(&i2sdev->lock); + + get_pcm_info(i2sdev, in, &pi, &other); + + if (pi->dbdma_ring.running) { + result = -EBUSY; + goto out_unlock; + } + + runtime = pi->substream->runtime; + pi->active = 1; + if (other->active && + ((i2sdev->format != runtime->format) + || (i2sdev->rate != runtime->rate))) { + result = -EINVAL; + goto out_unlock; + } + + i2sdev->format = runtime->format; + i2sdev->rate = runtime->rate; + + periodsize = snd_pcm_lib_period_bytes(pi->substream); + pi->current_period = 0; + + /* generate dbdma command ring first */ + command = pi->dbdma_ring.cmds; + offset = runtime->dma_addr; + for (i = 0; i < pi->substream->runtime->periods; + i++, command++, offset += periodsize) { + memset(command, 0, sizeof(struct dbdma_cmd)); + command->command = + cpu_to_le16((in ? INPUT_MORE : OUTPUT_MORE) | INTR_ALWAYS); + command->phy_addr = cpu_to_le32(offset); + command->req_count = cpu_to_le16(periodsize); + command->xfer_status = cpu_to_le16(0); + } + /* last one branches back to first */ + command--; + command->command |= cpu_to_le16(BR_ALWAYS); + command->cmd_dep = cpu_to_le32(pi->dbdma_ring.bus_cmd_start); + + /* ok, let's set the serial format and stuff */ + switch (runtime->format) { + /* 16 bit formats */ + case SNDRV_PCM_FORMAT_S16_BE: + case SNDRV_PCM_FORMAT_U16_BE: + /* FIXME: if we add different bus factors we need to + * do more here!! */ + bi.bus_factor = 0; + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { + bi.bus_factor = cii->codec->bus_factor; + break; + } + if (!bi.bus_factor) { + result = -ENODEV; + goto out_unlock; + } + input_16bit = 1; + break; + case SNDRV_PCM_FORMAT_S32_BE: + case SNDRV_PCM_FORMAT_U32_BE: + /* force 64x bus speed, otherwise the data cannot be + * transferred quickly enough! */ + bi.bus_factor = 64; + input_16bit = 0; + break; + default: + result = -EINVAL; + goto out_unlock; + } + /* we assume all sysclocks are the same! */ + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { + bi.sysclock_factor = cii->codec->sysclock_factor; + break; + } + + if (clock_and_divisors(bi.sysclock_factor, + bi.bus_factor, + runtime->rate, + &sfr) < 0) { + result = -EINVAL; + goto out_unlock; + } + switch (bi.bus_factor) { + case 32: + sfr |= I2S_SF_SERIAL_FORMAT_I2S_32X; + break; + case 64: + sfr |= I2S_SF_SERIAL_FORMAT_I2S_64X; + break; + } + /* FIXME: THIS ASSUMES MASTER ALL THE TIME */ + sfr |= I2S_SF_SCLK_MASTER; + + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { + int err = 0; + if (cii->codec->prepare) + err = cii->codec->prepare(cii, &bi, pi->substream); + if (err) { + result = err; + goto out_unlock; + } + } + /* codecs are fine with it, so set our clocks */ + if (input_16bit) + dws = (2 << I2S_DWS_NUM_CHANNELS_IN_SHIFT) | + (2 << I2S_DWS_NUM_CHANNELS_OUT_SHIFT) | + I2S_DWS_DATA_IN_16BIT | I2S_DWS_DATA_OUT_16BIT; + else + dws = (2 << I2S_DWS_NUM_CHANNELS_IN_SHIFT) | + (2 << I2S_DWS_NUM_CHANNELS_OUT_SHIFT) | + I2S_DWS_DATA_IN_24BIT | I2S_DWS_DATA_OUT_24BIT; + + /* early exit if already programmed correctly */ + /* not locking these is fine since we touch them only in this function */ + if (in_le32(&i2sdev->intfregs->serial_format) == sfr + && in_le32(&i2sdev->intfregs->data_word_sizes) == dws) + goto out_unlock; + + /* let's notify the codecs about clocks going away. + * For now we only do mastering on the i2s cell... */ + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) + if (cii->codec->switch_clock) + cii->codec->switch_clock(cii, CLOCK_SWITCH_PREPARE_SLAVE); + + i2sbus_control_enable(i2sdev->control, i2sdev); + i2sbus_control_cell(i2sdev->control, i2sdev, 1); + + out_le32(&i2sdev->intfregs->intr_ctl, I2S_PENDING_CLOCKS_STOPPED); + + i2sbus_control_clock(i2sdev->control, i2sdev, 0); + + msleep(1); + + /* wait for clock stopped. This can apparently take a while... */ + cnt = 100; + while (cnt-- && + !(in_le32(&i2sdev->intfregs->intr_ctl) & I2S_PENDING_CLOCKS_STOPPED)) { + msleep(5); + } + out_le32(&i2sdev->intfregs->intr_ctl, I2S_PENDING_CLOCKS_STOPPED); + + /* not locking these is fine since we touch them only in this function */ + out_le32(&i2sdev->intfregs->serial_format, sfr); + out_le32(&i2sdev->intfregs->data_word_sizes, dws); + + i2sbus_control_enable(i2sdev->control, i2sdev); + i2sbus_control_cell(i2sdev->control, i2sdev, 1); + i2sbus_control_clock(i2sdev->control, i2sdev, 1); + msleep(1); + + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) + if (cii->codec->switch_clock) + cii->codec->switch_clock(cii, CLOCK_SWITCH_SLAVE); + + out_unlock: + mutex_unlock(&i2sdev->lock); + return result; +} + +static struct dbdma_cmd STOP_CMD = { + .command = __constant_cpu_to_le16(DBDMA_STOP), +}; + +static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd) +{ + struct codec_info_item *cii; + struct pcm_info *pi; + int timeout; + struct dbdma_cmd tmp; + int result = 0; + unsigned long flags; + + spin_lock_irqsave(&i2sdev->low_lock, flags); + + get_pcm_info(i2sdev, in, &pi, NULL); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + if (pi->dbdma_ring.running) { + result = -EALREADY; + goto out_unlock; + } + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) + if (cii->codec->start) + cii->codec->start(cii, pi->substream); + pi->dbdma_ring.running = 1; + + /* reset dma engine */ + out_le32(&pi->dbdma->control, + 0 | (RUN | PAUSE | FLUSH | WAKE) << 16); + timeout = 100; + while (in_le32(&pi->dbdma->status) & RUN && timeout--) + udelay(1); + if (timeout <= 0) { + printk(KERN_ERR + "i2sbus: error waiting for dma reset\n"); + result = -ENXIO; + goto out_unlock; + } + + /* write dma command buffer address to the dbdma chip */ + out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start); + /* post PCI write */ + mb(); + (void)in_le32(&pi->dbdma->status); + + /* change first command to STOP */ + tmp = *pi->dbdma_ring.cmds; + *pi->dbdma_ring.cmds = STOP_CMD; + + /* set running state, remember that the first command is STOP */ + out_le32(&pi->dbdma->control, RUN | (RUN << 16)); + timeout = 100; + /* wait for STOP to be executed */ + while (in_le32(&pi->dbdma->status) & ACTIVE && timeout--) + udelay(1); + if (timeout <= 0) { + printk(KERN_ERR "i2sbus: error waiting for dma stop\n"); + result = -ENXIO; + goto out_unlock; + } + /* again, write dma command buffer address to the dbdma chip, + * this time of the first real command */ + *pi->dbdma_ring.cmds = tmp; + out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start); + /* post write */ + mb(); + (void)in_le32(&pi->dbdma->status); + + /* reset dma engine again */ + out_le32(&pi->dbdma->control, + 0 | (RUN | PAUSE | FLUSH | WAKE) << 16); + timeout = 100; + while (in_le32(&pi->dbdma->status) & RUN && timeout--) + udelay(1); + if (timeout <= 0) { + printk(KERN_ERR + "i2sbus: error waiting for dma reset\n"); + result = -ENXIO; + goto out_unlock; + } + + /* wake up the chip with the next descriptor */ + out_le32(&pi->dbdma->control, + (RUN | WAKE) | ((RUN | WAKE) << 16)); + /* get the frame count */ + pi->frame_count = in_le32(&i2sdev->intfregs->frame_count); + + /* off you go! */ + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + if (!pi->dbdma_ring.running) { + result = -EALREADY; + goto out_unlock; + } + + /* turn off all relevant bits */ + out_le32(&pi->dbdma->control, + (RUN | WAKE | FLUSH | PAUSE) << 16); + { + /* FIXME: move to own function */ + int timeout = 5000; + while ((in_le32(&pi->dbdma->status) & RUN) + && --timeout > 0) + udelay(1); + if (!timeout) + printk(KERN_ERR + "i2sbus: timed out turning " + "off dbdma engine!\n"); + } + + pi->dbdma_ring.running = 0; + list_for_each_entry(cii, &i2sdev->sound.codec_list, list) + if (cii->codec->stop) + cii->codec->stop(cii, pi->substream); + break; + default: + result = -EINVAL; + goto out_unlock; + } + + out_unlock: + spin_unlock_irqrestore(&i2sdev->low_lock, flags); + return result; +} + +static snd_pcm_uframes_t i2sbus_pcm_pointer(struct i2sbus_dev *i2sdev, int in) +{ + struct pcm_info *pi; + u32 fc; + + get_pcm_info(i2sdev, in, &pi, NULL); + + fc = in_le32(&i2sdev->intfregs->frame_count); + fc = fc - pi->frame_count; + + return (bytes_to_frames(pi->substream->runtime, + pi->current_period * + snd_pcm_lib_period_bytes(pi->substream)) + + fc) % pi->substream->runtime->buffer_size; +} + +static inline void handle_interrupt(struct i2sbus_dev *i2sdev, int in) +{ + struct pcm_info *pi; + u32 fc; + u32 delta; + + spin_lock(&i2sdev->low_lock); + get_pcm_info(i2sdev, in, &pi, NULL); + + if (!pi->dbdma_ring.running) { + /* there was still an interrupt pending + * while we stopped. or maybe another + * processor (not the one that was stopping + * the DMA engine) was spinning above + * waiting for the lock. */ + goto out_unlock; + } + + fc = in_le32(&i2sdev->intfregs->frame_count); + /* a counter overflow does not change the calculation. */ + delta = fc - pi->frame_count; + + /* update current_period */ + while (delta >= pi->substream->runtime->period_size) { + pi->current_period++; + delta = delta - pi->substream->runtime->period_size; + } + + if (unlikely(delta)) { + /* Some interrupt came late, so check the dbdma. + * This special case exists to syncronize the frame_count with + * the dbdma transfer, but is hit every once in a while. */ + int period; + + period = (in_le32(&pi->dbdma->cmdptr) + - pi->dbdma_ring.bus_cmd_start) + / sizeof(struct dbdma_cmd); + pi->current_period = pi->current_period + % pi->substream->runtime->periods; + + while (pi->current_period != period) { + pi->current_period++; + pi->current_period %= pi->substream->runtime->periods; + /* Set delta to zero, as the frame_count value is too + * high (otherwise the code path will not be executed). + * This corrects the fact that the frame_count is too + * low at the beginning due to buffering. */ + delta = 0; + } + } + + pi->frame_count = fc - delta; + pi->current_period %= pi->substream->runtime->periods; + + spin_unlock(&i2sdev->low_lock); + /* may call _trigger again, hence needs to be unlocked */ + snd_pcm_period_elapsed(pi->substream); + return; + out_unlock: + spin_unlock(&i2sdev->low_lock); +} + +irqreturn_t i2sbus_tx_intr(int irq, void *devid, struct pt_regs *regs) +{ + handle_interrupt((struct i2sbus_dev *)devid, 0); + return IRQ_HANDLED; +} + +irqreturn_t i2sbus_rx_intr(int irq, void *devid, struct pt_regs * regs) +{ + handle_interrupt((struct i2sbus_dev *)devid, 1); + return IRQ_HANDLED; +} + +static int i2sbus_playback_open(struct snd_pcm_substream *substream) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + + if (!i2sdev) + return -EINVAL; + i2sdev->out.substream = substream; + return i2sbus_pcm_open(i2sdev, 0); +} + +static int i2sbus_playback_close(struct snd_pcm_substream *substream) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + int err; + + if (!i2sdev) + return -EINVAL; + if (i2sdev->out.substream != substream) + return -EINVAL; + err = i2sbus_pcm_close(i2sdev, 0); + if (!err) + i2sdev->out.substream = NULL; + return err; +} + +static int i2sbus_playback_prepare(struct snd_pcm_substream *substream) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + + if (!i2sdev) + return -EINVAL; + if (i2sdev->out.substream != substream) + return -EINVAL; + return i2sbus_pcm_prepare(i2sdev, 0); +} + +static int i2sbus_playback_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + + if (!i2sdev) + return -EINVAL; + if (i2sdev->out.substream != substream) + return -EINVAL; + return i2sbus_pcm_trigger(i2sdev, 0, cmd); +} + +static snd_pcm_uframes_t i2sbus_playback_pointer(struct snd_pcm_substream + *substream) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + + if (!i2sdev) + return -EINVAL; + if (i2sdev->out.substream != substream) + return 0; + return i2sbus_pcm_pointer(i2sdev, 0); +} + +static struct snd_pcm_ops i2sbus_playback_ops = { + .open = i2sbus_playback_open, + .close = i2sbus_playback_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = i2sbus_hw_params, + .hw_free = i2sbus_hw_free, + .prepare = i2sbus_playback_prepare, + .trigger = i2sbus_playback_trigger, + .pointer = i2sbus_playback_pointer, +}; + +static int i2sbus_record_open(struct snd_pcm_substream *substream) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + + if (!i2sdev) + return -EINVAL; + i2sdev->in.substream = substream; + return i2sbus_pcm_open(i2sdev, 1); +} + +static int i2sbus_record_close(struct snd_pcm_substream *substream) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + int err; + + if (!i2sdev) + return -EINVAL; + if (i2sdev->in.substream != substream) + return -EINVAL; + err = i2sbus_pcm_close(i2sdev, 1); + if (!err) + i2sdev->in.substream = NULL; + return err; +} + +static int i2sbus_record_prepare(struct snd_pcm_substream *substream) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + + if (!i2sdev) + return -EINVAL; + if (i2sdev->in.substream != substream) + return -EINVAL; + return i2sbus_pcm_prepare(i2sdev, 1); +} + +static int i2sbus_record_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + + if (!i2sdev) + return -EINVAL; + if (i2sdev->in.substream != substream) + return -EINVAL; + return i2sbus_pcm_trigger(i2sdev, 1, cmd); +} + +static snd_pcm_uframes_t i2sbus_record_pointer(struct snd_pcm_substream + *substream) +{ + struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream); + + if (!i2sdev) + return -EINVAL; + if (i2sdev->in.substream != substream) + return 0; + return i2sbus_pcm_pointer(i2sdev, 1); +} + +static struct snd_pcm_ops i2sbus_record_ops = { + .open = i2sbus_record_open, + .close = i2sbus_record_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = i2sbus_hw_params, + .hw_free = i2sbus_hw_free, + .prepare = i2sbus_record_prepare, + .trigger = i2sbus_record_trigger, + .pointer = i2sbus_record_pointer, +}; + +static void i2sbus_private_free(struct snd_pcm *pcm) +{ + struct i2sbus_dev *i2sdev = snd_pcm_chip(pcm); + struct codec_info_item *p, *tmp; + + i2sdev->sound.pcm = NULL; + i2sdev->out.created = 0; + i2sdev->in.created = 0; + list_for_each_entry_safe(p, tmp, &i2sdev->sound.codec_list, list) { + printk(KERN_ERR "i2sbus: a codec didn't unregister!\n"); + list_del(&p->list); + module_put(p->codec->owner); + kfree(p); + } + soundbus_dev_put(&i2sdev->sound); + module_put(THIS_MODULE); +} + +/* FIXME: this function needs an error handling strategy with labels */ +int +i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card, + struct codec_info *ci, void *data) +{ + int err, in = 0, out = 0; + struct transfer_info *tmp; + struct i2sbus_dev *i2sdev = soundbus_dev_to_i2sbus_dev(dev); + struct codec_info_item *cii; + + if (!dev->pcmname || dev->pcmid == -1) { + printk(KERN_ERR "i2sbus: pcm name and id must be set!\n"); + return -EINVAL; + } + + list_for_each_entry(cii, &dev->codec_list, list) { + if (cii->codec_data == data) + return -EALREADY; + } + + if (!ci->transfers || !ci->transfers->formats + || !ci->transfers->rates || !ci->usable) + return -EINVAL; + + /* we currently code the i2s transfer on the clock, and support only + * 32 and 64 */ + if (ci->bus_factor != 32 && ci->bus_factor != 64) + return -EINVAL; + + /* If you want to fix this, you need to keep track of what transport infos + * are to be used, which codecs they belong to, and then fix all the + * sysclock/busclock stuff above to depend on which is usable */ + list_for_each_entry(cii, &dev->codec_list, list) { + if (cii->codec->sysclock_factor != ci->sysclock_factor) { + printk(KERN_DEBUG + "cannot yet handle multiple different sysclocks!\n"); + return -EINVAL; + } + if (cii->codec->bus_factor != ci->bus_factor) { + printk(KERN_DEBUG + "cannot yet handle multiple different bus clocks!\n"); + return -EINVAL; + } + } + + tmp = ci->transfers; + while (tmp->formats && tmp->rates) { + if (tmp->transfer_in) + in = 1; + else + out = 1; + tmp++; + } + + cii = kzalloc(sizeof(struct codec_info_item), GFP_KERNEL); + if (!cii) { + printk(KERN_DEBUG "i2sbus: failed to allocate cii\n"); + return -ENOMEM; + } + + /* use the private data to point to the codec info */ + cii->sdev = soundbus_dev_get(dev); + cii->codec = ci; + cii->codec_data = data; + + if (!cii->sdev) { + printk(KERN_DEBUG + "i2sbus: failed to get soundbus dev reference\n"); + kfree(cii); + return -ENODEV; + } + + if (!try_module_get(THIS_MODULE)) { + printk(KERN_DEBUG "i2sbus: failed to get module reference!\n"); + soundbus_dev_put(dev); + kfree(cii); + return -EBUSY; + } + + if (!try_module_get(ci->owner)) { + printk(KERN_DEBUG + "i2sbus: failed to get module reference to codec owner!\n"); + module_put(THIS_MODULE); + soundbus_dev_put(dev); + kfree(cii); + return -EBUSY; + } + + if (!dev->pcm) { + err = snd_pcm_new(card, + dev->pcmname, + dev->pcmid, + 0, + 0, + &dev->pcm); + if (err) { + printk(KERN_DEBUG "i2sbus: failed to create pcm\n"); + kfree(cii); + module_put(ci->owner); + soundbus_dev_put(dev); + module_put(THIS_MODULE); + return err; + } + } + + /* ALSA yet again sucks. + * If it is ever fixed, remove this line. See below. */ + out = in = 1; + + if (!i2sdev->out.created && out) { + if (dev->pcm->card != card) { + /* eh? */ + printk(KERN_ERR + "Can't attach same bus to different cards!\n"); + module_put(ci->owner); + kfree(cii); + soundbus_dev_put(dev); + module_put(THIS_MODULE); + return -EINVAL; + } + if ((err = + snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, 1))) { + module_put(ci->owner); + kfree(cii); + soundbus_dev_put(dev); + module_put(THIS_MODULE); + return err; + } + snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, + &i2sbus_playback_ops); + i2sdev->out.created = 1; + } + + if (!i2sdev->in.created && in) { + if (dev->pcm->card != card) { + printk(KERN_ERR + "Can't attach same bus to different cards!\n"); + module_put(ci->owner); + kfree(cii); + soundbus_dev_put(dev); + module_put(THIS_MODULE); + return -EINVAL; + } + if ((err = + snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, 1))) { + module_put(ci->owner); + kfree(cii); + soundbus_dev_put(dev); + module_put(THIS_MODULE); + return err; + } + snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, + &i2sbus_record_ops); + i2sdev->in.created = 1; + } + + /* so we have to register the pcm after adding any substream + * to it because alsa doesn't create the devices for the + * substreams when we add them later. + * Therefore, force in and out on both busses (above) and + * register the pcm now instead of just after creating it. + */ + err = snd_device_register(card, dev->pcm); + if (err) { + printk(KERN_ERR "i2sbus: error registering new pcm\n"); + module_put(ci->owner); + kfree(cii); + soundbus_dev_put(dev); + module_put(THIS_MODULE); + return err; + } + /* no errors any more, so let's add this to our list */ + list_add(&cii->list, &dev->codec_list); + + dev->pcm->private_data = i2sdev; + dev->pcm->private_free = i2sbus_private_free; + + /* well, we really should support scatter/gather DMA */ + snd_pcm_lib_preallocate_pages_for_all( + dev->pcm, SNDRV_DMA_TYPE_DEV, + snd_dma_pci_data(macio_get_pci_dev(i2sdev->macio)), + 64 * 1024, 64 * 1024); + + return 0; +} + +void i2sbus_detach_codec(struct soundbus_dev *dev, void *data) +{ + struct codec_info_item *cii = NULL, *i; + + list_for_each_entry(i, &dev->codec_list, list) { + if (i->codec_data == data) { + cii = i; + break; + } + } + if (cii) { + list_del(&cii->list); + module_put(cii->codec->owner); + kfree(cii); + } + /* no more codecs, but still a pcm? */ + if (list_empty(&dev->codec_list) && dev->pcm) { + /* the actual cleanup is done by the callback above! */ + snd_device_free(dev->pcm->card, dev->pcm); + } +} diff --git a/sound/aoa/soundbus/i2sbus/i2sbus.h b/sound/aoa/soundbus/i2sbus/i2sbus.h new file mode 100644 index 000000000..0c69d209b --- /dev/null +++ b/sound/aoa/soundbus/i2sbus/i2sbus.h @@ -0,0 +1,120 @@ +/* + * i2sbus driver -- private definitions + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + */ +#ifndef __I2SBUS_H +#define __I2SBUS_H +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/mutex.h> + +#include <sound/pcm.h> + +#include <asm/prom.h> +#include <asm/pmac_feature.h> +#include <asm/dbdma.h> + +#include "i2sbus-interface.h" +#include "../soundbus.h" + +struct i2sbus_control { + struct list_head list; + struct macio_chip *macio; +}; + +#define MAX_DBDMA_COMMANDS 32 + +struct dbdma_command_mem { + dma_addr_t bus_addr; + dma_addr_t bus_cmd_start; + struct dbdma_cmd *cmds; + void *space; + int size; + u32 running:1; +}; + +struct pcm_info { + u32 created:1, /* has this direction been created with alsa? */ + active:1; /* is this stream active? */ + /* runtime information */ + struct snd_pcm_substream *substream; + int current_period; + u32 frame_count; + struct dbdma_command_mem dbdma_ring; + volatile struct dbdma_regs __iomem *dbdma; +}; + +enum { + aoa_resource_i2smmio = 0, + aoa_resource_txdbdma, + aoa_resource_rxdbdma, +}; + +struct i2sbus_dev { + struct soundbus_dev sound; + struct macio_dev *macio; + struct i2sbus_control *control; + volatile struct i2s_interface_regs __iomem *intfregs; + + struct resource resources[3]; + struct resource *allocated_resource[3]; + int interrupts[3]; + char rnames[3][32]; + + /* info about currently active substreams */ + struct pcm_info out, in; + snd_pcm_format_t format; + unsigned int rate; + + /* list for a single controller */ + struct list_head item; + /* number of bus on controller */ + int bus_number; + /* for use by control layer */ + struct pmf_function *enable, + *cell_enable, + *cell_disable, + *clock_enable, + *clock_disable; + + /* locks */ + /* spinlock for low-level interrupt locking */ + spinlock_t low_lock; + /* mutex for high-level consistency */ + struct mutex lock; +}; + +#define soundbus_dev_to_i2sbus_dev(sdev) \ + container_of(sdev, struct i2sbus_dev, sound) + +/* pcm specific functions */ +extern int +i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card, + struct codec_info *ci, void *data); +extern void +i2sbus_detach_codec(struct soundbus_dev *dev, void *data); +extern irqreturn_t +i2sbus_tx_intr(int irq, void *devid, struct pt_regs *regs); +extern irqreturn_t +i2sbus_rx_intr(int irq, void *devid, struct pt_regs *regs); + +/* control specific functions */ +extern int i2sbus_control_init(struct macio_dev* dev, + struct i2sbus_control **c); +extern void i2sbus_control_destroy(struct i2sbus_control *c); +extern int i2sbus_control_add_dev(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev); +extern void i2sbus_control_remove_dev(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev); +extern int i2sbus_control_enable(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev); +extern int i2sbus_control_cell(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev, + int enable); +extern int i2sbus_control_clock(struct i2sbus_control *c, + struct i2sbus_dev *i2sdev, + int enable); +#endif /* __I2SBUS_H */ diff --git a/sound/aoa/soundbus/soundbus.h b/sound/aoa/soundbus/soundbus.h new file mode 100644 index 000000000..5c2729783 --- /dev/null +++ b/sound/aoa/soundbus/soundbus.h @@ -0,0 +1,202 @@ +/* + * soundbus generic definitions + * + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * GPL v2, can be found in COPYING. + */ +#ifndef __SOUNDBUS_H +#define __SOUNDBUS_H + +#include <asm/of_device.h> +#include <sound/pcm.h> +#include <linux/list.h> + + +/* When switching from master to slave or the other way around, + * you don't want to have the codec chip acting as clock source + * while the bus still is. + * More importantly, while switch from slave to master, you need + * to turn off the chip's master function first, but then there's + * no clock for a while and other chips might reset, so we notify + * their drivers after having switched. + * The constants here are codec-point of view, so when we switch + * the soundbus to master we tell the codec we're going to switch + * and give it CLOCK_SWITCH_PREPARE_SLAVE! + */ +enum clock_switch { + CLOCK_SWITCH_PREPARE_SLAVE, + CLOCK_SWITCH_PREPARE_MASTER, + CLOCK_SWITCH_SLAVE, + CLOCK_SWITCH_MASTER, + CLOCK_SWITCH_NOTIFY, +}; + +/* information on a transfer the codec can take */ +struct transfer_info { + u64 formats; /* SNDRV_PCM_FMTBIT_* */ + unsigned int rates; /* SNDRV_PCM_RATE_* */ + /* flags */ + u32 transfer_in:1, /* input = 1, output = 0 */ + must_be_clock_source:1; + /* for codecs to distinguish among their TIs */ + int tag; +}; + +struct codec_info_item { + struct codec_info *codec; + void *codec_data; + struct soundbus_dev *sdev; + /* internal, to be used by the soundbus provider */ + struct list_head list; +}; + +/* for prepare, where the codecs need to know + * what we're going to drive the bus with */ +struct bus_info { + /* see below */ + int sysclock_factor; + int bus_factor; +}; + +/* information on the codec itself, plus function pointers */ +struct codec_info { + /* the module this lives in */ + struct module *owner; + + /* supported transfer possibilities, array terminated by + * formats or rates being 0. */ + struct transfer_info *transfers; + + /* Master clock speed factor + * to be used (master clock speed = sysclock_factor * sampling freq) + * Unused if the soundbus provider has no such notion. + */ + int sysclock_factor; + + /* Bus factor, bus clock speed = bus_factor * sampling freq) + * Unused if the soundbus provider has no such notion. + */ + int bus_factor; + + /* operations */ + /* clock switching, see above */ + int (*switch_clock)(struct codec_info_item *cii, + enum clock_switch clock); + + /* called for each transfer_info when the user + * opens the pcm device to determine what the + * hardware can support at this point in time. + * That can depend on other user-switchable controls. + * Return 1 if usable, 0 if not. + * out points to another instance of a transfer_info + * which is initialised to the values in *ti, and + * it's format and rate values can be modified by + * the callback if it is necessary to further restrict + * the formats that can be used at the moment, for + * example when one codec has multiple logical codec + * info structs for multiple inputs. + */ + int (*usable)(struct codec_info_item *cii, + struct transfer_info *ti, + struct transfer_info *out); + + /* called when pcm stream is opened, probably not implemented + * most of the time since it isn't too useful */ + int (*open)(struct codec_info_item *cii, + struct snd_pcm_substream *substream); + + /* called when the pcm stream is closed, at this point + * the user choices can all be unlocked (see below) */ + int (*close)(struct codec_info_item *cii, + struct snd_pcm_substream *substream); + + /* if the codec must forbid some user choices because + * they are not valid with the substream/transfer info, + * it must do so here. Example: no digital output for + * incompatible framerate, say 8KHz, on Onyx. + * If the selected stuff in the substream is NOT + * compatible, you have to reject this call! */ + int (*prepare)(struct codec_info_item *cii, + struct bus_info *bi, + struct snd_pcm_substream *substream); + + /* start() is called before data is pushed to the codec. + * Note that start() must be atomic! */ + int (*start)(struct codec_info_item *cii, + struct snd_pcm_substream *substream); + + /* stop() is called after data is no longer pushed to the codec. + * Note that stop() must be atomic! */ + int (*stop)(struct codec_info_item *cii, + struct snd_pcm_substream *substream); + + int (*suspend)(struct codec_info_item *cii, pm_message_t state); + int (*resume)(struct codec_info_item *cii); +}; + +/* information on a soundbus device */ +struct soundbus_dev { + /* the bus it belongs to */ + struct list_head onbuslist; + + /* the of device it represents */ + struct of_device ofdev; + + /* what modules go by */ + char modalias[32]; + + /* These fields must be before attach_codec can be called. + * They should be set by the owner of the alsa card object + * that is needed, and whoever sets them must make sure + * that they are unique within that alsa card object. */ + char *pcmname; + int pcmid; + + /* this is assigned by the soundbus provider in attach_codec */ + struct snd_pcm *pcm; + + /* operations */ + /* attach a codec to this soundbus, give the alsa + * card object the PCMs for this soundbus should be in. + * The 'data' pointer must be unique, it is used as the + * key for detach_codec(). */ + int (*attach_codec)(struct soundbus_dev *dev, struct snd_card *card, + struct codec_info *ci, void *data); + void (*detach_codec)(struct soundbus_dev *dev, void *data); + /* TODO: suspend/resume */ + + /* private for the soundbus provider */ + struct list_head codec_list; + u32 have_out:1, have_in:1; +}; +#define to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev.dev) +#define of_to_soundbus_device(d) container_of(d, struct soundbus_dev, ofdev) + +extern int soundbus_add_one(struct soundbus_dev *dev); +extern void soundbus_remove_one(struct soundbus_dev *dev); + +extern struct soundbus_dev *soundbus_dev_get(struct soundbus_dev *dev); +extern void soundbus_dev_put(struct soundbus_dev *dev); + +struct soundbus_driver { + char *name; + struct module *owner; + + /* we don't implement any matching at all */ + + int (*probe)(struct soundbus_dev* dev); + int (*remove)(struct soundbus_dev* dev); + + int (*suspend)(struct soundbus_dev* dev, pm_message_t state); + int (*resume)(struct soundbus_dev* dev); + int (*shutdown)(struct soundbus_dev* dev); + + struct device_driver driver; +}; +#define to_soundbus_driver(drv) container_of(drv,struct soundbus_driver, driver) + +extern int soundbus_register_driver(struct soundbus_driver *drv); +extern void soundbus_unregister_driver(struct soundbus_driver *drv); + +#endif /* __SOUNDBUS_H */ diff --git a/sound/aoa/soundbus/sysfs.c b/sound/aoa/soundbus/sysfs.c new file mode 100644 index 000000000..f580942b5 --- /dev/null +++ b/sound/aoa/soundbus/sysfs.c @@ -0,0 +1,42 @@ +#include <linux/kernel.h> +#include <linux/stat.h> +/* FIX UP */ +#include "soundbus.h" + +#define soundbus_config_of_attr(field, format_string) \ +static ssize_t \ +field##_show (struct device *dev, struct device_attribute *attr, \ + char *buf) \ +{ \ + struct soundbus_dev *mdev = to_soundbus_device (dev); \ + return sprintf (buf, format_string, mdev->ofdev.node->field); \ +} + +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct soundbus_dev *sdev = to_soundbus_device(dev); + struct of_device *of = &sdev->ofdev; + int length; + + if (*sdev->modalias) { + strlcpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1); + strcat(buf, "\n"); + length = strlen(buf); + } else { + length = sprintf(buf, "of:N%sT%s\n", + of->node->name, of->node->type); + } + + return length; +} + +soundbus_config_of_attr (name, "%s\n"); +soundbus_config_of_attr (type, "%s\n"); + +struct device_attribute soundbus_dev_attrs[] = { + __ATTR_RO(name), + __ATTR_RO(type), + __ATTR_RO(modalias), + __ATTR_NULL +}; diff --git a/sound/pci/cs5535audio/cs5535audio_pm.c b/sound/pci/cs5535audio/cs5535audio_pm.c new file mode 100644 index 000000000..aad0e69db --- /dev/null +++ b/sound/pci/cs5535audio/cs5535audio_pm.c @@ -0,0 +1,123 @@ +/* + * Power management for audio on multifunction CS5535 companion device + * Copyright (C) Jaya Kumar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/pci.h> +#include <linux/delay.h> +#include <sound/driver.h> +#include <sound/core.h> +#include <sound/control.h> +#include <sound/initval.h> +#include <sound/asoundef.h> +#include <sound/pcm.h> +#include <sound/ac97_codec.h> +#include "cs5535audio.h" + +static void snd_cs5535audio_stop_hardware(struct cs5535audio *cs5535au) +{ + /* + we depend on snd_ac97_suspend to tell the + AC97 codec to shutdown. the amd spec suggests + that the LNK_SHUTDOWN be done at the same time + that the codec power-down is issued. instead, + we do it just after rather than at the same + time. excluding codec specific build_ops->suspend + ac97 powerdown hits: + 0x8000 EAPD + 0x4000 Headphone amplifier + 0x0300 ADC & DAC + 0x0400 Analog Mixer powerdown (Vref on) + I am not sure if this is the best that we can do. + The remainder to be investigated are: + - analog mixer (vref off) 0x0800 + - AC-link powerdown 0x1000 + - codec internal clock 0x2000 + */ + + /* set LNK_SHUTDOWN to shutdown AC link */ + cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_SHUTDOWN); + +} + +int snd_cs5535audio_suspend(struct pci_dev *pci, pm_message_t state) +{ + struct snd_card *card = pci_get_drvdata(pci); + struct cs5535audio *cs5535au = card->private_data; + int i; + + snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) { + struct cs5535audio_dma *dma = &cs5535au->dmas[i]; + if (dma && dma->substream && !dma->suspended) + dma->saved_prd = dma->ops->read_prd(cs5535au); + } + snd_pcm_suspend_all(cs5535au->pcm); + snd_ac97_suspend(cs5535au->ac97); + /* save important regs, then disable aclink in hw */ + snd_cs5535audio_stop_hardware(cs5535au); + pci_disable_device(pci); + pci_save_state(pci); + + return 0; +} + +int snd_cs5535audio_resume(struct pci_dev *pci) +{ + struct snd_card *card = pci_get_drvdata(pci); + struct cs5535audio *cs5535au = card->private_data; + u32 tmp; + int timeout; + int i; + + pci_restore_state(pci); + pci_enable_device(pci); + pci_set_master(pci); + + /* set LNK_WRM_RST to reset AC link */ + cs_writel(cs5535au, ACC_CODEC_CNTL, ACC_CODEC_CNTL_LNK_WRM_RST); + + timeout = 50; + do { + tmp = cs_readl(cs5535au, ACC_CODEC_STATUS); + if (tmp & PRM_RDY_STS) + break; + udelay(1); + } while (--timeout); + + if (!timeout) + snd_printk(KERN_ERR "Failure getting AC Link ready\n"); + + /* we depend on ac97 to perform the codec power up */ + snd_ac97_resume(cs5535au->ac97); + /* set up rate regs, dma. actual initiation is done in trig */ + for (i = 0; i < NUM_CS5535AUDIO_DMAS; i++) { + struct cs5535audio_dma *dma = &cs5535au->dmas[i]; + if (dma && dma->substream && dma->suspended) { + dma->substream->ops->prepare(dma->substream); + dma->ops->setup_prd(cs5535au, dma->saved_prd); + } + } + + snd_power_change_state(card, SNDRV_CTL_POWER_D0); + + return 0; +} + diff --git a/sound/pci/echoaudio/Makefile b/sound/pci/echoaudio/Makefile new file mode 100644 index 000000000..7b576aeb3 --- /dev/null +++ b/sound/pci/echoaudio/Makefile @@ -0,0 +1,30 @@ +# +# Makefile for ALSA Echoaudio soundcard drivers +# Copyright (c) 2003 by Giuliano Pochini <pochini@shiny.it> +# + +snd-darla20-objs := darla20.o +snd-gina20-objs := gina20.o +snd-layla20-objs := layla20.o +snd-darla24-objs := darla24.o +snd-gina24-objs := gina24.o +snd-layla24-objs := layla24.o +snd-mona-objs := mona.o +snd-mia-objs := mia.o +snd-echo3g-objs := echo3g.o +snd-indigo-objs := indigo.o +snd-indigoio-objs := indigoio.o +snd-indigodj-objs := indigodj.o + +obj-$(CONFIG_SND_DARLA20) += snd-darla20.o +obj-$(CONFIG_SND_GINA20) += snd-gina20.o +obj-$(CONFIG_SND_LAYLA20) += snd-layla20.o +obj-$(CONFIG_SND_DARLA24) += snd-darla24.o +obj-$(CONFIG_SND_GINA24) += snd-gina24.o +obj-$(CONFIG_SND_LAYLA24) += snd-layla24.o +obj-$(CONFIG_SND_MONA) += snd-mona.o +obj-$(CONFIG_SND_MIA) += snd-mia.o +obj-$(CONFIG_SND_ECHO3G) += snd-echo3g.o +obj-$(CONFIG_SND_INDIGO) += snd-indigo.o +obj-$(CONFIG_SND_INDIGOIO) += snd-indigoio.o +obj-$(CONFIG_SND_INDIGODJ) += snd-indigodj.o diff --git a/sound/pci/echoaudio/darla20.c b/sound/pci/echoaudio/darla20.c new file mode 100644 index 000000000..b7108e29a --- /dev/null +++ b/sound/pci/echoaudio/darla20.c @@ -0,0 +1,99 @@ +/* + * ALSA driver for Echoaudio soundcards. + * Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it> + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define ECHOGALS_FAMILY +#define ECHOCARD_DARLA20 +#define ECHOCARD_NAME "Darla20" +#define ECHOCARD_HAS_MONITOR + +/* Pipe indexes */ +#define PX_ANALOG_OUT 0 /* 8 */ +#define PX_DIGITAL_OUT 8 /* 0 */ +#define PX_ANALOG_IN 8 /* 2 */ +#define PX_DIGITAL_IN 10 /* 0 */ +#define PX_NUM 10 + +/* Bus indexes */ +#define BX_ANALOG_OUT 0 /* 8 */ +#define BX_DIGITAL_OUT 8 /* 0 */ +#define BX_ANALOG_IN 8 /* 2 */ +#define BX_DIGITAL_IN 10 /* 0 */ +#define BX_NUM 10 + + +#include <sound/driver.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/slab.h> +#include <linux/moduleparam.h> +#include <linux/firmware.h> +#include <sound/core.h> +#include <sound/info.h> +#include <sound/control.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/asoundef.h> +#include <sound/initval.h> +#include <asm/io.h> +#include <asm/atomic.h> +#include "echoaudio.h" + +#define FW_DARLA20_DSP 0 + +static const struct firmware card_fw[] = { + {0, "darla20_dsp.fw"} +}; + +static struct pci_device_id snd_echo_ids[] = { + {0x1057, 0x1801, 0xECC0, 0x0010, 0, 0, 0}, /* DSP 56301 Darla20 rev.0 */ + {0,} +}; + +static struct snd_pcm_hardware pcm_hardware_skel = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S32_BE, + .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, + .rate_min = 44100, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + .buffer_bytes_max = 262144, + .period_bytes_min = 32, + .period_bytes_max = 131072, + .periods_min = 2, + .periods_max = 220, + /* One page (4k) contains 512 instructions. I don't know if the hw + supports lists longer than this. In this case periods_max=220 is a + safe limit to make sure the list never exceeds 512 instructions. */ +}; + + +#include "darla20_dsp.c" +#include "echoaudio_dsp.c" +#include "echoaudio.c" diff --git a/sound/pci/echoaudio/darla20_dsp.c b/sound/pci/echoaudio/darla20_dsp.c new file mode 100644 index 000000000..4159e3bc1 --- /dev/null +++ b/sound/pci/echoaudio/darla20_dsp.c @@ -0,0 +1,125 @@ +/*************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + ************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + +****************************************************************************/ + + +static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) +{ + int err; + + DE_INIT(("init_hw() - Darla20\n")); + snd_assert((subdevice_id & 0xfff0) == DARLA20, return -ENODEV); + + if ((err = init_dsp_comm_page(chip))) { + DE_INIT(("init_hw - could not initialize DSP comm page\n")); + return err; + } + + chip->device_id = device_id; + chip->subdevice_id = subdevice_id; + chip->bad_board = TRUE; + chip->dsp_code_to_load = &card_fw[FW_DARLA20_DSP]; + chip->spdif_status = GD_SPDIF_STATUS_UNDEF; + chip->clock_state = GD_CLOCK_UNDEF; + /* Since this card has no ASIC, mark it as loaded so everything + works OK */ + chip->asic_loaded = TRUE; + chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; + + if ((err = load_firmware(chip)) < 0) + return err; + chip->bad_board = FALSE; + + if ((err = init_line_levels(chip)) < 0) + return err; + + DE_INIT(("init_hw done\n")); + return err; +} + + + +/* The Darla20 has no external clock sources */ +static u32 detect_input_clocks(const struct echoaudio *chip) +{ + return ECHO_CLOCK_BIT_INTERNAL; +} + + + +/* The Darla20 has no ASIC. Just do nothing */ +static int load_asic(struct echoaudio *chip) +{ + return 0; +} + + + +static int set_sample_rate(struct echoaudio *chip, u32 rate) +{ + u8 clock_state, spdif_status; + + if (wait_handshake(chip)) + return -EIO; + + switch (rate) { + case 44100: + clock_state = GD_CLOCK_44; + spdif_status = GD_SPDIF_STATUS_44; + break; + case 48000: + clock_state = GD_CLOCK_48; + spdif_status = GD_SPDIF_STATUS_48; + break; + default: + clock_state = GD_CLOCK_NOCHANGE; + spdif_status = GD_SPDIF_STATUS_NOCHANGE; + break; + } + + if (chip->clock_state == clock_state) + clock_state = GD_CLOCK_NOCHANGE; + if (spdif_status == chip->spdif_status) + spdif_status = GD_SPDIF_STATUS_NOCHANGE; + + chip->comm_page->sample_rate = cpu_to_le32(rate); + chip->comm_page->gd_clock_state = clock_state; + chip->comm_page->gd_spdif_status = spdif_status; + chip->comm_page->gd_resampler_state = 3; /* magic number - should always be 3 */ + + /* Save the new audio state if it changed */ + if (clock_state != GD_CLOCK_NOCHANGE) + chip->clock_state = clock_state; + if (spdif_status != GD_SPDIF_STATUS_NOCHANGE) + chip->spdif_status = spdif_status; + chip->sample_rate = rate; + + clear_handshake(chip); + return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE); +} diff --git a/sound/pci/echoaudio/darla24.c b/sound/pci/echoaudio/darla24.c new file mode 100644 index 000000000..e59a982ee --- /dev/null +++ b/sound/pci/echoaudio/darla24.c @@ -0,0 +1,106 @@ +/* + * ALSA driver for Echoaudio soundcards. + * Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it> + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define ECHOGALS_FAMILY +#define ECHOCARD_DARLA24 +#define ECHOCARD_NAME "Darla24" +#define ECHOCARD_HAS_MONITOR +#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL +#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL +#define ECHOCARD_HAS_EXTERNAL_CLOCK +#define ECHOCARD_HAS_SUPER_INTERLEAVE + +/* Pipe indexes */ +#define PX_ANALOG_OUT 0 /* 8 */ +#define PX_DIGITAL_OUT 8 /* 0 */ +#define PX_ANALOG_IN 8 /* 2 */ +#define PX_DIGITAL_IN 10 /* 0 */ +#define PX_NUM 10 + +/* Bus indexes */ +#define BX_ANALOG_OUT 0 /* 8 */ +#define BX_DIGITAL_OUT 8 /* 0 */ +#define BX_ANALOG_IN 8 /* 2 */ +#define BX_DIGITAL_IN 10 /* 0 */ +#define BX_NUM 10 + + +#include <sound/driver.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/slab.h> +#include <linux/moduleparam.h> +#include <linux/firmware.h> +#include <sound/core.h> +#include <sound/info.h> +#include <sound/control.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/asoundef.h> +#include <sound/initval.h> +#include <asm/io.h> +#include <asm/atomic.h> +#include "echoaudio.h" + +#define FW_DARLA24_DSP 0 + +static const struct firmware card_fw[] = { + {0, "darla24_dsp.fw"} +}; + +static struct pci_device_id snd_echo_ids[] = { + {0x1057, 0x1801, 0xECC0, 0x0040, 0, 0, 0}, /* DSP 56301 Darla24 rev.0 */ + {0x1057, 0x1801, 0xECC0, 0x0041, 0, 0, 0}, /* DSP 56301 Darla24 rev.1 */ + {0,} +}; + +static struct snd_pcm_hardware pcm_hardware_skel = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S32_BE, + .rates = SNDRV_PCM_RATE_8000_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000, + .rate_min = 8000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + .buffer_bytes_max = 262144, + .period_bytes_min = 32, + .period_bytes_max = 131072, + .periods_min = 2, + .periods_max = 220, + /* One page (4k) contains 512 instructions. I don't know if the hw + supports lists longer than this. In this case periods_max=220 is a + safe limit to make sure the list never exceeds 512 instructions. */ +}; + + +#include "darla24_dsp.c" +#include "echoaudio_dsp.c" +#include "echoaudio.c" diff --git a/sound/pci/echoaudio/darla24_dsp.c b/sound/pci/echoaudio/darla24_dsp.c new file mode 100644 index 000000000..79938eed7 --- /dev/null +++ b/sound/pci/echoaudio/darla24_dsp.c @@ -0,0 +1,156 @@ +/*************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + ************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + +****************************************************************************/ + + +static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) +{ + int err; + + DE_INIT(("init_hw() - Darla24\n")); + snd_assert((subdevice_id & 0xfff0) == DARLA24, return -ENODEV); + + if ((err = init_dsp_comm_page(chip))) { + DE_INIT(("init_hw - could not initialize DSP comm page\n")); + return err; + } + + chip->device_id = device_id; + chip->subdevice_id = subdevice_id; + chip->bad_board = TRUE; + chip->dsp_code_to_load = &card_fw[FW_DARLA24_DSP]; + /* Since this card has no ASIC, mark it as loaded so everything + works OK */ + chip->asic_loaded = TRUE; + chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | + ECHO_CLOCK_BIT_ESYNC; + + if ((err = load_firmware(chip)) < 0) + return err; + chip->bad_board = FALSE; + + if ((err = init_line_levels(chip)) < 0) + return err; + + DE_INIT(("init_hw done\n")); + return err; +} + + + +static u32 detect_input_clocks(const struct echoaudio *chip) +{ + u32 clocks_from_dsp, clock_bits; + + /* Map the DSP clock detect bits to the generic driver clock + detect bits */ + clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); + + clock_bits = ECHO_CLOCK_BIT_INTERNAL; + + if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_ESYNC) + clock_bits |= ECHO_CLOCK_BIT_ESYNC; + + return clock_bits; +} + + + +/* The Darla24 has no ASIC. Just do nothing */ +static int load_asic(struct echoaudio *chip) +{ + return 0; +} + + + +static int set_sample_rate(struct echoaudio *chip, u32 rate) +{ + u8 clock; + + switch (rate) { + case 96000: + clock = GD24_96000; + break; + case 88200: + clock = GD24_88200; + break; + case 48000: + clock = GD24_48000; + break; + case 44100: + clock = GD24_44100; + break; + case 32000: + clock = GD24_32000; + break; + case 22050: + clock = GD24_22050; + break; + case 16000: + clock = GD24_16000; + break; + case 11025: + clock = GD24_11025; + break; + case 8000: + clock = GD24_8000; + break; + default: + DE_ACT(("set_sample_rate: Error, invalid sample rate %d\n", + rate)); + return -EINVAL; + } + + if (wait_handshake(chip)) + return -EIO; + + DE_ACT(("set_sample_rate: %d clock %d\n", rate, clock)); + chip->sample_rate = rate; + + /* Override the sample rate if this card is set to Echo sync. */ + if (chip->input_clock == ECHO_CLOCK_ESYNC) + clock = GD24_EXT_SYNC; + + chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP ? */ + chip->comm_page->gd_clock_state = clock; + clear_handshake(chip); + return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE); +} + + + +static int set_input_clock(struct echoaudio *chip, u16 clock) +{ + snd_assert(clock == ECHO_CLOCK_INTERNAL || + clock == ECHO_CLOCK_ESYNC, return -EINVAL); + chip->input_clock = clock; + return set_sample_rate(chip, chip->sample_rate); +} + diff --git a/sound/pci/echoaudio/echo3g.c b/sound/pci/echoaudio/echo3g.c new file mode 100644 index 000000000..12099fe15 --- /dev/null +++ b/sound/pci/echoaudio/echo3g.c @@ -0,0 +1,118 @@ +/* + * ALSA driver for Echoaudio soundcards. + * Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it> + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define ECHO3G_FAMILY +#define ECHOCARD_ECHO3G +#define ECHOCARD_NAME "Echo3G" +#define ECHOCARD_HAS_MONITOR +#define ECHOCARD_HAS_ASIC +#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL +#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL +#define ECHOCARD_HAS_SUPER_INTERLEAVE +#define ECHOCARD_HAS_DIGITAL_IO +#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH +#define ECHOCARD_HAS_ADAT 6 +#define ECHOCARD_HAS_EXTERNAL_CLOCK +#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 +#define ECHOCARD_HAS_MIDI +#define ECHOCARD_HAS_PHANTOM_POWER + +/* Pipe indexes */ +#define PX_ANALOG_OUT 0 +#define PX_DIGITAL_OUT chip->px_digital_out +#define PX_ANALOG_IN chip->px_analog_in +#define PX_DIGITAL_IN chip->px_digital_in +#define PX_NUM chip->px_num + +/* Bus indexes */ +#define BX_ANALOG_OUT 0 +#define BX_DIGITAL_OUT chip->bx_digital_out +#define BX_ANALOG_IN chip->bx_analog_in +#define BX_DIGITAL_IN chip->bx_digital_in +#define BX_NUM chip->bx_num + + +#include <sound/driver.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/slab.h> +#include <linux/moduleparam.h> +#include <linux/firmware.h> +#include <sound/core.h> +#include <sound/info.h> +#include <sound/control.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/asoundef.h> +#include <sound/initval.h> +#include <sound/rawmidi.h> +#include <asm/io.h> +#include <asm/atomic.h> +#include "echoaudio.h" + +#define FW_361_LOADER 0 +#define FW_ECHO3G_DSP 1 +#define FW_3G_ASIC 2 + +static const struct firmware card_fw[] = { + {0, "loader_dsp.fw"}, + {0, "echo3g_dsp.fw"}, + {0, "3g_asic.fw"} +}; + +static struct pci_device_id snd_echo_ids[] = { + {0x1057, 0x3410, 0xECC0, 0x0100, 0, 0, 0}, /* Echo 3G */ + {0,} +}; + +static struct snd_pcm_hardware pcm_hardware_skel = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S32_BE, + .rates = SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 32000, + .rate_max = 100000, + .channels_min = 1, + .channels_max = 8, + .buffer_bytes_max = 262144, + .period_bytes_min = 32, + .period_bytes_max = 131072, + .periods_min = 2, + .periods_max = 220, +}; + +#include "echo3g_dsp.c" +#include "echoaudio_dsp.c" +#include "echoaudio_3g.c" +#include "echoaudio.c" +#include "midi.c" diff --git a/sound/pci/echoaudio/echo3g_dsp.c b/sound/pci/echoaudio/echo3g_dsp.c new file mode 100644 index 000000000..d26a1d1f3 --- /dev/null +++ b/sound/pci/echoaudio/echo3g_dsp.c @@ -0,0 +1,131 @@ +/**************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + ************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + +****************************************************************************/ + +static int load_asic(struct echoaudio *chip); +static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode); +static int set_digital_mode(struct echoaudio *chip, u8 mode); +static int check_asic_status(struct echoaudio *chip); +static int set_sample_rate(struct echoaudio *chip, u32 rate); +static int set_input_clock(struct echoaudio *chip, u16 clock); +static int set_professional_spdif(struct echoaudio *chip, char prof); +static int set_phantom_power(struct echoaudio *chip, char on); +static int write_control_reg(struct echoaudio *chip, u32 ctl, u32 frq, + char force); + +#include <linux/irq.h> + +static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) +{ + int err; + + local_irq_enable(); + DE_INIT(("init_hw() - Echo3G\n")); + snd_assert((subdevice_id & 0xfff0) == ECHO3G, return -ENODEV); + + if ((err = init_dsp_comm_page(chip))) { + DE_INIT(("init_hw - could not initialize DSP comm page\n")); + return err; + } + + chip->comm_page->e3g_frq_register = + __constant_cpu_to_le32((E3G_MAGIC_NUMBER / 48000) - 2); + chip->device_id = device_id; + chip->subdevice_id = subdevice_id; + chip->bad_board = TRUE; + chip->has_midi = TRUE; + chip->dsp_code_to_load = &card_fw[FW_ECHO3G_DSP]; + + /* Load the DSP code and the ASIC on the PCI card and get + what type of external box is attached */ + err = load_firmware(chip); + + if (err < 0) { + return err; + } else if (err == E3G_GINA3G_BOX_TYPE) { + chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | + ECHO_CLOCK_BIT_SPDIF | + ECHO_CLOCK_BIT_ADAT; + chip->card_name = "Gina3G"; + chip->px_digital_out = chip->bx_digital_out = 6; + chip->px_analog_in = chip->bx_analog_in = 14; + chip->px_digital_in = chip->bx_digital_in = 16; + chip->px_num = chip->bx_num = 24; + chip->has_phantom_power = TRUE; + chip->hasnt_input_nominal_level = TRUE; + } else if (err == E3G_LAYLA3G_BOX_TYPE) { + chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | + ECHO_CLOCK_BIT_SPDIF | + ECHO_CLOCK_BIT_ADAT | + ECHO_CLOCK_BIT_WORD; + chip->card_name = "Layla3G"; + chip->px_digital_out = chip->bx_digital_out = 8; + chip->px_analog_in = chip->bx_analog_in = 16; + chip->px_digital_in = chip->bx_digital_in = 24; + chip->px_num = chip->bx_num = 32; + } else { + return -ENODEV; + } + + chip->digital_modes = ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | + ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | + ECHOCAPS_HAS_DIGITAL_MODE_ADAT; + chip->digital_mode = DIGITAL_MODE_SPDIF_RCA; + chip->professional_spdif = FALSE; + chip->non_audio_spdif = FALSE; + chip->bad_board = FALSE; + + if ((err = init_line_levels(chip)) < 0) + return err; + err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA); + snd_assert(err >= 0, return err); + err = set_phantom_power(chip, 0); + snd_assert(err >= 0, return err); + err = set_professional_spdif(chip, TRUE); + + DE_INIT(("init_hw done\n")); + return err; +} + + + +static int set_phantom_power(struct echoaudio *chip, char on) +{ + u32 control_reg = le32_to_cpu(chip->comm_page->control_register); + + if (on) + control_reg |= E3G_PHANTOM_POWER; + else + control_reg &= ~E3G_PHANTOM_POWER; + + chip->phantom_power = on; + return write_control_reg(chip, control_reg, + le32_to_cpu(chip->comm_page->e3g_frq_register), + 0); +} diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c new file mode 100644 index 000000000..c3dafa290 --- /dev/null +++ b/sound/pci/echoaudio/echoaudio.c @@ -0,0 +1,2196 @@ +/* + * ALSA driver for Echoaudio soundcards. + * Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it> + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +MODULE_AUTHOR("Giuliano Pochini <pochini@shiny.it>"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Echoaudio " ECHOCARD_NAME " soundcards driver"); +MODULE_SUPPORTED_DEVICE("{{Echoaudio," ECHOCARD_NAME "}}"); +MODULE_DEVICE_TABLE(pci, snd_echo_ids); + +static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; +static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; +static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; + +module_param_array(index, int, NULL, 0444); +MODULE_PARM_DESC(index, "Index value for " ECHOCARD_NAME " soundcard."); +module_param_array(id, charp, NULL, 0444); +MODULE_PARM_DESC(id, "ID string for " ECHOCARD_NAME " soundcard."); +module_param_array(enable, bool, NULL, 0444); +MODULE_PARM_DESC(enable, "Enable " ECHOCARD_NAME " soundcard."); + +static unsigned int channels_list[10] = {1, 2, 4, 6, 8, 10, 12, 14, 16, 999999}; + +static int get_firmware(const struct firmware **fw_entry, + const struct firmware *frm, struct echoaudio *chip) +{ + int err; + char name[30]; + DE_ACT(("firmware requested: %s\n", frm->data)); + snprintf(name, sizeof(name), "ea/%s", frm->data); + if ((err = request_firmware(fw_entry, name, pci_device(chip))) < 0) + snd_printk(KERN_ERR "get_firmware(): Firmware not available (%d)\n", err); + return err; +} + +static void free_firmware(const struct firmware *fw_entry) +{ + release_firmware(fw_entry); + DE_ACT(("firmware released\n")); +} + + + +/****************************************************************************** + PCM interface +******************************************************************************/ + +static void audiopipe_free(struct snd_pcm_runtime *runtime) +{ + struct audiopipe *pipe = runtime->private_data; + + if (pipe->sgpage.area) + snd_dma_free_pages(&pipe->sgpage); + kfree(pipe); +} + + + +static int hw_rule_capture_format_by_channels(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct snd_interval *c = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + struct snd_mask fmt; + + snd_mask_any(&fmt); + +#ifndef ECHOCARD_HAS_STEREO_BIG_ENDIAN32 + /* >=2 channels cannot be S32_BE */ + if (c->min == 2) { + fmt.bits[0] &= ~SNDRV_PCM_FMTBIT_S32_BE; + return snd_mask_refine(f, &fmt); + } +#endif + /* > 2 channels cannot be U8 and S32_BE */ + if (c->min > 2) { + fmt.bits[0] &= ~(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_BE); + return snd_mask_refine(f, &fmt); + } + /* Mono is ok with any format */ + return 0; +} + + + +static int hw_rule_capture_channels_by_format(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct snd_interval *c = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + struct snd_interval ch; + + snd_interval_any(&ch); + + /* S32_BE is mono (and stereo) only */ + if (f->bits[0] == SNDRV_PCM_FMTBIT_S32_BE) { + ch.min = 1; +#ifdef ECHOCARD_HAS_STEREO_BIG_ENDIAN32 + ch.max = 2; +#else + ch.max = 1; +#endif + ch.integer = 1; + return snd_interval_refine(c, &ch); + } + /* U8 can be only mono or stereo */ + if (f->bits[0] == SNDRV_PCM_FMTBIT_U8) { + ch.min = 1; + ch.max = 2; + ch.integer = 1; + return snd_interval_refine(c, &ch); + } + /* S16_LE, S24_3LE and S32_LE support any number of channels. */ + return 0; +} + + + +static int hw_rule_playback_format_by_channels(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct snd_interval *c = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + struct snd_mask fmt; + u64 fmask; + snd_mask_any(&fmt); + + fmask = fmt.bits[0] + ((u64)fmt.bits[1] << 32); + + /* >2 channels must be S16_LE, S24_3LE or S32_LE */ + if (c->min > 2) { + fmask &= SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE; + /* 1 channel must be S32_BE or S32_LE */ + } else if (c->max == 1) + fmask &= SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE; +#ifndef ECHOCARD_HAS_STEREO_BIG_ENDIAN32 + /* 2 channels cannot be S32_BE */ + else if (c->min == 2 && c->max == 2) + fmask &= ~SNDRV_PCM_FMTBIT_S32_BE; +#endif + else + return 0; + + fmt.bits[0] &= (u32)fmask; + fmt.bits[1] &= (u32)(fmask >> 32); + return snd_mask_refine(f, &fmt); +} + + + +static int hw_rule_playback_channels_by_format(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct snd_interval *c = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + struct snd_interval ch; + u64 fmask; + + snd_interval_any(&ch); + ch.integer = 1; + fmask = f->bits[0] + ((u64)f->bits[1] << 32); + + /* S32_BE is mono (and stereo) only */ + if (fmask == SNDRV_PCM_FMTBIT_S32_BE) { + ch.min = 1; +#ifdef ECHOCARD_HAS_STEREO_BIG_ENDIAN32 + ch.max = 2; +#else + ch.max = 1; +#endif + /* U8 is stereo only */ + } else if (fmask == SNDRV_PCM_FMTBIT_U8) + ch.min = ch.max = 2; + /* S16_LE and S24_3LE must be at least stereo */ + else if (!(fmask & ~(SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE))) + ch.min = 2; + else + return 0; + + return snd_interval_refine(c, &ch); +} + + + +/* Since the sample rate is a global setting, do allow the user to change the +sample rate only if there is only one pcm device open. */ +static int hw_rule_sample_rate(struct snd_pcm_hw_params *params, + struct snd_pcm_hw_rule *rule) +{ + struct snd_interval *rate = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_RATE); + struct echoaudio *chip = rule->private; + struct snd_interval fixed; + + if (!chip->can_set_rate) { + snd_interval_any(&fixed); + fixed.min = fixed.max = chip->sample_rate; + return snd_interval_refine(rate, &fixed); + } + return 0; +} + + +static int pcm_open(struct snd_pcm_substream *substream, + signed char max_channels) +{ + struct echoaudio *chip; + struct snd_pcm_runtime *runtime; + struct audiopipe *pipe; + int err, i; + + if (max_channels <= 0) + return -EAGAIN; + + chip = snd_pcm_substream_chip(substream); + runtime = substream->runtime; + + pipe = kzalloc(sizeof(struct audiopipe), GFP_KERNEL); + if (!pipe) + return -ENOMEM; + pipe->index = -1; /* Not configured yet */ + + /* Set up hw capabilities and contraints */ + memcpy(&pipe->hw, &pcm_hardware_skel, sizeof(struct snd_pcm_hardware)); + DE_HWP(("max_channels=%d\n", max_channels)); + pipe->constr.list = channels_list; + pipe->constr.mask = 0; + for (i = 0; channels_list[i] <= max_channels; i++); + pipe->constr.count = i; + if (pipe->hw.channels_max > max_channels) + pipe->hw.channels_max = max_channels; + if (chip->digital_mode == DIGITAL_MODE_ADAT) { + pipe->hw.rate_max = 48000; + pipe->hw.rates &= SNDRV_PCM_RATE_8000_48000; + } + + runtime->hw = pipe->hw; + runtime->private_data = pipe; + runtime->private_free = audiopipe_free; + snd_pcm_set_sync(substream); + + /* Only mono and any even number of channels are allowed */ + if ((err = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &pipe->constr)) < 0) + return err; + + /* All periods should have the same size */ + if ((err = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + return err; + + /* The hw accesses memory in chunks 32 frames long and they should be + 32-bytes-aligned. It's not a requirement, but it seems that IRQs are + generated with a resolution of 32 frames. Thus we need the following */ + if ((err = snd_pcm_hw_constraint_step(runtime, 0, + SNDRV_PCM_HW_PARAM_PERIOD_SIZE, + 32)) < 0) + return err; + if ((err = snd_pcm_hw_constraint_step(runtime, 0, + SNDRV_PCM_HW_PARAM_BUFFER_SIZE, + 32)) < 0) + return err; + + if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + hw_rule_sample_rate, chip, + SNDRV_PCM_HW_PARAM_RATE, -1)) < 0) + return err; + + /* Finally allocate a page for the scatter-gather list */ + if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, + snd_dma_pci_data(chip->pci), + PAGE_SIZE, &pipe->sgpage)) < 0) { + DE_HWP(("s-g list allocation failed\n")); + return err; + } + + return 0; +} + + + +static int pcm_analog_in_open(struct snd_pcm_substream *substream) +{ + struct echoaudio *chip = snd_pcm_substream_chip(substream); + int err; + + DE_ACT(("pcm_analog_in_open\n")); + if ((err = pcm_open(substream, num_analog_busses_in(chip) - + substream->number)) < 0) + return err; + if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + hw_rule_capture_channels_by_format, NULL, + SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0) + return err; + if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_FORMAT, + hw_rule_capture_format_by_channels, NULL, + SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) + return err; + atomic_inc(&chip->opencount); + if (atomic_read(&chip->opencount) > 1 && chip->rate_set) + chip->can_set_rate=0; + DE_HWP(("pcm_analog_in_open cs=%d oc=%d r=%d\n", + chip->can_set_rate, atomic_read(&chip->opencount), + chip->sample_rate)); + return 0; +} + + + +static int pcm_analog_out_open(struct snd_pcm_substream *substream) +{ + struct echoaudio *chip = snd_pcm_substream_chip(substream); + int max_channels, err; + +#ifdef ECHOCARD_HAS_VMIXER + max_channels = num_pipes_out(chip); +#else + max_channels = num_analog_busses_out(chip); +#endif + DE_ACT(("pcm_analog_out_open\n")); + if ((err = pcm_open(substream, max_channels - substream->number)) < 0) + return err; + if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + hw_rule_playback_channels_by_format, + NULL, + SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0) + return err; + if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_FORMAT, + hw_rule_playback_format_by_channels, + NULL, + SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) + return err; + atomic_inc(&chip->opencount); + if (atomic_read(&chip->opencount) > 1 && chip->rate_set) + chip->can_set_rate=0; + DE_HWP(("pcm_analog_out_open cs=%d oc=%d r=%d\n", + chip->can_set_rate, atomic_read(&chip->opencount), + chip->sample_rate)); + return 0; +} + + + +#ifdef ECHOCARD_HAS_DIGITAL_IO + +static int pcm_digital_in_open(struct snd_pcm_substream *substream) +{ + struct echoaudio *chip = snd_pcm_substream_chip(substream); + int err, max_channels; + + DE_ACT(("pcm_digital_in_open\n")); + max_channels = num_digital_busses_in(chip) - substream->number; + down(&chip->mode_mutex); + if (chip->digital_mode == DIGITAL_MODE_ADAT) + err = pcm_open(substream, max_channels); + else /* If the card has ADAT, subtract the 6 channels + * that S/PDIF doesn't have + */ + err = pcm_open(substream, max_channels - ECHOCARD_HAS_ADAT); + + if (err < 0) + goto din_exit; + + if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + hw_rule_capture_channels_by_format, NULL, + SNDRV_PCM_HW_PARAM_FORMAT, -1)) < 0) + goto din_exit; + if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_FORMAT, + hw_rule_capture_format_by_channels, NULL, + SNDRV_PCM_HW_PARAM_CHANNELS, -1)) < 0) + goto din_exit; + + atomic_inc(&chip->opencount); + if (atomic_read(&chip->opencount) > 1 && chip->rate_set) + chip->can_set_rate=0; + +din_exit: + up(&chip->mode_mutex); + return err; +} + + + +#ifndef ECHOCARD_HAS_VMIXER /* See the note in snd_echo_new_pcm() */ + +static int pcm_digital_out_open(struct snd_pcm_substream *substream) +{ + struct echoaudio *chip = snd_pcm_substream_chip(substream); + int err, max_channels; + + DE_ACT(("pcm_digital_out_open\n")); + max_channels = num_digital_busses_out(chip) - substream->number; + down(&chip->mode_mutex); + if (chip->digital_mode == DIGITAL_MODE_ADAT) + err = pcm_open(substream, max_channels); + else /* If the card has ADAT, subtract the 6 channels + * that S/PDIF doesn't have + */ + err = pcm_open(substream, max_channels - ECHOCARD_HAS_ADAT); + + if (err < 0) + goto dout_exit; + + if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + hw_rule_playback_channels_by_format, + NULL, SNDRV_PCM_HW_PARAM_FORMAT, + -1)) < 0) + goto dout_exit; + if ((err = snd_pcm_hw_rule_add(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_FORMAT, + hw_rule_playback_format_by_channels, + NULL, SNDRV_PCM_HW_PARAM_CHANNELS, + -1)) < 0) + goto dout_exit; + atomic_inc(&chip->opencount); + if (atomic_read(&chip->opencount) > 1 && chip->rate_set) + chip->can_set_rate=0; +dout_exit: + up(&chip->mode_mutex); + return err; +} + +#endif /* !ECHOCARD_HAS_VMIXER */ + +#endif /* ECHOCARD_HAS_DIGITAL_IO */ + + + +static int pcm_close(struct snd_pcm_substream *substream) +{ + struct echoaudio *chip = snd_pcm_substream_chip(substream); + int oc; + + /* Nothing to do here. Audio is already off and pipe will be + * freed by its callback + */ + DE_ACT(("pcm_close\n")); + + atomic_dec(&chip->opencount); + oc = atomic_read(&chip->opencount); + DE_ACT(("pcm_close oc=%d cs=%d rs=%d\n", oc, + chip->can_set_rate, chip->rate_set)); + if (oc < 2) + chip->can_set_rate = 1; + if (oc == 0) + chip->rate_set = 0; + DE_ACT(("pcm_close2 oc=%d cs=%d rs=%d\n", oc, + chip->can_set_rate,chip->rate_set)); + + return 0; +} + + + +/* Channel allocation and scatter-gather list setup */ +static int init_engine(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params, + int pipe_index, int interleave) +{ + struct echoaudio *chip; + int err, per, rest, page, edge, offs; + struct snd_sg_buf *sgbuf; + struct audiopipe *pipe; + + chip = snd_pcm_substream_chip(substream); + pipe = (struct audiopipe *) substream->runtime->private_data; + + /* Sets up che hardware. If it's already initialized, reset and + * redo with the new parameters + */ + spin_lock_irq(&chip->lock); + if (pipe->index >= 0) { + DE_HWP(("hwp_ie free(%d)\n", pipe->index)); + err = free_pipes(chip, pipe); + snd_assert(!err); + chip->substream[pipe->index] = NULL; + } + + err = allocate_pipes(chip, pipe, pipe_index, interleave); + if (err < 0) { + spin_unlock_irq(&chip->lock); + DE_ACT((KERN_NOTICE "allocate_pipes(%d) err=%d\n", + pipe_index, err)); + return err; + } + spin_unlock_irq(&chip->lock); + DE_ACT((KERN_NOTICE "allocate_pipes()=%d\n", pipe_index)); + + DE_HWP(("pcm_hw_params (bufsize=%dB periods=%d persize=%dB)\n", + params_buffer_bytes(hw_params), params_periods(hw_params), + params_period_bytes(hw_params))); + err = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); + if (err < 0) { + snd_printk(KERN_ERR "malloc_pages err=%d\n", err); + spin_lock_irq(&chip->lock); + free_pipes(chip, pipe); + spin_unlock_irq(&chip->lock); + pipe->index = -1; + return err; + } + + sgbuf = snd_pcm_substream_sgbuf(substream); + + DE_HWP(("pcm_hw_params table size=%d pages=%d\n", + sgbuf->size, sgbuf->pages)); + sglist_init(chip, pipe); + edge = PAGE_SIZE; + for (offs = page = per = 0; offs < params_buffer_bytes(hw_params); + per++) { + rest = params_period_bytes(hw_params); + if (offs + rest > params_buffer_bytes(hw_params)) + rest = params_buffer_bytes(hw_params) - offs; + while (rest) { + if (rest <= edge - offs) { + sglist_add_mapping(chip, pipe, + snd_sgbuf_get_addr(sgbuf, offs), + rest); + sglist_add_irq(chip, pipe); + offs += rest; + rest = 0; + } else { + sglist_add_mapping(chip, pipe, + snd_sgbuf_get_addr(sgbuf, offs), + edge - offs); + rest -= edge - offs; + offs = edge; + } + if (offs == edge) { + edge += PAGE_SIZE; + page++; + } + } + } + + /* Close the ring buffer */ + sglist_wrap(chip, pipe); + + /* This stuff is used by the irq handler, so it must be + * initialized before chip->substream + */ + chip->last_period[pipe_index] = 0; + pipe->last_counter = 0; + pipe->position = 0; + smp_wmb(); + chip->substream[pipe_index] = substream; + chip->rate_set = 1; + spin_lock_irq(&chip->lock); + set_sample_rate(chip, hw_params->rate_num / hw_params->rate_den); + spin_unlock_irq(&chip->lock); + DE_HWP(("pcm_hw_params ok\n")); + return 0; +} + + + +static int pcm_analog_in_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + struct echoaudio *chip = snd_pcm_substream_chip(substream); + + return init_engine(substream, hw_params, px_analog_in(chip) + + substream->number, params_channels(hw_params)); +} + + + +static int pcm_analog_out_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + return init_engine(substream, hw_params, substream->number, + params_channels(hw_params)); +} + + + +#ifdef ECHOCARD_HAS_DIGITAL_IO + +static int pcm_digital_in_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + struct echoaudio *chip = snd_pcm_substream_chip(substream); + + return init_engine(substream, hw_params, px_digital_in(chip) + + substream->number, params_channels(hw_params)); +} + + + +#ifndef ECHOCARD_HAS_VMIXER /* See the note in snd_echo_new_pcm() */ +static int pcm_digital_out_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) +{ + struct echoaudio *chip = snd_pcm_substream_chip(substream); + + return init_engine(substream, hw_params, px_digital_out(chip) + + substream->number, params_channels(hw_params)); +} +#endif /* !ECHOCARD_HAS_VMIXER */ + +#endif /* ECHOCARD_HAS_DIGITAL_IO */ + + + +static int pcm_hw_free(struct snd_pcm_substream *substream) +{ + struct echoaudio *chip; + struct audiopipe *pipe; + + chip = snd_pcm_substream_chip(substream); + pipe = (struct audiopipe *) substream->runtime->private_data; + + spin_lock_irq(&chip->lock); + if (pipe->index >= 0) { + DE_HWP(("pcm_hw_free(%d)\n", pipe->index)); + free_pipes(chip, pipe); + chip->substream[pipe->index] = NULL; + pipe->index = -1; + } + spin_unlock_irq(&chip->lock); + + DE_HWP(("pcm_hw_freed\n")); + snd_pcm_lib_free_pages(substream); + return 0; +} + + + +static int pcm_prepare(struct snd_pcm_substream *substream) +{ + struct echoaudio *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + struct audioformat format; + int pipe_index = ((struct audiopipe *)runtime->private_data)->index; + + DE_HWP(("Prepare rate=%d format=%d channels=%d\n", + runtime->rate, runtime->format, runtime->channels)); + format.interleave = runtime->channels; + format.data_are_bigendian = 0; + format.mono_to_stereo = 0; + switch (runtime->format) { + case SNDRV_PCM_FORMAT_U8: + format.bits_per_sample = 8; + break; + case SNDRV_PCM_FORMAT_S16_LE: + format.bits_per_sample = 16; + break; + case SNDRV_PCM_FORMAT_S24_3LE: + format.bits_per_sample = 24; + break; + case SNDRV_PCM_FORMAT_S32_BE: + format.data_are_bigendian = 1; + case SNDRV_PCM_FORMAT_S32_LE: + format.bits_per_sample = 32; + break; + default: + DE_HWP(("Prepare error: unsupported format %d\n", + runtime->format)); + return -EINVAL; + } + + snd_assert(pipe_index < px_num(chip), return -EINVAL); + snd_assert(is_pipe_allocated(chip, pipe_index), return -EINVAL); + set_audio_format(chip, pipe_index, &format); + return 0; +} + + + +static int pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct echoaudio *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + struct audiopipe *pipe = runtime->private_data; + int i, err; + u32 channelmask = 0; + struct list_head *pos; + struct snd_pcm_substream *s; + + snd_pcm_group_for_each(pos, substream) { + s = snd_pcm_group_substream_entry(pos); + for (i = 0; i < DSP_MAXPIPES; i++) { + if (s == chip->substream[i]) { + channelmask |= 1 << i; + snd_pcm_trigger_done(s, substream); + } + } + } + + spin_lock(&chip->lock); + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + DE_ACT(("pcm_trigger start\n")); + for (i = 0; i < DSP_MAXPIPES; i++) { + if (channelmask & (1 << i)) { + pipe = chip->substream[i]->runtime->private_data; + switch (pipe->state) { + case PIPE_STATE_STOPPED: + chip->last_period[i] = 0; + pipe->last_counter = 0; + pipe->position = 0; + *pipe->dma_counter = 0; + case PIPE_STATE_PAUSED: + pipe->state = PIPE_STATE_STARTED; + break; + case PIPE_STATE_STARTED: + break; + } + } + } + err = start_transport(chip, channelmask, + chip->pipe_cyclic_mask); + break; + case SNDRV_PCM_TRIGGER_STOP: + DE_ACT(("pcm_trigger stop\n")); + for (i = 0; i < DSP_MAXPIPES; i++) { + if (channelmask & (1 << i)) { + pipe = chip->substream[i]->runtime->private_data; + pipe->state = PIPE_STATE_STOPPED; + } + } + err = stop_transport(chip, channelmask); + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + DE_ACT(("pcm_trigger pause\n")); + for (i = 0; i < DSP_MAXPIPES; i++) { + if (channelmask & (1 << i)) { + pipe = chip->substream[i]->runtime->private_data; + pipe->state = PIPE_STATE_PAUSED; + } + } + err = pause_transport(chip, channelmask); + break; + default: + err = -EINVAL; + } + spin_unlock(&chip->lock); + return err; +} + + + +static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct audiopipe *pipe = runtime->private_data; + size_t cnt, bufsize, pos; + + cnt = le32_to_cpu(*pipe->dma_counter); + pipe->position += cnt - pipe->last_counter; + pipe->last_counter = cnt; + bufsize = substream->runtime->buffer_size; + pos = bytes_to_frames(substream->runtime, pipe->position); + + while (pos >= bufsize) { + pipe->position -= frames_to_bytes(substream->runtime, bufsize); + pos -= bufsize; + } + return pos; +} + + + +/* pcm *_ops structures */ +static struct snd_pcm_ops analog_playback_ops = { + .open = pcm_analog_out_open, + .close = pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = pcm_analog_out_hw_params, + .hw_free = pcm_hw_free, + .prepare = pcm_prepare, + .trigger = pcm_trigger, + .pointer = pcm_pointer, + .page = snd_pcm_sgbuf_ops_page, +}; +static struct snd_pcm_ops analog_capture_ops = { + .open = pcm_analog_in_open, + .close = pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = pcm_analog_in_hw_params, + .hw_free = pcm_hw_free, + .prepare = pcm_prepare, + .trigger = pcm_trigger, + .pointer = pcm_pointer, + .page = snd_pcm_sgbuf_ops_page, +}; +#ifdef ECHOCARD_HAS_DIGITAL_IO +#ifndef ECHOCARD_HAS_VMIXER +static struct snd_pcm_ops digital_playback_ops = { + .open = pcm_digital_out_open, + .close = pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = pcm_digital_out_hw_params, + .hw_free = pcm_hw_free, + .prepare = pcm_prepare, + .trigger = pcm_trigger, + .pointer = pcm_pointer, + .page = snd_pcm_sgbuf_ops_page, +}; +#endif /* !ECHOCARD_HAS_VMIXER */ +static struct snd_pcm_ops digital_capture_ops = { + .open = pcm_digital_in_open, + .close = pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = pcm_digital_in_hw_params, + .hw_free = pcm_hw_free, + .prepare = pcm_prepare, + .trigger = pcm_trigger, + .pointer = pcm_pointer, + .page = snd_pcm_sgbuf_ops_page, +}; +#endif /* ECHOCARD_HAS_DIGITAL_IO */ + + + +/* Preallocate memory only for the first substream because it's the most + * used one + */ +static int snd_echo_preallocate_pages(struct snd_pcm *pcm, struct device *dev) +{ + struct snd_pcm_substream *ss; + int stream, err; + + for (stream = 0; stream < 2; stream++) + for (ss = pcm->streams[stream].substream; ss; ss = ss->next) { + err = snd_pcm_lib_preallocate_pages(ss, SNDRV_DMA_TYPE_DEV_SG, + dev, + ss->number ? 0 : 128<<10, + 256<<10); + if (err < 0) + return err; + } + return 0; +} + + + +/*<--snd_echo_probe() */ +static int __devinit snd_echo_new_pcm(struct echoaudio *chip) +{ + struct snd_pcm *pcm; + int err; + +#ifdef ECHOCARD_HAS_VMIXER + /* This card has a Vmixer, that is there is no direct mapping from PCM + streams to physical outputs. The user can mix the streams as he wishes + via control interface and it's possible to send any stream to any + output, thus it makes no sense to keep analog and digital outputs + separated */ + + /* PCM#0 Virtual outputs and analog inputs */ + if ((err = snd_pcm_new(chip->card, "PCM", 0, num_pipes_out(chip), + num_analog_busses_in(chip), &pcm)) < 0) + return err; + pcm->private_data = chip; + chip->analog_pcm = pcm; + strcpy(pcm->name, chip->card->shortname); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &analog_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &analog_capture_ops); + if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0) + return err; + DE_INIT(("Analog PCM ok\n")); + +#ifdef ECHOCARD_HAS_DIGITAL_IO + /* PCM#1 Digital inputs, no outputs */ + if ((err = snd_pcm_new(chip->card, "Digital PCM", 1, 0, + num_digital_busses_in(chip), &pcm)) < 0) + return err; + pcm->private_data = chip; + chip->digital_pcm = pcm; + strcpy(pcm->name, chip->card->shortname); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &digital_capture_ops); + if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0) + return err; + DE_INIT(("Digital PCM ok\n")); +#endif /* ECHOCARD_HAS_DIGITAL_IO */ + +#else /* ECHOCARD_HAS_VMIXER */ + + /* The card can manage substreams formed by analog and digital channels + at the same time, but I prefer to keep analog and digital channels + separated, because that mixed thing is confusing and useless. So we + register two PCM devices: */ + + /* PCM#0 Analog i/o */ + if ((err = snd_pcm_new(chip->card, "Analog PCM", 0, + num_analog_busses_out(chip), + num_analog_busses_in(chip), &pcm)) < 0) + return err; + pcm->private_data = chip; + chip->analog_pcm = pcm; + strcpy(pcm->name, chip->card->shortname); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &analog_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &analog_capture_ops); + if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0) + return err; + DE_INIT(("Analog PCM ok\n")); + +#ifdef ECHOCARD_HAS_DIGITAL_IO + /* PCM#1 Digital i/o */ + if ((err = snd_pcm_new(chip->card, "Digital PCM", 1, + num_digital_busses_out(chip), + num_digital_busses_in(chip), &pcm)) < 0) + return err; + pcm->private_data = chip; + chip->digital_pcm = pcm; + strcpy(pcm->name, chip->card->shortname); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &digital_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &digital_capture_ops); + if ((err = snd_echo_preallocate_pages(pcm, snd_dma_pci_data(chip->pci))) < 0) + return err; + DE_INIT(("Digital PCM ok\n")); +#endif /* ECHOCARD_HAS_DIGITAL_IO */ + +#endif /* ECHOCARD_HAS_VMIXER */ + + return 0; +} + + + + +/****************************************************************************** + Control interface +******************************************************************************/ + +/******************* PCM output volume *******************/ +static int snd_echo_output_gain_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct echoaudio *chip; + + chip = snd_kcontrol_chip(kcontrol); + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = num_busses_out(chip); + uinfo->value.integer.min = ECHOGAIN_MINOUT; + uinfo->value.integer.max = ECHOGAIN_MAXOUT; + return 0; +} + +static int snd_echo_output_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + int c; + + chip = snd_kcontrol_chip(kcontrol); + for (c = 0; c < num_busses_out(chip); c++) + ucontrol->value.integer.value[c] = chip->output_gain[c]; + return 0; +} + +static int snd_echo_output_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + int c, changed, gain; + + changed = 0; + chip = snd_kcontrol_chip(kcontrol); + spin_lock_irq(&chip->lock); + for (c = 0; c < num_busses_out(chip); c++) { + gain = ucontrol->value.integer.value[c]; + /* Ignore out of range values */ + if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT) + continue; + if (chip->output_gain[c] != gain) { + set_output_gain(chip, c, gain); + changed = 1; + } + } + if (changed) + update_output_line_level(chip); + spin_unlock_irq(&chip->lock); + return changed; +} + +#ifdef ECHOCARD_HAS_VMIXER +/* On Vmixer cards this one controls the line-out volume */ +static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = { + .name = "Line Playback Volume", + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .info = snd_echo_output_gain_info, + .get = snd_echo_output_gain_get, + .put = snd_echo_output_gain_put, +}; +#else +static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = { + .name = "PCM Playback Volume", + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .info = snd_echo_output_gain_info, + .get = snd_echo_output_gain_get, + .put = snd_echo_output_gain_put, +}; +#endif + + + +#ifdef ECHOCARD_HAS_INPUT_GAIN + +/******************* Analog input volume *******************/ +static int snd_echo_input_gain_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct echoaudio *chip; + + chip = snd_kcontrol_chip(kcontrol); + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = num_analog_busses_in(chip); + uinfo->value.integer.min = ECHOGAIN_MININP; + uinfo->value.integer.max = ECHOGAIN_MAXINP; + return 0; +} + +static int snd_echo_input_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + int c; + + chip = snd_kcontrol_chip(kcontrol); + for (c = 0; c < num_analog_busses_in(chip); c++) + ucontrol->value.integer.value[c] = chip->input_gain[c]; + return 0; +} + +static int snd_echo_input_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + int c, gain, changed; + + changed = 0; + chip = snd_kcontrol_chip(kcontrol); + spin_lock_irq(&chip->lock); + for (c = 0; c < num_analog_busses_in(chip); c++) { + gain = ucontrol->value.integer.value[c]; + /* Ignore out of range values */ + if (gain < ECHOGAIN_MININP || gain > ECHOGAIN_MAXINP) + continue; + if (chip->input_gain[c] != gain) { + set_input_gain(chip, c, gain); + changed = 1; + } + } + if (changed) + update_input_line_level(chip); + spin_unlock_irq(&chip->lock); + return changed; +} + +static struct snd_kcontrol_new snd_echo_line_input_gain __devinitdata = { + .name = "Line Capture Volume", + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .info = snd_echo_input_gain_info, + .get = snd_echo_input_gain_get, + .put = snd_echo_input_gain_put, +}; + +#endif /* ECHOCARD_HAS_INPUT_GAIN */ + + + +#ifdef ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL + +/************ Analog output nominal level (+4dBu / -10dBV) ***************/ +static int snd_echo_output_nominal_info (struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct echoaudio *chip; + + chip = snd_kcontrol_chip(kcontrol); + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = num_analog_busses_out(chip); + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int snd_echo_output_nominal_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + int c; + + chip = snd_kcontrol_chip(kcontrol); + for (c = 0; c < num_analog_busses_out(chip); c++) + ucontrol->value.integer.value[c] = chip->nominal_level[c]; + return 0; +} + +static int snd_echo_output_nominal_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + int c, changed; + + changed = 0; + chip = snd_kcontrol_chip(kcontrol); + spin_lock_irq(&chip->lock); + for (c = 0; c < num_analog_busses_out(chip); c++) { + if (chip->nominal_level[c] != ucontrol->value.integer.value[c]) { + set_nominal_level(chip, c, + ucontrol->value.integer.value[c]); + changed = 1; + } + } + if (changed) + update_output_line_level(chip); + spin_unlock_irq(&chip->lock); + return changed; +} + +static struct snd_kcontrol_new snd_echo_output_nominal_level __devinitdata = { + .name = "Line Playback Switch (-10dBV)", + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .info = snd_echo_output_nominal_info, + .get = snd_echo_output_nominal_get, + .put = snd_echo_output_nominal_put, +}; + +#endif /* ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL */ + + + +#ifdef ECHOCARD_HAS_INPUT_NOMINAL_LEVEL + +/*************** Analog input nominal level (+4dBu / -10dBV) ***************/ +static int snd_echo_input_nominal_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct echoaudio *chip; + + chip = snd_kcontrol_chip(kcontrol); + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = num_analog_busses_in(chip); + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int snd_echo_input_nominal_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + int c; + + chip = snd_kcontrol_chip(kcontrol); + for (c = 0; c < num_analog_busses_in(chip); c++) + ucontrol->value.integer.value[c] = + chip->nominal_level[bx_analog_in(chip) + c]; + return 0; +} + +static int snd_echo_input_nominal_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + int c, changed; + + changed = 0; + chip = snd_kcontrol_chip(kcontrol); + spin_lock_irq(&chip->lock); + for (c = 0; c < num_analog_busses_in(chip); c++) { + if (chip->nominal_level[bx_analog_in(chip) + c] != + ucontrol->value.integer.value[c]) { + set_nominal_level(chip, bx_analog_in(chip) + c, + ucontrol->value.integer.value[c]); + changed = 1; + } + } + if (changed) + update_output_line_level(chip); /* "Output" is not a mistake + * here. + */ + spin_unlock_irq(&chip->lock); + return changed; +} + +static struct snd_kcontrol_new snd_echo_intput_nominal_level __devinitdata = { + .name = "Line Capture Switch (-10dBV)", + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .info = snd_echo_input_nominal_info, + .get = snd_echo_input_nominal_get, + .put = snd_echo_input_nominal_put, +}; + +#endif /* ECHOCARD_HAS_INPUT_NOMINAL_LEVEL */ + + + +#ifdef ECHOCARD_HAS_MONITOR + +/******************* Monitor mixer *******************/ +static int snd_echo_mixer_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct echoaudio *chip; + + chip = snd_kcontrol_chip(kcontrol); + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = ECHOGAIN_MINOUT; + uinfo->value.integer.max = ECHOGAIN_MAXOUT; + uinfo->dimen.d[0] = num_busses_out(chip); + uinfo->dimen.d[1] = num_busses_in(chip); + return 0; +} + +static int snd_echo_mixer_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + + chip = snd_kcontrol_chip(kcontrol); + ucontrol->value.integer.value[0] = + chip->monitor_gain[ucontrol->id.index / num_busses_in(chip)] + [ucontrol->id.index % num_busses_in(chip)]; + return 0; +} + +static int snd_echo_mixer_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + int changed, gain; + short out, in; + + changed = 0; + chip = snd_kcontrol_chip(kcontrol); + out = ucontrol->id.index / num_busses_in(chip); + in = ucontrol->id.index % num_busses_in(chip); + gain = ucontrol->value.integer.value[0]; + if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT) + return -EINVAL; + if (chip->monitor_gain[out][in] != gain) { + spin_lock_irq(&chip->lock); + set_monitor_gain(chip, out, in, gain); + update_output_line_level(chip); + spin_unlock_irq(&chip->lock); + changed = 1; + } + return changed; +} + +static struct snd_kcontrol_new snd_echo_monitor_mixer __devinitdata = { + .name = "Monitor Mixer Volume", + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .info = snd_echo_mixer_info, + .get = snd_echo_mixer_get, + .put = snd_echo_mixer_put, +}; + +#endif /* ECHOCARD_HAS_MONITOR */ + + + +#ifdef ECHOCARD_HAS_VMIXER + +/******************* Vmixer *******************/ +static int snd_echo_vmixer_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct echoaudio *chip; + + chip = snd_kcontrol_chip(kcontrol); + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = ECHOGAIN_MINOUT; + uinfo->value.integer.max = ECHOGAIN_MAXOUT; + uinfo->dimen.d[0] = num_busses_out(chip); + uinfo->dimen.d[1] = num_pipes_out(chip); + return 0; +} + +static int snd_echo_vmixer_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + + chip = snd_kcontrol_chip(kcontrol); + ucontrol->value.integer.value[0] = + chip->vmixer_gain[ucontrol->id.index / num_pipes_out(chip)] + [ucontrol->id.index % num_pipes_out(chip)]; + return 0; +} + +static int snd_echo_vmixer_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + int gain, changed; + short vch, out; + + changed = 0; + chip = snd_kcontrol_chip(kcontrol); + out = ucontrol->id.index / num_pipes_out(chip); + vch = ucontrol->id.index % num_pipes_out(chip); + gain = ucontrol->value.integer.value[0]; + if (gain < ECHOGAIN_MINOUT || gain > ECHOGAIN_MAXOUT) + return -EINVAL; + if (chip->vmixer_gain[out][vch] != ucontrol->value.integer.value[0]) { + spin_lock_irq(&chip->lock); + set_vmixer_gain(chip, out, vch, ucontrol->value.integer.value[0]); + update_vmixer_level(chip); + spin_unlock_irq(&chip->lock); + changed = 1; + } + return changed; +} + +static struct snd_kcontrol_new snd_echo_vmixer __devinitdata = { + .name = "VMixer Volume", + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .info = snd_echo_vmixer_info, + .get = snd_echo_vmixer_get, + .put = snd_echo_vmixer_put, +}; + +#endif /* ECHOCARD_HAS_VMIXER */ + + + +#ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH + +/******************* Digital mode switch *******************/ +static int snd_echo_digital_mode_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static char *names[4] = { + "S/PDIF Coaxial", "S/PDIF Optical", "ADAT Optical", + "S/PDIF Cdrom" + }; + struct echoaudio *chip; + + chip = snd_kcontrol_chip(kcontrol); + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->value.enumerated.items = chip->num_digital_modes; + uinfo->count = 1; + if (uinfo->value.enumerated.item >= chip->num_digital_modes) + uinfo->value.enumerated.item = chip->num_digital_modes - 1; + strcpy(uinfo->value.enumerated.name, names[ + chip->digital_mode_list[uinfo->value.enumerated.item]]); + return 0; +} + +static int snd_echo_digital_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + int i, mode; + + chip = snd_kcontrol_chip(kcontrol); + mode = chip->digital_mode; + for (i = chip->num_digital_modes - 1; i >= 0; i--) + if (mode == chip->digital_mode_list[i]) { + ucontrol->value.enumerated.item[0] = i; + break; + } + return 0; +} + +static int snd_echo_digital_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + int changed; + unsigned short emode, dmode; + + changed = 0; + chip = snd_kcontrol_chip(kcontrol); + + emode = ucontrol->value.enumerated.item[0]; + if (emode >= chip->num_digital_modes) + return -EINVAL; + dmode = chip->digital_mode_list[emode]; + + if (dmode != chip->digital_mode) { + /* mode_mutex is required to make this operation atomic wrt + pcm_digital_*_open() and set_input_clock() functions. */ + down(&chip->mode_mutex); + + /* Do not allow the user to change the digital mode when a pcm + device is open because it also changes the number of channels + and the allowed sample rates */ + if (atomic_read(&chip->opencount)) { + changed = -EAGAIN; + } else { + changed = set_digital_mode(chip, dmode); + /* If we had to change the clock source, report it */ + if (changed > 0 && chip->clock_src_ctl) { + snd_ctl_notify(chip->card, + SNDRV_CTL_EVENT_MASK_VALUE, + &chip->clock_src_ctl->id); + DE_ACT(("SDM() =%d\n", changed)); + } + if (changed >= 0) + changed = 1; /* No errors */ + } + up(&chip->mode_mutex); + } + return changed; +} + +static struct snd_kcontrol_new snd_echo_digital_mode_switch __devinitdata = { + .name = "Digital mode Switch", + .iface = SNDRV_CTL_ELEM_IFACE_CARD, + .info = snd_echo_digital_mode_info, + .get = snd_echo_digital_mode_get, + .put = snd_echo_digital_mode_put, +}; + +#endif /* ECHOCARD_HAS_DIGITAL_MODE_SWITCH */ + + + +#ifdef ECHOCARD_HAS_DIGITAL_IO + +/******************* S/PDIF mode switch *******************/ +static int snd_echo_spdif_mode_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static char *names[2] = {"Consumer", "Professional"}; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->value.enumerated.items = 2; + uinfo->count = 1; + if (uinfo->value.enumerated.item) + uinfo->value.enumerated.item = 1; + strcpy(uinfo->value.enumerated.name, + names[uinfo->value.enumerated.item]); + return 0; +} + +static int snd_echo_spdif_mode_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + + chip = snd_kcontrol_chip(kcontrol); + ucontrol->value.enumerated.item[0] = !!chip->professional_spdif; + return 0; +} + +static int snd_echo_spdif_mode_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + int mode; + + chip = snd_kcontrol_chip(kcontrol); + mode = !!ucontrol->value.enumerated.item[0]; + if (mode != chip->professional_spdif) { + spin_lock_irq(&chip->lock); + set_professional_spdif(chip, mode); + spin_unlock_irq(&chip->lock); + return 1; + } + return 0; +} + +static struct snd_kcontrol_new snd_echo_spdif_mode_switch __devinitdata = { + .name = "S/PDIF mode Switch", + .iface = SNDRV_CTL_ELEM_IFACE_CARD, + .info = snd_echo_spdif_mode_info, + .get = snd_echo_spdif_mode_get, + .put = snd_echo_spdif_mode_put, +}; + +#endif /* ECHOCARD_HAS_DIGITAL_IO */ + + + +#ifdef ECHOCARD_HAS_EXTERNAL_CLOCK + +/******************* Select input clock source *******************/ +static int snd_echo_clock_source_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static char *names[8] = { + "Internal", "Word", "Super", "S/PDIF", "ADAT", "ESync", + "ESync96", "MTC" + }; + struct echoaudio *chip; + + chip = snd_kcontrol_chip(kcontrol); + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->value.enumerated.items = chip->num_clock_sources; + uinfo->count = 1; + if (uinfo->value.enumerated.item >= chip->num_clock_sources) + uinfo->value.enumerated.item = chip->num_clock_sources - 1; + strcpy(uinfo->value.enumerated.name, names[ + chip->clock_source_list[uinfo->value.enumerated.item]]); + return 0; +} + +static int snd_echo_clock_source_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + int i, clock; + + chip = snd_kcontrol_chip(kcontrol); + clock = chip->input_clock; + + for (i = 0; i < chip->num_clock_sources; i++) + if (clock == chip->clock_source_list[i]) + ucontrol->value.enumerated.item[0] = i; + + return 0; +} + +static int snd_echo_clock_source_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + int changed; + unsigned int eclock, dclock; + + changed = 0; + chip = snd_kcontrol_chip(kcontrol); + eclock = ucontrol->value.enumerated.item[0]; + if (eclock >= chip->input_clock_types) + return -EINVAL; + dclock = chip->clock_source_list[eclock]; + if (chip->input_clock != dclock) { + down(&chip->mode_mutex); + spin_lock_irq(&chip->lock); + if ((changed = set_input_clock(chip, dclock)) == 0) + changed = 1; /* no errors */ + spin_unlock_irq(&chip->lock); + up(&chip->mode_mutex); + } + + if (changed < 0) + DE_ACT(("seticlk val%d err 0x%x\n", dclock, changed)); + + return changed; +} + +static struct snd_kcontrol_new snd_echo_clock_source_switch __devinitdata = { + .name = "Sample Clock Source", + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .info = snd_echo_clock_source_info, + .get = snd_echo_clock_source_get, + .put = snd_echo_clock_source_put, +}; + +#endif /* ECHOCARD_HAS_EXTERNAL_CLOCK */ + + + +#ifdef ECHOCARD_HAS_PHANTOM_POWER + +/******************* Phantom power switch *******************/ +static int snd_echo_phantom_power_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int snd_echo_phantom_power_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = chip->phantom_power; + return 0; +} + +static int snd_echo_phantom_power_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip = snd_kcontrol_chip(kcontrol); + int power, changed = 0; + + power = !!ucontrol->value.integer.value[0]; + if (chip->phantom_power != power) { + spin_lock_irq(&chip->lock); + changed = set_phantom_power(chip, power); + spin_unlock_irq(&chip->lock); + if (changed == 0) + changed = 1; /* no errors */ + } + return changed; +} + +static struct snd_kcontrol_new snd_echo_phantom_power_switch __devinitdata = { + .name = "Phantom power Switch", + .iface = SNDRV_CTL_ELEM_IFACE_CARD, + .info = snd_echo_phantom_power_info, + .get = snd_echo_phantom_power_get, + .put = snd_echo_phantom_power_put, +}; + +#endif /* ECHOCARD_HAS_PHANTOM_POWER */ + + + +#ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE + +/******************* Digital input automute switch *******************/ +static int snd_echo_automute_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int snd_echo_automute_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip = snd_kcontrol_chip(kcontrol); + + ucontrol->value.integer.value[0] = chip->digital_in_automute; + return 0; +} + +static int snd_echo_automute_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip = snd_kcontrol_chip(kcontrol); + int automute, changed = 0; + + automute = !!ucontrol->value.integer.value[0]; + if (chip->digital_in_automute != automute) { + spin_lock_irq(&chip->lock); + changed = set_input_auto_mute(chip, automute); + spin_unlock_irq(&chip->lock); + if (changed == 0) + changed = 1; /* no errors */ + } + return changed; +} + +static struct snd_kcontrol_new snd_echo_automute_switch __devinitdata = { + .name = "Digital Capture Switch (automute)", + .iface = SNDRV_CTL_ELEM_IFACE_CARD, + .info = snd_echo_automute_info, + .get = snd_echo_automute_get, + .put = snd_echo_automute_put, +}; + +#endif /* ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE */ + + + +/******************* VU-meters switch *******************/ +static int snd_echo_vumeters_switch_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct echoaudio *chip; + + chip = snd_kcontrol_chip(kcontrol); + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int snd_echo_vumeters_switch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + + chip = snd_kcontrol_chip(kcontrol); + spin_lock_irq(&chip->lock); + set_meters_on(chip, ucontrol->value.integer.value[0]); + spin_unlock_irq(&chip->lock); + return 1; +} + +static struct snd_kcontrol_new snd_echo_vumeters_switch __devinitdata = { + .name = "VU-meters Switch", + .iface = SNDRV_CTL_ELEM_IFACE_CARD, + .access = SNDRV_CTL_ELEM_ACCESS_WRITE, + .info = snd_echo_vumeters_switch_info, + .put = snd_echo_vumeters_switch_put, +}; + + + +/***** Read VU-meters (input, output, analog and digital together) *****/ +static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct echoaudio *chip; + + chip = snd_kcontrol_chip(kcontrol); + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 96; + uinfo->value.integer.min = ECHOGAIN_MINOUT; + uinfo->value.integer.max = 0; +#ifdef ECHOCARD_HAS_VMIXER + uinfo->dimen.d[0] = 3; /* Out, In, Virt */ +#else + uinfo->dimen.d[0] = 2; /* Out, In */ +#endif + uinfo->dimen.d[1] = 16; /* 16 channels */ + uinfo->dimen.d[2] = 2; /* 0=level, 1=peak */ + return 0; +} + +static int snd_echo_vumeters_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + + chip = snd_kcontrol_chip(kcontrol); + get_audio_meters(chip, ucontrol->value.integer.value); + return 0; +} + +static struct snd_kcontrol_new snd_echo_vumeters __devinitdata = { + .name = "VU-meters", + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = snd_echo_vumeters_info, + .get = snd_echo_vumeters_get, +}; + + + +/*** Channels info - it exports informations about the number of channels ***/ +static int snd_echo_channels_info_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct echoaudio *chip; + + chip = snd_kcontrol_chip(kcontrol); + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 6; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1 << ECHO_CLOCK_NUMBER; + return 0; +} + +static int snd_echo_channels_info_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct echoaudio *chip; + int detected, clocks, bit, src; + + chip = snd_kcontrol_chip(kcontrol); + ucontrol->value.integer.value[0] = num_busses_in(chip); + ucontrol->value.integer.value[1] = num_analog_busses_in(chip); + ucontrol->value.integer.value[2] = num_busses_out(chip); + ucontrol->value.integer.value[3] = num_analog_busses_out(chip); + ucontrol->value.integer.value[4] = num_pipes_out(chip); + + /* Compute the bitmask of the currently valid input clocks */ + detected = detect_input_clocks(chip); + clocks = 0; + src = chip->num_clock_sources - 1; + for (bit = ECHO_CLOCK_NUMBER - 1; bit >= 0; bit--) + if (detected & (1 << bit)) + for (; src >= 0; src--) + if (bit == chip->clock_source_list[src]) { + clocks |= 1 << src; + break; + } + ucontrol->value.integer.value[5] = clocks; + + return 0; +} + +static struct snd_kcontrol_new snd_echo_channels_info __devinitdata = { + .name = "Channels info", + .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, + .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, + .info = snd_echo_channels_info_info, + .get = snd_echo_channels_info_get, +}; + + + + +/****************************************************************************** + IRQ Handler +******************************************************************************/ + +static irqreturn_t snd_echo_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + struct echoaudio *chip = dev_id; + struct snd_pcm_substream *substream; + int period, ss, st; + + spin_lock(&chip->lock); + st = service_irq(chip); + if (st < 0) { + spin_unlock(&chip->lock); + return IRQ_NONE; + } + /* The hardware doesn't tell us which substream caused the irq, + thus we have to check all running substreams. */ + for (ss = 0; ss < DSP_MAXPIPES; ss++) { + if ((substream = chip->substream[ss])) { + period = pcm_pointer(substream) / + substream->runtime->period_size; + if (period != chip->last_period[ss]) { + chip->last_period[ss] = period; + spin_unlock(&chip->lock); + snd_pcm_period_elapsed(substream); + spin_lock(&chip->lock); + } + } + } + spin_unlock(&chip->lock); + +#ifdef ECHOCARD_HAS_MIDI + if (st > 0 && chip->midi_in) { + snd_rawmidi_receive(chip->midi_in, chip->midi_buffer, st); + DE_MID(("rawmidi_iread=%d\n", st)); + } +#endif + return IRQ_HANDLED; +} + + + + +/****************************************************************************** + Module construction / destruction +******************************************************************************/ + +static int snd_echo_free(struct echoaudio *chip) +{ + DE_INIT(("Stop DSP...\n")); + if (chip->comm_page) { + rest_in_peace(chip); + snd_dma_free_pages(&chip->commpage_dma_buf); + } + DE_INIT(("Stopped.\n")); + + if (chip->irq >= 0) + free_irq(chip->irq, (void *)chip); + + if (chip->dsp_registers) + iounmap(chip->dsp_registers); + + if (chip->iores) + release_and_free_resource(chip->iores); + + DE_INIT(("MMIO freed.\n")); + + pci_disable_device(chip->pci); + + /* release chip data */ + kfree(chip); + DE_INIT(("Chip freed.\n")); + return 0; +} + + + +static int snd_echo_dev_free(struct snd_device *device) +{ + struct echoaudio *chip = device->device_data; + + DE_INIT(("snd_echo_dev_free()...\n")); + return snd_echo_free(chip); +} + + + +/* <--snd_echo_probe() */ +static __devinit int snd_echo_create(struct snd_card *card, + struct pci_dev *pci, + struct echoaudio **rchip) +{ + struct echoaudio *chip; + int err; + size_t sz; + static struct snd_device_ops ops = { + .dev_free = snd_echo_dev_free, + }; + + *rchip = NULL; + + pci_write_config_byte(pci, PCI_LATENCY_TIMER, 0xC0); + + if ((err = pci_enable_device(pci)) < 0) + return err; + pci_set_master(pci); + + /* allocate a chip-specific data */ + chip = kzalloc(sizeof(*chip), GFP_KERNEL); + if (!chip) { + pci_disable_device(pci); + return -ENOMEM; + } + DE_INIT(("chip=%p\n", chip)); + + spin_lock_init(&chip->lock); + chip->card = card; + chip->pci = pci; + chip->irq = -1; + + /* PCI resource allocation */ + chip->dsp_registers_phys = pci_resource_start(pci, 0); + sz = pci_resource_len(pci, 0); + if (sz > PAGE_SIZE) + sz = PAGE_SIZE; /* We map only the required part */ + + if ((chip->iores = request_mem_region(chip->dsp_registers_phys, sz, + ECHOCARD_NAME)) == NULL) { + snd_echo_free(chip); + snd_printk(KERN_ERR "cannot get memory region\n"); + return -EBUSY; + } + chip->dsp_registers = (volatile u32 __iomem *) + ioremap_nocache(chip->dsp_registers_phys, sz); + + if (request_irq(pci->irq, snd_echo_interrupt, IRQF_DISABLED | IRQF_SHARED, + ECHOCARD_NAME, (void *)chip)) { + snd_echo_free(chip); + snd_printk(KERN_ERR "cannot grab irq\n"); + return -EBUSY; + } + chip->irq = pci->irq; + DE_INIT(("pci=%p irq=%d subdev=%04x Init hardware...\n", + chip->pci, chip->irq, chip->pci->subsystem_device)); + + /* Create the DSP comm page - this is the area of memory used for most + of the communication with the DSP, which accesses it via bus mastering */ + if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci), + sizeof(struct comm_page), + &chip->commpage_dma_buf) < 0) { + snd_echo_free(chip); + snd_printk(KERN_ERR "cannot allocate the comm page\n"); + return -ENOMEM; + } + chip->comm_page_phys = chip->commpage_dma_buf.addr; + chip->comm_page = (struct comm_page *)chip->commpage_dma_buf.area; + + err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device); + if (err) { + DE_INIT(("init_hw err=%d\n", err)); + snd_echo_free(chip); + return err; + } + DE_INIT(("Card init OK\n")); + + if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + snd_echo_free(chip); + return err; + } + atomic_set(&chip->opencount, 0); + init_MUTEX(&chip->mode_mutex); + chip->can_set_rate = 1; + *rchip = chip; + /* Init done ! */ + return 0; +} + + + +/* constructor */ +static int __devinit snd_echo_probe(struct pci_dev *pci, + const struct pci_device_id *pci_id) +{ + static int dev; + struct snd_card *card; + struct echoaudio *chip; + char *dsp; + int i, err; + + if (dev >= SNDRV_CARDS) + return -ENODEV; + if (!enable[dev]) { + dev++; + return -ENOENT; + } + + DE_INIT(("Echoaudio driver starting...\n")); + i = 0; + card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + if (card == NULL) + return -ENOMEM; + + if ((err = snd_echo_create(card, pci, &chip)) < 0) { + snd_card_free(card); + return err; + } + + strcpy(card->driver, "Echo_" ECHOCARD_NAME); + strcpy(card->shortname, chip->card_name); + + dsp = "56301"; + if (pci_id->device == 0x3410) + dsp = "56361"; + + sprintf(card->longname, "%s rev.%d (DSP%s) at 0x%lx irq %i", + card->shortname, pci_id->subdevice & 0x000f, dsp, + chip->dsp_registers_phys, chip->irq); + + if ((err = snd_echo_new_pcm(chip)) < 0) { + snd_printk(KERN_ERR "new pcm error %d\n", err); + snd_card_free(card); + return err; + } + +#ifdef ECHOCARD_HAS_MIDI + if (chip->has_midi) { /* Some Mia's do not have midi */ + if ((err = snd_echo_midi_create(card, chip)) < 0) { + snd_printk(KERN_ERR "new midi error %d\n", err); + snd_card_free(card); + return err; + } + } +#endif + +#ifdef ECHOCARD_HAS_VMIXER + snd_echo_vmixer.count = num_pipes_out(chip) * num_busses_out(chip); + if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_output_gain, chip))) < 0) + goto ctl_error; + if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vmixer, chip))) < 0) + goto ctl_error; +#else + if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_pcm_output_gain, chip))) < 0) + goto ctl_error; +#endif + +#ifdef ECHOCARD_HAS_INPUT_GAIN + if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_line_input_gain, chip))) < 0) + goto ctl_error; +#endif + +#ifdef ECHOCARD_HAS_INPUT_NOMINAL_LEVEL + if (!chip->hasnt_input_nominal_level) + if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_intput_nominal_level, chip))) < 0) + goto ctl_error; +#endif + +#ifdef ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL + if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_output_nominal_level, chip))) < 0) + goto ctl_error; +#endif + + if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters_switch, chip))) < 0) + goto ctl_error; + + if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_vumeters, chip))) < 0) + goto ctl_error; + +#ifdef ECHOCARD_HAS_MONITOR + snd_echo_monitor_mixer.count = num_busses_in(chip) * num_busses_out(chip); + if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_monitor_mixer, chip))) < 0) + goto ctl_error; +#endif + +#ifdef ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE + if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_automute_switch, chip))) < 0) + goto ctl_error; +#endif + + if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_channels_info, chip))) < 0) + goto ctl_error; + +#ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH + /* Creates a list of available digital modes */ + chip->num_digital_modes = 0; + for (i = 0; i < 6; i++) + if (chip->digital_modes & (1 << i)) + chip->digital_mode_list[chip->num_digital_modes++] = i; + + if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_digital_mode_switch, chip))) < 0) + goto ctl_error; +#endif /* ECHOCARD_HAS_DIGITAL_MODE_SWITCH */ + +#ifdef ECHOCARD_HAS_EXTERNAL_CLOCK + /* Creates a list of available clock sources */ + chip->num_clock_sources = 0; + for (i = 0; i < 10; i++) + if (chip->input_clock_types & (1 << i)) + chip->clock_source_list[chip->num_clock_sources++] = i; + + if (chip->num_clock_sources > 1) { + chip->clock_src_ctl = snd_ctl_new1(&snd_echo_clock_source_switch, chip); + if ((err = snd_ctl_add(chip->card, chip->clock_src_ctl)) < 0) + goto ctl_error; + } +#endif /* ECHOCARD_HAS_EXTERNAL_CLOCK */ + +#ifdef ECHOCARD_HAS_DIGITAL_IO + if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_spdif_mode_switch, chip))) < 0) + goto ctl_error; +#endif + +#ifdef ECHOCARD_HAS_PHANTOM_POWER + if (chip->has_phantom_power) + if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_echo_phantom_power_switch, chip))) < 0) + goto ctl_error; +#endif + + if ((err = snd_card_register(card)) < 0) { + snd_card_free(card); + goto ctl_error; + } + snd_printk(KERN_INFO "Card registered: %s\n", card->longname); + + pci_set_drvdata(pci, chip); + dev++; + return 0; + +ctl_error: + snd_printk(KERN_ERR "new control error %d\n", err); + snd_card_free(card); + return err; +} + + + +static void __devexit snd_echo_remove(struct pci_dev *pci) +{ + struct echoaudio *chip; + + chip = pci_get_drvdata(pci); + if (chip) + snd_card_free(chip->card); + pci_set_drvdata(pci, NULL); +} + + + +/****************************************************************************** + Everything starts and ends here +******************************************************************************/ + +/* pci_driver definition */ +static struct pci_driver driver = { + .name = "Echoaudio " ECHOCARD_NAME, + .id_table = snd_echo_ids, + .probe = snd_echo_probe, + .remove = __devexit_p(snd_echo_remove), +}; + + + +/* initialization of the module */ +static int __init alsa_card_echo_init(void) +{ + return pci_register_driver(&driver); +} + + + +/* clean up the module */ +static void __exit alsa_card_echo_exit(void) +{ + pci_unregister_driver(&driver); +} + + +module_init(alsa_card_echo_init) +module_exit(alsa_card_echo_exit) diff --git a/sound/pci/echoaudio/echoaudio.h b/sound/pci/echoaudio/echoaudio.h new file mode 100644 index 000000000..7e88c968e --- /dev/null +++ b/sound/pci/echoaudio/echoaudio.h @@ -0,0 +1,590 @@ +/**************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + **************************************************************************** + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + + **************************************************************************** + + + Here's a block diagram of how most of the cards work: + + +-----------+ + record | |<-------------------- Inputs + <-------| | | + PCI | Transport | | + bus | engine | \|/ + ------->| | +-------+ + play | |--->|monitor|-------> Outputs + +-----------+ | mixer | + +-------+ + + The lines going to and from the PCI bus represent "pipes". A pipe performs + audio transport - moving audio data to and from buffers on the host via + bus mastering. + + The inputs and outputs on the right represent input and output "busses." + A bus is a physical, real connection to the outside world. An example + of a bus would be the 1/4" analog connectors on the back of Layla or + an RCA S/PDIF connector. + + For most cards, there is a one-to-one correspondence between outputs + and busses; that is, each individual pipe is hard-wired to a single bus. + + Cards that work this way are Darla20, Gina20, Layla20, Darla24, Gina24, + Layla24, Mona, and Indigo. + + + Mia has a feature called "virtual outputs." + + + +-----------+ + record | |<----------------------------- Inputs + <-------| | | + PCI | Transport | | + bus | engine | \|/ + ------->| | +------+ +-------+ + play | |-->|vmixer|-->|monitor|-------> Outputs + +-----------+ +------+ | mixer | + +-------+ + + + Obviously, the difference here is the box labeled "vmixer." Vmixer is + short for "virtual output mixer." For Mia, pipes are *not* hard-wired + to a single bus; the vmixer lets you mix any pipe to any bus in any + combination. + + Note, however, that the left-hand side of the diagram is unchanged. + Transport works exactly the same way - the difference is in the mixer stage. + + + Pipes and busses are numbered starting at zero. + + + + Pipe index + ========== + + A number of calls in CEchoGals refer to a "pipe index". A pipe index is + a unique number for a pipe that unambiguously refers to a playback or record + pipe. Pipe indices are numbered starting with analog outputs, followed by + digital outputs, then analog inputs, then digital inputs. + + Take Gina24 as an example: + + Pipe index + + 0-7 Analog outputs (0 .. FirstDigitalBusOut-1) + 8-15 Digital outputs (FirstDigitalBusOut .. NumBussesOut-1) + 16-17 Analog inputs + 18-25 Digital inputs + + + You get the pipe index by calling CEchoGals::OpenAudio; the other transport + functions take the pipe index as a parameter. If you need a pipe index for + some other reason, use the handy Makepipe_index method. + + + Some calls take a CChannelMask parameter; CChannelMask is a handy way to + group pipe indices. + + + + Digital mode switch + =================== + + Some cards (right now, Gina24, Layla24, and Mona) have a Digital Mode Switch + or DMS. Cards with a DMS can be set to one of three mutually exclusive + digital modes: S/PDIF RCA, S/PDIF optical, or ADAT optical. + + This may create some confusion since ADAT optical is 8 channels wide and + S/PDIF is only two channels wide. Gina24, Layla24, and Mona handle this + by acting as if they always have 8 digital outs and ins. If you are in + either S/PDIF mode, the last 6 channels don't do anything - data sent + out these channels is thrown away and you will always record zeros. + + Note that with Gina24, Layla24, and Mona, sample rates above 50 kHz are + only available if you have the card configured for S/PDIF optical or S/PDIF + RCA. + + + + Double speed mode + ================= + + Some of the cards support 88.2 kHz and 96 kHz sampling (Darla24, Gina24, + Layla24, Mona, Mia, and Indigo). For these cards, the driver sometimes has + to worry about "double speed mode"; double speed mode applies whenever the + sampling rate is above 50 kHz. + + For instance, Mona and Layla24 support word clock sync. However, they + actually support two different word clock modes - single speed (below + 50 kHz) and double speed (above 50 kHz). The hardware detects if a single + or double speed word clock signal is present; the generic code uses that + information to determine which mode to use. + + The generic code takes care of all this for you. +*/ + + +#ifndef _ECHOAUDIO_H_ +#define _ECHOAUDIO_H_ + + +#define TRUE 1 +#define FALSE 0 + +#include "echoaudio_dsp.h" + + + +/*********************************************************************** + + PCI configuration space + +***********************************************************************/ + +/* + * PCI vendor ID and device IDs for the hardware + */ +#define VENDOR_ID 0x1057 +#define DEVICE_ID_56301 0x1801 +#define DEVICE_ID_56361 0x3410 +#define SUBVENDOR_ID 0xECC0 + + +/* + * Valid Echo PCI subsystem card IDs + */ +#define DARLA20 0x0010 +#define GINA20 0x0020 +#define LAYLA20 0x0030 +#define DARLA24 0x0040 +#define GINA24 0x0050 +#define LAYLA24 0x0060 +#define MONA 0x0070 +#define MIA 0x0080 +#define INDIGO 0x0090 +#define INDIGO_IO 0x00a0 +#define INDIGO_DJ 0x00b0 +#define ECHO3G 0x0100 + + +/************************************************************************ + + Array sizes and so forth + +***********************************************************************/ + +/* + * Sizes + */ +#define ECHO_MAXAUDIOINPUTS 32 /* Max audio input channels */ +#define ECHO_MAXAUDIOOUTPUTS 32 /* Max audio output channels */ +#define ECHO_MAXAUDIOPIPES 32 /* Max number of input and output + * pipes */ +#define E3G_MAX_OUTPUTS 16 +#define ECHO_MAXMIDIJACKS 1 /* Max MIDI ports */ +#define ECHO_MIDI_QUEUE_SZ 512 /* Max MIDI input queue entries */ +#define ECHO_MTC_QUEUE_SZ 32 /* Max MIDI time code input queue + * entries */ + +/* + * MIDI activity indicator timeout + */ +#define MIDI_ACTIVITY_TIMEOUT_USEC 200000 + + +/**************************************************************************** + + Clocks + +*****************************************************************************/ + +/* + * Clock numbers + */ +#define ECHO_CLOCK_INTERNAL 0 +#define ECHO_CLOCK_WORD 1 +#define ECHO_CLOCK_SUPER 2 +#define ECHO_CLOCK_SPDIF 3 +#define ECHO_CLOCK_ADAT 4 +#define ECHO_CLOCK_ESYNC 5 +#define ECHO_CLOCK_ESYNC96 6 +#define ECHO_CLOCK_MTC 7 +#define ECHO_CLOCK_NUMBER 8 +#define ECHO_CLOCKS 0xffff + +/* + * Clock bit numbers - used to report capabilities and whatever clocks + * are being detected dynamically. + */ +#define ECHO_CLOCK_BIT_INTERNAL (1 << ECHO_CLOCK_INTERNAL) +#define ECHO_CLOCK_BIT_WORD (1 << ECHO_CLOCK_WORD) +#define ECHO_CLOCK_BIT_SUPER (1 << ECHO_CLOCK_SUPER) +#define ECHO_CLOCK_BIT_SPDIF (1 << ECHO_CLOCK_SPDIF) +#define ECHO_CLOCK_BIT_ADAT (1 << ECHO_CLOCK_ADAT) +#define ECHO_CLOCK_BIT_ESYNC (1 << ECHO_CLOCK_ESYNC) +#define ECHO_CLOCK_BIT_ESYNC96 (1 << ECHO_CLOCK_ESYNC96) +#define ECHO_CLOCK_BIT_MTC (1<<ECHO_CLOCK_MTC) + + +/*************************************************************************** + + Digital modes + +****************************************************************************/ + +/* + * Digital modes for Mona, Layla24, and Gina24 + */ +#define DIGITAL_MODE_NONE 0xFF +#define DIGITAL_MODE_SPDIF_RCA 0 +#define DIGITAL_MODE_SPDIF_OPTICAL 1 +#define DIGITAL_MODE_ADAT 2 +#define DIGITAL_MODE_SPDIF_CDROM 3 +#define DIGITAL_MODES 4 + +/* + * Digital mode capability masks + */ +#define ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA (1 << DIGITAL_MODE_SPDIF_RCA) +#define ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL (1 << DIGITAL_MODE_SPDIF_OPTICAL) +#define ECHOCAPS_HAS_DIGITAL_MODE_ADAT (1 << DIGITAL_MODE_ADAT) +#define ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_CDROM (1 << DIGITAL_MODE_SPDIF_CDROM) + + +#define EXT_3GBOX_NC 0x01 /* 3G box not connected */ +#define EXT_3GBOX_NOT_SET 0x02 /* 3G box not detected yet */ + + +#define ECHOGAIN_MUTED (-128) /* Minimum possible gain */ +#define ECHOGAIN_MINOUT (-128) /* Min output gain (dB) */ +#define ECHOGAIN_MAXOUT (6) /* Max output gain (dB) */ +#define ECHOGAIN_MININP (-50) /* Min input gain (0.5 dB) */ +#define ECHOGAIN_MAXINP (50) /* Max input gain (0.5 dB) */ + +#define PIPE_STATE_STOPPED 0 /* Pipe has been reset */ +#define PIPE_STATE_PAUSED 1 /* Pipe has been stopped */ +#define PIPE_STATE_STARTED 2 /* Pipe has been started */ +#define PIPE_STATE_PENDING 3 /* Pipe has pending start */ + + +/* Debug initialization */ +#ifdef CONFIG_SND_DEBUG +#define DE_INIT(x) snd_printk x +#else +#define DE_INIT(x) +#endif + +/* Debug hw_params callbacks */ +#ifdef CONFIG_SND_DEBUG +#define DE_HWP(x) snd_printk x +#else +#define DE_HWP(x) +#endif + +/* Debug normal activity (open, start, stop...) */ +#ifdef CONFIG_SND_DEBUG +#define DE_ACT(x) snd_printk x +#else +#define DE_ACT(x) +#endif + +/* Debug midi activity */ +#ifdef CONFIG_SND_DEBUG +#define DE_MID(x) snd_printk x +#else +#define DE_MID(x) +#endif + + +struct audiopipe { + volatile u32 *dma_counter; /* Commpage register that contains + * the current dma position + * (lower 32 bits only) + */ + u32 last_counter; /* The last position, which is used + * to compute... + */ + u32 position; /* ...the number of bytes tranferred + * by the DMA engine, modulo the + * buffer size + */ + short index; /* Index of the first channel or <0 + * if hw is not configured yet + */ + short interleave; + struct snd_dma_buffer sgpage; /* Room for the scatter-gather list */ + struct snd_pcm_hardware hw; + struct snd_pcm_hw_constraint_list constr; + short sglist_head; + char state; /* pipe state */ +}; + + +struct audioformat { + u8 interleave; /* How the data is arranged in memory: + * mono = 1, stereo = 2, ... + */ + u8 bits_per_sample; /* 8, 16, 24, 32 (24 bits left aligned) */ + char mono_to_stereo; /* Only used if interleave is 1 and + * if this is an output pipe. + */ + char data_are_bigendian; /* 1 = big endian, 0 = little endian */ +}; + + +struct echoaudio { + spinlock_t lock; + struct snd_pcm_substream *substream[DSP_MAXPIPES]; + int last_period[DSP_MAXPIPES]; + struct semaphore mode_mutex; + u16 num_digital_modes, digital_mode_list[6]; + u16 num_clock_sources, clock_source_list[10]; + atomic_t opencount; + struct snd_kcontrol *clock_src_ctl; + struct snd_pcm *analog_pcm, *digital_pcm; + struct snd_card *card; + const char *card_name; + struct pci_dev *pci; + unsigned long dsp_registers_phys; + struct resource *iores; + struct snd_dma_buffer commpage_dma_buf; + int irq; +#ifdef ECHOCARD_HAS_MIDI + struct snd_rawmidi *rmidi; + struct snd_rawmidi_substream *midi_in, *midi_out; +#endif + struct timer_list timer; + char tinuse; /* Timer in use */ + char midi_full; /* MIDI output buffer is full */ + char can_set_rate; + char rate_set; + + /* This stuff is used mainly by the lowlevel code */ + struct comm_page *comm_page; /* Virtual address of the memory + * seen by DSP + */ + u32 pipe_alloc_mask; /* Bitmask of allocated pipes */ + u32 pipe_cyclic_mask; /* Bitmask of pipes with cyclic + * buffers + */ + u32 sample_rate; /* Card sample rate in Hz */ + u8 digital_mode; /* Current digital mode + * (see DIGITAL_MODE_*) + */ + u8 spdif_status; /* Gina20, Darla20, Darla24 - only */ + u8 clock_state; /* Gina20, Darla20, Darla24 - only */ + u8 input_clock; /* Currently selected sample clock + * source + */ + u8 output_clock; /* Layla20 only */ + char meters_enabled; /* VU-meters status */ + char asic_loaded; /* Set TRUE when ASIC loaded */ + char bad_board; /* Set TRUE if DSP won't load */ + char professional_spdif; /* 0 = consumer; 1 = professional */ + char non_audio_spdif; /* 3G - only */ + char digital_in_automute; /* Gina24, Layla24, Mona - only */ + char has_phantom_power; + char hasnt_input_nominal_level; /* Gina3G */ + char phantom_power; /* Gina3G - only */ + char has_midi; + char midi_input_enabled; + +#ifdef ECHOCARD_ECHO3G + /* External module -dependent pipe and bus indexes */ + char px_digital_out, px_analog_in, px_digital_in, px_num; + char bx_digital_out, bx_analog_in, bx_digital_in, bx_num; +#endif + + char nominal_level[ECHO_MAXAUDIOPIPES]; /* True == -10dBV + * False == +4dBu */ + s8 input_gain[ECHO_MAXAUDIOINPUTS]; /* Input level -50..+50 + * unit is 0.5dB */ + s8 output_gain[ECHO_MAXAUDIOOUTPUTS]; /* Output level -128..+6 dB + * (-128=muted) */ + s8 monitor_gain[ECHO_MAXAUDIOOUTPUTS][ECHO_MAXAUDIOINPUTS]; + /* -128..+6 dB */ + s8 vmixer_gain[ECHO_MAXAUDIOOUTPUTS][ECHO_MAXAUDIOOUTPUTS]; + /* -128..+6 dB */ + + u16 digital_modes; /* Bitmask of supported modes + * (see ECHOCAPS_HAS_DIGITAL_MODE_*) */ + u16 input_clock_types; /* Suppoted input clock types */ + u16 output_clock_types; /* Suppoted output clock types - + * Layla20 only */ + u16 device_id, subdevice_id; + u16 *dsp_code; /* Current DSP code loaded, + * NULL if nothing loaded */ + const struct firmware *dsp_code_to_load;/* DSP code to load */ + const struct firmware *asic_code; /* Current ASIC code */ + u32 comm_page_phys; /* Physical address of the + * memory seen by DSP */ + volatile u32 __iomem *dsp_registers; /* DSP's register base */ + u32 active_mask; /* Chs. active mask or + * punks out */ + +#ifdef ECHOCARD_HAS_MIDI + u16 mtc_state; /* State for MIDI input parsing state machine */ + u8 midi_buffer[MIDI_IN_BUFFER_SIZE]; +#endif +}; + + +static int init_dsp_comm_page(struct echoaudio *chip); +static int init_line_levels(struct echoaudio *chip); +static int free_pipes(struct echoaudio *chip, struct audiopipe *pipe); +static int load_firmware(struct echoaudio *chip); +static int wait_handshake(struct echoaudio *chip); +static int send_vector(struct echoaudio *chip, u32 command); +static int get_firmware(const struct firmware **fw_entry, + const struct firmware *frm, struct echoaudio *chip); +static void free_firmware(const struct firmware *fw_entry); + +#ifdef ECHOCARD_HAS_MIDI +static int enable_midi_input(struct echoaudio *chip, char enable); +static int midi_service_irq(struct echoaudio *chip); +static int __devinit snd_echo_midi_create(struct snd_card *card, + struct echoaudio *chip); +#endif + + +static inline void clear_handshake(struct echoaudio *chip) +{ + chip->comm_page->handshake = 0; +} + +static inline u32 get_dsp_register(struct echoaudio *chip, u32 index) +{ + return readl(&chip->dsp_registers[index]); +} + +static inline void set_dsp_register(struct echoaudio *chip, u32 index, + u32 value) +{ + writel(value, &chip->dsp_registers[index]); +} + + +/* Pipe and bus indexes. PX_* and BX_* are defined as chip->px_* and chip->bx_* +for 3G cards because they depend on the external box. They are integer +constants for all other cards. +Never use those defines directly, use the following functions instead. */ + +static inline int px_digital_out(const struct echoaudio *chip) +{ + return PX_DIGITAL_OUT; +} + +static inline int px_analog_in(const struct echoaudio *chip) +{ + return PX_ANALOG_IN; +} + +static inline int px_digital_in(const struct echoaudio *chip) +{ + return PX_DIGITAL_IN; +} + +static inline int px_num(const struct echoaudio *chip) +{ + return PX_NUM; +} + +static inline int bx_digital_out(const struct echoaudio *chip) +{ + return BX_DIGITAL_OUT; +} + +static inline int bx_analog_in(const struct echoaudio *chip) +{ + return BX_ANALOG_IN; +} + +static inline int bx_digital_in(const struct echoaudio *chip) +{ + return BX_DIGITAL_IN; +} + +static inline int bx_num(const struct echoaudio *chip) +{ + return BX_NUM; +} + +static inline int num_pipes_out(const struct echoaudio *chip) +{ + return px_analog_in(chip); +} + +static inline int num_pipes_in(const struct echoaudio *chip) +{ + return px_num(chip) - px_analog_in(chip); +} + +static inline int num_busses_out(const struct echoaudio *chip) +{ + return bx_analog_in(chip); +} + +static inline int num_busses_in(const struct echoaudio *chip) +{ + return bx_num(chip) - bx_analog_in(chip); +} + +static inline int num_analog_busses_out(const struct echoaudio *chip) +{ + return bx_digital_out(chip); +} + +static inline int num_analog_busses_in(const struct echoaudio *chip) +{ + return bx_digital_in(chip) - bx_analog_in(chip); +} + +static inline int num_digital_busses_out(const struct echoaudio *chip) +{ + return num_busses_out(chip) - num_analog_busses_out(chip); +} + +static inline int num_digital_busses_in(const struct echoaudio *chip) +{ + return num_busses_in(chip) - num_analog_busses_in(chip); +} + +/* The monitor array is a one-dimensional array; compute the offset + * into the array */ +static inline int monitor_index(const struct echoaudio *chip, int out, int in) +{ + return out * num_busses_in(chip) + in; +} + + +#ifndef pci_device +#define pci_device(chip) (&chip->pci->dev) +#endif + + +#endif /* _ECHOAUDIO_H_ */ diff --git a/sound/pci/echoaudio/echoaudio_3g.c b/sound/pci/echoaudio/echoaudio_3g.c new file mode 100644 index 000000000..9f439ea45 --- /dev/null +++ b/sound/pci/echoaudio/echoaudio_3g.c @@ -0,0 +1,431 @@ +/**************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + ************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + +****************************************************************************/ + + + +/* These functions are common for all "3G" cards */ + + +static int check_asic_status(struct echoaudio *chip) +{ + u32 box_status; + + if (wait_handshake(chip)) + return -EIO; + + chip->comm_page->ext_box_status = + __constant_cpu_to_le32(E3G_ASIC_NOT_LOADED); + chip->asic_loaded = FALSE; + clear_handshake(chip); + send_vector(chip, DSP_VC_TEST_ASIC); + + if (wait_handshake(chip)) { + chip->dsp_code = NULL; + return -EIO; + } + + box_status = le32_to_cpu(chip->comm_page->ext_box_status); + DE_INIT(("box_status=%x\n", box_status)); + if (box_status == E3G_ASIC_NOT_LOADED) + return -ENODEV; + + chip->asic_loaded = TRUE; + return box_status & E3G_BOX_TYPE_MASK; +} + + + +static inline u32 get_frq_reg(struct echoaudio *chip) +{ + return le32_to_cpu(chip->comm_page->e3g_frq_register); +} + + + +/* Most configuration of 3G cards is accomplished by writing the control +register. write_control_reg sends the new control register value to the DSP. */ +static int write_control_reg(struct echoaudio *chip, u32 ctl, u32 frq, + char force) +{ + if (wait_handshake(chip)) + return -EIO; + + DE_ACT(("WriteControlReg: Setting 0x%x, 0x%x\n", ctl, frq)); + + ctl = cpu_to_le32(ctl); + frq = cpu_to_le32(frq); + + if (ctl != chip->comm_page->control_register || + frq != chip->comm_page->e3g_frq_register || force) { + chip->comm_page->e3g_frq_register = frq; + chip->comm_page->control_register = ctl; + clear_handshake(chip); + return send_vector(chip, DSP_VC_WRITE_CONTROL_REG); + } + + DE_ACT(("WriteControlReg: not written, no change\n")); + return 0; +} + + + +/* Set the digital mode - currently for Gina24, Layla24, Mona, 3G */ +static int set_digital_mode(struct echoaudio *chip, u8 mode) +{ + u8 previous_mode; + int err, i, o; + + /* All audio channels must be closed before changing the digital mode */ + snd_assert(!chip->pipe_alloc_mask, return -EAGAIN); + + snd_assert(chip->digital_modes & (1 << mode), return -EINVAL); + + previous_mode = chip->digital_mode; + err = dsp_set_digital_mode(chip, mode); + + /* If we successfully changed the digital mode from or to ADAT, + * then make sure all output, input and monitor levels are + * updated by the DSP comm object. */ + if (err >= 0 && previous_mode != mode && + (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) { + spin_lock_irq(&chip->lock); + for (o = 0; o < num_busses_out(chip); o++) + for (i = 0; i < num_busses_in(chip); i++) + set_monitor_gain(chip, o, i, + chip->monitor_gain[o][i]); + +#ifdef ECHOCARD_HAS_INPUT_GAIN + for (i = 0; i < num_busses_in(chip); i++) + set_input_gain(chip, i, chip->input_gain[i]); + update_input_line_level(chip); +#endif + + for (o = 0; o < num_busses_out(chip); o++) + set_output_gain(chip, o, chip->output_gain[o]); + update_output_line_level(chip); + spin_unlock_irq(&chip->lock); + } + + return err; +} + + + +static u32 set_spdif_bits(struct echoaudio *chip, u32 control_reg, u32 rate) +{ + control_reg &= E3G_SPDIF_FORMAT_CLEAR_MASK; + + switch (rate) { + case 32000 : + control_reg |= E3G_SPDIF_SAMPLE_RATE0 | E3G_SPDIF_SAMPLE_RATE1; + break; + case 44100 : + if (chip->professional_spdif) + control_reg |= E3G_SPDIF_SAMPLE_RATE0; + break; + case 48000 : + control_reg |= E3G_SPDIF_SAMPLE_RATE1; + break; + } + + if (chip->professional_spdif) + control_reg |= E3G_SPDIF_PRO_MODE; + + if (chip->non_audio_spdif) + control_reg |= E3G_SPDIF_NOT_AUDIO; + + control_reg |= E3G_SPDIF_24_BIT | E3G_SPDIF_TWO_CHANNEL | + E3G_SPDIF_COPY_PERMIT; + + return control_reg; +} + + + +/* Set the S/PDIF output format */ +static int set_professional_spdif(struct echoaudio *chip, char prof) +{ + u32 control_reg; + + control_reg = le32_to_cpu(chip->comm_page->control_register); + chip->professional_spdif = prof; + control_reg = set_spdif_bits(chip, control_reg, chip->sample_rate); + return write_control_reg(chip, control_reg, get_frq_reg(chip), 0); +} + + + +/* detect_input_clocks() returns a bitmask consisting of all the input clocks +currently connected to the hardware; this changes as the user connects and +disconnects clock inputs. You should use this information to determine which +clocks the user is allowed to select. */ +static u32 detect_input_clocks(const struct echoaudio *chip) +{ + u32 clocks_from_dsp, clock_bits; + + /* Map the DSP clock detect bits to the generic driver clock + * detect bits */ + clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); + + clock_bits = ECHO_CLOCK_BIT_INTERNAL; + + if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_WORD) + clock_bits |= ECHO_CLOCK_BIT_WORD; + + switch(chip->digital_mode) { + case DIGITAL_MODE_SPDIF_RCA: + case DIGITAL_MODE_SPDIF_OPTICAL: + if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_SPDIF) + clock_bits |= ECHO_CLOCK_BIT_SPDIF; + break; + case DIGITAL_MODE_ADAT: + if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_ADAT) + clock_bits |= ECHO_CLOCK_BIT_ADAT; + break; + } + + return clock_bits; +} + + + +static int load_asic(struct echoaudio *chip) +{ + int box_type, err; + + if (chip->asic_loaded) + return 0; + + /* Give the DSP a few milliseconds to settle down */ + mdelay(2); + + err = load_asic_generic(chip, DSP_FNC_LOAD_3G_ASIC, + &card_fw[FW_3G_ASIC]); + if (err < 0) + return err; + + chip->asic_code = &card_fw[FW_3G_ASIC]; + + /* Now give the new ASIC a little time to set up */ + mdelay(2); + /* See if it worked */ + box_type = check_asic_status(chip); + + /* Set up the control register if the load succeeded - + * 48 kHz, internal clock, S/PDIF RCA mode */ + if (box_type >= 0) { + err = write_control_reg(chip, E3G_48KHZ, + E3G_FREQ_REG_DEFAULT, TRUE); + if (err < 0) + return err; + } + + return box_type; +} + + + +static int set_sample_rate(struct echoaudio *chip, u32 rate) +{ + u32 control_reg, clock, base_rate, frq_reg; + + /* Only set the clock for internal mode. */ + if (chip->input_clock != ECHO_CLOCK_INTERNAL) { + DE_ACT(("set_sample_rate: Cannot set sample rate - " + "clock not set to CLK_CLOCKININTERNAL\n")); + /* Save the rate anyhow */ + chip->comm_page->sample_rate = cpu_to_le32(rate); + chip->sample_rate = rate; + set_input_clock(chip, chip->input_clock); + return 0; + } + + snd_assert(rate < 50000 || chip->digital_mode != DIGITAL_MODE_ADAT, + return -EINVAL); + + clock = 0; + control_reg = le32_to_cpu(chip->comm_page->control_register); + control_reg &= E3G_CLOCK_CLEAR_MASK; + + switch (rate) { + case 96000: + clock = E3G_96KHZ; + break; + case 88200: + clock = E3G_88KHZ; + break; + case 48000: + clock = E3G_48KHZ; + break; + case 44100: + clock = E3G_44KHZ; + break; + case 32000: + clock = E3G_32KHZ; + break; + default: + clock = E3G_CONTINUOUS_CLOCK; + if (rate > 50000) + clock |= E3G_DOUBLE_SPEED_MODE; + break; + } + + control_reg |= clock; + control_reg = set_spdif_bits(chip, control_reg, rate); + + base_rate = rate; + if (base_rate > 50000) + base_rate /= 2; + if (base_rate < 32000) + base_rate = 32000; + + frq_reg = E3G_MAGIC_NUMBER / base_rate - 2; + if (frq_reg > E3G_FREQ_REG_MAX) + frq_reg = E3G_FREQ_REG_MAX; + + chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ + chip->sample_rate = rate; + DE_ACT(("SetSampleRate: %d clock %x\n", rate, control_reg)); + + /* Tell the DSP about it - DSP reads both control reg & freq reg */ + return write_control_reg(chip, control_reg, frq_reg, 0); +} + + + +/* Set the sample clock source to internal, S/PDIF, ADAT */ +static int set_input_clock(struct echoaudio *chip, u16 clock) +{ + u32 control_reg, clocks_from_dsp; + + DE_ACT(("set_input_clock:\n")); + + /* Mask off the clock select bits */ + control_reg = le32_to_cpu(chip->comm_page->control_register) & + E3G_CLOCK_CLEAR_MASK; + clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); + + switch (clock) { + case ECHO_CLOCK_INTERNAL: + DE_ACT(("Set Echo3G clock to INTERNAL\n")); + chip->input_clock = ECHO_CLOCK_INTERNAL; + return set_sample_rate(chip, chip->sample_rate); + case ECHO_CLOCK_SPDIF: + if (chip->digital_mode == DIGITAL_MODE_ADAT) + return -EAGAIN; + DE_ACT(("Set Echo3G clock to SPDIF\n")); + control_reg |= E3G_SPDIF_CLOCK; + if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_SPDIF96) + control_reg |= E3G_DOUBLE_SPEED_MODE; + else + control_reg &= ~E3G_DOUBLE_SPEED_MODE; + break; + case ECHO_CLOCK_ADAT: + if (chip->digital_mode != DIGITAL_MODE_ADAT) + return -EAGAIN; + DE_ACT(("Set Echo3G clock to ADAT\n")); + control_reg |= E3G_ADAT_CLOCK; + control_reg &= ~E3G_DOUBLE_SPEED_MODE; + break; + case ECHO_CLOCK_WORD: + DE_ACT(("Set Echo3G clock to WORD\n")); + control_reg |= E3G_WORD_CLOCK; + if (clocks_from_dsp & E3G_CLOCK_DETECT_BIT_WORD96) + control_reg |= E3G_DOUBLE_SPEED_MODE; + else + control_reg &= ~E3G_DOUBLE_SPEED_MODE; + break; + default: + DE_ACT(("Input clock 0x%x not supported for Echo3G\n", clock)); + return -EINVAL; + } + + chip->input_clock = clock; + return write_control_reg(chip, control_reg, get_frq_reg(chip), 1); +} + + + +static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) +{ + u32 control_reg; + int err, incompatible_clock; + + /* Set clock to "internal" if it's not compatible with the new mode */ + incompatible_clock = FALSE; + switch (mode) { + case DIGITAL_MODE_SPDIF_OPTICAL: + case DIGITAL_MODE_SPDIF_RCA: + if (chip->input_clock == ECHO_CLOCK_ADAT) + incompatible_clock = TRUE; + break; + case DIGITAL_MODE_ADAT: + if (chip->input_clock == ECHO_CLOCK_SPDIF) + incompatible_clock = TRUE; + break; + default: + DE_ACT(("Digital mode not supported: %d\n", mode)); + return -EINVAL; + } + + spin_lock_irq(&chip->lock); + + if (incompatible_clock) { + chip->sample_rate = 48000; + set_input_clock(chip, ECHO_CLOCK_INTERNAL); + } + + /* Clear the current digital mode */ + control_reg = le32_to_cpu(chip->comm_page->control_register); + control_reg &= E3G_DIGITAL_MODE_CLEAR_MASK; + + /* Tweak the control reg */ + switch (mode) { + case DIGITAL_MODE_SPDIF_OPTICAL: + control_reg |= E3G_SPDIF_OPTICAL_MODE; + break; + case DIGITAL_MODE_SPDIF_RCA: + /* E3G_SPDIF_OPTICAL_MODE bit cleared */ + break; + case DIGITAL_MODE_ADAT: + control_reg |= E3G_ADAT_MODE; + control_reg &= ~E3G_DOUBLE_SPEED_MODE; /* @@ useless */ + break; + } + + err = write_control_reg(chip, control_reg, get_frq_reg(chip), 1); + spin_unlock_irq(&chip->lock); + if (err < 0) + return err; + chip->digital_mode = mode; + + DE_ACT(("set_digital_mode(%d)\n", chip->digital_mode)); + return incompatible_clock; +} diff --git a/sound/pci/echoaudio/echoaudio_dsp.c b/sound/pci/echoaudio/echoaudio_dsp.c new file mode 100644 index 000000000..42afa837d --- /dev/null +++ b/sound/pci/echoaudio/echoaudio_dsp.c @@ -0,0 +1,1125 @@ +/**************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + ************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + +****************************************************************************/ + +#if PAGE_SIZE < 4096 +#error PAGE_SIZE is < 4k +#endif + +static int restore_dsp_rettings(struct echoaudio *chip); + + +/* Some vector commands involve the DSP reading or writing data to and from the +comm page; if you send one of these commands to the DSP, it will complete the +command and then write a non-zero value to the Handshake field in the +comm page. This function waits for the handshake to show up. */ +static int wait_handshake(struct echoaudio *chip) +{ + int i; + + /* Wait up to 10ms for the handshake from the DSP */ + for (i = 0; i < HANDSHAKE_TIMEOUT; i++) { + /* Look for the handshake value */ + if (chip->comm_page->handshake) { + /*if (i) DE_ACT(("Handshake time: %d\n", i));*/ + return 0; + } + udelay(1); + } + + snd_printk(KERN_ERR "wait_handshake(): Timeout waiting for DSP\n"); + return -EBUSY; +} + + + +/* Much of the interaction between the DSP and the driver is done via vector +commands; send_vector writes a vector command to the DSP. Typically, this +causes the DSP to read or write fields in the comm page. +PCI posting is not required thanks to the handshake logic. */ +static int send_vector(struct echoaudio *chip, u32 command) +{ + int i; + + wmb(); /* Flush all pending writes before sending the command */ + + /* Wait up to 100ms for the "vector busy" bit to be off */ + for (i = 0; i < VECTOR_BUSY_TIMEOUT; i++) { + if (!(get_dsp_register(chip, CHI32_VECTOR_REG) & + CHI32_VECTOR_BUSY)) { + set_dsp_register(chip, CHI32_VECTOR_REG, command); + /*if (i) DE_ACT(("send_vector time: %d\n", i));*/ + return 0; + } + udelay(1); + } + + DE_ACT((KERN_ERR "timeout on send_vector\n")); + return -EBUSY; +} + + + +/* write_dsp writes a 32-bit value to the DSP; this is used almost +exclusively for loading the DSP. */ +static int write_dsp(struct echoaudio *chip, u32 data) +{ + u32 status, i; + + for (i = 0; i < 10000000; i++) { /* timeout = 10s */ + status = get_dsp_register(chip, CHI32_STATUS_REG); + if ((status & CHI32_STATUS_HOST_WRITE_EMPTY) != 0) { + set_dsp_register(chip, CHI32_DATA_REG, data); + wmb(); /* write it immediately */ + return 0; + } + udelay(1); + cond_resched(); + } + + chip->bad_board = TRUE; /* Set TRUE until DSP re-loaded */ + DE_ACT((KERN_ERR "write_dsp: Set bad_board to TRUE\n")); + return -EIO; +} + + + +/* read_dsp reads a 32-bit value from the DSP; this is used almost +exclusively for loading the DSP and checking the status of the ASIC. */ +static int read_dsp(struct echoaudio *chip, u32 *data) +{ + u32 status, i; + + for (i = 0; i < READ_DSP_TIMEOUT; i++) { + status = get_dsp_register(chip, CHI32_STATUS_REG); + if ((status & CHI32_STATUS_HOST_READ_FULL) != 0) { + *data = get_dsp_register(chip, CHI32_DATA_REG); + return 0; + } + udelay(1); + cond_resched(); + } + + chip->bad_board = TRUE; /* Set TRUE until DSP re-loaded */ + DE_INIT((KERN_ERR "read_dsp: Set bad_board to TRUE\n")); + return -EIO; +} + + + +/**************************************************************************** + Firmware loading functions + ****************************************************************************/ + +/* This function is used to read back the serial number from the DSP; +this is triggered by the SET_COMMPAGE_ADDR command. +Only some early Echogals products have serial numbers in the ROM; +the serial number is not used, but you still need to do this as +part of the DSP load process. */ +static int read_sn(struct echoaudio *chip) +{ + int i; + u32 sn[6]; + + for (i = 0; i < 5; i++) { + if (read_dsp(chip, &sn[i])) { + snd_printk(KERN_ERR "Failed to read serial number\n"); + return -EIO; + } + } + DE_INIT(("Read serial number %08x %08x %08x %08x %08x\n", + sn[0], sn[1], sn[2], sn[3], sn[4])); + return 0; +} + + + +#ifndef ECHOCARD_HAS_ASIC +/* This card has no ASIC, just return ok */ +static inline int check_asic_status(struct echoaudio *chip) +{ + chip->asic_loaded = TRUE; + return 0; +} + +#endif /* !ECHOCARD_HAS_ASIC */ + + + +#ifdef ECHOCARD_HAS_ASIC + +/* Load ASIC code - done after the DSP is loaded */ +static int load_asic_generic(struct echoaudio *chip, u32 cmd, + const struct firmware *asic) +{ + const struct firmware *fw; + int err; + u32 i, size; + u8 *code; + + if ((err = get_firmware(&fw, asic, chip)) < 0) { + snd_printk(KERN_WARNING "Firmware not found !\n"); + return err; + } + + code = (u8 *)fw->data; + size = fw->size; + + /* Send the "Here comes the ASIC" command */ + if (write_dsp(chip, cmd) < 0) + goto la_error; + + /* Write length of ASIC file in bytes */ + if (write_dsp(chip, size) < 0) + goto la_error; + + for (i = 0; i < size; i++) { + if (write_dsp(chip, code[i]) < 0) + goto la_error; + } + + DE_INIT(("ASIC loaded\n")); + free_firmware(fw); + return 0; + +la_error: + DE_INIT(("failed on write_dsp\n")); + free_firmware(fw); + return -EIO; +} + +#endif /* ECHOCARD_HAS_ASIC */ + + + +#ifdef DSP_56361 + +/* Install the resident loader for 56361 DSPs; The resident loader is on +the EPROM on the board for 56301 DSP. The resident loader is a tiny little +program that is used to load the real DSP code. */ +static int install_resident_loader(struct echoaudio *chip) +{ + u32 address; + int index, words, i; + u16 *code; + u32 status; + const struct firmware *fw; + + /* 56361 cards only! This check is required by the old 56301-based + Mona and Gina24 */ + if (chip->device_id != DEVICE_ID_56361) + return 0; + + /* Look to see if the resident loader is present. If the resident + loader is already installed, host flag 5 will be on. */ + status = get_dsp_register(chip, CHI32_STATUS_REG); + if (status & CHI32_STATUS_REG_HF5) { + DE_INIT(("Resident loader already installed; status is 0x%x\n", + status)); + return 0; + } + + if ((i = get_firmware(&fw, &card_fw[FW_361_LOADER], chip)) < 0) { + snd_printk(KERN_WARNING "Firmware not found !\n"); + return i; + } + + /* The DSP code is an array of 16 bit words. The array is divided up + into sections. The first word of each section is the size in words, + followed by the section type. + Since DSP addresses and data are 24 bits wide, they each take up two + 16 bit words in the array. + This is a lot like the other loader loop, but it's not a loop, you + don't write the memory type, and you don't write a zero at the end. */ + + /* Set DSP format bits for 24 bit mode */ + set_dsp_register(chip, CHI32_CONTROL_REG, + get_dsp_register(chip, CHI32_CONTROL_REG) | 0x900); + + code = (u16 *)fw->data; + + /* Skip the header section; the first word in the array is the size + of the first section, so the first real section of code is pointed + to by Code[0]. */ + index = code[0]; + + /* Skip the section size, LRS block type, and DSP memory type */ + index += 3; + + /* Get the number of DSP words to write */ + words = code[index++]; + + /* Get the DSP address for this block; 24 bits, so build from two words */ + address = ((u32)code[index] << 16) + code[index + 1]; + index += 2; + + /* Write the count to the DSP */ + if (write_dsp(chip, words)) { + DE_INIT(("install_resident_loader: Failed to write word count!\n")); + goto irl_error; + } + /* Write the DSP address */ + if (write_dsp(chip, address)) { + DE_INIT(("install_resident_loader: Failed to write DSP address!\n")); + goto irl_error; + } + /* Write out this block of code to the DSP */ + for (i = 0; i < words; i++) { + u32 data; + + data = ((u32)code[index] << 16) + code[index + 1]; + if (write_dsp(chip, data)) { + DE_INIT(("install_resident_loader: Failed to write DSP code\n")); + goto irl_error; + } + index += 2; + } + + /* Wait for flag 5 to come up */ + for (i = 0; i < 200; i++) { /* Timeout is 50us * 200 = 10ms */ + udelay(50); + status = get_dsp_register(chip, CHI32_STATUS_REG); + if (status & CHI32_STATUS_REG_HF5) + break; + } + + if (i == 200) { + DE_INIT(("Resident loader failed to set HF5\n")); + goto irl_error; + } + + DE_INIT(("Resident loader successfully installed\n")); + free_firmware(fw); + return 0; + +irl_error: + free_firmware(fw); + return -EIO; +} + +#endif /* DSP_56361 */ + + +static int load_dsp(struct echoaudio *chip, u16 *code) +{ + u32 address, data; + int index, words, i; + + if (chip->dsp_code == code) { + DE_INIT(("DSP is already loaded!\n")); + return 0; + } + chip->bad_board = TRUE; /* Set TRUE until DSP loaded */ + chip->dsp_code = NULL; /* Current DSP code not loaded */ + chip->asic_loaded = FALSE; /* Loading the DSP code will reset the ASIC */ + + DE_INIT(("load_dsp: Set bad_board to TRUE\n")); + + /* If this board requires a resident loader, install it. */ +#ifdef DSP_56361 + if ((i = install_resident_loader(chip)) < 0) + return i; +#endif + + /* Send software reset command */ + if (send_vector(chip, DSP_VC_RESET) < 0) { + DE_INIT(("LoadDsp: send_vector DSP_VC_RESET failed, Critical Failure\n")); + return -EIO; + } + /* Delay 10us */ + udelay(10); + + /* Wait 10ms for HF3 to indicate that software reset is complete */ + for (i = 0; i < 1000; i++) { /* Timeout is 10us * 1000 = 10ms */ + if (get_dsp_register(chip, CHI32_STATUS_REG) & + CHI32_STATUS_REG_HF3) + break; + udelay(10); + } + + if (i == 1000) { + DE_INIT(("load_dsp: Timeout waiting for CHI32_STATUS_REG_HF3\n")); + return -EIO; + } + + /* Set DSP format bits for 24 bit mode now that soft reset is done */ + set_dsp_register(chip, CHI32_CONTROL_REG, + get_dsp_register(chip, CHI32_CONTROL_REG) | 0x900); + + /* Main loader loop */ + + index = code[0]; + for (;;) { + int block_type, mem_type; + + /* Total Block Size */ + index++; + + /* Block Type */ + block_type = code[index]; + if (block_type == 4) /* We're finished */ + break; + + index++; + + /* Memory Type P=0,X=1,Y=2 */ + mem_type = code[index++]; + + /* Block Code Size */ + words = code[index++]; + if (words == 0) /* We're finished */ + break; + + /* Start Address */ + address = ((u32)code[index] << 16) + code[index + 1]; + index += 2; + + if (write_dsp(chip, words) < 0) { + DE_INIT(("load_dsp: failed to write number of DSP words\n")); + return -EIO; + } + if (write_dsp(chip, address) < 0) { + DE_INIT(("load_dsp: failed to write DSP address\n")); + return -EIO; + } + if (write_dsp(chip, mem_type) < 0) { + DE_INIT(("load_dsp: failed to write DSP memory type\n")); + return -EIO; + } + /* Code */ + for (i = 0; i < words; i++, index+=2) { + data = ((u32)code[index] << 16) + code[index + 1]; + if (write_dsp(chip, data) < 0) { + DE_INIT(("load_dsp: failed to write DSP data\n")); + return -EIO; + } + } + } + + if (write_dsp(chip, 0) < 0) { /* We're done!!! */ + DE_INIT(("load_dsp: Failed to write final zero\n")); + return -EIO; + } + udelay(10); + + for (i = 0; i < 5000; i++) { /* Timeout is 100us * 5000 = 500ms */ + /* Wait for flag 4 - indicates that the DSP loaded OK */ + if (get_dsp_register(chip, CHI32_STATUS_REG) & + CHI32_STATUS_REG_HF4) { + set_dsp_register(chip, CHI32_CONTROL_REG, + get_dsp_register(chip, CHI32_CONTROL_REG) & ~0x1b00); + + if (write_dsp(chip, DSP_FNC_SET_COMMPAGE_ADDR) < 0) { + DE_INIT(("load_dsp: Failed to write DSP_FNC_SET_COMMPAGE_ADDR\n")); + return -EIO; + } + + if (write_dsp(chip, chip->comm_page_phys) < 0) { + DE_INIT(("load_dsp: Failed to write comm page address\n")); + return -EIO; + } + + /* Get the serial number via slave mode. + This is triggered by the SET_COMMPAGE_ADDR command. + We don't actually use the serial number but we have to + get it as part of the DSP init voodoo. */ + if (read_sn(chip) < 0) { + DE_INIT(("load_dsp: Failed to read serial number\n")); + return -EIO; + } + + chip->dsp_code = code; /* Show which DSP code loaded */ + chip->bad_board = FALSE; /* DSP OK */ + DE_INIT(("load_dsp: OK!\n")); + return 0; + } + udelay(100); + } + + DE_INIT(("load_dsp: DSP load timed out waiting for HF4\n")); + return -EIO; +} + + + +/* load_firmware takes care of loading the DSP and any ASIC code. */ +static int load_firmware(struct echoaudio *chip) +{ + const struct firmware *fw; + int box_type, err; + + snd_assert(chip->dsp_code_to_load && chip->comm_page, return -EPERM); + + /* See if the ASIC is present and working - only if the DSP is already loaded */ + if (chip->dsp_code) { + if ((box_type = check_asic_status(chip)) >= 0) + return box_type; + /* ASIC check failed; force the DSP to reload */ + chip->dsp_code = NULL; + } + + if ((err = get_firmware(&fw, chip->dsp_code_to_load, chip)) < 0) + return err; + err = load_dsp(chip, (u16 *)fw->data); + free_firmware(fw); + if (err < 0) + return err; + + if ((box_type = load_asic(chip)) < 0) + return box_type; /* error */ + + if ((err = restore_dsp_rettings(chip)) < 0) + return err; + + return box_type; +} + + + +/**************************************************************************** + Mixer functions + ****************************************************************************/ + +#if defined(ECHOCARD_HAS_INPUT_NOMINAL_LEVEL) || \ + defined(ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL) + +/* Set the nominal level for an input or output bus (true = -10dBV, false = +4dBu) */ +static int set_nominal_level(struct echoaudio *chip, u16 index, char consumer) +{ + snd_assert(index < num_busses_out(chip) + num_busses_in(chip), + return -EINVAL); + + /* Wait for the handshake (OK even if ASIC is not loaded) */ + if (wait_handshake(chip)) + return -EIO; + + chip->nominal_level[index] = consumer; + + if (consumer) + chip->comm_page->nominal_level_mask |= cpu_to_le32(1 << index); + else + chip->comm_page->nominal_level_mask &= ~cpu_to_le32(1 << index); + + return 0; +} + +#endif /* ECHOCARD_HAS_*_NOMINAL_LEVEL */ + + + +/* Set the gain for a single physical output channel (dB). */ +static int set_output_gain(struct echoaudio *chip, u16 channel, s8 gain) +{ + snd_assert(channel < num_busses_out(chip), return -EINVAL); + + if (wait_handshake(chip)) + return -EIO; + + /* Save the new value */ + chip->output_gain[channel] = gain; + chip->comm_page->line_out_level[channel] = gain; + return 0; +} + + + +#ifdef ECHOCARD_HAS_MONITOR +/* Set the monitor level from an input bus to an output bus. */ +static int set_monitor_gain(struct echoaudio *chip, u16 output, u16 input, + s8 gain) +{ + snd_assert(output < num_busses_out(chip) && + input < num_busses_in(chip), return -EINVAL); + + if (wait_handshake(chip)) + return -EIO; + + chip->monitor_gain[output][input] = gain; + chip->comm_page->monitors[monitor_index(chip, output, input)] = gain; + return 0; +} +#endif /* ECHOCARD_HAS_MONITOR */ + + +/* Tell the DSP to read and update output, nominal & monitor levels in comm page. */ +static int update_output_line_level(struct echoaudio *chip) +{ + if (wait_handshake(chip)) + return -EIO; + clear_handshake(chip); + return send_vector(chip, DSP_VC_UPDATE_OUTVOL); +} + + + +/* Tell the DSP to read and update input levels in comm page */ +static int update_input_line_level(struct echoaudio *chip) +{ + if (wait_handshake(chip)) + return -EIO; + clear_handshake(chip); + return send_vector(chip, DSP_VC_UPDATE_INGAIN); +} + + + +/* set_meters_on turns the meters on or off. If meters are turned on, the DSP +will write the meter and clock detect values to the comm page at about 30Hz */ +static void set_meters_on(struct echoaudio *chip, char on) +{ + if (on && !chip->meters_enabled) { + send_vector(chip, DSP_VC_METERS_ON); + chip->meters_enabled = 1; + } else if (!on && chip->meters_enabled) { + send_vector(chip, DSP_VC_METERS_OFF); + chip->meters_enabled = 0; + memset((s8 *)chip->comm_page->vu_meter, ECHOGAIN_MUTED, + DSP_MAXPIPES); + memset((s8 *)chip->comm_page->peak_meter, ECHOGAIN_MUTED, + DSP_MAXPIPES); + } +} + + + +/* Fill out an the given array using the current values in the comm page. +Meters are written in the comm page by the DSP in this order: + Output busses + Input busses + Output pipes (vmixer cards only) + +This function assumes there are no more than 16 in/out busses or pipes +Meters is an array [3][16][2] of long. */ +static void get_audio_meters(struct echoaudio *chip, long *meters) +{ + int i, m, n; + + m = 0; + n = 0; + for (i = 0; i < num_busses_out(chip); i++, m++) { + meters[n++] = chip->comm_page->vu_meter[m]; + meters[n++] = chip->comm_page->peak_meter[m]; + } + for (; n < 32; n++) + meters[n] = 0; + +#ifdef ECHOCARD_ECHO3G + m = E3G_MAX_OUTPUTS; /* Skip unused meters */ +#endif + + for (i = 0; i < num_busses_in(chip); i++, m++) { + meters[n++] = chip->comm_page->vu_meter[m]; + meters[n++] = chip->comm_page->peak_meter[m]; + } + for (; n < 64; n++) + meters[n] = 0; + +#ifdef ECHOCARD_HAS_VMIXER + for (i = 0; i < num_pipes_out(chip); i++, m++) { + meters[n++] = chip->comm_page->vu_meter[m]; + meters[n++] = chip->comm_page->peak_meter[m]; + } +#endif + for (; n < 96; n++) + meters[n] = 0; +} + + + +static int restore_dsp_rettings(struct echoaudio *chip) +{ + int err; + DE_INIT(("restore_dsp_settings\n")); + + if ((err = check_asic_status(chip)) < 0) + return err; + + /* @ Gina20/Darla20 only. Should be harmless for other cards. */ + chip->comm_page->gd_clock_state = GD_CLOCK_UNDEF; + chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_UNDEF; + chip->comm_page->handshake = 0xffffffff; + + if ((err = set_sample_rate(chip, chip->sample_rate)) < 0) + return err; + + if (chip->meters_enabled) + if (send_vector(chip, DSP_VC_METERS_ON) < 0) + return -EIO; + +#ifdef ECHOCARD_HAS_EXTERNAL_CLOCK + if (set_input_clock(chip, chip->input_clock) < 0) + return -EIO; +#endif + +#ifdef ECHOCARD_HAS_OUTPUT_CLOCK_SWITCH + if (set_output_clock(chip, chip->output_clock) < 0) + return -EIO; +#endif + + if (update_output_line_level(chip) < 0) + return -EIO; + + if (update_input_line_level(chip) < 0) + return -EIO; + +#ifdef ECHOCARD_HAS_VMIXER + if (update_vmixer_level(chip) < 0) + return -EIO; +#endif + + if (wait_handshake(chip) < 0) + return -EIO; + clear_handshake(chip); + + DE_INIT(("restore_dsp_rettings done\n")); + return send_vector(chip, DSP_VC_UPDATE_FLAGS); +} + + + +/**************************************************************************** + Transport functions + ****************************************************************************/ + +/* set_audio_format() sets the format of the audio data in host memory for +this pipe. Note that _MS_ (mono-to-stereo) playback modes are not used by ALSA +but they are here because they are just mono while capturing */ +static void set_audio_format(struct echoaudio *chip, u16 pipe_index, + const struct audioformat *format) +{ + u16 dsp_format; + + dsp_format = DSP_AUDIOFORM_SS_16LE; + + /* Look for super-interleave (no big-endian and 8 bits) */ + if (format->interleave > 2) { + switch (format->bits_per_sample) { + case 16: + dsp_format = DSP_AUDIOFORM_SUPER_INTERLEAVE_16LE; + break; + case 24: + dsp_format = DSP_AUDIOFORM_SUPER_INTERLEAVE_24LE; + break; + case 32: + dsp_format = DSP_AUDIOFORM_SUPER_INTERLEAVE_32LE; + break; + } + dsp_format |= format->interleave; + } else if (format->data_are_bigendian) { + /* For big-endian data, only 32 bit samples are supported */ + switch (format->interleave) { + case 1: + dsp_format = DSP_AUDIOFORM_MM_32BE; + break; +#ifdef ECHOCARD_HAS_STEREO_BIG_ENDIAN32 + case 2: + dsp_format = DSP_AUDIOFORM_SS_32BE; + break; +#endif + } + } else if (format->interleave == 1 && + format->bits_per_sample == 32 && !format->mono_to_stereo) { + /* 32 bit little-endian mono->mono case */ + dsp_format = DSP_AUDIOFORM_MM_32LE; + } else { + /* Handle the other little-endian formats */ + switch (format->bits_per_sample) { + case 8: + if (format->interleave == 2) + dsp_format = DSP_AUDIOFORM_SS_8; + else + dsp_format = DSP_AUDIOFORM_MS_8; + break; + default: + case 16: + if (format->interleave == 2) + dsp_format = DSP_AUDIOFORM_SS_16LE; + else + dsp_format = DSP_AUDIOFORM_MS_16LE; + break; + case 24: + if (format->interleave == 2) + dsp_format = DSP_AUDIOFORM_SS_24LE; + else + dsp_format = DSP_AUDIOFORM_MS_24LE; + break; + case 32: + if (format->interleave == 2) + dsp_format = DSP_AUDIOFORM_SS_32LE; + else + dsp_format = DSP_AUDIOFORM_MS_32LE; + break; + } + } + DE_ACT(("set_audio_format[%d] = %x\n", pipe_index, dsp_format)); + chip->comm_page->audio_format[pipe_index] = cpu_to_le16(dsp_format); +} + + + +/* start_transport starts transport for a set of pipes. +The bits 1 in channel_mask specify what pipes to start. Only the bit of the +first channel must be set, regardless its interleave. +Same thing for pause_ and stop_ -trasport below. */ +static int start_transport(struct echoaudio *chip, u32 channel_mask, + u32 cyclic_mask) +{ + DE_ACT(("start_transport %x\n", channel_mask)); + + if (wait_handshake(chip)) + return -EIO; + + chip->comm_page->cmd_start |= cpu_to_le32(channel_mask); + + if (chip->comm_page->cmd_start) { + clear_handshake(chip); + send_vector(chip, DSP_VC_START_TRANSFER); + if (wait_handshake(chip)) + return -EIO; + /* Keep track of which pipes are transporting */ + chip->active_mask |= channel_mask; + chip->comm_page->cmd_start = 0; + return 0; + } + + DE_ACT(("start_transport: No pipes to start!\n")); + return -EINVAL; +} + + + +static int pause_transport(struct echoaudio *chip, u32 channel_mask) +{ + DE_ACT(("pause_transport %x\n", channel_mask)); + + if (wait_handshake(chip)) + return -EIO; + + chip->comm_page->cmd_stop |= cpu_to_le32(channel_mask); + chip->comm_page->cmd_reset = 0; + if (chip->comm_page->cmd_stop) { + clear_handshake(chip); + send_vector(chip, DSP_VC_STOP_TRANSFER); + if (wait_handshake(chip)) + return -EIO; + /* Keep track of which pipes are transporting */ + chip->active_mask &= ~channel_mask; + chip->comm_page->cmd_stop = 0; + chip->comm_page->cmd_reset = 0; + return 0; + } + + DE_ACT(("pause_transport: No pipes to stop!\n")); + return 0; +} + + + +static int stop_transport(struct echoaudio *chip, u32 channel_mask) +{ + DE_ACT(("stop_transport %x\n", channel_mask)); + + if (wait_handshake(chip)) + return -EIO; + + chip->comm_page->cmd_stop |= cpu_to_le32(channel_mask); + chip->comm_page->cmd_reset |= cpu_to_le32(channel_mask); + if (chip->comm_page->cmd_reset) { + clear_handshake(chip); + send_vector(chip, DSP_VC_STOP_TRANSFER); + if (wait_handshake(chip)) + return -EIO; + /* Keep track of which pipes are transporting */ + chip->active_mask &= ~channel_mask; + chip->comm_page->cmd_stop = 0; + chip->comm_page->cmd_reset = 0; + return 0; + } + + DE_ACT(("stop_transport: No pipes to stop!\n")); + return 0; +} + + + +static inline int is_pipe_allocated(struct echoaudio *chip, u16 pipe_index) +{ + return (chip->pipe_alloc_mask & (1 << pipe_index)); +} + + + +/* Stops everything and turns off the DSP. All pipes should be already +stopped and unallocated. */ +static int rest_in_peace(struct echoaudio *chip) +{ + DE_ACT(("rest_in_peace() open=%x\n", chip->pipe_alloc_mask)); + + /* Stops all active pipes (just to be sure) */ + stop_transport(chip, chip->active_mask); + + set_meters_on(chip, FALSE); + +#ifdef ECHOCARD_HAS_MIDI + enable_midi_input(chip, FALSE); +#endif + + /* Go to sleep */ + if (chip->dsp_code) { + /* Make load_firmware do a complete reload */ + chip->dsp_code = NULL; + /* Put the DSP to sleep */ + return send_vector(chip, DSP_VC_GO_COMATOSE); + } + return 0; +} + + + +/* Fills the comm page with default values */ +static int init_dsp_comm_page(struct echoaudio *chip) +{ + /* Check if the compiler added extra padding inside the structure */ + if (offsetof(struct comm_page, midi_output) != 0xbe0) { + DE_INIT(("init_dsp_comm_page() - Invalid struct comm_page structure\n")); + return -EPERM; + } + + /* Init all the basic stuff */ + chip->card_name = ECHOCARD_NAME; + chip->bad_board = TRUE; /* Set TRUE until DSP loaded */ + chip->dsp_code = NULL; /* Current DSP code not loaded */ + chip->digital_mode = DIGITAL_MODE_NONE; + chip->input_clock = ECHO_CLOCK_INTERNAL; + chip->output_clock = ECHO_CLOCK_WORD; + chip->asic_loaded = FALSE; + memset(chip->comm_page, 0, sizeof(struct comm_page)); + + /* Init the comm page */ + chip->comm_page->comm_size = + __constant_cpu_to_le32(sizeof(struct comm_page)); + chip->comm_page->handshake = 0xffffffff; + chip->comm_page->midi_out_free_count = + __constant_cpu_to_le32(DSP_MIDI_OUT_FIFO_SIZE); + chip->comm_page->sample_rate = __constant_cpu_to_le32(44100); + chip->sample_rate = 44100; + + /* Set line levels so we don't blast any inputs on startup */ + memset(chip->comm_page->monitors, ECHOGAIN_MUTED, MONITOR_ARRAY_SIZE); + memset(chip->comm_page->vmixer, ECHOGAIN_MUTED, VMIXER_ARRAY_SIZE); + + return 0; +} + + + +/* This function initializes the several volume controls for busses and pipes. +This MUST be called after the DSP is up and running ! */ +static int init_line_levels(struct echoaudio *chip) +{ + int st, i, o; + + DE_INIT(("init_line_levels\n")); + + /* Mute output busses */ + for (i = 0; i < num_busses_out(chip); i++) + if ((st = set_output_gain(chip, i, ECHOGAIN_MUTED))) + return st; + if ((st = update_output_line_level(chip))) + return st; + +#ifdef ECHOCARD_HAS_VMIXER + /* Mute the Vmixer */ + for (i = 0; i < num_pipes_out(chip); i++) + for (o = 0; o < num_busses_out(chip); o++) + if ((st = set_vmixer_gain(chip, o, i, ECHOGAIN_MUTED))) + return st; + if ((st = update_vmixer_level(chip))) + return st; +#endif /* ECHOCARD_HAS_VMIXER */ + +#ifdef ECHOCARD_HAS_MONITOR + /* Mute the monitor mixer */ + for (o = 0; o < num_busses_out(chip); o++) + for (i = 0; i < num_busses_in(chip); i++) + if ((st = set_monitor_gain(chip, o, i, ECHOGAIN_MUTED))) + return st; + if ((st = update_output_line_level(chip))) + return st; +#endif /* ECHOCARD_HAS_MONITOR */ + +#ifdef ECHOCARD_HAS_INPUT_GAIN + for (i = 0; i < num_busses_in(chip); i++) + if ((st = set_input_gain(chip, i, ECHOGAIN_MUTED))) + return st; + if ((st = update_input_line_level(chip))) + return st; +#endif /* ECHOCARD_HAS_INPUT_GAIN */ + + return 0; +} + + + +/* This is low level part of the interrupt handler. +It returns -1 if the IRQ is not ours, or N>=0 if it is, where N is the number +of midi data in the input queue. */ +static int service_irq(struct echoaudio *chip) +{ + int st; + + /* Read the DSP status register and see if this DSP generated this interrupt */ + if (get_dsp_register(chip, CHI32_STATUS_REG) & CHI32_STATUS_IRQ) { + st = 0; +#ifdef ECHOCARD_HAS_MIDI + /* Get and parse midi data if present */ + if (chip->comm_page->midi_input[0]) /* The count is at index 0 */ + st = midi_service_irq(chip); /* Returns how many midi bytes we received */ +#endif + /* Clear the hardware interrupt */ + chip->comm_page->midi_input[0] = 0; + send_vector(chip, DSP_VC_ACK_INT); + return st; + } + return -1; +} + + + + +/****************************************************************************** + Functions for opening and closing pipes + ******************************************************************************/ + +/* allocate_pipes is used to reserve audio pipes for your exclusive use. +The call will fail if some pipes are already allocated. */ +static int allocate_pipes(struct echoaudio *chip, struct audiopipe *pipe, + int pipe_index, int interleave) +{ + int i; + u32 channel_mask; + char is_cyclic; + + DE_ACT(("allocate_pipes: ch=%d int=%d\n", pipe_index, interleave)); + + if (chip->bad_board) + return -EIO; + + is_cyclic = 1; /* This driver uses cyclic buffers only */ + + for (channel_mask = i = 0; i < interleave; i++) + channel_mask |= 1 << (pipe_index + i); + if (chip->pipe_alloc_mask & channel_mask) { + DE_ACT(("allocate_pipes: channel already open\n")); + return -EAGAIN; + } + + chip->comm_page->position[pipe_index] = 0; + chip->pipe_alloc_mask |= channel_mask; + if (is_cyclic) + chip->pipe_cyclic_mask |= channel_mask; + pipe->index = pipe_index; + pipe->interleave = interleave; + pipe->state = PIPE_STATE_STOPPED; + + /* The counter register is where the DSP writes the 32 bit DMA + position for a pipe. The DSP is constantly updating this value as + it moves data. The DMA counter is in units of bytes, not samples. */ + pipe->dma_counter = &chip->comm_page->position[pipe_index]; + *pipe->dma_counter = 0; + DE_ACT(("allocate_pipes: ok\n")); + return pipe_index; +} + + + +static int free_pipes(struct echoaudio *chip, struct audiopipe *pipe) +{ + u32 channel_mask; + int i; + + DE_ACT(("free_pipes: Pipe %d\n", pipe->index)); + snd_assert(is_pipe_allocated(chip, pipe->index), return -EINVAL); + snd_assert(pipe->state == PIPE_STATE_STOPPED, return -EINVAL); + + for (channel_mask = i = 0; i < pipe->interleave; i++) + channel_mask |= 1 << (pipe->index + i); + + chip->pipe_alloc_mask &= ~channel_mask; + chip->pipe_cyclic_mask &= ~channel_mask; + return 0; +} + + + +/****************************************************************************** + Functions for managing the scatter-gather list +******************************************************************************/ + +static int sglist_init(struct echoaudio *chip, struct audiopipe *pipe) +{ + pipe->sglist_head = 0; + memset(pipe->sgpage.area, 0, PAGE_SIZE); + chip->comm_page->sglist_addr[pipe->index].addr = + cpu_to_le32(pipe->sgpage.addr); + return 0; +} + + + +static int sglist_add_mapping(struct echoaudio *chip, struct audiopipe *pipe, + dma_addr_t address, size_t length) +{ + int head = pipe->sglist_head; + struct sg_entry *list = (struct sg_entry *)pipe->sgpage.area; + + if (head < MAX_SGLIST_ENTRIES - 1) { + list[head].addr = cpu_to_le32(address); + list[head].size = cpu_to_le32(length); + pipe->sglist_head++; + } else { + DE_ACT(("SGlist: too many fragments\n")); + return -ENOMEM; + } + return 0; +} + + + +static inline int sglist_add_irq(struct echoaudio *chip, struct audiopipe *pipe) +{ + return sglist_add_mapping(chip, pipe, 0, 0); +} + + + +static inline int sglist_wrap(struct echoaudio *chip, struct audiopipe *pipe) +{ + return sglist_add_mapping(chip, pipe, pipe->sgpage.addr, 0); +} diff --git a/sound/pci/echoaudio/echoaudio_dsp.h b/sound/pci/echoaudio/echoaudio_dsp.h new file mode 100644 index 000000000..e55ee0099 --- /dev/null +++ b/sound/pci/echoaudio/echoaudio_dsp.h @@ -0,0 +1,694 @@ +/**************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + ************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + +****************************************************************************/ + +#ifndef _ECHO_DSP_ +#define _ECHO_DSP_ + + +/**** Echogals: Darla20, Gina20, Layla20, and Darla24 ****/ +#if defined(ECHOGALS_FAMILY) + +#define NUM_ASIC_TESTS 5 +#define READ_DSP_TIMEOUT 1000000L /* one second */ + +/**** Echo24: Gina24, Layla24, Mona, Mia, Mia-midi ****/ +#elif defined(ECHO24_FAMILY) + +#define DSP_56361 /* Some Echo24 cards use the 56361 DSP */ +#define READ_DSP_TIMEOUT 100000L /* .1 second */ + +/**** 3G: Gina3G, Layla3G ****/ +#elif defined(ECHO3G_FAMILY) + +#define DSP_56361 +#define READ_DSP_TIMEOUT 100000L /* .1 second */ +#define MIN_MTC_1X_RATE 32000 + +/**** Indigo: Indigo, Indigo IO, Indigo DJ ****/ +#elif defined(INDIGO_FAMILY) + +#define DSP_56361 +#define READ_DSP_TIMEOUT 100000L /* .1 second */ + +#else + +#error No family is defined + +#endif + + + +/* + * + * Max inputs and outputs + * + */ + +#define DSP_MAXAUDIOINPUTS 16 /* Max audio input channels */ +#define DSP_MAXAUDIOOUTPUTS 16 /* Max audio output channels */ +#define DSP_MAXPIPES 32 /* Max total pipes (input + output) */ + + +/* + * + * These are the offsets for the memory-mapped DSP registers; the DSP base + * address is treated as the start of a u32 array. + */ + +#define CHI32_CONTROL_REG 4 +#define CHI32_STATUS_REG 5 +#define CHI32_VECTOR_REG 6 +#define CHI32_DATA_REG 7 + + +/* + * + * Interesting bits within the DSP registers + * + */ + +#define CHI32_VECTOR_BUSY 0x00000001 +#define CHI32_STATUS_REG_HF3 0x00000008 +#define CHI32_STATUS_REG_HF4 0x00000010 +#define CHI32_STATUS_REG_HF5 0x00000020 +#define CHI32_STATUS_HOST_READ_FULL 0x00000004 +#define CHI32_STATUS_HOST_WRITE_EMPTY 0x00000002 +#define CHI32_STATUS_IRQ 0x00000040 + + +/* + * + * DSP commands sent via slave mode; these are sent to the DSP by write_dsp() + * + */ + +#define DSP_FNC_SET_COMMPAGE_ADDR 0x02 +#define DSP_FNC_LOAD_LAYLA_ASIC 0xa0 +#define DSP_FNC_LOAD_GINA24_ASIC 0xa0 +#define DSP_FNC_LOAD_MONA_PCI_CARD_ASIC 0xa0 +#define DSP_FNC_LOAD_LAYLA24_PCI_CARD_ASIC 0xa0 +#define DSP_FNC_LOAD_MONA_EXTERNAL_ASIC 0xa1 +#define DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC 0xa1 +#define DSP_FNC_LOAD_3G_ASIC 0xa0 + + +/* + * + * Defines to handle the MIDI input state engine; these are used to properly + * extract MIDI time code bytes and their timestamps from the MIDI input stream. + * + */ + +#define MIDI_IN_STATE_NORMAL 0 +#define MIDI_IN_STATE_TS_HIGH 1 +#define MIDI_IN_STATE_TS_LOW 2 +#define MIDI_IN_STATE_F1_DATA 3 +#define MIDI_IN_SKIP_DATA (-1) + + +/*---------------------------------------------------------------------------- + +Setting the sample rates on Layla24 is somewhat schizophrenic. + +For standard rates, it works exactly like Mona and Gina24. That is, for +8, 11.025, 16, 22.05, 32, 44.1, 48, 88.2, and 96 kHz, you just set the +appropriate bits in the control register and write the control register. + +In order to support MIDI time code sync (and possibly SMPTE LTC sync in +the future), Layla24 also has "continuous sample rate mode". In this mode, +Layla24 can generate any sample rate between 25 and 50 kHz inclusive, or +50 to 100 kHz inclusive for double speed mode. + +To use continuous mode: + +-Set the clock select bits in the control register to 0xe (see the #define + below) + +-Set double-speed mode if you want to use sample rates above 50 kHz + +-Write the control register as you would normally + +-Now, you need to set the frequency register. First, you need to determine the + value for the frequency register. This is given by the following formula: + +frequency_reg = (LAYLA24_MAGIC_NUMBER / sample_rate) - 2 + +Note the #define below for the magic number + +-Wait for the DSP handshake +-Write the frequency_reg value to the .SampleRate field of the comm page +-Send the vector command SET_LAYLA24_FREQUENCY_REG (see vmonkey.h) + +Once you have set the control register up for continuous mode, you can just +write the frequency register to change the sample rate. This could be +used for MIDI time code sync. For MTC sync, the control register is set for +continuous mode. The driver then just keeps writing the +SET_LAYLA24_FREQUENCY_REG command. + +-----------------------------------------------------------------------------*/ + +#define LAYLA24_MAGIC_NUMBER 677376000 +#define LAYLA24_CONTINUOUS_CLOCK 0x000e + + +/* + * + * DSP vector commands + * + */ + +#define DSP_VC_RESET 0x80ff + +#ifndef DSP_56361 + +#define DSP_VC_ACK_INT 0x8073 +#define DSP_VC_SET_VMIXER_GAIN 0x0000 /* Not used, only for compile */ +#define DSP_VC_START_TRANSFER 0x0075 /* Handshke rqd. */ +#define DSP_VC_METERS_ON 0x0079 +#define DSP_VC_METERS_OFF 0x007b +#define DSP_VC_UPDATE_OUTVOL 0x007d /* Handshke rqd. */ +#define DSP_VC_UPDATE_INGAIN 0x007f /* Handshke rqd. */ +#define DSP_VC_ADD_AUDIO_BUFFER 0x0081 /* Handshke rqd. */ +#define DSP_VC_TEST_ASIC 0x00eb +#define DSP_VC_UPDATE_CLOCKS 0x00ef /* Handshke rqd. */ +#define DSP_VC_SET_LAYLA_SAMPLE_RATE 0x00f1 /* Handshke rqd. */ +#define DSP_VC_SET_GD_AUDIO_STATE 0x00f1 /* Handshke rqd. */ +#define DSP_VC_WRITE_CONTROL_REG 0x00f1 /* Handshke rqd. */ +#define DSP_VC_MIDI_WRITE 0x00f5 /* Handshke rqd. */ +#define DSP_VC_STOP_TRANSFER 0x00f7 /* Handshke rqd. */ +#define DSP_VC_UPDATE_FLAGS 0x00fd /* Handshke rqd. */ +#define DSP_VC_GO_COMATOSE 0x00f9 + +#else /* !DSP_56361 */ + +/* Vector commands for families that use either the 56301 or 56361 */ +#define DSP_VC_ACK_INT 0x80F5 +#define DSP_VC_SET_VMIXER_GAIN 0x00DB /* Handshke rqd. */ +#define DSP_VC_START_TRANSFER 0x00DD /* Handshke rqd. */ +#define DSP_VC_METERS_ON 0x00EF +#define DSP_VC_METERS_OFF 0x00F1 +#define DSP_VC_UPDATE_OUTVOL 0x00E3 /* Handshke rqd. */ +#define DSP_VC_UPDATE_INGAIN 0x00E5 /* Handshke rqd. */ +#define DSP_VC_ADD_AUDIO_BUFFER 0x00E1 /* Handshke rqd. */ +#define DSP_VC_TEST_ASIC 0x00ED +#define DSP_VC_UPDATE_CLOCKS 0x00E9 /* Handshke rqd. */ +#define DSP_VC_SET_LAYLA24_FREQUENCY_REG 0x00E9 /* Handshke rqd. */ +#define DSP_VC_SET_LAYLA_SAMPLE_RATE 0x00EB /* Handshke rqd. */ +#define DSP_VC_SET_GD_AUDIO_STATE 0x00EB /* Handshke rqd. */ +#define DSP_VC_WRITE_CONTROL_REG 0x00EB /* Handshke rqd. */ +#define DSP_VC_MIDI_WRITE 0x00E7 /* Handshke rqd. */ +#define DSP_VC_STOP_TRANSFER 0x00DF /* Handshke rqd. */ +#define DSP_VC_UPDATE_FLAGS 0x00FB /* Handshke rqd. */ +#define DSP_VC_GO_COMATOSE 0x00d9 + +#endif /* !DSP_56361 */ + + +/* + * + * Timeouts + * + */ + +#define HANDSHAKE_TIMEOUT 20000 /* send_vector command timeout (20ms) */ +#define VECTOR_BUSY_TIMEOUT 100000 /* 100ms */ +#define MIDI_OUT_DELAY_USEC 2000 /* How long to wait after MIDI fills up */ + + +/* + * + * Flags for .Flags field in the comm page + * + */ + +#define DSP_FLAG_MIDI_INPUT 0x0001 /* Enable MIDI input */ +#define DSP_FLAG_SPDIF_NONAUDIO 0x0002 /* Sets the "non-audio" bit + * in the S/PDIF out status + * bits. Clear this flag for + * audio data; + * set it for AC3 or WMA or + * some such */ +#define DSP_FLAG_PROFESSIONAL_SPDIF 0x0008 /* 1 Professional, 0 Consumer */ + + +/* + * + * Clock detect bits reported by the DSP for Gina20, Layla20, Darla24, and Mia + * + */ + +#define GLDM_CLOCK_DETECT_BIT_WORD 0x0002 +#define GLDM_CLOCK_DETECT_BIT_SUPER 0x0004 +#define GLDM_CLOCK_DETECT_BIT_SPDIF 0x0008 +#define GLDM_CLOCK_DETECT_BIT_ESYNC 0x0010 + + +/* + * + * Clock detect bits reported by the DSP for Gina24, Mona, and Layla24 + * + */ + +#define GML_CLOCK_DETECT_BIT_WORD96 0x0002 +#define GML_CLOCK_DETECT_BIT_WORD48 0x0004 +#define GML_CLOCK_DETECT_BIT_SPDIF48 0x0008 +#define GML_CLOCK_DETECT_BIT_SPDIF96 0x0010 +#define GML_CLOCK_DETECT_BIT_WORD (GML_CLOCK_DETECT_BIT_WORD96 | GML_CLOCK_DETECT_BIT_WORD48) +#define GML_CLOCK_DETECT_BIT_SPDIF (GML_CLOCK_DETECT_BIT_SPDIF48 | GML_CLOCK_DETECT_BIT_SPDIF96) +#define GML_CLOCK_DETECT_BIT_ESYNC 0x0020 +#define GML_CLOCK_DETECT_BIT_ADAT 0x0040 + + +/* + * + * Layla clock numbers to send to DSP + * + */ + +#define LAYLA20_CLOCK_INTERNAL 0 +#define LAYLA20_CLOCK_SPDIF 1 +#define LAYLA20_CLOCK_WORD 2 +#define LAYLA20_CLOCK_SUPER 3 + + +/* + * + * Gina/Darla clock states + * + */ + +#define GD_CLOCK_NOCHANGE 0 +#define GD_CLOCK_44 1 +#define GD_CLOCK_48 2 +#define GD_CLOCK_SPDIFIN 3 +#define GD_CLOCK_UNDEF 0xff + + +/* + * + * Gina/Darla S/PDIF status bits + * + */ + +#define GD_SPDIF_STATUS_NOCHANGE 0 +#define GD_SPDIF_STATUS_44 1 +#define GD_SPDIF_STATUS_48 2 +#define GD_SPDIF_STATUS_UNDEF 0xff + + +/* + * + * Layla20 output clocks + * + */ + +#define LAYLA20_OUTPUT_CLOCK_SUPER 0 +#define LAYLA20_OUTPUT_CLOCK_WORD 1 + + +/**************************************************************************** + + Magic constants for the Darla24 hardware + + ****************************************************************************/ + +#define GD24_96000 0x0 +#define GD24_48000 0x1 +#define GD24_44100 0x2 +#define GD24_32000 0x3 +#define GD24_22050 0x4 +#define GD24_16000 0x5 +#define GD24_11025 0x6 +#define GD24_8000 0x7 +#define GD24_88200 0x8 +#define GD24_EXT_SYNC 0x9 + + +/* + * + * Return values from the DSP when ASIC is loaded + * + */ + +#define ASIC_ALREADY_LOADED 0x1 +#define ASIC_NOT_LOADED 0x0 + + +/* + * + * DSP Audio formats + * + * These are the audio formats that the DSP can transfer + * via input and output pipes. LE means little-endian, + * BE means big-endian. + * + * DSP_AUDIOFORM_MS_8 + * + * 8-bit mono unsigned samples. For playback, + * mono data is duplicated out the left and right channels + * of the output bus. The "MS" part of the name + * means mono->stereo. + * + * DSP_AUDIOFORM_MS_16LE + * + * 16-bit signed little-endian mono samples. Playback works + * like the previous code. + * + * DSP_AUDIOFORM_MS_24LE + * + * 24-bit signed little-endian mono samples. Data is packed + * three bytes per sample; if you had two samples 0x112233 and 0x445566 + * they would be stored in memory like this: 33 22 11 66 55 44. + * + * DSP_AUDIOFORM_MS_32LE + * + * 24-bit signed little-endian mono samples in a 32-bit + * container. In other words, each sample is a 32-bit signed + * integer, where the actual audio data is left-justified + * in the 32 bits and only the 24 most significant bits are valid. + * + * DSP_AUDIOFORM_SS_8 + * DSP_AUDIOFORM_SS_16LE + * DSP_AUDIOFORM_SS_24LE + * DSP_AUDIOFORM_SS_32LE + * + * Like the previous ones, except now with stereo interleaved + * data. "SS" means stereo->stereo. + * + * DSP_AUDIOFORM_MM_32LE + * + * Similar to DSP_AUDIOFORM_MS_32LE, except that the mono + * data is not duplicated out both the left and right outputs. + * This mode is used by the ASIO driver. Here, "MM" means + * mono->mono. + * + * DSP_AUDIOFORM_MM_32BE + * + * Just like DSP_AUDIOFORM_MM_32LE, but now the data is + * in big-endian format. + * + */ + +#define DSP_AUDIOFORM_MS_8 0 /* 8 bit mono */ +#define DSP_AUDIOFORM_MS_16LE 1 /* 16 bit mono */ +#define DSP_AUDIOFORM_MS_24LE 2 /* 24 bit mono */ +#define DSP_AUDIOFORM_MS_32LE 3 /* 32 bit mono */ +#define DSP_AUDIOFORM_SS_8 4 /* 8 bit stereo */ +#define DSP_AUDIOFORM_SS_16LE 5 /* 16 bit stereo */ +#define DSP_AUDIOFORM_SS_24LE 6 /* 24 bit stereo */ +#define DSP_AUDIOFORM_SS_32LE 7 /* 32 bit stereo */ +#define DSP_AUDIOFORM_MM_32LE 8 /* 32 bit mono->mono little-endian */ +#define DSP_AUDIOFORM_MM_32BE 9 /* 32 bit mono->mono big-endian */ +#define DSP_AUDIOFORM_SS_32BE 10 /* 32 bit stereo big endian */ +#define DSP_AUDIOFORM_INVALID 0xFF /* Invalid audio format */ + + +/* + * + * Super-interleave is defined as interleaving by 4 or more. Darla20 and Gina20 + * do not support super interleave. + * + * 16 bit, 24 bit, and 32 bit little endian samples are supported for super + * interleave. The interleave factor must be even. 16 - way interleave is the + * current maximum, so you can interleave by 4, 6, 8, 10, 12, 14, and 16. + * + * The actual format code is derived by taking the define below and or-ing with + * the interleave factor. So, 32 bit interleave by 6 is 0x86 and + * 16 bit interleave by 16 is (0x40 | 0x10) = 0x50. + * + */ + +#define DSP_AUDIOFORM_SUPER_INTERLEAVE_16LE 0x40 +#define DSP_AUDIOFORM_SUPER_INTERLEAVE_24LE 0xc0 +#define DSP_AUDIOFORM_SUPER_INTERLEAVE_32LE 0x80 + + +/* + * + * Gina24, Mona, and Layla24 control register defines + * + */ + +#define GML_CONVERTER_ENABLE 0x0010 +#define GML_SPDIF_PRO_MODE 0x0020 /* Professional S/PDIF == 1, + consumer == 0 */ +#define GML_SPDIF_SAMPLE_RATE0 0x0040 +#define GML_SPDIF_SAMPLE_RATE1 0x0080 +#define GML_SPDIF_TWO_CHANNEL 0x0100 /* 1 == two channels, + 0 == one channel */ +#define GML_SPDIF_NOT_AUDIO 0x0200 +#define GML_SPDIF_COPY_PERMIT 0x0400 +#define GML_SPDIF_24_BIT 0x0800 /* 1 == 24 bit, 0 == 20 bit */ +#define GML_ADAT_MODE 0x1000 /* 1 == ADAT mode, 0 == S/PDIF mode */ +#define GML_SPDIF_OPTICAL_MODE 0x2000 /* 1 == optical mode, 0 == RCA mode */ +#define GML_SPDIF_CDROM_MODE 0x3000 /* 1 == CDROM mode, + * 0 == RCA or optical mode */ +#define GML_DOUBLE_SPEED_MODE 0x4000 /* 1 == double speed, + 0 == single speed */ + +#define GML_DIGITAL_IN_AUTO_MUTE 0x800000 + +#define GML_96KHZ (0x0 | GML_DOUBLE_SPEED_MODE) +#define GML_88KHZ (0x1 | GML_DOUBLE_SPEED_MODE) +#define GML_48KHZ 0x2 +#define GML_44KHZ 0x3 +#define GML_32KHZ 0x4 +#define GML_22KHZ 0x5 +#define GML_16KHZ 0x6 +#define GML_11KHZ 0x7 +#define GML_8KHZ 0x8 +#define GML_SPDIF_CLOCK 0x9 +#define GML_ADAT_CLOCK 0xA +#define GML_WORD_CLOCK 0xB +#define GML_ESYNC_CLOCK 0xC +#define GML_ESYNCx2_CLOCK 0xD + +#define GML_CLOCK_CLEAR_MASK 0xffffbff0 +#define GML_SPDIF_RATE_CLEAR_MASK (~(GML_SPDIF_SAMPLE_RATE0|GML_SPDIF_SAMPLE_RATE1)) +#define GML_DIGITAL_MODE_CLEAR_MASK 0xffffcfff +#define GML_SPDIF_FORMAT_CLEAR_MASK 0xfffff01f + + +/* + * + * Mia sample rate and clock setting constants + * + */ + +#define MIA_32000 0x0040 +#define MIA_44100 0x0042 +#define MIA_48000 0x0041 +#define MIA_88200 0x0142 +#define MIA_96000 0x0141 + +#define MIA_SPDIF 0x00000044 +#define MIA_SPDIF96 0x00000144 + +#define MIA_MIDI_REV 1 /* Must be Mia rev 1 for MIDI support */ + + +/* + * + * 3G register bits + * + */ + +#define E3G_CONVERTER_ENABLE 0x0010 +#define E3G_SPDIF_PRO_MODE 0x0020 /* Professional S/PDIF == 1, + consumer == 0 */ +#define E3G_SPDIF_SAMPLE_RATE0 0x0040 +#define E3G_SPDIF_SAMPLE_RATE1 0x0080 +#define E3G_SPDIF_TWO_CHANNEL 0x0100 /* 1 == two channels, + 0 == one channel */ +#define E3G_SPDIF_NOT_AUDIO 0x0200 +#define E3G_SPDIF_COPY_PERMIT 0x0400 +#define E3G_SPDIF_24_BIT 0x0800 /* 1 == 24 bit, 0 == 20 bit */ +#define E3G_DOUBLE_SPEED_MODE 0x4000 /* 1 == double speed, + 0 == single speed */ +#define E3G_PHANTOM_POWER 0x8000 /* 1 == phantom power on, + 0 == phantom power off */ + +#define E3G_96KHZ (0x0 | E3G_DOUBLE_SPEED_MODE) +#define E3G_88KHZ (0x1 | E3G_DOUBLE_SPEED_MODE) +#define E3G_48KHZ 0x2 +#define E3G_44KHZ 0x3 +#define E3G_32KHZ 0x4 +#define E3G_22KHZ 0x5 +#define E3G_16KHZ 0x6 +#define E3G_11KHZ 0x7 +#define E3G_8KHZ 0x8 +#define E3G_SPDIF_CLOCK 0x9 +#define E3G_ADAT_CLOCK 0xA +#define E3G_WORD_CLOCK 0xB +#define E3G_CONTINUOUS_CLOCK 0xE + +#define E3G_ADAT_MODE 0x1000 +#define E3G_SPDIF_OPTICAL_MODE 0x2000 + +#define E3G_CLOCK_CLEAR_MASK 0xbfffbff0 +#define E3G_DIGITAL_MODE_CLEAR_MASK 0xffffcfff +#define E3G_SPDIF_FORMAT_CLEAR_MASK 0xfffff01f + +/* Clock detect bits reported by the DSP */ +#define E3G_CLOCK_DETECT_BIT_WORD96 0x0001 +#define E3G_CLOCK_DETECT_BIT_WORD48 0x0002 +#define E3G_CLOCK_DETECT_BIT_SPDIF48 0x0004 +#define E3G_CLOCK_DETECT_BIT_ADAT 0x0004 +#define E3G_CLOCK_DETECT_BIT_SPDIF96 0x0008 +#define E3G_CLOCK_DETECT_BIT_WORD (E3G_CLOCK_DETECT_BIT_WORD96|E3G_CLOCK_DETECT_BIT_WORD48) +#define E3G_CLOCK_DETECT_BIT_SPDIF (E3G_CLOCK_DETECT_BIT_SPDIF48|E3G_CLOCK_DETECT_BIT_SPDIF96) + +/* Frequency control register */ +#define E3G_MAGIC_NUMBER 677376000 +#define E3G_FREQ_REG_DEFAULT (E3G_MAGIC_NUMBER / 48000 - 2) +#define E3G_FREQ_REG_MAX 0xffff + +/* 3G external box types */ +#define E3G_GINA3G_BOX_TYPE 0x00 +#define E3G_LAYLA3G_BOX_TYPE 0x10 +#define E3G_ASIC_NOT_LOADED 0xffff +#define E3G_BOX_TYPE_MASK 0xf0 + +#define EXT_3GBOX_NC 0x01 +#define EXT_3GBOX_NOT_SET 0x02 + + +/* + * + * Gina20 & Layla20 have input gain controls for the analog inputs; + * this is the magic number for the hardware that gives you 0 dB at -10. + * + */ + +#define GL20_INPUT_GAIN_MAGIC_NUMBER 0xC8 + + +/* + * + * Defines how much time must pass between DSP load attempts + * + */ + +#define DSP_LOAD_ATTEMPT_PERIOD 1000000L /* One second */ + + +/* + * + * Size of arrays for the comm page. MAX_PLAY_TAPS and MAX_REC_TAPS are + * no longer used, but the sizes must still be right for the DSP to see + * the comm page correctly. + * + */ + +#define MONITOR_ARRAY_SIZE 0x180 +#define VMIXER_ARRAY_SIZE 0x40 +#define MIDI_OUT_BUFFER_SIZE 32 +#define MIDI_IN_BUFFER_SIZE 256 +#define MAX_PLAY_TAPS 168 +#define MAX_REC_TAPS 192 +#define DSP_MIDI_OUT_FIFO_SIZE 64 + + +/* sg_entry is a single entry for the scatter-gather list. The array of struct +sg_entry struct is read by the DSP, so all values must be little-endian. */ + +#define MAX_SGLIST_ENTRIES 512 + +struct sg_entry { + u32 addr; + u32 size; +}; + + +/**************************************************************************** + + The comm page. This structure is read and written by the DSP; the + DSP code is a firm believer in the byte offsets written in the comments + at the end of each line. This structure should not be changed. + + Any reads from or writes to this structure should be in little-endian format. + + ****************************************************************************/ + +struct comm_page { /* Base Length*/ + u32 comm_size; /* size of this object 0x000 4 */ + u32 flags; /* See Appendix A below 0x004 4 */ + u32 unused; /* Unused entry 0x008 4 */ + u32 sample_rate; /* Card sample rate in Hz 0x00c 4 */ + volatile u32 handshake; /* DSP command handshake 0x010 4 */ + u32 cmd_start; /* Chs. to start mask 0x014 4 */ + u32 cmd_stop; /* Chs. to stop mask 0x018 4 */ + u32 cmd_reset; /* Chs. to reset mask 0x01c 4 */ + u16 audio_format[DSP_MAXPIPES]; /* Chs. audio format 0x020 32*2 */ + struct sg_entry sglist_addr[DSP_MAXPIPES]; + /* Chs. Physical sglist addrs 0x060 32*8 */ + volatile u32 position[DSP_MAXPIPES]; + /* Positions for ea. ch. 0x160 32*4 */ + volatile s8 vu_meter[DSP_MAXPIPES]; + /* VU meters 0x1e0 32*1 */ + volatile s8 peak_meter[DSP_MAXPIPES]; + /* Peak meters 0x200 32*1 */ + s8 line_out_level[DSP_MAXAUDIOOUTPUTS]; + /* Output gain 0x220 16*1 */ + s8 line_in_level[DSP_MAXAUDIOINPUTS]; + /* Input gain 0x230 16*1 */ + s8 monitors[MONITOR_ARRAY_SIZE]; + /* Monitor map 0x240 0x180 */ + u32 play_coeff[MAX_PLAY_TAPS]; + /* Gina/Darla play filters - obsolete 0x3c0 168*4 */ + u32 rec_coeff[MAX_REC_TAPS]; + /* Gina/Darla record filters - obsolete 0x660 192*4 */ + volatile u16 midi_input[MIDI_IN_BUFFER_SIZE]; + /* MIDI input data transfer buffer 0x960 256*2 */ + u8 gd_clock_state; /* Chg Gina/Darla clock state 0xb60 1 */ + u8 gd_spdif_status; /* Chg. Gina/Darla S/PDIF state 0xb61 1 */ + u8 gd_resampler_state; /* Should always be 3 0xb62 1 */ + u8 filler2; /* 0xb63 1 */ + u32 nominal_level_mask; /* -10 level enable mask 0xb64 4 */ + u16 input_clock; /* Chg. Input clock state 0xb68 2 */ + u16 output_clock; /* Chg. Output clock state 0xb6a 2 */ + volatile u32 status_clocks; + /* Current Input clock state 0xb6c 4 */ + u32 ext_box_status; /* External box status 0xb70 4 */ + u32 cmd_add_buffer; /* Pipes to add (obsolete) 0xb74 4 */ + volatile u32 midi_out_free_count; + /* # of bytes free in MIDI output FIFO 0xb78 4 */ + u32 unused2; /* Cyclic pipes 0xb7c 4 */ + u32 control_register; + /* Mona, Gina24, Layla24, 3G ctrl reg 0xb80 4 */ + u32 e3g_frq_register; /* 3G frequency register 0xb84 4 */ + u8 filler[24]; /* filler 0xb88 24*1 */ + s8 vmixer[VMIXER_ARRAY_SIZE]; + /* Vmixer levels 0xba0 64*1 */ + u8 midi_output[MIDI_OUT_BUFFER_SIZE]; + /* MIDI output data 0xbe0 32*1 */ +}; + +#endif /* _ECHO_DSP_ */ diff --git a/sound/pci/echoaudio/echoaudio_gml.c b/sound/pci/echoaudio/echoaudio_gml.c new file mode 100644 index 000000000..3aa37e76e --- /dev/null +++ b/sound/pci/echoaudio/echoaudio_gml.c @@ -0,0 +1,198 @@ +/**************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + ************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + +****************************************************************************/ + + +/* These functions are common for Gina24, Layla24 and Mona cards */ + + +/* ASIC status check - some cards have one or two ASICs that need to be +loaded. Once that load is complete, this function is called to see if +the load was successful. +If this load fails, it does not necessarily mean that the hardware is +defective - the external box may be disconnected or turned off. */ +static int check_asic_status(struct echoaudio *chip) +{ + u32 asic_status; + + send_vector(chip, DSP_VC_TEST_ASIC); + + /* The DSP will return a value to indicate whether or not the + ASIC is currently loaded */ + if (read_dsp(chip, &asic_status) < 0) { + DE_INIT(("check_asic_status: failed on read_dsp\n")); + chip->asic_loaded = FALSE; + return -EIO; + } + + chip->asic_loaded = (asic_status == ASIC_ALREADY_LOADED); + return chip->asic_loaded ? 0 : -EIO; +} + + + +/* Most configuration of Gina24, Layla24, or Mona is accomplished by writing +the control register. write_control_reg sends the new control register +value to the DSP. */ +static int write_control_reg(struct echoaudio *chip, u32 value, char force) +{ + /* Handle the digital input auto-mute */ + if (chip->digital_in_automute) + value |= GML_DIGITAL_IN_AUTO_MUTE; + else + value &= ~GML_DIGITAL_IN_AUTO_MUTE; + + DE_ACT(("write_control_reg: 0x%x\n", value)); + + /* Write the control register */ + value = cpu_to_le32(value); + if (value != chip->comm_page->control_register || force) { + if (wait_handshake(chip)) + return -EIO; + chip->comm_page->control_register = value; + clear_handshake(chip); + return send_vector(chip, DSP_VC_WRITE_CONTROL_REG); + } + return 0; +} + + + +/* Gina24, Layla24, and Mona support digital input auto-mute. If the digital +input auto-mute is enabled, the DSP will only enable the digital inputs if +the card is syncing to a valid clock on the ADAT or S/PDIF inputs. +If the auto-mute is disabled, the digital inputs are enabled regardless of +what the input clock is set or what is connected. */ +static int set_input_auto_mute(struct echoaudio *chip, int automute) +{ + DE_ACT(("set_input_auto_mute %d\n", automute)); + + chip->digital_in_automute = automute; + + /* Re-set the input clock to the current value - indirectly causes + the auto-mute flag to be sent to the DSP */ + return set_input_clock(chip, chip->input_clock); +} + + + +/* S/PDIF coax / S/PDIF optical / ADAT - switch */ +static int set_digital_mode(struct echoaudio *chip, u8 mode) +{ + u8 previous_mode; + int err, i, o; + + if (chip->bad_board) + return -EIO; + + /* All audio channels must be closed before changing the digital mode */ + snd_assert(!chip->pipe_alloc_mask, return -EAGAIN); + + snd_assert(chip->digital_modes & (1 << mode), return -EINVAL); + + previous_mode = chip->digital_mode; + err = dsp_set_digital_mode(chip, mode); + + /* If we successfully changed the digital mode from or to ADAT, + then make sure all output, input and monitor levels are + updated by the DSP comm object. */ + if (err >= 0 && previous_mode != mode && + (previous_mode == DIGITAL_MODE_ADAT || mode == DIGITAL_MODE_ADAT)) { + spin_lock_irq(&chip->lock); + for (o = 0; o < num_busses_out(chip); o++) + for (i = 0; i < num_busses_in(chip); i++) + set_monitor_gain(chip, o, i, + chip->monitor_gain[o][i]); + +#ifdef ECHOCARD_HAS_INPUT_GAIN + for (i = 0; i < num_busses_in(chip); i++) + set_input_gain(chip, i, chip->input_gain[i]); + update_input_line_level(chip); +#endif + + for (o = 0; o < num_busses_out(chip); o++) + set_output_gain(chip, o, chip->output_gain[o]); + update_output_line_level(chip); + spin_unlock_irq(&chip->lock); + } + + return err; +} + + + +/* Set the S/PDIF output format */ +static int set_professional_spdif(struct echoaudio *chip, char prof) +{ + u32 control_reg; + int err; + + /* Clear the current S/PDIF flags */ + control_reg = le32_to_cpu(chip->comm_page->control_register); + control_reg &= GML_SPDIF_FORMAT_CLEAR_MASK; + + /* Set the new S/PDIF flags depending on the mode */ + control_reg |= GML_SPDIF_TWO_CHANNEL | GML_SPDIF_24_BIT | + GML_SPDIF_COPY_PERMIT; + if (prof) { + /* Professional mode */ + control_reg |= GML_SPDIF_PRO_MODE; + + switch (chip->sample_rate) { + case 32000: + control_reg |= GML_SPDIF_SAMPLE_RATE0 | + GML_SPDIF_SAMPLE_RATE1; + break; + case 44100: + control_reg |= GML_SPDIF_SAMPLE_RATE0; + break; + case 48000: + control_reg |= GML_SPDIF_SAMPLE_RATE1; + break; + } + } else { + /* Consumer mode */ + switch (chip->sample_rate) { + case 32000: + control_reg |= GML_SPDIF_SAMPLE_RATE0 | + GML_SPDIF_SAMPLE_RATE1; + break; + case 48000: + control_reg |= GML_SPDIF_SAMPLE_RATE1; + break; + } + } + + if ((err = write_control_reg(chip, control_reg, FALSE))) + return err; + chip->professional_spdif = prof; + DE_ACT(("set_professional_spdif to %s\n", + prof ? "Professional" : "Consumer")); + return 0; +} diff --git a/sound/pci/echoaudio/gina20.c b/sound/pci/echoaudio/gina20.c new file mode 100644 index 000000000..29d6d12f8 --- /dev/null +++ b/sound/pci/echoaudio/gina20.c @@ -0,0 +1,103 @@ +/* + * ALSA driver for Echoaudio soundcards. + * Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it> + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define ECHOGALS_FAMILY +#define ECHOCARD_GINA20 +#define ECHOCARD_NAME "Gina20" +#define ECHOCARD_HAS_MONITOR +#define ECHOCARD_HAS_INPUT_GAIN +#define ECHOCARD_HAS_DIGITAL_IO +#define ECHOCARD_HAS_EXTERNAL_CLOCK +#define ECHOCARD_HAS_ADAT FALSE + +/* Pipe indexes */ +#define PX_ANALOG_OUT 0 /* 8 */ +#define PX_DIGITAL_OUT 8 /* 2 */ +#define PX_ANALOG_IN 10 /* 2 */ +#define PX_DIGITAL_IN 12 /* 2 */ +#define PX_NUM 14 + +/* Bus indexes */ +#define BX_ANALOG_OUT 0 /* 8 */ +#define BX_DIGITAL_OUT 8 /* 2 */ +#define BX_ANALOG_IN 10 /* 2 */ +#define BX_DIGITAL_IN 12 /* 2 */ +#define BX_NUM 14 + + +#include <sound/driver.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/slab.h> +#include <linux/moduleparam.h> +#include <linux/firmware.h> +#include <sound/core.h> +#include <sound/info.h> +#include <sound/control.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/asoundef.h> +#include <sound/initval.h> +#include <asm/io.h> +#include <asm/atomic.h> +#include "echoaudio.h" + +#define FW_GINA20_DSP 0 + +static const struct firmware card_fw[] = { + {0, "gina20_dsp.fw"} +}; + +static struct pci_device_id snd_echo_ids[] = { + {0x1057, 0x1801, 0xECC0, 0x0020, 0, 0, 0}, /* DSP 56301 Gina20 rev.0 */ + {0,} +}; + +static struct snd_pcm_hardware pcm_hardware_skel = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S32_BE, + .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, + .rate_min = 44100, + .rate_max = 48000, + .channels_min = 1, + .channels_max = 2, + .buffer_bytes_max = 262144, + .period_bytes_min = 32, + .period_bytes_max = 131072, + .periods_min = 2, + .periods_max = 220, + /* One page (4k) contains 512 instructions. I don't know if the hw + supports lists longer than this. In this case periods_max=220 is a + safe limit to make sure the list never exceeds 512 instructions. */ +}; + + +#include "gina20_dsp.c" +#include "echoaudio_dsp.c" +#include "echoaudio.c" diff --git a/sound/pci/echoaudio/gina20_dsp.c b/sound/pci/echoaudio/gina20_dsp.c new file mode 100644 index 000000000..2757c8960 --- /dev/null +++ b/sound/pci/echoaudio/gina20_dsp.c @@ -0,0 +1,215 @@ +/**************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + ************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + +****************************************************************************/ + + +static int set_professional_spdif(struct echoaudio *chip, char prof); +static int update_flags(struct echoaudio *chip); + + +static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) +{ + int err; + + DE_INIT(("init_hw() - Gina20\n")); + snd_assert((subdevice_id & 0xfff0) == GINA20, return -ENODEV); + + if ((err = init_dsp_comm_page(chip))) { + DE_INIT(("init_hw - could not initialize DSP comm page\n")); + return err; + } + + chip->device_id = device_id; + chip->subdevice_id = subdevice_id; + chip->bad_board = TRUE; + chip->dsp_code_to_load = &card_fw[FW_GINA20_DSP]; + chip->spdif_status = GD_SPDIF_STATUS_UNDEF; + chip->clock_state = GD_CLOCK_UNDEF; + /* Since this card has no ASIC, mark it as loaded so everything + works OK */ + chip->asic_loaded = TRUE; + chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | + ECHO_CLOCK_BIT_SPDIF; + + if ((err = load_firmware(chip)) < 0) + return err; + chip->bad_board = FALSE; + + if ((err = init_line_levels(chip)) < 0) + return err; + + err = set_professional_spdif(chip, TRUE); + + DE_INIT(("init_hw done\n")); + return err; +} + + + +static u32 detect_input_clocks(const struct echoaudio *chip) +{ + u32 clocks_from_dsp, clock_bits; + + /* Map the DSP clock detect bits to the generic driver clock + detect bits */ + clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); + + clock_bits = ECHO_CLOCK_BIT_INTERNAL; + + if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF) + clock_bits |= ECHO_CLOCK_BIT_SPDIF; + + return clock_bits; +} + + + +/* The Gina20 has no ASIC. Just do nothing */ +static int load_asic(struct echoaudio *chip) +{ + return 0; +} + + + +static int set_sample_rate(struct echoaudio *chip, u32 rate) +{ + u8 clock_state, spdif_status; + + if (wait_handshake(chip)) + return -EIO; + + switch (rate) { + case 44100: + clock_state = GD_CLOCK_44; + spdif_status = GD_SPDIF_STATUS_44; + break; + case 48000: + clock_state = GD_CLOCK_48; + spdif_status = GD_SPDIF_STATUS_48; + break; + default: + clock_state = GD_CLOCK_NOCHANGE; + spdif_status = GD_SPDIF_STATUS_NOCHANGE; + break; + } + + if (chip->clock_state == clock_state) + clock_state = GD_CLOCK_NOCHANGE; + if (spdif_status == chip->spdif_status) + spdif_status = GD_SPDIF_STATUS_NOCHANGE; + + chip->comm_page->sample_rate = cpu_to_le32(rate); + chip->comm_page->gd_clock_state = clock_state; + chip->comm_page->gd_spdif_status = spdif_status; + chip->comm_page->gd_resampler_state = 3; /* magic number - should always be 3 */ + + /* Save the new audio state if it changed */ + if (clock_state != GD_CLOCK_NOCHANGE) + chip->clock_state = clock_state; + if (spdif_status != GD_SPDIF_STATUS_NOCHANGE) + chip->spdif_status = spdif_status; + chip->sample_rate = rate; + + clear_handshake(chip); + return send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE); +} + + + +static int set_input_clock(struct echoaudio *chip, u16 clock) +{ + DE_ACT(("set_input_clock:\n")); + + switch (clock) { + case ECHO_CLOCK_INTERNAL: + /* Reset the audio state to unknown (just in case) */ + chip->clock_state = GD_CLOCK_UNDEF; + chip->spdif_status = GD_SPDIF_STATUS_UNDEF; + set_sample_rate(chip, chip->sample_rate); + chip->input_clock = clock; + DE_ACT(("Set Gina clock to INTERNAL\n")); + break; + case ECHO_CLOCK_SPDIF: + chip->comm_page->gd_clock_state = GD_CLOCK_SPDIFIN; + chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_NOCHANGE; + clear_handshake(chip); + send_vector(chip, DSP_VC_SET_GD_AUDIO_STATE); + chip->clock_state = GD_CLOCK_SPDIFIN; + DE_ACT(("Set Gina20 clock to SPDIF\n")); + chip->input_clock = clock; + break; + default: + return -EINVAL; + } + + return 0; +} + + + +/* Set input bus gain (one unit is 0.5dB !) */ +static int set_input_gain(struct echoaudio *chip, u16 input, int gain) +{ + snd_assert(input < num_busses_in(chip), return -EINVAL); + + if (wait_handshake(chip)) + return -EIO; + + chip->input_gain[input] = gain; + gain += GL20_INPUT_GAIN_MAGIC_NUMBER; + chip->comm_page->line_in_level[input] = gain; + return 0; +} + + + +/* Tell the DSP to reread the flags from the comm page */ +static int update_flags(struct echoaudio *chip) +{ + if (wait_handshake(chip)) + return -EIO; + clear_handshake(chip); + return send_vector(chip, DSP_VC_UPDATE_FLAGS); +} + + + +static int set_professional_spdif(struct echoaudio *chip, char prof) +{ + DE_ACT(("set_professional_spdif %d\n", prof)); + if (prof) + chip->comm_page->flags |= + __constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); + else + chip->comm_page->flags &= + ~__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); + chip->professional_spdif = prof; + return update_flags(chip); +} diff --git a/sound/pci/echoaudio/gina24.c b/sound/pci/echoaudio/gina24.c new file mode 100644 index 000000000..e464d720d --- /dev/null +++ b/sound/pci/echoaudio/gina24.c @@ -0,0 +1,123 @@ +/* + * ALSA driver for Echoaudio soundcards. + * Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it> + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define ECHO24_FAMILY +#define ECHOCARD_GINA24 +#define ECHOCARD_NAME "Gina24" +#define ECHOCARD_HAS_MONITOR +#define ECHOCARD_HAS_ASIC +#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL +#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL +#define ECHOCARD_HAS_SUPER_INTERLEAVE +#define ECHOCARD_HAS_DIGITAL_IO +#define ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE +#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH +#define ECHOCARD_HAS_EXTERNAL_CLOCK +#define ECHOCARD_HAS_ADAT 6 +#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 + +/* Pipe indexes */ +#define PX_ANALOG_OUT 0 /* 8 */ +#define PX_DIGITAL_OUT 8 /* 8 */ +#define PX_ANALOG_IN 16 /* 2 */ +#define PX_DIGITAL_IN 18 /* 8 */ +#define PX_NUM 26 + +/* Bus indexes */ +#define BX_ANALOG_OUT 0 /* 8 */ +#define BX_DIGITAL_OUT 8 /* 8 */ +#define BX_ANALOG_IN 16 /* 2 */ +#define BX_DIGITAL_IN 18 /* 8 */ +#define BX_NUM 26 + + +#include <sound/driver.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/slab.h> +#include <linux/moduleparam.h> +#include <linux/firmware.h> +#include <sound/core.h> +#include <sound/info.h> +#include <sound/control.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/asoundef.h> +#include <sound/initval.h> +#include <asm/io.h> +#include <asm/atomic.h> +#include "echoaudio.h" + +#define FW_361_LOADER 0 +#define FW_GINA24_301_DSP 1 +#define FW_GINA24_361_DSP 2 +#define FW_GINA24_301_ASIC 3 +#define FW_GINA24_361_ASIC 4 + +static const struct firmware card_fw[] = { + {0, "loader_dsp.fw"}, + {0, "gina24_301_dsp.fw"}, + {0, "gina24_361_dsp.fw"}, + {0, "gina24_301_asic.fw"}, + {0, "gina24_361_asic.fw"} +}; + +static struct pci_device_id snd_echo_ids[] = { + {0x1057, 0x1801, 0xECC0, 0x0050, 0, 0, 0}, /* DSP 56301 Gina24 rev.0 */ + {0x1057, 0x1801, 0xECC0, 0x0051, 0, 0, 0}, /* DSP 56301 Gina24 rev.1 */ + {0x1057, 0x3410, 0xECC0, 0x0050, 0, 0, 0}, /* DSP 56361 Gina24 rev.0 */ + {0x1057, 0x3410, 0xECC0, 0x0051, 0, 0, 0}, /* DSP 56361 Gina24 rev.1 */ + {0,} +}; + +static struct snd_pcm_hardware pcm_hardware_skel = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S32_BE, + .rates = SNDRV_PCM_RATE_8000_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000, + .rate_min = 8000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + .buffer_bytes_max = 262144, + .period_bytes_min = 32, + .period_bytes_max = 131072, + .periods_min = 2, + .periods_max = 220, + /* One page (4k) contains 512 instructions. I don't know if the hw + supports lists longer than this. In this case periods_max=220 is a + safe limit to make sure the list never exceeds 512 instructions. + 220 ~= (512 - 1 - (BUFFER_BYTES_MAX / PAGE_SIZE)) / 2 */ +}; + +#include "gina24_dsp.c" +#include "echoaudio_dsp.c" +#include "echoaudio_gml.c" +#include "echoaudio.c" diff --git a/sound/pci/echoaudio/gina24_dsp.c b/sound/pci/echoaudio/gina24_dsp.c new file mode 100644 index 000000000..144fc567b --- /dev/null +++ b/sound/pci/echoaudio/gina24_dsp.c @@ -0,0 +1,346 @@ +/**************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + ************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + +****************************************************************************/ + + +static int write_control_reg(struct echoaudio *chip, u32 value, char force); +static int set_input_clock(struct echoaudio *chip, u16 clock); +static int set_professional_spdif(struct echoaudio *chip, char prof); +static int set_digital_mode(struct echoaudio *chip, u8 mode); +static int load_asic_generic(struct echoaudio *chip, u32 cmd, + const struct firmware *asic); +static int check_asic_status(struct echoaudio *chip); + + +static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) +{ + int err; + + DE_INIT(("init_hw() - Gina24\n")); + snd_assert((subdevice_id & 0xfff0) == GINA24, return -ENODEV); + + if ((err = init_dsp_comm_page(chip))) { + DE_INIT(("init_hw - could not initialize DSP comm page\n")); + return err; + } + + chip->device_id = device_id; + chip->subdevice_id = subdevice_id; + chip->bad_board = TRUE; + chip->input_clock_types = + ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | + ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96 | + ECHO_CLOCK_BIT_ADAT; + chip->professional_spdif = FALSE; + chip->digital_in_automute = TRUE; + chip->digital_mode = DIGITAL_MODE_SPDIF_RCA; + + /* Gina24 comes in both '301 and '361 flavors */ + if (chip->device_id == DEVICE_ID_56361) { + chip->dsp_code_to_load = &card_fw[FW_GINA24_361_DSP]; + chip->digital_modes = + ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | + ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | + ECHOCAPS_HAS_DIGITAL_MODE_ADAT; + } else { + chip->dsp_code_to_load = &card_fw[FW_GINA24_301_DSP]; + chip->digital_modes = + ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | + ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | + ECHOCAPS_HAS_DIGITAL_MODE_ADAT | + ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_CDROM; + } + + if ((err = load_firmware(chip)) < 0) + return err; + chip->bad_board = FALSE; + + if ((err = init_line_levels(chip)) < 0) + return err; + err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA); + snd_assert(err >= 0, return err); + err = set_professional_spdif(chip, TRUE); + + DE_INIT(("init_hw done\n")); + return err; +} + + + +static u32 detect_input_clocks(const struct echoaudio *chip) +{ + u32 clocks_from_dsp, clock_bits; + + /* Map the DSP clock detect bits to the generic driver clock + detect bits */ + clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); + + clock_bits = ECHO_CLOCK_BIT_INTERNAL; + + if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF) + clock_bits |= ECHO_CLOCK_BIT_SPDIF; + + if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT) + clock_bits |= ECHO_CLOCK_BIT_ADAT; + + if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ESYNC) + clock_bits |= ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96; + + return clock_bits; +} + + + +/* Gina24 has an ASIC on the PCI card which must be loaded for anything +interesting to happen. */ +static int load_asic(struct echoaudio *chip) +{ + u32 control_reg; + int err; + const struct firmware *fw; + + if (chip->asic_loaded) + return 1; + + /* Give the DSP a few milliseconds to settle down */ + mdelay(10); + + /* Pick the correct ASIC for '301 or '361 Gina24 */ + if (chip->device_id == DEVICE_ID_56361) + fw = &card_fw[FW_GINA24_361_ASIC]; + else + fw = &card_fw[FW_GINA24_301_ASIC]; + + if ((err = load_asic_generic(chip, DSP_FNC_LOAD_GINA24_ASIC, fw)) < 0) + return err; + + chip->asic_code = fw; + + /* Now give the new ASIC a little time to set up */ + mdelay(10); + /* See if it worked */ + err = check_asic_status(chip); + + /* Set up the control register if the load succeeded - + 48 kHz, internal clock, S/PDIF RCA mode */ + if (!err) { + control_reg = GML_CONVERTER_ENABLE | GML_48KHZ; + err = write_control_reg(chip, control_reg, TRUE); + } + DE_INIT(("load_asic() done\n")); + return err; +} + + + +static int set_sample_rate(struct echoaudio *chip, u32 rate) +{ + u32 control_reg, clock; + + snd_assert(rate < 50000 || chip->digital_mode != DIGITAL_MODE_ADAT, + return -EINVAL); + + /* Only set the clock for internal mode. */ + if (chip->input_clock != ECHO_CLOCK_INTERNAL) { + DE_ACT(("set_sample_rate: Cannot set sample rate - " + "clock not set to CLK_CLOCKININTERNAL\n")); + /* Save the rate anyhow */ + chip->comm_page->sample_rate = cpu_to_le32(rate); + chip->sample_rate = rate; + return 0; + } + + clock = 0; + + control_reg = le32_to_cpu(chip->comm_page->control_register); + control_reg &= GML_CLOCK_CLEAR_MASK & GML_SPDIF_RATE_CLEAR_MASK; + + switch (rate) { + case 96000: + clock = GML_96KHZ; + break; + case 88200: + clock = GML_88KHZ; + break; + case 48000: + clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1; + break; + case 44100: + clock = GML_44KHZ; + /* Professional mode ? */ + if (control_reg & GML_SPDIF_PRO_MODE) + clock |= GML_SPDIF_SAMPLE_RATE0; + break; + case 32000: + clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 | + GML_SPDIF_SAMPLE_RATE1; + break; + case 22050: + clock = GML_22KHZ; + break; + case 16000: + clock = GML_16KHZ; + break; + case 11025: + clock = GML_11KHZ; + break; + case 8000: + clock = GML_8KHZ; + break; + default: + DE_ACT(("set_sample_rate: %d invalid!\n", rate)); + return -EINVAL; + } + + control_reg |= clock; + + chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ + chip->sample_rate = rate; + DE_ACT(("set_sample_rate: %d clock %d\n", rate, clock)); + + return write_control_reg(chip, control_reg, FALSE); +} + + + +static int set_input_clock(struct echoaudio *chip, u16 clock) +{ + u32 control_reg, clocks_from_dsp; + + DE_ACT(("set_input_clock:\n")); + + /* Mask off the clock select bits */ + control_reg = le32_to_cpu(chip->comm_page->control_register) & + GML_CLOCK_CLEAR_MASK; + clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); + + switch (clock) { + case ECHO_CLOCK_INTERNAL: + DE_ACT(("Set Gina24 clock to INTERNAL\n")); + chip->input_clock = ECHO_CLOCK_INTERNAL; + return set_sample_rate(chip, chip->sample_rate); + case ECHO_CLOCK_SPDIF: + if (chip->digital_mode == DIGITAL_MODE_ADAT) + return -EAGAIN; + DE_ACT(("Set Gina24 clock to SPDIF\n")); + control_reg |= GML_SPDIF_CLOCK; + if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF96) + control_reg |= GML_DOUBLE_SPEED_MODE; + else + control_reg &= ~GML_DOUBLE_SPEED_MODE; + break; + case ECHO_CLOCK_ADAT: + if (chip->digital_mode != DIGITAL_MODE_ADAT) + return -EAGAIN; + DE_ACT(("Set Gina24 clock to ADAT\n")); + control_reg |= GML_ADAT_CLOCK; + control_reg &= ~GML_DOUBLE_SPEED_MODE; + break; + case ECHO_CLOCK_ESYNC: + DE_ACT(("Set Gina24 clock to ESYNC\n")); + control_reg |= GML_ESYNC_CLOCK; + control_reg &= ~GML_DOUBLE_SPEED_MODE; + break; + case ECHO_CLOCK_ESYNC96: + DE_ACT(("Set Gina24 clock to ESYNC96\n")); + control_reg |= GML_ESYNC_CLOCK | GML_DOUBLE_SPEED_MODE; + break; + default: + DE_ACT(("Input clock 0x%x not supported for Gina24\n", clock)); + return -EINVAL; + } + + chip->input_clock = clock; + return write_control_reg(chip, control_reg, TRUE); +} + + + +static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) +{ + u32 control_reg; + int err, incompatible_clock; + + /* Set clock to "internal" if it's not compatible with the new mode */ + incompatible_clock = FALSE; + switch (mode) { + case DIGITAL_MODE_SPDIF_OPTICAL: + case DIGITAL_MODE_SPDIF_CDROM: + case DIGITAL_MODE_SPDIF_RCA: + if (chip->input_clock == ECHO_CLOCK_ADAT) + incompatible_clock = TRUE; + break; + case DIGITAL_MODE_ADAT: + if (chip->input_clock == ECHO_CLOCK_SPDIF) + incompatible_clock = TRUE; + break; + default: + DE_ACT(("Digital mode not supported: %d\n", mode)); + return -EINVAL; + } + + spin_lock_irq(&chip->lock); + + if (incompatible_clock) { /* Switch to 48KHz, internal */ + chip->sample_rate = 48000; + set_input_clock(chip, ECHO_CLOCK_INTERNAL); + } + + /* Clear the current digital mode */ + control_reg = le32_to_cpu(chip->comm_page->control_register); + control_reg &= GML_DIGITAL_MODE_CLEAR_MASK; + + /* Tweak the control reg */ + switch (mode) { + case DIGITAL_MODE_SPDIF_OPTICAL: + control_reg |= GML_SPDIF_OPTICAL_MODE; + break; + case DIGITAL_MODE_SPDIF_CDROM: + /* '361 Gina24 cards do not have the S/PDIF CD-ROM mode */ + if (chip->device_id == DEVICE_ID_56301) + control_reg |= GML_SPDIF_CDROM_MODE; + break; + case DIGITAL_MODE_SPDIF_RCA: + /* GML_SPDIF_OPTICAL_MODE bit cleared */ + break; + case DIGITAL_MODE_ADAT: + control_reg |= GML_ADAT_MODE; + control_reg &= ~GML_DOUBLE_SPEED_MODE; + break; + } + + err = write_control_reg(chip, control_reg, TRUE); + spin_unlock_irq(&chip->lock); + if (err < 0) + return err; + chip->digital_mode = mode; + + DE_ACT(("set_digital_mode to %d\n", chip->digital_mode)); + return incompatible_clock; +} diff --git a/sound/pci/echoaudio/indigo.c b/sound/pci/echoaudio/indigo.c new file mode 100644 index 000000000..bfd246709 --- /dev/null +++ b/sound/pci/echoaudio/indigo.c @@ -0,0 +1,104 @@ +/* + * ALSA driver for Echoaudio soundcards. + * Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it> + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define INDIGO_FAMILY +#define ECHOCARD_INDIGO +#define ECHOCARD_NAME "Indigo" +#define ECHOCARD_HAS_SUPER_INTERLEAVE +#define ECHOCARD_HAS_VMIXER +#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 + +/* Pipe indexes */ +#define PX_ANALOG_OUT 0 /* 8 */ +#define PX_DIGITAL_OUT 8 /* 0 */ +#define PX_ANALOG_IN 8 /* 0 */ +#define PX_DIGITAL_IN 8 /* 0 */ +#define PX_NUM 8 + +/* Bus indexes */ +#define BX_ANALOG_OUT 0 /* 2 */ +#define BX_DIGITAL_OUT 2 /* 0 */ +#define BX_ANALOG_IN 2 /* 0 */ +#define BX_DIGITAL_IN 2 /* 0 */ +#define BX_NUM 2 + + +#include <sound/driver.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/slab.h> +#include <linux/moduleparam.h> +#include <linux/firmware.h> +#include <sound/core.h> +#include <sound/info.h> +#include <sound/control.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/asoundef.h> +#include <sound/initval.h> +#include <asm/io.h> +#include <asm/atomic.h> +#include "echoaudio.h" + +#define FW_361_LOADER 0 +#define FW_INDIGO_DSP 1 + +static const struct firmware card_fw[] = { + {0, "loader_dsp.fw"}, + {0, "indigo_dsp.fw"} +}; + +static struct pci_device_id snd_echo_ids[] = { + {0x1057, 0x3410, 0xECC0, 0x0090, 0, 0, 0}, /* Indigo */ + {0,} +}; + +static struct snd_pcm_hardware pcm_hardware_skel = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S32_BE, + .rates = SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000, + .rate_min = 32000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + .buffer_bytes_max = 262144, + .period_bytes_min = 32, + .period_bytes_max = 131072, + .periods_min = 2, + .periods_max = 220, +}; + +#include "indigo_dsp.c" +#include "echoaudio_dsp.c" +#include "echoaudio.c" + diff --git a/sound/pci/echoaudio/indigo_dsp.c b/sound/pci/echoaudio/indigo_dsp.c new file mode 100644 index 000000000..d6ac77346 --- /dev/null +++ b/sound/pci/echoaudio/indigo_dsp.c @@ -0,0 +1,170 @@ +/**************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + ************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + +****************************************************************************/ + + +static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, + int gain); +static int update_vmixer_level(struct echoaudio *chip); + + +static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) +{ + int err; + + DE_INIT(("init_hw() - Indigo\n")); + snd_assert((subdevice_id & 0xfff0) == INDIGO, return -ENODEV); + + if ((err = init_dsp_comm_page(chip))) { + DE_INIT(("init_hw - could not initialize DSP comm page\n")); + return err; + } + + chip->device_id = device_id; + chip->subdevice_id = subdevice_id; + chip->bad_board = TRUE; + chip->dsp_code_to_load = &card_fw[FW_INDIGO_DSP]; + /* Since this card has no ASIC, mark it as loaded so everything + works OK */ + chip->asic_loaded = TRUE; + chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; + + if ((err = load_firmware(chip)) < 0) + return err; + chip->bad_board = FALSE; + + if ((err = init_line_levels(chip)) < 0) + return err; + + /* Default routing of the virtual channels: all vchannels are routed + to the stereo output */ + set_vmixer_gain(chip, 0, 0, 0); + set_vmixer_gain(chip, 1, 1, 0); + set_vmixer_gain(chip, 0, 2, 0); + set_vmixer_gain(chip, 1, 3, 0); + set_vmixer_gain(chip, 0, 4, 0); + set_vmixer_gain(chip, 1, 5, 0); + set_vmixer_gain(chip, 0, 6, 0); + set_vmixer_gain(chip, 1, 7, 0); + err = update_vmixer_level(chip); + + DE_INIT(("init_hw done\n")); + return err; +} + + + +static u32 detect_input_clocks(const struct echoaudio *chip) +{ + return ECHO_CLOCK_BIT_INTERNAL; +} + + + +/* The Indigo has no ASIC. Just do nothing */ +static int load_asic(struct echoaudio *chip) +{ + return 0; +} + + + +static int set_sample_rate(struct echoaudio *chip, u32 rate) +{ + u32 control_reg; + + switch (rate) { + case 96000: + control_reg = MIA_96000; + break; + case 88200: + control_reg = MIA_88200; + break; + case 48000: + control_reg = MIA_48000; + break; + case 44100: + control_reg = MIA_44100; + break; + case 32000: + control_reg = MIA_32000; + break; + default: + DE_ACT(("set_sample_rate: %d invalid!\n", rate)); + return -EINVAL; + } + + /* Set the control register if it has changed */ + if (control_reg != le32_to_cpu(chip->comm_page->control_register)) { + if (wait_handshake(chip)) + return -EIO; + + chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ + chip->comm_page->control_register = cpu_to_le32(control_reg); + chip->sample_rate = rate; + + clear_handshake(chip); + return send_vector(chip, DSP_VC_UPDATE_CLOCKS); + } + return 0; +} + + + +/* This function routes the sound from a virtual channel to a real output */ +static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, + int gain) +{ + int index; + + snd_assert(pipe < num_pipes_out(chip) && + output < num_busses_out(chip), return -EINVAL); + + if (wait_handshake(chip)) + return -EIO; + + chip->vmixer_gain[output][pipe] = gain; + index = output * num_pipes_out(chip) + pipe; + chip->comm_page->vmixer[index] = gain; + + DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain)); + return 0; +} + + + +/* Tell the DSP to read and update virtual mixer levels in comm page. */ +static int update_vmixer_level(struct echoaudio *chip) +{ + if (wait_handshake(chip)) + return -EIO; + clear_handshake(chip); + return send_vector(chip, DSP_VC_SET_VMIXER_GAIN); +} + diff --git a/sound/pci/echoaudio/indigodj.c b/sound/pci/echoaudio/indigodj.c new file mode 100644 index 000000000..8ed7ff1fd --- /dev/null +++ b/sound/pci/echoaudio/indigodj.c @@ -0,0 +1,104 @@ +/* + * ALSA driver for Echoaudio soundcards. + * Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it> + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define INDIGO_FAMILY +#define ECHOCARD_INDIGO_DJ +#define ECHOCARD_NAME "Indigo DJ" +#define ECHOCARD_HAS_SUPER_INTERLEAVE +#define ECHOCARD_HAS_VMIXER +#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 + +/* Pipe indexes */ +#define PX_ANALOG_OUT 0 /* 8 */ +#define PX_DIGITAL_OUT 8 /* 0 */ +#define PX_ANALOG_IN 8 /* 0 */ +#define PX_DIGITAL_IN 8 /* 0 */ +#define PX_NUM 8 + +/* Bus indexes */ +#define BX_ANALOG_OUT 0 /* 4 */ +#define BX_DIGITAL_OUT 4 /* 0 */ +#define BX_ANALOG_IN 4 /* 0 */ +#define BX_DIGITAL_IN 4 /* 0 */ +#define BX_NUM 4 + + +#include <sound/driver.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/slab.h> +#include <linux/moduleparam.h> +#include <linux/firmware.h> +#include <sound/core.h> +#include <sound/info.h> +#include <sound/control.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/asoundef.h> +#include <sound/initval.h> +#include <asm/io.h> +#include <asm/atomic.h> +#include "echoaudio.h" + +#define FW_361_LOADER 0 +#define FW_INDIGO_DJ_DSP 1 + +static const struct firmware card_fw[] = { + {0, "loader_dsp.fw"}, + {0, "indigo_dj_dsp.fw"} +}; + +static struct pci_device_id snd_echo_ids[] = { + {0x1057, 0x3410, 0xECC0, 0x00B0, 0, 0, 0}, /* Indigo DJ*/ + {0,} +}; + +static struct snd_pcm_hardware pcm_hardware_skel = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S32_BE, + .rates = SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000, + .rate_min = 32000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 4, + .buffer_bytes_max = 262144, + .period_bytes_min = 32, + .period_bytes_max = 131072, + .periods_min = 2, + .periods_max = 220, +}; + +#include "indigodj_dsp.c" +#include "echoaudio_dsp.c" +#include "echoaudio.c" + diff --git a/sound/pci/echoaudio/indigodj_dsp.c b/sound/pci/echoaudio/indigodj_dsp.c new file mode 100644 index 000000000..500e150b4 --- /dev/null +++ b/sound/pci/echoaudio/indigodj_dsp.c @@ -0,0 +1,170 @@ +/**************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + ************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + +****************************************************************************/ + + +static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, + int gain); +static int update_vmixer_level(struct echoaudio *chip); + + +static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) +{ + int err; + + DE_INIT(("init_hw() - Indigo DJ\n")); + snd_assert((subdevice_id & 0xfff0) == INDIGO_DJ, return -ENODEV); + + if ((err = init_dsp_comm_page(chip))) { + DE_INIT(("init_hw - could not initialize DSP comm page\n")); + return err; + } + + chip->device_id = device_id; + chip->subdevice_id = subdevice_id; + chip->bad_board = TRUE; + chip->dsp_code_to_load = &card_fw[FW_INDIGO_DJ_DSP]; + /* Since this card has no ASIC, mark it as loaded so everything + works OK */ + chip->asic_loaded = TRUE; + chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; + + if ((err = load_firmware(chip)) < 0) + return err; + chip->bad_board = FALSE; + + if ((err = init_line_levels(chip)) < 0) + return err; + + /* Default routing of the virtual channels: vchannels 0-3 and + vchannels 4-7 are routed to real channels 0-4 */ + set_vmixer_gain(chip, 0, 0, 0); + set_vmixer_gain(chip, 1, 1, 0); + set_vmixer_gain(chip, 2, 2, 0); + set_vmixer_gain(chip, 3, 3, 0); + set_vmixer_gain(chip, 0, 4, 0); + set_vmixer_gain(chip, 1, 5, 0); + set_vmixer_gain(chip, 2, 6, 0); + set_vmixer_gain(chip, 3, 7, 0); + err = update_vmixer_level(chip); + + DE_INIT(("init_hw done\n")); + return err; +} + + + +static u32 detect_input_clocks(const struct echoaudio *chip) +{ + return ECHO_CLOCK_BIT_INTERNAL; +} + + + +/* The IndigoDJ has no ASIC. Just do nothing */ +static int load_asic(struct echoaudio *chip) +{ + return 0; +} + + + +static int set_sample_rate(struct echoaudio *chip, u32 rate) +{ + u32 control_reg; + + switch (rate) { + case 96000: + control_reg = MIA_96000; + break; + case 88200: + control_reg = MIA_88200; + break; + case 48000: + control_reg = MIA_48000; + break; + case 44100: + control_reg = MIA_44100; + break; + case 32000: + control_reg = MIA_32000; + break; + default: + DE_ACT(("set_sample_rate: %d invalid!\n", rate)); + return -EINVAL; + } + + /* Set the control register if it has changed */ + if (control_reg != le32_to_cpu(chip->comm_page->control_register)) { + if (wait_handshake(chip)) + return -EIO; + + chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ + chip->comm_page->control_register = cpu_to_le32(control_reg); + chip->sample_rate = rate; + + clear_handshake(chip); + return send_vector(chip, DSP_VC_UPDATE_CLOCKS); + } + return 0; +} + + + +/* This function routes the sound from a virtual channel to a real output */ +static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, + int gain) +{ + int index; + + snd_assert(pipe < num_pipes_out(chip) && + output < num_busses_out(chip), return -EINVAL); + + if (wait_handshake(chip)) + return -EIO; + + chip->vmixer_gain[output][pipe] = gain; + index = output * num_pipes_out(chip) + pipe; + chip->comm_page->vmixer[index] = gain; + + DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain)); + return 0; +} + + + +/* Tell the DSP to read and update virtual mixer levels in comm page. */ +static int update_vmixer_level(struct echoaudio *chip) +{ + if (wait_handshake(chip)) + return -EIO; + clear_handshake(chip); + return send_vector(chip, DSP_VC_SET_VMIXER_GAIN); +} + diff --git a/sound/pci/echoaudio/indigoio.c b/sound/pci/echoaudio/indigoio.c new file mode 100644 index 000000000..a8788e959 --- /dev/null +++ b/sound/pci/echoaudio/indigoio.c @@ -0,0 +1,105 @@ +/* + * ALSA driver for Echoaudio soundcards. + * Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it> + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define INDIGO_FAMILY +#define ECHOCARD_INDIGO_IO +#define ECHOCARD_NAME "Indigo IO" +#define ECHOCARD_HAS_MONITOR +#define ECHOCARD_HAS_SUPER_INTERLEAVE +#define ECHOCARD_HAS_VMIXER +#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 + +/* Pipe indexes */ +#define PX_ANALOG_OUT 0 /* 8 */ +#define PX_DIGITAL_OUT 8 /* 0 */ +#define PX_ANALOG_IN 8 /* 2 */ +#define PX_DIGITAL_IN 10 /* 0 */ +#define PX_NUM 10 + +/* Bus indexes */ +#define BX_ANALOG_OUT 0 /* 2 */ +#define BX_DIGITAL_OUT 2 /* 0 */ +#define BX_ANALOG_IN 2 /* 2 */ +#define BX_DIGITAL_IN 4 /* 0 */ +#define BX_NUM 4 + + +#include <sound/driver.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/slab.h> +#include <linux/moduleparam.h> +#include <linux/firmware.h> +#include <sound/core.h> +#include <sound/info.h> +#include <sound/control.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/asoundef.h> +#include <sound/initval.h> +#include <asm/io.h> +#include <asm/atomic.h> +#include "echoaudio.h" + +#define FW_361_LOADER 0 +#define FW_INDIGO_IO_DSP 1 + +static const struct firmware card_fw[] = { + {0, "loader_dsp.fw"}, + {0, "indigo_io_dsp.fw"} +}; + +static struct pci_device_id snd_echo_ids[] = { + {0x1057, 0x3410, 0xECC0, 0x00A0, 0, 0, 0}, /* Indigo IO*/ + {0,} +}; + +static struct snd_pcm_hardware pcm_hardware_skel = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S32_BE, + .rates = SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000, + .rate_min = 32000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + .buffer_bytes_max = 262144, + .period_bytes_min = 32, + .period_bytes_max = 131072, + .periods_min = 2, + .periods_max = 220, +}; + +#include "indigoio_dsp.c" +#include "echoaudio_dsp.c" +#include "echoaudio.c" + diff --git a/sound/pci/echoaudio/indigoio_dsp.c b/sound/pci/echoaudio/indigoio_dsp.c new file mode 100644 index 000000000..f3ad13d06 --- /dev/null +++ b/sound/pci/echoaudio/indigoio_dsp.c @@ -0,0 +1,141 @@ +/**************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + ************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + +****************************************************************************/ + + +static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, + int gain); +static int update_vmixer_level(struct echoaudio *chip); + + +static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) +{ + int err; + + DE_INIT(("init_hw() - Indigo IO\n")); + snd_assert((subdevice_id & 0xfff0) == INDIGO_IO, return -ENODEV); + + if ((err = init_dsp_comm_page(chip))) { + DE_INIT(("init_hw - could not initialize DSP comm page\n")); + return err; + } + + chip->device_id = device_id; + chip->subdevice_id = subdevice_id; + chip->bad_board = TRUE; + chip->dsp_code_to_load = &card_fw[FW_INDIGO_IO_DSP]; + /* Since this card has no ASIC, mark it as loaded so everything + works OK */ + chip->asic_loaded = TRUE; + chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; + + if ((err = load_firmware(chip)) < 0) + return err; + chip->bad_board = FALSE; + + if ((err = init_line_levels(chip)) < 0) + return err; + + /* Default routing of the virtual channels: all vchannels are routed + to the stereo output */ + set_vmixer_gain(chip, 0, 0, 0); + set_vmixer_gain(chip, 1, 1, 0); + set_vmixer_gain(chip, 0, 2, 0); + set_vmixer_gain(chip, 1, 3, 0); + set_vmixer_gain(chip, 0, 4, 0); + set_vmixer_gain(chip, 1, 5, 0); + set_vmixer_gain(chip, 0, 6, 0); + set_vmixer_gain(chip, 1, 7, 0); + err = update_vmixer_level(chip); + + DE_INIT(("init_hw done\n")); + return err; +} + + + +static u32 detect_input_clocks(const struct echoaudio *chip) +{ + return ECHO_CLOCK_BIT_INTERNAL; +} + + + +/* The IndigoIO has no ASIC. Just do nothing */ +static int load_asic(struct echoaudio *chip) +{ + return 0; +} + + + +static int set_sample_rate(struct echoaudio *chip, u32 rate) +{ + if (wait_handshake(chip)) + return -EIO; + + chip->sample_rate = rate; + chip->comm_page->sample_rate = cpu_to_le32(rate); + clear_handshake(chip); + return send_vector(chip, DSP_VC_UPDATE_CLOCKS); +} + + + +/* This function routes the sound from a virtual channel to a real output */ +static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, + int gain) +{ + int index; + + snd_assert(pipe < num_pipes_out(chip) && + output < num_busses_out(chip), return -EINVAL); + + if (wait_handshake(chip)) + return -EIO; + + chip->vmixer_gain[output][pipe] = gain; + index = output * num_pipes_out(chip) + pipe; + chip->comm_page->vmixer[index] = gain; + + DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain)); + return 0; +} + + + +/* Tell the DSP to read and update virtual mixer levels in comm page. */ +static int update_vmixer_level(struct echoaudio *chip) +{ + if (wait_handshake(chip)) + return -EIO; + clear_handshake(chip); + return send_vector(chip, DSP_VC_SET_VMIXER_GAIN); +} + diff --git a/sound/pci/echoaudio/layla20.c b/sound/pci/echoaudio/layla20.c new file mode 100644 index 000000000..e503d74b3 --- /dev/null +++ b/sound/pci/echoaudio/layla20.c @@ -0,0 +1,112 @@ +/* + * ALSA driver for Echoaudio soundcards. + * Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it> + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define ECHOGALS_FAMILY +#define ECHOCARD_LAYLA20 +#define ECHOCARD_NAME "Layla20" +#define ECHOCARD_HAS_MONITOR +#define ECHOCARD_HAS_ASIC +#define ECHOCARD_HAS_INPUT_GAIN +#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL +#define ECHOCARD_HAS_SUPER_INTERLEAVE +#define ECHOCARD_HAS_DIGITAL_IO +#define ECHOCARD_HAS_EXTERNAL_CLOCK +#define ECHOCARD_HAS_ADAT FALSE +#define ECHOCARD_HAS_OUTPUT_CLOCK_SWITCH +#define ECHOCARD_HAS_MIDI + +/* Pipe indexes */ +#define PX_ANALOG_OUT 0 /* 10 */ +#define PX_DIGITAL_OUT 10 /* 2 */ +#define PX_ANALOG_IN 12 /* 8 */ +#define PX_DIGITAL_IN 20 /* 2 */ +#define PX_NUM 22 + +/* Bus indexes */ +#define BX_ANALOG_OUT 0 /* 10 */ +#define BX_DIGITAL_OUT 10 /* 2 */ +#define BX_ANALOG_IN 12 /* 8 */ +#define BX_DIGITAL_IN 20 /* 2 */ +#define BX_NUM 22 + + +#include <sound/driver.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/slab.h> +#include <linux/moduleparam.h> +#include <linux/firmware.h> +#include <sound/core.h> +#include <sound/info.h> +#include <sound/control.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/asoundef.h> +#include <sound/initval.h> +#include <sound/rawmidi.h> +#include <asm/io.h> +#include <asm/atomic.h> +#include "echoaudio.h" + +#define FW_LAYLA20_DSP 0 +#define FW_LAYLA20_ASIC 1 + +static const struct firmware card_fw[] = { + {0, "layla20_dsp.fw"}, + {0, "layla20_asic.fw"} +}; + +static struct pci_device_id snd_echo_ids[] = { + {0x1057, 0x1801, 0xECC0, 0x0030, 0, 0, 0}, /* DSP 56301 Layla20 rev.0 */ + {0x1057, 0x1801, 0xECC0, 0x0031, 0, 0, 0}, /* DSP 56301 Layla20 rev.1 */ + {0,} +}; + +static struct snd_pcm_hardware pcm_hardware_skel = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S32_BE, + .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 8000, + .rate_max = 50000, + .channels_min = 1, + .channels_max = 10, + .buffer_bytes_max = 262144, + .period_bytes_min = 32, + .period_bytes_max = 131072, + .periods_min = 2, + .periods_max = 220, + /* One page (4k) contains 512 instructions. I don't know if the hw + supports lists longer than this. In this case periods_max=220 is a + safe limit to make sure the list never exceeds 512 instructions. */ +}; + +#include "layla20_dsp.c" +#include "echoaudio_dsp.c" +#include "echoaudio.c" +#include "midi.c" diff --git a/sound/pci/echoaudio/layla20_dsp.c b/sound/pci/echoaudio/layla20_dsp.c new file mode 100644 index 000000000..990c9a60a --- /dev/null +++ b/sound/pci/echoaudio/layla20_dsp.c @@ -0,0 +1,290 @@ +/**************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + ************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + +****************************************************************************/ + + +static int read_dsp(struct echoaudio *chip, u32 *data); +static int set_professional_spdif(struct echoaudio *chip, char prof); +static int load_asic_generic(struct echoaudio *chip, u32 cmd, + const struct firmware *asic); +static int check_asic_status(struct echoaudio *chip); +static int update_flags(struct echoaudio *chip); + + +static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) +{ + int err; + + DE_INIT(("init_hw() - Layla20\n")); + snd_assert((subdevice_id & 0xfff0) == LAYLA20, return -ENODEV); + + if ((err = init_dsp_comm_page(chip))) { + DE_INIT(("init_hw - could not initialize DSP comm page\n")); + return err; + } + + chip->device_id = device_id; + chip->subdevice_id = subdevice_id; + chip->bad_board = TRUE; + chip->has_midi = TRUE; + chip->dsp_code_to_load = &card_fw[FW_LAYLA20_DSP]; + chip->input_clock_types = + ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | + ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_SUPER; + chip->output_clock_types = + ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_SUPER; + + if ((err = load_firmware(chip)) < 0) + return err; + chip->bad_board = FALSE; + + if ((err = init_line_levels(chip)) < 0) + return err; + + err = set_professional_spdif(chip, TRUE); + + DE_INIT(("init_hw done\n")); + return err; +} + + + +static u32 detect_input_clocks(const struct echoaudio *chip) +{ + u32 clocks_from_dsp, clock_bits; + + /* Map the DSP clock detect bits to the generic driver clock detect bits */ + clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); + + clock_bits = ECHO_CLOCK_BIT_INTERNAL; + + if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF) + clock_bits |= ECHO_CLOCK_BIT_SPDIF; + + if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_WORD) { + if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SUPER) + clock_bits |= ECHO_CLOCK_BIT_SUPER; + else + clock_bits |= ECHO_CLOCK_BIT_WORD; + } + + return clock_bits; +} + + + +/* ASIC status check - some cards have one or two ASICs that need to be +loaded. Once that load is complete, this function is called to see if +the load was successful. +If this load fails, it does not necessarily mean that the hardware is +defective - the external box may be disconnected or turned off. +This routine sometimes fails for Layla20; for Layla20, the loop runs +5 times and succeeds if it wins on three of the loops. */ +static int check_asic_status(struct echoaudio *chip) +{ + u32 asic_status; + int goodcnt, i; + + chip->asic_loaded = FALSE; + for (i = goodcnt = 0; i < 5; i++) { + send_vector(chip, DSP_VC_TEST_ASIC); + + /* The DSP will return a value to indicate whether or not + the ASIC is currently loaded */ + if (read_dsp(chip, &asic_status) < 0) { + DE_ACT(("check_asic_status: failed on read_dsp\n")); + return -EIO; + } + + if (asic_status == ASIC_ALREADY_LOADED) { + if (++goodcnt == 3) { + chip->asic_loaded = TRUE; + return 0; + } + } + } + return -EIO; +} + + + +/* Layla20 has an ASIC in the external box */ +static int load_asic(struct echoaudio *chip) +{ + int err; + + if (chip->asic_loaded) + return 0; + + err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA_ASIC, + &card_fw[FW_LAYLA20_ASIC]); + if (err < 0) + return err; + + /* Check if ASIC is alive and well. */ + return check_asic_status(chip); +} + + + +static int set_sample_rate(struct echoaudio *chip, u32 rate) +{ + snd_assert(rate >= 8000 && rate <= 50000, return -EINVAL); + + /* Only set the clock for internal mode. Do not return failure, + simply treat it as a non-event. */ + if (chip->input_clock != ECHO_CLOCK_INTERNAL) { + DE_ACT(("set_sample_rate: Cannot set sample rate - " + "clock not set to CLK_CLOCKININTERNAL\n")); + chip->comm_page->sample_rate = cpu_to_le32(rate); + chip->sample_rate = rate; + return 0; + } + + if (wait_handshake(chip)) + return -EIO; + + DE_ACT(("set_sample_rate(%d)\n", rate)); + chip->sample_rate = rate; + chip->comm_page->sample_rate = cpu_to_le32(rate); + clear_handshake(chip); + return send_vector(chip, DSP_VC_SET_LAYLA_SAMPLE_RATE); +} + + + +static int set_input_clock(struct echoaudio *chip, u16 clock_source) +{ + u16 clock; + u32 rate; + + DE_ACT(("set_input_clock:\n")); + rate = 0; + switch (clock_source) { + case ECHO_CLOCK_INTERNAL: + DE_ACT(("Set Layla20 clock to INTERNAL\n")); + rate = chip->sample_rate; + clock = LAYLA20_CLOCK_INTERNAL; + break; + case ECHO_CLOCK_SPDIF: + DE_ACT(("Set Layla20 clock to SPDIF\n")); + clock = LAYLA20_CLOCK_SPDIF; + break; + case ECHO_CLOCK_WORD: + DE_ACT(("Set Layla20 clock to WORD\n")); + clock = LAYLA20_CLOCK_WORD; + break; + case ECHO_CLOCK_SUPER: + DE_ACT(("Set Layla20 clock to SUPER\n")); + clock = LAYLA20_CLOCK_SUPER; + break; + default: + DE_ACT(("Input clock 0x%x not supported for Layla24\n", + clock_source)); + return -EINVAL; + } + chip->input_clock = clock_source; + + chip->comm_page->input_clock = cpu_to_le16(clock); + clear_handshake(chip); + send_vector(chip, DSP_VC_UPDATE_CLOCKS); + + if (rate) + set_sample_rate(chip, rate); + + return 0; +} + + + +static int set_output_clock(struct echoaudio *chip, u16 clock) +{ + DE_ACT(("set_output_clock: %d\n", clock)); + switch (clock) { + case ECHO_CLOCK_SUPER: + clock = LAYLA20_OUTPUT_CLOCK_SUPER; + break; + case ECHO_CLOCK_WORD: + clock = LAYLA20_OUTPUT_CLOCK_WORD; + break; + default: + DE_ACT(("set_output_clock wrong clock\n")); + return -EINVAL; + } + + if (wait_handshake(chip)) + return -EIO; + + chip->comm_page->output_clock = cpu_to_le16(clock); + chip->output_clock = clock; + clear_handshake(chip); + return send_vector(chip, DSP_VC_UPDATE_CLOCKS); +} + + + +/* Set input bus gain (one unit is 0.5dB !) */ +static int set_input_gain(struct echoaudio *chip, u16 input, int gain) +{ + snd_assert(input < num_busses_in(chip), return -EINVAL); + + if (wait_handshake(chip)) + return -EIO; + + chip->input_gain[input] = gain; + gain += GL20_INPUT_GAIN_MAGIC_NUMBER; + chip->comm_page->line_in_level[input] = gain; + return 0; +} + + + +/* Tell the DSP to reread the flags from the comm page */ +static int update_flags(struct echoaudio *chip) +{ + if (wait_handshake(chip)) + return -EIO; + clear_handshake(chip); + return send_vector(chip, DSP_VC_UPDATE_FLAGS); +} + + + +static int set_professional_spdif(struct echoaudio *chip, char prof) +{ + DE_ACT(("set_professional_spdif %d\n", prof)); + if (prof) + chip->comm_page->flags |= + __constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); + else + chip->comm_page->flags &= + ~__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); + chip->professional_spdif = prof; + return update_flags(chip); +} diff --git a/sound/pci/echoaudio/layla24.c b/sound/pci/echoaudio/layla24.c new file mode 100644 index 000000000..d4581fdc8 --- /dev/null +++ b/sound/pci/echoaudio/layla24.c @@ -0,0 +1,121 @@ +/* + * ALSA driver for Echoaudio soundcards. + * Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it> + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define ECHO24_FAMILY +#define ECHOCARD_LAYLA24 +#define ECHOCARD_NAME "Layla24" +#define ECHOCARD_HAS_MONITOR +#define ECHOCARD_HAS_ASIC +#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL +#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL +#define ECHOCARD_HAS_SUPER_INTERLEAVE +#define ECHOCARD_HAS_DIGITAL_IO +#define ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE +#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH +#define ECHOCARD_HAS_EXTERNAL_CLOCK +#define ECHOCARD_HAS_ADAT 6 +#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 +#define ECHOCARD_HAS_MIDI + +/* Pipe indexes */ +#define PX_ANALOG_OUT 0 /* 8 */ +#define PX_DIGITAL_OUT 8 /* 8 */ +#define PX_ANALOG_IN 16 /* 8 */ +#define PX_DIGITAL_IN 24 /* 8 */ +#define PX_NUM 32 + +/* Bus indexes */ +#define BX_ANALOG_OUT 0 /* 8 */ +#define BX_DIGITAL_OUT 8 /* 8 */ +#define BX_ANALOG_IN 16 /* 8 */ +#define BX_DIGITAL_IN 24 /* 8 */ +#define BX_NUM 32 + + +#include <sound/driver.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/slab.h> +#include <linux/moduleparam.h> +#include <linux/firmware.h> +#include <sound/core.h> +#include <sound/info.h> +#include <sound/control.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/asoundef.h> +#include <sound/initval.h> +#include <sound/rawmidi.h> +#include <asm/io.h> +#include <asm/atomic.h> +#include "echoaudio.h" + +#define FW_361_LOADER 0 +#define FW_LAYLA24_DSP 1 +#define FW_LAYLA24_1_ASIC 2 +#define FW_LAYLA24_2A_ASIC 3 +#define FW_LAYLA24_2S_ASIC 4 + +static const struct firmware card_fw[] = { + {0, "loader_dsp.fw"}, + {0, "layla24_dsp.fw"}, + {0, "layla24_1_asic.fw"}, + {0, "layla24_2A_asic.fw"}, + {0, "layla24_2S_asic.fw"} +}; + +static struct pci_device_id snd_echo_ids[] = { + {0x1057, 0x3410, 0xECC0, 0x0060, 0, 0, 0}, /* DSP 56361 Layla24 rev.0 */ + {0,} +}; + +static struct snd_pcm_hardware pcm_hardware_skel = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S32_BE, + .rates = SNDRV_PCM_RATE_8000_96000, + .rate_min = 8000, + .rate_max = 100000, + .channels_min = 1, + .channels_max = 8, + .buffer_bytes_max = 262144, + .period_bytes_min = 32, + .period_bytes_max = 131072, + .periods_min = 2, + .periods_max = 220, + /* One page (4k) contains 512 instructions. I don't know if the hw + supports lists longer than this. In this case periods_max=220 is a + safe limit to make sure the list never exceeds 512 instructions. */ +}; + + +#include "layla24_dsp.c" +#include "echoaudio_dsp.c" +#include "echoaudio_gml.c" +#include "echoaudio.c" +#include "midi.c" diff --git a/sound/pci/echoaudio/layla24_dsp.c b/sound/pci/echoaudio/layla24_dsp.c new file mode 100644 index 000000000..7ec5b63d0 --- /dev/null +++ b/sound/pci/echoaudio/layla24_dsp.c @@ -0,0 +1,394 @@ +/**************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + ************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + +****************************************************************************/ + + +static int write_control_reg(struct echoaudio *chip, u32 value, char force); +static int set_input_clock(struct echoaudio *chip, u16 clock); +static int set_professional_spdif(struct echoaudio *chip, char prof); +static int set_digital_mode(struct echoaudio *chip, u8 mode); +static int load_asic_generic(struct echoaudio *chip, u32 cmd, + const struct firmware *asic); +static int check_asic_status(struct echoaudio *chip); + + +static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) +{ + int err; + + DE_INIT(("init_hw() - Layla24\n")); + snd_assert((subdevice_id & 0xfff0) == LAYLA24, return -ENODEV); + + if ((err = init_dsp_comm_page(chip))) { + DE_INIT(("init_hw - could not initialize DSP comm page\n")); + return err; + } + + chip->device_id = device_id; + chip->subdevice_id = subdevice_id; + chip->bad_board = TRUE; + chip->has_midi = TRUE; + chip->dsp_code_to_load = &card_fw[FW_LAYLA24_DSP]; + chip->input_clock_types = + ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | + ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_ADAT; + chip->digital_modes = + ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | + ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | + ECHOCAPS_HAS_DIGITAL_MODE_ADAT; + chip->digital_mode = DIGITAL_MODE_SPDIF_RCA; + chip->professional_spdif = FALSE; + chip->digital_in_automute = TRUE; + + if ((err = load_firmware(chip)) < 0) + return err; + chip->bad_board = FALSE; + + if ((err = init_line_levels(chip)) < 0) + return err; + + err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA); + snd_assert(err >= 0, return err); + err = set_professional_spdif(chip, TRUE); + + DE_INIT(("init_hw done\n")); + return err; +} + + + +static u32 detect_input_clocks(const struct echoaudio *chip) +{ + u32 clocks_from_dsp, clock_bits; + + /* Map the DSP clock detect bits to the generic driver clock detect bits */ + clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); + + clock_bits = ECHO_CLOCK_BIT_INTERNAL; + + if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF) + clock_bits |= ECHO_CLOCK_BIT_SPDIF; + + if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT) + clock_bits |= ECHO_CLOCK_BIT_ADAT; + + if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD) + clock_bits |= ECHO_CLOCK_BIT_WORD; + + return clock_bits; +} + + + +/* Layla24 has an ASIC on the PCI card and another ASIC in the external box; +both need to be loaded. */ +static int load_asic(struct echoaudio *chip) +{ + int err; + + if (chip->asic_loaded) + return 1; + + DE_INIT(("load_asic\n")); + + /* Give the DSP a few milliseconds to settle down */ + mdelay(10); + + /* Load the ASIC for the PCI card */ + err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_PCI_CARD_ASIC, + &card_fw[FW_LAYLA24_1_ASIC]); + if (err < 0) + return err; + + chip->asic_code = &card_fw[FW_LAYLA24_2S_ASIC]; + + /* Now give the new ASIC a little time to set up */ + mdelay(10); + + /* Do the external one */ + err = load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC, + &card_fw[FW_LAYLA24_2S_ASIC]); + if (err < 0) + return FALSE; + + /* Now give the external ASIC a little time to set up */ + mdelay(10); + + /* See if it worked */ + err = check_asic_status(chip); + + /* Set up the control register if the load succeeded - + 48 kHz, internal clock, S/PDIF RCA mode */ + if (!err) + err = write_control_reg(chip, GML_CONVERTER_ENABLE | GML_48KHZ, + TRUE); + + DE_INIT(("load_asic() done\n")); + return err; +} + + + +static int set_sample_rate(struct echoaudio *chip, u32 rate) +{ + u32 control_reg, clock, base_rate; + + snd_assert(rate < 50000 || chip->digital_mode != DIGITAL_MODE_ADAT, + return -EINVAL); + + /* Only set the clock for internal mode. */ + if (chip->input_clock != ECHO_CLOCK_INTERNAL) { + DE_ACT(("set_sample_rate: Cannot set sample rate - " + "clock not set to CLK_CLOCKININTERNAL\n")); + /* Save the rate anyhow */ + chip->comm_page->sample_rate = cpu_to_le32(rate); + chip->sample_rate = rate; + return 0; + } + + /* Get the control register & clear the appropriate bits */ + control_reg = le32_to_cpu(chip->comm_page->control_register); + control_reg &= GML_CLOCK_CLEAR_MASK & GML_SPDIF_RATE_CLEAR_MASK; + + clock = 0; + + switch (rate) { + case 96000: + clock = GML_96KHZ; + break; + case 88200: + clock = GML_88KHZ; + break; + case 48000: + clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1; + break; + case 44100: + clock = GML_44KHZ; + /* Professional mode */ + if (control_reg & GML_SPDIF_PRO_MODE) + clock |= GML_SPDIF_SAMPLE_RATE0; + break; + case 32000: + clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 | + GML_SPDIF_SAMPLE_RATE1; + break; + case 22050: + clock = GML_22KHZ; + break; + case 16000: + clock = GML_16KHZ; + break; + case 11025: + clock = GML_11KHZ; + break; + case 8000: + clock = GML_8KHZ; + break; + default: + /* If this is a non-standard rate, then the driver needs to + use Layla24's special "continuous frequency" mode */ + clock = LAYLA24_CONTINUOUS_CLOCK; + if (rate > 50000) { + base_rate = rate >> 1; + control_reg |= GML_DOUBLE_SPEED_MODE; + } else { + base_rate = rate; + } + + if (base_rate < 25000) + base_rate = 25000; + + if (wait_handshake(chip)) + return -EIO; + + chip->comm_page->sample_rate = + cpu_to_le32(LAYLA24_MAGIC_NUMBER / base_rate - 2); + + clear_handshake(chip); + send_vector(chip, DSP_VC_SET_LAYLA24_FREQUENCY_REG); + } + + control_reg |= clock; + + chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP ? */ + chip->sample_rate = rate; + DE_ACT(("set_sample_rate: %d clock %d\n", rate, control_reg)); + + return write_control_reg(chip, control_reg, FALSE); +} + + + +static int set_input_clock(struct echoaudio *chip, u16 clock) +{ + u32 control_reg, clocks_from_dsp; + + /* Mask off the clock select bits */ + control_reg = le32_to_cpu(chip->comm_page->control_register) & + GML_CLOCK_CLEAR_MASK; + clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); + + /* Pick the new clock */ + switch (clock) { + case ECHO_CLOCK_INTERNAL: + DE_ACT(("Set Layla24 clock to INTERNAL\n")); + chip->input_clock = ECHO_CLOCK_INTERNAL; + return set_sample_rate(chip, chip->sample_rate); + case ECHO_CLOCK_SPDIF: + if (chip->digital_mode == DIGITAL_MODE_ADAT) + return -EAGAIN; + control_reg |= GML_SPDIF_CLOCK; + /* Layla24 doesn't support 96KHz S/PDIF */ + control_reg &= ~GML_DOUBLE_SPEED_MODE; + DE_ACT(("Set Layla24 clock to SPDIF\n")); + break; + case ECHO_CLOCK_WORD: + control_reg |= GML_WORD_CLOCK; + if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD96) + control_reg |= GML_DOUBLE_SPEED_MODE; + else + control_reg &= ~GML_DOUBLE_SPEED_MODE; + DE_ACT(("Set Layla24 clock to WORD\n")); + break; + case ECHO_CLOCK_ADAT: + if (chip->digital_mode != DIGITAL_MODE_ADAT) + return -EAGAIN; + control_reg |= GML_ADAT_CLOCK; + control_reg &= ~GML_DOUBLE_SPEED_MODE; + DE_ACT(("Set Layla24 clock to ADAT\n")); + break; + default: + DE_ACT(("Input clock 0x%x not supported for Layla24\n", clock)); + return -EINVAL; + } + + chip->input_clock = clock; + return write_control_reg(chip, control_reg, TRUE); +} + + + +/* Depending on what digital mode you want, Layla24 needs different ASICs +loaded. This function checks the ASIC needed for the new mode and sees +if it matches the one already loaded. */ +static int switch_asic(struct echoaudio *chip, const struct firmware *asic) +{ + s8 *monitors; + + /* Check to see if this is already loaded */ + if (asic != chip->asic_code) { + monitors = kmalloc(MONITOR_ARRAY_SIZE, GFP_KERNEL); + if (! monitors) + return -ENOMEM; + + memcpy(monitors, chip->comm_page->monitors, MONITOR_ARRAY_SIZE); + memset(chip->comm_page->monitors, ECHOGAIN_MUTED, + MONITOR_ARRAY_SIZE); + + /* Load the desired ASIC */ + if (load_asic_generic(chip, DSP_FNC_LOAD_LAYLA24_EXTERNAL_ASIC, + asic) < 0) { + memcpy(chip->comm_page->monitors, monitors, + MONITOR_ARRAY_SIZE); + kfree(monitors); + return -EIO; + } + chip->asic_code = asic; + memcpy(chip->comm_page->monitors, monitors, MONITOR_ARRAY_SIZE); + kfree(monitors); + } + + return 0; +} + + + +static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) +{ + u32 control_reg; + int err, incompatible_clock; + const struct firmware *asic; + + /* Set clock to "internal" if it's not compatible with the new mode */ + incompatible_clock = FALSE; + switch (mode) { + case DIGITAL_MODE_SPDIF_OPTICAL: + case DIGITAL_MODE_SPDIF_RCA: + if (chip->input_clock == ECHO_CLOCK_ADAT) + incompatible_clock = TRUE; + asic = &card_fw[FW_LAYLA24_2S_ASIC]; + break; + case DIGITAL_MODE_ADAT: + if (chip->input_clock == ECHO_CLOCK_SPDIF) + incompatible_clock = TRUE; + asic = &card_fw[FW_LAYLA24_2A_ASIC]; + break; + default: + DE_ACT(("Digital mode not supported: %d\n", mode)); + return -EINVAL; + } + + if (incompatible_clock) { /* Switch to 48KHz, internal */ + chip->sample_rate = 48000; + spin_lock_irq(&chip->lock); + set_input_clock(chip, ECHO_CLOCK_INTERNAL); + spin_unlock_irq(&chip->lock); + } + + /* switch_asic() can sleep */ + if (switch_asic(chip, asic) < 0) + return -EIO; + + spin_lock_irq(&chip->lock); + + /* Tweak the control register */ + control_reg = le32_to_cpu(chip->comm_page->control_register); + control_reg &= GML_DIGITAL_MODE_CLEAR_MASK; + + switch (mode) { + case DIGITAL_MODE_SPDIF_OPTICAL: + control_reg |= GML_SPDIF_OPTICAL_MODE; + break; + case DIGITAL_MODE_SPDIF_RCA: + /* GML_SPDIF_OPTICAL_MODE bit cleared */ + break; + case DIGITAL_MODE_ADAT: + control_reg |= GML_ADAT_MODE; + control_reg &= ~GML_DOUBLE_SPEED_MODE; + break; + } + + err = write_control_reg(chip, control_reg, TRUE); + spin_unlock_irq(&chip->lock); + if (err < 0) + return err; + chip->digital_mode = mode; + + DE_ACT(("set_digital_mode to %d\n", mode)); + return incompatible_clock; +} diff --git a/sound/pci/echoaudio/mia.c b/sound/pci/echoaudio/mia.c new file mode 100644 index 000000000..be40c6426 --- /dev/null +++ b/sound/pci/echoaudio/mia.c @@ -0,0 +1,117 @@ +/* + * ALSA driver for Echoaudio soundcards. + * Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it> + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define ECHO24_FAMILY +#define ECHOCARD_MIA +#define ECHOCARD_NAME "Mia" +#define ECHOCARD_HAS_MONITOR +#define ECHOCARD_HAS_INPUT_NOMINAL_LEVEL +#define ECHOCARD_HAS_OUTPUT_NOMINAL_LEVEL +#define ECHOCARD_HAS_SUPER_INTERLEAVE +#define ECHOCARD_HAS_VMIXER +#define ECHOCARD_HAS_DIGITAL_IO +#define ECHOCARD_HAS_EXTERNAL_CLOCK +#define ECHOCARD_HAS_ADAT FALSE +#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 +#define ECHOCARD_HAS_MIDI + +/* Pipe indexes */ +#define PX_ANALOG_OUT 0 /* 8 */ +#define PX_DIGITAL_OUT 8 /* 0 */ +#define PX_ANALOG_IN 8 /* 2 */ +#define PX_DIGITAL_IN 10 /* 2 */ +#define PX_NUM 12 + +/* Bus indexes */ +#define BX_ANALOG_OUT 0 /* 2 */ +#define BX_DIGITAL_OUT 2 /* 2 */ +#define BX_ANALOG_IN 4 /* 2 */ +#define BX_DIGITAL_IN 6 /* 2 */ +#define BX_NUM 8 + + +#include <sound/driver.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/slab.h> +#include <linux/moduleparam.h> +#include <linux/firmware.h> +#include <sound/core.h> +#include <sound/info.h> +#include <sound/control.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/asoundef.h> +#include <sound/initval.h> +#include <sound/rawmidi.h> +#include <asm/io.h> +#include <asm/atomic.h> +#include "echoaudio.h" + +#define FW_361_LOADER 0 +#define FW_MIA_DSP 1 + +static const struct firmware card_fw[] = { + {0, "loader_dsp.fw"}, + {0, "mia_dsp.fw"} +}; + +static struct pci_device_id snd_echo_ids[] = { + {0x1057, 0x3410, 0xECC0, 0x0080, 0, 0, 0}, /* DSP 56361 Mia rev.0 */ + {0x1057, 0x3410, 0xECC0, 0x0081, 0, 0, 0}, /* DSP 56361 Mia rev.1 */ + {0,} +}; + +static struct snd_pcm_hardware pcm_hardware_skel = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S32_BE, + .rates = SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000, + .rate_min = 8000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + .buffer_bytes_max = 262144, + .period_bytes_min = 32, + .period_bytes_max = 131072, + .periods_min = 2, + .periods_max = 220, + /* One page (4k) contains 512 instructions. I don't know if the hw + supports lists longer than this. In this case periods_max=220 is a + safe limit to make sure the list never exceeds 512 instructions. */ +}; + + +#include "mia_dsp.c" +#include "echoaudio_dsp.c" +#include "echoaudio.c" +#include "midi.c" diff --git a/sound/pci/echoaudio/mia_dsp.c b/sound/pci/echoaudio/mia_dsp.c new file mode 100644 index 000000000..891c70519 --- /dev/null +++ b/sound/pci/echoaudio/mia_dsp.c @@ -0,0 +1,229 @@ +/**************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + ************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + +****************************************************************************/ + + +static int set_input_clock(struct echoaudio *chip, u16 clock); +static int set_professional_spdif(struct echoaudio *chip, char prof); +static int update_flags(struct echoaudio *chip); +static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, + int gain); +static int update_vmixer_level(struct echoaudio *chip); + + +static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) +{ + int err; + + DE_INIT(("init_hw() - Mia\n")); + snd_assert((subdevice_id & 0xfff0) == MIA, return -ENODEV); + + if ((err = init_dsp_comm_page(chip))) { + DE_INIT(("init_hw - could not initialize DSP comm page\n")); + return err; + } + + chip->device_id = device_id; + chip->subdevice_id = subdevice_id; + chip->bad_board = TRUE; + chip->dsp_code_to_load = &card_fw[FW_MIA_DSP]; + /* Since this card has no ASIC, mark it as loaded so everything + works OK */ + chip->asic_loaded = TRUE; + if ((subdevice_id & 0x0000f) == MIA_MIDI_REV) + chip->has_midi = TRUE; + chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | + ECHO_CLOCK_BIT_SPDIF; + + if ((err = load_firmware(chip)) < 0) + return err; + chip->bad_board = FALSE; + + if ((err = init_line_levels(chip))) + return err; + + /* Default routing of the virtual channels: vchannels 0-3 go to analog + outputs and vchannels 4-7 go to S/PDIF outputs */ + set_vmixer_gain(chip, 0, 0, 0); + set_vmixer_gain(chip, 1, 1, 0); + set_vmixer_gain(chip, 0, 2, 0); + set_vmixer_gain(chip, 1, 3, 0); + set_vmixer_gain(chip, 2, 4, 0); + set_vmixer_gain(chip, 3, 5, 0); + set_vmixer_gain(chip, 2, 6, 0); + set_vmixer_gain(chip, 3, 7, 0); + err = update_vmixer_level(chip); + + DE_INIT(("init_hw done\n")); + return err; +} + + + +static u32 detect_input_clocks(const struct echoaudio *chip) +{ + u32 clocks_from_dsp, clock_bits; + + /* Map the DSP clock detect bits to the generic driver clock + detect bits */ + clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); + + clock_bits = ECHO_CLOCK_BIT_INTERNAL; + + if (clocks_from_dsp & GLDM_CLOCK_DETECT_BIT_SPDIF) + clock_bits |= ECHO_CLOCK_BIT_SPDIF; + + return clock_bits; +} + + + +/* The Mia has no ASIC. Just do nothing */ +static int load_asic(struct echoaudio *chip) +{ + return 0; +} + + + +static int set_sample_rate(struct echoaudio *chip, u32 rate) +{ + u32 control_reg; + + switch (rate) { + case 96000: + control_reg = MIA_96000; + break; + case 88200: + control_reg = MIA_88200; + break; + case 48000: + control_reg = MIA_48000; + break; + case 44100: + control_reg = MIA_44100; + break; + case 32000: + control_reg = MIA_32000; + break; + default: + DE_ACT(("set_sample_rate: %d invalid!\n", rate)); + return -EINVAL; + } + + /* Override the clock setting if this Mia is set to S/PDIF clock */ + if (chip->input_clock == ECHO_CLOCK_SPDIF) + control_reg |= MIA_SPDIF; + + /* Set the control register if it has changed */ + if (control_reg != le32_to_cpu(chip->comm_page->control_register)) { + if (wait_handshake(chip)) + return -EIO; + + chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ + chip->comm_page->control_register = cpu_to_le32(control_reg); + chip->sample_rate = rate; + + clear_handshake(chip); + return send_vector(chip, DSP_VC_UPDATE_CLOCKS); + } + return 0; +} + + + +static int set_input_clock(struct echoaudio *chip, u16 clock) +{ + DE_ACT(("set_input_clock(%d)\n", clock)); + snd_assert(clock == ECHO_CLOCK_INTERNAL || clock == ECHO_CLOCK_SPDIF, + return -EINVAL); + + chip->input_clock = clock; + return set_sample_rate(chip, chip->sample_rate); +} + + + +/* This function routes the sound from a virtual channel to a real output */ +static int set_vmixer_gain(struct echoaudio *chip, u16 output, u16 pipe, + int gain) +{ + int index; + + snd_assert(pipe < num_pipes_out(chip) && + output < num_busses_out(chip), return -EINVAL); + + if (wait_handshake(chip)) + return -EIO; + + chip->vmixer_gain[output][pipe] = gain; + index = output * num_pipes_out(chip) + pipe; + chip->comm_page->vmixer[index] = gain; + + DE_ACT(("set_vmixer_gain: pipe %d, out %d = %d\n", pipe, output, gain)); + return 0; +} + + + +/* Tell the DSP to read and update virtual mixer levels in comm page. */ +static int update_vmixer_level(struct echoaudio *chip) +{ + if (wait_handshake(chip)) + return -EIO; + clear_handshake(chip); + return send_vector(chip, DSP_VC_SET_VMIXER_GAIN); +} + + + +/* Tell the DSP to reread the flags from the comm page */ +static int update_flags(struct echoaudio *chip) +{ + if (wait_handshake(chip)) + return -EIO; + clear_handshake(chip); + return send_vector(chip, DSP_VC_UPDATE_FLAGS); +} + + + +static int set_professional_spdif(struct echoaudio *chip, char prof) +{ + DE_ACT(("set_professional_spdif %d\n", prof)); + if (prof) + chip->comm_page->flags |= + __constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); + else + chip->comm_page->flags &= + ~__constant_cpu_to_le32(DSP_FLAG_PROFESSIONAL_SPDIF); + chip->professional_spdif = prof; + return update_flags(chip); +} + diff --git a/sound/pci/echoaudio/midi.c b/sound/pci/echoaudio/midi.c new file mode 100644 index 000000000..e31f0f11e --- /dev/null +++ b/sound/pci/echoaudio/midi.c @@ -0,0 +1,327 @@ +/**************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + ************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + +****************************************************************************/ + + +/****************************************************************************** + MIDI lowlevel code +******************************************************************************/ + +/* Start and stop Midi input */ +static int enable_midi_input(struct echoaudio *chip, char enable) +{ + DE_MID(("enable_midi_input(%d)\n", enable)); + + if (wait_handshake(chip)) + return -EIO; + + if (enable) { + chip->mtc_state = MIDI_IN_STATE_NORMAL; + chip->comm_page->flags |= + __constant_cpu_to_le32(DSP_FLAG_MIDI_INPUT); + } else + chip->comm_page->flags &= + ~__constant_cpu_to_le32(DSP_FLAG_MIDI_INPUT); + + clear_handshake(chip); + return send_vector(chip, DSP_VC_UPDATE_FLAGS); +} + + + +/* Send a buffer full of MIDI data to the DSP +Returns how many actually written or < 0 on error */ +static int write_midi(struct echoaudio *chip, u8 *data, int bytes) +{ + snd_assert(bytes > 0 && bytes < MIDI_OUT_BUFFER_SIZE, return -EINVAL); + + if (wait_handshake(chip)) + return -EIO; + + /* HF4 indicates that it is safe to write MIDI output data */ + if (! (get_dsp_register(chip, CHI32_STATUS_REG) & CHI32_STATUS_REG_HF4)) + return 0; + + chip->comm_page->midi_output[0] = bytes; + memcpy(&chip->comm_page->midi_output[1], data, bytes); + chip->comm_page->midi_out_free_count = 0; + clear_handshake(chip); + send_vector(chip, DSP_VC_MIDI_WRITE); + DE_MID(("write_midi: %d\n", bytes)); + return bytes; +} + + + +/* Run the state machine for MIDI input data +MIDI time code sync isn't supported by this code right now, but you still need +this state machine to parse the incoming MIDI data stream. Every time the DSP +sees a 0xF1 byte come in, it adds the DSP sample position to the MIDI data +stream. The DSP sample position is represented as a 32 bit unsigned value, +with the high 16 bits first, followed by the low 16 bits. Since these aren't +real MIDI bytes, the following logic is needed to skip them. */ +static inline int mtc_process_data(struct echoaudio *chip, short midi_byte) +{ + switch (chip->mtc_state) { + case MIDI_IN_STATE_NORMAL: + if (midi_byte == 0xF1) + chip->mtc_state = MIDI_IN_STATE_TS_HIGH; + break; + case MIDI_IN_STATE_TS_HIGH: + chip->mtc_state = MIDI_IN_STATE_TS_LOW; + return MIDI_IN_SKIP_DATA; + break; + case MIDI_IN_STATE_TS_LOW: + chip->mtc_state = MIDI_IN_STATE_F1_DATA; + return MIDI_IN_SKIP_DATA; + break; + case MIDI_IN_STATE_F1_DATA: + chip->mtc_state = MIDI_IN_STATE_NORMAL; + break; + } + return 0; +} + + + +/* This function is called from the IRQ handler and it reads the midi data +from the DSP's buffer. It returns the number of bytes received. */ +static int midi_service_irq(struct echoaudio *chip) +{ + short int count, midi_byte, i, received; + + /* The count is at index 0, followed by actual data */ + count = le16_to_cpu(chip->comm_page->midi_input[0]); + + snd_assert(count < MIDI_IN_BUFFER_SIZE, return 0); + + /* Get the MIDI data from the comm page */ + i = 1; + received = 0; + for (i = 1; i <= count; i++) { + /* Get the MIDI byte */ + midi_byte = le16_to_cpu(chip->comm_page->midi_input[i]); + + /* Parse the incoming MIDI stream. The incoming MIDI data + consists of MIDI bytes and timestamps for the MIDI time code + 0xF1 bytes. mtc_process_data() is a little state machine that + parses the stream. If you get MIDI_IN_SKIP_DATA back, then + this is a timestamp byte, not a MIDI byte, so don't store it + in the MIDI input buffer. */ + if (mtc_process_data(chip, midi_byte) == MIDI_IN_SKIP_DATA) + continue; + + chip->midi_buffer[received++] = (u8)midi_byte; + } + + return received; +} + + + + +/****************************************************************************** + MIDI interface +******************************************************************************/ + +static int snd_echo_midi_input_open(struct snd_rawmidi_substream *substream) +{ + struct echoaudio *chip = substream->rmidi->private_data; + + chip->midi_in = substream; + DE_MID(("rawmidi_iopen\n")); + return 0; +} + + + +static void snd_echo_midi_input_trigger(struct snd_rawmidi_substream *substream, + int up) +{ + struct echoaudio *chip = substream->rmidi->private_data; + + if (up != chip->midi_input_enabled) { + spin_lock_irq(&chip->lock); + enable_midi_input(chip, up); + spin_unlock_irq(&chip->lock); + chip->midi_input_enabled = up; + } +} + + + +static int snd_echo_midi_input_close(struct snd_rawmidi_substream *substream) +{ + struct echoaudio *chip = substream->rmidi->private_data; + + chip->midi_in = NULL; + DE_MID(("rawmidi_iclose\n")); + return 0; +} + + + +static int snd_echo_midi_output_open(struct snd_rawmidi_substream *substream) +{ + struct echoaudio *chip = substream->rmidi->private_data; + + chip->tinuse = 0; + chip->midi_full = 0; + chip->midi_out = substream; + DE_MID(("rawmidi_oopen\n")); + return 0; +} + + + +static void snd_echo_midi_output_write(unsigned long data) +{ + struct echoaudio *chip = (struct echoaudio *)data; + unsigned long flags; + int bytes, sent, time; + unsigned char buf[MIDI_OUT_BUFFER_SIZE - 1]; + + DE_MID(("snd_echo_midi_output_write\n")); + /* No interrupts are involved: we have to check at regular intervals + if the card's output buffer has room for new data. */ + sent = bytes = 0; + spin_lock_irqsave(&chip->lock, flags); + chip->midi_full = 0; + if (chip->midi_out && !snd_rawmidi_transmit_empty(chip->midi_out)) { + bytes = snd_rawmidi_transmit_peek(chip->midi_out, buf, + MIDI_OUT_BUFFER_SIZE - 1); + DE_MID(("Try to send %d bytes...\n", bytes)); + sent = write_midi(chip, buf, bytes); + if (sent < 0) { + snd_printk(KERN_ERR "write_midi() error %d\n", sent); + /* retry later */ + sent = 9000; + chip->midi_full = 1; + } else if (sent > 0) { + DE_MID(("%d bytes sent\n", sent)); + snd_rawmidi_transmit_ack(chip->midi_out, sent); + } else { + /* Buffer is full. DSP's internal buffer is 64 (128 ?) + bytes long. Let's wait until half of them are sent */ + DE_MID(("Full\n")); + sent = 32; + chip->midi_full = 1; + } + } + + /* We restart the timer only if there is some data left to send */ + if (!snd_rawmidi_transmit_empty(chip->midi_out) && chip->tinuse) { + /* The timer will expire slightly after the data has been + sent */ + time = (sent << 3) / 25 + 1; /* 8/25=0.32ms to send a byte */ + mod_timer(&chip->timer, jiffies + (time * HZ + 999) / 1000); + DE_MID(("Timer armed(%d)\n", ((time * HZ + 999) / 1000))); + } + spin_unlock_irqrestore(&chip->lock, flags); +} + + + +static void snd_echo_midi_output_trigger(struct snd_rawmidi_substream *substream, + int up) +{ + struct echoaudio *chip = substream->rmidi->private_data; + + DE_MID(("snd_echo_midi_output_trigger(%d)\n", up)); + spin_lock_irq(&chip->lock); + if (up) { + if (!chip->tinuse) { + init_timer(&chip->timer); + chip->timer.function = snd_echo_midi_output_write; + chip->timer.data = (unsigned long)chip; + chip->tinuse = 1; + } + } else { + if (chip->tinuse) { + del_timer(&chip->timer); + chip->tinuse = 0; + DE_MID(("Timer removed\n")); + } + } + spin_unlock_irq(&chip->lock); + + if (up && !chip->midi_full) + snd_echo_midi_output_write((unsigned long)chip); +} + + + +static int snd_echo_midi_output_close(struct snd_rawmidi_substream *substream) +{ + struct echoaudio *chip = substream->rmidi->private_data; + + chip->midi_out = NULL; + DE_MID(("rawmidi_oclose\n")); + return 0; +} + + + +static struct snd_rawmidi_ops snd_echo_midi_input = { + .open = snd_echo_midi_input_open, + .close = snd_echo_midi_input_close, + .trigger = snd_echo_midi_input_trigger, +}; + +static struct snd_rawmidi_ops snd_echo_midi_output = { + .open = snd_echo_midi_output_open, + .close = snd_echo_midi_output_close, + .trigger = snd_echo_midi_output_trigger, +}; + + + +/* <--snd_echo_probe() */ +static int __devinit snd_echo_midi_create(struct snd_card *card, + struct echoaudio *chip) +{ + int err; + + if ((err = snd_rawmidi_new(card, card->shortname, 0, 1, 1, + &chip->rmidi)) < 0) + return err; + + strcpy(chip->rmidi->name, card->shortname); + chip->rmidi->private_data = chip; + + snd_rawmidi_set_ops(chip->rmidi, SNDRV_RAWMIDI_STREAM_INPUT, + &snd_echo_midi_input); + snd_rawmidi_set_ops(chip->rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, + &snd_echo_midi_output); + + chip->rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | + SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; + DE_INIT(("MIDI ok\n")); + return 0; +} diff --git a/sound/pci/echoaudio/mona.c b/sound/pci/echoaudio/mona.c new file mode 100644 index 000000000..5dc512add --- /dev/null +++ b/sound/pci/echoaudio/mona.c @@ -0,0 +1,129 @@ +/* + * ALSA driver for Echoaudio soundcards. + * Copyright (C) 2003-2004 Giuliano Pochini <pochini@shiny.it> + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define ECHO24_FAMILY +#define ECHOCARD_MONA +#define ECHOCARD_NAME "Mona" +#define ECHOCARD_HAS_MONITOR +#define ECHOCARD_HAS_ASIC +#define ECHOCARD_HAS_SUPER_INTERLEAVE +#define ECHOCARD_HAS_DIGITAL_IO +#define ECHOCARD_HAS_DIGITAL_IN_AUTOMUTE +#define ECHOCARD_HAS_DIGITAL_MODE_SWITCH +#define ECHOCARD_HAS_EXTERNAL_CLOCK +#define ECHOCARD_HAS_ADAT 6 +#define ECHOCARD_HAS_STEREO_BIG_ENDIAN32 + +/* Pipe indexes */ +#define PX_ANALOG_OUT 0 /* 6 */ +#define PX_DIGITAL_OUT 6 /* 8 */ +#define PX_ANALOG_IN 14 /* 4 */ +#define PX_DIGITAL_IN 18 /* 8 */ +#define PX_NUM 26 + +/* Bus indexes */ +#define BX_ANALOG_OUT 0 /* 6 */ +#define BX_DIGITAL_OUT 6 /* 8 */ +#define BX_ANALOG_IN 14 /* 4 */ +#define BX_DIGITAL_IN 18 /* 8 */ +#define BX_NUM 26 + + +#include <sound/driver.h> +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <linux/slab.h> +#include <linux/moduleparam.h> +#include <linux/firmware.h> +#include <sound/core.h> +#include <sound/info.h> +#include <sound/control.h> +#include <sound/pcm.h> +#include <sound/pcm_params.h> +#include <sound/asoundef.h> +#include <sound/initval.h> +#include <asm/io.h> +#include <asm/atomic.h> +#include "echoaudio.h" + +#define FW_361_LOADER 0 +#define FW_MONA_301_DSP 1 +#define FW_MONA_361_DSP 2 +#define FW_MONA_301_1_ASIC48 3 +#define FW_MONA_301_1_ASIC96 4 +#define FW_MONA_361_1_ASIC48 5 +#define FW_MONA_361_1_ASIC96 6 +#define FW_MONA_2_ASIC 7 + +static const struct firmware card_fw[] = { + {0, "loader_dsp.fw"}, + {0, "mona_301_dsp.fw"}, + {0, "mona_361_dsp.fw"}, + {0, "mona_301_1_asic_48.fw"}, + {0, "mona_301_1_asic_96.fw"}, + {0, "mona_361_1_asic_48.fw"}, + {0, "mona_361_1_asic_96.fw"}, + {0, "mona_2_asic.fw"} +}; + +static struct pci_device_id snd_echo_ids[] = { + {0x1057, 0x1801, 0xECC0, 0x0070, 0, 0, 0}, /* DSP 56301 Mona rev.0 */ + {0x1057, 0x1801, 0xECC0, 0x0071, 0, 0, 0}, /* DSP 56301 Mona rev.1 */ + {0x1057, 0x1801, 0xECC0, 0x0072, 0, 0, 0}, /* DSP 56301 Mona rev.2 */ + {0x1057, 0x3410, 0xECC0, 0x0070, 0, 0, 0}, /* DSP 56361 Mona rev.0 */ + {0x1057, 0x3410, 0xECC0, 0x0071, 0, 0, 0}, /* DSP 56361 Mona rev.1 */ + {0x1057, 0x3410, 0xECC0, 0x0072, 0, 0, 0}, /* DSP 56361 Mona rev.2 */ + {0,} +}; + +static struct snd_pcm_hardware pcm_hardware_skel = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S32_BE, + .rates = SNDRV_PCM_RATE_8000_48000 | + SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000, + .rate_min = 8000, + .rate_max = 96000, + .channels_min = 1, + .channels_max = 8, + .buffer_bytes_max = 262144, + .period_bytes_min = 32, + .period_bytes_max = 131072, + .periods_min = 2, + .periods_max = 220, + /* One page (4k) contains 512 instructions. I don't know if the hw + supports lists longer than this. In this case periods_max=220 is a + safe limit to make sure the list never exceeds 512 instructions. */ +}; + + +#include "mona_dsp.c" +#include "echoaudio_dsp.c" +#include "echoaudio_gml.c" +#include "echoaudio.c" diff --git a/sound/pci/echoaudio/mona_dsp.c b/sound/pci/echoaudio/mona_dsp.c new file mode 100644 index 000000000..c0b4bf0be --- /dev/null +++ b/sound/pci/echoaudio/mona_dsp.c @@ -0,0 +1,428 @@ +/**************************************************************************** + + Copyright Echo Digital Audio Corporation (c) 1998 - 2004 + All rights reserved + www.echoaudio.com + + This file is part of Echo Digital Audio's generic driver library. + + Echo Digital Audio's generic driver library 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. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. + + ************************************************************************* + + Translation from C++ and adaptation for use in ALSA-Driver + were made by Giuliano Pochini <pochini@shiny.it> + +****************************************************************************/ + + +static int write_control_reg(struct echoaudio *chip, u32 value, char force); +static int set_input_clock(struct echoaudio *chip, u16 clock); +static int set_professional_spdif(struct echoaudio *chip, char prof); +static int set_digital_mode(struct echoaudio *chip, u8 mode); +static int load_asic_generic(struct echoaudio *chip, u32 cmd, + const struct firmware *asic); +static int check_asic_status(struct echoaudio *chip); + + +static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) +{ + int err; + + DE_INIT(("init_hw() - Mona\n")); + snd_assert((subdevice_id & 0xfff0) == MONA, return -ENODEV); + + if ((err = init_dsp_comm_page(chip))) { + DE_INIT(("init_hw - could not initialize DSP comm page\n")); + return err; + } + + chip->device_id = device_id; + chip->subdevice_id = subdevice_id; + chip->bad_board = TRUE; + chip->input_clock_types = + ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | + ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_ADAT; + chip->digital_modes = + ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | + ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | + ECHOCAPS_HAS_DIGITAL_MODE_ADAT; + + /* Mona comes in both '301 and '361 flavors */ + if (chip->device_id == DEVICE_ID_56361) + chip->dsp_code_to_load = &card_fw[FW_MONA_361_DSP]; + else + chip->dsp_code_to_load = &card_fw[FW_MONA_301_DSP]; + + chip->digital_mode = DIGITAL_MODE_SPDIF_RCA; + chip->professional_spdif = FALSE; + chip->digital_in_automute = TRUE; + + if ((err = load_firmware(chip)) < 0) + return err; + chip->bad_board = FALSE; + + if ((err = init_line_levels(chip)) < 0) + return err; + + err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA); + snd_assert(err >= 0, return err); + err = set_professional_spdif(chip, TRUE); + + DE_INIT(("init_hw done\n")); + return err; +} + + + +static u32 detect_input_clocks(const struct echoaudio *chip) +{ + u32 clocks_from_dsp, clock_bits; + + /* Map the DSP clock detect bits to the generic driver clock + detect bits */ + clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); + + clock_bits = ECHO_CLOCK_BIT_INTERNAL; + + if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF) + clock_bits |= ECHO_CLOCK_BIT_SPDIF; + + if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_ADAT) + clock_bits |= ECHO_CLOCK_BIT_ADAT; + + if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD) + clock_bits |= ECHO_CLOCK_BIT_WORD; + + return clock_bits; +} + + + +/* Mona has an ASIC on the PCI card and another ASIC in the external box; +both need to be loaded. */ +static int load_asic(struct echoaudio *chip) +{ + u32 control_reg; + int err; + const struct firmware *asic; + + if (chip->asic_loaded) + return 0; + + mdelay(10); + + if (chip->device_id == DEVICE_ID_56361) + asic = &card_fw[FW_MONA_361_1_ASIC48]; + else + asic = &card_fw[FW_MONA_301_1_ASIC48]; + + err = load_asic_generic(chip, DSP_FNC_LOAD_MONA_PCI_CARD_ASIC, asic); + if (err < 0) + return err; + + chip->asic_code = asic; + mdelay(10); + + /* Do the external one */ + err = load_asic_generic(chip, DSP_FNC_LOAD_MONA_EXTERNAL_ASIC, + &card_fw[FW_MONA_2_ASIC]); + if (err < 0) + return err; + + mdelay(10); + err = check_asic_status(chip); + + /* Set up the control register if the load succeeded - + 48 kHz, internal clock, S/PDIF RCA mode */ + if (!err) { + control_reg = GML_CONVERTER_ENABLE | GML_48KHZ; + err = write_control_reg(chip, control_reg, TRUE); + } + + return err; +} + + + +/* Depending on what digital mode you want, Mona needs different ASICs +loaded. This function checks the ASIC needed for the new mode and sees +if it matches the one already loaded. */ +static int switch_asic(struct echoaudio *chip, char double_speed) +{ + const struct firmware *asic; + int err; + + /* Check the clock detect bits to see if this is + a single-speed clock or a double-speed clock; load + a new ASIC if necessary. */ + if (chip->device_id == DEVICE_ID_56361) { + if (double_speed) + asic = &card_fw[FW_MONA_361_1_ASIC96]; + else + asic = &card_fw[FW_MONA_361_1_ASIC48]; + } else { + if (double_speed) + asic = &card_fw[FW_MONA_301_1_ASIC96]; + else + asic = &card_fw[FW_MONA_301_1_ASIC48]; + } + + if (asic != chip->asic_code) { + /* Load the desired ASIC */ + err = load_asic_generic(chip, DSP_FNC_LOAD_MONA_PCI_CARD_ASIC, + asic); + if (err < 0) + return err; + chip->asic_code = asic; + } + + return 0; +} + + + +static int set_sample_rate(struct echoaudio *chip, u32 rate) +{ + u32 control_reg, clock; + const struct firmware *asic; + char force_write; + + /* Only set the clock for internal mode. */ + if (chip->input_clock != ECHO_CLOCK_INTERNAL) { + DE_ACT(("set_sample_rate: Cannot set sample rate - " + "clock not set to CLK_CLOCKININTERNAL\n")); + /* Save the rate anyhow */ + chip->comm_page->sample_rate = cpu_to_le32(rate); + chip->sample_rate = rate; + return 0; + } + + /* Now, check to see if the required ASIC is loaded */ + if (rate >= 88200) { + if (chip->digital_mode == DIGITAL_MODE_ADAT) + return -EINVAL; + if (chip->device_id == DEVICE_ID_56361) + asic = &card_fw[FW_MONA_361_1_ASIC96]; + else + asic = &card_fw[FW_MONA_301_1_ASIC96]; + } else { + if (chip->device_id == DEVICE_ID_56361) + asic = &card_fw[FW_MONA_361_1_ASIC48]; + else + asic = &card_fw[FW_MONA_301_1_ASIC48]; + } + + force_write = 0; + if (asic != chip->asic_code) { + int err; + /* Load the desired ASIC (load_asic_generic() can sleep) */ + spin_unlock_irq(&chip->lock); + err = load_asic_generic(chip, DSP_FNC_LOAD_MONA_PCI_CARD_ASIC, + asic); + spin_lock_irq(&chip->lock); + + if (err < 0) + return err; + chip->asic_code = asic; + force_write = 1; + } + + /* Compute the new control register value */ + clock = 0; + control_reg = le32_to_cpu(chip->comm_page->control_register); + control_reg &= GML_CLOCK_CLEAR_MASK; + control_reg &= GML_SPDIF_RATE_CLEAR_MASK; + + switch (rate) { + case 96000: + clock = GML_96KHZ; + break; + case 88200: + clock = GML_88KHZ; + break; + case 48000: + clock = GML_48KHZ | GML_SPDIF_SAMPLE_RATE1; + break; + case 44100: + clock = GML_44KHZ; + /* Professional mode */ + if (control_reg & GML_SPDIF_PRO_MODE) + clock |= GML_SPDIF_SAMPLE_RATE0; + break; + case 32000: + clock = GML_32KHZ | GML_SPDIF_SAMPLE_RATE0 | + GML_SPDIF_SAMPLE_RATE1; + break; + case 22050: + clock = GML_22KHZ; + break; + case 16000: + clock = GML_16KHZ; + break; + case 11025: + clock = GML_11KHZ; + break; + case 8000: + clock = GML_8KHZ; + break; + default: + DE_ACT(("set_sample_rate: %d invalid!\n", rate)); + return -EINVAL; + } + + control_reg |= clock; + + chip->comm_page->sample_rate = cpu_to_le32(rate); /* ignored by the DSP */ + chip->sample_rate = rate; + DE_ACT(("set_sample_rate: %d clock %d\n", rate, clock)); + + return write_control_reg(chip, control_reg, force_write); +} + + + +static int set_input_clock(struct echoaudio *chip, u16 clock) +{ + u32 control_reg, clocks_from_dsp; + int err; + + DE_ACT(("set_input_clock:\n")); + + /* Prevent two simultaneous calls to switch_asic() */ + if (atomic_read(&chip->opencount)) + return -EAGAIN; + + /* Mask off the clock select bits */ + control_reg = le32_to_cpu(chip->comm_page->control_register) & + GML_CLOCK_CLEAR_MASK; + clocks_from_dsp = le32_to_cpu(chip->comm_page->status_clocks); + + switch (clock) { + case ECHO_CLOCK_INTERNAL: + DE_ACT(("Set Mona clock to INTERNAL\n")); + chip->input_clock = ECHO_CLOCK_INTERNAL; + return set_sample_rate(chip, chip->sample_rate); + case ECHO_CLOCK_SPDIF: + if (chip->digital_mode == DIGITAL_MODE_ADAT) + return -EAGAIN; + spin_unlock_irq(&chip->lock); + err = switch_asic(chip, clocks_from_dsp & + GML_CLOCK_DETECT_BIT_SPDIF96); + spin_lock_irq(&chip->lock); + if (err < 0) + return err; + DE_ACT(("Set Mona clock to SPDIF\n")); + control_reg |= GML_SPDIF_CLOCK; + if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_SPDIF96) + control_reg |= GML_DOUBLE_SPEED_MODE; + else + control_reg &= ~GML_DOUBLE_SPEED_MODE; + break; + case ECHO_CLOCK_WORD: + DE_ACT(("Set Mona clock to WORD\n")); + spin_unlock_irq(&chip->lock); + err = switch_asic(chip, clocks_from_dsp & + GML_CLOCK_DETECT_BIT_WORD96); + spin_lock_irq(&chip->lock); + if (err < 0) + return err; + control_reg |= GML_WORD_CLOCK; + if (clocks_from_dsp & GML_CLOCK_DETECT_BIT_WORD96) + control_reg |= GML_DOUBLE_SPEED_MODE; + else + control_reg &= ~GML_DOUBLE_SPEED_MODE; + break; + case ECHO_CLOCK_ADAT: + DE_ACT(("Set Mona clock to ADAT\n")); + if (chip->digital_mode != DIGITAL_MODE_ADAT) + return -EAGAIN; + control_reg |= GML_ADAT_CLOCK; + control_reg &= ~GML_DOUBLE_SPEED_MODE; + break; + default: + DE_ACT(("Input clock 0x%x not supported for Mona\n", clock)); + return -EINVAL; + } + + chip->input_clock = clock; + return write_control_reg(chip, control_reg, TRUE); +} + + + +static int dsp_set_digital_mode(struct echoaudio *chip, u8 mode) +{ + u32 control_reg; + int err, incompatible_clock; + + /* Set clock to "internal" if it's not compatible with the new mode */ + incompatible_clock = FALSE; + switch (mode) { + case DIGITAL_MODE_SPDIF_OPTICAL: + case DIGITAL_MODE_SPDIF_RCA: + if (chip->input_clock == ECHO_CLOCK_ADAT) + incompatible_clock = TRUE; + break; + case DIGITAL_MODE_ADAT: + if (chip->input_clock == ECHO_CLOCK_SPDIF) + incompatible_clock = TRUE; + break; + default: + DE_ACT(("Digital mode not supported: %d\n", mode)); + return -EINVAL; + } + + spin_lock_irq(&chip->lock); + + if (incompatible_clock) { /* Switch to 48KHz, internal */ + chip->sample_rate = 48000; + set_input_clock(chip, ECHO_CLOCK_INTERNAL); + } + + /* Clear the current digital mode */ + control_reg = le32_to_cpu(chip->comm_page->control_register); + control_reg &= GML_DIGITAL_MODE_CLEAR_MASK; + + /* Tweak the control reg */ + switch (mode) { + case DIGITAL_MODE_SPDIF_OPTICAL: + control_reg |= GML_SPDIF_OPTICAL_MODE; + break; + case DIGITAL_MODE_SPDIF_RCA: + /* GML_SPDIF_OPTICAL_MODE bit cleared */ + break; + case DIGITAL_MODE_ADAT: + /* If the current ASIC is the 96KHz ASIC, switch the ASIC + and set to 48 KHz */ + if (chip->asic_code == &card_fw[FW_MONA_361_1_ASIC96] || + chip->asic_code == &card_fw[FW_MONA_301_1_ASIC96]) { + set_sample_rate(chip, 48000); + } + control_reg |= GML_ADAT_MODE; + control_reg &= ~GML_DOUBLE_SPEED_MODE; + break; + } + + err = write_control_reg(chip, control_reg, FALSE); + spin_unlock_irq(&chip->lock); + if (err < 0) + return err; + chip->digital_mode = mode; + + DE_ACT(("set_digital_mode to %d\n", mode)); + return incompatible_clock; +} diff --git a/sound/pci/emu10k1/p17v.h b/sound/pci/emu10k1/p17v.h new file mode 100644 index 000000000..7ddb5be63 --- /dev/null +++ b/sound/pci/emu10k1/p17v.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> + * Driver p17v chips + * Version: 0.01 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/******************************************************************************/ +/* Audigy2Value Tina (P17V) pointer-offset register set, + * accessed through the PTR20 and DATA24 registers */ +/******************************************************************************/ + +/* 00 - 07: Not used */ +#define P17V_PLAYBACK_FIFO_PTR 0x08 /* Current playback fifo pointer + * and number of sound samples in cache. + */ +/* 09 - 12: Not used */ +#define P17V_CAPTURE_FIFO_PTR 0x13 /* Current capture fifo pointer + * and number of sound samples in cache. + */ +/* 14 - 17: Not used */ +#define P17V_PB_CHN_SEL 0x18 /* P17v playback channel select */ +#define P17V_SE_SLOT_SEL_L 0x19 /* Sound Engine slot select low */ +#define P17V_SE_SLOT_SEL_H 0x1a /* Sound Engine slot select high */ +/* 1b - 1f: Not used */ +/* 20 - 2f: Not used */ +/* 30 - 3b: Not used */ +#define P17V_SPI 0x3c /* SPI interface register */ +#define P17V_I2C_ADDR 0x3d /* I2C Address */ +#define P17V_I2C_0 0x3e /* I2C Data */ +#define P17V_I2C_1 0x3f /* I2C Data */ + +#define P17V_START_AUDIO 0x40 /* Start Audio bit */ +/* 41 - 47: Reserved */ +#define P17V_START_CAPTURE 0x48 /* Start Capture bit */ +#define P17V_CAPTURE_FIFO_BASE 0x49 /* Record FIFO base address */ +#define P17V_CAPTURE_FIFO_SIZE 0x4a /* Record FIFO buffer size */ +#define P17V_CAPTURE_FIFO_INDEX 0x4b /* Record FIFO capture index */ +#define P17V_CAPTURE_VOL_H 0x4c /* P17v capture volume control */ +#define P17V_CAPTURE_VOL_L 0x4d /* P17v capture volume control */ +/* 4e - 4f: Not used */ +/* 50 - 5f: Not used */ +#define P17V_SRCSel 0x60 /* SRC48 and SRCMulti sample rate select + * and output select + */ +#define P17V_MIXER_AC97_10K1_VOL_L 0x61 /* 10K to Mixer_AC97 input volume control */ +#define P17V_MIXER_AC97_10K1_VOL_H 0x62 /* 10K to Mixer_AC97 input volume control */ +#define P17V_MIXER_AC97_P17V_VOL_L 0x63 /* P17V to Mixer_AC97 input volume control */ +#define P17V_MIXER_AC97_P17V_VOL_H 0x64 /* P17V to Mixer_AC97 input volume control */ +#define P17V_MIXER_AC97_SRP_REC_VOL_L 0x65 /* SRP Record to Mixer_AC97 input volume control */ +#define P17V_MIXER_AC97_SRP_REC_VOL_H 0x66 /* SRP Record to Mixer_AC97 input volume control */ +/* 67 - 68: Reserved */ +#define P17V_MIXER_Spdif_10K1_VOL_L 0x69 /* 10K to Mixer_Spdif input volume control */ +#define P17V_MIXER_Spdif_10K1_VOL_H 0x6A /* 10K to Mixer_Spdif input volume control */ +#define P17V_MIXER_Spdif_P17V_VOL_L 0x6B /* P17V to Mixer_Spdif input volume control */ +#define P17V_MIXER_Spdif_P17V_VOL_H 0x6C /* P17V to Mixer_Spdif input volume control */ +#define P17V_MIXER_Spdif_SRP_REC_VOL_L 0x6D /* SRP Record to Mixer_Spdif input volume control */ +#define P17V_MIXER_Spdif_SRP_REC_VOL_H 0x6E /* SRP Record to Mixer_Spdif input volume control */ +/* 6f - 70: Reserved */ +#define P17V_MIXER_I2S_10K1_VOL_L 0x71 /* 10K to Mixer_I2S input volume control */ +#define P17V_MIXER_I2S_10K1_VOL_H 0x72 /* 10K to Mixer_I2S input volume control */ +#define P17V_MIXER_I2S_P17V_VOL_L 0x73 /* P17V to Mixer_I2S input volume control */ +#define P17V_MIXER_I2S_P17V_VOL_H 0x74 /* P17V to Mixer_I2S input volume control */ +#define P17V_MIXER_I2S_SRP_REC_VOL_L 0x75 /* SRP Record to Mixer_I2S input volume control */ +#define P17V_MIXER_I2S_SRP_REC_VOL_H 0x76 /* SRP Record to Mixer_I2S input volume control */ +/* 77 - 78: Reserved */ +#define P17V_MIXER_AC97_ENABLE 0x79 /* Mixer AC97 input audio enable */ +#define P17V_MIXER_SPDIF_ENABLE 0x7A /* Mixer SPDIF input audio enable */ +#define P17V_MIXER_I2S_ENABLE 0x7B /* Mixer I2S input audio enable */ +#define P17V_AUDIO_OUT_ENABLE 0x7C /* Audio out enable */ +#define P17V_MIXER_ATT 0x7D /* SRP Mixer Attenuation Select */ +#define P17V_SRP_RECORD_SRR 0x7E /* SRP Record channel source Select */ +#define P17V_SOFT_RESET_SRP_MIXER 0x7F /* SRP and mixer soft reset */ + +#define P17V_AC97_OUT_MASTER_VOL_L 0x80 /* AC97 Output master volume control */ +#define P17V_AC97_OUT_MASTER_VOL_H 0x81 /* AC97 Output master volume control */ +#define P17V_SPDIF_OUT_MASTER_VOL_L 0x82 /* SPDIF Output master volume control */ +#define P17V_SPDIF_OUT_MASTER_VOL_H 0x83 /* SPDIF Output master volume control */ +#define P17V_I2S_OUT_MASTER_VOL_L 0x84 /* I2S Output master volume control */ +#define P17V_I2S_OUT_MASTER_VOL_H 0x85 /* I2S Output master volume control */ +/* 86 - 87: Not used */ +#define P17V_I2S_CHANNEL_SWAP_PHASE_INVERSE 0x88 /* I2S out mono channel swap + * and phase inverse */ +#define P17V_SPDIF_CHANNEL_SWAP_PHASE_INVERSE 0x89 /* SPDIF out mono channel swap + * and phase inverse */ +/* 8A: Not used */ +#define P17V_SRP_P17V_ESR 0x8B /* SRP_P17V estimated sample rate and rate lock */ +#define P17V_SRP_REC_ESR 0x8C /* SRP_REC estimated sample rate and rate lock */ +#define P17V_SRP_BYPASS 0x8D /* srps channel bypass and srps bypass */ +/* 8E - 92: Not used */ +#define P17V_I2S_SRC_SEL 0x93 /* I2SIN mode sel */ + + + + + + diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c new file mode 100644 index 000000000..a27440ffd --- /dev/null +++ b/sound/pci/hda/patch_atihdmi.c @@ -0,0 +1,165 @@ +/* + * Universal Interface for Intel High Definition Audio Codec + * + * HD audio interface patch for ATI HDMI codecs + * + * Copyright (c) 2006 ATI Technologies Inc. + * + * + * This driver is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This driver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <sound/driver.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/pci.h> +#include <sound/core.h> +#include "hda_codec.h" +#include "hda_local.h" + +struct atihdmi_spec { + struct hda_multi_out multiout; + + struct hda_pcm pcm_rec; +}; + +static struct hda_verb atihdmi_basic_init[] = { + /* enable digital output on pin widget */ + { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, + {} /* terminator */ +}; + +/* + * Controls + */ +static int atihdmi_build_controls(struct hda_codec *codec) +{ + struct atihdmi_spec *spec = codec->spec; + int err; + + err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); + if (err < 0) + return err; + + return 0; +} + +static int atihdmi_init(struct hda_codec *codec) +{ + snd_hda_sequence_write(codec, atihdmi_basic_init); + return 0; +} + +#ifdef CONFIG_PM +/* + * resume + */ +static int atihdmi_resume(struct hda_codec *codec) +{ + atihdmi_init(codec); + snd_hda_resume_spdif_out(codec); + + return 0; +} +#endif + +/* + * Digital out + */ +static int atihdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) +{ + struct atihdmi_spec *spec = codec->spec; + return snd_hda_multi_out_dig_open(codec, &spec->multiout); +} + +static int atihdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, + struct hda_codec *codec, + struct snd_pcm_substream *substream) +{ + struct atihdmi_spec *spec = codec->spec; + return snd_hda_multi_out_dig_close(codec, &spec->multiout); +} + +static struct hda_pcm_stream atihdmi_pcm_digital_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 2, + .nid = 0x2, /* NID to query formats and rates and setup streams */ + .ops = { + .open = atihdmi_dig_playback_pcm_open, + .close = atihdmi_dig_playback_pcm_close + }, +}; + +static int atihdmi_build_pcms(struct hda_codec *codec) +{ + struct atihdmi_spec *spec = codec->spec; + struct hda_pcm *info = &spec->pcm_rec; + + codec->num_pcms = 1; + codec->pcm_info = info; + + info->name = "ATI HDMI"; + info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback; + + return 0; +} + +static void atihdmi_free(struct hda_codec *codec) +{ + kfree(codec->spec); +} + +static struct hda_codec_ops atihdmi_patch_ops = { + .build_controls = atihdmi_build_controls, + .build_pcms = atihdmi_build_pcms, + .init = atihdmi_init, + .free = atihdmi_free, +#ifdef CONFIG_PM + .resume = atihdmi_resume, +#endif +}; + +static int patch_atihdmi(struct hda_codec *codec) +{ + struct atihdmi_spec *spec; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + codec->spec = spec; + + spec->multiout.num_dacs = 0; /* no analog */ + spec->multiout.max_channels = 2; + spec->multiout.dig_out_nid = 0x2; /* NID for copying analog to digital, + * seems to be unused in pure-digital + * case. */ + + codec->patch_ops = atihdmi_patch_ops; + + return 0; +} + +/* + * patch entries + */ +struct hda_codec_preset snd_hda_preset_atihdmi[] = { + { .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi }, + {} /* terminator */ +};